Completed
Pull Request — master (#3)
by James
03:03
created
src/Contract/Core/Container.php 2 patches
Indentation   +66 added lines, -66 removed lines patch added patch discarded remove patch
@@ -2,75 +2,75 @@
 block discarded – undo
2 2
 namespace Intraxia\Jaxion\Contract\Core;
3 3
 
4 4
 interface Container extends \ArrayAccess, \Iterator {
5
-	/**
6
-	 * Define a new service or value on the Container.
7
-	 *
8
-	 * The alias is the name that the value will be referenced by. This can be used by both
9
-	 * the `get` method to retrieve the value or through ArrayAccess (`$container['alias']`).
10
-	 * It should be a short name used to reference the defined value. The definition can be
11
-	 * any scalar value to assign to the alias, or it can define a service object to return.
12
-	 * This can be accomplished by passing in a closure, which takes the container and returns
13
-	 * a fully constructed object. This closure will be executed every time the class is fetched.
14
-	 * If an already-instantiated object is passed in, it will be returned when fetched. A
15
-	 * Definition object will be returned for additional manipulation. Scalar values will be
16
-	 * locked automatically and can't be overridden.
17
-	 *
18
-	 * @param string|array $alias
19
-	 * @param mixed        $definition
20
-	 *
21
-	 * @return $this
22
-	 */
23
-	public function define( $alias, $definition );
5
+    /**
6
+     * Define a new service or value on the Container.
7
+     *
8
+     * The alias is the name that the value will be referenced by. This can be used by both
9
+     * the `get` method to retrieve the value or through ArrayAccess (`$container['alias']`).
10
+     * It should be a short name used to reference the defined value. The definition can be
11
+     * any scalar value to assign to the alias, or it can define a service object to return.
12
+     * This can be accomplished by passing in a closure, which takes the container and returns
13
+     * a fully constructed object. This closure will be executed every time the class is fetched.
14
+     * If an already-instantiated object is passed in, it will be returned when fetched. A
15
+     * Definition object will be returned for additional manipulation. Scalar values will be
16
+     * locked automatically and can't be overridden.
17
+     *
18
+     * @param string|array $alias
19
+     * @param mixed        $definition
20
+     *
21
+     * @return $this
22
+     */
23
+    public function define( $alias, $definition );
24 24
 
25
-	/**
26
-	 * Defines a new singleton on the Container.
27
-	 *
28
-	 * Functions identically to Container::define, except closures passed in are only executed
29
-	 * once, and the return value is reused across multiple fetches.
30
-	 *
31
-	 * @param string|array $alias
32
-	 * @param mixed        $definition
33
-	 *
34
-	 * @return $this
35
-	 */
36
-	public function share( $alias, $definition );
25
+    /**
26
+     * Defines a new singleton on the Container.
27
+     *
28
+     * Functions identically to Container::define, except closures passed in are only executed
29
+     * once, and the return value is reused across multiple fetches.
30
+     *
31
+     * @param string|array $alias
32
+     * @param mixed        $definition
33
+     *
34
+     * @return $this
35
+     */
36
+    public function share( $alias, $definition );
37 37
 
38
-	/**
39
-	 * Fetches the value for the provided alias.
40
-	 *
41
-	 * @param string $alias
42
-	 *
43
-	 * @return mixed
44
-	 */
45
-	public function fetch( $alias );
38
+    /**
39
+     * Fetches the value for the provided alias.
40
+     *
41
+     * @param string $alias
42
+     *
43
+     * @return mixed
44
+     */
45
+    public function fetch( $alias );
46 46
 
47
-	/**
48
-	 * Checks whether the provided alias exists on the container.
49
-	 *
50
-	 * @param string $alias
51
-	 *
52
-	 * @return bool
53
-	 */
54
-	public function has( $alias );
47
+    /**
48
+     * Checks whether the provided alias exists on the container.
49
+     *
50
+     * @param string $alias
51
+     *
52
+     * @return bool
53
+     */
54
+    public function has( $alias );
55 55
 
56
-	/**
57
-	 * Removes the provided alias from the container.
58
-	 *
59
-	 * @param string $alias
60
-	 *
61
-	 * @return bool
62
-	 */
63
-	public function remove( $alias );
56
+    /**
57
+     * Removes the provided alias from the container.
58
+     *
59
+     * @param string $alias
60
+     *
61
+     * @return bool
62
+     */
63
+    public function remove( $alias );
64 64
 
65
-	/**
66
-	 * Registers a service provider with the container.
67
-	 *
68
-	 * A service provider is responsible for defining and generating services that will be bound
69
-	 * into the container. This keeps the container and Application responsible solely for maintaining
70
-	 * the generated services and the API for registering them and allows for a clean interface for
71
-	 * adding new services to the container.
72
-	 *
73
-	 * @param ServiceProvider $provider
74
-	 */
75
-	public function register( ServiceProvider $provider );
65
+    /**
66
+     * Registers a service provider with the container.
67
+     *
68
+     * A service provider is responsible for defining and generating services that will be bound
69
+     * into the container. This keeps the container and Application responsible solely for maintaining
70
+     * the generated services and the API for registering them and allows for a clean interface for
71
+     * adding new services to the container.
72
+     *
73
+     * @param ServiceProvider $provider
74
+     */
75
+    public function register( ServiceProvider $provider );
76 76
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -20,7 +20,7 @@  discard block
 block discarded – undo
20 20
 	 *
21 21
 	 * @return $this
22 22
 	 */
23
-	public function define( $alias, $definition );
23
+	public function define($alias, $definition);
24 24
 
25 25
 	/**
26 26
 	 * Defines a new singleton on the Container.
@@ -33,7 +33,7 @@  discard block
 block discarded – undo
33 33
 	 *
34 34
 	 * @return $this
35 35
 	 */
36
-	public function share( $alias, $definition );
36
+	public function share($alias, $definition);
37 37
 
38 38
 	/**
39 39
 	 * Fetches the value for the provided alias.
@@ -42,7 +42,7 @@  discard block
 block discarded – undo
42 42
 	 *
43 43
 	 * @return mixed
44 44
 	 */
45
-	public function fetch( $alias );
45
+	public function fetch($alias);
46 46
 
47 47
 	/**
48 48
 	 * Checks whether the provided alias exists on the container.
@@ -51,7 +51,7 @@  discard block
 block discarded – undo
51 51
 	 *
52 52
 	 * @return bool
53 53
 	 */
54
-	public function has( $alias );
54
+	public function has($alias);
55 55
 
56 56
 	/**
57 57
 	 * Removes the provided alias from the container.
@@ -60,7 +60,7 @@  discard block
 block discarded – undo
60 60
 	 *
61 61
 	 * @return bool
62 62
 	 */
63
-	public function remove( $alias );
63
+	public function remove($alias);
64 64
 
65 65
 	/**
66 66
 	 * Registers a service provider with the container.
@@ -72,5 +72,5 @@  discard block
 block discarded – undo
72 72
 	 *
73 73
 	 * @param ServiceProvider $provider
74 74
 	 */
75
-	public function register( ServiceProvider $provider );
75
+	public function register(ServiceProvider $provider);
76 76
 }
Please login to merge, or discard this patch.
src/Contract/Assets/Register.php 2 patches
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -13,21 +13,21 @@
 block discarded – undo
13 13
 	 *
14 14
 	 * @param bool $debug
15 15
 	 */
16
-	public function set_debug( $debug );
16
+	public function set_debug($debug);
17 17
 
18 18
 	/**
19 19
 	 * Provides a method to register new scripts outside of the constructor.
20 20
 	 *
21 21
 	 * @param $script
22 22
 	 */
23
-	public function register_script( $script );
23
+	public function register_script($script);
24 24
 
25 25
 	/**
26 26
 	 * Provides a method to register new styles outside of the constructor.
27 27
 	 *
28 28
 	 * @param $style
29 29
 	 */
30
-	public function register_style( $style );
30
+	public function register_style($style);
31 31
 
32 32
 	/**
33 33
 	 * Enqueues the web & shared scripts on the Register.
Please login to merge, or discard this patch.
Indentation   +44 added lines, -44 removed lines patch added patch discarded remove patch
@@ -4,48 +4,48 @@
 block discarded – undo
4 4
 use Intraxia\Jaxion\Contract\Core\HasActions;
5 5
 
6 6
 interface Register extends HasActions {
7
-	/**
8
-	 * Enable debug mode for the enqueued assets.
9
-	 *
10
-	 * Debug mode will enqueue unminified versions of the registered assets.
11
-	 * Primarily, this is intended to be used along with WordPress's `SCRIPT_DEBUG`
12
-	 * constant, which enables unminified core assets to be enqueued.
13
-	 *
14
-	 * @param bool $debug
15
-	 */
16
-	public function set_debug( $debug );
17
-
18
-	/**
19
-	 * Provides a method to register new scripts outside of the constructor.
20
-	 *
21
-	 * @param array $script
22
-	 */
23
-	public function register_script( $script );
24
-
25
-	/**
26
-	 * Provides a method to register new styles outside of the constructor.
27
-	 *
28
-	 * @param array $style
29
-	 */
30
-	public function register_style( $style );
31
-
32
-	/**
33
-	 * Enqueues the web & shared scripts on the Register.
34
-	 */
35
-	public function enqueue_web_scripts();
36
-
37
-	/**
38
-	 * Enqueues the web & shared styles on the Register.
39
-	 */
40
-	public function enqueue_web_styles();
41
-
42
-	/**
43
-	 * Enqueues the admin & shared scripts on the Register.
44
-	 */
45
-	public function enqueue_admin_scripts();
46
-
47
-	/**
48
-	 * Enqueues the admin & shared styles on the Register.
49
-	 */
50
-	public function enqueue_admin_styles();
7
+    /**
8
+     * Enable debug mode for the enqueued assets.
9
+     *
10
+     * Debug mode will enqueue unminified versions of the registered assets.
11
+     * Primarily, this is intended to be used along with WordPress's `SCRIPT_DEBUG`
12
+     * constant, which enables unminified core assets to be enqueued.
13
+     *
14
+     * @param bool $debug
15
+     */
16
+    public function set_debug( $debug );
17
+
18
+    /**
19
+     * Provides a method to register new scripts outside of the constructor.
20
+     *
21
+     * @param array $script
22
+     */
23
+    public function register_script( $script );
24
+
25
+    /**
26
+     * Provides a method to register new styles outside of the constructor.
27
+     *
28
+     * @param array $style
29
+     */
30
+    public function register_style( $style );
31
+
32
+    /**
33
+     * Enqueues the web & shared scripts on the Register.
34
+     */
35
+    public function enqueue_web_scripts();
36
+
37
+    /**
38
+     * Enqueues the web & shared styles on the Register.
39
+     */
40
+    public function enqueue_web_styles();
41
+
42
+    /**
43
+     * Enqueues the admin & shared scripts on the Register.
44
+     */
45
+    public function enqueue_admin_scripts();
46
+
47
+    /**
48
+     * Enqueues the admin & shared styles on the Register.
49
+     */
50
+    public function enqueue_admin_styles();
51 51
 }
Please login to merge, or discard this patch.
src/Contract/Http/Filter.php 1 patch
Indentation   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -10,13 +10,13 @@
 block discarded – undo
10 10
  * @subpackage Contract\Http
11 11
  */
12 12
 interface Filter {
13
-	/**
14
-	 * Generates argument rules.
15
-	 *
16
-	 * Returns an array matching the WP-API format for argument rules,
17
-	 * including sanitization, validation, required, or defaults.
18
-	 *
19
-	 * @return array
20
-	 */
21
-	public function rules();
13
+    /**
14
+     * Generates argument rules.
15
+     *
16
+     * Returns an array matching the WP-API format for argument rules,
17
+     * including sanitization, validation, required, or defaults.
18
+     *
19
+     * @return array
20
+     */
21
+    public function rules();
22 22
 }
Please login to merge, or discard this patch.
src/Contract/Http/Guard.php 1 patch
Indentation   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -10,13 +10,13 @@
 block discarded – undo
10 10
  * @subpackage Contract\Http
11 11
  */
12 12
 interface Guard {
13
-	/**
14
-	 * Validates when the user is authorized for the route.
15
-	 *
16
-	 * Returns a boolean based on whether the current user is authorized
17
-	 * to interact with the given route.
18
-	 *
19
-	 * @return bool
20
-	 */
21
-	public function authorized();
13
+    /**
14
+     * Validates when the user is authorized for the route.
15
+     *
16
+     * Returns a boolean based on whether the current user is authorized
17
+     * to interact with the given route.
18
+     *
19
+     * @return bool
20
+     */
21
+    public function authorized();
22 22
 }
Please login to merge, or discard this patch.
src/Http/Router.php 2 patches
Spacing   +24 added lines, -24 removed lines patch added patch discarded remove patch
@@ -71,7 +71,7 @@  discard block
 block discarded – undo
71 71
 	 *
72 72
 	 * @param string $vendor
73 73
 	 */
