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

Completed
Pull Request — master (#656)
by Vincent
14:47
created

Paginator::forward()   A

Complexity

Conditions 5
Paths 2

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 5

Importance

Changes 0
Metric Value
eloc 13
c 0
b 0
f 0
dl 0
loc 20
ccs 14
cts 14
cp 1
rs 9.5222
cc 5
nc 2
nop 1
crap 5
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, function ($entities) use ($args) {
72 3
                return $this->connectionBuilder->connectionFromArray($entities, $args);
73 4
            });
74
        } else {
75 3
            $entities = call_user_func($this->fetcher, $offset, $limit ? $limit + 2 : $limit);
76
77 3
            return $this->handleEntities($entities, function ($entities) use ($args, $offset) {
78 3
                return $this->connectionBuilder->connectionFromArraySlice($entities, $args, [
79 3
                    'sliceStart' => $offset,
80 3
                    'arrayLength' => $offset + count($entities),
81
                ]);
82 3
            });
83
        }
84
    }
85
86
    /**
87
     * @param int|callable $total
88
     *
89
     * @return Connection|Promise A connection or a promise
90
     */
91 5
    public function auto(ArgumentInterface $args, $total, array $callableArgs = [])
92
    {
93 5
        if (isset($args['last'])) {
94 3
            $connection = $this->backward($args, $total, $callableArgs);
95
        } else {
96 2
            $connection = $this->forward($args);
97
        }
98
99 5
        if ($this->promise) {
100
            /** @var Promise $connection */
101 1
            return $connection->then(function (ConnectionInterface $connection) use ($total, $callableArgs) {
102
                $connection->setTotalCount($this->computeTotalCount($total, $callableArgs));
103
104
                return $connection;
105 1
            });
106
        } else {
107
            /** @var Connection $connection */
108 4
            $connection->setTotalCount($this->computeTotalCount($total, $callableArgs));
109
110 4
            return $connection;
111
        }
112
    }
113
114
    /**
115
     * @param array<int, string>|Promise $entities An array of entities to paginate or a promise
116
     *
117
     * @return Connection|Promise A connection or a promise
118
     */
119 14
    private function handleEntities($entities, callable $callback)
120
    {
121 14
        if ($this->promise) {
122
            /** @var Promise $entities */
123 1
            return $entities->then($callback);
124
        }
125
126 13
        return $callback($entities);
127
    }
128
129
    /**
130
     * @param int|callable $total
131
     *
132
     * @return int|mixed
133
     */
134 8
    private function computeTotalCount($total, array $callableArgs = [])
135
    {
136 8
        if (isset($this->totalCount)) {
137 3
            return $this->totalCount;
138
        }
139
140 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 $function 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

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