Completed
Push — master ( f8fd12...f064aa )
by James
10s
created
src/Axolotl/Model.php 2 patches
Indentation   +716 added lines, -716 removed lines patch added patch discarded remove patch
@@ -21,720 +21,720 @@
 block discarded – undo
21 21
  * @since      0.1.0
22 22
  */
23 23
 abstract class Model implements Serializes {
24
-	/**
25
-	 * Table attribute key.
26
-	 */
27
-	const TABLE_KEY = '@@table';
28
-
29
-	/**
30
-	 * Object attribute key.
31
-	 */
32
-	const OBJECT_KEY = '@@object';
33
-
34
-	/**
35
-	 * Memoized values for class methods.
36
-	 *
37
-	 * @var array
38
-	 */
39
-	private static $memo = array();
40
-
41
-	/**
42
-	 * Model attributes.
43
-	 *
44
-	 * @var array
45
-	 */
46
-	private $attributes = array(
47
-		self::TABLE_KEY  => array(),
48
-		self::OBJECT_KEY => null,
49
-	);
50
-
51
-	/**
52
-	 * Model's original attributes.
53
-	 *
54
-	 * @var array
55
-	 */
56
-	private $original = array(
57
-		self::TABLE_KEY  => array(),
58
-		self::OBJECT_KEY => null,
59
-	);
60
-
61
-	/**
62
-	 * Properties which are allowed to be set on the model.
63
-	 *
64
-	 * If this array is empty, any attributes can be set on the model.
65
-	 *
66
-	 * @var string[]
67
-	 */
68
-	protected $fillable = array();
69
-
70
-	/**
71
-	 * Properties which cannot be automatically filled on the model.
72
-	 *
73
-	 * If the model is unguarded, these properties can be filled.
74
-	 *
75
-	 * @var array
76
-	 */
77
-	protected $guarded = array();
78
-
79
-	/**
80
-	 * Properties which should not be serialized.
81
-	 *
82
-	 * @var array
83
-	 */
84
-	protected $hidden = array();
85
-
86
-	/**
87
-	 * Properties which should be serialized.
88
-	 *
89
-	 * @var array
90
-	 */
91
-	protected $visible = array();
92
-
93
-	/**
94
-	 * Whether the model's properties are guarded.
95
-	 *
96
-	 * When false, allows guarded properties to be filled.
97
-	 *
98
-	 * @var bool
99
-	 */
100
-	protected $is_guarded = true;
101
-
102
-	/**
103
-	 * Constructs a new model with provided attributes.
104
-	 *
105
-	 * If self::OBJECT_KEY is passed as one of the attributes, the underlying post
106
-	 * will be overwritten.
107
-	 *
108
-	 * @param array <string, mixed> $attributes
109
-	 */
110
-	public function __construct( array $attributes = array() ) {
111
-		$this->maybe_boot();
112
-		$this->sync_original();
113
-
114
-		if ( $this->uses_wp_object() ) {
115
-			$this->create_wp_object();
116
-		}
117
-
118
-		$this->unguard();
119
-		$this->refresh( $attributes );
120
-		$this->reguard();
121
-	}
122
-
123
-	/**
124
-	 * Refreshes the model's current attributes with the provided array.
125
-	 *
126
-	 * The model's attributes will match what was provided in the array,
127
-	 * and any attributes not passed
128
-	 *
129
-	 * @param array $attributes
130
-	 *
131
-	 * @return $this
132
-	 */
133
-	public function refresh( array $attributes ) {
134
-		$this->clear();
135
-
136
-		return $this->merge( $attributes );
137
-	}
138
-
139
-	/**
140
-	 * Merges the provided attributes with the provided array.
141
-	 *
142
-	 * @param array $attributes
143
-	 *
144
-	 * @return $this
145
-	 */
146
-	public function merge( array $attributes ) {
147
-		foreach ( $attributes as $name => $value ) {
148
-			$this->set_attribute( $name, $value );
149
-		}
150
-
151
-		return $this;
152
-	}
153
-
154
-	/**
155
-	 * Get the model's table attributes.
156
-	 *
157
-	 * Returns the array of for the model that will either need to be
158
-	 * saved in postmeta or a separate table.
159
-	 *
160
-	 * @return array
161
-	 */
162
-	public function get_table_attributes() {
163
-		return $this->attributes[ self::TABLE_KEY ];
164
-	}
165
-
166
-	/**
167
-	 * Get the model's original attributes.
168
-	 *
169
-	 * @return array
170
-	 */
171
-	public function get_original_table_attributes() {
172
-		return $this->original[ self::TABLE_KEY ];
173
-	}
174
-
175
-	/**
176
-	 * Retrieve an array of the attributes on the model
177
-	 * that have changed compared to the model's
178
-	 * original data.
179
-	 *
180
-	 * @return array
181
-	 */
182
-	public function get_changed_table_attributes() {
183
-		$changed = array();
184
-
185
-		foreach ( $this->get_table_attributes() as $key => $value ) {
186
-			if ( $value !==
187
-			     $this->get_original_attribute( $key )
188
-			) {
189
-				$changed[ $key ] = $value;
190
-			}
191
-		}
192
-
193
-		return $changed;
194
-	}
195
-
196
-	/**
197
-	 * Get the model's underlying post.
198
-	 *
199
-	 * Returns the underlying WP_Post object for the model, representing
200
-	 * the data that will be save in the wp_posts table.
201
-	 *
202
-	 * @return false|WP_Post|WP_Term
203
-	 */
204
-	public function get_underlying_wp_object() {
205
-		if ( isset( $this->attributes[ self::OBJECT_KEY ] ) ) {
206
-			return $this->attributes[ self::OBJECT_KEY ];
207
-		}
208
-
209
-		return false;
210
-	}
211
-
212
-	/**
213
-	 * Get the model's original underlying post.
214
-	 *
215
-	 * @return WP_Post
216
-	 */
217
-	public function get_original_underlying_wp_object() {
218
-		return $this->original[ self::OBJECT_KEY ];
219
-	}
220
-
221
-	/**
222
-	 * Get the model attributes on the WordPress object
223
-	 * that have changed compared to the model's
224
-	 * original attributes.
225
-	 *
226
-	 * @return array
227
-	 */
228
-	public function get_changed_wp_object_attributes() {
229
-		$changed = array();
230
-
231
-		foreach ( $this->get_wp_object_keys() as $key ) {
232
-			if ( $this->get_attribute( $key ) !==
233
-			     $this->get_original_attribute( $key )
234
-			) {
235
-				$changed[ $key ] = $this->get_attribute( $key );
236
-			}
237
-		}
238
-
239
-		return $changed;
240
-	}
241
-
242
-	/**
243
-	 * Magic __set method.
244
-	 *
245
-	 * Passes the name and value to set_attribute, which is where the magic happens.
246
-	 *
247
-	 * @param string $name
248
-	 * @param mixed  $value
249
-	 */
250
-	public function __set( $name, $value ) {
251
-		$this->set_attribute( $name, $value );
252
-	}
253
-
254
-	/**
255
-	 * Sets the model attributes.
256
-	 *
257
-	 * Checks whether the model attribute can be set, check if it
258
-	 * maps to the WP_Post property, otherwise, assigns it to the
259
-	 * table attribute array.
260
-	 *
261
-	 * @param string $name
262
-	 * @param mixed  $value
263
-	 *
264
-	 * @return $this
265
-	 *
266
-	 * @throws Exception
267
-	 * @throws GuardedPropertyException
268
-	 */
269
-	public function set_attribute( $name, $value ) {
270
-		if ( self::OBJECT_KEY === $name ) {
271
-			if ( ! $value ) {
272
-				throw new Exception;
273
-			}
274
-
275
-			return $this->override_wp_object( $value );
276
-		}
277
-
278
-		if ( self::TABLE_KEY === $name ) {
279
-			return $this->override_table( $value );
280
-		}
281
-
282
-		if ( ! $this->is_fillable( $name ) ) {
283
-			throw new GuardedPropertyException;
284
-		}
285
-
286
-		if ( $method = $this->has_map_method( $name ) ) {
287
-			$this->attributes[ self::OBJECT_KEY ]->{$this->{$method}()} = $value;
288
-		} else {
289
-			$this->attributes[ self::TABLE_KEY ][ $name ] = $value;
290
-		}
291
-
292
-		return $this;
293
-	}
294
-
295
-	/**
296
-	 * Retrieves all the attribute keys for the model.
297
-	 *
298
-	 * @return array
299
-	 */
300
-	public function get_attribute_keys() {
301
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
302
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
303
-		}
304
-
305
-		return self::$memo[ get_called_class() ][ __METHOD__ ]
306
-			= array_merge(
307
-				$this->fillable,
308
-				$this->guarded,
309
-				$this->get_compute_methods()
310
-			);
311
-	}
312
-
313
-	/**
314
-	 * Retrieves the attribute keys that aren't mapped to a post.
315
-	 *
316
-	 * @return array
317
-	 */
318
-	public function get_table_keys() {
319
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
320
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
321
-		}
322
-
323
-		$keys = array();
324
-
325
-		foreach ( $this->get_attribute_keys() as $key ) {
326
-			if ( ! $this->has_map_method( $key ) &&
327
-			     ! $this->has_compute_method( $key )
328
-			) {
329
-				$keys[] = $key;
330
-			}
331
-		}
332
-
333
-		return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
334
-	}
335
-
336
-	/**
337
-	 * Retrieves the attribute keys that are mapped to a post.
338
-	 *
339
-	 * @return array
340
-	 */
341
-	public function get_wp_object_keys() {
342
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
343
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
344
-		}
345
-
346
-		$keys = array();
347
-
348
-		foreach ( $this->get_attribute_keys() as $key ) {
349
-			if ( $this->has_map_method( $key ) ) {
350
-				$keys[] = $key;
351
-			}
352
-		}
353
-
354
-		return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
355
-	}
356
-
357
-	/**
358
-	 * Returns the model's keys that are computed at call time.
359
-	 *
360
-	 * @return array
361
-	 */
362
-	public function get_computed_keys() {
363
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
364
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
365
-		}
366
-
367
-		$keys = array();
368
-
369
-		foreach ( $this->get_attribute_keys() as $key ) {
370
-			if ( $this->has_compute_method( $key ) ) {
371
-				$keys[] = $key;
372
-			}
373
-		}
374
-
375
-		return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
376
-	}
377
-
378
-	/**
379
-	 * Serializes the model's public data into an array.
380
-	 *
381
-	 * @return array
382
-	 */
383
-	public function serialize() {
384
-		$attributes = array();
385
-
386
-		if ( $this->visible ) {
387
-			// If visible attributes are set, we'll only reveal those.
388
-			foreach ( $this->visible as $key ) {
389
-				$attributes[ $key ] = $this->get_attribute( $key );
390
-			}
391
-		} elseif ( $this->hidden ) {
392
-			// If hidden attributes are set, we'll grab everything and hide those.
393
-			foreach ( $this->get_attribute_keys() as $key ) {
394
-				if ( ! in_array( $key, $this->hidden ) ) {
395
-					$attributes[ $key ] = $this->get_attribute( $key );
396
-				}
397
-			}
398
-		} else {
399
-			// If nothing is hidden/visible, we'll grab and reveal everything.
400
-			foreach ( $this->get_attribute_keys() as $key ) {
401
-				$attributes[ $key ] = $this->get_attribute( $key );
402
-			}
403
-		}
404
-
405
-		return array_map( function ( $attribute ) {
406
-			if ( $attribute instanceof Serializes ) {
407
-				return $attribute->serialize();
408
-			}
409
-
410
-			return $attribute;
411
-		}, $attributes );
412
-	}
413
-
414
-	/**
415
-	 * Syncs the current attributes to the model's original.
416
-	 *
417
-	 * @return $this
418
-	 */
419
-	public function sync_original() {
420
-		$this->original = $this->attributes;
421
-
422
-		if ( $this->attributes[ self::OBJECT_KEY ] ) {
423
-			$this->original[ self::OBJECT_KEY ] = clone $this->attributes[ self::OBJECT_KEY ];
424
-		}
425
-
426
-		foreach ( $this->original[ self::TABLE_KEY ] as $key => $item ) {
427
-			if ( is_object( $item ) ) {
428
-				$this->original[ $key ] = clone $item;
429
-			}
430
-		}
431
-
432
-		return $this;
433
-	}
434
-
435
-	/**
436
-	 * Checks if a given attribute is mass-fillable.
437
-	 *
438
-	 * Returns true if the attribute can be filled, false if it can't.
439
-	 *
440
-	 * @param string $name
441
-	 *
442
-	 * @return bool
443
-	 */
444
-	private function is_fillable( $name ) {
445
-		// If this model isn't guarded, everything is fillable.
446
-		if ( ! $this->is_guarded ) {
447
-			return true;
448
-		}
449
-
450
-		// If it's in the fillable array, then it's fillable.
451
-		if ( in_array( $name, $this->fillable ) ) {
452
-			return true;
453
-		}
454
-
455
-		// If it's explicitly guarded, then it's not fillable.
456
-		if ( in_array( $name, $this->guarded ) ) {
457
-			return false;
458
-		}
459
-
460
-		// If fillable hasn't been defined, then everything else fillable.
461
-		return ! $this->fillable;
462
-	}
463
-
464
-	/**
465
-	 * Overrides the current WordPress object with a provided one.
466
-	 *
467
-	 * Resets the post's default values and stores it in the attributes.
468
-	 *
469
-	 * @param WP_Post|WP_Term $value
470
-	 *
471
-	 * @return $this
472
-	 */
473
-	private function override_wp_object( $value ) {
474
-		$this->attributes[ self::OBJECT_KEY ] = $this->set_wp_object_constants( $value );
475
-
476
-		return $this;
477
-	}
478
-
479
-	/**
480
-	 * Overrides the current table attributes array with a provided one.
481
-	 *
482
-	 * @param array $value
483
-	 *
484
-	 * @return $this
485
-	 */
486
-	private function override_table( array $value ) {
487
-		$this->attributes[ self::TABLE_KEY ] = $value;
488
-
489
-		return $this;
490
-	}
491
-
492
-	/**
493
-	 * Create and set with a new blank post.
494
-	 *
495
-	 * Creates a new WP_Post object, assigns it the default attributes,
496
-	 * and stores it in the attributes.
497
-	 *
498
-	 * @throws LogicException
499
-	 */
500
-	private function create_wp_object() {
501
-		switch ( true ) {
502
-			case $this instanceof UsesWordPressPost:
503
-				$object = new WP_Post( (object) array() );
504
-				break;
505
-			case $this instanceof UsesWordPressTerm:
506
-				$object = new WP_Term( (object) array() );
507
-				break;
508
-			default:
509
-				throw new LogicException;
510
-				break;
511
-		}
512
-
513
-		$this->attributes[ self::OBJECT_KEY ] = $this->set_wp_object_constants( $object );
514
-	}
515
-
516
-	/**
517
-	 * Enforces values on the post that can't change.
518
-	 *
519
-	 * Primarily, this is used to make sure the post_type always maps
520
-	 * to the model's "$type" property, but this can all be overridden
521
-	 * by the developer to enforce other values in the model.
522
-	 *
523
-	 * @param object $object
524
-	 *
525
-	 * @return object
526
-	 */
527
-	protected function set_wp_object_constants( $object ) {
528
-		if ( $this instanceof UsesWordPressPost ) {
529
-			$object->post_type = static::get_post_type();
530
-		}
531
-
532
-		if ( $this instanceof UsesWordPressTerm ) {
533
-			$object->taxonomy = static::get_taxonomy();
534
-		}
535
-
536
-		return $object;
537
-	}
538
-
539
-	/**
540
-	 * Magic __get method.
541
-	 *
542
-	 * Passes the name and value to get_attribute, which is where the magic happens.
543
-	 *
544
-	 * @param string $name
545
-	 *
546
-	 * @return mixed
547
-	 */
548
-	public function __get( $name ) {
549
-		return $this->get_attribute( $name );
550
-	}
551
-
552
-	/**
553
-	 * Retrieves the model attribute.
554
-	 *
555
-	 * @param string $name
556
-	 *
557
-	 * @return mixed
558
-	 *
559
-	 * @throws PropertyDoesNotExistException If property isn't found.
560
-	 */
561
-	public function get_attribute( $name ) {
562
-		if ( $method = $this->has_map_method( $name ) ) {
563
-			$value = $this->attributes[ self::OBJECT_KEY ]->{$this->{$method}()};
564
-		} elseif ( $method = $this->has_compute_method( $name ) ) {
565
-			$value = $this->{$method}();
566
-		} else {
567
-			if ( ! isset( $this->attributes[ self::TABLE_KEY ][ $name ] ) ) {
568
-				throw new PropertyDoesNotExistException( $name );
569
-			}
570
-
571
-			$value = $this->attributes[ self::TABLE_KEY ][ $name ];
572
-		}
573
-
574
-		return $value;
575
-	}
576
-
577
-	/**
578
-	 * Retrieve the model's original attribute value.
579
-	 *
580
-	 * @param string $name
581
-	 *
582
-	 * @return mixed
583
-	 *
584
-	 * @throws PropertyDoesNotExistException If property isn't found.
585
-	 */
586
-	public function get_original_attribute( $name ) {
587
-		$original_attributes = $this->original;
588
-
589
-		if ( ! is_object( $original_attributes[ static::OBJECT_KEY ] ) ) {
590
-			unset( $original_attributes[ static::OBJECT_KEY ] );
591
-		}
592
-
593
-		$original = new static( $original_attributes );
594
-
595
-		try {
596
-			return $original->get_attribute( $name );
597
-		} catch ( Exception $exception ) {
598
-			return null;
599
-		}
600
-	}
601
-
602
-	/**
603
-	 * Fetches the Model's primary ID, depending on the model
604
-	 * implementation.
605
-	 *
606
-	 * @return int
607
-	 *
608
-	 * @throws LogicException
609
-	 */
610
-	public function get_primary_id() {
611
-		if ( $this instanceof UsesWordPressPost ) {
612
-			return $this->get_underlying_wp_object()->ID;
613
-		}
614
-
615
-		if ( $this instanceof UsesWordPressTerm ) {
616
-			return $this->get_underlying_wp_object()->term_id;
617
-		}
618
-
619
-		// Model w/o wp_object not yet supported.
620
-		throw new LogicException;
621
-	}
622
-
623
-	/**
624
-	 * Checks whether the attribute has a map method.
625
-	 *
626
-	 * This is used to determine whether the attribute maps to a
627
-	 * property on the underlying WP_Post object. Returns the
628
-	 * method if one exists, returns false if it doesn't.
629
-	 *
630
-	 * @param string $name
631
-	 *
632
-	 * @return false|string
633
-	 */
634
-	protected function has_map_method( $name ) {
635
-		if ( method_exists( $this, $method = "map_{$name}" ) ) {
636
-			return $method;
637
-		}
638
-
639
-		return false;
640
-	}
641
-
642
-	/**
643
-	 * Checks whether the attribute has a compute method.
644
-	 *
645
-	 * This is used to determine if the attribute should be computed
646
-	 * from other attributes.
647
-	 *
648
-	 * @param string $name
649
-	 *
650
-	 * @return false|string
651
-	 */
652
-	protected function has_compute_method( $name ) {
653
-		if ( method_exists( $this, $method = "compute_{$name}" ) ) {
654
-			return $method;
655
-		}
656
-
657
-		return false;
658
-	}
659
-
660
-	/**
661
-	 * Clears all the current attributes from the model.
662
-	 *
663
-	 * This does not touch the model's original attributes, and will
664
-	 * only clear fillable attributes, unless the model is unguarded.
665
-	 *
666
-	 * @return $this
667
-	 */
668
-	public function clear() {
669
-		$keys = array_merge(
670
-			$this->get_table_keys(),
671
-			$this->get_wp_object_keys()
672
-		);
673
-
674
-		foreach ( $keys as $key ) {
675
-			try {
676
-				$this->set_attribute( $key, null );
677
-			} catch ( GuardedPropertyException $e ) {
678
-				// We won't clear out guarded attributes.
679
-			}
680
-		}
681
-
682
-		return $this;
683
-	}
684
-
685
-	/**
686
-	 * Unguards the model.
687
-	 *
688
-	 * Sets the model to be unguarded, allowing the filling of
689
-	 * guarded attributes.
690
-	 */
691
-	public function unguard() {
692
-		$this->is_guarded = false;
693
-	}
694
-
695
-	/**
696
-	 * Reguards the model.
697
-	 *
698
-	 * Sets the model to be guarded, preventing filling of
699
-	 * guarded attributes.
700
-	 */
701
-	public function reguard() {
702
-		$this->is_guarded = true;
703
-	}
704
-
705
-	/**
706
-	 * Retrieves all the compute methods on the model.
707
-	 *
708
-	 * @return array
709
-	 */
710
-	protected function get_compute_methods() {
711
-		$methods = get_class_methods( get_called_class() );
712
-		$methods = array_filter( $methods, function ( $method ) {
713
-			return strrpos( $method, 'compute_', - strlen( $method ) ) !== false;
714
-		} );
715
-		$methods = array_map( function ( $method ) {
716
-			return substr( $method, strlen( 'compute_' ) );
717
-		}, $methods );
718
-
719
-		return $methods;
720
-	}
721
-
722
-	/**
723
-	 * Sets up the memo array for the creating model.
724
-	 */
725
-	private function maybe_boot() {
726
-		if ( ! isset( self::$memo[ get_called_class() ] ) ) {
727
-			self::$memo[ get_called_class() ] = array();
728
-		}
729
-	}
730
-
731
-	/**
732
-	 * Whether this Model uses an underlying WordPress object.
733
-	 *
734
-	 * @return bool
735
-	 */
736
-	protected function uses_wp_object() {
737
-		return $this instanceof UsesWordPressPost ||
738
-			$this instanceof UsesWordPressTerm;
739
-	}
24
+    /**
25
+     * Table attribute key.
26
+     */
27
+    const TABLE_KEY = '@@table';
28
+
29
+    /**
30
+     * Object attribute key.
31
+     */
32
+    const OBJECT_KEY = '@@object';
33
+
34
+    /**
35
+     * Memoized values for class methods.
36
+     *
37
+     * @var array
38
+     */
39
+    private static $memo = array();
40
+
41
+    /**
42
+     * Model attributes.
43
+     *
44
+     * @var array
45
+     */
46
+    private $attributes = array(
47
+        self::TABLE_KEY  => array(),
48
+        self::OBJECT_KEY => null,
49
+    );
50
+
51
+    /**
52
+     * Model's original attributes.
53
+     *
54
+     * @var array
55
+     */
56
+    private $original = array(
57
+        self::TABLE_KEY  => array(),
58
+        self::OBJECT_KEY => null,
59
+    );
60
+
61
+    /**
62
+     * Properties which are allowed to be set on the model.
63
+     *
64
+     * If this array is empty, any attributes can be set on the model.
65
+     *
66
+     * @var string[]
67
+     */
68
+    protected $fillable = array();
69
+
70
+    /**
71
+     * Properties which cannot be automatically filled on the model.
72
+     *
73
+     * If the model is unguarded, these properties can be filled.
74
+     *
75
+     * @var array
76
+     */
77
+    protected $guarded = array();
78
+
79
+    /**
80
+     * Properties which should not be serialized.
81
+     *
82
+     * @var array
83
+     */
84
+    protected $hidden = array();
85
+
86
+    /**
87
+     * Properties which should be serialized.
88
+     *
89
+     * @var array
90
+     */
91
+    protected $visible = array();
92
+
93
+    /**
94
+     * Whether the model's properties are guarded.
95
+     *
96
+     * When false, allows guarded properties to be filled.
97
+     *
98
+     * @var bool
99
+     */
100
+    protected $is_guarded = true;
101
+
102
+    /**
103
+     * Constructs a new model with provided attributes.
104
+     *
105
+     * If self::OBJECT_KEY is passed as one of the attributes, the underlying post
106
+     * will be overwritten.
107
+     *
108
+     * @param array <string, mixed> $attributes
109
+     */
110
+    public function __construct( array $attributes = array() ) {
111
+        $this->maybe_boot();
112
+        $this->sync_original();
113
+
114
+        if ( $this->uses_wp_object() ) {
115
+            $this->create_wp_object();
116
+        }
117
+
118
+        $this->unguard();
119
+        $this->refresh( $attributes );
120
+        $this->reguard();
121
+    }
122
+
123
+    /**
124
+     * Refreshes the model's current attributes with the provided array.
125
+     *
126
+     * The model's attributes will match what was provided in the array,
127
+     * and any attributes not passed
128
+     *
129
+     * @param array $attributes
130
+     *
131
+     * @return $this
132
+     */
133
+    public function refresh( array $attributes ) {
134
+        $this->clear();
135
+
136
+        return $this->merge( $attributes );
137
+    }
138
+
139
+    /**
140
+     * Merges the provided attributes with the provided array.
141
+     *
142
+     * @param array $attributes
143
+     *
144
+     * @return $this
145
+     */
146
+    public function merge( array $attributes ) {
147
+        foreach ( $attributes as $name => $value ) {
148
+            $this->set_attribute( $name, $value );
149
+        }
150
+
151
+        return $this;
152
+    }
153
+
154
+    /**
155
+     * Get the model's table attributes.
156
+     *
157
+     * Returns the array of for the model that will either need to be
158
+     * saved in postmeta or a separate table.
159
+     *
160
+     * @return array
161
+     */
162
+    public function get_table_attributes() {
163
+        return $this->attributes[ self::TABLE_KEY ];
164
+    }
165
+
166
+    /**
167
+     * Get the model's original attributes.
168
+     *
169
+     * @return array
170
+     */
171
+    public function get_original_table_attributes() {
172
+        return $this->original[ self::TABLE_KEY ];
173
+    }
174
+
175
+    /**
176
+     * Retrieve an array of the attributes on the model
177
+     * that have changed compared to the model's
178
+     * original data.
179
+     *
180
+     * @return array
181
+     */
182
+    public function get_changed_table_attributes() {
183
+        $changed = array();
184
+
185
+        foreach ( $this->get_table_attributes() as $key => $value ) {
186
+            if ( $value !==
187
+                    $this->get_original_attribute( $key )
188
+            ) {
189
+                $changed[ $key ] = $value;
190
+            }
191
+        }
192
+
193
+        return $changed;
194
+    }
195
+
196
+    /**
197
+     * Get the model's underlying post.
198
+     *
199
+     * Returns the underlying WP_Post object for the model, representing
200
+     * the data that will be save in the wp_posts table.
201
+     *
202
+     * @return false|WP_Post|WP_Term
203
+     */
204
+    public function get_underlying_wp_object() {
205
+        if ( isset( $this->attributes[ self::OBJECT_KEY ] ) ) {
206
+            return $this->attributes[ self::OBJECT_KEY ];
207
+        }
208
+
209
+        return false;
210
+    }
211
+
212
+    /**
213
+     * Get the model's original underlying post.
214
+     *
215
+     * @return WP_Post
216
+     */
217
+    public function get_original_underlying_wp_object() {
218
+        return $this->original[ self::OBJECT_KEY ];
219
+    }
220
+
221
+    /**
222
+     * Get the model attributes on the WordPress object
223
+     * that have changed compared to the model's
224
+     * original attributes.
225
+     *
226
+     * @return array
227
+     */
228
+    public function get_changed_wp_object_attributes() {
229
+        $changed = array();
230
+
231
+        foreach ( $this->get_wp_object_keys() as $key ) {
232
+            if ( $this->get_attribute( $key ) !==
233
+                    $this->get_original_attribute( $key )
234
+            ) {
235
+                $changed[ $key ] = $this->get_attribute( $key );
236
+            }
237
+        }
238
+
239
+        return $changed;
240
+    }
241
+
242
+    /**
243
+     * Magic __set method.
244
+     *
245
+     * Passes the name and value to set_attribute, which is where the magic happens.
246
+     *
247
+     * @param string $name
248
+     * @param mixed  $value
249
+     */
250
+    public function __set( $name, $value ) {
251
+        $this->set_attribute( $name, $value );
252
+    }
253
+
254
+    /**
255
+     * Sets the model attributes.
256
+     *
257
+     * Checks whether the model attribute can be set, check if it
258
+     * maps to the WP_Post property, otherwise, assigns it to the
259
+     * table attribute array.
260
+     *
261
+     * @param string $name
262
+     * @param mixed  $value
263
+     *
264
+     * @return $this
265
+     *
266
+     * @throws Exception
267
+     * @throws GuardedPropertyException
268
+     */
269
+    public function set_attribute( $name, $value ) {
270
+        if ( self::OBJECT_KEY === $name ) {
271
+            if ( ! $value ) {
272
+                throw new Exception;
273
+            }
274
+
275
+            return $this->override_wp_object( $value );
276
+        }
277
+
278
+        if ( self::TABLE_KEY === $name ) {
279
+            return $this->override_table( $value );
280
+        }
281
+
282
+        if ( ! $this->is_fillable( $name ) ) {
283
+            throw new GuardedPropertyException;
284
+        }
285
+
286
+        if ( $method = $this->has_map_method( $name ) ) {
287
+            $this->attributes[ self::OBJECT_KEY ]->{$this->{$method}()} = $value;
288
+        } else {
289
+            $this->attributes[ self::TABLE_KEY ][ $name ] = $value;
290
+        }
291
+
292
+        return $this;
293
+    }
294
+
295
+    /**
296
+     * Retrieves all the attribute keys for the model.
297
+     *
298
+     * @return array
299
+     */
300
+    public function get_attribute_keys() {
301
+        if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
302
+            return self::$memo[ get_called_class() ][ __METHOD__ ];
303
+        }
304
+
305
+        return self::$memo[ get_called_class() ][ __METHOD__ ]
306
+            = array_merge(
307
+                $this->fillable,
308
+                $this->guarded,
309
+                $this->get_compute_methods()
310
+            );
311
+    }
312
+
313
+    /**
314
+     * Retrieves the attribute keys that aren't mapped to a post.
315
+     *
316
+     * @return array
317
+     */
318
+    public function get_table_keys() {
319
+        if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
320
+            return self::$memo[ get_called_class() ][ __METHOD__ ];
321
+        }
322
+
323
+        $keys = array();
324
+
325
+        foreach ( $this->get_attribute_keys() as $key ) {
326
+            if ( ! $this->has_map_method( $key ) &&
327
+                 ! $this->has_compute_method( $key )
328
+            ) {
329
+                $keys[] = $key;
330
+            }
331
+        }
332
+
333
+        return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
334
+    }
335
+
336
+    /**
337
+     * Retrieves the attribute keys that are mapped to a post.
338
+     *
339
+     * @return array
340
+     */
341
+    public function get_wp_object_keys() {
342
+        if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
343
+            return self::$memo[ get_called_class() ][ __METHOD__ ];
344
+        }
345
+
346
+        $keys = array();
347
+
348
+        foreach ( $this->get_attribute_keys() as $key ) {
349
+            if ( $this->has_map_method( $key ) ) {
350
+                $keys[] = $key;
351
+            }
352
+        }
353
+
354
+        return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
355
+    }
356
+
357
+    /**
358
+     * Returns the model's keys that are computed at call time.
359
+     *
360
+     * @return array
361
+     */
362
+    public function get_computed_keys() {
363
+        if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
364
+            return self::$memo[ get_called_class() ][ __METHOD__ ];
365
+        }
366
+
367
+        $keys = array();
368
+
369
+        foreach ( $this->get_attribute_keys() as $key ) {
370
+            if ( $this->has_compute_method( $key ) ) {
371
+                $keys[] = $key;
372
+            }
373
+        }
374
+
375
+        return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
376
+    }
377
+
378
+    /**
379
+     * Serializes the model's public data into an array.
380
+     *
381
+     * @return array
382
+     */
383
+    public function serialize() {
384
+        $attributes = array();
385
+
386
+        if ( $this->visible ) {
387
+            // If visible attributes are set, we'll only reveal those.
388
+            foreach ( $this->visible as $key ) {
389
+                $attributes[ $key ] = $this->get_attribute( $key );
390
+            }
391
+        } elseif ( $this->hidden ) {
392
+            // If hidden attributes are set, we'll grab everything and hide those.
393
+            foreach ( $this->get_attribute_keys() as $key ) {
394
+                if ( ! in_array( $key, $this->hidden ) ) {
395
+                    $attributes[ $key ] = $this->get_attribute( $key );
396
+                }
397
+            }
398
+        } else {
399
+            // If nothing is hidden/visible, we'll grab and reveal everything.
400
+            foreach ( $this->get_attribute_keys() as $key ) {
401
+                $attributes[ $key ] = $this->get_attribute( $key );
402
+            }
403
+        }
404
+
405
+        return array_map( function ( $attribute ) {
406
+            if ( $attribute instanceof Serializes ) {
407
+                return $attribute->serialize();
408
+            }
409
+
410
+            return $attribute;
411
+        }, $attributes );
412
+    }
413
+
414
+    /**
415
+     * Syncs the current attributes to the model's original.
416
+     *
417
+     * @return $this
418
+     */
419
+    public function sync_original() {
420
+        $this->original = $this->attributes;
421
+
422
+        if ( $this->attributes[ self::OBJECT_KEY ] ) {
423
+            $this->original[ self::OBJECT_KEY ] = clone $this->attributes[ self::OBJECT_KEY ];
424
+        }
425
+
426
+        foreach ( $this->original[ self::TABLE_KEY ] as $key => $item ) {
427
+            if ( is_object( $item ) ) {
428
+                $this->original[ $key ] = clone $item;
429
+            }
430
+        }
431
+
432
+        return $this;
433
+    }
434
+
435
+    /**
436
+     * Checks if a given attribute is mass-fillable.
437
+     *
438
+     * Returns true if the attribute can be filled, false if it can't.
439
+     *
440
+     * @param string $name
441
+     *
442
+     * @return bool
443
+     */
444
+    private function is_fillable( $name ) {
445
+        // If this model isn't guarded, everything is fillable.
446
+        if ( ! $this->is_guarded ) {
447
+            return true;
448
+        }
449
+
450
+        // If it's in the fillable array, then it's fillable.
451
+        if ( in_array( $name, $this->fillable ) ) {
452
+            return true;
453
+        }
454
+
455
+        // If it's explicitly guarded, then it's not fillable.
456
+        if ( in_array( $name, $this->guarded ) ) {
457
+            return false;
458
+        }
459
+
460
+        // If fillable hasn't been defined, then everything else fillable.
461
+        return ! $this->fillable;
462
+    }
463
+
464
+    /**
465
+     * Overrides the current WordPress object with a provided one.
466
+     *
467
+     * Resets the post's default values and stores it in the attributes.
468
+     *
469
+     * @param WP_Post|WP_Term $value
470
+     *
471
+     * @return $this
472
+     */
473
+    private function override_wp_object( $value ) {
474
+        $this->attributes[ self::OBJECT_KEY ] = $this->set_wp_object_constants( $value );
475
+
476
+        return $this;
477
+    }
478
+
479
+    /**
480
+     * Overrides the current table attributes array with a provided one.
481
+     *
482
+     * @param array $value
483
+     *
484
+     * @return $this
485
+     */
486
+    private function override_table( array $value ) {
487
+        $this->attributes[ self::TABLE_KEY ] = $value;
488
+
489
+        return $this;
490
+    }
491
+
492
+    /**
493
+     * Create and set with a new blank post.
494
+     *
495
+     * Creates a new WP_Post object, assigns it the default attributes,
496
+     * and stores it in the attributes.
497
+     *
498
+     * @throws LogicException
499
+     */
500
+    private function create_wp_object() {
501
+        switch ( true ) {
502
+            case $this instanceof UsesWordPressPost:
503
+                $object = new WP_Post( (object) array() );
504
+                break;
505
+            case $this instanceof UsesWordPressTerm:
506
+                $object = new WP_Term( (object) array() );
507
+                break;
508
+            default:
509
+                throw new LogicException;
510
+                break;
511
+        }
512
+
513
+        $this->attributes[ self::OBJECT_KEY ] = $this->set_wp_object_constants( $object );
514
+    }
515
+
516
+    /**
517
+     * Enforces values on the post that can't change.
518
+     *
519
+     * Primarily, this is used to make sure the post_type always maps
520
+     * to the model's "$type" property, but this can all be overridden
521
+     * by the developer to enforce other values in the model.
522
+     *
523
+     * @param object $object
524
+     *
525
+     * @return object
526
+     */
527
+    protected function set_wp_object_constants( $object ) {
528
+        if ( $this instanceof UsesWordPressPost ) {
529
+            $object->post_type = static::get_post_type();
530
+        }
531
+
532
+        if ( $this instanceof UsesWordPressTerm ) {
533
+            $object->taxonomy = static::get_taxonomy();
534
+        }
535
+
536
+        return $object;
537
+    }
538
+
539
+    /**
540
+     * Magic __get method.
541
+     *
542
+     * Passes the name and value to get_attribute, which is where the magic happens.
543
+     *
544
+     * @param string $name
545
+     *
546
+     * @return mixed
547
+     */
548
+    public function __get( $name ) {
549
+        return $this->get_attribute( $name );
550
+    }
551
+
552
+    /**
553
+     * Retrieves the model attribute.
554
+     *
555
+     * @param string $name
556
+     *
557
+     * @return mixed
558
+     *
559
+     * @throws PropertyDoesNotExistException If property isn't found.
560
+     */
561
+    public function get_attribute( $name ) {
562
+        if ( $method = $this->has_map_method( $name ) ) {
563
+            $value = $this->attributes[ self::OBJECT_KEY ]->{$this->{$method}()};
564
+        } elseif ( $method = $this->has_compute_method( $name ) ) {
565
+            $value = $this->{$method}();
566
+        } else {
567
+            if ( ! isset( $this->attributes[ self::TABLE_KEY ][ $name ] ) ) {
568
+                throw new PropertyDoesNotExistException( $name );
569
+            }
570
+
571
+            $value = $this->attributes[ self::TABLE_KEY ][ $name ];
572
+        }
573
+
574
+        return $value;
575
+    }
576
+
577
+    /**
578
+     * Retrieve the model's original attribute value.
579
+     *
580
+     * @param string $name
581
+     *
582
+     * @return mixed
583
+     *
584
+     * @throws PropertyDoesNotExistException If property isn't found.
585
+     */
586
+    public function get_original_attribute( $name ) {
587
+        $original_attributes = $this->original;
588
+
589
+        if ( ! is_object( $original_attributes[ static::OBJECT_KEY ] ) ) {
590
+            unset( $original_attributes[ static::OBJECT_KEY ] );
591
+        }
592
+
593
+        $original = new static( $original_attributes );
594
+
595
+        try {
596
+            return $original->get_attribute( $name );
597
+        } catch ( Exception $exception ) {
598
+            return null;
599
+        }
600
+    }
601
+
602
+    /**
603
+     * Fetches the Model's primary ID, depending on the model
604
+     * implementation.
605
+     *
606
+     * @return int
607
+     *
608
+     * @throws LogicException
609
+     */
610
+    public function get_primary_id() {
611
+        if ( $this instanceof UsesWordPressPost ) {
612
+            return $this->get_underlying_wp_object()->ID;
613
+        }
614
+
615
+        if ( $this instanceof UsesWordPressTerm ) {
616
+            return $this->get_underlying_wp_object()->term_id;
617
+        }
618
+
619
+        // Model w/o wp_object not yet supported.
620
+        throw new LogicException;
621
+    }
622
+
623
+    /**
624
+     * Checks whether the attribute has a map method.
625
+     *
626
+     * This is used to determine whether the attribute maps to a
627
+     * property on the underlying WP_Post object. Returns the
628
+     * method if one exists, returns false if it doesn't.
629
+     *
630
+     * @param string $name
631
+     *
632
+     * @return false|string
633
+     */
634
+    protected function has_map_method( $name ) {
635
+        if ( method_exists( $this, $method = "map_{$name}" ) ) {
636
+            return $method;
637
+        }
638
+
639
+        return false;
640
+    }
641
+
642
+    /**
643
+     * Checks whether the attribute has a compute method.
644
+     *
645
+     * This is used to determine if the attribute should be computed
646
+     * from other attributes.
647
+     *
648
+     * @param string $name
649
+     *
650
+     * @return false|string
651
+     */
652
+    protected function has_compute_method( $name ) {
653
+        if ( method_exists( $this, $method = "compute_{$name}" ) ) {
654
+            return $method;
655
+        }
656
+
657
+        return false;
658
+    }
659
+
660
+    /**
661
+     * Clears all the current attributes from the model.
662
+     *
663
+     * This does not touch the model's original attributes, and will
664
+     * only clear fillable attributes, unless the model is unguarded.
665
+     *
666
+     * @return $this
667
+     */
668
+    public function clear() {
669
+        $keys = array_merge(
670
+            $this->get_table_keys(),
671
+            $this->get_wp_object_keys()
672
+        );
673
+
674
+        foreach ( $keys as $key ) {
675
+            try {
676
+                $this->set_attribute( $key, null );
677
+            } catch ( GuardedPropertyException $e ) {
678
+                // We won't clear out guarded attributes.
679
+            }
680
+        }
681
+
682
+        return $this;
683
+    }
684
+
685
+    /**
686
+     * Unguards the model.
687
+     *
688
+     * Sets the model to be unguarded, allowing the filling of
689
+     * guarded attributes.
690
+     */
691
+    public function unguard() {
692
+        $this->is_guarded = false;
693
+    }
694
+
695
+    /**
696
+     * Reguards the model.
697
+     *
698
+     * Sets the model to be guarded, preventing filling of
699
+     * guarded attributes.
700
+     */
701
+    public function reguard() {
702
+        $this->is_guarded = true;
703
+    }
704
+
705
+    /**
706
+     * Retrieves all the compute methods on the model.
707
+     *
708
+     * @return array
709
+     */
710
+    protected function get_compute_methods() {
711
+        $methods = get_class_methods( get_called_class() );
712
+        $methods = array_filter( $methods, function ( $method ) {
713
+            return strrpos( $method, 'compute_', - strlen( $method ) ) !== false;
714
+        } );
715
+        $methods = array_map( function ( $method ) {
716
+            return substr( $method, strlen( 'compute_' ) );
717
+        }, $methods );
718
+
719
+        return $methods;
720
+    }
721
+
722
+    /**
723
+     * Sets up the memo array for the creating model.
724
+     */
725
+    private function maybe_boot() {
726
+        if ( ! isset( self::$memo[ get_called_class() ] ) ) {
727
+            self::$memo[ get_called_class() ] = array();
728
+        }
729
+    }
730
+
731
+    /**
732
+     * Whether this Model uses an underlying WordPress object.
733
+     *
734
+     * @return bool
735
+     */
736
+    protected function uses_wp_object() {
737
+        return $this instanceof UsesWordPressPost ||
738
+            $this instanceof UsesWordPressTerm;
739
+    }
740 740
 }
