Completed
Branch BUG-9871-email-validation (e62b1a)
by
unknown
350:41 queued 333:27
created

CollectionDetails::setFileMasks()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 4
nop 1
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace EventEspresso\core\services\collections;
3
4
use  EventEspresso\core\exceptions\InvalidDataTypeException;
5
use  EventEspresso\core\exceptions\InvalidFilePathException;
6
use  EventEspresso\core\exceptions\InvalidIdentifierException;
7
use  EventEspresso\core\exceptions\InvalidInterfaceException;
8
use EventEspresso\core\services\locators\FqcnLocator;
9
use EventEspresso\core\services\locators\LocatorInterface;
10
11
if ( ! defined( 'EVENT_ESPRESSO_VERSION' ) ) {
12
	exit( 'No direct script access allowed' );
13
}
14
15
16
17
/**
18
 * Class CollectionDetails
19
 *
20
 * Abstract parent class for defining classes for loading into a collection.
21
 * The supplied interface will be used for type hinting the objects being loaded.
22
 * Classes can either be located by supplying an array of FQCNs (Fully Qualified Class Names),
23
 * AND/OR
24
 * an array of full server filepaths to a folder containing a set of files,
25
 * where the classnames match the filenames minus all extensions.
26
 *  for example:
27
 *  $FQCNs = array(
28
 *      '/Fully/Qualified/ClassNameA'
29
 *      '/Fully/Qualified/Other/ClassNameB'
30
 *  );
31
 *  $paths = array(
32
 *      '/full/server/path/to/ClassNameA.ext.php' // for class ClassNameA
33
 *      '/full/server/path/to/other/ClassNameB.php' // for class ClassNameB
34
 *  );
35
 * You do NOT have to provide both! They operate exclusively.
36
 * So you can provide an array of class names (FQCNs),
37
 * OR an array of folder filepaths,
38
 * OR you can provide both, if you happen to have classes of the same type in two locations,
39
 * and want to add both locations, and it turns out to be easier to use one loading method (FQCNs)
40
 * for the one location, and the other method for the other location.
41
 * You can of course use the same loading method for both locations if that worked best.
42
 *
43
 * @package       Event Espresso
44
 * @subpackage    core
45
 * @author        Brent Christensen
46
 * @since         4.9.0
47
 */
