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