GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 5cefd1...492078 )
by Anton
04:08
created

some()   C

Complexity

Conditions 13
Paths 1

Size

Total Lines 64
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 39
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 64
rs 6.6166

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace React\Promise;
4
5
/**
6
 * Creates a promise for the supplied `$promiseOrValue`.
7
 *
8
 * If `$promiseOrValue` is a value, it will be the resolution value of the
9
 * returned promise.
10
 *
11
 * If `$promiseOrValue` is a thenable (any object that provides a `then()` method),
12
 * a trusted promise that follows the state of the thenable is returned.
13
 *
14
 * If `$promiseOrValue` is a promise, it will be returned as is.
15
 *
16
 * @param mixed $promiseOrValue
17
 * @return PromiseInterface
18
 */
19
function resolve($promiseOrValue = null)
20
{
21
    if ($promiseOrValue instanceof ExtendedPromiseInterface) {
22
        return $promiseOrValue;
23
    }
24
25
    // Check is_object() first to avoid method_exists() triggering
26
    // class autoloaders if $promiseOrValue is a string.
27
    if (\is_object($promiseOrValue) && \method_exists($promiseOrValue, 'then')) {
28
        $canceller = null;
29
30
        if (\method_exists($promiseOrValue, 'cancel')) {
31
            $canceller = [$promiseOrValue, 'cancel'];
32
        }
33
34
        return new Promise(function ($resolve, $reject, $notify) use ($promiseOrValue) {
35
            $promiseOrValue->then($resolve, $reject, $notify);
0 ignored issues
show
Bug introduced by
The method then() does not exist on null. ( Ignorable by Annotation )

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

35
            $promiseOrValue->/** @scrutinizer ignore-call */ 
36
                             then($resolve, $reject, $notify);

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...
36
        }, $canceller);
37
    }
38
39
    return new FulfilledPromise($promiseOrValue);
0 ignored issues
show
Deprecated Code introduced by
The class React\Promise\FulfilledPromise has been deprecated: 2.8.0 External usage of FulfilledPromise is deprecated, use `resolve()` instead. ( Ignorable by Annotation )

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

39
    return /** @scrutinizer ignore-deprecated */ new FulfilledPromise($promiseOrValue);
Loading history...
40
}
41
42
/**
43
 * Creates a rejected promise for the supplied `$promiseOrValue`.
44
 *
45
 * If `$promiseOrValue` is a value, it will be the rejection value of the
46
 * returned promise.
47
 *
48
 * If `$promiseOrValue` is a promise, its completion value will be the rejected
49
 * value of the returned promise.
50
 *
51
 * This can be useful in situations where you need to reject a promise without
52
 * throwing an exception. For example, it allows you to propagate a rejection with
53
 * the value of another promise.
54
 *
55
 * @param mixed $promiseOrValue
56
 * @return PromiseInterface
57
 */
58
function reject($promiseOrValue = null)
59
{
60
    if ($promiseOrValue instanceof PromiseInterface) {
61
        return resolve($promiseOrValue)->then(function ($value) {
62
            return new RejectedPromise($value);
0 ignored issues
show
Deprecated Code introduced by
The class React\Promise\RejectedPromise has been deprecated: 2.8.0 External usage of RejectedPromise is deprecated, use `reject()` instead. ( Ignorable by Annotation )

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

62
            return /** @scrutinizer ignore-deprecated */ new RejectedPromise($value);
Loading history...
63
        });
64
    }
65
66
    return new RejectedPromise($promiseOrValue);
0 ignored issues
show
Deprecated Code introduced by
The class React\Promise\RejectedPromise has been deprecated: 2.8.0 External usage of RejectedPromise is deprecated, use `reject()` instead. ( Ignorable by Annotation )

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

66
    return /** @scrutinizer ignore-deprecated */ new RejectedPromise($promiseOrValue);
Loading history...
67
}
68
69
/**
70
 * Returns a promise that will resolve only once all the items in
71
 * `$promisesOrValues` have resolved. The resolution value of the returned promise
72
 * will be an array containing the resolution values of each of the items in
73
 * `$promisesOrValues`.
74
 *
75
 * @param array $promisesOrValues
76
 * @return PromiseInterface
77
 */
78
function all($promisesOrValues)
79
{
80
    return map($promisesOrValues, function ($val) {
81
        return $val;
82
    });
83
}
84
85
/**
86
 * Initiates a competitive race that allows one winner. Returns a promise which is
87
 * resolved in the same way the first settled promise resolves.
88
 *
89
 * The returned promise will become **infinitely pending** if  `$promisesOrValues`
90
 * contains 0 items.
91
 *
92
 * @param array $promisesOrValues
93
 * @return PromiseInterface
94
 */
