Completed
Branch master (b7a0b6)
by Adrian
04:26 queued 02:31
created

RuleFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Sirius\Validation;
4
5
use Sirius\Validation\Rule\Callback as CallbackRule;
6
7
class RuleFactory
8
{
9
    /**
10
     * Validator map allows for flexibility when creating a validation rule
11
     * You can use 'required' instead of 'required' for the name of the rule
12
     * or 'minLength'/'minlength' instead of 'MinLength'
13
     *
14
     * @var array
15
     */
16
    protected $validatorsMap = array();
17
18
    /**
19
     * @var array
20
     */
21
    protected $errorMessages = array();
22
23
    /**
24
     * @var array
25
     */
26
    protected $labeledErrorMessages = array();
27
28
    /**
29
     * Constructor
30
     */
31 27
    public function __construct()
32
    {
33 27
        $this->registerDefaultRules();
34 27
    }
35
36
    /**
37
     * Set up the default rules that come with the library
38
     */
39 27
    protected function registerDefaultRules()
40
    {
41
        $rulesClasses = array(
42 27
            'Alpha',
43 27
            'AlphaNumeric',
44 27
            'AlphaNumHyphen',
45 27
            'ArrayLength',
46 27
            'ArrayMaxLength',
47 27
            'ArrayMinLength',
48 27
            'Between',
49 27
            'Callback',
50 27
            'Date',
51 27
            'DateTime',
52 27
            'Email',
53 27
            'EmailDomain',
54 27
            'Equal',
55 27
            'FullName',
56 27
            'GreaterThan',
57 27
            'InList',
58 27
            'Integer',
59 27
            'IpAddress',
60 27
            'Length',
61 27
            'LessThan',
62 27
            'Match',
63 27
            'MaxLength',
64 27
            'MinLength',
65 27
            'NotInList',
66 27
            'NotRegex',
67 27
            'Number',
68 27
            'Regex',
69 27
            'Required',
70 27
            'RequiredWhen',
71 27
            'RequiredWith',
72 27
            'RequiredWithout',
73 27
            'Time',
74 27
            'Url',
75 27
            'Website',
76 27
            'File\Extension',
77 27
            'File\Image',
78 27
            'File\ImageHeight',
79 27
            'File\ImageRatio',
80 27
            'File\ImageWidth',
81 27
            'File\Size',
82 27
            'Upload\Extension',
83 27
            'Upload\Image',
84 27
            'Upload\ImageHeight',
85 27
            'Upload\ImageRatio',
86 27
            'Upload\ImageWidth',
87 27
            'Upload\Size',
88 27
        );
89 27
        foreach ($rulesClasses as $class) {
90 27
            $fullClassName       = '\\' . __NAMESPACE__ . '\Rule\\' . $class;
91 27
            $name                = strtolower(str_replace('\\', '', $class));
92 27
            $errorMessage        = constant($fullClassName . '::MESSAGE');
93 27
            $labeledErrorMessage = constant($fullClassName . '::LABELED_MESSAGE');
94 27
            $this->register($name, $fullClassName, $errorMessage, $labeledErrorMessage);
95 27
        }
96 27
    }
97
98
99
    /**
100
     * Register a class to be used when creating validation rules
101
     *
102
     * @param string $name
103
     * @param string $class
104
     *
105
     * @return \Sirius\Validation\RuleFactory
106
     */
107 27
    public function register($name, $class, $errorMessage = '', $labeledErrorMessage = '')
108
    {
109 27
        if (is_subclass_of($class, '\Sirius\Validation\Rule\AbstractRule')) {
110 27
            $this->validatorsMap[$name] = $class;
111 27
        }
112 27
        if ($errorMessage) {
113 27
            $this->errorMessages[$name] = $errorMessage;
114 27
        }
115 27
        if ($labeledErrorMessage) {
116 27
            $this->labeledErrorMessages[$name] = $labeledErrorMessage;
117 27
        }
118
119 27
        return $this;
120
    }
121
122
    /**
123
     * Factory method to construct a validator based on options that are used most of the times
124
     *
125
     * @param string|callable $name
126
     *            name of a validator class or a callable object/function
127
     * @param string|array $options
128
     *            validator options (an array, JSON string or QUERY string)
129
     * @param string $messageTemplate
130
     *            error message template
131
     * @param string $label
132
     *            label of the form input field or model attribute
133
     *
134
     * @throws \InvalidArgumentException
135
     * @return \Sirius\Validation\Rule\AbstractValidator
136
     */
137 24
    public function createRule($name, $options = null, $messageTemplate = null, $label = null)
138
    {
139 24
        $validator = $this->construcRuleByNameAndOptions($name, $options);
140
141
        // no message template, try to get it from the registry
142 22
        if (!$messageTemplate) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $messageTemplate of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
143 19
            $messageTemplate = $this->getSuggestedMessageTemplate($name, !!$label);
0 ignored issues
show
Documentation introduced by
$name is of type callable, but the function expects a string.

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...
144 19
        }
145
146 22
        if (is_string($messageTemplate) && $messageTemplate !== '') {
147 20
            $validator->setMessageTemplate($messageTemplate);
148 20
        }
149 22
        if (is_string($label) && $label !== '') {
150 8
            $validator->setOption('label', $label);
151 8
        }
152
153 22
        return $validator;
154
    }
