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
wordpress-seo / src / bulk-editor / infrastructure / updates / meta-writer.php

meta-writer.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI trunk, at src/bulk-editor/infrastructure/updates/meta-writer.php

138 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
4 namespace Yoast\WP\SEO\Bulk_Editor\Infrastructure\Updates;
5
6 use WPSEO_Meta;
7 use WPSEO_Utils;
8 use Yoast\WP\SEO\Bulk_Editor\Application\Updates\Meta_Writer_Interface;
9 use Yoast\WP\SEO\Bulk_Editor\Domain\Updates\Update_Type;
10 use Yoast\WP\SEO\Helpers\Meta_Helper;
11
12 /**
13 * Persists a title, description and focus keyphrase to Yoast post meta.
14 *
15 * Writing through the meta helper triggers the post meta watcher, so the
16 * indexable of the post is rebuilt through the normal flow.
17 */
18 class Meta_Writer implements Meta_Writer_Interface {
19
20 /**
21 * The meta helper.
22 *
23 * @var Meta_Helper
24 */
25 private $meta_helper;
26
27 /**
28 * The constructor.
29 *
30 * @param Meta_Helper $meta_helper The meta helper.
31 */
32 public function __construct( Meta_Helper $meta_helper ) {
33 $this->meta_helper = $meta_helper;
34 }
35
36 /**
37 * Writes the title for a post.
38 *
39 * @param Update_Type $type The appearance the title belongs to.
40 * @param int $post_id The ID of the post.
41 * @param string $title The title to write.
42 *
43 * @return void
44 */
45 public function write_title( Update_Type $type, int $post_id, string $title ): void {
46 $key = $type->is_social() ? 'opengraph-title' : 'title';
47 $this->write( $key, $post_id, $title );
48 }
49
50 /**
51 * Writes the description for a post.
52 *
53 * @param Update_Type $type The appearance the description belongs to.
54 * @param int $post_id The ID of the post.
55 * @param string $description The description to write.
56 *
57 * @return void
58 */
59 public function write_description( Update_Type $type, int $post_id, string $description ): void {
60 $key = $type->is_social() ? 'opengraph-description' : 'metadesc';
61 $this->write( $key, $post_id, $description );
62 }
63
64 /**
65 * Writes the focus keyphrase for a post. The focus keyphrase is channel-agnostic,
66 * so it does not depend on the update type.
67 *
68 * Returns the sanitized value that was actually stored, so callers can detect
69 * when the input was silently altered (e.g. HTML stripped by sanitize_text_field).
70 *
71 * @param int $post_id The ID of the post.
72 * @param string $focus_keyphrase The focus keyphrase to write.
73 *
74 * @return string The sanitized focus keyphrase that was persisted.
75 */
76 public function write_focus_keyphrase( int $post_id, string $focus_keyphrase ): string {
77 return $this->write( 'focuskw', $post_id, $focus_keyphrase );
78 }
79
80 /**
81 * Writes a per-field score for a post.
82 *
83 * The score is routed through the same sanitization as a normal post save, which clamps it to a
84 * 0-100 integer.
85 *
86 * @param int $post_id The ID of the post.
87 * @param string $key The score meta key (without prefix) to write.
88 * @param int $score The 0-100 score to write.
89 *
90 * @return void
91 */
92 public function write_score( int $post_id, string $key, int $score ): void {
93 $this->write( $key, $post_id, (string) $score );
94 }
95
96 /**
97 * Sanitizes and persists a value under the given meta key.
98 *
99 * Returns the sanitized value so callers that need the stored value (e.g. to echo
100 * it back in the REST response) do not have to re-read from the database.
101 *
102 * @param string $key The meta key (without prefix) to store the value under.
103 * @param int $post_id The ID of the post.
104 * @param string $value The value to write.
105 *
106 * @return string The sanitized value that was persisted.
107 */
108 private function write( string $key, int $post_id, string $value ): string {
109 $sanitized = $this->sanitize( $key, $value );
110 $this->meta_helper->set_value( $key, $sanitized, $post_id );
111 return $sanitized;
112 }
113
114 /**
115 * Sanitizes a value the same way the post editor sanitizes meta values.
116 *
117 * Registered fields are routed through the canonical meta sanitizer so the
118 * field-specific handling and the `wpseo_sanitize_post_meta_*` filter run, matching
119 * a normal post save. Fields that are not registered (for example the Open Graph
120 * fields when social appearance is disabled) have no canonical sanitize callback, so
121 * they fall back to plain text sanitization.
122 *
123 * @param string $key The meta key (without prefix) the value is stored under.
124 * @param string $value The value to sanitize.
125 *
126 * @return string The sanitized value.
127 */
128 private function sanitize( string $key, string $value ): string {
129 $meta_key = WPSEO_Meta::$meta_prefix . $key;
130
131 if ( isset( WPSEO_Meta::$fields_index[ $meta_key ] ) ) {
132 return WPSEO_Meta::sanitize_post_meta( $value, $meta_key );
133 }
134
135 return WPSEO_Utils::sanitize_text_field( \trim( $value ) );
136 }
137 }
138