Completed
Push — master ( 874476...6bd4da )
by Glynn
33s queued 12s
created

Meta_Data_Registrar::register_for_user()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 2
rs 10
cc 1
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 bool
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 bool
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 bool
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 bool
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 bool
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
				"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() ) {
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 callable(mixed $value, \WP_Post|\WP_Term|\WP_User|\WP_Comment $object)
198
	 */
199
	protected function create_rest_update_method( Meta_Data $meta ): callable {
200
		/**
201
		 * @param mixed $value
202
		 * @param \WP_Post|\WP_Term|\WP_User|\WP_Comment $object
203
		 */
204
		return function( $value, $object ) use ( $meta ) {
205
			switch ( $meta->get_meta_type() ) {
206
				case 'post':
207
					/** @var \WP_Post $object */
208
					update_post_meta( $object->ID, $meta->get_meta_key(), $value );
209
					break;
210
211
				case 'term':
212
					/** @var \WP_Term $object */
213
					update_term_meta( $object->term_id, $meta->get_meta_key(), $value );
214
					break;
215
216
				case 'user':
217
					/** @var \WP_User $object */
218
					update_user_meta( $object->ID, $meta->get_meta_key(), $value );
219
					break;
220
221
				case 'comment':
222
					/** @var \WP_Comment $object */
223
					update_comment_meta( (int) $object->comment_ID, $meta->get_meta_key(), $value );
224
					break;
225
226
				default:
227
					// @codeCoverageIgnoreStart
228
					break;
229
					// @codeCoverageIgnoreEnd
230
			}
231
232
			return $value;
233
		};
234
	}
235
}
236