Completed
Push — master ( 0375a2...821836 )
by Ivannis Suárez
02:49
created

Selector::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
/**
4
 * This file is part of the Cubiche package.
5
 *
6
 * Copyright (c) Cubiche
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
namespace Cubiche\Core\Specification;
12
13
use Cubiche\Core\Selector\Count;
14
use Cubiche\Core\Selector\Custom;
15
use Cubiche\Core\Selector\Key;
16
use Cubiche\Core\Selector\Method;
17
use Cubiche\Core\Selector\Property;
18
use Cubiche\Core\Selector\SelectorInterface;
19
use Cubiche\Core\Selector\Value;
20
use Cubiche\Core\Specification\Constraint\Equal;
21
use Cubiche\Core\Specification\Constraint\GreaterThan;
22
use Cubiche\Core\Specification\Constraint\GreaterThanEqual;
23
use Cubiche\Core\Specification\Constraint\LessThan;
24
use Cubiche\Core\Specification\Constraint\LessThanEqual;
25
use Cubiche\Core\Specification\Constraint\NotEqual;
26
use Cubiche\Core\Specification\Constraint\NotSame;
27
use Cubiche\Core\Specification\Constraint\Same;
28
use Cubiche\Core\Specification\Quantifier\All;
29
use Cubiche\Core\Specification\Quantifier\AtLeast;
30
31
/**
32
 * Selector Specification Class.
33
 *
34
 * @author Karel Osorio Ramírez <[email protected]>
35
 */
