1919use function is_numeric ;
2020use function max ;
2121use function min ;
22- use function sprintf ;
2322use function str_replace ;
2423
2524/**
2625 * Class ConnectionBuilder.
2726 *
2827 * https://github.com/graphql/graphql-relay-js/blob/master/src/connection/arrayconnection.js
28+ *
29+ * @phpstan-type ConnectionFactoryFunc callable(EdgeInterface<T>[], PageInfoInterface): ConnectionInterface
30+ * @phpstan-type EdgeFactoryFunc callable(string, T, int): EdgeInterface<T>
31+ *
32+ * @phpstan-template T
2933 */
3034final class ConnectionBuilder
3135{
@@ -34,24 +38,32 @@ final class ConnectionBuilder
3438 private CursorEncoderInterface $ cursorEncoder ;
3539
3640 /**
37- * If set, used to generate the connection object.
41+ * Factorty callback used to generate the connection object.
42+ *
43+ * @var callable
3844 *
39- * @var callable|null
45+ * @phpstan- var ConnectionFactoryFunc
4046 */
4147 private $ connectionCallback ;
4248
4349 /**
44- * If set, used to generate the edge object.
50+ * Factorty callback used to generate the edge object.
4551 *
46- * @var ?callable
52+ * @var callable
53+ *
54+ * @phpstan-var EdgeFactoryFunc
4755 */
4856 private $ edgeCallback ;
4957
50- public function __construct (?CursorEncoderInterface $ cursorEncoder = null , callable $ connectionCallback = null , callable $ edgeCallback = null )
58+ /**
59+ * @phpstan-param ConnectionFactoryFunc|null $connectionCallback
60+ * @phpstan-param EdgeFactoryFunc|null $edgeCallback
61+ */
62+ public function __construct (?CursorEncoderInterface $ cursorEncoder = null , ?callable $ connectionCallback = null , ?callable $ edgeCallback = null )
5163 {
5264 $ this ->cursorEncoder = $ cursorEncoder ?? new Base64CursorEncoder ();
53- $ this ->connectionCallback = $ connectionCallback ;
54- $ this ->edgeCallback = $ edgeCallback ;
65+ $ this ->connectionCallback = $ connectionCallback ?? static fn ( array $ edges , PageInfoInterface $ pageInfo ): Connection => new Connection ( $ edges , $ pageInfo ) ;
66+ $ this ->edgeCallback = $ edgeCallback ?? static fn ( string $ cursor , mixed $ value ): Edge => new Edge ( $ cursor , $ value ) ;
5567 }
5668
5769 /**
@@ -60,6 +72,10 @@ public function __construct(?CursorEncoderInterface $cursorEncoder = null, calla
6072 * so pagination will only work if the array is static.
6173 *
6274 * @param array|ArgumentInterface $args
75+ *
76+ * @phpstan-param T[] $data
77+ *
78+ * @return ConnectionInterface<T>
6379 */
6480 public function connectionFromArray (array $ data , $ args = []): ConnectionInterface
6581 {
@@ -99,6 +115,10 @@ public function connectionFromPromisedArray($dataPromise, $args = [])
99115 * total result large enough to cover the range specified in `args`.
100116 *
101117 * @param array|ArgumentInterface $args
118+ *
119+ * @phpstan-param T[] $arraySlice
120+ *
121+ * @phpstan-return ConnectionInterface<T>
102122 */
103123 public function connectionFromArraySlice (array $ arraySlice , $ args , array $ meta ): ConnectionInterface
104124 {
@@ -257,41 +277,43 @@ public function cursorToOffset(?string $cursor): string
257277 return str_replace (static ::PREFIX , '' , $ this ->cursorEncoder ->decode ($ cursor ));
258278 }
259279
280+ /**
281+ * @phpstan-param iterable<T> $slice
282+ *
283+ * @phpstan-return EdgeInterface<T>[]
284+ */
260285 private function createEdges (iterable $ slice , int $ startOffset ): array
261286 {
262287 $ edges = [];
263288
264289 foreach ($ slice as $ index => $ value ) {
265290 $ cursor = $ this ->offsetToCursor ($ startOffset + $ index );
266- if ($ this ->edgeCallback ) {
267- $ edge = ($ this ->edgeCallback )($ cursor , $ value , $ index );
268- if (!($ edge instanceof EdgeInterface)) {
269- throw new InvalidArgumentException (sprintf ('The $edgeCallback of the ConnectionBuilder must return an instance of EdgeInterface ' ));
270- }
271- } else {
272- $ edge = new Edge ($ cursor , $ value );
291+ $ edge = ($ this ->edgeCallback )($ cursor , $ value , $ index );
292+
293+ if (!($ edge instanceof EdgeInterface)) {
294+ throw new InvalidArgumentException ('The $edgeCallback of the ConnectionBuilder must return an instance of EdgeInterface ' );
273295 }
296+
274297 $ edges [] = $ edge ;
275298 }
276299
277300 return $ edges ;
278301 }
279302
280303 /**
281- * @param mixed $edges
304+ * @phpstan-param EdgeInterface<T>[] $edges
305+ *
306+ * @phpstan-return ConnectionInterface<T>
282307 */
283- private function createConnection ($ edges , PageInfoInterface $ pageInfo ): ConnectionInterface
308+ private function createConnection (array $ edges , PageInfoInterface $ pageInfo ): ConnectionInterface
284309 {
285- if ($ this ->connectionCallback ) {
286- $ connection = ($ this ->connectionCallback )($ edges , $ pageInfo );
287- if (!($ connection instanceof ConnectionInterface)) {
288- throw new InvalidArgumentException (sprintf ('The $connectionCallback of the ConnectionBuilder must return an instance of ConnectionInterface ' ));
289- }
310+ $ connection = ($ this ->connectionCallback )($ edges , $ pageInfo );
290311
291- return $ connection ;
312+ if (!($ connection instanceof ConnectionInterface)) {
313+ throw new InvalidArgumentException ('The $connectionCallback of the ConnectionBuilder must return an instance of ConnectionInterface ' );
292314 }
293315
294- return new Connection ( $ edges , $ pageInfo ) ;
316+ return $ connection ;
295317 }
296318
297319 private function getOptionsWithDefaults (array $ options , array $ defaults ): array
0 commit comments