95
function race($promisesOrValues)
96
{
97
    $cancellationQueue = new CancellationQueue();
98
    $cancellationQueue->enqueue($promisesOrValues);
99
100
    return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $cancellationQueue) {
101
        resolve($promisesOrValues)
0 ignored issues
show
Bug introduced by
$promisesOrValues of type array is incompatible with the type React\Promise\PromiseInterface expected by parameter $promiseOrValue of React\Promise\resolve(). ( Ignorable by Annotation )

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

101
        resolve(/** @scrutinizer ignore-type */ $promisesOrValues)
Loading history...
102
            ->done(function ($array) use ($cancellationQueue, $resolve, $reject, $notify) {
0 ignored issues
show
Bug introduced by
The method done() does not exist on React\Promise\Internal\FulfilledPromise. ( Ignorable by Annotation )

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

102
            ->/** @scrutinizer ignore-call */ done(function ($array) use ($cancellationQueue, $resolve, $reject, $notify) {

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...
103
                if (!is_array($array) || !$array) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $array of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
104
                    $resolve();
105
                    return;
106
                }
107
108
                foreach ($array as $promiseOrValue) {
109
                    $cancellationQueue->enqueue($promiseOrValue);
110
111
                    resolve($promiseOrValue)
112
                        ->done($resolve, $reject, $notify);
0 ignored issues
show
Bug introduced by
The method done() does not exist on React\Promise\PromiseInterface. It seems like you code against a sub-type of said class. However, the method does not exist in React\Promise\CancellablePromiseInterface or React\Promise\Promise or React\Promise\Internal\FulfilledPromise. Are you sure you never get one of those? ( Ignorable by Annotation )

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

112
                        ->/** @scrutinizer ignore-call */ done($resolve, $reject, $notify);
Loading history...
113
                }
114
            }, $reject, $notify);
115
    }, $cancellationQueue);
116
}
117
118
/**
119
 * Returns a promise that will resolve when any one of the items in
120
 * `$promisesOrValues` resolves. The resolution value of the returned promise
121
 * will be the resolution value of the triggering item.
122
 *
123
 * The returned promise will only reject if *all* items in `$promisesOrValues` are
124
 * rejected. The rejection value will be an array of all rejection reasons.
125
 *
126
 * The returned promise will also reject with a `React\Promise\Exception\LengthException`
127
 * if `$promisesOrValues` contains 0 items.
128
 *
129
 * @param array $promisesOrValues
130
 * @return PromiseInterface
131
 */
132
function any($promisesOrValues)
133
{
134
    return some($promisesOrValues, 1)
135
        ->then(function ($val) {
136
            return \array_shift($val);
137
        });
138
}
139
140
/**
141
 * Returns a promise that will resolve when `$howMany` of the supplied items in
142
 * `$promisesOrValues` resolve. The resolution value of the returned promise
143
 * will be an array of length `$howMany` containing the resolution values of the
144
 * triggering items.
145
 *
146
 * The returned promise will reject if it becomes impossible for `$howMany` items
147
 * to resolve (that is, when `(count($promisesOrValues) - $howMany) + 1` items
148
 * reject). The rejection value will be an array of
149
 * `(count($promisesOrValues) - $howMany) + 1` rejection reasons.
150
 *
151
 * The returned promise will also reject with a `React\Promise\Exception\LengthException`
152
 * if `$promisesOrValues` contains less items than `$howMany`.
153
 *
154
 * @param array $promisesOrValues
155
 * @param int $howMany
156
 * @return PromiseInterface
157
 */
