Test Failed
Push — master ( ce3748...e186d3 )
by Kirill
02:26
created

Collection::exportProxies()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
/**
3
 * This file is part of Hydrogen package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace RDS\Hydrogen;
11
12
use Doctrine\Common\Collections\ArrayCollection;
13
use Illuminate\Support\Arr;
14
use Illuminate\Support\Collection as BaseCollection;
15
use RDS\Hydrogen\HighOrderMessaging\HigherOrderCollectionProxy;
16
17
/**
18
 * Class Collection
19
 * @mixin BaseCollection
20
 */
21
class Collection extends ArrayCollection
22
{
23
    /**
24
     * @var array|string[]
25
     */
26
    private static $proxies;
27
28
    /**
29
     * @var BaseCollection
30
     */
31
    private $inner;
32
33
    /**
34
     * Collection constructor.
35
     * @param array|iterable $elements
36
     */
37
    public function __construct($elements = [])
38
    {
39
        $this->inner = BaseCollection::wrap($elements);
40
41
        parent::__construct($this->inner->toArray());
42
43
        $this->exportProxies();
44
    }
45
46
    /**
47
     * @return void
48
     */
49
    private function exportProxies(): void
50
    {
51
        if (static::$proxies === null) {
0 ignored issues
show
Bug introduced by
Since $proxies is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $proxies to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
52
            $class = new \ReflectionClass($this->inner);
53
            $property = $class->getProperty('proxies');
54
            $property->setAccessible(true);
55
56
            static::$proxies = $property->getValue();
0 ignored issues
show
Bug introduced by
Since $proxies is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $proxies to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
57
        }
58
    }
59
60
    /**
61
     * @param string $name
62
     * @param array $arguments
63
     * @return mixed
64
     * @throws \BadMethodCallException
65
     */
66
    public static function __callStatic(string $name, array $arguments = [])
67
    {
68
        if (\method_exists(BaseCollection::class, $name)) {
69
            $result = BaseCollection::$name(...$arguments);
70
71
            if ($result instanceof BaseCollection) {
72
                return new static($result->toArray());
73
            }
74
75
            return $result;
76
        }
77
78
        $error = \sprintf('Call to undefined method %s::%s', static::class, $name);
79
        throw new \BadMethodCallException($error);
80
    }
81
82
    /**
83
     * Wrap the given value in a collection if applicable.
84
     *
85
     * @param mixed $value
86
     * @return static
87
     */
88
    public static function wrap($value): self
89
    {
90
        switch (true) {
91
            case $value instanceof self:
92
                return new static($value);
0 ignored issues
show
Documentation introduced by
$value is of type object<RDS\Hydrogen\Collection>, but the function expects a array|object<RDS\Hydrogen\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
93
94
            case $value instanceof BaseCollection:
95
                return new static($value);
0 ignored issues
show
Documentation introduced by
$value is of type object<Illuminate\Support\Collection>, but the function expects a array|object<RDS\Hydrogen\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
96
97
            default:
98
                return new static(Arr::wrap($value));
99
        }
100
    }
101
102
    /**
103
     * @param string $name
104
     * @param array $arguments
105
     * @return mixed
106
     * @throws \BadMethodCallException
107
     */
108
    public function __call(string $name, array $arguments = [])
109
    {
110
        if (\method_exists($this->inner, $name)) {
111
            $result = $this->inner->$name(...$arguments);
112
113
            if ($result instanceof BaseCollection) {
114
                return new static($result->toArray());
115
            }
116
117
            return $result;
118
        }
119
120
        $error = \sprintf('Call to undefined method %s::%s', static::class, $name);
121
        throw new \BadMethodCallException($error);
122
    }
123
124
    /**
125
     * @param string $key
126
     * @return HigherOrderCollectionProxy
127
     * @throws \InvalidArgumentException
128
     */
129
    public function __get(string $key): HigherOrderCollectionProxy
130
    {
131
        if (! \in_array($key, static::$proxies, true)) {
0 ignored issues
show
Bug introduced by
Since $proxies is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $proxies to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
132
            $error = "Property [{$key}] does not exist on this collection instance.";
133
            throw new \InvalidArgumentException($error);
134
        }
135
136
        return new HigherOrderCollectionProxy($this, $key);
137
    }
138
}
139