Completed
Push — master ( e15c58...b150a8 )
by Changwan
07:08
created

ValidatorFactory::from()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 7

Importance

Changes 0
Metric Value
cc 7
eloc 15
nc 7
nop 1
dl 0
loc 24
ccs 17
cts 17
cp 1
crap 7
rs 6.7272
c 0
b 0
f 0
1
<?php
2
namespace Wandu\Validator;
3
4
use Wandu\Validator\Contracts\ValidatorInterface;
5
use Wandu\Validator\Exception\ValidatorNotFoundException;
6
use Wandu\Validator\Rules\ArrayValidator;
7
8
/**
9
 * @method \Wandu\Validator\Contracts\ValidatorInterface required()
10
 * @method \Wandu\Validator\Contracts\ValidatorInterface not(\Wandu\Validator\Contracts\ValidatorInterface $validator)
11
 * @method \Wandu\Validator\Contracts\ValidatorInterface array(array $attributes = [])
12
 * @method \Wandu\Validator\Contracts\ValidatorInterface collection($rule = null)
13
 * @method \Wandu\Validator\Contracts\ValidatorInterface arrayable(array $attributes = [])
14
 * @method \Wandu\Validator\Contracts\ValidatorInterface object(array $properties = [])
15
 * @method \Wandu\Validator\Contracts\ValidatorInterface integer()
16
 * @method \Wandu\Validator\Contracts\ValidatorInterface boolean()
17
 * @method \Wandu\Validator\Contracts\ValidatorInterface float()
18
 * @method \Wandu\Validator\Contracts\ValidatorInterface string()
19
 * @method \Wandu\Validator\Contracts\ValidatorInterface integerable()
20
 * @method \Wandu\Validator\Contracts\ValidatorInterface floatable()
21
 * @method \Wandu\Validator\Contracts\ValidatorInterface numeric()
22
 * @method \Wandu\Validator\Contracts\ValidatorInterface stringable()
23
 * @method \Wandu\Validator\Contracts\ValidatorInterface printable()
24
 * @method \Wandu\Validator\Contracts\ValidatorInterface pipeline(array $validators = [])
25
 * @method \Wandu\Validator\Contracts\ValidatorInterface min(int $min)
26
 * @method \Wandu\Validator\Contracts\ValidatorInterface max(int $max)
27
 * @method \Wandu\Validator\Contracts\ValidatorInterface lengthMin(int $min)
28
 * @method \Wandu\Validator\Contracts\ValidatorInterface lengthMax(int $max)
29
 * @method \Wandu\Validator\Contracts\ValidatorInterface email(\Egulias\EmailValidator\Validation\EmailValidation $validation = null)
30
 * @method \Wandu\Validator\Contracts\ValidatorInterface regExp(string $pattern)
31
 */
