Completed
Push — master ( 8155ff...9fff48 )
by Changwan
03:00
created

TesterFactory::__construct()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 21
nc 1
nop 1
dl 0
loc 24
ccs 4
cts 4
cp 1
crap 1
rs 8.9713
c 0
b 0
f 0
1
<?php
2
namespace Wandu\Validator;
3
4
use Wandu\Validator\Contracts\TesterInterface;
5
use Wandu\Validator\Exception\TesterNotFoundException;
6
use Wandu\Validator\Testers\AlwaysFalseTester;
7
use Wandu\Validator\Testers\AlwaysTrueTester;
8
use Wandu\Validator\Testers\BooleanTester;
9
use Wandu\Validator\Testers\EmailTester;
10
use Wandu\Validator\Testers\FloatTester;
11
use Wandu\Validator\Testers\IntegerableTester;
12
use Wandu\Validator\Testers\IntegerTester;
13
use Wandu\Validator\Testers\LengthMaxTester;
14
use Wandu\Validator\Testers\LengthMinTester;
15
use Wandu\Validator\Testers\MaxTester;
16
use Wandu\Validator\Testers\MinTester;
17
use Wandu\Validator\Testers\NumericTester;
18
use Wandu\Validator\Testers\PrintableTester;
19
use Wandu\Validator\Testers\RegExpTester;
20
use Wandu\Validator\Testers\StringableTester;
21
use Wandu\Validator\Testers\StringTester;
22
23
class TesterFactory
24
{
25
    /** @var \Wandu\Validator\TesterFactory */
26
    public static $instance;
27
    
28
    /** @var string[] */
29
    protected $testers;
30
31
    /** @var \Wandu\Validator\Contracts\TesterInterface[] */
32
    protected $caches = [];
33
34 5
    public function __construct(array $testers = [])
35
    {
36 5
        $this->testers = $testers + [
37 5
                'always_false' => AlwaysFalseTester::class,
38
                'always_true' => AlwaysTrueTester::class,
39
                'bool' => BooleanTester::class,
40
                'boolean' => BooleanTester::class,
41
                'email' => EmailTester::class,
42
                'float' => FloatTester::class,
43
                'floatable' => NumericTester::class,
44
                'integerable' => IntegerableTester::class,
45
                'int' => IntegerTester::class,
46
                'integer' => IntegerTester::class,
47
                'length_max' => LengthMaxTester::class,
48
                'length_min' => LengthMinTester::class,
49
                'max' => MaxTester::class,
50
                'min' => MinTester::class,
51
                'numeric' => NumericTester::class,
52
                'printable' => PrintableTester::class,
53
                'regexp' => RegExpTester::class,
54
                'stringable' => StringableTester::class,
55
                'string' => StringTester::class,
56
            ];
57 5
    }
58
59
    /**
60
     * @return \Wandu\Validator\TesterFactory
61
     */
62 4
    public function setAsGlobal()
63
    {
64 4
        $instance = static::$instance;
65 4
        static::$instance = $this;
66 4
        return $instance;
67
    }
68
    
69
    /**
70
     * @param string $tester
71
     * @param array ...$arguments
72
     * @return \Wandu\Validator\Contracts\TesterInterface
73
     */
74 27
    public function from(string $tester, ...$arguments): TesterInterface
75
    {
76 27
        if (count($arguments)) {
77 2
            $className = $this->getClassName($tester);
78 2
            return new $className(...$arguments);
79
        }
80 25
        list($name, $arguments) = $this->getMethodAndParams($tester);
81 25
        if (!array_key_exists($tester, $this->caches)) {
82 24
            $className = $this->getClassName($name);
83 24
            $this->caches[$tester] = new $className(...$arguments);
84
        }
85 25
        return $this->caches[$tester];
86
    }
87
88
    /**
89
     * @param string $pattern
90
     * @return array
91
     */
92 25
    protected function getMethodAndParams($pattern)
93
    {
94 25
        $pattern = trim($pattern);
95 25
        if (false === $pivot = strpos($pattern, ':')) {
96 19
            return [$pattern, []]; // "simple"
97
        }
98 9
        $method = substr($pattern, 0, $pivot);
99 9
        preg_match_all('/\/[^\/]*\/|[^,]+/', substr($pattern, $pivot + 1), $matches);
100 9
        $params = array_reduce(
101 9
            $matches[0],
102 9
            function ($carry, $value) {
103 9
                $value = trim($value);
104 9
                if ($value) {
105 9
                    $carry[] = $value;
106
                }
107 9
                return $carry;
108 9
            },
109 9
            []
110
        );
111 9
        return [$method, $params];
112
    }
113
114
    /**
115
     * @param string $name
116
     * @return string
117
     */
118 26
    protected function getClassName($name)
119
    {
120 26
        if (isset($this->testers[$name])) {
121 26
            $className = $this->testers[$name];
122 26
            if (class_exists($className)) {
123 26
                return $className;
124
            }
125
        }
126
        throw new TesterNotFoundException($name);
127
    }
128
}
129