PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.3.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.3.0
2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 1.25.0 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.10.0 All 48 releases
thinkrank / includes / abilities / settings / class-update-social-platforms-settings.php

class-update-social-platforms-settings.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 2.3.0, at includes/abilities/settings/class-update-social-platforms-settings.php

202 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Update social platforms settings ability.
4 *
5 * @package ThinkRank\Abilities\Settings
6 */
7
8 declare(strict_types=1);
9
10 namespace ThinkRank\Abilities\Settings;
11
12 use ThinkRank\Abilities\Ability_Base;
13 use ThinkRank\Core\Settings;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit; // Exit if accessed directly.
17 }
18
19 /**
20 * Updates ThinkRank social platform verification settings.
21 *
22 * Mirrors `POST /thinkrank/v1/social-platforms/settings`: accepts any subset of
23 * the public platform IDs and sensitive verification codes, sanitizes them, and
24 * persists only the non-empty allowed keys via the Settings store (which
25 * encrypts the sensitive verification codes at rest). Returns the resulting
26 * settings with sensitive codes masked.
27 */
28 class Update_Social_Platforms_Settings extends Ability_Base {
29 /**
30 * Public platform IDs.
31 */
32 private const PUBLIC_KEYS = [
33 'facebook_app_id',
34 'facebook_admins',
35 'youtube_channel_id',
36 'whatsapp_business_id',
37 ];
38
39 /**
40 * Sensitive verification codes (encrypted at rest by the Settings store).
41 */
42 private const SENSITIVE_KEYS = [
43 'pinterest_site_verification',
44 'instagram_verification',
45 'tiktok_verification',
46 ];
47
48 /**
49 * Constructor.
50 */
51 public function __construct() {
52 $this->id = 'thinkrank/update-social-platforms-settings';
53 $this->label = __( 'Update ThinkRank Social Platform Settings', 'thinkrank' );
54 $this->description = __( 'Update ThinkRank social platform verification settings: public platform IDs (Facebook, YouTube, WhatsApp) and sensitive site-verification codes (Pinterest, Instagram, TikTok). Only non-empty provided keys are saved; sensitive codes are stored encrypted. Read the current values with get-social-platforms-settings first.', 'thinkrank' );
55 }
56
57 /**
58 * {@inheritDoc}
59 *
60 * @return array<string, bool|float|string>
61 */
62 public function get_annotations() {
63 return [
64 'readonly' => false,
65 'destructive' => true,
66 'idempotent' => true,
67 'priority' => 2.0,
68 'openWorldHint' => false,
69 ];
70 }
71
72 /**
73 * {@inheritDoc}
74 *
75 * @return array<string, mixed>
76 */
77 public function get_input_schema() {
78 return [
79 'type' => 'object',
80 'additionalProperties' => false,
81 'properties' => [
82 'settings' => [
83 'type' => 'object',
84 'description' => __( 'Social platform settings to update (any subset of the fields below).', 'thinkrank' ),
85 'additionalProperties' => false,
86 'properties' => [
87 'facebook_app_id' => [ 'type' => 'string' ],
88 'facebook_admins' => [ 'type' => 'string' ],
89 'youtube_channel_id' => [ 'type' => 'string' ],
90 'whatsapp_business_id' => [ 'type' => 'string' ],
91 'pinterest_site_verification' => [ 'type' => 'string' ],
92 'instagram_verification' => [ 'type' => 'string' ],
93 'tiktok_verification' => [ 'type' => 'string' ],
94 ],
95 ],
96 ],
97 'required' => [ 'settings' ],
98 ];
99 }
100
101 /**
102 * {@inheritDoc}
103 *
104 * @return array<string, mixed>
105 */
106 public function get_output_schema() {
107 return [
108 'type' => 'object',
109 'properties' => [
110 'success' => [ 'type' => 'boolean' ],
111 'message' => [ 'type' => 'string' ],
112 'settings' => [
113 'type' => 'object',
114 'description' => __( 'The resulting settings, with sensitive codes masked.', 'thinkrank' ),
115 'additionalProperties' => true,
116 ],
117 ],
118 ];
119 }
120
121 /**
122 * Execute ability.
123 *
124 * @param array<string, mixed> $input Ability input payload.
125 * @return array<string, mixed>|\WP_Error
126 */
127 public function execute( $input ) {
128 $settings = isset( $input['settings'] ) && is_array( $input['settings'] ) ? $input['settings'] : [];
129
130 if ( empty( $settings ) ) {
131 return new \WP_Error(
132 'thinkrank_missing_social_platforms_settings_payload',
133 __( 'A social platform settings payload is required.', 'thinkrank' ),
134 [ 'status' => 400 ]
135 );
136 }
137
138 $store = Settings::instance();
139 $allowed = array_merge( self::PUBLIC_KEYS, self::SENSITIVE_KEYS );
140 $found = false;
141
142 foreach ( $allowed as $key ) {
143 if ( ! array_key_exists( $key, $settings ) ) {
144 continue;
145 }
146
147 $value = sanitize_text_field( (string) $settings[ $key ] );
148
149 // Mirror the REST endpoint: only persist non-empty values so a
150 // masked/blank round-trip never wipes an existing code.
151 if ( '' === $value ) {
152 continue;
153 }
154
155 $store->set( $key, $value );
156 $found = true;
157 }
158
159 if ( ! $found ) {
160 return new \WP_Error(
161 'thinkrank_no_valid_social_platforms_setting_keys',
162 __( 'No valid, non-empty social platform setting keys were provided.', 'thinkrank' ),
163 [ 'status' => 400 ]
164 );
165 }
166
167 return [
168 'success' => true,
169 'message' => __( 'Social platform settings updated.', 'thinkrank' ),
170 'settings' => $this->read_masked( $store ),
171 ];
172 }
173
174 /**
175 * Read current settings back with sensitive codes masked.
176 *
177 * @param Settings $store Settings store.
178 * @return array<string, string>
179 */
180 private function read_masked( Settings $store ): array {
181 $out = [];
182
183 foreach ( self::PUBLIC_KEYS as $key ) {
184 $out[ $key ] = (string) $store->get( $key, '' );
185 }
186
187 foreach ( self::SENSITIVE_KEYS as $key ) {
188 $code = (string) $store->get( $key, '' );
189
190 if ( '' === $code ) {
191 $out[ $key ] = '';
192 } elseif ( strlen( $code ) > 8 ) {
193 $out[ $key ] = substr( $code, 0, 4 ) . 'XXXX';
194 } else {
195 $out[ $key ] = 'XXXX';
196 }
197 }
198
199 return $out;
200 }
201 }
202