155
156
    /**
157
     * Set default error message for a rule
158
     *
159
     * @param string $rule
160
     * @param string|null $messageWithoutLabel
161
     * @param string|null $messageWithLabel
162
     *
163
     * @return $this
164
     */
165
    public function setMessages($rule, $messageWithoutLabel = null, $messageWithLabel = null)
166
    {
167
        if ($messageWithoutLabel) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $messageWithoutLabel of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
168
            $this->errorMessages[$rule] = $messageWithoutLabel;
169
        }
170
        if ($messageWithLabel) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $messageWithLabel of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
171
            $this->labeledErrorMessages[$rule] = $messageWithLabel;
172
        }
173
174
        return $this;
175
    }
176
177
    /**
178
     * Get the error message saved in the registry for a rule, where the message
179
     * is with or without a the label
180
     *
181
     * @param string $name name of the rule
182
     * @param bool $withLabel
183
     *
184
     * @return string|NULL
185
     */
186 19
    protected function getSuggestedMessageTemplate($name, $withLabel)
187
    {
188 19
        $noLabelMessage = is_string($name) && isset($this->errorMessages[$name]) ? $this->errorMessages[$name] : null;
189 19
        if ($withLabel) {
190 3
            return is_string($name) && isset($this->labeledErrorMessages[$name]) ?
191 3
                $this->labeledErrorMessages[$name] :
192 3
                $noLabelMessage;
193
        }
194
195 18
        return $noLabelMessage;
196
    }
197
198
    /**
199
     * @param $name
200
     * @param $options
201
     *
202
     * @return CallbackRule
203
     */
204 24
    protected function construcRuleByNameAndOptions($name, $options)
205
    {
206 24
        if (is_callable($name)) {
207 1
            $validator = new CallbackRule(
208
                array(
209 1
                    'callback'  => $name,
210
                    'arguments' => $options
211 1
                )
212 1
            );
213 24
        } elseif (is_string($name)) {
214 23
            $name = trim($name);
215
            // use the validator map
216 23
            if (isset($this->validatorsMap[strtolower($name)])) {
217 22
                $name = $this->validatorsMap[strtolower($name)];
218 22
            }
219
            // try if the validator is the name of a class in the package
220 23
            if (class_exists('\Sirius\Validation\Rule\\' . $name, false)) {
221
                $name = '\Sirius\Validation\Rule\\' . $name;
222
            }
223
            // at this point we should have a class that can be instanciated
224 23
            if (class_exists($name) && is_subclass_of($name, '\Sirius\Validation\Rule\AbstractRule')) {
225 22
                $validator = new $name($options);
226 21
            }
227 22
        }
228
229 23
        if (!isset($validator)) {
230 1
            throw new \InvalidArgumentException(
231 1
                sprintf('Impossible to determine the validator based on the name: %s', (string) $name)
232 1
            );
233
        }
234
235 22
        return $validator;
236
    }
237
}
238