Passed
Pull Request — master (#58)
by Alexander
02:01
created

Callback::invokeMethod()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 6.5625

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 6
eloc 16
c 1
b 0
f 1
nc 6
nop 2
dl 0
loc 25
ccs 12
cts 16
cp 0.75
crap 6.5625
rs 9.1111
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule;
6
7
use Yiisoft\Validator\Rule;
8
use Yiisoft\Validator\Result;
9
use Yiisoft\Validator\DataSetInterface;
10
11
/**
12
 * Callback rule could be used to create custom rules without defining a class.
13
 * If callback is specified as [className, methodName], the method of the class could be private.
14
 */
15
class Callback extends Rule
16
{
17
    private $callback;
18
19 10
    public function __construct($callback)
20
    {
21 10
        if (!(is_callable($callback) || (is_array($callback) && count($callback) === 2))) {
22 1
            throw new \InvalidArgumentException(
23 1
                'The argument must be a callable or an array with the class and method name.'
24
            );
25
        }
26
27 9
        $this->callback = $callback;
28
    }
29
30 8
    protected function validateValue($value, DataSetInterface $dataSet = null): Result
31
    {
32 8
        $result = new Result();
33 8
        $callback = $this->callback;
34
35
        /**
36
         * @var $callbackResult Result
37
         */
38 8
        $callbackResult = is_callable($callback)
39 4
            ? $callback($value, $dataSet)
40 8
            : $this->invokeMethod($value, $callback);
41
42 7
        if ($callbackResult->isValid() === false) {
43 7
            foreach ($callbackResult->getErrors() as $message) {
44 7
                $result->addError($this->translateMessage($message));
45
            }
46
        }
47 7
        return $result;
48
    }
49
50 4
    private function invokeMethod($value, array $callback): Result
51
    {
52 4
        [$class, $method] = $callback;
53 4
        if (!method_exists($class, $method)) {
54
            throw new \InvalidArgumentException(
55
                sprintf(
56
                    'Method "%s" targeted by Callback rule does not exist in class %s',
57
                    $method,
58
                    \get_class($class)
59
                )
60
            );
61
        }
62 4
        $reflectionMethod = new \ReflectionMethod($class, $method);
63 4
        if (is_string($class) && !$reflectionMethod->isStatic()) {
64 1
            throw new \InvalidArgumentException(
65 1
                sprintf('Method "%s" targeted by Callback rule must be static.', $method)
66
            );
67
        }
68 3
        if (!$reflectionMethod->isPublic()) {
69 3
            $reflectionMethod->setAccessible(true);
70
        }
71 3
        if ($reflectionMethod->isStatic()) {
72 1
            return $reflectionMethod->invoke(null, $value);
73
        }
74 2
        return $reflectionMethod->invoke($class, $value);
75
    }
76
}
77