Completed
Push — master ( 144c08...e73d65 )
by J.D.
02:53
created

WordPoints_Hooks::fire()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 31
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 16
c 1
b 0
f 0
nc 5
nop 3
dl 0
loc 31
rs 8.439
1
<?php
2
3
/**
4
 * Class for the hooks app.
5
 *
6
 * @package wordpoints-hooks-api
7
 * @since 1.0.0
8
 */
9
10
/**
11
 * Hooks app.
12
 *
13
 * The hooks API consists primarily of actions, events, reactors, args, and
14
 * other extensions. Events are "fired" at various reactors when actions occur.
15
 * The args that the event relates to is passed to any extensions, along with
16
 * the list of predefined reactions. The extensions can then analyse the args and
17
 * the reaction specifications to determine whether the reactor should "hit" or
18
 * "miss" the target entity.
19
 *
20
 * @since 1.0.0
21
 *
22
 * @property-read WordPoints_Hook_Router               $router     The hook action router.
23
 * @property-read WordPoints_Hook_Actions              $actions    The actions registry.
24
 * @property-read WordPoints_Hook_Events               $events     The events registry.
25
 * @property-read WordPoints_Class_Registry_Persistent $reactors   The reactors registry.
26
 * @property-read WordPoints_Class_Registry_Children   $reaction_stores The reaction stores registry.
27
 * @property-read WordPoints_Class_Registry_Persistent $extensions The extensions registry.
28
 * @property-read WordPoints_Class_Registry_Children   $conditions The conditions registry.
29
 */
30
class WordPoints_Hooks extends WordPoints_App {
31
32
	/**
33
	 * The current mode of the API.
34
	 *
35
	 * @since 1.0.0
36
	 *
37
	 * @var string
38
	 */
39
	protected $current_mode;
40
41
	/**
42
	 * Register the sub apps when the app is constructed.
43
	 *
44
	 * @since 1.0.0
45
	 */
46
	protected function init() {
47
48
		$sub_apps = $this->sub_apps;
49
		$sub_apps->register( 'router', 'WordPoints_Hook_Router' );
50
		$sub_apps->register( 'actions', 'WordPoints_Hook_Actions' );
51
		$sub_apps->register( 'events', 'WordPoints_Hook_Events' );
52
		$sub_apps->register( 'reactors', 'WordPoints_Class_Registry_Persistent' );
53
		$sub_apps->register( 'reaction_stores', 'WordPoints_Class_Registry_Children' );
54
		$sub_apps->register( 'extensions', 'WordPoints_Class_Registry_Persistent' );
55
		$sub_apps->register( 'conditions', 'WordPoints_Class_Registry_Children' );
56
57
		parent::init();
58
	}
59
60
	/**
61
	 * Gets the current mode that the API is in.
62
	 *
63
	 * By default 'standard' mode is on, unless in network context (such as in the
64
	 * network admin) on multisite, when 'network' mode is the default.
65
	 *
66
	 * The current mode is used by reactors to determine which reaction type to offer
67
	 * access to through the $reactions property. This is allows for generic code for
68
	 * handling reactions to reference the $reactions property of the reactor, and
69
	 * what type of reactions it will get will be determined based on the current
70
	 * mode that is set.
71
	 *
72
	 * @since 1.0.0
73
	 *
74
	 * @return string The slug of the current mode.
75
	 */
76
	public function get_current_mode() {
77
78
		if ( ! isset( $this->current_mode ) ) {
79
			$this->current_mode = ( wordpoints_is_network_context() ? 'network' : 'standard' );
80
		}
81
82
		return $this->current_mode;
83
	}
84
85
	/**
86
	 * Sets the current mode of the API.
87
	 *
88
	 * This function should be used very sparingly. The default mode which is set by
89
	 * WordPoints should work for you in most cases. The primary reason that you
90
	 * would ever need to set the mode yourself is if you have created your own
91
	 * custom mode. Otherwise you probably shouldn't be using this function.
92
	 *
93
	 * @since 1.0.0
94
	 *
95
	 * @param string $mode The slug of the mode to set as the current mode.
96
	 */
97
	public function set_current_mode( $mode ) {
98
		$this->current_mode = $mode;
99
	}
100
101
	/**
102
	 * Get a reaction storage object.
103
	 *
104
	 * @since 1.0.0
105
	 *
106
	 * @param string $slug The slug of the reaction store to get.
107
	 *
108
	 * @return WordPoints_Hook_Reaction_StoreI|false The reaction storage object.
109
	 */
110
	public function get_reaction_store( $slug ) {
111
112
		$reaction_store = $this->reaction_stores->get(
113
			$this->get_current_mode()
114
			, $slug
115
		);
116
117
		if ( ! $reaction_store instanceof WordPoints_Hook_Reaction_StoreI ) {
118
			return false;
119
		}
120
121
		// Allowing access to stores out-of-context would lead to strange behavior.
122
		if ( false === $reaction_store->get_context_id() ) {
123
			return false;
124
		}
125
126
		return $reaction_store;
127
	}
128
	
129
	/**
130
	 * Fire an event at each of the reactions.
131
	 *
132
	 * @since 1.0.0
133
	 *
134
	 * @param string                     $action_type The type of action triggering
135
	 *                                                this fire of this event.
136
	 * @param string                     $event_slug  The slug of the event.
137
	 * @param WordPoints_Hook_Event_Args $event_args  The event args.
138
	 */
139
	public function fire(
140
		$action_type,
141
		$event_slug,
142
		WordPoints_Hook_Event_Args $event_args
143
	) {
144
145
		foreach ( $this->reaction_stores->get_all() as $reaction_stores ) {
146
			foreach ( $reaction_stores as $reaction_store ) {
147
148
				if ( ! $reaction_store instanceof WordPoints_Hook_Reaction_StoreI ) {
149
					continue;
150
				}
151
152
				// Allowing access to stores out-of-context would lead to strange behavior.
153
				if ( false === $reaction_store->get_context_id() ) {
154
					continue;
155
				}
156
157
				foreach ( $reaction_store->get_reactions_to_event( $event_slug ) as $reaction ) {
158
159
					$fire = new WordPoints_Hook_Fire(
160
						$action_type
161
						, $event_args
162
						, $reaction
163
					);
164
165
					$this->fire_reaction( $fire );
166
				}
167
			}
168
		}
169
	}
170
171
	/**
172
	 * Fire for a particular reaction.
173
	 *
174
	 * @since 1.0.0
175
	 *
176
	 * @param WordPoints_Hook_Fire $fire The hook fire object.
177
	 */
178
	protected function fire_reaction( $fire ) {
179
180
		/** @var WordPoints_Hook_Reactor $reactor */
181
		$reactor = $this->reactors->get( $fire->reaction->get_reactor_slug() );
182
183
		if ( ! in_array( $fire->action_type, $reactor->get_action_types(), true ) ) {
184
			return;
185
		}
186
187
		$validator = new WordPoints_Hook_Reaction_Validator( $fire->reaction, true );
188
		$validator->validate();
189
190
		if ( $validator->had_errors() ) {
191
			return;
192
		}
193
194
		unset( $validator );
195
196
		/** @var WordPoints_Hook_Extension[] $extensions */
197
		$extensions = $this->extensions->get_all();
198
199
		foreach ( $extensions as $extension ) {
200
			if ( ! $extension->should_hit( $fire ) ) {
201
				return;
202
			}
203
		}
204
205
		$fire->hit();
206
207
		$reactor->hit( $fire );
208
209
		foreach ( $extensions as $extension ) {
210
			$extension->after_hit( $fire );
211
		}
212
	}
213
}
214
215
// EOF
216