Please login to merge, or discard this patch.
Spacing   +117 added lines, -117 removed lines patch added patch discarded remove patch
@@ -107,16 +107,16 @@  discard block
 block discarded – undo
107 107
 	 *
108 108
 	 * @param array <string, mixed> $attributes
109 109
 	 */
110
-	public function __construct( array $attributes = array() ) {
110
+	public function __construct(array $attributes = array()) {
111 111
 		$this->maybe_boot();
112 112
 		$this->sync_original();
113 113
 
114
-		if ( $this->uses_wp_object() ) {
114
+		if ($this->uses_wp_object()) {
115 115
 			$this->create_wp_object();
116 116
 		}
117 117
 
118 118
 		$this->unguard();
119
-		$this->refresh( $attributes );
119
+		$this->refresh($attributes);
120 120
 		$this->reguard();
121 121
 	}
122 122
 
@@ -130,10 +130,10 @@  discard block
 block discarded – undo
130 130
 	 *
131 131
 	 * @return $this
132 132
 	 */
133
-	public function refresh( array $attributes ) {
133
+	public function refresh(array $attributes) {
134 134
 		$this->clear();
135 135
 
136
-		return $this->merge( $attributes );
136
+		return $this->merge($attributes);
137 137
 	}
138 138
 
139 139
 	/**
@@ -143,9 +143,9 @@  discard block
 block discarded – undo
143 143
 	 *
144 144
 	 * @return $this
145 145
 	 */
146
-	public function merge( array $attributes ) {
147
-		foreach ( $attributes as $name => $value ) {
148
-			$this->set_attribute( $name, $value );
146
+	public function merge(array $attributes) {
147
+		foreach ($attributes as $name => $value) {
148
+			$this->set_attribute($name, $value);
149 149
 		}
150 150
 
151 151
 		return $this;
@@ -160,7 +160,7 @@  discard block
 block discarded – undo
160 160
 	 * @return array
161 161
 	 */
162 162
 	public function get_table_attributes() {
163
-		return $this->attributes[ self::TABLE_KEY ];
163
+		return $this->attributes[self::TABLE_KEY];
164 164
 	}
165 165
 
166 166
 	/**
@@ -169,7 +169,7 @@  discard block
 block discarded – undo
169 169
 	 * @return array
170 170
 	 */
171 171
 	public function get_original_table_attributes() {
172
-		return $this->original[ self::TABLE_KEY ];
172
+		return $this->original[self::TABLE_KEY];
173 173
 	}
174 174
 
175 175
 	/**
@@ -182,11 +182,11 @@  discard block
 block discarded – undo
182 182
 	public function get_changed_table_attributes() {
183 183
 		$changed = array();
184 184
 
185
-		foreach ( $this->get_table_attributes() as $key => $value ) {
186
-			if ( $value !==
187
-			     $this->get_original_attribute( $key )
185
+		foreach ($this->get_table_attributes() as $key => $value) {
186
+			if ($value !==
187
+			     $this->get_original_attribute($key)
188 188
 			) {
189
-				$changed[ $key ] = $value;
189
+				$changed[$key] = $value;
190 190
 			}
191 191
 		}
192 192
 
@@ -202,8 +202,8 @@  discard block
 block discarded – undo
202 202
 	 * @return false|WP_Post|WP_Term
203 203
 	 */
204 204
 	public function get_underlying_wp_object() {
205
-		if ( isset( $this->attributes[ self::OBJECT_KEY ] ) ) {
206
-			return $this->attributes[ self::OBJECT_KEY ];
205
+		if (isset($this->attributes[self::OBJECT_KEY])) {
206
+			return $this->attributes[self::OBJECT_KEY];
207 207
 		}
208 208
 
209 209
 		return false;
@@ -215,7 +215,7 @@  discard block
 block discarded – undo
215 215
 	 * @return WP_Post
216 216
 	 */
217 217
 	public function get_original_underlying_wp_object() {
218
-		return $this->original[ self::OBJECT_KEY ];
218
+		return $this->original[self::OBJECT_KEY];
219 219
 	}
220 220
 
221 221
 	/**
@@ -228,11 +228,11 @@  discard block
 block discarded – undo
228 228
 	public function get_changed_wp_object_attributes() {
229 229
 		$changed = array();
230 230
 
231
-		foreach ( $this->get_wp_object_keys() as $key ) {
232
-			if ( $this->get_attribute( $key ) !==
233
-			     $this->get_original_attribute( $key )
231
+		foreach ($this->get_wp_object_keys() as $key) {
232
+			if ($this->get_attribute($key) !==
233
+			     $this->get_original_attribute($key)
234 234
 			) {
235
-				$changed[ $key ] = $this->get_attribute( $key );
235
+				$changed[$key] = $this->get_attribute($key);
236 236
 			}
237 237
 		}
238 238
 
@@ -247,8 +247,8 @@  discard block
 block discarded – undo
247 247
 	 * @param string $name
248 248
 	 * @param mixed  $value
249 249
 	 */
250
-	public function __set( $name, $value ) {
251
-		$this->set_attribute( $name, $value );
250
+	public function __set($name, $value) {
251
+		$this->set_attribute($name, $value);
252 252
 	}
253 253
 
254 254
 	/**
@@ -266,27 +266,27 @@  discard block
 block discarded – undo
266 266
 	 * @throws Exception
267 267
 	 * @throws GuardedPropertyException
268 268
 	 */
269
-	public function set_attribute( $name, $value ) {
270
-		if ( self::OBJECT_KEY === $name ) {
271
-			if ( ! $value ) {
269
+	public function set_attribute($name, $value) {
270
+		if (self::OBJECT_KEY === $name) {
271
+			if (!$value) {
272 272
 				throw new Exception;
273 273
 			}
274 274
 
275
-			return $this->override_wp_object( $value );
275
+			return $this->override_wp_object($value);
276 276
 		}
277 277
 
278
-		if ( self::TABLE_KEY === $name ) {
279
-			return $this->override_table( $value );
278
+		if (self::TABLE_KEY === $name) {
279
+			return $this->override_table($value);
280 280
 		}
281 281
 
282
-		if ( ! $this->is_fillable( $name ) ) {
282
+		if (!$this->is_fillable($name)) {
283 283
 			throw new GuardedPropertyException;
284 284
 		}
285 285
 
286
-		if ( $method = $this->has_map_method( $name ) ) {
287
-			$this->attributes[ self::OBJECT_KEY ]->{$this->{$method}()} = $value;
286
+		if ($method = $this->has_map_method($name)) {
287
+			$this->attributes[self::OBJECT_KEY]->{$this->{$method}()} = $value;
288 288
 		} else {
289
-			$this->attributes[ self::TABLE_KEY ][ $name ] = $value;
289
+			$this->attributes[self::TABLE_KEY][$name] = $value;
290 290
 		}
291 291
 
292 292
 		return $this;
@@ -298,11 +298,11 @@  discard block
 block discarded – undo
298 298
 	 * @return array
299 299
 	 */
300 300
 	public function get_attribute_keys() {
301
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
302
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
301
+		if (isset(self::$memo[get_called_class()][__METHOD__])) {
302
+			return self::$memo[get_called_class()][__METHOD__];
303 303
 		}
304 304
 
305
-		return self::$memo[ get_called_class() ][ __METHOD__ ]
305
+		return self::$memo[get_called_class()][__METHOD__]
306 306
 			= array_merge(
307 307
 				$this->fillable,
308 308
 				$this->guarded,
@@ -316,21 +316,21 @@  discard block
 block discarded – undo
316 316
 	 * @return array
317 317
 	 */
318 318
 	public function get_table_keys() {
319
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
320
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
319
+		if (isset(self::$memo[get_called_class()][__METHOD__])) {
320
+			return self::$memo[get_called_class()][__METHOD__];
321 321
 		}
322 322
 
323 323
 		$keys = array();
324 324
 
325
-		foreach ( $this->get_attribute_keys() as $key ) {
326
-			if ( ! $this->has_map_method( $key ) &&
327
-			     ! $this->has_compute_method( $key )
325
+		foreach ($this->get_attribute_keys() as $key) {
326
+			if (!$this->has_map_method($key) &&
327
+			     !$this->has_compute_method($key)
328 328
 			) {
329 329
 				$keys[] = $key;
330 330
 			}
331 331
 		}
332 332
 
333
-		return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
333
+		return self::$memo[get_called_class()][__METHOD__] = $keys;
334 334
 	}
335 335
 
336 336
 	/**
@@ -339,19 +339,19 @@  discard block
 block discarded – undo
339 339
 	 * @return array
340 340
 	 */
341 341
 	public function get_wp_object_keys() {
342
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
343
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
342
+		if (isset(self::$memo[get_called_class()][__METHOD__])) {
343
+			return self::$memo[get_called_class()][__METHOD__];
344 344
 		}
345 345
 
346 346
 		$keys = array();
347 347
 
348
-		foreach ( $this->get_attribute_keys() as $key ) {
349
-			if ( $this->has_map_method( $key ) ) {
348
+		foreach ($this->get_attribute_keys() as $key) {
349
+			if ($this->has_map_method($key)) {
350 350
 				$keys[] = $key;
351 351
 			}
352 352
 		}
353 353
 
354
-		return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
354
+		return self::$memo[get_called_class()][__METHOD__] = $keys;
355 355
 	}
356 356
 
357 357
 	/**
@@ -360,19 +360,19 @@  discard block
 block discarded – undo
360 360
 	 * @return array
361 361
 	 */
362 362
 	public function get_computed_keys() {
363
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
364
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
363
+		if (isset(self::$memo[get_called_class()][__METHOD__])) {
364
+			return self::$memo[get_called_class()][__METHOD__];
365 365
 		}
366 366
 
367 367
 		$keys = array();
368 368
 
369
-		foreach ( $this->get_attribute_keys() as $key ) {
370
-			if ( $this->has_compute_method( $key ) ) {
369
+		foreach ($this->get_attribute_keys() as $key) {
370
+			if ($this->has_compute_method($key)) {
371 371
 				$keys[] = $key;
372 372
 			}
373 373
 		}
374 374
 
375
-		return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
375
+		return self::$memo[get_called_class()][__METHOD__] = $keys;
376 376
 	}
377 377
 
378 378
 	/**
@@ -383,32 +383,32 @@  discard block
 block discarded – undo
383 383
 	public function serialize() {
384 384
 		$attributes = array();
385 385
 
386
-		if ( $this->visible ) {
386
+		if ($this->visible) {
387 387
 			// If visible attributes are set, we'll only reveal those.
388
-			foreach ( $this->visible as $key ) {
389
-				$attributes[ $key ] = $this->get_attribute( $key );
388
+			foreach ($this->visible as $key) {
389
+				$attributes[$key] = $this->get_attribute($key);
390 390
 			}
391
-		} elseif ( $this->hidden ) {
391
+		} elseif ($this->hidden) {
392 392
 			// If hidden attributes are set, we'll grab everything and hide those.
393
-			foreach ( $this->get_attribute_keys() as $key ) {
394
-				if ( ! in_array( $key, $this->hidden ) ) {
395
-					$attributes[ $key ] = $this->get_attribute( $key );
393
+			foreach ($this->get_attribute_keys() as $key) {
394
+				if (!in_array($key, $this->hidden)) {
395
+					$attributes[$key] = $this->get_attribute($key);
396 396
 				}
397 397
 			}
398 398
 		} else {
399 399
 			// If nothing is hidden/visible, we'll grab and reveal everything.
400
-			foreach ( $this->get_attribute_keys() as $key ) {
401
-				$attributes[ $key ] = $this->get_attribute( $key );
400
+			foreach ($this->get_attribute_keys() as $key) {
401
+				$attributes[$key] = $this->get_attribute($key);
402 402
 			}
403 403
 		}
404 404
 
405
-		return array_map( function ( $attribute ) {
406
-			if ( $attribute instanceof Serializes ) {
405
+		return array_map(function($attribute) {
406
+			if ($attribute instanceof Serializes) {
407 407
 				return $attribute->serialize();
408 408
 			}
409 409
 
410 410
 			return $attribute;
411
-		}, $attributes );
411
+		}, $attributes);
412 412
 	}
413 413
 
414 414
 	/**
@@ -419,13 +419,13 @@  discard block
 block discarded – undo
419 419
 	public function sync_original() {
420 420
 		$this->original = $this->attributes;
421 421
 
422
-		if ( $this->attributes[ self::OBJECT_KEY ] ) {
423
-			$this->original[ self::OBJECT_KEY ] = clone $this->attributes[ self::OBJECT_KEY ];
422
+		if ($this->attributes[self::OBJECT_KEY]) {
423
+			$this->original[self::OBJECT_KEY] = clone $this->attributes[self::OBJECT_KEY];
424 424
 		}
425 425
 
426
-		foreach ( $this->original[ self::TABLE_KEY ] as $key => $item ) {
427
-			if ( is_object( $item ) ) {
428
-				$this->original[ $key ] = clone $item;
426
+		foreach ($this->original[self::TABLE_KEY] as $key => $item) {
427
+			if (is_object($item)) {
428
+				$this->original[$key] = clone $item;
429 429
 			}
430 430
 		}
431 431
 
@@ -441,24 +441,24 @@  discard block
 block discarded – undo
441 441
 	 *
442 442
 	 * @return bool
443 443
 	 */
444
-	private function is_fillable( $name ) {
444
+	private function is_fillable($name) {
445 445
 		// If this model isn't guarded, everything is fillable.
446
-		if ( ! $this->is_guarded ) {
446
+		if (!$this->is_guarded) {
447 447
 			return true;
448 448
 		}
449 449
 
450 450
 		// If it's in the fillable array, then it's fillable.
451
-		if ( in_array( $name, $this->fillable ) ) {
451
+		if (in_array($name, $this->fillable)) {
452 452
 			return true;
453 453
 		}
454 454
 
455 455
 		// If it's explicitly guarded, then it's not fillable.
456
-		if ( in_array( $name, $this->guarded ) ) {
456
+		if (in_array($name, $this->guarded)) {
457 457
 			return false;
458 458
 		}
459 459
 
460 460
 		// If fillable hasn't been defined, then everything else fillable.
461
-		return ! $this->fillable;
461
+		return !$this->fillable;
462 462
 	}
463 463
 
464 464
 	/**
@@ -470,8 +470,8 @@  discard block
 block discarded – undo
470 470
 	 *
471 471
 	 * @return $this
472 472
 	 */
473
-	private function override_wp_object( $value ) {
474
-		$this->attributes[ self::OBJECT_KEY ] = $this->set_wp_object_constants( $value );
473
+	private function override_wp_object($value) {
474
+		$this->attributes[self::OBJECT_KEY] = $this->set_wp_object_constants($value);
475 475
 
476 476
 		return $this;
477 477
 	}
@@ -483,8 +483,8 @@  discard block
 block discarded – undo
483 483
 	 *
484 484
 	 * @return $this
485 485
 	 */
486
-	private function override_table( array $value ) {
487
-		$this->attributes[ self::TABLE_KEY ] = $value;
486
+	private function override_table(array $value) {
487
+		$this->attributes[self::TABLE_KEY] = $value;
488 488
 
489 489
 		return $this;
490 490
 	}
@@ -498,19 +498,19 @@  discard block
 block discarded – undo
498 498
 	 * @throws LogicException
499 499
 	 */
500 500
 	private function create_wp_object() {
501
-		switch ( true ) {
501
+		switch (true) {
502 502
 			case $this instanceof UsesWordPressPost:
503
-				$object = new WP_Post( (object) array() );
503
+				$object = new WP_Post((object) array());
504 504
 				break;
505 505
 			case $this instanceof UsesWordPressTerm:
506
-				$object = new WP_Term( (object) array() );
506
+				$object = new WP_Term((object) array());
507 507
 				break;
508 508
 			default:
509 509
 				throw new LogicException;
510 510
 				break;
511 511
 		}
512 512
 
513
-		$this->attributes[ self::OBJECT_KEY ] = $this->set_wp_object_constants( $object );
513
+		$this->attributes[self::OBJECT_KEY] = $this->set_wp_object_constants($object);
514 514
 	}
515 515
 
516 516
 	/**
@@ -524,12 +524,12 @@  discard block
 block discarded – undo
524 524
 	 *
525 525
 	 * @return object
526 526
 	 */
527
-	protected function set_wp_object_constants( $object ) {
528
-		if ( $this instanceof UsesWordPressPost ) {
527
+	protected function set_wp_object_constants($object) {
528
+		if ($this instanceof UsesWordPressPost) {
529 529
 			$object->post_type = static::get_post_type();
530 530
 		}
531 531
 
532
-		if ( $this instanceof UsesWordPressTerm ) {
532
+		if ($this instanceof UsesWordPressTerm) {
533 533
 			$object->taxonomy = static::get_taxonomy();
534 534
 		}
535 535
 
@@ -545,8 +545,8 @@  discard block
 block discarded – undo
545 545
 	 *
546 546
 	 * @return mixed
547 547
 	 */
548
-	public function __get( $name ) {
549
-		return $this->get_attribute( $name );
548
+	public function __get($name) {
549
+		return $this->get_attribute($name);
550 550
 	}
551 551
 
552 552
 	/**
@@ -558,17 +558,17 @@  discard block
 block discarded – undo
558 558
 	 *
559 559
 	 * @throws PropertyDoesNotExistException If property isn't found.
560 560
 	 */
561
-	public function get_attribute( $name ) {
562
-		if ( $method = $this->has_map_method( $name ) ) {
563
-			$value = $this->attributes[ self::OBJECT_KEY ]->{$this->{$method}()};
564
-		} elseif ( $method = $this->has_compute_method( $name ) ) {
561
+	public function get_attribute($name) {
562
+		if ($method = $this->has_map_method($name)) {
563
+			$value = $this->attributes[self::OBJECT_KEY]->{$this->{$method}()};
564
+		} elseif ($method = $this->has_compute_method($name)) {
565 565
 			$value = $this->{$method}();
566 566
 		} else {
567
-			if ( ! isset( $this->attributes[ self::TABLE_KEY ][ $name ] ) ) {
568
-				throw new PropertyDoesNotExistException( $name );
567
+			if (!isset($this->attributes[self::TABLE_KEY][$name])) {
568
+				throw new PropertyDoesNotExistException($name);
569 569
 			}
570 570
 
571
-			$value = $this->attributes[ self::TABLE_KEY ][ $name ];
571
+			$value = $this->attributes[self::TABLE_KEY][$name];
572 572
 		}
573 573
 
574 574
 		return $value;
@@ -583,18 +583,18 @@  discard block
 block discarded – undo
583 583
 	 *
584 584
 	 * @throws PropertyDoesNotExistException If property isn't found.
585 585
 	 */
586
-	public function get_original_attribute( $name ) {
586
+	public function get_original_attribute($name) {
587 587
 		$original_attributes = $this->original;
588 588
 
589
-		if ( ! is_object( $original_attributes[ static::OBJECT_KEY ] ) ) {
590
-			unset( $original_attributes[ static::OBJECT_KEY ] );
589
+		if (!is_object($original_attributes[static::OBJECT_KEY])) {
590
+			unset($original_attributes[static::OBJECT_KEY]);
591 591
 		}
592 592
 
593
-		$original = new static( $original_attributes );
593
+		$original = new static($original_attributes);
594 594
 
595 595
 		try {
596
-			return $original->get_attribute( $name );
597
-		} catch ( Exception $exception ) {
596
+			return $original->get_attribute($name);
597
+		} catch (Exception $exception) {
598 598
 			return null;
599 599
 		}
600 600
 	}
@@ -608,11 +608,11 @@  discard block
 block discarded – undo
608 608
 	 * @throws LogicException
609 609
 	 */
610 610
 	public function get_primary_id() {
611
-		if ( $this instanceof UsesWordPressPost ) {
611
+		if ($this instanceof UsesWordPressPost) {
612 612
 			return $this->get_underlying_wp_object()->ID;
613 613
 		}
614 614
 
615
-		if ( $this instanceof UsesWordPressTerm ) {
615
+		if ($this instanceof UsesWordPressTerm) {
616 616
 			return $this->get_underlying_wp_object()->term_id;
617 617
 		}
618 618
 
@@ -631,8 +631,8 @@  discard block
 block discarded – undo
631 631
 	 *
632 632
 	 * @return false|string
633 633
 	 */
634
-	protected function has_map_method( $name ) {
635
-		if ( method_exists( $this, $method = "map_{$name}" ) ) {
634
+	protected function has_map_method($name) {
635
+		if (method_exists($this, $method = "map_{$name}")) {
636 636
 			return $method;
637 637
 		}
638 638
 
@@ -649,8 +649,8 @@  discard block
 block discarded – undo
649 649
 	 *
650 650
 	 * @return false|string
651 651
 	 */
652
-	protected function has_compute_method( $name ) {
653
-		if ( method_exists( $this, $method = "compute_{$name}" ) ) {
652
+	protected function has_compute_method($name) {
653
+		if (method_exists($this, $method = "compute_{$name}")) {
654 654
 			return $method;
655 655
 		}
656 656
 
@@ -671,10 +671,10 @@  discard block
 block discarded – undo
671 671
 			$this->get_wp_object_keys()
672 672
 		);
673 673
 
674
-		foreach ( $keys as $key ) {
674
+		foreach ($keys as $key) {
675 675
 			try {
676
-				$this->set_attribute( $key, null );
677
-			} catch ( GuardedPropertyException $e ) {
676
+				$this->set_attribute($key, null);
677
+			} catch (GuardedPropertyException $e) {
678 678
 				// We won't clear out guarded attributes.
679 679
 			}
680 680
 		}
@@ -708,13 +708,13 @@  discard block
 block discarded – undo
708 708
 	 * @return array
709 709
 	 */
710 710
 	protected function get_compute_methods() {
711
-		$methods = get_class_methods( get_called_class() );
712
-		$methods = array_filter( $methods, function ( $method ) {
713
-			return strrpos( $method, 'compute_', - strlen( $method ) ) !== false;
711
+		$methods = get_class_methods(get_called_class());
712
+		$methods = array_filter($methods, function($method) {
713
+			return strrpos($method, 'compute_', - strlen($method)) !== false;
714 714
 		} );
715
-		$methods = array_map( function ( $method ) {
716
-			return substr( $method, strlen( 'compute_' ) );
717
-		}, $methods );
715
+		$methods = array_map(function($method) {
716
+			return substr($method, strlen('compute_'));
717
+		}, $methods);
718 718
 
719 719
 		return $methods;
720 720
 	}
@@ -723,8 +723,8 @@  discard block
 block discarded – undo
723 723
 	 * Sets up the memo array for the creating model.
724 724
 	 */
725 725
 	private function maybe_boot() {
726
-		if ( ! isset( self::$memo[ get_called_class() ] ) ) {
727
-			self::$memo[ get_called_class() ] = array();
726
+		if (!isset(self::$memo[get_called_class()])) {
727
+			self::$memo[get_called_class()] = array();
728 728
 		}
729 729
 	}
730 730
 
Please login to merge, or discard this patch.
src/Axolotl/Collection.php 2 patches
Indentation   +202 added lines, -202 removed lines patch added patch discarded remove patch
@@ -14,206 +14,206 @@
 block discarded – undo
14 14
  * @subpackage Axolotl
15 15
  */
16 16
 class Collection implements Countable, Iterator, Serializes {
17
-	/**
18
-	 * Collection elements.
19
-	 *
20
-	 * @var array
21
-	 */
22
-	protected $elements = array();
23
-
24
-	/**
25
-	 * Collection configuration.
26
-	 *
27
-	 * @var array
28
-	 */
29
-	protected $config = array();
30
-
31
-	/**
32
-	 * Models registered to the collection.
33
-	 *
34
-	 * @var string
35
-	 */
36
-	protected $model;
37
-
38
-	/**
39
-	 * Where Collection is in loop.
40
-	 *
41
-	 * @var int
42
-	 */
43
-	protected $position = 0;
44
-
45
-	/**
46
-	 * Collection constructor.
47
-	 *
48
-	 * @param array $elements
49
-	 * @param array $config
50
-	 */
51
-	public function __construct( array $elements = array(), array $config = array() ) {
52
-		$this->parse_config( $this->config = $config );
53
-
54
-		foreach ( $elements as $element ) {
55
-			$this->add( $element );
56
-		}
57
-	}
58
-
59
-	/**
60
-	 * Adds a new element to the Collection.
61
-	 *
62
-	 * @param mixed $element
63
-	 *
64
-	 * @throws RuntimeException
65
-	 */
66
-	public function add( $element ) {
67
-		if ( $this->model && is_array( $element ) ) {
68
-			$element = new $this->model( $element );
69
-		}
70
-
71
-		if ( $this->model && ! ( $element instanceof $this->model ) ) {
72
-			throw new RuntimeException;
73
-		}
74
-
75
-		$this->elements[] = $element;
76
-	}
77
-
78
-	/**
79
-	 * Removes an element by index or value.
80
-	 *
81
-	 * @param mixed $index
82
-	 *
83
-	 * @return $this
84
-	 */
85
-	public function remove( $index ) {
86
-		if ( ! is_string( $index ) || ! is_numeric( $index ) || ! isset( $this->elements[ $index ] ) ) {
87
-			foreach ( $this->elements as $key => $element ) {
88
-				if ( $element === $index ) {
89
-					$index = $key;
90
-					break;
91
-				}
92
-			}
93
-		}
94
-
95
-		if ( isset( $this->elements[ $index ] ) ) {
96
-			unset( $this->elements[ $index ] );
97
-			$this->elements = array_values( $this->elements );
98
-		}
99
-
100
-		return $this;
101
-	}
102
-
103
-	/**
104
-	 * Fetches the element at the provided index.
105
-	 *
106
-	 * @param int $index
107
-	 *
108
-	 * @return mixed
109
-	 */
110
-	public function at( $index ) {
111
-		return isset( $this->elements[ $index ] ) ? $this->elements[ $index ] : null;
112
-	}
113
-
114
-	/**
115
-	 * Maps over the Collection's elements,
116
-	 *
117
-	 * @param callable $callback
118
-	 *
119
-	 * @return Collection
120
-	 */
121
-	protected function map( callable $callback ) {
122
-		return new Collection( array_map( $callback, $this->elements ), $this->config );
123
-	}
124
-
125
-	/**
126
-	 * Filters the Collection's elements.
127
-	 *
128
-	 * @param callable $callback
129
-	 *
130
-	 * @return Collection
131
-	 */
132
-	public function filter( callable $callback ) {
133
-		return new Collection( array_filter( $this->elements, $callback ) );
134
-	}
135
-
136
-	/**
137
-	 * {@inheritDoc}
138
-	 *
139
-	 * @return array
140
-	 */
141
-	public function serialize() {
142
-		return array_map(function( $element ) {
143
-			if ( $element instanceof Serializes ) {
144
-				return $element->serialize();
145
-			}
146
-
147
-			return $element;
148
-		}, $this->elements);
149
-	}
150
-
151
-	/**
152
-	 * Return the current element.
153
-	 *
154
-	 * @return mixed
155
-	 */
156
-	public function current() {
157
-		return $this->at( $this->position );
158
-	}
159
-
160
-	/**
161
-	 * Move forward to next element.
162
-	 */
163
-	public function next() {
164
-		$this->position ++;
165
-	}
166
-
167
-	/**
168
-	 * Return the key of the current element.
169
-	 *
170
-	 * @return mixed
171
-	 */
172
-	public function key() {
173
-		return $this->position;
174
-	}
175
-
176
-	/**
177
-	 * Checks if current position is valid.
178
-	 *
179
-	 * @return bool
180
-	 */
181
-	public function valid() {
182
-		return isset( $this->elements[ $this->position ] );
183
-	}
184
-
185
-	/**
186
-	 * Rewind the Iterator to the first element.
187
-	 */
188
-	public function rewind() {
189
-		$this->position = 0;
190
-	}
191
-
192
-	/**
193
-	 * Count elements of an object.
194
-	 *
195
-	 * @return int
196
-	 */
197
-	public function count() {
198
-		return count( $this->elements );
199
-	}
200
-
201
-	/**
202
-	 * Parses the Collection config to set its properties.
203
-	 *
204
-	 * @param array $config
205
-	 *
206
-	 * @throws LogicException
207
-	 */
208
-	protected function parse_config( array $config ) {
209
-		if ( isset( $config['model'] ) ) {
210
-			$model = $config['model'];
211
-
212
-			if ( ! is_subclass_of( $model, 'Intraxia\Jaxion\Axolotl\Model' ) ) {
213
-				throw new LogicException;
214
-			}
215
-
216
-			$this->model = $model;
217
-		}
218
-	}
17
+    /**
18
+     * Collection elements.
19
+     *
20
+     * @var array
21
+     */
22
+    protected $elements = array();
23
+
24
+    /**
25
+     * Collection configuration.
26
+     *
27
+     * @var array
28
+     */
29
+    protected $config = array();
30
+
31
+    /**
32
+     * Models registered to the collection.
33
+     *
34
+     * @var string
35
+     */
36
+    protected $model;
37
+
38
+    /**
39
+     * Where Collection is in loop.
40
+     *
41
+     * @var int
42
+     */
43
+    protected $position = 0;
44
+
45
+    /**
46
+     * Collection constructor.
47
+     *
48
+     * @param array $elements
49
+     * @param array $config
50
+     */
51
+    public function __construct( array $elements = array(), array $config = array() ) {
52
+        $this->parse_config( $this->config = $config );
53
+
54
+        foreach ( $elements as $element ) {
55
+            $this->add( $element );
56
+        }
57
+    }
58
+
59
+    /**
60
+     * Adds a new element to the Collection.
61
+     *
62
+     * @param mixed $element
63
+     *
64
+     * @throws RuntimeException
65
+     */
66
+    public function add( $element ) {
67
+        if ( $this->model && is_array( $element ) ) {
68
+            $element = new $this->model( $element );
69
+        }
70
+
71
+        if ( $this->model && ! ( $element instanceof $this->model ) ) {
72
+            throw new RuntimeException;
73
+        }
74
+
75
+        $this->elements[] = $element;
76
+    }
77
+
78
+    /**
79
+     * Removes an element by index or value.
80
+     *
81
+     * @param mixed $index
82
+     *
83
+     * @return $this
84
+     */
85
+    public function remove( $index ) {
86
+        if ( ! is_string( $index ) || ! is_numeric( $index ) || ! isset( $this->elements[ $index ] ) ) {
87
+            foreach ( $this->elements as $key => $element ) {
88
+                if ( $element === $index ) {
89
+                    $index = $key;
90
+                    break;
91
+                }
92
+            }
93
+        }
94
+
95
+        if ( isset( $this->elements[ $index ] ) ) {
96
+            unset( $this->elements[ $index ] );
97
+            $this->elements = array_values( $this->elements );
98
+        }
99
+
100
+        return $this;
101
+    }
102
+
103
+    /**
104
+     * Fetches the element at the provided index.
105
+     *
106
+     * @param int $index
107
+     *
108
+     * @return mixed
109
+     */
110
+    public function at( $index ) {
111
+        return isset( $this->elements[ $index ] ) ? $this->elements[ $index ] : null;
112
+    }
113
+
114
+    /**
115
+     * Maps over the Collection's elements,
116
+     *
117
+     * @param callable $callback
118
+     *
119
+     * @return Collection
120
+     */
121
+    protected function map( callable $callback ) {
122
+        return new Collection( array_map( $callback, $this->elements ), $this->config );
123
+    }
124
+
125
+    /**
126
+     * Filters the Collection's elements.
127
+     *
128
+     * @param callable $callback
129
+     *
130
+     * @return Collection
131
+     */
132
+    public function filter( callable $callback ) {
133
+        return new Collection( array_filter( $this->elements, $callback ) );
134
+    }
135
+
136
+    /**
137
+     * {@inheritDoc}
138
+     *
139
+     * @return array
140
+     */
141
+    public function serialize() {
142
+        return array_map(function( $element ) {
143
+            if ( $element instanceof Serializes ) {
144
+                return $element->serialize();
145
+            }
146
+
147
+            return $element;
148
+        }, $this->elements);
149
+    }
150
+
151
+    /**
152
+     * Return the current element.
153
+     *
154
+     * @return mixed
155
+     */
156
+    public function current() {
157
+        return $this->at( $this->position );
158
+    }
159
+
160
+    /**
161
+     * Move forward to next element.
162
+     */
163
+    public function next() {
164
+        $this->position ++;
165
+    }
166
+
167
+    /**
168
+     * Return the key of the current element.
169
+     *
170
+     * @return mixed
171
+     */
172
+    public function key() {
173
+        return $this->position;
174
+    }
175
+
176
+    /**
177
+     * Checks if current position is valid.
178
+     *
179
+     * @return bool
180
+     */
181
+    public function valid() {
182
+        return isset( $this->elements[ $this->position ] );
183
+    }
184
+
185
+    /**
186
+     * Rewind the Iterator to the first element.
187
+     */
188
+    public function rewind() {
189
+        $this->position = 0;
190
+    }
191
+
192
+    /**
193
+     * Count elements of an object.
194
+     *
195
+     * @return int
196
+     */
197
+    public function count() {
198
+        return count( $this->elements );
199
+    }
200
+
201
+    /**
202
+     * Parses the Collection config to set its properties.
203
+     *
204
+     * @param array $config
205
+     *
206
+     * @throws LogicException
207
+     */
208
+    protected function parse_config( array $config ) {
209
+        if ( isset( $config['model'] ) ) {
210
+            $model = $config['model'];
211
+
212
+            if ( ! is_subclass_of( $model, 'Intraxia\Jaxion\Axolotl\Model' ) ) {
213
+                throw new LogicException;
214
+            }
215
+
216
+            $this->model = $model;
217
+        }
218
+    }
219 219
 }
Please login to merge, or discard this patch.
Spacing   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -48,11 +48,11 @@  discard block
 block discarded – undo
48 48
 	 * @param array $elements
49 49
 	 * @param array $config
50 50
 	 */
51
-	public function __construct( array $elements = array(), array $config = array() ) {
52
-		$this->parse_config( $this->config = $config );
51
+	public function __construct(array $elements = array(), array $config = array()) {
52
+		$this->parse_config($this->config = $config);
53 53
 
54
-		foreach ( $elements as $element ) {
55
-			$this->add( $element );
54
+		foreach ($elements as $element) {
55
+			$this->add($element);
56 56
 		}
57 57
 	}
58 58
 
@@ -63,12 +63,12 @@  discard block
 block discarded – undo
63 63
 	 *
64 64
 	 * @throws RuntimeException
65 65
 	 */
66
-	public function add( $element ) {
67
-		if ( $this->model && is_array( $element ) ) {
68
-			$element = new $this->model( $element );
66
+	public function add($element) {
67
+		if ($this->model && is_array($element)) {
68
+			$element = new $this->model($element);
69 69
 		}
70 70
 
71
-		if ( $this->model && ! ( $element instanceof $this->model ) ) {
71
+		if ($this->model && !($element instanceof $this->model)) {
72 72
 			throw new RuntimeException;
73 73
 		}
74 74
 
@@ -82,19 +82,19 @@  discard block
 block discarded – undo
82 82
 	 *
83 83
 	 * @return $this
84 84
 	 */
85
-	public function remove( $index ) {
86
-		if ( ! is_string( $index ) || ! is_numeric( $index ) || ! isset( $this->elements[ $index ] ) ) {
87
-			foreach ( $this->elements as $key => $element ) {
88
-				if ( $element === $index ) {
85
+	public function remove($index) {
86
+		if (!is_string($index) || !is_numeric($index) || !isset($this->elements[$index])) {
87
+			foreach ($this->elements as $key => $element) {
88
+				if ($element === $index) {
89 89
 					$index = $key;
90 90
 					break;
91 91
 				}
92 92
 			}
93 93
 		}
94 94
 
95
-		if ( isset( $this->elements[ $index ] ) ) {
96
-			unset( $this->elements[ $index ] );
97
-			$this->elements = array_values( $this->elements );
95
+		if (isset($this->elements[$index])) {
96
+			unset($this->elements[$index]);
97
+			$this->elements = array_values($this->elements);
98 98
 		}
99 99
 
100 100
 		return $this;
@@ -107,8 +107,8 @@  discard block
 block discarded – undo
107 107
 	 *
108 108
 	 * @return mixed
109 109
 	 */
110
-	public function at( $index ) {
111
-		return isset( $this->elements[ $index ] ) ? $this->elements[ $index ] : null;
110
+	public function at($index) {
111
+		return isset($this->elements[$index]) ? $this->elements[$index] : null;
112 112
 	}
113 113
 
114 114
 	/**
@@ -118,8 +118,8 @@  discard block
 block discarded – undo
118 118
 	 *
119 119
 	 * @return Collection
120 120
 	 */
121
-	protected function map( callable $callback ) {
122
-		return new Collection( array_map( $callback, $this->elements ), $this->config );
121
+	protected function map(callable $callback) {
122
+		return new Collection(array_map($callback, $this->elements), $this->config);
123 123
 	}
124 124
 
125 125
 	/**
@@ -129,8 +129,8 @@  discard block
 block discarded – undo
129 129
 	 *
130 130
 	 * @return Collection
131 131
 	 */
132
-	public function filter( callable $callback ) {
133
-		return new Collection( array_filter( $this->elements, $callback ) );
132
+	public function filter(callable $callback) {
133
+		return new Collection(array_filter($this->elements, $callback));
134 134
 	}
135 135
 
136 136
 	/**
@@ -139,8 +139,8 @@  discard block
 block discarded – undo
139 139
 	 * @return array
140 140
 	 */
141 141
 	public function serialize() {
142
-		return array_map(function( $element ) {
143
-			if ( $element instanceof Serializes ) {
142
+		return array_map(function($element) {
143
+			if ($element instanceof Serializes) {
144 144
 				return $element->serialize();
145 145
 			}
146 146
 
@@ -154,14 +154,14 @@  discard block
 block discarded – undo
154 154
 	 * @return mixed
155 155
 	 */
156 156
 	public function current() {
157
-		return $this->at( $this->position );
157
+		return $this->at($this->position);
158 158
 	}
159 159
 
160 160
 	/**
161 161
 	 * Move forward to next element.
162 162
 	 */
163 163
 	public function next() {
164
-		$this->position ++;
164
+		$this->position++;
165 165
 	}
166 166
 
167 167
 	/**
@@ -179,7 +179,7 @@  discard block
 block discarded – undo
179 179
 	 * @return bool
180 180
 	 */
181 181
 	public function valid() {
182
-		return isset( $this->elements[ $this->position ] );
182
+		return isset($this->elements[$this->position]);
183 183
 	}
184 184
 
185 185
 	/**
@@ -195,7 +195,7 @@  discard block
 block discarded – undo
195 195
 	 * @return int
196 196
 	 */
197 197
 	public function count() {
198
-		return count( $this->elements );
198
+		return count($this->elements);
199 199
 	}
200 200
 
201 201
 	/**
@@ -205,11 +205,11 @@  discard block
 block discarded – undo
205 205
 	 *
206 206
 	 * @throws LogicException
207 207
 	 */
208
-	protected function parse_config( array $config ) {
209
-		if ( isset( $config['model'] ) ) {
208
+	protected function parse_config(array $config) {
209
+		if (isset($config['model'])) {
210 210
 			$model = $config['model'];
211 211
 
212
-			if ( ! is_subclass_of( $model, 'Intraxia\Jaxion\Axolotl\Model' ) ) {
212
+			if (!is_subclass_of($model, 'Intraxia\Jaxion\Axolotl\Model')) {
213 213
 				throw new LogicException;
214 214
 			}
215 215
 
Please login to merge, or discard this patch.