PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / trunk
Yoast SEO – Advanced SEO with real-time guidance and built-in AI vtrunk
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
← All changes | src/helpers/indexable-to-postmeta-helper.php +253 -14 18.0 → trunk View file →
@@ -5,9 +5,8 @@
5 5 use Yoast\WP\SEO\Models\Indexable;
6 6
7 7 /**
8 8 * A helper object to map indexable data to postmeta.
9 - * @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded
10 9 */
11 10 class Indexable_To_Postmeta_Helper {
12 11
13 12 /**
@@ -22,14 +21,80 @@
22 21 *
23 22 * @var array
24 23 */
25 24 protected $yoast_to_postmeta = [
26 - 'title' => 'title',
27 - 'description' => 'metadesc',
28 - 'open_graph_title' => 'opengraph-title',
29 - 'open_graph_description' => 'opengraph-description',
30 - 'twitter_title' => 'twitter-title',
31 - 'twitter_description' => 'twitter-description',
25 + 'title' => [
26 + 'post_meta_key' => 'title',
27 + 'map_method' => 'simple_map',
28 + ],
29 + 'description' => [
30 + 'post_meta_key' => 'metadesc',
31 + 'map_method' => 'simple_map',
32 + ],
33 + 'open_graph_title' => [
34 + 'post_meta_key' => 'opengraph-title',
35 + 'map_method' => 'simple_map',
36 + ],
37 + 'open_graph_description' => [
38 + 'post_meta_key' => 'opengraph-description',
39 + 'map_method' => 'simple_map',
40 + ],
41 + 'twitter_title' => [
42 + 'post_meta_key' => 'twitter-title',
43 + 'map_method' => 'simple_map',
44 + ],
45 + 'twitter_description' => [
46 + 'post_meta_key' => 'twitter-description',
47 + 'map_method' => 'simple_map',
48 + ],
49 + 'canonical' => [
50 + 'post_meta_key' => 'canonical',
51 + 'map_method' => 'simple_map',
52 + ],
53 + 'primary_focus_keyword' => [
54 + 'post_meta_key' => 'focuskw',
55 + 'map_method' => 'simple_map',
56 + ],
57 + 'open_graph_image' => [
58 + 'post_meta_key' => 'opengraph-image',
59 + 'map_method' => 'social_image_map',
60 + ],
61 + 'open_graph_image_id' => [
62 + 'post_meta_key' => 'opengraph-image-id',
63 + 'map_method' => 'social_image_map',
64 + ],
65 + 'twitter_image' => [
66 + 'post_meta_key' => 'twitter-image',
67 + 'map_method' => 'social_image_map',
68 + ],
69 + 'twitter_image_id' => [
70 + 'post_meta_key' => 'twitter-image-id',
71 + 'map_method' => 'social_image_map',
72 + ],
73 + 'is_robots_noindex' => [
74 + 'post_meta_key' => 'meta-robots-noindex',
75 + 'map_method' => 'noindex_map',
76 + ],
77 + 'is_robots_nofollow' => [
78 + 'post_meta_key' => 'meta-robots-nofollow',
79 + 'map_method' => 'nofollow_map',
80 + ],
81 + 'meta_robots_adv' => [
82 + 'post_meta_key' => 'meta-robots-adv',
83 + 'map_method' => 'robots_adv_map',
84 + ],
85 + 'is_cornerstone' => [
86 + 'post_meta_key' => 'is_cornerstone',
87 + 'map_method' => 'cornerstone_map',
88 + ],
89 + 'schema_page_type' => [
90 + 'post_meta_key' => 'schema_page_type',
91 + 'map_method' => 'simple_map',
92 + ],
93 + 'schema_article_type' => [
94 + 'post_meta_key' => 'schema_article_type',
95 + 'map_method' => 'simple_map',
96 + ],
32 97 ];
33 98
34 99 /**
35 100 * Indexable_To_Postmeta_Helper constructor.
@@ -42,18 +107,192 @@
42 107
43 108 /**
44 109 * Creates postmeta from a Yoast indexable.
45 110 *
46 - * @param Indexable $indexable The Yoast indexable.
111 + * @param Indexable $indexable The Yoast indexable.
112 + * @param bool $delete_empty Whether an empty indexable value should delete the post meta
113 + * instead of being left untouched. Defaults to false so importers,
114 + * which only fill in missing data, keep their set-only behaviour.
47 115 *
48 - * @return void.
116 + * @return void
49 117 */
50 - public function map_to_postmeta( $indexable ) {
51 - foreach ( $this->yoast_to_postmeta as $indexable_column => $post_meta_key ) {
52 - if ( empty( $indexable->{$indexable_column} ) ) {
53 - continue;
118 + public function map_to_postmeta( $indexable, $delete_empty = false ) {
119 + foreach ( \array_keys( $this->yoast_to_postmeta ) as $indexable_column ) {
120 + $this->map_column_to_postmeta( $indexable, $indexable_column, $delete_empty );
121 + }
122 + }
123 +
124 + /**
125 + * Creates postmeta from a single indexable column.
126 + *
127 + * @param Indexable $indexable The Yoast indexable.
128 + * @param string $indexable_column The indexable column to map.
129 + * @param bool $delete_empty Whether an empty value should delete the post meta key.
130 + *
131 + * @return void
132 + */
133 + public function map_column_to_postmeta( $indexable, $indexable_column, $delete_empty = false ) {
134 + // The advanced-robots flags are persisted together under one meta key, so they cascade through it.
135 + if ( \in_array( $indexable_column, [ 'is_robots_noimageindex', 'is_robots_noarchive', 'is_robots_nosnippet' ], true ) ) {
136 + $indexable_column = 'meta_robots_adv';
137 + }
138 +
139 + if ( ! isset( $this->yoast_to_postmeta[ $indexable_column ] ) ) {
140 + return;
141 + }
142 +
143 + $map_info = $this->yoast_to_postmeta[ $indexable_column ];
144 + \call_user_func( [ $this, $map_info['map_method'] ], $indexable, $map_info['post_meta_key'], $indexable_column, $delete_empty );
145 + }
146 +
147 + /**
148 + * Uses a simple set_value for non-empty data.
149 + *
150 + * @param Indexable $indexable The Yoast indexable.
151 + * @param string $post_meta_key The post_meta key that will be populated.
152 + * @param string $indexable_column The indexable data that will be mapped to post_meta.
153 + * @param bool $delete_empty Whether an empty value should delete the post meta key.
154 + *
155 + * @return void
156 + */
157 + public function simple_map( $indexable, $post_meta_key, $indexable_column, $delete_empty = false ) {
158 + $value = $indexable->{$indexable_column};
159 +
160 + // Strict emptiness check because empty() would treat the literal string '0' as empty and drop it.
161 + if ( $value === null || $value === '' ) {
162 + if ( $delete_empty ) {
163 + $this->meta->delete( $post_meta_key, $indexable->object_id );
54 164 }
165 + return;
166 + }
55 167
56 - $this->meta->set_value( $post_meta_key, $indexable->{$indexable_column}, $indexable->object_id );
168 + $this->meta->set_value( $post_meta_key, $value, $indexable->object_id );
169 + }
170 +
171 + /**
172 + * Maps the cornerstone flag, which is stored as '1' when on and absent when off.
173 + *
174 + * @param Indexable $indexable The Yoast indexable.
175 + * @param string $post_meta_key The post_meta key that will be populated.
176 + * @param string $indexable_column The indexable data that will be mapped to post_meta.
177 + * @param bool $delete_empty Whether a disabled flag should delete the post meta key.
178 + *
179 + * @return void
180 + */
181 + public function cornerstone_map( $indexable, $post_meta_key, $indexable_column, $delete_empty = false ) {
182 + if ( $indexable->is_cornerstone === true ) {
183 + $this->meta->set_value( $post_meta_key, '1', $indexable->object_id );
184 + return;
57 185 }
186 +
187 + if ( $delete_empty ) {
188 + $this->meta->delete( $post_meta_key, $indexable->object_id );
189 + }
190 + }
191 +
192 + /**
193 + * Map social image data only if social image is explicitly set.
194 + *
195 + * @param Indexable $indexable The Yoast indexable.
196 + * @param string $post_meta_key The post_meta key that will be populated.
197 + * @param string $indexable_column The indexable data that will be mapped to post_meta.
198 + *
199 + * @return void
200 + */
201 + public function social_image_map( $indexable, $post_meta_key, $indexable_column ) {
202 + if ( empty( $indexable->{$indexable_column} ) ) {
203 + return;
204 + }
205 +
206 + switch ( $indexable_column ) {
207 + case 'open_graph_image':
208 + case 'open_graph_image_id':
209 + $source = $indexable->open_graph_image_source;
210 + break;
211 + case 'twitter_image':
212 + case 'twitter_image_id':
213 + $source = $indexable->twitter_image_source;
214 + break;
215 + }
216 +
217 + // Map the social image data only when the social image is explicitly set.
218 + if ( $source === 'set-by-user' || $source === 'imported' ) {
219 + $value = (string) $indexable->{$indexable_column};
220 +
221 + $this->meta->set_value( $post_meta_key, $value, $indexable->object_id );
222 + }
223 + }
224 +
225 + /**
226 + * Deletes the noindex post_meta key if no noindex in the indexable. Populates the post_meta key appropriately if there is noindex in the indexable.
227 + *
228 + * @param Indexable $indexable The Yoast indexable.
229 + * @param string $post_meta_key The post_meta key that will be populated.
230 + *
231 + * @return void
232 + */
233 + public function noindex_map( $indexable, $post_meta_key ) {
234 + if ( $indexable->is_robots_noindex === null ) {
235 + $this->meta->delete( $post_meta_key, $indexable->object_id );
236 + return;
237 + }
238 +
239 + if ( $indexable->is_robots_noindex === false ) {
240 + $this->meta->set_value( $post_meta_key, 2, $indexable->object_id );
241 + }
242 +
243 + if ( $indexable->is_robots_noindex === true ) {
244 + $this->meta->set_value( $post_meta_key, 1, $indexable->object_id );
245 + }
246 + }
247 +
248 + /**
249 + * Deletes the nofollow post_meta key if no nofollow in the indexable or if nofollow is false. Populates the post_meta key appropriately if there is a true nofollow in the indexable.
250 + *
251 + * @param Indexable $indexable The Yoast indexable.
252 + * @param string $post_meta_key The post_meta key that will be populated.
253 + *
254 + * @return void
255 + */
256 + public function nofollow_map( $indexable, $post_meta_key ) {
257 + if ( $indexable->is_robots_nofollow === null || $indexable->is_robots_nofollow === false ) {
258 + $this->meta->delete( $post_meta_key, $indexable->object_id );
259 + }
260 +
261 + if ( $indexable->is_robots_nofollow === true ) {
262 + $this->meta->set_value( $post_meta_key, 1, $indexable->object_id );
263 + }
264 + }
265 +
266 + /**
267 + * Deletes the nofollow post_meta key if no nofollow in the indexable or if nofollow is false. Populates the post_meta key appropriately if there is a true nofollow in the indexable.
268 + *
269 + * @param Indexable $indexable The Yoast indexable.
270 + * @param string $post_meta_key The post_meta key that will be populated.
271 + *
272 + * @return void
273 + */
274 + public function robots_adv_map( $indexable, $post_meta_key ) {
275 + $adv_settings_to_be_imported = [];
276 + $no_adv_settings = true;
277 +
278 + if ( $indexable->is_robots_noimageindex === true ) {
279 + $adv_settings_to_be_imported[] = 'noimageindex';
280 + $no_adv_settings = false;
281 + }
282 + if ( $indexable->is_robots_noarchive === true ) {
283 + $adv_settings_to_be_imported[] = 'noarchive';
284 + $no_adv_settings = false;
285 + }
286 + if ( $indexable->is_robots_nosnippet === true ) {
287 + $adv_settings_to_be_imported[] = 'nosnippet';
288 + $no_adv_settings = false;
289 + }
290 +
291 + if ( $no_adv_settings === true ) {
292 + $this->meta->delete( $post_meta_key, $indexable->object_id );
293 + return;
294 + }
295 +
296 + $this->meta->set_value( $post_meta_key, \implode( ',', $adv_settings_to_be_imported ), $indexable->object_id );
58 297 }
59 298 }