Completed
Push — master ( 6730cd...13507f )
by J.D.
03:41
created

WordPoints_Hook_Event_Args::__construct()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 21
rs 9.0534
cc 4
eloc 11
nc 5
nop 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 slugs of the stateful args.
32
	 *
33
	 * Indexed by slug, so that `isset()` can be used.
34
	 *
35
	 * @since 1.0.0
36
	 *
37
	 * @var string[]
38
	 */
39
	protected $stateful_args = array();
40
41
	/**
42
	 * The validator associated with the current hook reaction.
43
	 *
44
	 * @since 1.0.0
45
	 *
46
	 * @var WordPoints_Hook_Reaction_Validator
47
	 */
48
	protected $validator;
49
50
	/**
51
	 * Whether to push fields onto the validator when we descend into the hierarchy.
52
	 *
53
	 * This will usually be true, however, when we are getting a value from the
54
	 * hierarchy, we aren't actually descending into a sub-field, but descending
55
	 * down the arg hierarchy stored within a field.
56
	 *
57
	 * @since 1.0.0
58
	 *
59
	 * @var bool
60
	 */
61
	protected $push_on_descend = true;
62
63
	/**
64
	 * Construct the object with the arg objects.
65
	 *
66
	 * @param WordPoints_Hook_Arg[] $args The hook args.
67
	 */
68
	public function __construct( array $args ) {
69
70
		parent::__construct();
71
72
		foreach ( $args as $arg ) {
73
74
			$entity = $arg->get_entity();
75
			$slug = $arg->get_slug();
76
77
			if ( $entity instanceof WordPoints_Entity ) {
78
				$this->entities[ $slug ] = $entity;
79
			}
80
81
			if ( $arg->is_stateful() ) {
82
				$this->stateful_args[ $slug ] = $slug;
83
			} else {
84
				// If any of the args aren't stateful the event isn't repeatable.
85
				$this->is_repeatable = false;
86
			}
87
		}
88
	}
89
90
	/**
91
	 * Whether the event is repeatable.
92
	 *
93
	 * An event is repeatable if none of its args have their status toggled by the
94
	 * event. In that case, it is possible for the event to occur with those same args
95
	 * multiple times in a row without being reversed in between.
96
	 *
97
	 * An arg that has its status modified is called a signature arg. One that does
98
	 * not is called a stateful arg. An event is repeatable if it has no signature
99
	 * args, only stateful ones.
100
	 *
101
	 * @since 1.0.0
102
	 *
103
	 * @return bool Whether the event is repeatable.
104
	 */
105
	public function is_event_repeatable() {
106
		return $this->is_repeatable;
107
	}
108
109
	/**
110
	 * Get the stateful args for this event.
111
	 *
112
	 * @since 1.0.0
113
	 *
114
	 * @return WordPoints_Entity[] The entity objects for the stateful args.
115
	 */
116
	public function get_stateful_args() {
117
		return array_intersect_key( $this->entities, $this->stateful_args );
118
	}
119
120
	/**
121
	 * Get the non-stateful args for this event.
122
	 *
123
	 * @since 1.0.0
124
	 *
125
	 * @return WordPoints_Entity[] The entity objects for the non-stateful args.
126
	 */
127
	public function get_non_stateful_args() {
128
		return array_diff_key( $this->entities, $this->stateful_args );
129
	}
130
131
	/**
132
	 * Set the validator for the current reaction.
133
	 *
134
	 * @since 1.0.0
135
	 *
136
	 * @param WordPoints_Hook_Reaction_Validator $validator The validator.
137
	 */
138
	public function set_validator( WordPoints_Hook_Reaction_Validator $validator ) {
139
		$this->validator = $validator;
140
	}
141
142
	/**
143
	 * @since 1.0.0
144
	 */
145
	public function descend( $child_slug ) {
146
147
		$result = parent::descend( $child_slug );
148
149
		// Just in case no validator has been set.
150
		if ( ! $this->validator ) {
151
			return $result;
152
		}
153
154
		if ( ! $result ) {
155
156
			if ( ! isset( $this->current ) ) {
157
158
				$this->validator->add_error(
159
					sprintf(
160
						__( 'The %s arg is not registered for this event.', 'wordpoints' ) // TODO message
161
						, $child_slug
162
					)
163
				);
164
165
			} elseif ( ! ( $this->current instanceof WordPoints_Entity_ParentI ) ) {
166
167
				$this->validator->add_error(
168
					__( 'Cannot get descendant of %s: not a parent.', 'wordpoints' ) // TODO message
169
				);
170
171
			} else {
172
173
				$child_arg = $this->current->get_child( $child_slug );
174
175
				if ( ! $child_arg ) {
176
					$this->validator->add_error(
177
						__( '%s does not have a child "%s".', 'wordpoints' ) // TODO message
178
						, $this->push_on_descend ? $child_slug : null
179
					);
180
				}
181
			}
182
183
		} elseif ( $this->push_on_descend ) {
184
185
			$this->validator->push_field( $child_slug );
186
		}
187
188
		return $result;
189
	}
190
191
	/**
192
	 * @since 1.0.0
193
	 */
194
	public function ascend() {
195
196
		$ascended = parent::ascend();
197
198
		if ( $ascended && $this->validator ) {
199
			$this->validator->pop_field();
200
		}
201
202
		return $ascended;
203
	}
204
205
	/**
206
	 * @since 1.0.0
207
	 */
208
	public function get_from_hierarchy( array $hierarchy ) {
209
210
		$this->push_on_descend = false;
211
		$entityish = parent::get_from_hierarchy( $hierarchy );
212
		$this->push_on_descend = true;
213
214
		return $entityish;
215
	}
216
}
217
218
// EOF
219