Meta_Data_Registrar::create_rest_get_method()   A
last analyzed

Complexity

Conditions 5
Paths 1

Size

Total Lines 25
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 18
c 0
b 0
f 0
dl 0
loc 25
rs 9.3554
cc 5
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Used for registering Meta Data.
7
 *
8
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
9
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
11
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
12
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
13
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
14
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
15
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
16
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
18
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
 *
20
 * @author Glynn Quelch <[email protected]>
21
 * @license http://www.opensource.org/licenses/mit-license.html  MIT License
22
 * @package PinkCrab\Registerables
23
 * @since 0.7.1
24
 */
25
26
namespace PinkCrab\Registerables\Registrar;
27
28
use PinkCrab\Registerables\Meta_Data;
29
30
class Meta_Data_Registrar {
31
32
	/**
33
	 * Registers meta data for post types.
34
	 *
35
	 * @param \PinkCrab\Registerables\Meta_Data $meta
36
	 * @param string                            $post_type
37
	 * @return boolean
38
	 * @throws \Exception if fails to register meta data.
39
	 */
40
	public function register_for_post_type( Meta_Data $meta, string $post_type ): bool {
41
		return $this->register_meta( $meta, 'post', $post_type );
42
	}
43
44
	/**
45
	 * Registers meta data for terms.
46
	 *
47
	 * @param \PinkCrab\Registerables\Meta_Data $meta
48
	 * @param string                            $taxonomy
49
	 * @return boolean
50
	 * @throws \Exception if fails to register meta data.
51
	 */
52
	public function register_for_term( Meta_Data $meta, string $taxonomy ): bool {
53
		return $this->register_meta( $meta, 'term', $taxonomy );
54
	}
55
56
	/**
57
	 * Registers meta data for users.
58
	 *
59
	 * @param \PinkCrab\Registerables\Meta_Data $meta
60
	 * @return boolean
61
	 * @throws \Exception if fails to register meta data.
62
	 */
63
	public function register_for_user( Meta_Data $meta ): bool {
64
		return $this->register_meta( $meta, 'user', '' );
65
	}
66
67
	/**
68
	 * Registers meta data for comments.
69
	 *
70
	 * @param \PinkCrab\Registerables\Meta_Data $meta
71
	 * @return boolean
72
	 * @throws \Exception if fails to register meta data.
73
	 */
74
	public function register_for_comment( Meta_Data $meta ): bool {
75
		return $this->register_meta( $meta, 'comment', '' );
76
	}
77
78
	/**
79
	 * Registers meta data for a defined type.
80
	 *
81
	 * Will cast WP Rest Schema model to array
82
	 *
83
	 * @param \PinkCrab\Registerables\Meta_Data $meta
84
	 * @param  string                            $meta_type The object type ('post', 'user', 'comment', 'term')
85
	 * @param  string                            $sub_type  The object sub-type ('post_type', 'taxonomy')
86
	 * @return boolean
87
	 * @throws \Exception if fails to register meta data.
88
	 */
89
	protected function register_meta( Meta_Data $meta, string $meta_type, string $sub_type ): bool {
90
		// Clone and set the post type, while enforcing it as a post meta.
91
		$meta = clone $meta;
92
		$meta->object_subtype( $sub_type );
93
		$meta->meta_type( $meta_type );
94
95
		// Normalise rest schema model to array.
96
		$meta = $this->normalise_rest_schema( $meta );
97
98
		$result = register_meta( $meta->get_meta_type(), $meta->get_meta_key(), $meta->parse_args() );
99
		if ( ! $result ) {
100
			throw new \Exception(
101
				esc_html( "Failed to register {$meta->get_meta_key()} (meta) for {$sub_type} of {$meta_type} type" )
102
			);
103
		}
104
105
		// Maybe register rest fields.
106
		if ( false !== $meta->get_rest_schema() ) {
0 ignored issues
show
introduced by
The condition false !== $meta->get_rest_schema() is always true.
Loading history...
107
			$this->register_meta_rest_field( $meta );
108
		}
109
110
		return $result;
111
	}
112
113
114
	/**
115
	 * Potentially casts a Rest Schema to an array.
116
	 *
117
	 * Only if the module active and the schema is Argument type.
118
	 *
119
	 * @param \PinkCrab\Registerables\Meta_Data $meta
120
	 * @return \PinkCrab\Registerables\Meta_Data
121
	 */
122
	protected function normalise_rest_schema( Meta_Data $meta ): Meta_Data {
123
		if ( \class_exists( 'PinkCrab\WP_Rest_Schema\Argument\Argument' )
124
		&& $meta->get_rest_schema() instanceof \PinkCrab\WP_Rest_Schema\Argument\Argument
125
		) {
126
			$meta->rest_schema( \PinkCrab\WP_Rest_Schema\Parser\Argument_Parser::for_meta_data( $meta->get_rest_schema() ) );
127
		}
128
		return $meta;
129
	}
130
131
	/**
132
	* Registers a Meta Data object as defined REST field.
133
	*
134
	* @param \PinkCrab\Registerables\Meta_Data $meta
135
	* @return void
136
	*/
137
	public function register_meta_rest_field( Meta_Data $meta ) {
138
		// Skip if not sub type defined for post or term.
139
		if ( null === $meta->get_subtype() ) {
140
			return;
141
		}
142
143
		add_action(
144
			'rest_api_init',
145
			function () use ( $meta ) {
146
				register_rest_field(
147
					$meta->get_subtype(),
148
					$meta->get_meta_key(),
149
					array( // @phpstan-ignore-line WP Docblock doesn't give enough details of callable param types, so throws false positive
150
						'get_callback'    => $meta->get_rest_view() ?? $this->create_rest_get_method( $meta ),
151
						'schema'          => $meta->get_rest_schema(),
152
						'update_callback' => $meta->get_rest_update() ?? $this->create_rest_update_method( $meta ),
153
					)
154
				);
155
			}
156
		);
157
	}
158
159
	/**
160
	 * Creates a fallback rest get callback.
161
	 *
162
	 * @param \PinkCrab\Registerables\Meta_Data $meta
163
	 * @return callable(array<mixed>):void
164
	 */
165
	protected function create_rest_get_method( Meta_Data $meta ): callable {
166
		return function ( $model ) use ( $meta ) {
167
			switch ( $meta->get_meta_type() ) {
168
				case 'post':
169
					$value = get_post_meta( $model['id'], $meta->get_meta_key(), true );
170
					break;
171
172
				case 'term':
173
					$value = get_term_meta( $model['id'], $meta->get_meta_key(), true );
174
					break;
175
176
				case 'user':
177
					$value = get_user_meta( $model['id'], $meta->get_meta_key(), true );
178
					break;
179
180
				case 'comment':
181
					$value = get_comment_meta( $model['id'], $meta->get_meta_key(), true );
182
					break;
183
184
				default:
185
					$value = null;
186
					break;
187
			}
188
189
			return $value;
190
		};
191
	}
192
193
	/**
194
	 * Creates a fallback rest update callback.
195
	 *
196
	 * @param Meta_Data $meta
197
	 * @return \Closure(mixed, \WP_Post|\WP_Term|\WP_User|\WP_Comment): mixed
198
	 */
199
	protected function create_rest_update_method( Meta_Data $meta ): \Closure {
200
		/**
201
		 * @param mixed $value
202
		 * @param \WP_Post|\WP_Term|\WP_User|\WP_Comment $object_instance
203
		 */
204
		return function ( $value, $object_instance ) use ( $meta ) {
205
			switch ( $meta->get_meta_type() ) {
206
				case 'post':
207
					/**
208
 * @var \WP_Post $object_instance
209
*/
210
					update_post_meta( $object_instance->ID, $meta->get_meta_key(), $value );
211
					break;
212
213
				case 'term':
214
					/**
215
 * @var \WP_Term $object_instance
216
*/
217
					update_term_meta( $object_instance->term_id, $meta->get_meta_key(), $value );
218
					break;
219
220
				case 'user':
221
					/**
222
 * @var \WP_User $object_instance
223
*/
224
					update_user_meta( $object_instance->ID, $meta->get_meta_key(), $value );
225
					break;
226
227
				case 'comment':
228
					/**
229
 * @var \WP_Comment $object_instance
230
*/
231
					update_comment_meta( (int) $object_instance->comment_ID, $meta->get_meta_key(), $value );
232
					break;
233
234
				default:
235
					// @codeCoverageIgnoreStart
236
					break;
237
					// @codeCoverageIgnoreEnd
238
			}
239
240
			return $value;
241
		};
242
	}
243
}
244