PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.7.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.7.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 / api / class-global-robot-meta-endpoint.php

class-global-robot-meta-endpoint.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 2.7.0, at includes/api/class-global-robot-meta-endpoint.php

208 lines 5.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Global Robot Meta API Endpoints Class
4 *
5 * REST API endpoints for global robots meta tags settings.
6 *
7 * @package ThinkRank
8 * @subpackage API
9 * @since 1.0.0
10 */
11
12 declare(strict_types=1);
13
14 namespace ThinkRank\API;
15
16 use WP_REST_Controller;
17 use WP_REST_Request;
18 use WP_REST_Response;
19 use WP_Error;
20
21 // Prevent direct access
22 if (!defined('ABSPATH')) {
23 exit;
24 }
25
26 /**
27 * Global Robot Meta API Endpoints Class
28 *
29 * @since 1.0.0
30 */
31 class Global_Robot_Meta_Endpoint extends WP_REST_Controller {
32
33 /**
34 * API namespace
35 *
36 * @since 1.0.0
37 * @var string
38 */
39 protected $namespace = 'thinkrank/v1';
40
41 /**
42 * API resource base
43 *
44 * @since 1.0.0
45 * @var string
46 */
47 protected $rest_base = 'global-robot-meta';
48
49 /**
50 * Option name
51 */
52 private const OPTION_NAME = 'thinkrank_global_robot_meta_settings';
53
54 /**
55 * Register API routes
56 *
57 * @since 1.0.0
58 */
59 public function register_routes(): void {
60 register_rest_route(
61 $this->namespace,
62 '/' . $this->rest_base . '/settings',
63 [
64 [
65 'methods' => 'GET',
66 'callback' => [$this, 'get_settings'],
67 'permission_callback' => [$this, 'check_read_permissions']
68 ],
69 [
70 'methods' => 'POST',
71 'callback' => [$this, 'update_settings'],
72 'permission_callback' => [$this, 'check_manage_permissions'],
73 'args' => $this->get_settings_args()
74 ]
75 ]
76 );
77 }
78
79 /**
80 * Get settings
81 *
82 * @param WP_REST_Request $request Request object
83 * @return WP_REST_Response Response object
84 */
85 public function get_settings(WP_REST_Request $request): WP_REST_Response {
86 $settings = get_option(self::OPTION_NAME, $this->get_default_settings());
87
88 return new WP_REST_Response([
89 'success' => true,
90 'settings' => $settings,
91 'message' => 'Settings retrieved successfully'
92 ], 200);
93 }
94
95 /**
96 * Update settings
97 *
98 * @param WP_REST_Request $request Request object
99 * @return WP_REST_Response|WP_Error Response object or error
100 */
101 public function update_settings(WP_REST_Request $request) {
102 $settings = $request->get_param('settings');
103
104 if (empty($settings) || !is_array($settings)) {
105 return new WP_Error(
106 'invalid_settings',
107 'Settings must be provided as an array',
108 ['status' => 400]
109 );
110 }
111
112 // Merge into the existing option rather than replacing it, so sibling
113 // keys written by other paths (e.g. the SEO importer's
114 // noindex_date_archives / noindex_author_archives, consumed by the
115 // frontend) survive a save (#134).
116 $existing = get_option(self::OPTION_NAME, []);
117 if (!is_array($existing)) {
118 $existing = [];
119 }
120
121 $sanitized_settings = wp_parse_args($existing, $this->get_default_settings());
122
123 // Only write the keys the caller actually sent. Writing all six on every
124 // request meant a payload of {"noarchive": true} silently reset the
125 // other five — and diverged from the MCP ability, which writes the same
126 // option with an array_key_exists() merge (#560).
127 $found = false;
128 foreach (array_keys($this->get_default_settings()) as $key) {
129 if (array_key_exists($key, $settings)) {
130 $sanitized_settings[$key] = (bool) $settings[$key];
131 $found = true;
132 }
133 }
134
135 if (!$found) {
136 return new WP_Error(
137 'no_valid_settings',
138 'No valid robots meta setting keys were provided.',
139 ['status' => 400]
140 );
141 }
142
143 update_option(self::OPTION_NAME, $sanitized_settings);
144
145 return new WP_REST_Response([
146 'success' => true,
147 'settings' => $sanitized_settings,
148 'message' => 'Settings saved successfully'
149 ], 200);
150 }
151
152 /**
153 * Get default settings
154 *
155 * @return array
156 */
157 private function get_default_settings(): array {
158 return [
159 'index' => true,
160 'noindex' => false,
161 'nofollow' => false,
162 'noarchive' => false,
163 'noimageindex' => false,
164 'nosnippet' => false,
165 ];
166 }
167
168 /**
169 * Get settings args for validation
170 *
171 * @return array
172 */
173 private function get_settings_args(): array {
174 return [
175 'settings' => [
176 'required' => true,
177 'type' => 'object',
178 'properties' => [
179 'index' => ['type' => 'boolean'],
180 'noindex' => ['type' => 'boolean'],
181 'nofollow' => ['type' => 'boolean'],
182 'noarchive' => ['type' => 'boolean'],
183 'noimageindex' => ['type' => 'boolean'],
184 'nosnippet' => ['type' => 'boolean'],
185 ]
186 ]
187 ];
188 }
189
190 /**
191 * Check read permissions
192 *
193 * @return bool
194 */
195 public function check_read_permissions(): bool {
196 return current_user_can('edit_posts');
197 }
198
199 /**
200 * Check manage permissions
201 *
202 * @return bool
203 */
204 public function check_manage_permissions(): bool {
205 return \ThinkRank\Core\Capability_Manager::current_user_can('thinkrank_crawling');
206 }
207 }
208