Passed
Push — master ( 52a1f2...f8ab54 )
by Alain
03:16
created

DependencyManager::validate_context()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 6
ccs 0
cts 4
cp 0
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
crap 6
1
<?php
2
/**
3
 * DependencyManager Class.
4
 *
5
 * @package   BrightNucleus\Dependency
6
 * @author    Alain Schlesser <[email protected]>
7
 * @license   GPL-2.0+
8
 * @link      http://www.brightnucleus.com/
9
 * @copyright 2015 Alain Schlesser, Bright NucleusInterface
10
 */
11
12
namespace BrightNucleus\Dependency;
13
14
use BrightNucleus\Config\ConfigInterface;
15
use BrightNucleus\Config\ConfigTrait;
16
use BrightNucleus\Exception\InvalidArgumentException;
17
use BrightNucleus\Exception\RuntimeException;
18
19
/**
20
 * Register and enqueue dependencies that are listed in the config file.
21
 *
22
 * @since   0.1.0
23
 *
24
 * @package BrightNucleus\Dependency
25
 * @author  Alain Schlesser <[email protected]>
26
 */
27
class DependencyManager implements DependencyManagerInterface {
28
29
	use ConfigTrait;
30
31
	/*
32
	 * Default dependency handler implementations.
33
	 */
34
	const DEFAULT_SCRIPT_HANDLER = '\BrightNucleus\Dependency\ScriptHandler';
35
	const DEFAULT_STYLE_HANDLER  = '\BrightNucleus\Dependency\StyleHandler';
36
37
	/*
38
	 * Names of the configuration keys.
39
	 */
40
	const KEY_HANDLERS = 'handlers';
41
	const KEY_SCRIPTS  = 'scripts';
42
	const KEY_STYLES   = 'styles';
43
44
	/**
45
	 * Hold the dependencies, grouped by type.
46
	 *
47
	 * @since 0.1.0
48
	 *
49
	 * @var array;
50
	 */
51
	protected $dependencies = [ ];
52
53
	/**
54
	 * Hold the handlers.
55
	 *
56
	 * @since 0.1.0
57
	 *
58
	 * @var array
59
	 */
60
	protected $handlers = [ ];
61
62
	/**
63
	 * Instantiate DependencyManager object.
64
	 *
65
	 * @since 0.1.0
66
	 *
67
	 * @param ConfigInterface $config         ConfigInterface object that
68
	 *                                        contains dependency settings.
69
	 * @throws RuntimeException If the config could not be processed.
70
	 * @throws InvalidArgumentException If no dependency handlers were
71
	 *                                        specified.
72
	 */
73
	public function __construct( ConfigInterface $config ) {
74
		$this->processConfig( $config );
75
		$this->init_handlers();
76
		$this->init_dependencies();
77
	}
78
79
	/**
80
	 * Initialize the dependency handlers.
81
	 *
82
	 * @since 0.1.0
83
	 */
84
	protected function init_handlers() {
85
		$keys = [ self::KEY_SCRIPTS, self::KEY_STYLES ];
86
		foreach ( $keys as $key ) {
87
			if ( $this->hasConfigKey( $key ) ) {
88
				$this->add_handler( $key );
89
			}
90
		}
91
	}
92
93
	/**
94
	 * Add a single dependency handler.
95
	 *
96
	 * @since 0.1.0
97
	 *
98
	 * @param string $dependency The dependency type for which to add a handler.
99
	 */
100
	protected function add_handler( $dependency ) {
101
		if ( $this->hasConfigKey( $dependency ) ) {
102
			$handler = $this->hasConfigKey( self::KEY_HANDLERS, $dependency )
103
				? $this->getConfigKey( self::KEY_HANDLERS, $dependency )
104
				: $this->get_default_handler( $dependency );
105
			if ( $handler ) {
106
				$this->handlers[ $dependency ] = $handler;
107
			}
108
		}
109
	}
110
111
	/**
112
	 * Get the default handler class for a given type of dependency.
113
	 *
114
	 * @since 0.1.0
115
	 *
116
	 * @param string $dependency The dependency that needs a handler.
117
	 * @return string|null Class name of the handler. Null if none.
118
	 */
119
	protected function get_default_handler( $dependency ) {
120
		switch ( $dependency ) {
121
			case self::KEY_STYLES:
122
				return self::DEFAULT_STYLE_HANDLER;
123
			case self::KEY_SCRIPTS:
124
				return self::DEFAULT_SCRIPT_HANDLER;
125
			default:
126
				return null;
127
		}
128
	}
129
130
	/**
131
	 * Initialize the actual dependencies.
132
	 *
133
	 * @since 0.1.0
134
	 */
135
	protected function init_dependencies() {
136
		array_walk( $this->handlers,
137
			function ( $handler, $dependency_type ) {
138
				if ( $this->hasConfigKey( $dependency_type ) ) {
139
					$this->dependencies[ $dependency_type ] = $this->getConfigKey( $dependency_type );
140
				}
141
			} );
142
	}
143
144
	/**
145
	 * Register all dependencies.
146
	 *
147
	 * @since 0.1.0
148
	 *
149
	 * @param mixed $context Optional. The context to pass to the dependencies.
150
	 */
151
	public function register( $context = null ) {
152
		$context = $this->validate_context( $context );
153
		array_walk( $this->dependencies,
154
			[ $this, 'register_dependency_type' ], $context );
155
	}
156
157
	/**
158
	 * Validate the context to make sure it is an array.
159
	 *
160
	 * @since 0.2.1
161
	 *
162
	 * @param mixed $context The context as passed in by WordPress.
163
	 * @return array Validated context.
164
	 */
165
	protected function validate_context( $context ) {
166
		if ( is_string( $context ) ) {
167
			return [ 'wp_context' => $context ];
168
		}
169
		return (array) $context;
170
	}
171
172
	/**
173
	 * Enqueue all dependencies.
174
	 *
175
	 * @since 0.1.0
176
	 *
177
	 * @param mixed $context Optional. The context to pass to the dependencies.
178
	 */
179
	public function enqueue( $context = null ) {
180
		$context = $this->validate_context( $context );
181
		array_walk( $this->dependencies,
182
			[ $this, 'enqueue_dependency_type' ], $context );
183
	}
184
185
	/**
186
	 * Enqueue all dependencies of a specific type.
187
	 *
188
	 * @since 0.1.0
189
	 *
190
	 * @param array  $dependencies    The dependencies to enqueue.
191
	 * @param string $dependency_type The type of the dependencies.
192
	 * @param mixed  $context         Optional. The context to pass to the
193
	 *                                dependencies.
194
	 */
195
	protected function enqueue_dependency_type( $dependencies, $dependency_type, $context = null ) {
196
		$context['dependency_type'] = $dependency_type;
197
		array_walk( $dependencies, [ $this, 'enqueue_dependency' ], $context );
198
	}
199
200
	/**
201
	 * Register all dependencies of a specific type.
202
	 *
203
	 * @since 0.1.0
204
	 *
205
	 * @param array  $dependencies    The dependencies to register.
206
	 * @param string $dependency_type The type of the dependencies.
207
	 * @param mixed  $context         Optional. The context to pass to the
208
	 *                                dependencies.
209
	 */
210
	protected function register_dependency_type( $dependencies, $dependency_type, $context = null ) {
211
		$context['dependency_type'] = $dependency_type;
212
		array_walk( $dependencies, [ $this, 'register_dependency' ], $context );
213
	}
214
215
	/**
216
	 * Register a single dependency.
217
	 *
218
	 * @since 0.1.0
219
	 *
220
	 * @param array  $dependency     Configuration data of the dependency.
221
	 * @param string $dependency_key Config key of the dependency.
222
	 * @param mixed  $context        Optional. Context to pass to the
223
	 *                               dependencies. Contains the type of the
224
	 *                               dependency at key
225
	 *                               'dependency_type'.
226
	 */
227
	protected function register_dependency( $dependency, $dependency_key, $context = null ) {
228
		/** @var \BrightNucleus\Contract\Registerable $handler */
229
		$handler = new $this->handlers[$context['dependency_type']];
230
		$handler->register( $dependency );
231
		\add_action( 'wp_enqueue_scripts',
232
			[ $this, 'enqueue' ] );
233
		\add_action( 'admin_enqueue_scripts',
234
			[ $this, 'enqueue' ] );
235
		if ( array_key_exists( 'localize', $dependency ) ) {
236
			$this->localize( $dependency, $context );
237
		}
238
	}
239
240
	/**
241
	 * Localize the script of a given dependency.
242
	 *
243
	 * @since 0.1.0
244
	 *
245
	 * @param array $dependency The dependency to localize the script of.
246
	 * @param mixed $context    Contextual data to pass to the callback.
247
	 *                          Contains the type of the dependency at key
248
	 *                          'dependency_type'.
249
	 */
250
	protected function localize( $dependency, $context ) {
251
		$localize = $dependency['localize'];
252
		$data     = $localize['data'];
253
		if ( is_callable( $data ) ) {
254
			$data = $data( $context );
255
		}
256
		\wp_localize_script( $dependency['handle'], $localize['name'], $data );
257
	}
258
259
	/**
260
	 * Enqueue a single dependency.
261
	 *
262
	 * @since 0.1.0
263
	 *
264
	 * @param array  $dependency     Configuration data of the dependency.
265
	 * @param string $dependency_key Config key of the dependency.
266
	 * @param mixed  $context        Optional. Context to pass to the
267
	 *                               dependencies. Contains the type of the
268
	 *                               dependency at key
269
	 *                               'dependency_type'.
270
	 */
271
	protected function enqueue_dependency( $dependency, $dependency_key, $context = null ) {
272
		if ( ! $this->is_needed( $dependency, $context ) ) {
273
			return;
274
		}
275
		/** @var \BrightNucleus\Contract\Enqueueable $handler */
276
		$handler = new $this->handlers[$context['dependency_type']];
277
		$handler->enqueue( $dependency );
278
	}
279
280
	/**
281
	 * Check whether a specific dependency is needed.
282
	 *
283
	 * @since 0.1.0
284
	 *
285
	 * @param array $dependency Configuration of the dependency to check.
286
	 * @param mixed $context    Context to pass to the dependencies.
287
	 *                          Contains the type of the dependency at key
288
	 *                          'dependency_type'.
289
	 * @return bool Whether it is needed or not.
290
	 */
291
	protected function is_needed( $dependency, $context ) {
292
		$is_needed = array_key_exists( 'is_needed', $dependency )
293
			? $dependency['is_needed']
294
			: null;
295
296
		if ( null === $is_needed ) {
297
			return true;
298
		}
299
300
		return is_callable( $is_needed ) && $is_needed( $context );
301
	}
302
}
303