Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Passed
Pull Request — 0.14 (#841)
by Jérémiah
02:54
created

Paginator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Overblog\GraphQLBundle\Relay\Connection;
6
7
use GraphQL\Executor\Promise\Promise;
8
use Overblog\GraphQLBundle\Definition\ArgumentInterface;
9
use Overblog\GraphQLBundle\Relay\Connection\Output\Connection;
10
use function call_user_func;
11
use function call_user_func_array;
12
use function count;
13
use function is_callable;
14
use function is_numeric;
15
use function max;
16
17
class Paginator
18
{
19
    public const MODE_REGULAR = false;
20
    public const MODE_PROMISE = true;
21
22
    private bool $promise;
23
    private int $totalCount;
24
    private ConnectionBuilder $connectionBuilder;
25
26
    /** @var callable */
27
    private $fetcher;
28
29 14
    public function __construct(callable $fetcher, bool $promise = self::MODE_REGULAR, ConnectionBuilder $connectionBuilder = null)
30
    {
31 14
        $this->fetcher = $fetcher;
32 14
        $this->promise = $promise;
33 14
        $this->connectionBuilder = $connectionBuilder ?? new ConnectionBuilder();
34 14
    }
35
36
    /**
37
     * @param int|callable $total
38
     *
39
     * @return Connection|Promise A connection or a promise
40
     */
41 7
    public function backward(ArgumentInterface $args, $total, array $callableArgs = [])
42
    {
43 7
        $total = $this->computeTotalCount($total, $callableArgs);
44 7
        $limit = $args['last'] ?? null;
45 7
        $before = $args['before'] ?? null;
46 7
        $offset = max(0, $this->connectionBuilder->getOffsetWithDefault($before, $total) - $limit);
47
48 7
        $entities = call_user_func($this->fetcher, $offset, $limit);
49
50 7
        return $this->handleEntities($entities, function ($entities) use ($args, $offset, $total) {
51 7
            return $this->connectionBuilder->connectionFromArraySlice($entities, $args, [
52 7
                'sliceStart' => $offset,
53 7
                'arrayLength' => $total,
54
            ]);
55 7
        });
56
    }
57
58
    /**
59
     * @return Connection|Promise A connection or a promise
60
     */
61 7
    public function forward(ArgumentInterface $args)
62
    {
63 7
        $limit = $args['first'] ?? null;
64 7
        $after = $args['after'] ?? null;
65 7
        $offset = $this->connectionBuilder->getOffsetWithDefault($after, 0);
66
67
        // If we don't have a cursor or if it's not valid, then we must not use the slice method
68 7
        if (!is_numeric($this->connectionBuilder->cursorToOffset($after)) || !$after) {
69 4
            $entities = call_user_func($this->fetcher, $offset, $limit ? $limit + 1 : $limit);
70
71 4
            return $this->handleEntities($entities, fn ($entities) => $this->connectionBuilder->connectionFromArray($entities, $args));
72
        } else {
73 3
            $entities = call_user_func($this->fetcher, $offset, $limit ? $limit + 2 : $limit);
74
75 3
            return $this->handleEntities($entities, function ($entities) use ($args, $offset) {
76 3
                return $this->connectionBuilder->connectionFromArraySlice($entities, $args, [
77 3
                    'sliceStart' => $offset,
78 3
                    'arrayLength' => $offset + count($entities),
79
                ]);
80 3
            });
81
        }
82
    }
83
84
    /**
85
     * @param int|callable $total
86
     *
87
     * @return Connection|Promise A connection or a promise
88
     */
89 5
    public function auto(ArgumentInterface $args, $total, array $callableArgs = [])
90
    {
91 5
        if (isset($args['last'])) {
92 3
            $connection = $this->backward($args, $total, $callableArgs);
93
        } else {
94 2
            $connection = $this->forward($args);
95
        }
96
97 5
        if ($this->promise) {
98
            /** @var Promise $connection */
99 1
            return $connection->then(function (ConnectionInterface $connection) use ($total, $callableArgs) {
100
                $connection->setTotalCount($this->computeTotalCount($total, $callableArgs));
101
102
                return $connection;
103 1
            });
104
        } else {
105
            /** @var Connection $connection */
106 4
            $connection->setTotalCount($this->computeTotalCount($total, $callableArgs));
107
108 4
            return $connection;
109
        }
110
    }
111
112
    /**
113
     * @param array<int, string>|Promise $entities An array of entities to paginate or a promise
114
     *
115
     * @return Connection|Promise A connection or a promise
116
     */
117 14
    private function handleEntities($entities, callable $callback)
118
    {
119 14
        if ($this->promise) {
120
            /** @var Promise $entities */
121 1
            return $entities->then($callback);
122
        }
123
124 13
        return $callback($entities);
125
    }
126
127
    /**
128
     * @param int|callable $total
129
     *
130
     * @return int|mixed
131
     */
132 8
    private function computeTotalCount($total, array $callableArgs = [])
133
    {
134 8
        if (isset($this->totalCount)) {
135 3
            return $this->totalCount;
136
        }
137
138 8
        $this->totalCount = is_callable($total) ? call_user_func_array($total, $callableArgs) : $total;
0 ignored issues
show
Bug introduced by
It seems like $total can also be of type integer; however, parameter $callback of call_user_func_array() does only seem to accept callable, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

138
        $this->totalCount = is_callable($total) ? call_user_func_array(/** @scrutinizer ignore-type */ $total, $callableArgs) : $total;
Loading history...
139
140 8
        return $this->totalCount;
141
    }
142
}
143