36
class Selector extends Specification implements SelectorInterface
0 ignored issues
show
Bug introduced by
There is one abstract method acceptSelectorVisitor in this class; you could implement it, or declare this class as abstract.
Loading history...
37
{
38
    /**
39
     * @var SelectorInterface
40
     */
41
    protected $selector;
42
43
    /**
44
     * @param SelectorInterface $selector
45
     */
46
    public function __construct(SelectorInterface $selector)
47
    {
48
        $this->selector = $selector;
49
    }
50
51
    /**
52
     * @return \Cubiche\Core\Selector\SelectorInterface
53
     */
54
    public function selector()
55
    {
56
        return $this->selector;
57
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62
    public function evaluate($value)
63
    {
64
        return $this->apply($value) === true;
65
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70
    public function __invoke()
71
    {
72
        return $this->selector()->__invoke(\func_get_args());
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Cubiche\Core\Selector\SelectorInterface as the method __invoke() does only exist in the following implementations of said interface: Cubiche\Core\Specification\Selector.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78
    public function apply($value)
79
    {
80
        return $this->selector()->apply($value);
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86
    public function select(callable $selector)
87
    {
88
        return new self($this->selector()->select($selector));
0 ignored issues
show
Documentation introduced by
$selector is of type callable, but the function expects a object<Cubiche\Core\Selector\SelectorInterface>.

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...
89
    }
90
91
    /**
92
     * @param string $key
93
     *
94
     * @return \Cubiche\Core\Specification\Selector
95
     */
96
    public function key($key)
97
    {
98
        return $this->select(new Key($key));
0 ignored issues
show
Documentation introduced by
new \Cubiche\Core\Selector\Key($key) is of type object<Cubiche\Core\Selector\Key>, but the function expects a callable.

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...
99
    }
100
101
    /**
102
     * @param string $property
103
     *
104
     * @return \Cubiche\Core\Specification\Selector
105
     */
106
    public function property($property)
107
    {
108
        return $this->select(new Property($property));
0 ignored issues
show
Documentation introduced by
new \Cubiche\Core\Selector\Property($property) is of type object<Cubiche\Core\Selector\Property>, but the function expects a callable.

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...
109
    }
110
111
    /**
112
     * @param string $method
113
     *
114
     * @return \Cubiche\Core\Specification\Selector
115
     */
116
    public function method($method)
117
    {
118
        return $this->select(new Method($method));
0 ignored issues
show
Documentation introduced by
new \Cubiche\Core\Selector\Method($method) is of type object<Cubiche\Core\Selector\Method>, but the function expects a callable.

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...
119
    }
120
121
    /**
122
     * @param callable $callable
123
     *
124
     * @return \Cubiche\Core\Specification\Selector
125
     */
126
    public function custom(callable $callable)
127
    {
128
        return $this->select(new Custom($callable));
0 ignored issues
show
Documentation introduced by
new \Cubiche\Core\Selector\Custom($callable) is of type object<Cubiche\Core\Selector\Custom>, but the function expects a callable.

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...
129
    }
130
131
    /**
132
     * @return \Cubiche\Core\Specification\Selector
133
     */
134
    public function count()
135
    {
136
        return $this->select(new Count());
0 ignored issues
show
Documentation introduced by
new \Cubiche\Core\Selector\Count() is of type object<Cubiche\Core\Selector\Count>, but the function expects a callable.

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...
137
    }
138
139
    /**
140
     * @param SpecificationInterface $specification
141
     *
142
     * @return \Cubiche\Core\Specification\Quantifier\All
143
     */
144
    public function all(SpecificationInterface $specification)
145
    {
146
        return new All($this->selector(), $specification);
147
    }
148
149
    /**
150
     * @param int                    $count
151
     * @param SpecificationInterface $specification
152
     *
153
     * @return \Cubiche\Core\Specification\Quantifier\AtLeast
154
     */
155
    public function atLeast($count, SpecificationInterface $specification)
156
    {
157
        return new AtLeast($count, $this->selector(), $specification);
158
    }
159
160
    /**
161
     * @param SpecificationInterface $specification
162
     *
163
     * @return \Cubiche\Core\Specification\Quantifier\AtLeast
164
     */
165
    public function any(SpecificationInterface $specification)
166
    {
167
        return $this->atLeast(1, $specification);
168
    }
169
170
    /**
171
     * @param SelectorInterface|mixed $value
172
     *
173
     * @return \Cubiche\Domain\Specification\Constraint\GreaterThan
174
     */
175
    public function gt($value)
176
    {
177
        return new GreaterThan($this->selector(), $this->createSelector($value));
178
    }
179
180
    /**
181
     * @param SelectorInterface|mixed $value
182
     *
183
     * @return \Cubiche\Core\Specification\Constraint\GreaterThanEqual
184
     */
185
    public function gte($value)
186
    {
187
        return new GreaterThanEqual($this->selector(), $this->createSelector($value));
188
    }
189
190
    /**
191
     * @param SelectorInterface|mixed $value
192
     *
193
     * @return \Cubiche\Core\Specification\Constraint\LessThan
194
     */
195
    public function lt($value)
196
    {
197
        return new LessThan($this->selector(), $this->createSelector($value));
198
    }
199
200
    /**
201
     * @param SelectorInterface|mixed $value
202
     *
203
     * @return \Cubiche\Core\Specification\Constraint\LessThanEqual
204
     */
205
    public function lte($value)
206
    {
207
        return new LessThanEqual($this->selector(), $this->createSelector($value));
208
    }
209
210
    /**
211
     * @param SelectorInterface|mixed $value
212
     *
213
     * @return \Cubiche\Core\Specification\Constraint\Equal
214
     */
215
    public function eq($value)
216
    {
217
        return new Equal($this->selector(), $this->createSelector($value));
218
    }
219
220
    /**
221
     * @param SelectorInterface|mixed $value
222
     *
223
     * @return \Cubiche\Core\Specification\Constraint\NotEqual
224
     */
225
    public function neq($value)
226
    {
227
        return new NotEqual($this->selector(), $this->createSelector($value));
228
    }
229
230
    /**
231
     * @param SelectorInterface|mixed $value
232
     *
233
     * @return \Cubiche\Core\Specification\Constraint\Same
234
     */
235
    public function same($value)
236
    {
237
        return new Same($this->selector(), $this->createSelector($value));
238
    }
239
240
    /**
241
     * @param SelectorInterface|mixed $value
242
     *
243
     * @return \Cubiche\Core\Specification\Constraint\NotSame
244
     */
245
    public function notSame($value)
246
    {
247
        return new NotSame($this->selector(), $this->createSelector($value));
248
    }
249
250
    /**
251
     * @return \Cubiche\Core\Specification\Constraint\Same
252
     */
253
    public function isNull()
254
    {
255
        return new Same($this->selector(), $this->createSelector(null));
256
    }
257
258
    /**
259
     * @return \Cubiche\Core\Specification\Constraint\NotSame
260
     */
261
    public function notNull()
262
    {
263
        return new NotSame($this->selector(), $this->createSelector(null));
264
    }
265
266
    /**
267
     * @return \Cubiche\Core\Specification\Constraint\Same
268
     */
269
    public function isTrue()
270
    {
271
        return new Same($this->selector(), $this->createSelector(true));
272
    }
273
274
    /**
275
     * @return \Cubiche\Core\Specification\Constraint\Same
276
     */
277
    public function isFalse()
278
    {
279
        return new Same($this->selector(), $this->createSelector(false));
280
    }
281
282
    /**
283
     * @param SelectorInterface|mixed $value
284
     *
285
     * @return \Cubiche\Core\Specification\SelectorInterface
286
     */
287
    protected function createSelector($value)
288
    {
289
        return $value instanceof SelectorInterface ? $value : new Value($value);
290
    }
291
}
292