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