32
class ValidatorFactory
33
{
34
    /** @var \Wandu\Validator\ValidatorFactory */
35
    public static $factory;
36
    
37
    /** @var array */
38
    private $instances = [];
39
    
40
    /** @var array */
41
    private $namespaces = [
42
        __NAMESPACE__ . '\\Rules',
43
    ];
44
45
    /**
46
     * @return \Wandu\Validator\ValidatorFactory
47
     */
48 4
    public static function clearGlobal()
49
    {
50 4
        $clearedFactory = static::$factory;
51 4
        static::$factory = null;
52 4
        return $clearedFactory;
53
    }
54
    
55
    /**
56
     * @param string $name
57
     * @param array $arguments
58
     * @return \Wandu\Validator\Contracts\ValidatorInterface
59
     */
60 54
    public function __call($name, array $arguments = [])
61
    {
62 54
        if (count($arguments)) {
63 41
            $className = $this->getClassName($name);
64 41
            return new $className(...$arguments);
65
        }
66 44
        if (!array_key_exists($name, $this->instances)) {
67 16
            $className = $this->getClassName($name);
68 16
            $this->instances[$name] = new $className();
69 16
        }
70 44
        return $this->instances[$name];
71
    }
72
73
    /**
74
     * @return \Wandu\Validator\ValidatorFactory
75
     */
76 3
    public function setAsGlobal()
77
    {
78 3
        $oldFactory = static::$factory;
79 3
        static::$factory = $this;
80 3
        return $oldFactory;
81
    }
82
    
83
    /**
84
     * @param string|array $namespaces
85
     * @return static
86
     */
87 2
    public function register($namespaces)
88
    {
89 2
        if (!is_array($namespaces)) {
90 2
            $namespaces = [$namespaces];
91 2
        }
92 2
        $this->namespaces = array_merge($this->namespaces, $namespaces);
93 2
        return $this;
94
    }
95
96
    /**
97
     * @param $rule
98
     * @return \Wandu\Validator\Contracts\ValidatorInterface
99
     */
100 26
    public function from($rule)
101
    {
102 26
        if ($rule instanceof ValidatorInterface) {
103 5
            return $rule;
104
        }
105 25
        if (is_array($rule)) {
106 11
            return new ArrayValidator($rule);
107
        }
108 25
        if (is_object($rule)) {
109 1
            return $this->object(get_object_vars($rule));
110
        }
111 25
        $rule = explode('|', $rule);
112 25
        if (count($rule) === 1) {
113 21
            return $this->createValidator($rule[0]);
114
        }
115
        // if count bigger than 1, need pipeline.
116 13
        $validators = [];
117 13
        foreach ($rule as $attribute) {
118 13
            if ($validator = $this->createValidator($attribute)) {
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $validator is correct as $this->createValidator($attribute) (which targets Wandu\Validator\Validato...tory::createValidator()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
119 13
                $validators[] = $validator;
120 13
            }
121 13
        }
122 13
        return validator()->pipeline($validators);
123
    }
124
    
125 25
    protected function createValidator($attribute)
126
    {
127 25
        $attribute = trim($attribute, ": \t\n\r\0\x0B");
128 25
        if (!$attribute) {
129
            return null;
130
        }
131 25
        list($method, $params) = $this->getMethodAndParams($attribute);
132 25
        $validator = $this->__call($this->underscoreToCamelCase($method), $params);
133 25
        if (substr($method, 0, 1) === '!') {
134 1
            $validator = $this->not($validator);
135 1
        }
136 25
        return $validator;
137
    }
138
    
139 25
    protected function getMethodAndParams($pattern)
140
    {
141 25
        if (false === $pivot = strpos($pattern, ':')) {
142 25
            return [$pattern, []]; // "simple"
143
        }
144 7
        $method = substr($pattern, 0, $pivot);
145 7
        $params = array_reduce(
146 7
            explode(',', substr($pattern, $pivot + 1)),
147 7
            function ($carry, $value) {
148 7
                $value = trim($value);
149 7
                if ($value) {
150 7
                    $carry[] = $value;
151 7
                }
152 7
                return $carry;
153 7
            },
154 7
            []
155 7
        );
156 7
        return [$method, $params];
157
    }
158
159
    /**
160
     * @param string $text
161
     * @return string
162
     */
163 25
    protected function underscoreToCamelCase($text)
164
    {
165 25
        $text = trim($text, '!');
166 25
        $text = str_replace(' ', '', ucwords(str_replace('_', ' ', $text)));
167 25
        $text[0] = strtolower($text[0]);
168 25
        return $text;
169
    }
170
171
    /**
172
     * @param string $name
173
     * @return string
174
     */
175 50
    protected function getClassName($name)
176
    {
177 50
        foreach (array_reverse($this->namespaces) as $baseNamespace) {
178 50
            $className = $baseNamespace . '\\' . ucfirst($name) . 'Validator';
179 50
            if (class_exists($className)) {
180 50
                return $className;
181
            }
182 1
        }
183 1
        throw new ValidatorNotFoundException($name);
184
    }
185
}
186