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 — master (#197)
by Renato
09:16 queued 02:55
created

Paginator::computeTotalCount()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 5
nc 3
nop 2
crap 3
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
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
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
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
            $connection->then(function (Connection $connection) use ($total, $callableArgs) {
0 ignored issues
show
Bug introduced by
The method then() does not seem to exist on object<Overblog\GraphQLB...tion\Output\Connection>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

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