158
function some($promisesOrValues, $howMany)
159
{
160
    $cancellationQueue = new CancellationQueue();
161
    $cancellationQueue->enqueue($promisesOrValues);
162
163
    return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $howMany, $cancellationQueue) {
164
        resolve($promisesOrValues)
0 ignored issues
show
Bug introduced by
$promisesOrValues of type array is incompatible with the type React\Promise\PromiseInterface expected by parameter $promiseOrValue of React\Promise\resolve(). ( Ignorable by Annotation )

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

164
        resolve(/** @scrutinizer ignore-type */ $promisesOrValues)
Loading history...
165
            ->done(function ($array) use ($howMany, $cancellationQueue, $resolve, $reject, $notify) {
166
                if (!\is_array($array) || $howMany < 1) {
167
                    $resolve([]);
168
                    return;
169
                }
170
171
                $len = \count($array);
172
173
                if ($len < $howMany) {
174
                    throw new Exception\LengthException(
175
                        \sprintf(
176
                            'Input array must contain at least %d item%s but contains only %s item%s.',
177
                            $howMany,
178
                            1 === $howMany ? '' : 's',
179
                            $len,
180
                            1 === $len ? '' : 's'
181
                        )
182
                    );
183
                }
184
185
                $toResolve = $howMany;
186
                $toReject  = ($len - $toResolve) + 1;
187
                $values    = [];
188
                $reasons   = [];
189
190
                foreach ($array as $i => $promiseOrValue) {
191
                    $fulfiller = function ($val) use ($i, &$values, &$toResolve, $toReject, $resolve) {
192
                        if ($toResolve < 1 || $toReject < 1) {
193
                            return;
194
                        }
195
196
                        $values[$i] = $val;
197
198
                        if (0 === --$toResolve) {
199
                            $resolve($values);
200
                        }
201
                    };
202
203
                    $rejecter = function ($reason) use ($i, &$reasons, &$toReject, $toResolve, $reject) {
204
                        if ($toResolve < 1 || $toReject < 1) {
205
                            return;
206
                        }
207
208
                        $reasons[$i] = $reason;
209
210
                        if (0 === --$toReject) {
211
                            $reject($reasons);
212
                        }
213
                    };
214
215
                    $cancellationQueue->enqueue($promiseOrValue);
216
217
                    resolve($promiseOrValue)
218
                        ->done($fulfiller, $rejecter, $notify);
219
                }
220
            }, $reject, $notify);
221
    }, $cancellationQueue);
222
}
223
224
/**
225
 * Traditional map function, similar to `array_map()`, but allows input to contain
226
 * promises and/or values, and `$mapFunc` may return either a value or a promise.
227
 *
228
 * The map function receives each item as argument, where item is a fully resolved
229
 * value of a promise or value in `$promisesOrValues`.
230
 *
231
 * @param array $promisesOrValues
232
 * @param callable $mapFunc
233
 * @return PromiseInterface
234
 */
235
function map($promisesOrValues, callable $mapFunc)
236
{
237
    $cancellationQueue = new CancellationQueue();
238
    $cancellationQueue->enqueue($promisesOrValues);
239
240
    return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $mapFunc, $cancellationQueue) {
241
        resolve($promisesOrValues)
0 ignored issues
show
Bug introduced by
$promisesOrValues of type array is incompatible with the type React\Promise\PromiseInterface expected by parameter $promiseOrValue of React\Promise\resolve(). ( Ignorable by Annotation )

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

241
        resolve(/** @scrutinizer ignore-type */ $promisesOrValues)
Loading history...
242
            ->done(function ($array) use ($mapFunc, $cancellationQueue, $resolve, $reject, $notify) {
243
                if (!\is_array($array) || !$array) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $array of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
244
                    $resolve([]);
245
                    return;
246
                }
247
248
                $toResolve = \count($array);
249
                $values    = [];
250
251
                foreach ($array as $i => $promiseOrValue) {
252
                    $cancellationQueue->enqueue($promiseOrValue);
253
                    $values[$i] = null;
254
255
                    resolve($promiseOrValue)
256
                        ->then($mapFunc)
257
                        ->done(
258
                            function ($mapped) use ($i, &$values, &$toResolve, $resolve) {
259
                                $values[$i] = $mapped;
260
261
                                if (0 === --$toResolve) {
262
                                    $resolve($values);
263
                                }
264
                            },
265
                            $reject,
266
                            $notify
267
                        );
268
                }
269
            }, $reject, $notify);
270
    }, $cancellationQueue);
271
}
272
273
/**
274
 * Traditional reduce function, similar to `array_reduce()`, but input may contain
275
 * promises and/or values, and `$reduceFunc` may return either a value or a
276
 * promise, *and* `$initialValue` may be a promise or a value for the starting
277
 * value.
278
 *
279
 * @param array $promisesOrValues
280
 * @param callable $reduceFunc
281
 * @param mixed $initialValue
282
 * @return PromiseInterface
283
 */