74
-	public function set_vendor( $vendor ) {
74
+	public function set_vendor($vendor) {
75 75
 		$this->vendor = $vendor;
76 76
 	}
77 77
 
@@ -80,7 +80,7 @@  discard block
 block discarded – undo
80 80
 	 *
81 81
 	 * @param int $version
82 82
 	 */
83
-	public function set_version( $version ) {
83
+	public function set_version($version) {
84 84
 		$this->version = $version;
85 85
 	}
86 86
 
@@ -94,15 +94,15 @@  discard block
 block discarded – undo
94 94
 	 * @throws VersionNotSetException
95 95
 	 */
96 96
 	public function register() {
97
-		if ( ! $this->vendor ) {
97
+		if (!$this->vendor) {
98 98
 			throw new VendorNotSetException;
99 99
 		}
100 100
 
101
-		if ( ! $this->version ) {
101
+		if (!$this->version) {
102 102
 			throw new VersionNotSetException;
103 103
 		}
104 104
 
105
-		foreach ( $this->endpoints as $endpoint ) {
105
+		foreach ($this->endpoints as $endpoint) {
106 106
 			register_rest_route(
107 107
 				$this->get_namespace(),
108 108
 				$endpoint->get_route(),
@@ -120,13 +120,13 @@  discard block
 block discarded – undo
120 120
 	 * @param array    $options
121 121
 	 * @param callable $callback
122 122
 	 */
123
-	public function group( array $options, $callback ) {
123
+	public function group(array $options, $callback) {
124 124
 		$router = new static;
125 125
 
126
-		call_user_func( $callback, $router );
126
+		call_user_func($callback, $router);
127 127
 
128
-		foreach ( $router->get_endpoints() as $endpoint ) {
129
-			$this->endpoints[] = $this->set_options( $endpoint, $options );
128
+		foreach ($router->get_endpoints() as $endpoint) {
129
+			$this->endpoints[] = $this->set_options($endpoint, $options);
130 130
 		}
131 131
 	}
132 132
 
@@ -145,26 +145,26 @@  discard block
 block discarded – undo
145 145
 	 * @throws MissingArgumentException
146 146
 	 * @throws InvalidArgumentException
147 147
 	 */
148
-	public function __call( $name, $arguments ) {
149
-		if ( ! in_array( $name, array_keys( $this->methods ) ) ) {
148
+	public function __call($name, $arguments) {
149
+		if (!in_array($name, array_keys($this->methods))) {
150 150
 			throw new UnknownMethodException;
151 151
 		}
152 152
 
153 153
 		// array_merge ensures we have 3 elements
154
-		list( $route, $callback, $options ) = array_merge( $arguments, array( null, null, null ) );
154
+		list($route, $callback, $options) = array_merge($arguments, array(null, null, null));
155 155
 
156
-		if ( ! $route || ! $callback ) {
156
+		if (!$route || !$callback) {
157 157
 			throw new MissingArgumentException;
158 158
 		}
159 159
 
160
-		if ( ! is_callable( $callback ) ) {
160
+		if (!is_callable($callback)) {
161 161
 			throw new InvalidArgumentException;
162 162
 		}
163 163
 
164
-		$endpoint = new Endpoint( $route, $this->methods[ $name ], $callback );
164
+		$endpoint = new Endpoint($route, $this->methods[$name], $callback);
165 165
 
166
-		if ( $options && is_array( $options ) ) {
167
-			$endpoint = $this->set_options( $endpoint, $options );
166
+		if ($options && is_array($options)) {
167
+			$endpoint = $this->set_options($endpoint, $options);
168 168
 		}
169 169
 
170 170
 		return $this->endpoints[] = $endpoint;
@@ -181,17 +181,17 @@  discard block
 block discarded – undo
181 181
 	 * @return Endpoint
182 182
 	 * @throws MalformedRouteException
183 183
 	 */
184
-	protected function set_options( Endpoint $endpoint, array $options ) {
185
-		if ( isset( $options['guard'] ) ) {
186
-			$endpoint->set_guard( $options['guard'] );
184
+	protected function set_options(Endpoint $endpoint, array $options) {
185
+		if (isset($options['guard'])) {
186
+			$endpoint->set_guard($options['guard']);
187 187
 		}
188 188
 
189
-		if ( isset( $options['filter'] ) ) {
190
-			$endpoint->set_filter( $options['filter'] );
189
+		if (isset($options['filter'])) {
190
+			$endpoint->set_filter($options['filter']);
191 191
 		}
192 192
 
193
-		if ( isset( $options['prefix'] ) ) {
194
-			$endpoint->set_prefix( $options['prefix'] );
193
+		if (isset($options['prefix'])) {
194
+			$endpoint->set_prefix($options['prefix']);
195 195
 		}
196 196
 
197 197
 		return $endpoint;
Please login to merge, or discard this patch.
Indentation   +206 added lines, -206 removed lines patch added patch discarded remove patch
@@ -21,210 +21,210 @@
 block discarded – undo
21 21
  * @method Endpoint all(string $route, callable $callback, array $options = array())
22 22
  */
23 23
 class Router implements HasActions {
24
-	/**
25
-	 * Resource's vendor prefix.
26
-	 *
27
-	 * @var string
28
-	 */
29
-	protected $vendor;
30
-
31
-	/**
32
-	 * Resource's version.
33
-	 *
34
-	 * @var int
35
-	 */
36
-	protected $version;
37
-
38
-	/**
39
-	 * Valid methods and their HTTP verb(s).
40
-	 *
41
-	 * @var array
42
-	 */
43
-	private $methods = array(
44
-		'get'      => 'GET',
45
-		'post'     => 'POST',
46
-		'put'      => 'PUT',
47
-		'patch'    => 'PATCH',
48
-		'delete'   => 'DELETE',
49
-		'editable' => 'POST, PUT, PATCH',
50
-		'all'      => 'GET, POST, PUT, PATCH, DELETE',
51
-	);
52
-
53
-	/**
54
-	 * Endpoints registered for the resource.
55
-	 *
56
-	 * @var Endpoint[]
57
-	 */
58
-	protected $endpoints = array();
59
-
60
-	/**
61
-	 * Returns all the resource endpoints.
62
-	 *
63
-	 * @return Endpoint[]
64
-	 */
65
-	public function get_endpoints() {
66
-		return $this->endpoints;
67
-	}
68
-
69
-	/**
70
-	 * Sets the resource's vendor prefix.
71
-	 *
72
-	 * @param string $vendor
73
-	 *
74
-	 * @return $this
75
-	 */
76
-	public function set_vendor( $vendor ) {
77
-		$this->vendor = $vendor;
78
-
79
-		return $this;
80
-	}
81
-
82
-	/**
83
-	 * Sets the resource's version.
84
-	 *
85
-	 * @param int $version
86
-	 *
87
-	 * @return $this
88
-	 */
89
-	public function set_version( $version ) {
90
-		$this->version = $version;
91
-
92
-		return $this;
93
-	}
94
-
95
-	/**
96
-	 * Registers all of the routes with the WP-API.
97
-	 *
98
-	 * Runs on the `rest_api_init` hook. Registers all of the routes loaded
99
-	 * on the router into the WordPress REST API.
100
-	 *
101
-	 * @throws VendorNotSetException
102
-	 * @throws VersionNotSetException
103
-	 */
104
-	public function register() {
105
-		if ( ! $this->vendor ) {
106
-			throw new VendorNotSetException;
107
-		}
108
-
109
-		if ( ! $this->version ) {
110
-			throw new VersionNotSetException;
111
-		}
112
-
113
-		foreach ( $this->endpoints as $endpoint ) {
114
-			register_rest_route(
115
-				$this->get_namespace(),
116
-				$endpoint->get_route(),
117
-				$endpoint->get_options()
118
-			);
119
-		}
120
-	}
121
-
122
-	/**
123
-	 * Registers a set of routes with a shared set of options.
124
-	 *
125
-	 * Allows you to group routes together with shared set of options, including
126
-	 * a route prefix, shared guards, and common parameter validation or sanitization.
127
-	 *
128
-	 * @param array    $options
129
-	 * @param callable $callback
130
-	 */
131
-	public function group( array $options, $callback ) {
132
-		$router = new static;
133
-
134
-		call_user_func( $callback, $router );
135
-
136
-		foreach ( $router->get_endpoints() as $endpoint ) {
137
-			$this->endpoints[] = $this->set_options( $endpoint, $options );
138
-		}
139
-	}
140
-
141
-	/**
142
-	 * Magic __call method.
143
-	 *
144
-	 * All of the endpoints registration method calls pass through here. This validates whether the method
145
-	 * is a valid endpoint type to register, and creates a new endpoint with the passed options.
146
-	 *
147
-	 * @param string $name
148
-	 * @param array  $arguments
149
-	 *
150
-	 * @return Endpoint
151
-	 *
152
-	 * @throws UnknownMethodException
153
-	 * @throws MissingArgumentException
154
-	 * @throws InvalidArgumentException
155
-	 */
156
-	public function __call( $name, $arguments ) {
157
-		if ( ! in_array( $name, array_keys( $this->methods ) ) ) {
158
-			throw new UnknownMethodException;
159
-		}
160
-
161
-		// array_merge ensures we have 3 elements
162
-		list( $route, $callback, $options ) = array_merge( $arguments, array( null, null, null ) );
163
-
164
-		if ( ! $route || ! $callback ) {
165
-			throw new MissingArgumentException;
166
-		}
167
-
168
-		if ( ! is_callable( $callback ) ) {
169
-			throw new InvalidArgumentException;
170
-		}
171
-
172
-		$endpoint = new Endpoint( $route, $this->methods[ $name ], $callback );
173
-
174
-		if ( $options && is_array( $options ) ) {
175
-			$endpoint = $this->set_options( $endpoint, $options );
176
-		}
177
-
178
-		return $this->endpoints[] = $endpoint;
179
-	}
180
-
181
-	/**
182
-	 * Sets the passed options on the endpoint.
183
-	 *
184
-	 * Only sets endpoints matching setters in the Endpoint class.
185
-	 *
186
-	 * @param Endpoint $endpoint
187
-	 * @param array    $options
188
-	 *
189
-	 * @return Endpoint
190
-	 * @throws MalformedRouteException
191
-	 */
192
-	protected function set_options( Endpoint $endpoint, array $options ) {
193
-		if ( isset( $options['guard'] ) ) {
194
-			$endpoint->set_guard( $options['guard'] );
195
-		}
196
-
197
-		if ( isset( $options['filter'] ) ) {
198
-			$endpoint->set_filter( $options['filter'] );
199
-		}
200
-
201
-		if ( isset( $options['prefix'] ) ) {
202
-			$endpoint->set_prefix( $options['prefix'] );
203
-		}
204
-
205
-		return $endpoint;
206
-	}
207
-
208
-	/**
209
-	 * Generates the resource's namespace.
210
-	 *
211
-	 * @return string
212
-	 */
213
-	protected function get_namespace() {
214
-		return $this->vendor . '/v' . $this->version;
215
-	}
216
-
217
-	/**
218
-	 * {@inheritDoc}
219
-	 *
220
-	 * @return array[]
221
-	 */
222
-	public function action_hooks() {
223
-		return array(
224
-			array(
225
-				'method' => 'register',
226
-				'hook'   => 'rest_api_init',
227
-			),
228
-		);
229
-	}
24
+    /**
25
+     * Resource's vendor prefix.
26
+     *
27
+     * @var string
28
+     */
29
+    protected $vendor;
30
+
31
+    /**
32
+     * Resource's version.
33
+     *
34
+     * @var int
35
+     */
36
+    protected $version;
37
+
38
+    /**
39
+     * Valid methods and their HTTP verb(s).
40
+     *
41
+     * @var array
42
+     */
43
+    private $methods = array(
44
+        'get'      => 'GET',
45
+        'post'     => 'POST',
46
+        'put'      => 'PUT',
47
+        'patch'    => 'PATCH',
48
+        'delete'   => 'DELETE',
49
+        'editable' => 'POST, PUT, PATCH',
50
+        'all'      => 'GET, POST, PUT, PATCH, DELETE',
51
+    );
52
+
53
+    /**
54
+     * Endpoints registered for the resource.
55
+     *
56
+     * @var Endpoint[]
57
+     */
58
+    protected $endpoints = array();
59
+
60
+    /**
61
+     * Returns all the resource endpoints.
62
+     *
63
+     * @return Endpoint[]
64
+     */
65
+    public function get_endpoints() {
66
+        return $this->endpoints;
67
+    }
68
+
69
+    /**
70
+     * Sets the resource's vendor prefix.
71
+     *
72
+     * @param string $vendor
73
+     *
74
+     * @return $this
75
+     */
76
+    public function set_vendor( $vendor ) {
77
+        $this->vendor = $vendor;
78
+
79
+        return $this;
80
+    }
81
+
82
+    /**
83
+     * Sets the resource's version.
84
+     *
85
+     * @param int $version
86
+     *
87
+     * @return $this
88
+     */
89
+    public function set_version( $version ) {
90
+        $this->version = $version;
91
+
92
+        return $this;
93
+    }
94
+
95
+    /**
96
+     * Registers all of the routes with the WP-API.
97
+     *
98
+     * Runs on the `rest_api_init` hook. Registers all of the routes loaded
99
+     * on the router into the WordPress REST API.
100
+     *
101
+     * @throws VendorNotSetException
102
+     * @throws VersionNotSetException
103
+     */
104
+    public function register() {
105
+        if ( ! $this->vendor ) {
106
+            throw new VendorNotSetException;
107
+        }
108
+
109
+        if ( ! $this->version ) {
110
+            throw new VersionNotSetException;
111
+        }
112
+
113
+        foreach ( $this->endpoints as $endpoint ) {
114
+            register_rest_route(
115
+                $this->get_namespace(),
116
+                $endpoint->get_route(),
117
+                $endpoint->get_options()
118
+            );
119
+        }
120
+    }
121
+
122
+    /**
123
+     * Registers a set of routes with a shared set of options.
124
+     *
125
+     * Allows you to group routes together with shared set of options, including
126
+     * a route prefix, shared guards, and common parameter validation or sanitization.
127
+     *
128
+     * @param array    $options
129
+     * @param callable $callback
130
+     */
131
+    public function group( array $options, $callback ) {
132
+        $router = new static;
133
+
134
+        call_user_func( $callback, $router );
135
+
136
+        foreach ( $router->get_endpoints() as $endpoint ) {
137
+            $this->endpoints[] = $this->set_options( $endpoint, $options );
138
+        }
139
+    }
140
+
141
+    /**
142
+     * Magic __call method.
143
+     *
144
+     * All of the endpoints registration method calls pass through here. This validates whether the method
145
+     * is a valid endpoint type to register, and creates a new endpoint with the passed options.
146
+     *
147
+     * @param string $name
148
+     * @param array  $arguments
149
+     *
150
+     * @return Endpoint
151
+     *
152
+     * @throws UnknownMethodException
153
+     * @throws MissingArgumentException
154
+     * @throws InvalidArgumentException
155
+     */
156
+    public function __call( $name, $arguments ) {
157
+        if ( ! in_array( $name, array_keys( $this->methods ) ) ) {
158
+            throw new UnknownMethodException;
159
+        }
160
+
161
+        // array_merge ensures we have 3 elements
162
+        list( $route, $callback, $options ) = array_merge( $arguments, array( null, null, null ) );
163
+
164
+        if ( ! $route || ! $callback ) {
165
+            throw new MissingArgumentException;
166
+        }
167
+
168
+        if ( ! is_callable( $callback ) ) {
169
+            throw new InvalidArgumentException;
170
+        }
171
+
172
+        $endpoint = new Endpoint( $route, $this->methods[ $name ], $callback );
173
+
174
+        if ( $options && is_array( $options ) ) {
175
+            $endpoint = $this->set_options( $endpoint, $options );
176
+        }
177
+
178
+        return $this->endpoints[] = $endpoint;
179
+    }
180
+
181
+    /**
182
+     * Sets the passed options on the endpoint.
183
+     *
184
+     * Only sets endpoints matching setters in the Endpoint class.
185
+     *
186
+     * @param Endpoint $endpoint
187
+     * @param array    $options
188
+     *
189
+     * @return Endpoint
190
+     * @throws MalformedRouteException
191
+     */
192
+    protected function set_options( Endpoint $endpoint, array $options ) {
193
+        if ( isset( $options['guard'] ) ) {
194
+            $endpoint->set_guard( $options['guard'] );
195
+        }
196
+
197
+        if ( isset( $options['filter'] ) ) {
198
+            $endpoint->set_filter( $options['filter'] );
199
+        }
200
+
201
+        if ( isset( $options['prefix'] ) ) {
202
+            $endpoint->set_prefix( $options['prefix'] );
203
+        }
204
+
205
+        return $endpoint;
206
+    }
207
+
208
+    /**
209
+     * Generates the resource's namespace.
210
+     *
211
+     * @return string
212
+     */
213
+    protected function get_namespace() {
214
+        return $this->vendor . '/v' . $this->version;
215
+    }
216
+
217
+    /**
218
+     * {@inheritDoc}
219
+     *
220
+     * @return array[]
221
+     */
222
+    public function action_hooks() {
223
+        return array(
224
+            array(
225
+                'method' => 'register',
226
+                'hook'   => 'rest_api_init',
227
+            ),
228
+        );
229
+    }
230 230
 }
Please login to merge, or discard this patch.
src/Http/Endpoint.php 2 patches
Indentation   +137 added lines, -137 removed lines patch added patch discarded remove patch
@@ -14,141 +14,141 @@
 block discarded – undo
14 14
  * @subpackage Http
15 15
  */
16 16
 class Endpoint {
17
-	/**
18
-	 * Endpoint's route.
19
-	 *
20
-	 * @var string
21
-	 */
22
-	protected $route;
23
-
24
-	/**
25
-	 * Endpoint's HTTP verb(s).
26
-	 *
27
-	 * @var string
28
-	 */
29
-	protected $method;
30
-
31
-	/**
32
-	 * Endpoint's callback.
33
-	 *
34
-	 * @var callable
35
-	 */
36
-	protected $callback;
37
-
38
-	/**
39
-	 * Endpoint's permission guard.
40
-	 *
41
-	 * @var GuardContract
42
-	 */
43
-	protected $guard;
44
-
45
-	/**
46
-	 * Endpoint's arguments filter.
47
-	 *
48
-	 * @var FilterContract
49
-	 */
50
-	protected $filter;
51
-
52
-	/**
53
-	 * Endpoint's route prefix.
54
-	 *
55
-	 * @var string
56
-	 */
57
-	protected $prefix;
58
-
59
-	/**
60
-	 * Instantiate a new endpoint with a provided route, method, and callback.
61
-	 *
62
-	 * @param string   $route
63
-	 * @param string   $method
64
-	 * @param callable $callback
65
-	 *
66
-	 * @throws MalformedRouteException
67
-	 */
68
-	public function __construct( $route, $method, $callback ) {
69
-		if ( ! Str::starts_with( $route, '/' ) || Str::ends_with( $route, '/' ) ) {
70
-			throw new MalformedRouteException;
71
-		}
72
-
73
-		$this->route    = $route;
74
-		$this->method   = $method;
75
-		$this->callback = $callback;
76
-	}
77
-
78
-	/**
79
-	 * Generates the endpoint's route.
80
-	 *
81
-	 * Combines the prefix with the route to generate the full route string.
82
-	 *
83
-	 * @return string
84
-	 */
85
-	public function get_route() {
86
-		return ( $this->prefix ?: '' ) . $this->route;
87
-	}
88
-
89
-	/**
90
-	 * Generates the endpoint's WP-API options array.
91
-	 *
92
-	 * @return array
93
-	 */
94
-	public function get_options() {
95
-		$options = array(
96
-			'methods'  => $this->method,
97
-			'callback' => $this->callback,
98
-		);
99
-
100
-		if ( $this->guard ) {
101
-			$options['permission_callback'] = array( $this->guard, 'authorized' );
102
-		}
103
-
104
-		if ( $this->filter ) {
105
-			$options['args'] = $this->filter->rules();
106
-		}
107
-
108
-		return $options;
109
-	}
110
-
111
-	/**
112
-	 * Sets the endpoint's permission guard.
113
-	 *
114
-	 * @param GuardContract $guard
115
-	 *
116
-	 * @return $this
117
-	 */
118
-	public function set_guard( GuardContract $guard ) {
119
-		$this->guard = $guard;
120
-
121
-		return $this;
122
-	}
123
-
124
-	/**
125
-	 * Sets the endpoint's arguments filter.
126
-	 *
127
-	 * @param FilterContract $filter
128
-	 *
129
-	 * @return $this
130
-	 */
131
-	public function set_filter( FilterContract $filter ) {
132
-		$this->filter = $filter;
133
-
134
-		return $this;
135
-	}
136
-
137
-	/**
138
-	 * Sets the endpoint's prefix.
139
-	 *
140
-	 * @param string $prefix
141
-	 *
142
-	 * @return $this
143
-	 * @throws MalformedRouteException
144
-	 */
145
-	public function set_prefix( $prefix ) {
146
-		if ( ! Str::starts_with( $prefix, '/' ) || Str::ends_with( $prefix, '/' ) ) {
147
-			throw new MalformedRouteException;
148
-		}
149
-
150
-		$this->prefix = $prefix;
151
-
152
-		return $this;
153
-	}
17
+    /**
18
+     * Endpoint's route.
19
+     *
20
+     * @var string
21
+     */
22
+    protected $route;
23
+
24
+    /**
25
+     * Endpoint's HTTP verb(s).
26
+     *
27
+     * @var string
28
+     */
29
+    protected $method;
30
+
31
+    /**
32
+     * Endpoint's callback.
33
+     *
34
+     * @var callable
35
+     */
36
+    protected $callback;
37
+
38
+    /**
39
+     * Endpoint's permission guard.
40
+     *
41
+     * @var GuardContract
42
+     */
43
+    protected $guard;
44
+
45
+    /**
46
+     * Endpoint's arguments filter.
47
+     *
48
+     * @var FilterContract
49
+     */
50
+    protected $filter;
51
+
52
+    /**
53
+     * Endpoint's route prefix.
54
+     *
55
+     * @var string
56
+     */
57
+    protected $prefix;
58
+
59
+    /**
60
+     * Instantiate a new endpoint with a provided route, method, and callback.
61
+     *
62
+     * @param string   $route
63
+     * @param string   $method
64
+     * @param callable $callback
65
+     *
66
+     * @throws MalformedRouteException
67
+     */
68
+    public function __construct( $route, $method, $callback ) {
69
+        if ( ! Str::starts_with( $route, '/' ) || Str::ends_with( $route, '/' ) ) {
70
+            throw new MalformedRouteException;
71
+        }
72
+
73
+        $this->route    = $route;
74
+        $this->method   = $method;
75
+        $this->callback = $callback;
76
+    }
77
+
78
+    /**
79
+     * Generates the endpoint's route.
80
+     *
81
+     * Combines the prefix with the route to generate the full route string.
82
+     *
83
+     * @return string
84
+     */
85
+    public function get_route() {
86
+        return ( $this->prefix ?: '' ) . $this->route;
87
+    }
88
+
89
+    /**
90
+     * Generates the endpoint's WP-API options array.
91
+     *
92
+     * @return array
93
+     */
94
+    public function get_options() {
95
+        $options = array(
96
+            'methods'  => $this->method,
97
+            'callback' => $this->callback,
98
+        );
99
+
100
+        if ( $this->guard ) {
101
+            $options['permission_callback'] = array( $this->guard, 'authorized' );
102
+        }
103
+
104
+        if ( $this->filter ) {
105
+            $options['args'] = $this->filter->rules();
106
+        }
107
+
108
+        return $options;
109
+    }
110
+
111
+    /**
112
+     * Sets the endpoint's permission guard.
113
+     *
114
+     * @param GuardContract $guard
115
+     *
116
+     * @return $this
117
+     */
118
+    public function set_guard( GuardContract $guard ) {
119
+        $this->guard = $guard;
120
+
121
+        return $this;
122
+    }
123
+
124
+    /**
125
+     * Sets the endpoint's arguments filter.
126
+     *
127
+     * @param FilterContract $filter
128
+     *
129
+     * @return $this
130
+     */
131
+    public function set_filter( FilterContract $filter ) {
132
+        $this->filter = $filter;
133
+
134
+        return $this;
135
+    }
136
+
137
+    /**
138
+     * Sets the endpoint's prefix.
139
+     *
140
+     * @param string $prefix
141
+     *
142
+     * @return $this
143
+     * @throws MalformedRouteException
144
+     */
145
+    public function set_prefix( $prefix ) {
146
+        if ( ! Str::starts_with( $prefix, '/' ) || Str::ends_with( $prefix, '/' ) ) {
147
+            throw new MalformedRouteException;
148
+        }
149
+
150
+        $this->prefix = $prefix;
151
+
152
+        return $this;
153
+    }
154 154
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -65,8 +65,8 @@  discard block
 block discarded – undo
65 65
 	 *
66 66
 	 * @throws MalformedRouteException
67 67
 	 */
68
-	public function __construct( $route, $method, $callback ) {
69
-		if ( ! Str::starts_with( $route, '/' ) || Str::ends_with( $route, '/' ) ) {
68
+	public function __construct($route, $method, $callback) {
69
+		if (!Str::starts_with($route, '/') || Str::ends_with($route, '/')) {
70 70
 			throw new MalformedRouteException;
71 71
 		}
72 72
 
@@ -83,7 +83,7 @@  discard block
 block discarded – undo
83 83
 	 * @return string
84 84
 	 */
85 85
 	public function get_route() {
86
-		return ( $this->prefix ?: '' ) . $this->route;
86
+		return ($this->prefix ?: '') . $this->route;
87 87
 	}
88 88
 
89 89
 	/**
@@ -97,11 +97,11 @@  discard block
 block discarded – undo
97 97
 			'callback' => $this->callback,
98 98
 		);
99 99
 
100
-		if ( $this->guard ) {
101
-			$options['permission_callback'] = array( $this->guard, 'authorized' );
100
+		if ($this->guard) {
101
+			$options['permission_callback'] = array($this->guard, 'authorized');
102 102
 		}
103 103
 
104
-		if ( $this->filter ) {
104
+		if ($this->filter) {
105 105
 			$options['args'] = $this->filter->rules();
106 106
 		}
107 107
 
@@ -115,7 +115,7 @@  discard block
 block discarded – undo
115 115
 	 *
116 116
 	 * @return $this
117 117
 	 */
118
-	public function set_guard( GuardContract $guard ) {
118
+	public function set_guard(GuardContract $guard) {
119 119
 		$this->guard = $guard;
120 120
 
121 121
 		return $this;
@@ -128,7 +128,7 @@  discard block
 block discarded – undo
128 128
 	 *
129 129
 	 * @return $this
130 130
 	 */
131
-	public function set_filter( FilterContract $filter ) {
131
+	public function set_filter(FilterContract $filter) {
132 132
 		$this->filter = $filter;
133 133
 
134 134
 		return $this;
@@ -142,8 +142,8 @@  discard block
 block discarded – undo
142 142
 	 * @return $this
143 143
 	 * @throws MalformedRouteException
144 144
 	 */
145
-	public function set_prefix( $prefix ) {
146
-		if ( ! Str::starts_with( $prefix, '/' ) || Str::ends_with( $prefix, '/' ) ) {
145
+	public function set_prefix($prefix) {
146
+		if (!Str::starts_with($prefix, '/') || Str::ends_with($prefix, '/')) {
147 147
 			throw new MalformedRouteException;
148 148
 		}
149 149
 
Please login to merge, or discard this patch.
src/Http/Guard.php 3 patches
Unused Use Statements   -1 removed lines patch added patch discarded remove patch
@@ -1,7 +1,6 @@
 block discarded – undo
1 1
 <?php
2 2
 namespace Intraxia\Jaxion\Model;
3 3
 
4
-use Intraxia\Jaxion\Utility\Str;
5 4
 use stdClass;
6 5
 use WP_Post;
7 6
 
Please login to merge, or discard this patch.
Indentation   +73 added lines, -73 removed lines patch added patch discarded remove patch
@@ -15,86 +15,86 @@
 block discarded – undo
15 15
  * @subpackage Http
16 16
  */
17 17
 class Guard implements GuardContract {
18
-	/**
19
-	 * Default options.
20
-	 *
21
-	 * @var array
22
-	 */
23
-	protected $defaults = array(
24
-		'rule'     => 'public',
25
-		'callback' => false,
26
-	);
18
+    /**
19
+     * Default options.
20
+     *
21
+     * @var array
22
+     */
23
+    protected $defaults = array(
24
+        'rule'     => 'public',
25
+        'callback' => false,
26
+    );
27 27
 
28
-	/**
29
-	 * Guard options.
30
-	 *
31
-	 * @var array
32
-	 */
33
-	protected $options;
28
+    /**
29
+     * Guard options.
30
+     *
31
+     * @var array
32
+     */
33
+    protected $options;
34 34
 
35
-	/**
36
-	 * Instantiate a new Guard with provided options.
37
-	 *
38
-	 * @param array $options
39
-	 */
40
-	public function __construct( array $options = array() ) {
41
-		$this->options = $this->set_defaults( $options );
42
-	}
35
+    /**
36
+     * Instantiate a new Guard with provided options.
37
+     *
38
+     * @param array $options
39
+     */
40
+    public function __construct( array $options = array() ) {
41
+        $this->options = $this->set_defaults( $options );
42
+    }
43 43
 
44
-	/**
45
-	 * Validates whether the current user is authorized.
46
-	 *
47
-	 * @return true|WP_Error
48
-	 */
49
-	public function authorized() {
50
-		// if the rule is public, always authorized
51
-		if ( 'public' === $this->options['rule'] ) {
52
-			return true;
53
-		}
44
+    /**
45
+     * Validates whether the current user is authorized.
46
+     *
47
+     * @return true|WP_Error
48
+     */
49
+    public function authorized() {
50
+        // if the rule is public, always authorized
51
+        if ( 'public' === $this->options['rule'] ) {
52
+            return true;
53
+        }
54 54
 
55
-		// enable passing in callback
56
-		if ( 'callback' === $this->options['rule'] && is_callable( $this->options['callback'] ) ) {
57
-			return call_user_func( $this->options['callback'] );
58
-		}
55
+        // enable passing in callback
56
+        if ( 'callback' === $this->options['rule'] && is_callable( $this->options['callback'] ) ) {
57
+            return call_user_func( $this->options['callback'] );
58
+        }
59 59
 
60
-		// map rule to method
61
-		if ( method_exists( $this, $method = $this->options['rule'] ) ) {
62
-			return $this->{$method}();
63
-		}
60
+        // map rule to method
61
+        if ( method_exists( $this, $method = $this->options['rule'] ) ) {
62
+            return $this->{$method}();
63
+        }
64 64
 
65
-		// disable in rule is misconfigused
66
-		// @todo set up internal translations
67
-		// @todo also, this error message kinda sucks
68
-		return new WP_Error( '500', __( 'Guard failure', 'jaxion' ) );
69
-	}
65
+        // disable in rule is misconfigused
66
+        // @todo set up internal translations
67
+        // @todo also, this error message kinda sucks
68
+        return new WP_Error( '500', __( 'Guard failure', 'jaxion' ) );
69
+    }
70 70
 
71
-	/**
72
-	 * Checks whether the current user can edit other's posts.
73
-	 *
74
-	 * @return bool|WP_Error
75
-	 */
76
-	protected function can_edit_others_posts() {
77
-		return current_user_can( 'edit_others_posts' ) ?: new WP_Error( 'unauthorized', __( 'Unauthorized user', 'jaxion' ), array( 'status' => 401 ) );
78
-	}
71
+    /**
72
+     * Checks whether the current user can edit other's posts.
73
+     *
74
+     * @return bool|WP_Error
75
+     */
76
+    protected function can_edit_others_posts() {
77
+        return current_user_can( 'edit_others_posts' ) ?: new WP_Error( 'unauthorized', __( 'Unauthorized user', 'jaxion' ), array( 'status' => 401 ) );
78
+    }
79 79
 
80
-	/**
81
-	 * Checks whether the user is currently logged in.
82
-	 *
83
-	 * @return bool|WP_Error
84
-	 */
85
-	protected function user_logged_in() {
86
-		return is_user_logged_in() ?: new WP_Error( 'unauthorized', __( 'Unauthorized user', 'jaxion' ), array( 'status' => 401 ) );
87
-	}
80
+    /**
81
+     * Checks whether the user is currently logged in.
82
+     *
83
+     * @return bool|WP_Error
84
+     */
85
+    protected function user_logged_in() {
86
+        return is_user_logged_in() ?: new WP_Error( 'unauthorized', __( 'Unauthorized user', 'jaxion' ), array( 'status' => 401 ) );
87
+    }
88 88
 
89
-	/**
90
-	 * Sets the default params for the Guard options.
91
-	 *
92
-	 * @param array $options
93
-	 *
94
-	 * @return array
95
-	 */
96
-	protected function set_defaults( $options ) {
97
-		// these are the valid options
98
-		return wp_parse_args( $options, $this->defaults );
99
-	}
89
+    /**
90
+     * Sets the default params for the Guard options.
91
+     *
92
+     * @param array $options
93
+     *
94
+     * @return array
95
+     */
96
+    protected function set_defaults( $options ) {
97
+        // these are the valid options
98
+        return wp_parse_args( $options, $this->defaults );
99
+    }
100 100
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -37,8 +37,8 @@  discard block
 block discarded – undo
37 37
 	 *
38 38
 	 * @param array $options
39 39
 	 */
40
-	public function __construct( array $options = array() ) {
41
-		$this->options = $this->set_defaults( $options );
40
+	public function __construct(array $options = array()) {
41
+		$this->options = $this->set_defaults($options);
42 42
 	}
43 43
 
44 44
 	/**
@@ -48,24 +48,24 @@  discard block
 block discarded – undo
48 48
 	 */
49 49
 	public function authorized() {
50 50
 		// if the rule is public, always authorized
51
-		if ( 'public' === $this->options['rule'] ) {
51
+		if ('public' === $this->options['rule']) {
52 52
 			return true;
53 53
 		}
54 54
 
55 55
 		// enable passing in callback
56
-		if ( 'callback' === $this->options['rule'] && is_callable( $this->options['callback'] ) ) {
57
-			return call_user_func( $this->options['callback'] );
56
+		if ('callback' === $this->options['rule'] && is_callable($this->options['callback'])) {
57
+			return call_user_func($this->options['callback']);
58 58
 		}
59 59
 
60 60
 		// map rule to method
61
-		if ( method_exists( $this, $method = $this->options['rule'] ) ) {
61
+		if (method_exists($this, $method = $this->options['rule'])) {
62 62
 			return $this->{$method}();
63 63
 		}
64 64
 
65 65
 		// disable in rule is misconfigused
66 66
 		// @todo set up internal translations
67 67
 		// @todo also, this error message kinda sucks
68
-		return new WP_Error( '500', __( 'Guard failure', 'jaxion' ) );
68
+		return new WP_Error('500', __('Guard failure', 'jaxion'));
69 69
 	}
70 70
 
71 71
 	/**
@@ -74,7 +74,7 @@  discard block
 block discarded – undo
74 74
 	 * @return bool|WP_Error
75 75
 	 */
76 76
 	protected function can_edit_others_posts() {
77
-		return current_user_can( 'edit_others_posts' ) ?: new WP_Error( 'unauthorized', __( 'Unauthorized user', 'jaxion' ), array( 'status' => 401 ) );
77
+		return current_user_can('edit_others_posts') ?: new WP_Error('unauthorized', __('Unauthorized user', 'jaxion'), array('status' => 401));
78 78
 	}
79 79
 
80 80
 	/**
@@ -83,7 +83,7 @@  discard block
 block discarded – undo
83 83
 	 * @return bool|WP_Error
84 84
 	 */
85 85
 	protected function user_logged_in() {
86
-		return is_user_logged_in() ?: new WP_Error( 'unauthorized', __( 'Unauthorized user', 'jaxion' ), array( 'status' => 401 ) );
86
+		return is_user_logged_in() ?: new WP_Error('unauthorized', __('Unauthorized user', 'jaxion'), array('status' => 401));
87 87
 	}
88 88
 
89 89
 	/**
@@ -93,8 +93,8 @@  discard block
 block discarded – undo
93 93
 	 *
94 94
 	 * @return array
95 95
 	 */
96
-	protected function set_defaults( $options ) {
96
+	protected function set_defaults($options) {
97 97
 		// these are the valid options
98
-		return wp_parse_args( $options, $this->defaults );
98
+		return wp_parse_args($options, $this->defaults);
99 99
 	}
100 100
 }
Please login to merge, or discard this patch.
src/Axolotl/EntityManager.php 3 patches
Unused Use Statements   -1 removed lines patch added patch discarded remove patch
@@ -3,7 +3,6 @@
 block discarded – undo
3 3
 
4 4
 use Intraxia\Jaxion\Axolotl\Relationship\Root as Relationship;
5 5
 use Intraxia\Jaxion\Axolotl\Repository\AbstractRepository;
6
-use Intraxia\Jaxion\Axolotl\Repository\CustomTable as CustomTableRepository;
7 6
 use Intraxia\Jaxion\Axolotl\Repository\WordPressPost as WordPressPostRepository;
8 7
 use Intraxia\Jaxion\Axolotl\Repository\WordPressTerm as WordPressTermRepository;
9 8
 use Intraxia\Jaxion\Contract\Axolotl\EntityManager as EntityManagerContract;
Please login to merge, or discard this patch.
Indentation   +241 added lines, -241 removed lines patch added patch discarded remove patch
@@ -22,245 +22,245 @@
 block discarded – undo
22 22
  * @subpackage Axolotl
23 23
  */
24 24
 class EntityManager implements EntityManagerContract {
25
-	/**
26
-	 * Post meta prefix.
27
-	 *
28
-	 * @var string
29
-	 */
30
-	protected $prefix;
31
-
32
-	/**
33
-	 * WP_Query instance.
34
-	 *
35
-	 * @var WP_Query
36
-	 */
37
-	protected $main;
38
-
39
-	/**
40
-	 * Global WPDB instance.
41
-	 *
42
-	 * @var wpdb
43
-	 */
44
-	protected $wpdb;
45
-
46
-	/**
47
-	 * EntityManager constructor.
48
-	 *
49
-	 * @param WP_Query $main
50
-	 * @param string   $prefix Post meta prefix.
51
-	 */
52
-	public function __construct( WP_Query $main, $prefix ) {
53
-		global $wpdb;
54
-
55
-		$this->wpdb   = $wpdb;
56
-		$this->main   = $main;
57
-		$this->prefix = $prefix;
58
-	}
59
-
60
-	/**
61
-	 * {@inheritDoc}
62
-	 *
63
-	 * @param string $class
64
-	 * @param int    $id
65
-	 *
66
-	 * @return Model|WP_Error
67
-	 *
68
-	 * @throws LogicException
69
-	 */
70
-	public function find( $class, $id ) {
71
-		$repository = $this->get_repository( $class );
72
-		$model      = $repository->find( $id );
73
-
74
-		if ( is_wp_error( $model ) ) {
75
-			return $model;
76
-		}
77
-
78
-		$this->handle_model( $repository, $model );
79
-
80
-		return $model;
81
-	}
82
-
83
-	/**
84
-	 * {@inheritDoc}
85
-	 *
86
-	 * @param string $class
87
-	 * @param array  $params
88
-	 *
89
-	 * @return Collection
90
-	 *
91
-	 * @throws LogicException
92
-	 */
93
-	public function find_by( $class, $params = array() ) {
94
-		$repository = $this->get_repository( $class );
95
-		$collection = $repository->find_by( $params );
96
-
97
-		foreach ( $collection as $model ) {
98
-			$this->handle_model( $repository, $model );
99
-		}
100
-
101
-		return $collection;
102
-	}
103
-
104
-	/**
105
-	 * {@inheritDoc}
106
-	 *
107
-	 * @param string $class
108
-	 * @param array  $data
109
-	 *
110
-	 * @return Model|WP_Error
111
-	 */
112
-	public function create( $class, $data = array() ) {
113
-		$repository = $this->get_repository( $class );
114
-		$model      = $repository->create( $data );
115
-
116
-		$this->handle_model( $repository, $model );
117
-
118
-		return $model;
119
-	}
120
-
121
-	/**
122
-	 * {@inheritDoc}
123
-	 *
124
-	 * @param Model $model
125
-	 *
126
-	 * @return Model|WP_Error
127
-	 */
128
-	public function persist( Model $model ) {
129
-		return $this->get_repository( get_class( $model ) )->persist( $model );
130
-	}
131
-
132
-	/**
133
-	 * {@inheritDoc}
134
-	 *
135
-	 * @param Model $model
136
-	 * @param bool  $force
137
-	 *
138
-	 * @return Model|WP_Error
139
-	 */
140
-	public function delete( Model $model, $force = false ) {
141
-		return $this->get_repository( get_class( $model ) )->delete( $model, $force );
142
-	}
143
-
144
-	/**
145
-	 * {@inheritDoc}
146
-	 */
147
-	public function free() {
148
-		AbstractRepository::free();
149
-	}
150
-
151
-	/**
152
-	 * Get the EntityManager prefix.
153
-	 *
154
-	 * @return string
155
-	 */
156
-	public function get_prefix() {
157
-		return $this->prefix;
158
-	}
159
-
160
-	/**
161
-	 * Get the main WP_Query instance.
162
-	 *
163
-	 * @return WP_Query
164
-	 */
165
-	public function get_main_query() {
166
-		return $this->main;
167
-	}
168
-
169
-	/**
170
-	 * Get the wpdb connection instance.
171
-	 *
172
-	 * @return wpdb
173
-	 */
174
-	public function get_wpdb() {
175
-		return $this->wpdb;
176
-	}
177
-
178
-	/**
179
-	 * Retrieves the repository for the given class.
180
-	 *
181
-	 * @param string $class
182
-	 *
183
-	 * @return Repository\AbstractRepository
184
-	 *
185
-	 * @throws LogicException
186
-	 */
187
-	protected function get_repository( $class ) {
188
-		// We can only use Axolotl models.
189
-		if ( ! is_subclass_of( $class, 'Intraxia\Jaxion\Axolotl\Model' ) ) {
190
-			throw new LogicException;
191
-		}
192
-
193
-		if ( is_subclass_of(
194
-			$class,
195
-			'Intraxia\Jaxion\Contract\Axolotl\UsesWordPressPost'
196
-		) ) {
197
-			return new WordPressPostRepository( $this, $class );
198
-		}
199
-
200
-		if ( is_subclass_of(
201
-			$class,
202
-			'Intraxia\Jaxion\Contract\Axolotl\UsesWordPressTerm'
203
-		) ) {
204
-			return new WordPressTermRepository( $this, $class );
205
-		}
206
-
207
-		if ( is_subclass_of(
208
-			$class,
209
-			'Intraxia\Jaxion\Contract\Axolotl\UsesCustomTable'
210
-		) ) {
211
-			throw new LogicException;
212
-		}
213
-
214
-		// If a model doesn't have a backing data source,
215
-		// the developer needs to fix this immediately.
216
-		throw new LogicException;
217
-	}
218
-
219
-	/**
220
-	 * Ensures the model is registered with the model and fills its relations.
221
-	 *
222
-	 * @param AbstractRepository $repository
223
-	 * @param Model              $model
224
-	 */
225
-	protected function handle_model( AbstractRepository $repository, Model $model ) {
226
-		$repository->register_model( $model );
227
-
228
-		if ( $model instanceof HasEagerRelationships ) {
229
-			$this->fill_related( $model, $model::get_eager_relationships() );
230
-		}
231
-	}
232
-
233
-	/**
234
-	 * Fills the Model with the provided relations.
235
-	 *
236
-	 * If no relations are provided, all relations are filled.
237
-	 *
238
-	 * @param Model $model
239
-	 * @param array $relations
240
-	 *
241
-	 * @throws LogicException
242
-	 */
243
-	protected function fill_related( Model $model, array $relations = array() ) {
244
-		if ( ! $relations ) {
245
-			$relations = $model->get_related_keys();
246
-		}
247
-
248
-		foreach ( $relations as $relation ) {
249
-			if ( ! in_array( $relation, $model->get_related_keys() ) ) {
250
-				throw new LogicException;
251
-			}
252
-
253
-			if ( $model->relation_is_filled( $relation ) ) {
254
-				continue;
255
-			}
256
-
257
-			/**
258
-			 * Model relationship.
259
-			 *
260
-			 * @var Relationship $relation
261
-			 */
262
-			$relation = $model->{"related_{$relation}"}();
263
-			$relation->attach_relation( $this );
264
-		}
265
-	}
25
+    /**
26
+     * Post meta prefix.
27
+     *
28
+     * @var string
29
+     */
30
+    protected $prefix;
31
+
32
+    /**
33
+     * WP_Query instance.
34
+     *
35
+     * @var WP_Query
36
+     */
37
+    protected $main;
38
+
39
+    /**
40
+     * Global WPDB instance.
41
+     *
42
+     * @var wpdb
43
+     */
44
+    protected $wpdb;
45
+
46
+    /**
47
+     * EntityManager constructor.
48
+     *
49
+     * @param WP_Query $main
50
+     * @param string   $prefix Post meta prefix.
51
+     */
52
+    public function __construct( WP_Query $main, $prefix ) {
53
+        global $wpdb;
54
+
55
+        $this->wpdb   = $wpdb;
56
+        $this->main   = $main;
57
+        $this->prefix = $prefix;
58
+    }
59
+
60
+    /**
61
+     * {@inheritDoc}
62
+     *
63
+     * @param string $class
64
+     * @param int    $id
65
+     *
66
+     * @return Model|WP_Error
67
+     *
68
+     * @throws LogicException
69
+     */
70
+    public function find( $class, $id ) {
71
+        $repository = $this->get_repository( $class );
72
+        $model      = $repository->find( $id );
73
+
74
+        if ( is_wp_error( $model ) ) {
75
+            return $model;
76
+        }
77
+
78
+        $this->handle_model( $repository, $model );
79
+
80
+        return $model;
81
+    }
82
+
83
+    /**
84
+     * {@inheritDoc}
85
+     *
86
+     * @param string $class
87
+     * @param array  $params
88
+     *
89
+     * @return Collection
90
+     *
91
+     * @throws LogicException
92
+     */
93
+    public function find_by( $class, $params = array() ) {
94
+        $repository = $this->get_repository( $class );
95
+        $collection = $repository->find_by( $params );
96
+
97
+        foreach ( $collection as $model ) {
98
+            $this->handle_model( $repository, $model );
99
+        }
100
+
101
+        return $collection;
102
+    }
103
+
104
+    /**
105
+     * {@inheritDoc}
106
+     *
107
+     * @param string $class
108
+     * @param array  $data
109
+     *
110
+     * @return Model|WP_Error
111
+     */
112
+    public function create( $class, $data = array() ) {
113
+        $repository = $this->get_repository( $class );
114
+        $model      = $repository->create( $data );
115
+
116
+        $this->handle_model( $repository, $model );
117
+
118
+        return $model;
119
+    }
120
+
121
+    /**
122
+     * {@inheritDoc}
123
+     *
124
+     * @param Model $model
125
+     *
126
+     * @return Model|WP_Error
127
+     */
128
+    public function persist( Model $model ) {
129
+        return $this->get_repository( get_class( $model ) )->persist( $model );
130
+    }
131
+
132
+    /**
133
+     * {@inheritDoc}
134
+     *
135
+     * @param Model $model
136
+     * @param bool  $force
137
+     *
138
+     * @return Model|WP_Error
139
+     */
140
+    public function delete( Model $model, $force = false ) {
141
+        return $this->get_repository( get_class( $model ) )->delete( $model, $force );
142
+    }
143
+
144
+    /**
145
+     * {@inheritDoc}
146
+     */
147
+    public function free() {
148
+        AbstractRepository::free();
149
+    }
150
+
151
+    /**
152
+     * Get the EntityManager prefix.
153
+     *
154
+     * @return string
155
+     */
156
+    public function get_prefix() {
157
+        return $this->prefix;
158
+    }
159
+
160
+    /**
161
+     * Get the main WP_Query instance.
162
+     *
163
+     * @return WP_Query
164
+     */
165
+    public function get_main_query() {
166
+        return $this->main;
167
+    }
168
+
169
+    /**
170
+     * Get the wpdb connection instance.
171
+     *
172
+     * @return wpdb
173
+     */
174
+    public function get_wpdb() {
175
+        return $this->wpdb;
176
+    }
177
+
178
+    /**
179
+     * Retrieves the repository for the given class.
180
+     *
181
+     * @param string $class
182
+     *
183
+     * @return Repository\AbstractRepository
184
+     *
185
+     * @throws LogicException
186
+     */
187
+    protected function get_repository( $class ) {
188
+        // We can only use Axolotl models.
189
+        if ( ! is_subclass_of( $class, 'Intraxia\Jaxion\Axolotl\Model' ) ) {
190
+            throw new LogicException;
191
+        }
192
+
193
+        if ( is_subclass_of(
194
+            $class,
195
+            'Intraxia\Jaxion\Contract\Axolotl\UsesWordPressPost'
196
+        ) ) {
197
+            return new WordPressPostRepository( $this, $class );
198
+        }
199
+
200
+        if ( is_subclass_of(
201
+            $class,
202
+            'Intraxia\Jaxion\Contract\Axolotl\UsesWordPressTerm'
203
+        ) ) {
204
+            return new WordPressTermRepository( $this, $class );
205
+        }
206
+
207
+        if ( is_subclass_of(
208
+            $class,
209
+            'Intraxia\Jaxion\Contract\Axolotl\UsesCustomTable'
210
+        ) ) {
211
+            throw new LogicException;
212
+        }
213
+
214
+        // If a model doesn't have a backing data source,
215
+        // the developer needs to fix this immediately.
216
+        throw new LogicException;
217
+    }
218
+
219
+    /**
220
+     * Ensures the model is registered with the model and fills its relations.
221
+     *
222
+     * @param AbstractRepository $repository
223
+     * @param Model              $model
224
+     */
225
+    protected function handle_model( AbstractRepository $repository, Model $model ) {
226
+        $repository->register_model( $model );
227
+
228
+        if ( $model instanceof HasEagerRelationships ) {
229
+            $this->fill_related( $model, $model::get_eager_relationships() );
230
+        }
231
+    }
232
+
233
+    /**
234
+     * Fills the Model with the provided relations.
235
+     *
236
+     * If no relations are provided, all relations are filled.
237
+     *
238
+     * @param Model $model
239
+     * @param array $relations
240
+     *
241
+     * @throws LogicException
242
+     */
243
+    protected function fill_related( Model $model, array $relations = array() ) {
244
+        if ( ! $relations ) {
245
+            $relations = $model->get_related_keys();
246
+        }
247
+
248
+        foreach ( $relations as $relation ) {
249
+            if ( ! in_array( $relation, $model->get_related_keys() ) ) {
250
+                throw new LogicException;
251
+            }
252
+
253
+            if ( $model->relation_is_filled( $relation ) ) {
254
+                continue;
255
+            }
256
+
257
+            /**
258
+             * Model relationship.
259
+             *
260
+             * @var Relationship $relation
261
+             */
262
+            $relation = $model->{"related_{$relation}"}();
263
+            $relation->attach_relation( $this );
264
+        }
265
+    }
266 266
 }
Please login to merge, or discard this patch.
Spacing   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -49,7 +49,7 @@  discard block
 block discarded – undo
49 49
 	 * @param WP_Query $main
50 50
 	 * @param string   $prefix Post meta prefix.
51 51
 	 */
52
-	public function __construct( WP_Query $main, $prefix ) {
52
+	public function __construct(WP_Query $main, $prefix) {
53 53
 		global $wpdb;
54 54
 
55 55
 		$this->wpdb   = $wpdb;
@@ -67,15 +67,15 @@  discard block
 block discarded – undo
67 67
 	 *
68 68
 	 * @throws LogicException
69 69
 	 */
70
-	public function find( $class, $id ) {
71
-		$repository = $this->get_repository( $class );
72
-		$model      = $repository->find( $id );
70
+	public function find($class, $id) {
71
+		$repository = $this->get_repository($class);
72
+		$model      = $repository->find($id);
73 73
 
74
-		if ( is_wp_error( $model ) ) {
74
+		if (is_wp_error($model)) {
75 75
 			return $model;
76 76
 		}
77 77
 
78
-		$this->handle_model( $repository, $model );
78
+		$this->handle_model($repository, $model);
79 79
 
80 80
 		return $model;
81 81
 	}
@@ -90,12 +90,12 @@  discard block
 block discarded – undo
90 90
 	 *
91 91
 	 * @throws LogicException
92 92
 	 */
93
-	public function find_by( $class, $params = array() ) {
94
-		$repository = $this->get_repository( $class );
95
-		$collection = $repository->find_by( $params );
93
+	public function find_by($class, $params = array()) {
94
+		$repository = $this->get_repository($class);
95
+		$collection = $repository->find_by($params);
96 96
 
97
-		foreach ( $collection as $model ) {
98
-			$this->handle_model( $repository, $model );
97
+		foreach ($collection as $model) {
98
+			$this->handle_model($repository, $model);
99 99
 		}
100 100
 
101 101
 		return $collection;
@@ -109,11 +109,11 @@  discard block
 block discarded – undo
109 109
 	 *
110 110
 	 * @return Model|WP_Error
111 111
 	 */
112
-	public function create( $class, $data = array() ) {
113
-		$repository = $this->get_repository( $class );
114
-		$model      = $repository->create( $data );
112
+	public function create($class, $data = array()) {
113
+		$repository = $this->get_repository($class);
114
+		$model      = $repository->create($data);
115 115
 
116
-		$this->handle_model( $repository, $model );
116
+		$this->handle_model($repository, $model);
117 117
 
118 118
 		return $model;
119 119
 	}
@@ -125,8 +125,8 @@  discard block
 block discarded – undo
125 125
 	 *
126 126
 	 * @return Model|WP_Error
127 127
 	 */
128
-	public function persist( Model $model ) {
129
-		return $this->get_repository( get_class( $model ) )->persist( $model );
128
+	public function persist(Model $model) {
129
+		return $this->get_repository(get_class($model))->persist($model);
130 130
 	}
131 131
 
132 132
 	/**
@@ -137,8 +137,8 @@  discard block
 block discarded – undo
137 137
 	 *
138 138
 	 * @return Model|WP_Error
139 139
 	 */
140
-	public function delete( Model $model, $force = false ) {
141
-		return $this->get_repository( get_class( $model ) )->delete( $model, $force );
140
+	public function delete(Model $model, $force = false) {
141
+		return $this->get_repository(get_class($model))->delete($model, $force);
142 142
 	}
143 143
 
144 144
 	/**
@@ -184,30 +184,30 @@  discard block
 block discarded – undo
184 184
 	 *
185 185
 	 * @throws LogicException
186 186
 	 */
187
-	protected function get_repository( $class ) {
187
+	protected function get_repository($class) {
188 188
 		// We can only use Axolotl models.
189
-		if ( ! is_subclass_of( $class, 'Intraxia\Jaxion\Axolotl\Model' ) ) {
189
+		if (!is_subclass_of($class, 'Intraxia\Jaxion\Axolotl\Model')) {
190 190
 			throw new LogicException;
191 191
 		}
192 192
 
193
-		if ( is_subclass_of(
193
+		if (is_subclass_of(
194 194
 			$class,
195 195
 			'Intraxia\Jaxion\Contract\Axolotl\UsesWordPressPost'
196
-		) ) {
197
-			return new WordPressPostRepository( $this, $class );
196
+		)) {
197
+			return new WordPressPostRepository($this, $class);
198 198
 		}
199 199
 
200
-		if ( is_subclass_of(
200
+		if (is_subclass_of(
201 201
 			$class,
202 202
 			'Intraxia\Jaxion\Contract\Axolotl\UsesWordPressTerm'
203
-		) ) {
204
-			return new WordPressTermRepository( $this, $class );
203
+		)) {
204
+			return new WordPressTermRepository($this, $class);
205 205
 		}
206 206
 
207
-		if ( is_subclass_of(
207
+		if (is_subclass_of(
208 208
 			$class,
209 209
 			'Intraxia\Jaxion\Contract\Axolotl\UsesCustomTable'
210
-		) ) {
210
+		)) {
211 211
 			throw new LogicException;
212 212
 		}
213 213
 
@@ -222,11 +222,11 @@  discard block
 block discarded – undo
222 222
 	 * @param AbstractRepository $repository
223 223
 	 * @param Model              $model
224 224
 	 */
225
-	protected function handle_model( AbstractRepository $repository, Model $model ) {
226
-		$repository->register_model( $model );
225
+	protected function handle_model(AbstractRepository $repository, Model $model) {
226
+		$repository->register_model($model);
227 227
 
228
-		if ( $model instanceof HasEagerRelationships ) {
229
-			$this->fill_related( $model, $model::get_eager_relationships() );
228
+		if ($model instanceof HasEagerRelationships) {
229
+			$this->fill_related($model, $model::get_eager_relationships());
230 230
 		}
231 231
 	}
232 232
 
@@ -240,17 +240,17 @@  discard block
 block discarded – undo
240 240
 	 *
241 241
 	 * @throws LogicException
242 242
 	 */
243
-	protected function fill_related( Model $model, array $relations = array() ) {
244
-		if ( ! $relations ) {
243
+	protected function fill_related(Model $model, array $relations = array()) {
244
+		if (!$relations) {
245 245
 			$relations = $model->get_related_keys();
246 246
 		}
247 247
 
248
-		foreach ( $relations as $relation ) {
249
-			if ( ! in_array( $relation, $model->get_related_keys() ) ) {
248
+		foreach ($relations as $relation) {
249
+			if (!in_array($relation, $model->get_related_keys())) {
250 250
 				throw new LogicException;
251 251
 			}
252 252
 
253
-			if ( $model->relation_is_filled( $relation ) ) {
253
+			if ($model->relation_is_filled($relation)) {
254 254
 				continue;
255 255
 			}
256 256
 
@@ -260,7 +260,7 @@  discard block
 block discarded – undo
260 260
 			 * @var Relationship $relation
261 261
 			 */
262 262
 			$relation = $model->{"related_{$relation}"}();
263
-			$relation->attach_relation( $this );
263
+			$relation->attach_relation($this);
264 264
 		}
265 265
 	}
266 266
 }
Please login to merge, or discard this patch.
src/Axolotl/Model.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -825,7 +825,7 @@
 block discarded – undo
825 825
 	 * @param string $type
826 826
 	 * @param string $local_key
827 827
 	 *
828
-	 * @return HasMany
828
+	 * @return BelongsToOne
829 829
 	 */
830 830
 	protected function belongs_to_one( $class, $type, $local_key = '' ) {
831 831
 		return new BelongsToOne( $this, $class, $type, $local_key );
Please login to merge, or discard this patch.
Indentation   +843 added lines, -843 removed lines patch added patch discarded remove patch
@@ -23,847 +23,847 @@
 block discarded – undo
23 23
  * @since      0.1.0
24 24
  */
25 25
 abstract class Model implements Serializes {
26
-	/**
27
-	 * Memoized values for class methods.
28
-	 *
29
-	 * @var array
30
-	 */
31
-	private static $memo = array();
32
-
33
-	/**
34
-	 * Model attributes.
35
-	 *
36
-	 * @var array
37
-	 */
38
-	private $attributes = array(
39
-		'table'  => array(),
40
-		'object' => null,
41
-	);
42
-
43
-	/**
44
-	 * Model's original attributes.
45
-	 *
46
-	 * @var array
47
-	 */
48
-	private $original = array(
49
-		'table'  => array(),
50
-		'object' => null,
51
-	);
52
-
53
-	/**
54
-	 * Properties which are allowed to be set on the model.
55
-	 *
56
-	 * If this array is empty, any attributes can be set on the model.
57
-	 *
58
-	 * @var string[]
59
-	 */
60
-	protected $fillable = array();
61
-
62
-	/**
63
-	 * Properties which cannot be automatically filled on the model.
64
-	 *
65
-	 * If the model is unguarded, these properties can be filled.
66
-	 *
67
-	 * @var array
68
-	 */
69
-	protected $guarded = array();
70
-
71
-	/**
72
-	 * Properties which should not be serialized.
73
-	 *
74
-	 * @var array
75
-	 */
76
-	protected $hidden = array();
77
-
78
-	/**
79
-	 * Properties which should be serialized.
80
-	 *
81
-	 * @var array
82
-	 */
83
-	protected $visible = array();
84
-
85
-	/**
86
-	 * Relations saved on the Model.
87
-	 *
88
-	 * @var array
89
-	 */
90
-	protected $related = 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
-	 * Whether the Model is having its relations filled.
103
-	 *
104
-	 * @var bool
105
-	 */
106
-	protected $filling = false;
107
-
108
-	/**
109
-	 * Constructs a new model with provided attributes.
110
-	 *
111
-	 * If 'object' is passed as one of the attributes, the underlying post
112
-	 * will be overwritten.
113
-	 *
114
-	 * @param array <string, mixed> $attributes
115
-	 */
116
-	public function __construct( array $attributes = array() ) {
117
-		$this->maybe_boot();
118
-		$this->sync_original();
119
-
120
-		if ( $this->uses_wp_object() ) {
121
-			$this->create_wp_object();
122
-		}
123
-
124
-		$this->refresh( $attributes );
125
-	}
126
-
127
-	/**
128
-	 * Refreshes the model's current attributes with the provided array.
129
-	 *
130
-	 * The model's attributes will match what was provided in the array,
131
-	 * and any attributes not passed
132
-	 *
133
-	 * @param array $attributes
134
-	 *
135
-	 * @return $this
136
-	 */
137
-	public function refresh( array $attributes ) {
138
-		$this->clear();
139
-
140
-		return $this->merge( $attributes );
141
-	}
142
-
143
-	/**
144
-	 * Merges the provided attributes with the provided array.
145
-	 *
146
-	 *
147
-	 *
148
-	 * @param array $attributes
149
-	 *
150
-	 * @return $this
151
-	 */
152
-	public function merge( array $attributes ) {
153
-		foreach ( $attributes as $name => $value ) {
154
-			$this->set_attribute( $name, $value );
155
-		}
156
-
157
-		return $this;
158
-	}
159
-
160
-	/**
161
-	 * Get the model's table attributes.
162
-	 *
163
-	 * Returns the array of for the model that will either need to be
164
-	 * saved in postmeta or a separate table.
165
-	 *
166
-	 * @return array
167
-	 */
168
-	public function get_table_attributes() {
169
-		return $this->attributes['table'];
170
-	}
171
-
172
-	/**
173
-	 * Get the model's original attributes.
174
-	 *
175
-	 * @return array
176
-	 */
177
-	public function get_original_table_attributes() {
178
-		return $this->original['table'];
179
-	}
180
-
181
-	/**
182
-	 * Retrieve an array of the attributes on the model
183
-	 * that have changed compared to the model's
184
-	 * original data.
185
-	 *
186
-	 * @return array
187
-	 */
188
-	public function get_changed_table_attributes() {
189
-		$changed = array();
190
-
191
-		foreach ( $this->get_table_attributes() as $attribute ) {
192
-			if ( $this->get_attribute( $attribute ) !==
193
-			     $this->get_original_attribute( $attribute )
194
-			) {
195
-				$changed[ $attribute ] = $this->get_attribute( $attribute );
196
-			}
197
-		}
198
-
199
-		return $changed;
200
-	}
201
-
202
-	/**
203
-	 * Get the model's underlying post.
204
-	 *
205
-	 * Returns the underlying WP_Post object for the model, representing
206
-	 * the data that will be save in the wp_posts table.
207
-	 *
208
-	 * @return false|WP_Post|WP_Term
209
-	 */
210
-	public function get_underlying_wp_object() {
211
-		if ( isset( $this->attributes['object'] ) ) {
212
-			return $this->attributes['object'];
213
-		}
214
-
215
-		return false;
216
-	}
217
-
218
-	/**
219
-	 * Get the model's original underlying post.
220
-	 *
221
-	 * @return WP_Post
222
-	 */
223
-	public function get_original_underlying_wp_object() {
224
-		return $this->original['object'];
225
-	}
226
-
227
-	/**
228
-	 * Get the model attributes on the WordPress object
229
-	 * that have changed compared to the model's
230
-	 * original attributes.
231
-	 *
232
-	 * @return array
233
-	 */
234
-	public function get_changed_wp_object_attributes() {
235
-		$changed = array();
236
-
237
-		foreach ( $this->get_wp_object_keys() as $key ) {
238
-			if ( $this->get_attribute( $key ) !==
239
-			     $this->get_original_attribute( $key )
240
-			) {
241
-				$changed[ $key ] = $this->get_attribute( $key );
242
-			}
243
-		}
244
-
245
-		return $changed;
246
-	}
247
-
248
-	/**
249
-	 * Magic __set method.
250
-	 *
251
-	 * Passes the name and value to set_attribute, which is where the magic happens.
252
-	 *
253
-	 * @param string $name
254
-	 * @param mixed  $value
255
-	 */
256
-	public function __set( $name, $value ) {
257
-		$this->set_attribute( $name, $value );
258
-	}
259
-
260
-	/**
261
-	 * Sets the model attributes.
262
-	 *
263
-	 * Checks whether the model attribute can be set, check if it
264
-	 * maps to the WP_Post property, otherwise, assigns it to the
265
-	 * table attribute array.
266
-	 *
267
-	 * @param string $name
268
-	 * @param mixed  $value
269
-	 *
270
-	 * @return $this
271
-	 *
272
-	 * @throws GuardedPropertyException
273
-	 */
274
-	public function set_attribute( $name, $value ) {
275
-		if ( 'object' === $name ) {
276
-			return $this->override_wp_object( $value );
277
-		}
278
-
279
-		if ( ! $this->is_fillable( $name ) ) {
280
-			throw new GuardedPropertyException;
281
-		}
282
-
283
-		if ( $method = $this->has_map_method( $name ) ) {
284
-			$this->attributes['object']->{$this->{$method}()} = $value;
285
-		} else {
286
-			$this->attributes['table'][ $name ] = $value;
287
-		}
288
-
289
-		return $this;
290
-	}
291
-
292
-	/**
293
-	 * Retrieves all the attribute keys for the model.
294
-	 *
295
-	 * @return array
296
-	 */
297
-	public function get_attribute_keys() {
298
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
299
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
300
-		}
301
-
302
-		return self::$memo[ get_called_class() ][ __METHOD__ ]
303
-			= array_merge(
304
-				$this->fillable,
305
-				$this->guarded,
306
-				$this->get_compute_methods(),
307
-				$this->get_related_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
-			     ! $this->has_related_method( $key )
327
-			) {
328
-				$keys[] = $key;
329
-			}
330
-		}
331
-
332
-		return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
333
-	}
334
-
335
-	/**
336
-	 * Retrieves the attribute keys that are mapped to a post.
337
-	 *
338
-	 * @return array
339
-	 */
340
-	public function get_wp_object_keys() {
341
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
342
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
343
-		}
344
-
345
-		$keys = array();
346
-
347
-		foreach ( $this->get_attribute_keys() as $key ) {
348
-			if ( $this->has_map_method( $key ) ) {
349
-				$keys[] = $key;
350
-			}
351
-		}
352
-
353
-		return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
354
-	}
355
-
356
-	/**
357
-	 * Returns the model's keys that are computed at call time.
358
-	 *
359
-	 * @return array
360
-	 */
361
-	public function get_computed_keys() {
362
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
363
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
364
-		}
365
-
366
-		$keys = array();
367
-
368
-		foreach ( $this->get_attribute_keys() as $key ) {
369
-			if ( $this->has_compute_method( $key ) ) {
370
-				$keys[] = $key;
371
-			}
372
-		}
373
-
374
-		return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
375
-	}
376
-
377
-	/**
378
-	 * Returns the model's keys that are related to other Models.
379
-	 *
380
-	 * @return array
381
-	 */
382
-	public function get_related_keys() {
383
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
384
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
385
-		}
386
-
387
-		$keys = array();
388
-
389
-		foreach ( $this->get_attribute_keys() as $key ) {
390
-			if ( $this->has_related_method( $key ) ) {
391
-				$keys[] = $key;
392
-			}
393
-		}
394
-
395
-		return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
396
-	}
397
-
398
-	/**
399
-	 * Serializes the model's public data into an array.
400
-	 *
401
-	 * @return array
402
-	 */
403
-	public function serialize() {
404
-		$attributes = array();
405
-
406
-		if ( $this->visible ) {
407
-			// If visible attributes are set, we'll only reveal those.
408
-			foreach ( $this->visible as $key ) {
409
-				$attributes[ $key ] = $this->get_attribute( $key );
410
-			}
411
-		} elseif ( $this->hidden ) {
412
-			// If hidden attributes are set, we'll grab everything and hide those.
413
-			foreach ( $this->get_attribute_keys() as $key ) {
414
-				if ( ! in_array( $key, $this->hidden ) ) {
415
-					$attributes[ $key ] = $this->get_attribute( $key );
416
-				}
417
-			}
418
-		} else {
419
-			// If nothing is hidden/visible, we'll grab and reveal everything.
420
-			foreach ( $this->get_attribute_keys() as $key ) {
421
-				$attributes[ $key ] = $this->get_attribute( $key );
422
-			}
423
-		}
424
-
425
-		return array_map( function ( $attribute ) {
426
-			if ( $attribute instanceof Serializes ) {
427
-				return $attribute->serialize();
428
-			}
429
-
430
-			return $attribute;
431
-		}, $attributes );
432
-	}
433
-
434
-	/**
435
-	 * Syncs the current attributes to the model's original.
436
-	 *
437
-	 * @return $this
438
-	 */
439
-	public function sync_original() {
440
-		$this->original = $this->attributes;
441
-
442
-		if ( $this->attributes['object'] ) {
443
-			$this->original['object'] = clone $this->attributes['object'];
444
-		}
445
-
446
-		return $this;
447
-	}
448
-
449
-	/**
450
-	 * Checks if a given attribute is mass-fillable.
451
-	 *
452
-	 * Returns true if the attribute can be filled, false if it can't.
453
-	 *
454
-	 * @param string $name
455
-	 *
456
-	 * @return bool
457
-	 */
458
-	private function is_fillable( $name ) {
459
-		// If this model isn't guarded, everything is fillable.
460
-		if ( ! $this->is_guarded ) {
461
-			return true;
462
-		}
463
-
464
-		// If it's in the fillable array, then it's fillable.
465
-		if ( in_array( $name, $this->fillable ) ) {
466
-			return true;
467
-		}
468
-
469
-		// If it's explicitly guarded, then it's not fillable.
470
-		if ( in_array( $name, $this->guarded ) ) {
471
-			return false;
472
-		}
473
-
474
-		// If fillable hasn't been defined, then everything else fillable.
475
-		return ! $this->fillable;
476
-	}
477
-
478
-	/**
479
-	 * Overrides the current WP_Post with a provided one.
480
-	 *
481
-	 * Resets the post's default values and stores it in the attributes.
482
-	 *
483
-	 * @param WP_Post $value
484
-	 *
485
-	 * @return $this
486
-	 */
487
-	private function override_wp_object( $value ) {
488
-		$this->attributes['object'] = $this->set_wp_object_constants( $value );
489
-
490
-		return $this;
491
-	}
492
-
493
-	/**
494
-	 * Create and set with a new blank post.
495
-	 *
496
-	 * Creates a new WP_Post object, assigns it the default attributes,
497
-	 * and stores it in the attributes.
498
-	 *
499
-	 * @throws LogicException
500
-	 */
501
-	private function create_wp_object() {
502
-		switch ( true ) {
503
-			case $this instanceof UsesWordPressPost:
504
-				$object = new WP_Post( (object) array() );
505
-				break;
506
-			case $this instanceof UsesWordPressTerm:
507
-				$object = new WP_Term( (object) array() );
508
-				break;
509
-			default:
510
-				throw new LogicException;
511
-				break;
512
-		}
513
-
514
-		$this->attributes['object'] = $this->set_wp_object_constants( $object );
515
-	}
516
-
517
-	/**
518
-	 * Enforces values on the post that can't change.
519
-	 *
520
-	 * Primarily, this is used to make sure the post_type always maps
521
-	 * to the model's "$type" property, but this can all be overridden
522
-	 * by the developer to enforce other values in the model.
523
-	 *
524
-	 * @param object $object
525
-	 *
526
-	 * @return object
527
-	 */
528
-	protected function set_wp_object_constants( $object ) {
529
-		if ( $this instanceof UsesWordPressPost ) {
530
-			$object->post_type = $this::get_post_type();
531
-		}
532
-
533
-		if ( $this instanceof UsesWordPressTerm ) {
534
-			$object->taxonomy = $this::get_taxonomy();
535
-		}
536
-
537
-		return $object;
538
-	}
539
-
540
-	/**
541
-	 * Magic __get method.
542
-	 *
543
-	 * Passes the name and value to get_attribute, which is where the magic happens.
544
-	 *
545
-	 * @param string $name
546
-	 *
547
-	 * @return mixed
548
-	 */
549
-	public function __get( $name ) {
550
-		return $this->get_attribute( $name );
551
-	}
552
-
553
-	/**
554
-	 * Retrieves the model attribute.
555
-	 *
556
-	 * @param string $name
557
-	 *
558
-	 * @return mixed
559
-	 *
560
-	 * @throws PropertyDoesNotExistException If property isn't found.
561
-	 */
562
-	public function get_attribute( $name ) {
563
-		if ( $method = $this->has_map_method( $name ) ) {
564
-			$value = $this->attributes['object']->{$this->{$method}()};
565
-		} elseif ( $method = $this->has_compute_method( $name ) ) {
566
-			$value = $this->{$method}();
567
-		} else if ( $method = $this->has_related_method( $name ) ) {
568
-			$value = $this->get_related( $this->{$method}()->get_sha() );
569
-		} else {
570
-			if ( ! isset( $this->attributes['table'][ $name ] ) ) {
571
-				throw new PropertyDoesNotExistException;
572
-			}
573
-
574
-			$value = $this->attributes['table'][ $name ];
575
-		}
576
-
577
-		return $value;
578
-	}
579
-
580
-	/**
581
-	 * Retrieve the model's original attribute value.
582
-	 *
583
-	 * @param string $name
584
-	 *
585
-	 * @return mixed
586
-	 *
587
-	 * @throws PropertyDoesNotExistException If property isn't found.
588
-	 */
589
-	public function get_original_attribute( $name ) {
590
-		$original = new static( $this->original );
591
-
592
-		return $original->get_attribute( $name );
593
-	}
594
-
595
-	/**
596
-	 * Fetches the Model's primary ID, depending on the model
597
-	 * implementation.
598
-	 *
599
-	 * @return int
600
-	 *
601
-	 * @throws LogicException
602
-	 */
603
-	public function get_primary_id() {
604
-		if ( $this instanceof UsesWordPressPost ) {
605
-			return $this->get_underlying_wp_object()->ID;
606
-		}
607
-
608
-		if ( $this instanceof UsesWordPressTerm ) {
609
-			return $this->get_underlying_wp_object()->term_id;
610
-		}
611
-
612
-		// Model w/o wp_object not yet supported.
613
-		throw new LogicException;
614
-	}
615
-
616
-	/**
617
-	 * Generates the table foreign key, depending on the model
618
-	 * implementation.
619
-	 *
620
-	 * @return string
621
-	 *
622
-	 * @throws LogicException
623
-	 */
624
-	public function get_foreign_key() {
625
-		if ( $this instanceof UsesWordPressPost ) {
626
-			return 'post_id';
627
-		}
628
-
629
-		// Model w/o wp_object not yet supported.
630
-		throw new LogicException;
631
-	}
632
-
633
-	/**
634
-	 * Gets the related Model or Collection for the given sha.
635
-	 *
636
-	 * @param string $sha
637
-	 *
638
-	 * @return Model|Collection
639
-	 */
640
-	public function get_related( $sha ) {
641
-		return $this->related[ $sha ];
642
-	}
643
-
644
-	/**
645
-	 * Sets the related Model or Collection for the given sha.
646
-	 *
647
-	 * @param string           $sha
648
-	 * @param Model|Collection $target
649
-	 *
650
-	 * @throws RuntimeException
651
-	 */
652
-	public function set_related( $sha, $target ) {
653
-		if ( ! ( $target instanceof Model ) && ! ( $target instanceof Collection ) ) {
654
-			throw new RuntimeException;
655
-		}
656
-
657
-		$this->related[ $sha ] = $target;
658
-	}
659
-
660
-	/**
661
-	 * Checks whether the attribute has a map method.
662
-	 *
663
-	 * This is used to determine whether the attribute maps to a
664
-	 * property on the underlying WP_Post object. Returns the
665
-	 * method if one exists, returns false if it doesn't.
666
-	 *
667
-	 * @param string $name
668
-	 *
669
-	 * @return false|string
670
-	 */
671
-	protected function has_map_method( $name ) {
672
-		if ( method_exists( $this, $method = "map_{$name}" ) ) {
673
-			return $method;
674
-		}
675
-
676
-		return false;
677
-	}
678
-
679
-	/**
680
-	 * Checks whether the attribute has a compute method.
681
-	 *
682
-	 * This is used to determine if the attribute should be computed
683
-	 * from other attributes.
684
-	 *
685
-	 * @param string $name
686
-	 *
687
-	 * @return false|string
688
-	 */
689
-	protected function has_compute_method( $name ) {
690
-		if ( method_exists( $this, $method = "compute_{$name}" ) ) {
691
-			return $method;
692
-		}
693
-
694
-		return false;
695
-	}
696
-
697
-	/**
698
-	 * Checks whether the attribute has a compute method.
699
-	 *
700
-	 * This is used to determine if the attribute should be computed
701
-	 * from other attributes.
702
-	 *
703
-	 * @param string $name
704
-	 *
705
-	 * @return false|string
706
-	 */
707
-	protected function has_related_method( $name ) {
708
-		if ( method_exists( $this, $method = "related_{$name}" ) ) {
709
-			return $method;
710
-		}
711
-
712
-		return false;
713
-	}
714
-
715
-	/**
716
-	 * Clears all the current attributes from the model.
717
-	 *
718
-	 * This does not touch the model's original attributes, and will
719
-	 * only clear fillable attributes, unless the model is unguarded.
720
-	 *
721
-	 * @return $this
722
-	 */
723
-	public function clear() {
724
-		$keys = $this->get_attribute_keys();
725
-
726
-		foreach ( $keys as $key ) {
727
-			try {
728
-				$this->set_attribute( $key, null );
729
-			} catch ( GuardedPropertyException $e ) {
730
-				// We won't clear out guarded attributes.
731
-			}
732
-		}
733
-
734
-		return $this;
735
-	}
736
-
737
-	/**
738
-	 * Unguards the model.
739
-	 *
740
-	 * Sets the model to be unguarded, allowing the filling of
741
-	 * guarded attributes.
742
-	 */
743
-	public function unguard() {
744
-		$this->is_guarded = false;
745
-	}
746
-
747
-	/**
748
-	 * Reguards the model.
749
-	 *
750
-	 * Sets the model to be guarded, preventing filling of
751
-	 * guarded attributes.
752
-	 */
753
-	public function reguard() {
754
-		$this->is_guarded = true;
755
-	}
756
-
757
-	/**
758
-	 * Retrieves all the compute methods on the model.
759
-	 *
760
-	 * @return array
761
-	 */
762
-	protected function get_compute_methods() {
763
-		$methods = get_class_methods( get_called_class() );
764
-		$methods = array_filter( $methods, function ( $method ) {
765
-			return strrpos( $method, 'compute_', - strlen( $method ) ) !== false;
766
-		} );
767
-		$methods = array_map( function ( $method ) {
768
-			return substr( $method, strlen( 'compute_' ) );
769
-		}, $methods );
770
-
771
-		return $methods;
772
-	}
773
-
774
-	/**
775
-	 * Retrieves all the related methods on the model.
776
-	 *
777
-	 * @return array
778
-	 */
779
-	protected function get_related_methods() {
780
-		$methods = get_class_methods( get_called_class() );
781
-		$methods = array_filter( $methods, function ( $method ) {
782
-			return strrpos( $method, 'related_', - strlen( $method ) ) !== false;
783
-		} );
784
-		$methods = array_map( function ( $method ) {
785
-			return substr( $method, strlen( 'related_' ) );
786
-		}, $methods );
787
-
788
-		return $methods;
789
-	}
790
-
791
-	/**
792
-	 * Returns whether this relation has already been filled on the model.
793
-	 *
794
-	 * @param string $relation
795
-	 *
796
-	 * @return bool
797
-	 */
798
-	public function relation_is_filled( $relation ) {
799
-		$sha = $this
800
-			->{$this->has_related_method( $relation )}()
801
-			->get_sha();
802
-
803
-		return isset( $this->related[ $sha ] );
804
-	}
805
-
806
-	/**
807
-	 * Returns whether the Model is currently having
808
-	 * its relationships filled.
809
-	 *
810
-	 * @return bool
811
-	 */
812
-	public function is_filling() {
813
-		return $this->filling;
814
-	}
815
-
816
-	/**
817
-	 * Sets whether the Model is having its relationships filled.
818
-	 *
819
-	 * @param bool $is_filling
820
-	 */
821
-	public function set_filling( $is_filling ) {
822
-		$this->filling = $is_filling;
823
-	}
824
-
825
-	/**
826
-	 * Returns a HasMany relationship for the model.
827
-	 *
828
-	 * @param string $class
829
-	 * @param string $type
830
-	 * @param string $foreign_key
831
-	 *
832
-	 * @return HasMany
833
-	 */
834
-	protected function has_many( $class, $type, $foreign_key ) {
835
-		return new HasMany( $this, $class, $type, $foreign_key );
836
-	}
837
-
838
-	/**
839
-	 * Returns a BelongsToOne relationship for the model.
840
-	 *
841
-	 * @param string $class
842
-	 * @param string $type
843
-	 * @param string $local_key
844
-	 *
845
-	 * @return HasMany
846
-	 */
847
-	protected function belongs_to_one( $class, $type, $local_key = '' ) {
848
-		return new BelongsToOne( $this, $class, $type, $local_key );
849
-	}
850
-
851
-	/**
852
-	 * Sets up the memo array for the creating model.
853
-	 */
854
-	private function maybe_boot() {
855
-		if ( ! isset( self::$memo[ get_called_class() ] ) ) {
856
-			self::$memo[ get_called_class() ] = array();
857
-		}
858
-	}
859
-
860
-	/**
861
-	 * Whether this Model uses an underlying WordPress object.
862
-	 *
863
-	 * @return bool
864
-	 */
865
-	protected function uses_wp_object() {
866
-		return $this instanceof UsesWordPressPost ||
867
-			$this instanceof UsesWordPressTerm;
868
-	}
26
+    /**
27
+     * Memoized values for class methods.
28
+     *
29
+     * @var array
30
+     */
31
+    private static $memo = array();
32
+
33
+    /**
34
+     * Model attributes.
35
+     *
36
+     * @var array
37
+     */
38
+    private $attributes = array(
39
+        'table'  => array(),
40
+        'object' => null,
41
+    );
42
+
43
+    /**
44
+     * Model's original attributes.
45
+     *
46
+     * @var array
47
+     */
48
+    private $original = array(
49
+        'table'  => array(),
50
+        'object' => null,
51
+    );
52
+
53
+    /**
54
+     * Properties which are allowed to be set on the model.
55
+     *
56
+     * If this array is empty, any attributes can be set on the model.
57
+     *
58
+     * @var string[]
59
+     */
60
+    protected $fillable = array();
61
+
62
+    /**
63
+     * Properties which cannot be automatically filled on the model.
64
+     *
65
+     * If the model is unguarded, these properties can be filled.
66
+     *
67
+     * @var array
68
+     */
69
+    protected $guarded = array();
70
+
71
+    /**
72
+     * Properties which should not be serialized.
73
+     *
74
+     * @var array
75
+     */
76
+    protected $hidden = array();
77
+
78
+    /**
79
+     * Properties which should be serialized.
80
+     *
81
+     * @var array
82
+     */
83
+    protected $visible = array();
84
+
85
+    /**
86
+     * Relations saved on the Model.
87
+     *
88
+     * @var array
89
+     */
90
+    protected $related = 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
+     * Whether the Model is having its relations filled.
103
+     *
104
+     * @var bool
105
+     */
106
+    protected $filling = false;
107
+
108
+    /**
109
+     * Constructs a new model with provided attributes.
110
+     *
111
+     * If 'object' is passed as one of the attributes, the underlying post
112
+     * will be overwritten.
113
+     *
114
+     * @param array <string, mixed> $attributes
115
+     */
116
+    public function __construct( array $attributes = array() ) {
117
+        $this->maybe_boot();
118
+        $this->sync_original();
119
+
120
+        if ( $this->uses_wp_object() ) {
121
+            $this->create_wp_object();
122
+        }
123
+
124
+        $this->refresh( $attributes );
125
+    }
126
+
127
+    /**
128
+     * Refreshes the model's current attributes with the provided array.
129
+     *
130
+     * The model's attributes will match what was provided in the array,
131
+     * and any attributes not passed
132
+     *
133
+     * @param array $attributes
134
+     *
135
+     * @return $this
136
+     */
137
+    public function refresh( array $attributes ) {
138
+        $this->clear();
139
+
140
+        return $this->merge( $attributes );
141
+    }
142
+
143
+    /**
144
+     * Merges the provided attributes with the provided array.
145
+     *
146
+     *
147
+     *
148
+     * @param array $attributes
149
+     *
150
+     * @return $this
151
+     */
152
+    public function merge( array $attributes ) {
153
+        foreach ( $attributes as $name => $value ) {
154
+            $this->set_attribute( $name, $value );
155
+        }
156
+
157
+        return $this;
158
+    }
159
+
160
+    /**
161
+     * Get the model's table attributes.
162
+     *
163
+     * Returns the array of for the model that will either need to be
164
+     * saved in postmeta or a separate table.
165
+     *
166
+     * @return array
167
+     */
168
+    public function get_table_attributes() {
169
+        return $this->attributes['table'];
170
+    }
171
+
172
+    /**
173
+     * Get the model's original attributes.
174
+     *
175
+     * @return array
176
+     */
177
+    public function get_original_table_attributes() {
178
+        return $this->original['table'];
179
+    }
180
+
181
+    /**
182
+     * Retrieve an array of the attributes on the model
183
+     * that have changed compared to the model's
184
+     * original data.
185
+     *
186
+     * @return array
187
+     */
188
+    public function get_changed_table_attributes() {
189
+        $changed = array();
190
+
191
+        foreach ( $this->get_table_attributes() as $attribute ) {
192
+            if ( $this->get_attribute( $attribute ) !==
193
+                    $this->get_original_attribute( $attribute )
194
+            ) {
195
+                $changed[ $attribute ] = $this->get_attribute( $attribute );
196
+            }
197
+        }
198
+
199
+        return $changed;
200
+    }
201
+
202
+    /**
203
+     * Get the model's underlying post.
204
+     *
205
+     * Returns the underlying WP_Post object for the model, representing
206
+     * the data that will be save in the wp_posts table.
207
+     *
208
+     * @return false|WP_Post|WP_Term
209
+     */
210
+    public function get_underlying_wp_object() {
211
+        if ( isset( $this->attributes['object'] ) ) {
212
+            return $this->attributes['object'];
213
+        }
214
+
215
+        return false;
216
+    }
217
+
218
+    /**
219
+     * Get the model's original underlying post.
220
+     *
221
+     * @return WP_Post
222
+     */
223
+    public function get_original_underlying_wp_object() {
224
+        return $this->original['object'];
225
+    }
226
+
227
+    /**
228
+     * Get the model attributes on the WordPress object
229
+     * that have changed compared to the model's
230
+     * original attributes.
231
+     *
232
+     * @return array
233
+     */
234
+    public function get_changed_wp_object_attributes() {
235
+        $changed = array();
236
+
237
+        foreach ( $this->get_wp_object_keys() as $key ) {
238
+            if ( $this->get_attribute( $key ) !==
239
+                    $this->get_original_attribute( $key )
240
+            ) {
241
+                $changed[ $key ] = $this->get_attribute( $key );
242
+            }
243
+        }
244
+
245
+        return $changed;
246
+    }
247
+
248
+    /**
249
+     * Magic __set method.
250
+     *
251
+     * Passes the name and value to set_attribute, which is where the magic happens.
252
+     *
253
+     * @param string $name
254
+     * @param mixed  $value
255
+     */
256
+    public function __set( $name, $value ) {
257
+        $this->set_attribute( $name, $value );
258
+    }
259
+
260
+    /**
261
+     * Sets the model attributes.
262
+     *
263
+     * Checks whether the model attribute can be set, check if it
264
+     * maps to the WP_Post property, otherwise, assigns it to the
265
+     * table attribute array.
266
+     *
267
+     * @param string $name
268
+     * @param mixed  $value
269
+     *
270
+     * @return $this
271
+     *
272
+     * @throws GuardedPropertyException
273
+     */
274
+    public function set_attribute( $name, $value ) {
275
+        if ( 'object' === $name ) {
276
+            return $this->override_wp_object( $value );
277
+        }
278
+
279
+        if ( ! $this->is_fillable( $name ) ) {
280
+            throw new GuardedPropertyException;
281
+        }
282
+
283
+        if ( $method = $this->has_map_method( $name ) ) {
284
+            $this->attributes['object']->{$this->{$method}()} = $value;
285
+        } else {
286
+            $this->attributes['table'][ $name ] = $value;
287
+        }
288
+
289
+        return $this;
290
+    }
291
+
292
+    /**
293
+     * Retrieves all the attribute keys for the model.
294
+     *
295
+     * @return array
296
+     */
297
+    public function get_attribute_keys() {
298
+        if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
299
+            return self::$memo[ get_called_class() ][ __METHOD__ ];
300
+        }
301
+
302
+        return self::$memo[ get_called_class() ][ __METHOD__ ]
303
+            = array_merge(
304
+                $this->fillable,
305
+                $this->guarded,
306
+                $this->get_compute_methods(),
307
+                $this->get_related_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
+                 ! $this->has_related_method( $key )
327
+            ) {
328
+                $keys[] = $key;
329
+            }
330
+        }
331
+
332
+        return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
333
+    }
334
+
335
+    /**
336
+     * Retrieves the attribute keys that are mapped to a post.
337
+     *
338
+     * @return array
339
+     */
340
+    public function get_wp_object_keys() {
341
+        if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
342
+            return self::$memo[ get_called_class() ][ __METHOD__ ];
343
+        }
344
+
345
+        $keys = array();
346
+
347
+        foreach ( $this->get_attribute_keys() as $key ) {
348
+            if ( $this->has_map_method( $key ) ) {
349
+                $keys[] = $key;
350
+            }
351
+        }
352
+
353
+        return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
354
+    }
355
+
356
+    /**
357
+     * Returns the model's keys that are computed at call time.
358
+     *
359
+     * @return array
360
+     */
361
+    public function get_computed_keys() {
362
+        if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
363
+            return self::$memo[ get_called_class() ][ __METHOD__ ];
364
+        }
365
+
366
+        $keys = array();
367
+
368
+        foreach ( $this->get_attribute_keys() as $key ) {
369
+            if ( $this->has_compute_method( $key ) ) {
370
+                $keys[] = $key;
371
+            }
372
+        }
373
+
374
+        return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
375
+    }
376
+
377
+    /**
378
+     * Returns the model's keys that are related to other Models.
379
+     *
380
+     * @return array
381
+     */
382
+    public function get_related_keys() {
383
+        if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
384
+            return self::$memo[ get_called_class() ][ __METHOD__ ];
385
+        }
386
+
387
+        $keys = array();
388
+
389
+        foreach ( $this->get_attribute_keys() as $key ) {
390
+            if ( $this->has_related_method( $key ) ) {
391
+                $keys[] = $key;
392
+            }
393
+        }
394
+
395
+        return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
396
+    }
397
+
398
+    /**
399
+     * Serializes the model's public data into an array.
400
+     *
401
+     * @return array
402
+     */
403
+    public function serialize() {
404
+        $attributes = array();
405
+
406
+        if ( $this->visible ) {
407
+            // If visible attributes are set, we'll only reveal those.
408
+            foreach ( $this->visible as $key ) {
409
+                $attributes[ $key ] = $this->get_attribute( $key );
410
+            }
411
+        } elseif ( $this->hidden ) {
412
+            // If hidden attributes are set, we'll grab everything and hide those.
413
+            foreach ( $this->get_attribute_keys() as $key ) {
414
+                if ( ! in_array( $key, $this->hidden ) ) {
415
+                    $attributes[ $key ] = $this->get_attribute( $key );
416
+                }
417
+            }
418
+        } else {
419
+            // If nothing is hidden/visible, we'll grab and reveal everything.
420
+            foreach ( $this->get_attribute_keys() as $key ) {
421
+                $attributes[ $key ] = $this->get_attribute( $key );
422
+            }
423
+        }
424
+
425
+        return array_map( function ( $attribute ) {
426
+            if ( $attribute instanceof Serializes ) {
427
+                return $attribute->serialize();
428
+            }
429
+
430
+            return $attribute;
431
+        }, $attributes );
432
+    }
433
+
434
+    /**
435
+     * Syncs the current attributes to the model's original.
436
+     *
437
+     * @return $this
438
+     */
439
+    public function sync_original() {
440
+        $this->original = $this->attributes;
441
+
442
+        if ( $this->attributes['object'] ) {
443
+            $this->original['object'] = clone $this->attributes['object'];
444
+        }
445
+
446
+        return $this;
447
+    }
448
+
449
+    /**
450
+     * Checks if a given attribute is mass-fillable.
451
+     *
452
+     * Returns true if the attribute can be filled, false if it can't.
453
+     *
454
+     * @param string $name
455
+     *
456
+     * @return bool
457
+     */
458
+    private function is_fillable( $name ) {
459
+        // If this model isn't guarded, everything is fillable.
460
+        if ( ! $this->is_guarded ) {
461
+            return true;
462
+        }
463
+
464
+        // If it's in the fillable array, then it's fillable.
465
+        if ( in_array( $name, $this->fillable ) ) {
466
+            return true;
467
+        }
468
+
469
+        // If it's explicitly guarded, then it's not fillable.
470
+        if ( in_array( $name, $this->guarded ) ) {
471
+            return false;
472
+        }
473
+
474
+        // If fillable hasn't been defined, then everything else fillable.
475
+        return ! $this->fillable;
476
+    }
477
+
478
+    /**
479
+     * Overrides the current WP_Post with a provided one.
480
+     *
481
+     * Resets the post's default values and stores it in the attributes.
482
+     *
483
+     * @param WP_Post $value
484
+     *
485
+     * @return $this
486
+     */
487
+    private function override_wp_object( $value ) {
488
+        $this->attributes['object'] = $this->set_wp_object_constants( $value );
489
+
490
+        return $this;
491
+    }
492
+
493
+    /**
494
+     * Create and set with a new blank post.
495
+     *
496
+     * Creates a new WP_Post object, assigns it the default attributes,
497
+     * and stores it in the attributes.
498
+     *
499
+     * @throws LogicException
500
+     */
501
+    private function create_wp_object() {
502
+        switch ( true ) {
503
+            case $this instanceof UsesWordPressPost:
504
+                $object = new WP_Post( (object) array() );
505
+                break;
506
+            case $this instanceof UsesWordPressTerm:
507
+                $object = new WP_Term( (object) array() );
508
+                break;
509
+            default:
510
+                throw new LogicException;
511
+                break;
512
+        }
513
+
514
+        $this->attributes['object'] = $this->set_wp_object_constants( $object );
515
+    }
516
+
517
+    /**
518
+     * Enforces values on the post that can't change.
519
+     *
520
+     * Primarily, this is used to make sure the post_type always maps
521
+     * to the model's "$type" property, but this can all be overridden
522
+     * by the developer to enforce other values in the model.
523
+     *
524
+     * @param object $object
525
+     *
526
+     * @return object
527
+     */
528
+    protected function set_wp_object_constants( $object ) {
529
+        if ( $this instanceof UsesWordPressPost ) {
530
+            $object->post_type = $this::get_post_type();
531
+        }
532
+
533
+        if ( $this instanceof UsesWordPressTerm ) {
534
+            $object->taxonomy = $this::get_taxonomy();
535
+        }
536
+
537
+        return $object;
538
+    }
539
+
540
+    /**
541
+     * Magic __get method.
542
+     *
543
+     * Passes the name and value to get_attribute, which is where the magic happens.
544
+     *
545
+     * @param string $name
546
+     *
547
+     * @return mixed
548
+     */
549
+    public function __get( $name ) {
550
+        return $this->get_attribute( $name );
551
+    }
552
+
553
+    /**
554
+     * Retrieves the model attribute.
555
+     *
556
+     * @param string $name
557
+     *
558
+     * @return mixed
559
+     *
560
+     * @throws PropertyDoesNotExistException If property isn't found.
561
+     */
562
+    public function get_attribute( $name ) {
563
+        if ( $method = $this->has_map_method( $name ) ) {
564
+            $value = $this->attributes['object']->{$this->{$method}()};
565
+        } elseif ( $method = $this->has_compute_method( $name ) ) {
566
+            $value = $this->{$method}();
567
+        } else if ( $method = $this->has_related_method( $name ) ) {
568
+            $value = $this->get_related( $this->{$method}()->get_sha() );
569
+        } else {
570
+            if ( ! isset( $this->attributes['table'][ $name ] ) ) {
571
+                throw new PropertyDoesNotExistException;
572
+            }
573
+
574
+            $value = $this->attributes['table'][ $name ];
575
+        }
576
+
577
+        return $value;
578
+    }
579
+
580
+    /**
581
+     * Retrieve the model's original attribute value.
582
+     *
583
+     * @param string $name
584
+     *
585
+     * @return mixed
586
+     *
587
+     * @throws PropertyDoesNotExistException If property isn't found.
588
+     */
589
+    public function get_original_attribute( $name ) {
590
+        $original = new static( $this->original );
591
+
592
+        return $original->get_attribute( $name );
593
+    }
594
+
595
+    /**
596
+     * Fetches the Model's primary ID, depending on the model
597
+     * implementation.
598
+     *
599
+     * @return int
600
+     *
601
+     * @throws LogicException
602
+     */
603
+    public function get_primary_id() {
604
+        if ( $this instanceof UsesWordPressPost ) {
605
+            return $this->get_underlying_wp_object()->ID;
606
+        }
607
+
608
+        if ( $this instanceof UsesWordPressTerm ) {
609
+            return $this->get_underlying_wp_object()->term_id;
610
+        }
611
+
612
+        // Model w/o wp_object not yet supported.
613
+        throw new LogicException;
614
+    }
615
+
616
+    /**
617
+     * Generates the table foreign key, depending on the model
618
+     * implementation.
619
+     *
620
+     * @return string
621
+     *
622
+     * @throws LogicException
623
+     */
624
+    public function get_foreign_key() {
625
+        if ( $this instanceof UsesWordPressPost ) {
626
+            return 'post_id';
627
+        }
628
+
629
+        // Model w/o wp_object not yet supported.
630
+        throw new LogicException;
631
+    }
632
+
633
+    /**
634
+     * Gets the related Model or Collection for the given sha.
635
+     *
636
+     * @param string $sha
637
+     *
638
+     * @return Model|Collection
639
+     */
640
+    public function get_related( $sha ) {
641
+        return $this->related[ $sha ];
642
+    }
643
+
644
+    /**
645
+     * Sets the related Model or Collection for the given sha.
646
+     *
647
+     * @param string           $sha
648
+     * @param Model|Collection $target
649
+     *
650
+     * @throws RuntimeException
651
+     */
652
+    public function set_related( $sha, $target ) {
653
+        if ( ! ( $target instanceof Model ) && ! ( $target instanceof Collection ) ) {
654
+            throw new RuntimeException;
655
+        }
656
+
657
+        $this->related[ $sha ] = $target;
658
+    }
659
+
660
+    /**
661
+     * Checks whether the attribute has a map method.
662
+     *
663
+     * This is used to determine whether the attribute maps to a
664
+     * property on the underlying WP_Post object. Returns the
665
+     * method if one exists, returns false if it doesn't.
666
+     *
667
+     * @param string $name
668
+     *
669
+     * @return false|string
670
+     */
671
+    protected function has_map_method( $name ) {
672
+        if ( method_exists( $this, $method = "map_{$name}" ) ) {
673
+            return $method;
674
+        }
675
+
676
+        return false;
677
+    }
678
+
679
+    /**
680
+     * Checks whether the attribute has a compute method.
681
+     *
682
+     * This is used to determine if the attribute should be computed
683
+     * from other attributes.
684
+     *
685
+     * @param string $name
686
+     *
687
+     * @return false|string
688
+     */
689
+    protected function has_compute_method( $name ) {
690
+        if ( method_exists( $this, $method = "compute_{$name}" ) ) {
691
+            return $method;
692
+        }
693
+
694
+        return false;
695
+    }
696
+
697
+    /**
698
+     * Checks whether the attribute has a compute method.
699
+     *
700
+     * This is used to determine if the attribute should be computed
701
+     * from other attributes.
702
+     *
703
+     * @param string $name
704
+     *
705
+     * @return false|string
706
+     */
707
+    protected function has_related_method( $name ) {
708
+        if ( method_exists( $this, $method = "related_{$name}" ) ) {
709
+            return $method;
710
+        }
711
+
712
+        return false;
713
+    }
714
+
715
+    /**
716
+     * Clears all the current attributes from the model.
717
+     *
718
+     * This does not touch the model's original attributes, and will
719
+     * only clear fillable attributes, unless the model is unguarded.
720
+     *
721
+     * @return $this
722
+     */
723
+    public function clear() {
724
+        $keys = $this->get_attribute_keys();
725
+
726
+        foreach ( $keys as $key ) {
727
+            try {
728
+                $this->set_attribute( $key, null );
729
+            } catch ( GuardedPropertyException $e ) {
730
+                // We won't clear out guarded attributes.
731
+            }
732
+        }
733
+
734
+        return $this;
735
+    }
736
+
737
+    /**
738
+     * Unguards the model.
739
+     *
740
+     * Sets the model to be unguarded, allowing the filling of
741
+     * guarded attributes.
742
+     */
743
+    public function unguard() {
744
+        $this->is_guarded = false;
745
+    }
746
+
747
+    /**
748
+     * Reguards the model.
749
+     *
750
+     * Sets the model to be guarded, preventing filling of
751
+     * guarded attributes.
752
+     */
753
+    public function reguard() {
754
+        $this->is_guarded = true;
755
+    }
756
+
757
+    /**
758
+     * Retrieves all the compute methods on the model.
759
+     *
760
+     * @return array
761
+     */
762
+    protected function get_compute_methods() {
763
+        $methods = get_class_methods( get_called_class() );
764
+        $methods = array_filter( $methods, function ( $method ) {
765
+            return strrpos( $method, 'compute_', - strlen( $method ) ) !== false;
766
+        } );
767
+        $methods = array_map( function ( $method ) {
768
+            return substr( $method, strlen( 'compute_' ) );
769
+        }, $methods );
770
+
771
+        return $methods;
772
+    }
773
+
774
+    /**
775
+     * Retrieves all the related methods on the model.
776
+     *
777
+     * @return array
778
+     */
779
+    protected function get_related_methods() {
780
+        $methods = get_class_methods( get_called_class() );
781
+        $methods = array_filter( $methods, function ( $method ) {
782
+            return strrpos( $method, 'related_', - strlen( $method ) ) !== false;
783
+        } );
784
+        $methods = array_map( function ( $method ) {
785
+            return substr( $method, strlen( 'related_' ) );
786
+        }, $methods );
787
+
788
+        return $methods;
789
+    }
790
+
791
+    /**
792
+     * Returns whether this relation has already been filled on the model.
793
+     *
794
+     * @param string $relation
795
+     *
796
+     * @return bool
797
+     */
798
+    public function relation_is_filled( $relation ) {
799
+        $sha = $this
800
+            ->{$this->has_related_method( $relation )}()
801
+            ->get_sha();
802
+
803
+        return isset( $this->related[ $sha ] );
804
+    }
805
+
806
+    /**
807
+     * Returns whether the Model is currently having
808
+     * its relationships filled.
809
+     *
810
+     * @return bool
811
+     */
812
+    public function is_filling() {
813
+        return $this->filling;
814
+    }
815
+
816
+    /**
817
+     * Sets whether the Model is having its relationships filled.
818
+     *
819
+     * @param bool $is_filling
820
+     */
821
+    public function set_filling( $is_filling ) {
822
+        $this->filling = $is_filling;
823
+    }
824
+
825
+    /**
826
+     * Returns a HasMany relationship for the model.
827
+     *
828
+     * @param string $class
829
+     * @param string $type
830
+     * @param string $foreign_key
831
+     *
832
+     * @return HasMany
833
+     */
834
+    protected function has_many( $class, $type, $foreign_key ) {
835
+        return new HasMany( $this, $class, $type, $foreign_key );
836
+    }
837
+
838
+    /**
839
+     * Returns a BelongsToOne relationship for the model.
840
+     *
841
+     * @param string $class
842
+     * @param string $type
843
+     * @param string $local_key
844
+     *
845
+     * @return HasMany
846
+     */
847
+    protected function belongs_to_one( $class, $type, $local_key = '' ) {
848
+        return new BelongsToOne( $this, $class, $type, $local_key );
849
+    }
850
+
851
+    /**
852
+     * Sets up the memo array for the creating model.
853
+     */
854
+    private function maybe_boot() {
855
+        if ( ! isset( self::$memo[ get_called_class() ] ) ) {
856
+            self::$memo[ get_called_class() ] = array();
857
+        }
858
+    }
859
+
860
+    /**
861
+     * Whether this Model uses an underlying WordPress object.
862
+     *
863
+     * @return bool
864
+     */
865
+    protected function uses_wp_object() {
866
+        return $this instanceof UsesWordPressPost ||
867
+            $this instanceof UsesWordPressTerm;
868
+    }
869 869
 }
Please login to merge, or discard this patch.
Spacing   +128 added lines, -128 removed lines patch added patch discarded remove patch
@@ -113,15 +113,15 @@  discard block
 block discarded – undo
113 113
 	 *
114 114
 	 * @param array <string, mixed> $attributes
115 115
 	 */
116
-	public function __construct( array $attributes = array() ) {
116
+	public function __construct(array $attributes = array()) {
117 117
 		$this->maybe_boot();
118 118
 		$this->sync_original();
119 119
 
120
-		if ( $this->uses_wp_object() ) {
120
+		if ($this->uses_wp_object()) {
121 121
 			$this->create_wp_object();
122 122
 		}
123 123
 
124
-		$this->refresh( $attributes );
124
+		$this->refresh($attributes);
125 125
 	}
126 126
 
127 127
 	/**
@@ -134,10 +134,10 @@  discard block
 block discarded – undo
134 134
 	 *
135 135
 	 * @return $this
136 136
 	 */
137
-	public function refresh( array $attributes ) {
137
+	public function refresh(array $attributes) {
138 138
 		$this->clear();
139 139
 
140
-		return $this->merge( $attributes );
140
+		return $this->merge($attributes);
141 141
 	}
142 142
 
143 143
 	/**
@@ -149,9 +149,9 @@  discard block
 block discarded – undo
149 149
 	 *
150 150
 	 * @return $this
151 151
 	 */
152
-	public function merge( array $attributes ) {
153
-		foreach ( $attributes as $name => $value ) {
154
-			$this->set_attribute( $name, $value );
152
+	public function merge(array $attributes) {
153
+		foreach ($attributes as $name => $value) {
154
+			$this->set_attribute($name, $value);
155 155
 		}
156 156
 
157 157
 		return $this;
@@ -188,11 +188,11 @@  discard block
 block discarded – undo
188 188
 	public function get_changed_table_attributes() {
189 189
 		$changed = array();
190 190
 
191
-		foreach ( $this->get_table_attributes() as $attribute ) {
192
-			if ( $this->get_attribute( $attribute ) !==
193
-			     $this->get_original_attribute( $attribute )
191
+		foreach ($this->get_table_attributes() as $attribute) {
192
+			if ($this->get_attribute($attribute) !==
193
+			     $this->get_original_attribute($attribute)
194 194
 			) {
195
-				$changed[ $attribute ] = $this->get_attribute( $attribute );
195
+				$changed[$attribute] = $this->get_attribute($attribute);
196 196
 			}
197 197
 		}
198 198
 
@@ -208,7 +208,7 @@  discard block
 block discarded – undo
208 208
 	 * @return false|WP_Post|WP_Term
209 209
 	 */
210 210
 	public function get_underlying_wp_object() {
211
-		if ( isset( $this->attributes['object'] ) ) {
211
+		if (isset($this->attributes['object'])) {
212 212
 			return $this->attributes['object'];
213 213
 		}
214 214
 
@@ -234,11 +234,11 @@  discard block
 block discarded – undo
234 234
 	public function get_changed_wp_object_attributes() {
235 235
 		$changed = array();
236 236
 
237
-		foreach ( $this->get_wp_object_keys() as $key ) {
238
-			if ( $this->get_attribute( $key ) !==
239
-			     $this->get_original_attribute( $key )
237
+		foreach ($this->get_wp_object_keys() as $key) {
238
+			if ($this->get_attribute($key) !==
239
+			     $this->get_original_attribute($key)
240 240
 			) {
241
-				$changed[ $key ] = $this->get_attribute( $key );
241
+				$changed[$key] = $this->get_attribute($key);
242 242
 			}
243 243
 		}
244 244
 
@@ -253,8 +253,8 @@  discard block
 block discarded – undo
253 253
 	 * @param string $name
254 254
 	 * @param mixed  $value
255 255
 	 */
256
-	public function __set( $name, $value ) {
257
-		$this->set_attribute( $name, $value );
256
+	public function __set($name, $value) {
257
+		$this->set_attribute($name, $value);
258 258
 	}
259 259
 
260 260
 	/**
@@ -271,19 +271,19 @@  discard block
 block discarded – undo
271 271
 	 *
272 272
 	 * @throws GuardedPropertyException
273 273
 	 */
274
-	public function set_attribute( $name, $value ) {
275
-		if ( 'object' === $name ) {
276
-			return $this->override_wp_object( $value );
274
+	public function set_attribute($name, $value) {
275
+		if ('object' === $name) {
276
+			return $this->override_wp_object($value);
277 277
 		}
278 278
 
279
-		if ( ! $this->is_fillable( $name ) ) {
279
+		if (!$this->is_fillable($name)) {
280 280
 			throw new GuardedPropertyException;
281 281
 		}
282 282
 
283
-		if ( $method = $this->has_map_method( $name ) ) {
283
+		if ($method = $this->has_map_method($name)) {
284 284
 			$this->attributes['object']->{$this->{$method}()} = $value;
285 285
 		} else {
286
-			$this->attributes['table'][ $name ] = $value;
286
+			$this->attributes['table'][$name] = $value;
287 287
 		}
288 288
 
289 289
 		return $this;
@@ -295,11 +295,11 @@  discard block
 block discarded – undo
295 295
 	 * @return array
296 296
 	 */
297 297
 	public function get_attribute_keys() {
298
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
299
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
298
+		if (isset(self::$memo[get_called_class()][__METHOD__])) {
299
+			return self::$memo[get_called_class()][__METHOD__];
300 300
 		}
301 301
 
302
-		return self::$memo[ get_called_class() ][ __METHOD__ ]
302
+		return self::$memo[get_called_class()][__METHOD__]
303 303
 			= array_merge(
304 304
 				$this->fillable,
305 305
 				$this->guarded,
@@ -314,22 +314,22 @@  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 ) &&
326
-			     ! $this->has_related_method( $key )
323
+		foreach ($this->get_attribute_keys() as $key) {
324
+			if (!$this->has_map_method($key) &&
325
+			     !$this->has_compute_method($key) &&
326
+			     !$this->has_related_method($key)
327 327
 			) {
328 328
 				$keys[] = $key;
329 329
 			}
330 330
 		}
331 331
 
332
-		return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
332
+		return self::$memo[get_called_class()][__METHOD__] = $keys;
333 333
 	}
334 334
 
335 335
 	/**
@@ -338,19 +338,19 @@  discard block
 block discarded – undo
338 338
 	 * @return array
339 339
 	 */
340 340
 	public function get_wp_object_keys() {
341
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
342
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
341
+		if (isset(self::$memo[get_called_class()][__METHOD__])) {
342
+			return self::$memo[get_called_class()][__METHOD__];
343 343
 		}
344 344
 
345 345
 		$keys = array();
346 346
 
347
-		foreach ( $this->get_attribute_keys() as $key ) {
348
-			if ( $this->has_map_method( $key ) ) {
347
+		foreach ($this->get_attribute_keys() as $key) {
348
+			if ($this->has_map_method($key)) {
349 349
 				$keys[] = $key;
350 350
 			}
351 351
 		}
352 352
 
353
-		return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
353
+		return self::$memo[get_called_class()][__METHOD__] = $keys;
354 354
 	}
355 355
 
356 356
 	/**
@@ -359,19 +359,19 @@  discard block
 block discarded – undo
359 359
 	 * @return array
360 360
 	 */
361 361
 	public function get_computed_keys() {
362
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
363
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
362
+		if (isset(self::$memo[get_called_class()][__METHOD__])) {
363
+			return self::$memo[get_called_class()][__METHOD__];
364 364
 		}
365 365
 
366 366
 		$keys = array();
367 367
 
368
-		foreach ( $this->get_attribute_keys() as $key ) {
369
-			if ( $this->has_compute_method( $key ) ) {
368
+		foreach ($this->get_attribute_keys() as $key) {
369
+			if ($this->has_compute_method($key)) {
370 370
 				$keys[] = $key;
371 371
 			}
372 372
 		}
373 373
 
374
-		return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
374
+		return self::$memo[get_called_class()][__METHOD__] = $keys;
375 375
 	}
376 376
 
377 377
 	/**
@@ -380,19 +380,19 @@  discard block
 block discarded – undo
380 380
 	 * @return array
381 381
 	 */
382 382
 	public function get_related_keys() {
383
-		if ( isset( self::$memo[ get_called_class() ][ __METHOD__ ] ) ) {
384
-			return self::$memo[ get_called_class() ][ __METHOD__ ];
383
+		if (isset(self::$memo[get_called_class()][__METHOD__])) {
384
+			return self::$memo[get_called_class()][__METHOD__];
385 385
 		}
386 386
 
387 387
 		$keys = array();
388 388
 
389
-		foreach ( $this->get_attribute_keys() as $key ) {
390
-			if ( $this->has_related_method( $key ) ) {
389
+		foreach ($this->get_attribute_keys() as $key) {
390
+			if ($this->has_related_method($key)) {
391 391
 				$keys[] = $key;
392 392
 			}
393 393
 		}
394 394
 
395
-		return self::$memo[ get_called_class() ][ __METHOD__ ] = $keys;
395
+		return self::$memo[get_called_class()][__METHOD__] = $keys;
396 396
 	}
397 397
 
398 398
 	/**
@@ -403,32 +403,32 @@  discard block
 block discarded – undo
403 403
 	public function serialize() {
404 404
 		$attributes = array();
405 405
 
406
-		if ( $this->visible ) {
406
+		if ($this->visible) {
407 407
 			// If visible attributes are set, we'll only reveal those.
408
-			foreach ( $this->visible as $key ) {
409
-				$attributes[ $key ] = $this->get_attribute( $key );
408
+			foreach ($this->visible as $key) {
409
+				$attributes[$key] = $this->get_attribute($key);
410 410
 			}
411
-		} elseif ( $this->hidden ) {
411
+		} elseif ($this->hidden) {
412 412
 			// If hidden attributes are set, we'll grab everything and hide those.
413
-			foreach ( $this->get_attribute_keys() as $key ) {
414
-				if ( ! in_array( $key, $this->hidden ) ) {
415
-					$attributes[ $key ] = $this->get_attribute( $key );
413
+			foreach ($this->get_attribute_keys() as $key) {
414
+				if (!in_array($key, $this->hidden)) {
415
+					$attributes[$key] = $this->get_attribute($key);
416 416
 				}
417 417
 			}
418 418
 		} else {
419 419
 			// If nothing is hidden/visible, we'll grab and reveal everything.
420
-			foreach ( $this->get_attribute_keys() as $key ) {
421
-				$attributes[ $key ] = $this->get_attribute( $key );
420
+			foreach ($this->get_attribute_keys() as $key) {
421
+				$attributes[$key] = $this->get_attribute($key);
422 422
 			}
423 423
 		}
424 424
 
425
-		return array_map( function ( $attribute ) {
426
-			if ( $attribute instanceof Serializes ) {
425
+		return array_map(function($attribute) {
426
+			if ($attribute instanceof Serializes) {
427 427
 				return $attribute->serialize();
428 428
 			}
429 429
 
430 430
 			return $attribute;
431
-		}, $attributes );
431
+		}, $attributes);
432 432
 	}
433 433
 
434 434
 	/**
@@ -439,7 +439,7 @@  discard block
 block discarded – undo
439 439
 	public function sync_original() {
440 440
 		$this->original = $this->attributes;
441 441
 
442
-		if ( $this->attributes['object'] ) {
442
+		if ($this->attributes['object']) {
443 443
 			$this->original['object'] = clone $this->attributes['object'];
444 444
 		}
445 445
 
@@ -455,24 +455,24 @@  discard block
 block discarded – undo
455 455
 	 *
456 456
 	 * @return bool
457 457
 	 */
458
-	private function is_fillable( $name ) {
458
+	private function is_fillable($name) {
459 459
 		// If this model isn't guarded, everything is fillable.
460
-		if ( ! $this->is_guarded ) {
460
+		if (!$this->is_guarded) {
461 461
 			return true;
462 462
 		}
463 463
 
464 464
 		// If it's in the fillable array, then it's fillable.
465
-		if ( in_array( $name, $this->fillable ) ) {
465
+		if (in_array($name, $this->fillable)) {
466 466
 			return true;
467 467
 		}
468 468
 
469 469
 		// If it's explicitly guarded, then it's not fillable.
470
-		if ( in_array( $name, $this->guarded ) ) {
470
+		if (in_array($name, $this->guarded)) {
471 471
 			return false;
472 472
 		}
473 473
 
474 474
 		// If fillable hasn't been defined, then everything else fillable.
475
-		return ! $this->fillable;
475
+		return !$this->fillable;
476 476
 	}
477 477
 
478 478
 	/**
@@ -484,8 +484,8 @@  discard block
 block discarded – undo
484 484
 	 *
485 485
 	 * @return $this
486 486
 	 */
487
-	private function override_wp_object( $value ) {
488
-		$this->attributes['object'] = $this->set_wp_object_constants( $value );
487
+	private function override_wp_object($value) {
488
+		$this->attributes['object'] = $this->set_wp_object_constants($value);
489 489
 
490 490
 		return $this;
491 491
 	}
@@ -499,19 +499,19 @@  discard block
 block discarded – undo
499 499
 	 * @throws LogicException
500 500
 	 */
501 501
 	private function create_wp_object() {
502
-		switch ( true ) {
502
+		switch (true) {
503 503
 			case $this instanceof UsesWordPressPost:
504
-				$object = new WP_Post( (object) array() );
504
+				$object = new WP_Post((object) array());
505 505
 				break;
506 506
 			case $this instanceof UsesWordPressTerm:
507
-				$object = new WP_Term( (object) array() );
507
+				$object = new WP_Term((object) array());
508 508
 				break;
509 509
 			default:
510 510
 				throw new LogicException;
511 511
 				break;
512 512
 		}
513 513
 
514
-		$this->attributes['object'] = $this->set_wp_object_constants( $object );
514
+		$this->attributes['object'] = $this->set_wp_object_constants($object);
515 515
 	}
516 516
 
517 517
 	/**
@@ -525,12 +525,12 @@  discard block
 block discarded – undo
525 525
 	 *
526 526
 	 * @return object
527 527
 	 */
528
-	protected function set_wp_object_constants( $object ) {
529
-		if ( $this instanceof UsesWordPressPost ) {
528
+	protected function set_wp_object_constants($object) {
529
+		if ($this instanceof UsesWordPressPost) {
530 530
 			$object->post_type = $this::get_post_type();
531 531
 		}
532 532
 
533
-		if ( $this instanceof UsesWordPressTerm ) {
533
+		if ($this instanceof UsesWordPressTerm) {
534 534
 			$object->taxonomy = $this::get_taxonomy();
535 535
 		}
536 536
 
@@ -546,8 +546,8 @@  discard block
 block discarded – undo
546 546
 	 *
547 547
 	 * @return mixed
548 548
 	 */
549
-	public function __get( $name ) {
550
-		return $this->get_attribute( $name );
549
+	public function __get($name) {
550
+		return $this->get_attribute($name);
551 551
 	}
552 552
 
553 553
 	/**
@@ -559,19 +559,19 @@  discard block
 block discarded – undo
559 559
 	 *
560 560
 	 * @throws PropertyDoesNotExistException If property isn't found.
561 561
 	 */
562
-	public function get_attribute( $name ) {
563
-		if ( $method = $this->has_map_method( $name ) ) {
562
+	public function get_attribute($name) {
563
+		if ($method = $this->has_map_method($name)) {
564 564
 			$value = $this->attributes['object']->{$this->{$method}()};
565
-		} elseif ( $method = $this->has_compute_method( $name ) ) {
565
+		} elseif ($method = $this->has_compute_method($name)) {
566 566
 			$value = $this->{$method}();
567
-		} else if ( $method = $this->has_related_method( $name ) ) {
568
-			$value = $this->get_related( $this->{$method}()->get_sha() );
567
+		} else if ($method = $this->has_related_method($name)) {
568
+			$value = $this->get_related($this->{$method}()->get_sha());
569 569
 		} else {
570
-			if ( ! isset( $this->attributes['table'][ $name ] ) ) {
570
+			if (!isset($this->attributes['table'][$name])) {
571 571
 				throw new PropertyDoesNotExistException;
572 572
 			}
573 573
 
574
-			$value = $this->attributes['table'][ $name ];
574
+			$value = $this->attributes['table'][$name];
575 575
 		}
576 576
 
577 577
 		return $value;
@@ -586,10 +586,10 @@  discard block
 block discarded – undo
586 586
 	 *
587 587
 	 * @throws PropertyDoesNotExistException If property isn't found.
588 588
 	 */
589
-	public function get_original_attribute( $name ) {
590
-		$original = new static( $this->original );
589
+	public function get_original_attribute($name) {
590
+		$original = new static($this->original);
591 591
 
592
-		return $original->get_attribute( $name );
592
+		return $original->get_attribute($name);
593 593
 	}
594 594
 
595 595
 	/**
@@ -601,11 +601,11 @@  discard block
 block discarded – undo
601 601
 	 * @throws LogicException
602 602
 	 */
603 603
 	public function get_primary_id() {
604
-		if ( $this instanceof UsesWordPressPost ) {
604
+		if ($this instanceof UsesWordPressPost) {
605 605
 			return $this->get_underlying_wp_object()->ID;
606 606
 		}
607 607
 
608
-		if ( $this instanceof UsesWordPressTerm ) {
608
+		if ($this instanceof UsesWordPressTerm) {
609 609
 			return $this->get_underlying_wp_object()->term_id;
610 610
 		}
611 611
 
@@ -622,7 +622,7 @@  discard block
 block discarded – undo
622 622
 	 * @throws LogicException
623 623
 	 */
624 624
 	public function get_foreign_key() {
625
-		if ( $this instanceof UsesWordPressPost ) {
625
+		if ($this instanceof UsesWordPressPost) {
626 626
 			return 'post_id';
627 627
 		}
628 628
 
@@ -637,8 +637,8 @@  discard block
 block discarded – undo
637 637
 	 *
638 638
 	 * @return Model|Collection
639 639
 	 */
640
-	public function get_related( $sha ) {
641
-		return $this->related[ $sha ];
640
+	public function get_related($sha) {
641
+		return $this->related[$sha];
642 642
 	}
643 643
 
644 644
 	/**
@@ -649,12 +649,12 @@  discard block
 block discarded – undo
649 649
 	 *
650 650
 	 * @throws RuntimeException
651 651
 	 */
652
-	public function set_related( $sha, $target ) {
653
-		if ( ! ( $target instanceof Model ) && ! ( $target instanceof Collection ) ) {
652
+	public function set_related($sha, $target) {
653
+		if (!($target instanceof Model) && !($target instanceof Collection)) {
654 654
 			throw new RuntimeException;
655 655
 		}
656 656
 
657
-		$this->related[ $sha ] = $target;
657
+		$this->related[$sha] = $target;
658 658
 	}
659 659
 
660 660
 	/**
@@ -668,8 +668,8 @@  discard block
 block discarded – undo
668 668
 	 *
669 669
 	 * @return false|string
670 670
 	 */
671
-	protected function has_map_method( $name ) {
672
-		if ( method_exists( $this, $method = "map_{$name}" ) ) {
671
+	protected function has_map_method($name) {
672
+		if (method_exists($this, $method = "map_{$name}")) {
673 673
 			return $method;
674 674
 		}
675 675
 
@@ -686,8 +686,8 @@  discard block
 block discarded – undo
686 686
 	 *
687 687
 	 * @return false|string
688 688
 	 */
689
-	protected function has_compute_method( $name ) {
690
-		if ( method_exists( $this, $method = "compute_{$name}" ) ) {
689
+	protected function has_compute_method($name) {
690
+		if (method_exists($this, $method = "compute_{$name}")) {
691 691
 			return $method;
692 692
 		}
693 693
 
@@ -704,8 +704,8 @@  discard block
 block discarded – undo
704 704
 	 *
705 705
 	 * @return false|string
706 706
 	 */
707
-	protected function has_related_method( $name ) {
708
-		if ( method_exists( $this, $method = "related_{$name}" ) ) {
707
+	protected function has_related_method($name) {
708
+		if (method_exists($this, $method = "related_{$name}")) {
709 709
 			return $method;
710 710
 		}
711 711
 
@@ -723,10 +723,10 @@  discard block
 block discarded – undo
723 723
 	public function clear() {
724 724
 		$keys = $this->get_attribute_keys();
725 725
 
726
-		foreach ( $keys as $key ) {
726
+		foreach ($keys as $key) {
727 727
 			try {
728
-				$this->set_attribute( $key, null );
729
-			} catch ( GuardedPropertyException $e ) {
728
+				$this->set_attribute($key, null);
729
+			} catch (GuardedPropertyException $e) {
730 730
 				// We won't clear out guarded attributes.
731 731
 			}
732 732
 		}
@@ -760,13 +760,13 @@  discard block
 block discarded – undo
760 760
 	 * @return array
761 761
 	 */
762 762
 	protected function get_compute_methods() {
763
-		$methods = get_class_methods( get_called_class() );
764
-		$methods = array_filter( $methods, function ( $method ) {
765
-			return strrpos( $method, 'compute_', - strlen( $method ) ) !== false;
763
+		$methods = get_class_methods(get_called_class());
764
+		$methods = array_filter($methods, function($method) {
765
+			return strrpos($method, 'compute_', - strlen($method)) !== false;
766 766
 		} );
767
-		$methods = array_map( function ( $method ) {
768
-			return substr( $method, strlen( 'compute_' ) );
769
-		}, $methods );
767
+		$methods = array_map(function($method) {
768
+			return substr($method, strlen('compute_'));
769
+		}, $methods);
770 770
 
771 771
 		return $methods;
772 772
 	}
@@ -777,13 +777,13 @@  discard block
 block discarded – undo
777 777
 	 * @return array
778 778
 	 */
779 779
 	protected function get_related_methods() {
780
-		$methods = get_class_methods( get_called_class() );
781
-		$methods = array_filter( $methods, function ( $method ) {
782
-			return strrpos( $method, 'related_', - strlen( $method ) ) !== false;
780
+		$methods = get_class_methods(get_called_class());
781
+		$methods = array_filter($methods, function($method) {
782
+			return strrpos($method, 'related_', - strlen($method)) !== false;
783 783
 		} );
784
-		$methods = array_map( function ( $method ) {
785
-			return substr( $method, strlen( 'related_' ) );
786
-		}, $methods );
784
+		$methods = array_map(function($method) {
785
+			return substr($method, strlen('related_'));
786
+		}, $methods);
787 787
 
788 788
 		return $methods;
789 789
 	}
@@ -795,12 +795,12 @@  discard block
 block discarded – undo
795 795
 	 *
796 796
 	 * @return bool
797 797
 	 */
798
-	public function relation_is_filled( $relation ) {
798
+	public function relation_is_filled($relation) {
799 799
 		$sha = $this
800
-			->{$this->has_related_method( $relation )}()
800
+			->{$this->has_related_method($relation)}()
801 801
 			->get_sha();
802 802
 
803
-		return isset( $this->related[ $sha ] );
803
+		return isset($this->related[$sha]);
804 804
 	}
805 805
 
806 806
 	/**
@@ -818,7 +818,7 @@  discard block
 block discarded – undo
818 818
 	 *
819 819
 	 * @param bool $is_filling
820 820
 	 */
821
-	public function set_filling( $is_filling ) {
821
+	public function set_filling($is_filling) {
822 822
 		$this->filling = $is_filling;
823 823
 	}
824 824
 
@@ -831,8 +831,8 @@  discard block
 block discarded – undo
831 831
 	 *
832 832
 	 * @return HasMany
833 833
 	 */
834
-	protected function has_many( $class, $type, $foreign_key ) {
835
-		return new HasMany( $this, $class, $type, $foreign_key );
834
+	protected function has_many($class, $type, $foreign_key) {
835
+		return new HasMany($this, $class, $type, $foreign_key);
836 836
 	}
837 837
 
838 838
 	/**
@@ -844,16 +844,16 @@  discard block
 block discarded – undo
844 844
 	 *
845 845
 	 * @return HasMany
846 846
 	 */
847
-	protected function belongs_to_one( $class, $type, $local_key = '' ) {
848
-		return new BelongsToOne( $this, $class, $type, $local_key );
847
+	protected function belongs_to_one($class, $type, $local_key = '') {
848
+		return new BelongsToOne($this, $class, $type, $local_key);
849 849
 	}
850 850
 
851 851
 	/**
852 852
 	 * Sets up the memo array for the creating model.
853 853
 	 */
854 854
 	private function maybe_boot() {
855
-		if ( ! isset( self::$memo[ get_called_class() ] ) ) {
856
-			self::$memo[ get_called_class() ] = array();
855
+		if (!isset(self::$memo[get_called_class()])) {
856
+			self::$memo[get_called_class()] = array();
857 857
 		}
858 858
 	}
859 859
 
Please login to merge, or discard this patch.