48
class CollectionDetails implements CollectionDetailsInterface {
49
50
	/**
51
	 * if $identifier_type is set to this,
52
	 * then the collection will use each object's spl_object_hash() as it's identifier
53
	 */
54
	const ID_OBJECT_HASH = 'identifier-uses-spl-object-hash';
55
56
	/**
57
	 * if $identifier_type is set to this,
58
	 * then the collection will use each object's class name as it's identifier
59
	 */
60
	const ID_CLASS_NAME = 'identifier-uses-object-class-name';
61
62
	/**
63
	 * if $identifier_type is set to this,
64
	 * then the collection will use the return value from a specified callback method on each object
65
	 */
66
	const ID_CALLBACK_METHOD = 'identifier-uses-callback-method';
67
68
	/**
69
	 * The interface used for controlling what gets added to the collection
70
	 *
71
	 * @var string $collection_interface
72
	 */
73
	protected $collection_interface = '';
74
75
	/**
76
	 * a unique name used to identify the collection in filter names
77
	 * supplied value is run through sanitize_title_with_dashes(),
78
	 * but then also converts dashes to underscores
79
	 *
80
	 * @var string $collection_name
81
	 */
82
	protected $collection_name = '';
83
84
	/**
85
	 * what the collection uses for the object identifier.
86
	 * corresponds to one of the class constants above.
87
	 * CollectionDetails::ID_OBJECT_HASH will use spl_object_hash( object ) for the identifier
88
	 * CollectionDetails::ID_CLASS_NAME will use get_class( object ) for the identifier
89
	 * CollectionDetails::ID_CALLBACK_METHOD will use a callback for the identifier
90
	 * defaults to using spl_object_hash() so that multiple objects of the same class can be added
91
	 *
92
	 * @var string $identifier_type
93
	 */
94
	protected $identifier_type = CollectionDetails::ID_OBJECT_HASH;
95
96
	/**
97
	 * the pattern applied to paths when searching for class files to add to the collection
98
	 * ie: "My_Awesome_*.class.php"
99
	 * defaults to "*.php"
100
	 *
101
	 * @var string $file_mask
102
	 */
103
	protected $file_mask = '';
104
105
	/**
106
	 * if the $identifier_type above is set to CollectionDetails::ID_CALLBACK_METHOD,
107
	 * then this specifies the method to use on each entity.
108
	 * If the callback method does not exist, then an exception will be thrown
109
	 *
110
	 * @var string $identifier_callback
111
	 */
112
	protected $identifier_callback = '';
113
114
	/**
115
	 * an array of Fully Qualified Class Names
116
	 *  for example:
117
	 *  $FQCNs = array(
118
	 *      '/Fully/Qualified/ClassNameA'
119
	 *      '/Fully/Qualified/Other/ClassNameB'
120
	 *  );
121
	 *
122
	 * @var array $collection_FQCNs
123
	 */
124
	protected $collection_FQCNs = array();
125
126
	/**
127
	 * an array of full server paths to folders containing files to be loaded into collection
128
	 *  for example:
129
	 *  $paths = array(
130
	 *      '/full/server/path/to/ClassNameA.ext.php' // for class ClassNameA
131
	 *      '/full/server/path/to/other/ClassNameB.php' // for class ClassNameB
132
	 *  );
133
	 *
134
	 * @var array $collection_paths
135
	 */
136
	protected $collection_paths = array();
137
138
	/**
139
	 * @var LocatorInterface $file_locator
140
	 */
141
	protected $file_locator;
142
143
144
145
	/**
146
	 * CollectionDetails constructor.
147
	 *
148
	 * @access public
149
	 * @param string           $collection_name
150
	 * @param string           $collection_interface
151
	 * @param array            $collection_FQCNs
152
	 * @param array            $collection_paths
153
	 * @param string           $file_mask
154
	 * @param string           $identifier_type
155
	 * @param string           $identifier_callback
156
	 * @param LocatorInterface $file_locator
157
	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
158
	 * @throws \EventEspresso\core\exceptions\InvalidFilePathException
159
	 * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
160
	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
161
	 * @throws \EventEspresso\core\exceptions\InvalidClassException
162
	 */
163
	public function __construct(
164
		$collection_name,
165
		$collection_interface,
166
		$collection_FQCNs = array(),
167
		$collection_paths = array(),
168
		$file_mask = '',
169
		$identifier_type = CollectionDetails::ID_OBJECT_HASH,
170
		$identifier_callback = '',
171
		LocatorInterface $file_locator = null
172
	) {
173
		$this->setCollectionName( $collection_name );
174
		$this->setCollectionInterface( $collection_interface );
175
		$this->setCollectionFQCNs( $collection_FQCNs );
176
		$this->setCollectionPaths( $collection_paths );
177
		$this->setFileMasks( $file_mask );
178
		$this->setIdentifierType( $identifier_type );
179
		$this->setIdentifierCallback( $identifier_callback );
180
		$this->file_locator = $file_locator;
181
	}
182
183
184
185
	/**
186
	 * @access public
187
	 * @return mixed
188
	 */
189
	public function getCollectionInterface() {
190
		return $this->collection_interface;
191
	}
192
193
194
195
	/**
196
	 * @access protected
197
	 * @param string $collection_interface
198
	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
199
	 */
200
	protected function setCollectionInterface( $collection_interface ) {
201
		if ( ! ( interface_exists( $collection_interface ) || class_exists( $collection_interface ) ) ) {
202
			throw new InvalidInterfaceException( $collection_interface );
203
		}
204
		$this->collection_interface = $collection_interface;
205
	}
206
207
208
209
	/**
210
	 * the collection name will be used for creating dynamic filters
211
	 *
212
	 * @access public
213
	 * @return string
214
	 */
215
	public function collectionName() {
216
		return $this->collection_name;
217
	}
218
219
220
221
	/**
222
	 * sanitizes collection name and converts spaces and dashes to underscores
223
	 *
224
	 * @access protected
225
	 * @param string $collection_name
226
	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
227
	 */
228
	protected function setCollectionName( $collection_name ) {
229
		if ( ! is_string( $collection_name ) ) {
230
			throw new InvalidDataTypeException( '$collection_name', $collection_name, 'string' );
231
		}
232
		$this->collection_name = str_replace(
233
			'-',
234
			'_',
235
			sanitize_title_with_dashes( $collection_name, '', 'save' )
236
		);
237
	}
238
239
240
241
	/**
242
	 * @access public
243
	 * @return string
244
	 */
245
	public function identifierType() {
246
		return $this->identifier_type;
247
	}
248
249
250
251
	/**
252
	 * @access protected
253
	 * @param string $identifier_type
254
	 * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
255
	 */
256
	protected function setIdentifierType( $identifier_type ) {
257
		if (
258
			! (
259
				$identifier_type === CollectionDetails::ID_CLASS_NAME
260
				|| $identifier_type === CollectionDetails::ID_OBJECT_HASH
261
				|| $identifier_type === CollectionDetails::ID_CALLBACK_METHOD
262
			)
263
		) {
264
			throw new InvalidIdentifierException(
265
				$identifier_type,
266
				'CollectionDetails::ID_CLASS_NAME or CollectionDetails::ID_OBJECT_HASH or CollectionDetails::ID_CALLBACK_METHOD'
267
			);
268
		}
269
		$this->identifier_type = $identifier_type;
270
	}
271
272
273
274
	/**
275
	 * @access public
276
	 * @return string
277
	 */
278
	public function identifierCallback() {
279
		return $this->identifier_callback;
280
	}
281
282
283
284
	/**
285
	 * @access protected
286
	 * @param string $identifier_callback
287
	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
288
	 */
289
	protected function setIdentifierCallback( $identifier_callback = 'identifier' ) {
290
		if ( ! is_string( $identifier_callback ) ) {
291
			throw new InvalidDataTypeException( '$identifier_callback', $identifier_callback, 'string' );
292
		}
293
		$this->identifier_callback = $identifier_callback;
294
	}
295
296
297
298
	/**
299
	 * @access public
300
	 * @return array
301
	 */
302
	public function getFileMask() {
303
		return $this->file_mask;
304
	}
305
306
307
308
	/**
309
	 * sets the file mask which is then used to filter what files get loaded
310
	 * when searching for classes to add to the collection. Defaults to '*.php'
311
	 *
312
	 * @access protected
313
	 * @param string $file_mask
314
	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
315
	 */
316
	protected function setFileMasks( $file_mask ) {
317
		$this->file_mask = ! empty( $file_mask ) ? $file_mask : '*.php';
318
		// we know our default is a string, so if it's not a string now,
319
		// then that means the incoming parameter was something else
320
		if ( ! is_string( $this->file_mask ) ) {
321
			throw new InvalidDataTypeException( '$file_mask', $this->file_mask, 'string' );
322
		}
323
	}
324
325
326
327
	/**
328
	 * @access public
329
	 * @return string
330
	 */
331
	public function getCollectionFQCNs() {
332
		return $this->collection_FQCNs;
333
	}
334
335
336
337
	/**
338
	 * @access public
339
	 * @param string|array $collection_FQCNs
340
	 * @throws \EventEspresso\core\exceptions\InvalidClassException
341
	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
342
	 */
343
	public function setCollectionFQCNs( $collection_FQCNs ) {
344
		foreach ( (array) $collection_FQCNs as $collection_FQCN ) {
345
			if ( ! empty( $collection_FQCN ) ) {
346
				if ( class_exists( $collection_FQCN ) ) {
347
					$this->collection_FQCNs[] = $collection_FQCN;
348
				} else {
349
					foreach ( $this->getFQCNsFromPartialNamespace( $collection_FQCN ) as $FQCN ) {
350
						$this->collection_FQCNs[] = $FQCN;
351
					}
352
				}
353
			}
354
		}
355
	}
356
357
358
359
	/**
360
	 * @access protected
361
	 * @param  string $partial_FQCN
362
	 * @return array
363
	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
364
	 * @throws \EventEspresso\core\exceptions\InvalidClassException
365
	 */
366
	protected function getFQCNsFromPartialNamespace( $partial_FQCN ) {
367
		if ( ! $this->file_locator instanceof FqcnLocator ) {
368
			$this->file_locator = new FqcnLocator();
369
		}
370
		$this->file_locator->locate( $partial_FQCN );
371
		return $this->file_locator->getFQCNs();
372
	}
373
374
375
376
	/**
377
	 * @access public
378
	 * @return string
379
	 */
380
	public function getCollectionPaths() {
381
		return $this->collection_paths;
382
	}
383
384
385
386
	/**
387
	 * @access public
388
	 * @param string|array $collection_paths
389
	 * @throws \EventEspresso\core\exceptions\InvalidFilePathException
390
	 */
391
	public function setCollectionPaths( $collection_paths ) {
392
		foreach ( (array) $collection_paths as $collection_path ) {
393
			if ( ! empty( $collection_path ) ) {
394
				if ( ! is_readable( $collection_path ) ) {
395
					throw new InvalidFilePathException( $collection_path );
396
				}
397
				$this->collection_paths[] = $collection_path;
398
			}
399
		}
400
	}
401
402
403
404
}
405
// End of file CollectionDetails.php
406
// Location: /CollectionDetails.php