Completed
Push — master ( 637b3c...faeb69 )
by J.D.
03:49
created

WordPoints_Hook_Event_Args   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 210
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 3
Metric Value
wmc 22
lcom 2
cbo 3
dl 0
loc 210
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 22 4
A is_event_repeatable() 0 3 1
A get_stateful_args() 0 10 2
A get_primary_arg() 0 8 2
A set_validator() 0 3 1
C descend() 0 45 8
A ascend() 0 10 3
A get_from_hierarchy() 0 8 1
1
<?php
2
3
/**
4
 * Hook event args class.
5
 *
6
 * @package wordpoints-hooks-api
7
 * @since   1.0.0
8
 */
9
10
/**
11
 * Represents the args associated with a hook event.
12
 *
13
 * This is similar to the regular entity hierarchy, except that it handles errors
14
 * with the reaction validators, and accepts an array of hook args instead of
15
 * requiring entity objects to be passed directly.
16
 *
17
 * @since 1.0.0
18
 */
19
class WordPoints_Hook_Event_Args extends WordPoints_Entity_Hierarchy {
20
21
	/**
22
	 * Whether the event is repeatable.
23
	 *
24
	 * @since 1.0.0
25
	 *
26
	 * @var bool
27
	 */
28
	protected $is_repeatable = true;
29
30
	/**
31
	 * The slug of the primary arg for this event, if it has one.
32
	 *
33
	 * @since 1.0.0
34
	 *
35
	 * @var string|false
36
	 */
37
	protected $primary_arg_slug = false;
38
39
	/**
40
	 * The validator associated with the current hook reaction.
41
	 *
42
	 * @since 1.0.0
43
	 *
44
	 * @var WordPoints_Hook_Reaction_Validator
45
	 */
46
	protected $validator;
47
48
	/**
49
	 * Whether to push fields onto the validator when we descend into the hierarchy.
50
	 *
51
	 * This will usually be true, however, when we are getting a value from the
52
	 * hierarchy, we aren't actually descending into a sub-field, but descending
53
	 * down the arg hierarchy stored within a field.
54
	 *
55
	 * @since 1.0.0
56
	 *
57
	 * @var bool
58
	 */
59
	protected $push_on_descend = true;
60
61
	/**
62
	 * Construct the object with the arg objects.
63
	 *
64
	 * @param WordPoints_Hook_Arg[] $args The hook args.
65
	 */
66
	public function __construct( array $args ) {
67
68
		parent::__construct();
69
70
		foreach ( $args as $arg ) {
71
72
			$entity = $arg->get_entity();
73
			$slug = $arg->get_slug();
74
75
			if ( ! $entity instanceof WordPoints_Entity ) {
76
				continue;
77
			}
78
79
			$this->entities[ $slug ] = $entity;
80
81
			if ( ! $arg->is_stateful() ) {
82
				// If any of the args aren't stateful the event isn't repeatable.
83
				$this->is_repeatable = false;
84
				$this->primary_arg_slug = $slug;
85
			}
86
		}
87
	}
88
89
	/**
90
	 * Whether the event is repeatable.
91
	 *
92
	 * An event is repeatable if none of its args have their status toggled by the
93
	 * event. In that case, it is possible for the event to occur with those same args
94
	 * multiple times in a row without being reversed in between.
95
	 *
96
	 * An arg that has its status modified is called a signature arg. One that does
97
	 * not is called a stateful arg. An event is repeatable if it has no signature
98
	 * args, only stateful ones.
99
	 *
100
	 * @since 1.0.0
101
	 *
102
	 * @return bool Whether the event is repeatable.
103
	 */
104
	public function is_event_repeatable() {
105
		return $this->is_repeatable;
106
	}
107
108
	/**
109
	 * Get the stateful args for this event.
110
	 *
111
	 * @since 1.0.0
112
	 *
113
	 * @return WordPoints_Entity[] The entity objects for the stateful args.
114
	 */
115
	public function get_stateful_args() {
116
117
		$stateful = $this->entities;
118
119
		if ( $this->primary_arg_slug ) {
1 ignored issue
show
Bug Best Practice introduced by
The expression $this->primary_arg_slug of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false 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...
120
			unset( $stateful[ $this->primary_arg_slug ] );
121
		}
122
123
		return $stateful;
124
	}
125
126
	/**
127
	 * Get the primary arg for this event.
128
	 *
129
	 * @since 1.0.0
130
	 *
131
	 * @return WordPoints_Entity|false The entity objects for the primary arg, or
132
	 *                                 false if this entity has none.
133
	 */
134
	public function get_primary_arg() {
135
136
		if ( ! $this->primary_arg_slug ) {
1 ignored issue
show
Bug Best Practice introduced by
The expression $this->primary_arg_slug of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false 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...
137
			return false;
138
		}
139
140
		return $this->entities[ $this->primary_arg_slug ];
141
	}
142
143
	/**
144
	 * Set the validator for the current reaction.
145
	 *
146
	 * @since 1.0.0
147
	 *
148
	 * @param WordPoints_Hook_Reaction_Validator $validator The validator.
149
	 */
150
	public function set_validator( WordPoints_Hook_Reaction_Validator $validator ) {
151
		$this->validator = $validator;
152
	}
153
154
	/**
155
	 * @since 1.0.0
156
	 */
157
	public function descend( $child_slug ) {
158
159
		$result = parent::descend( $child_slug );
160
161
		// Just in case no validator has been set.
162
		if ( ! $this->validator ) {
163
			return $result;
164
		}
165
166
		if ( ! $result ) {
167
168
			if ( ! isset( $this->current ) ) {
169
170
				$this->validator->add_error(
171
					sprintf(
172
						__( 'The %s arg is not registered for this event.', 'wordpoints' ) // TODO message
173
						, $child_slug
174
					)
175
				);
176
177
			} elseif ( ! ( $this->current instanceof WordPoints_Entity_ParentI ) ) {
178
179
				$this->validator->add_error(
180
					__( 'Cannot get descendant of %s: not a parent.', 'wordpoints' ) // TODO message
181
				);
182
183
			} else {
184
185
				$child_arg = $this->current->get_child( $child_slug );
186
187
				if ( ! $child_arg ) {
188
					$this->validator->add_error(
189
						__( '%s does not have a child "%s".', 'wordpoints' ) // TODO message
190
						, $this->push_on_descend ? $child_slug : null
191
					);
192
				}
193
			}
194
195
		} elseif ( $this->push_on_descend ) {
196
197
			$this->validator->push_field( $child_slug );
198
		}
199
200
		return $result;
201
	}
202
203
	/**
204
	 * @since 1.0.0
205
	 */
206
	public function ascend() {
207
208
		$ascended = parent::ascend();
209
210
		if ( $ascended && $this->validator ) {
211
			$this->validator->pop_field();
212
		}
213
214
		return $ascended;
215
	}
216
217
	/**
218
	 * @since 1.0.0
219
	 */
220
	public function get_from_hierarchy( array $hierarchy ) {
221
222
		$this->push_on_descend = false;
223
		$entityish = parent::get_from_hierarchy( $hierarchy );
224
		$this->push_on_descend = true;
225
226
		return $entityish;
227
	}
228
}
229
230
// EOF
231