284
function reduce($promisesOrValues, callable $reduceFunc, $initialValue = null)
285
{
286
    $cancellationQueue = new CancellationQueue();
287
    $cancellationQueue->enqueue($promisesOrValues);
288
289
    return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $reduceFunc, $initialValue, $cancellationQueue) {
290
        resolve($promisesOrValues)
0 ignored issues
show
Bug introduced by
$promisesOrValues of type array is incompatible with the type React\Promise\PromiseInterface expected by parameter $promiseOrValue of React\Promise\resolve(). ( Ignorable by Annotation )

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

290
        resolve(/** @scrutinizer ignore-type */ $promisesOrValues)
Loading history...
291
            ->done(function ($array) use ($reduceFunc, $initialValue, $cancellationQueue, $resolve, $reject, $notify) {
292
                if (!\is_array($array)) {
293
                    $array = [];
294
                }
295
296
                $total = \count($array);
297
                $i = 0;
298
299
                // Wrap the supplied $reduceFunc with one that handles promises and then
300
                // delegates to the supplied.
301
                $wrappedReduceFunc = function ($current, $val) use ($reduceFunc, $cancellationQueue, $total, &$i) {
302
                    $cancellationQueue->enqueue($val);
303
304
                    return $current
305
                        ->then(function ($c) use ($reduceFunc, $total, &$i, $val) {
306
                            return resolve($val)
307
                                ->then(function ($value) use ($reduceFunc, $total, &$i, $c) {
308
                                    return $reduceFunc($c, $value, $i++, $total);
309
                                });
310
                        });
311
                };
312
313
                $cancellationQueue->enqueue($initialValue);
314
315
                \array_reduce($array, $wrappedReduceFunc, resolve($initialValue))
316
                    ->done($resolve, $reject, $notify);
317
            }, $reject, $notify);
318
    }, $cancellationQueue);
319
}
320
321
/**
322
 * @internal
323
 */
324
function _checkTypehint(callable $callback, $object)
325
{
326
    if (!\is_object($object)) {
327
        return true;
328
    }
329
330
    if (\is_array($callback)) {
331
        $callbackReflection = new \ReflectionMethod($callback[0], $callback[1]);
332
    } elseif (\is_object($callback) && !$callback instanceof \Closure) {
333
        $callbackReflection = new \ReflectionMethod($callback, '__invoke');
334
    } else {
335
        $callbackReflection = new \ReflectionFunction($callback);
336
    }
337
338
    $parameters = $callbackReflection->getParameters();
339
340
    if (!isset($parameters[0])) {
341
        return true;
342
    }
343
344
    $expectedException = $parameters[0];
345
346
    // PHP before v8 used an easy API:
347
    if (\PHP_VERSION_ID < 70100 || \defined('HHVM_VERSION')) {
348
        if (!$expectedException->getClass()) {
349
            return true;
350
        }
351
352
        return $expectedException->getClass()->isInstance($object);
353
    }
354
355
    // Extract the type of the argument and handle different possibilities
356
    $type = $expectedException->getType();
357
    
358
    $isTypeUnion = true;
359
    $types = [];
360
361
    switch (true) {
362
        case $type === null:
363
            break;
364
        case $type instanceof \ReflectionNamedType:
365
            $types = [$type];
366
            break;
367
        case $type instanceof \ReflectionIntersectionType:
0 ignored issues
show
Bug introduced by
The type ReflectionIntersectionType was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
368
            $isTypeUnion = false;
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment if this fall-through is intended.
Loading history...
369
        case $type instanceof \ReflectionUnionType;
370
            $types = $type->getTypes();
371
            break;
372
        default:
373
            throw new \LogicException('Unexpected return value of ReflectionParameter::getType');
374
    }
375
376
    // If there is no type restriction, it matches
377
    if (empty($types)) {
378
        return true;
379
    }
380
381
    foreach ($types as $type) {
382
        if (!$type instanceof \ReflectionNamedType) {
383
            throw new \LogicException('This implementation does not support groups of intersection or union types');
384
        }
385
386
        // A named-type can be either a class-name or a built-in type like string, int, array, etc.
387
        $matches = ($type->isBuiltin() && \gettype($object) === $type->getName())
388
            || (new \ReflectionClass($type->getName()))->isInstance($object);
389
390
391
        // If we look for a single match (union), we can return early on match
392
        // If we look for a full match (intersection), we can return early on mismatch
393
        if ($matches) {
394
            if ($isTypeUnion) {
395
                return true;
396
            }
397
        } else {
398
            if (!$isTypeUnion) {
399
                return false;
400
            }
401
        }
402
    }
403
404
    // If we look for a single match (union) and did not return early, we matched no type and are false
405
    // If we look for a full match (intersection) and did not return early, we matched all types and are true
406
    return $isTypeUnion ? false : true;
407
}
408