Validator::validate()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 3
nop 1
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 15 and the first side effect is on line 3.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
namespace WFV;
3
defined( 'ABSPATH' ) || die();
4
5
use WFV\FormComposite;
6
use WFV\Collection\InputCollection;
7
use WFV\Collection\MessageCollection;
8
use WFV\Contract\ValidateInterface;
9
10
/**
11
 * Validates field/rule pairs using provided strategy classes
12
 *
13
 * @since 0.11.0
14
 */
15
class Validator {
16
17
	/**
18
	 * Container for error messages for rule/field pairs
19
	 * Only contains messages for validations that failed
20
	 *
21
	 * @since 0.11.0
22
	 * @access protected
23
	 * @var array
24
	 */
25
	protected $errors = [];
26
27
	/**
28
	 *
29
	 *
30
	 * @since 0.11.3
31
	 * @access protected
32
	 * @var RuleFactory
33
	 */
34
	protected $factory;
35
36
	/**
37
	 *
38
	 *
39
	 * @since 0.11.3
40
	 * @access protected
41
	 * @var MessageCollection
42
	 */
43
	protected $messages;
44
45
	/**
46
	 *
47
	 *
48
	 * @since 0.11.0
49
	 *
50
	 * @param RuleFactory $factory
51
	 */
52
	public function __construct( RuleFactory $factory, MessageCollection $messages ) {
53
		$this->factory = $factory;
54
		$this->messages = $messages;
55
	}
56
57
	/**
58
	 *
59
	 *
60
	 * @since 0.11.3
61
	 *
62
	 * @param FormComposite $form
63
	 * @return bool
64
	 */
65
	public function validate( FormComposite $form ) {
66
		$rule_collection = $form->rules();
67
		$rules = $rule_collection->get_array( true );
68
69
		foreach( $rules as $field => $ruleset ) {
70
			$input = $this->field_value( $form->input(), $field );
71
			$optional = $rule_collection->is_optional( $field );
72
73
			foreach( $ruleset as $index => $rule ) {
74
				$params = $rule_collection->get_params( $field, $index );
75
				$this->is_valid( $this->factory->get( $rule ), $field, $input, $optional, $params );
0 ignored issues
show
Bug introduced by
It seems like $this->factory->get($rule) targeting WFV\RuleFactory::get() can also be of type boolean; however, WFV\Validator::is_valid() does only seem to accept object<WFV\Contract\ValidateInterface>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
Bug introduced by
It seems like $input defined by $this->field_value($form->input(), $field) on line 70 can also be of type null; however, WFV\Validator::is_valid() does only seem to accept string|array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
76
			}
77
		}
78
		return $this->result( $form );
79
	}
80
81
	/**
82
	 * Add a single error msg for a field's rule if it failed validating
83
	 *
84
	 * @since 0.11.0
85
	 * @access protected
86
	 *
87
	 * @param string $field
88
	 * @param array $template
89
	 */
90
	protected function add_error( $field, array $template ) {
91
		$message = ( $this->messages->has( $field ) )
92
			? $this->messages->get_msg( $field, $template['name'] )
93
			: $template['message'];
94
		$this->errors[ $field ][ $template['name'] ] = $message;
95
	}
96
97
	/**
98
	 * Returns the array of error messages
99
	 *
100
	 * @since 0.11.0
101
	 * @access protected
102
	 *
103
	 * @return array
104
	 */
105
	protected function errors() {
106
		return $this->errors;
107
	}
108
109
	/**
110
	 * Returns the input value for a field
111
	 * When not present, returns null
112
	 *
113
	 * @since 0.11.0
114
	 * @since 0.11.3 Moved from FormComposite
115
	 * @access protected
116
	 *
117
	 * @param InputCollection $input
118
	 * @param string $field
119
	 * @return string|array|null
120
	 */
121
	protected function field_value( InputCollection $input, $field ) {
122
		if( $input->has( $field ) ) {
123
			$input = $input->get_array();
124
			return $input[ $field ];
125
		}
126
		return null;
127
	}
128
129
	/**
130
	 * Validate a single input using provided rule (strategy)
131
	 *
132
	 * @since 0.11.0
133
	 *
134
	 * @param ValidateInterface $rule
135
	 * @param string $field
136
	 * @param string|array $value
137
	 * @param bool $optional
138
	 * @param array (optional) $params
139
	 */
140
	protected function is_valid( ValidateInterface $rule, $field, $value, $optional, $params = false ) {
141
		$params[] = ( $params ) ? $field : false;
142
		$valid = $rule->validate( $value, $optional, $params );
0 ignored issues
show
Unused Code introduced by
The call to ValidateInterface::validate() has too many arguments starting with $params.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
143
		if( !$valid ){
144
			$this->add_error( $field, $rule->template() );
145
		}
146
	}
147
148
	/**
149
	 * Did the full validation cycle pass or fail?
150
	 *
151
	 * @since 0.11.0
152
	 * @access protected
153
	 *
154
	 * @param FormComposite $form
155
	 * @return bool
156
	 */
157
	protected function result( FormComposite $form ) {
158
		$valid = empty( $this->errors );
159
		if( !$valid ) {
160
			$form->errors()->set_errors( $this->errors );
161
		}
162
		$this->trigger_post_validate_action( $form, $valid );
163
		return $valid;
164
	}
165
166
	/**
167
	 * Trigger action hook for validation pass or fail
168
	 *
169
	 * @since 0.10.0
170
	 * @since 0.11.3 Moved from FormComposite
171
	 * @access protected
172
	 *
173
	 * @param FormComposite $form
174
	 * @param bool $is_valid
175
	 */
176
	protected function trigger_post_validate_action( FormComposite $form, $is_valid = false ) {
177
		$action = ( true === $is_valid ) ? $form->name() : $form->name() .'_fail';
178
		do_action( $action, $form );
179
	}
180
}
181