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
Push — 0.9 ( 2e758e...e8e8ed )
by Jérémiah
01:55
created

Paginator::auto()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3.0416

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 10
cts 12
cp 0.8333
rs 9.2
c 0
b 0
f 0
cc 3
eloc 13
nc 4
nop 3
crap 3.0416
1
<?php
2
3
/*
4
 * This file is part of the OverblogGraphQLBundle package.
5
 *
6
 * (c) Overblog <http://github.com/overblog/>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Overblog\GraphQLBundle\Relay\Connection;
13
14
use Overblog\GraphQLBundle\Definition\Argument;
15
use Overblog\GraphQLBundle\Relay\Connection\Output\Connection;
16
use Overblog\GraphQLBundle\Relay\Connection\Output\ConnectionBuilder;
17
18
class Paginator
19
{
20
    const MODE_REGULAR = false;
21
    const MODE_PROMISE = true;
22
23
    /**
24
     * @var callable
25
     */
26
    private $fetcher;
27
28
    /**
29
     * @var bool
30
     */
31
    private $promise;
32
33
    /**
34
     * @var int
35
     */
36
    private $totalCount;
37
38
    /**
39
     * @param callable $fetcher
40
     * @param bool     $promise
41
     */
42 14
    public function __construct(callable $fetcher, $promise = self::MODE_REGULAR)
43
    {
44 14
        $this->fetcher = $fetcher;
45 14
        $this->promise = $promise;
46 14
    }
47
48
    /**
49
     * @param Argument|array $args
50
     * @param int|callable   $total
51
     * @param array          $callableArgs
52
     *
53
     * @return Connection|object A connection or a promise
54
     */
55 7
    public function backward($args, $total, array $callableArgs = [])
56
    {
57 7
        $total = $this->computeTotalCount($total, $callableArgs);
0 ignored issues
show
Bug introduced by
It seems like $total defined by $this->computeTotalCount($total, $callableArgs) on line 57 can also be of type callable; however, Overblog\GraphQLBundle\R...or::computeTotalCount() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
58
59 7
        $args = $this->protectArgs($args);
60 7
        $limit = $args['last'];
61 7
        $offset = max(0, ConnectionBuilder::getOffsetWithDefault($args['before'], $total) - $limit);
62
63 7
        $entities = call_user_func($this->fetcher, $offset, $limit);
64
65 7 View Code Duplication
        return $this->handleEntities($entities, function ($entities) use ($args, $offset, $total) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
66 7
            return ConnectionBuilder::connectionFromArraySlice($entities, $args, [
67 7
                'sliceStart' => $offset,
68 7
                'arrayLength' => $total,
69
            ]);
70 7
        });
71
    }
72
73
    /**
74
     * @param Argument|array $args
75
     *
76
     * @return Connection|object A connection or a promise
77
     */
78 7
    public function forward($args)
79
    {
80 7
        $args = $this->protectArgs($args);
81 7
        $limit = $args['first'];
82 7
        $offset = ConnectionBuilder::getOffsetWithDefault($args['after'], 0);
83
84
        // If we don't have a cursor or if it's not valid, then we must not use the slice method
85 7
        if (!is_numeric(ConnectionBuilder::cursorToOffset($args['after'])) || !$args['after']) {
86 4
            $entities = call_user_func($this->fetcher, $offset, $limit + 1);
87
88 4
            return $this->handleEntities($entities, function ($entities) use ($args) {
89 3
                return ConnectionBuilder::connectionFromArray($entities, $args);
90 4
            });
91
        } else {
92 3
            $entities = call_user_func($this->fetcher, $offset, $limit + 2);
93
94 3 View Code Duplication
            return $this->handleEntities($entities, function ($entities) use ($args, $offset) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
95 3
                return ConnectionBuilder::connectionFromArraySlice($entities, $args, [
96 3
                    'sliceStart' => $offset,
97 3
                    'arrayLength' => $offset + count($entities),
98
                ]);
99 3
            });
100
        }
101
    }
102
103
    /**
104
     * @param Argument|array $args
105
     * @param int|callable   $total
106
     * @param array          $callableArgs
107
     *
108
     * @return Connection|object A connection or a promise
109
     */
110 5
    public function auto($args, $total, $callableArgs = [])
111
    {
112 5
        $args = $this->protectArgs($args);
113
114 5
        if ($args['last']) {
115 3
            $connection = $this->backward($args, $total, $callableArgs);
116
        } else {
117 2
            $connection = $this->forward($args);
118
        }
119
120 5
        if ($this->promise) {
121 1
            return $connection->then(function (Connection $connection) use ($total, $callableArgs) {
122
                $connection->totalCount = $this->computeTotalCount($total, $callableArgs);
0 ignored issues
show
Bug introduced by
It seems like $total defined by parameter $total on line 110 can also be of type callable; however, Overblog\GraphQLBundle\R...or::computeTotalCount() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
123
124
                return $connection;
125 1
            });
126
        } else {
127 4
            $connection->totalCount = $this->computeTotalCount($total, $callableArgs);
0 ignored issues
show
Bug introduced by
It seems like $total defined by parameter $total on line 110 can also be of type callable; however, Overblog\GraphQLBundle\R...or::computeTotalCount() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
128
129 4
            return $connection;
130
        }
131
    }
132
133
    /**
134
     * @param array|object $entities An array of entities to paginate or a promise
135
     * @param callable     $callback
136
     *
137
     * @return Connection|object A connection or a promise
138
     */
139 14
    private function handleEntities($entities, callable $callback)
140
    {
141 14
        if ($this->promise) {
142 1
            return $entities->then($callback);
143
        }
144
145 13
        return call_user_func($callback, $entities);
146
    }
147
148
    /**
149
     * @param Argument|array $args
150
     *
151
     * @return Argument
152
     */
153 14
    private function protectArgs($args)
154
    {
155 14
        return $args instanceof Argument ? $args : new Argument($args);
156
    }
157
158
    /**
159
     * @param int   $total
160
     * @param array $callableArgs
161
     *
162
     * @return int|mixed
163
     */
164 8
    private function computeTotalCount($total, array $callableArgs = [])
165
    {
166 8
        if ($this->totalCount !== null) {
167 3
            return $this->totalCount;
168
        }
169
170 8
        $this->totalCount = is_callable($total) ? call_user_func_array($total, $callableArgs) : $total;
171
172 8
        return $this->totalCount;
173
    }
174
}
175