PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 1.1.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v1.1.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-settings-management-endpoint.php

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

2,004 lines 67.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Settings Management API Endpoints Class
4 *
5 * REST API endpoints for centralized settings management across all SEO managers
6 * including global settings CRUD, validation and schema management, import/export
7 * functionality, and backup/restore operations. Provides comprehensive API access
8 * to Settings Manager functionality with proper authentication and validation.
9 *
10 * @package ThinkRank
11 * @subpackage API
12 * @since 1.0.0
13 */
14
15 declare(strict_types=1);
16
17 namespace ThinkRank\API;
18
19 use ThinkRank\Core\Settings_Manager;
20 use ThinkRank\SEO\Site_Identity_Manager;
21 use ThinkRank\SEO\Performance_Monitoring_Manager;
22 use ThinkRank\SEO\AI_Content_Analyzer;
23 use ThinkRank\SEO\Content_Optimization_Manager;
24 use ThinkRank\SEO\Schema_Management_System;
25 use ThinkRank\SEO\Social_Meta_Manager;
26 use ThinkRank\SEO\Sitemap_Generator;
27 use WP_REST_Controller;
28 use WP_REST_Request;
29 use WP_REST_Response;
30 use WP_Error;
31
32 /**
33 * Settings Management API Endpoints Class
34 *
35 * Provides REST API endpoints for centralized settings management operations
36 * including global settings CRUD, validation, import/export, backup/restore,
37 * and cross-manager settings coordination with proper authentication and validation.
38 *
39 * @since 1.0.0
40 */
41 class Settings_Management_Endpoint extends WP_REST_Controller {
42
43 /**
44 * Settings Manager instance
45 *
46 * @since 1.0.0
47 * @var Settings_Manager
48 */
49 private Settings_Manager $settings_manager;
50
51 /**
52 * SEO Manager instances for integration
53 *
54 * @since 1.0.0
55 * @var array
56 */
57 private array $seo_managers;
58
59 /**
60 * API namespace
61 *
62 * @since 1.0.0
63 * @var string
64 */
65 protected $namespace = 'thinkrank/v1';
66
67 /**
68 * API resource base
69 *
70 * @since 1.0.0
71 * @var string
72 */
73 protected $rest_base = 'settings-management';
74
75 /**
76 * Supported setting categories
77 *
78 * @since 1.0.0
79 * @var array
80 */
81 private array $setting_categories = [
82 'site_identity' => 'Site Identity & Global SEO',
83 'content_analysis' => 'AI Content Analysis',
84 'content_optimization' => 'Content Optimization',
85 'performance_monitoring' => 'Performance Monitoring',
86 'schema_management' => 'Schema Management',
87 'social_media' => 'Social Media & Open Graph',
88 'sitemap' => 'XML Sitemap Management',
89 'integrations' => 'External Integrations',
90 'analytics_integration' => 'Analytics Integration',
91 'seo_analytics' => 'SEO Analytics & Intelligence',
92 'global_defaults' => 'Global Default Settings'
93 ];
94
95 /**
96 * Constructor
97 *
98 * @since 1.0.0
99 */
100 public function __construct() {
101 $this->settings_manager = new Settings_Manager();
102
103 // Initialize SEO manager instances for integration
104 $this->seo_managers = [
105 'site_identity' => new Site_Identity_Manager(),
106 'performance_monitoring' => new Performance_Monitoring_Manager(),
107 'ai_content_analyzer' => new AI_Content_Analyzer(),
108 'content_optimization' => new Content_Optimization_Manager(),
109 'schema_management' => new Schema_Management_System(),
110 'social_media' => new Social_Meta_Manager(),
111 'sitemap' => new Sitemap_Generator(),
112 'analytics_integration' => new Performance_Monitoring_Manager()
113 ];
114 }
115
116 /**
117 * Register API routes
118 *
119 * @since 1.0.0
120 */
121 public function register_routes(): void {
122 // Global settings management
123 register_rest_route(
124 $this->namespace,
125 '/' . $this->rest_base . '/global',
126 [
127 [
128 'methods' => 'GET',
129 'callback' => [$this, 'get_global_settings'],
130 'permission_callback' => [$this, 'check_read_permissions']
131 ],
132 [
133 'methods' => 'POST',
134 'callback' => [$this, 'update_global_settings'],
135 'permission_callback' => [$this, 'check_manage_permissions'],
136 'args' => $this->get_global_settings_args()
137 ]
138 ]
139 );
140
141 // Category-specific settings
142 register_rest_route(
143 $this->namespace,
144 '/' . $this->rest_base . '/category/(?P<category>[a-zA-Z0-9_-]+)',
145 [
146 [
147 'methods' => 'GET',
148 'callback' => [$this, 'get_category_settings'],
149 'permission_callback' => [$this, 'check_read_permissions'],
150 'args' => [
151 'category' => [
152 'required' => true,
153 'type' => 'string',
154 'enum' => array_keys($this->setting_categories)
155 ]
156 ]
157 ],
158 [
159 'methods' => 'POST',
160 'callback' => [$this, 'update_category_settings'],
161 'permission_callback' => [$this, 'check_manage_permissions'],
162 'args' => $this->get_category_settings_args()
163 ]
164 ]
165 );
166
167 // Settings validation and schema
168 register_rest_route(
169 $this->namespace,
170 '/' . $this->rest_base . '/validate',
171 [
172 [
173 'methods' => 'POST',
174 'callback' => [$this, 'validate_settings'],
175 'permission_callback' => [$this, 'check_read_permissions'],
176 'args' => $this->get_validation_args()
177 ]
178 ]
179 );
180
181 // Settings schema management
182 register_rest_route(
183 $this->namespace,
184 '/' . $this->rest_base . '/schema',
185 [
186 [
187 'methods' => 'GET',
188 'callback' => [$this, 'get_settings_schema'],
189 'permission_callback' => [$this, 'check_read_permissions']
190 ]
191 ]
192 );
193
194 // Settings import/export
195 register_rest_route(
196 $this->namespace,
197 '/' . $this->rest_base . '/export',
198 [
199 [
200 'methods' => 'POST',
201 'callback' => [$this, 'export_settings'],
202 'permission_callback' => [$this, 'check_manage_permissions'],
203 'args' => $this->get_export_args()
204 ]
205 ]
206 );
207
208 register_rest_route(
209 $this->namespace,
210 '/' . $this->rest_base . '/import',
211 [
212 [
213 'methods' => 'POST',
214 'callback' => [$this, 'import_settings'],
215 'permission_callback' => [$this, 'check_manage_permissions'],
216 'args' => $this->get_import_args()
217 ]
218 ]
219 );
220
221 // Settings backup/restore
222 register_rest_route(
223 $this->namespace,
224 '/' . $this->rest_base . '/backup',
225 [
226 [
227 'methods' => 'POST',
228 'callback' => [$this, 'create_settings_backup'],
229 'permission_callback' => [$this, 'check_manage_permissions'],
230 'args' => $this->get_backup_args()
231 ]
232 ]
233 );
234
235 register_rest_route(
236 $this->namespace,
237 '/' . $this->rest_base . '/restore',
238 [
239 [
240 'methods' => 'POST',
241 'callback' => [$this, 'restore_settings_backup'],
242 'permission_callback' => [$this, 'check_manage_permissions'],
243 'args' => $this->get_restore_args()
244 ]
245 ]
246 );
247
248 // Settings conflicts resolution
249 register_rest_route(
250 $this->namespace,
251 '/' . $this->rest_base . '/conflicts',
252 [
253 [
254 'methods' => 'GET',
255 'callback' => [$this, 'detect_settings_conflicts'],
256 'permission_callback' => [$this, 'check_read_permissions']
257 ],
258 [
259 'methods' => 'POST',
260 'callback' => [$this, 'resolve_settings_conflicts'],
261 'permission_callback' => [$this, 'check_manage_permissions'],
262 'args' => $this->get_conflict_resolution_args()
263 ]
264 ]
265 );
266
267 // Settings reset
268 register_rest_route(
269 $this->namespace,
270 '/' . $this->rest_base . '/reset',
271 [
272 [
273 'methods' => 'POST',
274 'callback' => [$this, 'reset_settings'],
275 'permission_callback' => [$this, 'check_manage_permissions'],
276 'args' => $this->get_reset_args()
277 ]
278 ]
279 );
280
281 // Bulk operations
282 register_rest_route(
283 $this->namespace,
284 '/' . $this->rest_base . '/bulk',
285 [
286 [
287 'methods' => 'POST',
288 'callback' => [$this, 'bulk_operations'],
289 'permission_callback' => [$this, 'check_manage_permissions'],
290 'args' => $this->get_bulk_operations_args()
291 ]
292 ]
293 );
294
295 // Database maintenance operations
296 register_rest_route(
297 $this->namespace,
298 '/' . $this->rest_base . '/maintenance/performance-indexes',
299 [
300 [
301 'methods' => 'POST',
302 'callback' => [$this, 'add_performance_indexes'],
303 'permission_callback' => [$this, 'check_manage_permissions']
304 ]
305 ]
306 );
307 }
308
309 /**
310 * Get global settings across all categories
311 *
312 * @since 1.0.0
313 *
314 * @param WP_REST_Request $request Request object
315 * @return WP_REST_Response Response object
316 */
317 public function get_global_settings(WP_REST_Request $request): WP_REST_Response {
318 try {
319 $include_categories = $request->get_param('categories') ?? array_keys($this->setting_categories);
320 $include_schema = $request->get_param('include_schema') ?? false;
321
322 $global_settings = [];
323 $settings_schema = [];
324
325 foreach ($include_categories as $category) {
326 if (!isset($this->setting_categories[$category])) {
327 continue;
328 }
329
330 // Get settings for each category using Settings Manager
331 $category_settings = $this->settings_manager->get_settings($category);
332 $global_settings[$category] = $category_settings;
333
334 // Get schema if requested
335 if ($include_schema && isset($this->seo_managers[$category])) {
336 $settings_schema[$category] = $this->seo_managers[$category]->get_settings_schema($category);
337 }
338 }
339
340 // Get global metadata
341 $metadata = [
342 'total_categories' => count($this->setting_categories),
343 'loaded_categories' => count($global_settings),
344 'last_updated' => $this->get_last_settings_update(),
345 'settings_version' => $this->get_settings_version()
346 ];
347
348 return new WP_REST_Response([
349 'success' => true,
350 'data' => [
351 'settings' => $global_settings,
352 'schema' => $settings_schema,
353 'metadata' => $metadata,
354 'categories' => $this->setting_categories
355 ],
356 'message' => 'Global settings retrieved successfully'
357 ], 200);
358
359 } catch (\Exception $e) {
360 return new WP_REST_Response([
361 'success' => false,
362 'error' => 'Failed to retrieve global settings: ' . $e->getMessage()
363 ], 500);
364 }
365 }
366
367 /**
368 * Update global settings across multiple categories
369 *
370 * @since 1.0.0
371 *
372 * @param WP_REST_Request $request Request object
373 * @return WP_REST_Response|WP_Error Response object or error
374 */
375 public function update_global_settings(WP_REST_Request $request) {
376 try {
377 $settings = $request->get_param('settings');
378 $validate_before_update = $request->get_param('validate') ?? true;
379
380 // Validate settings structure
381 if (empty($settings) || !is_array($settings)) {
382 return new WP_Error(
383 'invalid_settings',
384 'Settings must be provided as an array',
385 ['status' => 400]
386 );
387 }
388
389 $validation_results = [];
390 $update_results = [];
391
392 // Validate all settings before updating if requested
393 if ($validate_before_update) {
394 foreach ($settings as $category => $category_settings) {
395 if (!isset($this->setting_categories[$category])) {
396 continue;
397 }
398
399 if (isset($this->seo_managers[$category])) {
400 $validation = $this->seo_managers[$category]->validate_settings($category_settings);
401 $validation_results[$category] = $validation;
402
403 if (!$validation['valid']) {
404 return new WP_Error(
405 'validation_failed',
406 "Settings validation failed for category: {$category}",
407 [
408 'status' => 400,
409 'validation_results' => $validation_results
410 ]
411 );
412 }
413 }
414 }
415 }
416
417 // Update settings for each category
418 foreach ($settings as $category => $category_settings) {
419 if (!isset($this->setting_categories[$category])) {
420 continue;
421 }
422
423 try {
424 // Update using Settings Manager
425 $update_success = $this->settings_manager->update_settings($category_settings, $category);
426
427 // Also update through specific SEO manager if available
428 if (isset($this->seo_managers[$category])) {
429 $manager_update = $this->seo_managers[$category]->save_settings('site', null, $category_settings);
430 $update_success = $update_success && $manager_update;
431 }
432
433 $update_results[$category] = [
434 'success' => $update_success,
435 'settings_count' => count($category_settings)
436 ];
437
438 } catch (\Exception $e) {
439 $update_results[$category] = [
440 'success' => false,
441 'error' => $e->getMessage()
442 ];
443 }
444 }
445
446 // Update settings version and timestamp
447 $this->update_settings_metadata();
448
449 // Get updated settings
450 $updated_settings = [];
451 foreach (array_keys($settings) as $category) {
452 if (isset($this->setting_categories[$category])) {
453 $updated_settings[$category] = $this->settings_manager->get_settings($category);
454 }
455 }
456
457 return new WP_REST_Response([
458 'success' => true,
459 'data' => [
460 'updated_settings' => $updated_settings,
461 'validation_results' => $validation_results,
462 'update_results' => $update_results,
463 'settings_version' => $this->get_settings_version()
464 ],
465 'message' => 'Global settings updated successfully'
466 ], 200);
467
468 } catch (\Exception $e) {
469 return new WP_Error(
470 'update_failed',
471 'Global settings update failed: ' . $e->getMessage(),
472 ['status' => 500]
473 );
474 }
475 }
476
477 /**
478 * Get settings for specific category
479 *
480 * @since 1.0.0
481 *
482 * @param WP_REST_Request $request Request object
483 * @return WP_REST_Response|WP_Error Response object or error
484 */
485 public function get_category_settings(WP_REST_Request $request) {
486 try {
487 $category = $request->get_param('category');
488 $include_schema = $request->get_param('include_schema') ?? false;
489
490 // Validate category
491 if (!isset($this->setting_categories[$category])) {
492 return new WP_Error(
493 'invalid_category',
494 'Invalid settings category provided',
495 ['status' => 400]
496 );
497 }
498
499 // Get category settings
500 $category_settings = $this->settings_manager->get_settings($category);
501
502 // Get schema if requested
503 $schema = [];
504 if ($include_schema && isset($this->seo_managers[$category])) {
505 $schema = $this->seo_managers[$category]->get_settings_schema($category);
506 }
507
508 // Get category metadata
509 $metadata = [
510 'category' => $category,
511 'category_name' => $this->setting_categories[$category],
512 'settings_count' => count($category_settings),
513 'last_updated' => $this->get_category_last_update($category),
514 'has_manager' => isset($this->seo_managers[$category])
515 ];
516
517 return new WP_REST_Response([
518 'success' => true,
519 'data' => [
520 'settings' => $category_settings,
521 'schema' => $schema,
522 'metadata' => $metadata
523 ],
524 'message' => "Settings for category '{$category}' retrieved successfully"
525 ], 200);
526
527 } catch (\Exception $e) {
528 return new WP_Error(
529 'retrieval_failed',
530 'Category settings retrieval failed: ' . $e->getMessage(),
531 ['status' => 500]
532 );
533 }
534 }
535
536 /**
537 * Update settings for specific category
538 *
539 * @since 1.0.0
540 *
541 * @param WP_REST_Request $request Request object
542 * @return WP_REST_Response|WP_Error Response object or error
543 */
544 public function update_category_settings(WP_REST_Request $request) {
545 try {
546 $category = $request->get_param('category');
547 $request_data = $request->get_param('settings');
548 $validate_before_update = $request->get_param('validate') ?? true;
549
550 // Extract only the actual settings data, not metadata
551 if (isset($request_data['settings'])) {
552 // If settings are nested under 'settings' key, use that
553 $settings = $request_data['settings'];
554 } else {
555 // Otherwise use the data directly
556 $settings = $request_data;
557 }
558
559 // Validate category
560 if (!isset($this->setting_categories[$category])) {
561 return new WP_Error(
562 'invalid_category',
563 'Invalid settings category provided',
564 ['status' => 400]
565 );
566 }
567
568 // Validate settings
569 if (empty($settings) || !is_array($settings)) {
570 return new WP_Error(
571 'invalid_settings',
572 'Settings must be provided as an array',
573 ['status' => 400]
574 );
575 }
576
577 $validation_result = ['valid' => true];
578
579 // Validate settings if requested
580 if ($validate_before_update && isset($this->seo_managers[$category])) {
581 $validation_result = $this->seo_managers[$category]->validate_settings($settings);
582
583 if (!$validation_result['valid']) {
584 return new WP_Error(
585 'validation_failed',
586 "Settings validation failed for category: {$category}",
587 [
588 'status' => 400,
589 'validation_errors' => $validation_result['errors'],
590 'validation_warnings' => $validation_result['warnings']
591 ]
592 );
593 }
594 }
595
596 // Update settings
597 $update_success = $this->settings_manager->update_settings($settings, $category);
598
599 // Also update through specific SEO manager if available
600 if (isset($this->seo_managers[$category])) {
601 $context_type = $request->get_param('context_type') ?? 'site';
602 $context_id = $request->get_param('context_id') ?? null;
603 $manager_update = $this->seo_managers[$category]->save_settings($context_type, $context_id, $settings);
604 $update_success = $update_success && $manager_update;
605 }
606
607 if (!$update_success) {
608 return new WP_Error(
609 'update_failed',
610 "Failed to update settings for category: {$category}",
611 ['status' => 500]
612 );
613 }
614
615 // Update category metadata
616 $this->update_category_metadata($category);
617
618 // Get updated settings
619 $updated_settings = $this->settings_manager->get_settings($category);
620
621 return new WP_REST_Response([
622 'success' => true,
623 'data' => [
624 'category' => $category,
625 'updated_settings' => $updated_settings,
626 'validation_result' => $validation_result,
627 'settings_count' => count($updated_settings)
628 ],
629 'message' => "Settings for category '{$category}' updated successfully"
630 ], 200);
631
632 } catch (\Exception $e) {
633 return new WP_Error(
634 'update_failed',
635 'Category settings update failed: ' . $e->getMessage(),
636 ['status' => 500]
637 );
638 }
639 }
640
641 /**
642 * Validate settings across categories
643 *
644 * @since 1.0.0
645 *
646 * @param WP_REST_Request $request Request object
647 * @return WP_REST_Response Response object
648 */
649 public function validate_settings(WP_REST_Request $request): WP_REST_Response {
650 try {
651 $settings = $request->get_param('settings');
652 $categories = $request->get_param('categories') ?? array_keys($this->setting_categories);
653
654 $validation_results = [];
655 $overall_valid = true;
656
657 foreach ($categories as $category) {
658 if (!isset($this->setting_categories[$category])) {
659 continue;
660 }
661
662 $category_settings = $settings[$category] ?? [];
663
664 if (isset($this->seo_managers[$category])) {
665 $validation = $this->seo_managers[$category]->validate_settings($category_settings);
666 $validation_results[$category] = $validation;
667
668 if (!$validation['valid']) {
669 $overall_valid = false;
670 }
671 } else {
672 // Basic validation for categories without specific managers
673 $validation_results[$category] = [
674 'valid' => true,
675 'errors' => [],
676 'warnings' => [],
677 'suggestions' => []
678 ];
679 }
680 }
681
682 // Check for cross-category conflicts
683 $conflict_analysis = $this->analyze_cross_category_conflicts($settings);
684
685 return new WP_REST_Response([
686 'success' => true,
687 'data' => [
688 'validation_results' => $validation_results,
689 'overall_valid' => $overall_valid,
690 'conflict_analysis' => $conflict_analysis,
691 'validated_categories' => count($validation_results),
692 'validation_timestamp' => current_time('mysql')
693 ],
694 'message' => 'Settings validation completed'
695 ], 200);
696
697 } catch (\Exception $e) {
698 return new WP_REST_Response([
699 'success' => false,
700 'error' => 'Settings validation failed: ' . $e->getMessage()
701 ], 500);
702 }
703 }
704
705 /**
706 * Get settings schema for all categories
707 *
708 * @since 1.0.0
709 *
710 * @param WP_REST_Request $request Request object
711 * @return WP_REST_Response Response object
712 */
713 public function get_settings_schema(WP_REST_Request $request): WP_REST_Response {
714 try {
715 $categories = $request->get_param('categories') ?? array_keys($this->setting_categories);
716
717 $schema_data = [];
718
719 foreach ($categories as $category) {
720 if (!isset($this->setting_categories[$category])) {
721 continue;
722 }
723
724 if (isset($this->seo_managers[$category])) {
725 $schema_data[$category] = [
726 'schema' => $this->seo_managers[$category]->get_settings_schema($category),
727 'defaults' => $this->seo_managers[$category]->get_default_settings($category),
728 'category_name' => $this->setting_categories[$category]
729 ];
730 } else {
731 $schema_data[$category] = [
732 'schema' => [],
733 'defaults' => [],
734 'category_name' => $this->setting_categories[$category]
735 ];
736 }
737 }
738
739 return new WP_REST_Response([
740 'success' => true,
741 'data' => [
742 'schema' => $schema_data,
743 'categories' => $this->setting_categories,
744 'schema_version' => $this->get_schema_version(),
745 'generated_at' => current_time('mysql')
746 ],
747 'message' => 'Settings schema retrieved successfully'
748 ], 200);
749
750 } catch (\Exception $e) {
751 return new WP_REST_Response([
752 'success' => false,
753 'error' => 'Failed to retrieve settings schema: ' . $e->getMessage()
754 ], 500);
755 }
756 }
757
758 /**
759 * Export settings
760 *
761 * @since 1.0.0
762 *
763 * @param WP_REST_Request $request Request object
764 * @return WP_REST_Response|WP_Error Response object or error
765 */
766 public function export_settings(WP_REST_Request $request) {
767 try {
768 $categories = $request->get_param('categories') ?? array_keys($this->setting_categories);
769 $format = $request->get_param('format') ?? 'json';
770 $include_metadata = $request->get_param('include_metadata') ?? true;
771
772 // Validate format
773 if (!in_array($format, ['json', 'yaml', 'xml'], true)) {
774 return new WP_Error(
775 'invalid_format',
776 'Invalid export format. Supported formats: json, yaml, xml',
777 ['status' => 400]
778 );
779 }
780
781 $export_data = [];
782
783 // Export settings for each category
784 foreach ($categories as $category) {
785 if (!isset($this->setting_categories[$category])) {
786 continue;
787 }
788
789 $export_data[$category] = $this->settings_manager->get_settings($category);
790 }
791
792 // Add metadata if requested
793 $metadata = [];
794 if ($include_metadata) {
795 $metadata = [
796 'export_timestamp' => current_time('mysql'),
797 'export_version' => $this->get_settings_version(),
798 'wordpress_version' => get_bloginfo('version'),
799 'thinkrank_version' => '1.0.0',
800 'site_url' => home_url(),
801 'exported_categories' => $categories
802 ];
803 }
804
805 // Format export data
806 $formatted_export = $this->format_export_data($export_data, $metadata, $format);
807
808 return new WP_REST_Response([
809 'success' => true,
810 'data' => [
811 'export_data' => $formatted_export,
812 'format' => $format,
813 'metadata' => $metadata,
814 'exported_categories' => count($export_data)
815 ],
816 'message' => 'Settings exported successfully'
817 ], 200);
818
819 } catch (\Exception $e) {
820 return new WP_Error(
821 'export_failed',
822 'Settings export failed: ' . $e->getMessage(),
823 ['status' => 500]
824 );
825 }
826 }
827
828 /**
829 * Import settings
830 *
831 * @since 1.0.0
832 *
833 * @param WP_REST_Request $request Request object
834 * @return WP_REST_Response|WP_Error Response object or error
835 */
836 public function import_settings(WP_REST_Request $request) {
837 try {
838 $import_data = $request->get_param('import_data');
839 $format = $request->get_param('format') ?? 'json';
840 $validate_before_import = $request->get_param('validate') ?? true;
841 $overwrite_existing = $request->get_param('overwrite_existing') ?? false;
842
843 // Validate import data
844 if (empty($import_data)) {
845 return new WP_Error(
846 'missing_import_data',
847 'Import data is required',
848 ['status' => 400]
849 );
850 }
851
852 // Parse import data based on format
853 $parsed_data = $this->parse_import_data($import_data, $format);
854
855 if (!$parsed_data) {
856 return new WP_Error(
857 'invalid_import_data',
858 'Failed to parse import data',
859 ['status' => 400]
860 );
861 }
862
863 $import_results = [];
864 $validation_results = [];
865
866 // Validate imported settings if requested
867 if ($validate_before_import) {
868 foreach ($parsed_data as $category => $category_settings) {
869 if (!isset($this->setting_categories[$category])) {
870 continue;
871 }
872
873 if (isset($this->seo_managers[$category])) {
874 $validation = $this->seo_managers[$category]->validate_settings($category_settings);
875 $validation_results[$category] = $validation;
876
877 if (!$validation['valid']) {
878 return new WP_Error(
879 'import_validation_failed',
880 "Import validation failed for category: {$category}",
881 [
882 'status' => 400,
883 'validation_results' => $validation_results
884 ]
885 );
886 }
887 }
888 }
889 }
890
891 // Import settings for each category
892 foreach ($parsed_data as $category => $category_settings) {
893 if (!isset($this->setting_categories[$category])) {
894 $import_results[$category] = [
895 'success' => false,
896 'error' => 'Invalid category'
897 ];
898 continue;
899 }
900
901 try {
902 // Check if settings exist and handle overwrite
903 $existing_settings = $this->settings_manager->get_settings($category);
904
905 if (!empty($existing_settings) && !$overwrite_existing) {
906 $import_results[$category] = [
907 'success' => false,
908 'error' => 'Settings exist and overwrite is disabled'
909 ];
910 continue;
911 }
912
913 // Import settings
914 $import_success = $this->settings_manager->update_settings($category_settings, $category);
915
916 // Also update through specific SEO manager if available
917 if (isset($this->seo_managers[$category])) {
918 $manager_update = $this->seo_managers[$category]->save_settings('site', null, $category_settings);
919 $import_success = $import_success && $manager_update;
920 }
921
922 $import_results[$category] = [
923 'success' => $import_success,
924 'settings_count' => count($category_settings)
925 ];
926
927 } catch (\Exception $e) {
928 $import_results[$category] = [
929 'success' => false,
930 'error' => $e->getMessage()
931 ];
932 }
933 }
934
935 // Update settings metadata
936 $this->update_settings_metadata();
937
938 return new WP_REST_Response([
939 'success' => true,
940 'data' => [
941 'import_results' => $import_results,
942 'validation_results' => $validation_results,
943 'imported_categories' => count($import_results),
944 'successful_imports' => count(array_filter($import_results, function($result) {
945 return $result['success'];
946 }))
947 ],
948 'message' => 'Settings import completed'
949 ], 200);
950
951 } catch (\Exception $e) {
952 return new WP_Error(
953 'import_failed',
954 'Settings import failed: ' . $e->getMessage(),
955 ['status' => 500]
956 );
957 }
958 }
959
960 /**
961 * Create settings backup
962 *
963 * @since 1.0.0
964 *
965 * @param WP_REST_Request $request Request object
966 * @return WP_REST_Response|WP_Error Response object or error
967 */
968 public function create_settings_backup(WP_REST_Request $request) {
969 try {
970 $backup_name = $request->get_param('backup_name') ?? 'backup_' . gmdate('Y-m-d_H-i-s');
971 $categories = $request->get_param('categories') ?? array_keys($this->setting_categories);
972 $description = $request->get_param('description') ?? '';
973
974 // Create backup data
975 $backup_data = [];
976 foreach ($categories as $category) {
977 if (isset($this->setting_categories[$category])) {
978 $backup_data[$category] = $this->settings_manager->get_settings($category);
979 }
980 }
981
982 // Create backup metadata
983 $backup_metadata = [
984 'backup_name' => $backup_name,
985 'description' => $description,
986 'created_at' => current_time('mysql'),
987 'created_by' => get_current_user_id(),
988 'categories' => $categories,
989 'settings_version' => $this->get_settings_version(),
990 'wordpress_version' => get_bloginfo('version')
991 ];
992
993 // Save backup
994 $backup_id = $this->save_settings_backup($backup_data, $backup_metadata);
995
996 if (!$backup_id) {
997 return new WP_Error(
998 'backup_failed',
999 'Failed to create settings backup',
1000 ['status' => 500]
1001 );
1002 }
1003
1004 return new WP_REST_Response([
1005 'success' => true,
1006 'data' => [
1007 'backup_id' => $backup_id,
1008 'backup_name' => $backup_name,
1009 'backup_metadata' => $backup_metadata,
1010 'backed_up_categories' => count($backup_data)
1011 ],
1012 'message' => 'Settings backup created successfully'
1013 ], 200);
1014
1015 } catch (\Exception $e) {
1016 return new WP_Error(
1017 'backup_failed',
1018 'Settings backup failed: ' . $e->getMessage(),
1019 ['status' => 500]
1020 );
1021 }
1022 }
1023
1024 /**
1025 * Restore settings from backup
1026 *
1027 * @since 1.0.0
1028 *
1029 * @param WP_REST_Request $request Request object
1030 * @return WP_REST_Response|WP_Error Response object or error
1031 */
1032 public function restore_settings_backup(WP_REST_Request $request) {
1033 try {
1034 $backup_id = $request->get_param('backup_id');
1035 $categories = $request->get_param('categories') ?? null;
1036 $create_restore_point = $request->get_param('create_restore_point') ?? true;
1037
1038 // Validate backup ID
1039 if (empty($backup_id)) {
1040 return new WP_Error(
1041 'missing_backup_id',
1042 'Backup ID is required',
1043 ['status' => 400]
1044 );
1045 }
1046
1047 // Load backup data
1048 $backup_data = $this->load_settings_backup($backup_id);
1049
1050 if (!$backup_data) {
1051 return new WP_Error(
1052 'backup_not_found',
1053 'Backup not found or could not be loaded',
1054 ['status' => 404]
1055 );
1056 }
1057
1058 // Create restore point if requested
1059 $restore_point_id = null;
1060 if ($create_restore_point) {
1061 $restore_point_id = $this->create_restore_point();
1062 }
1063
1064 $restore_results = [];
1065
1066 // Determine categories to restore
1067 $categories_to_restore = $categories ?? array_keys($backup_data['settings']);
1068
1069 // Restore settings for each category
1070 foreach ($categories_to_restore as $category) {
1071 if (!isset($backup_data['settings'][$category])) {
1072 $restore_results[$category] = [
1073 'success' => false,
1074 'error' => 'Category not found in backup'
1075 ];
1076 continue;
1077 }
1078
1079 try {
1080 $category_settings = $backup_data['settings'][$category];
1081
1082 // Restore settings
1083 $restore_success = $this->settings_manager->update_settings($category_settings, $category);
1084
1085 // Also update through specific SEO manager if available
1086 if (isset($this->seo_managers[$category])) {
1087 $manager_update = $this->seo_managers[$category]->save_settings('site', null, $category_settings);
1088 $restore_success = $restore_success && $manager_update;
1089 }
1090
1091 $restore_results[$category] = [
1092 'success' => $restore_success,
1093 'settings_count' => count($category_settings)
1094 ];
1095
1096 } catch (\Exception $e) {
1097 $restore_results[$category] = [
1098 'success' => false,
1099 'error' => $e->getMessage()
1100 ];
1101 }
1102 }
1103
1104 // Update settings metadata
1105 $this->update_settings_metadata();
1106
1107 return new WP_REST_Response([
1108 'success' => true,
1109 'data' => [
1110 'backup_id' => $backup_id,
1111 'restore_point_id' => $restore_point_id,
1112 'restore_results' => $restore_results,
1113 'restored_categories' => count($restore_results),
1114 'backup_metadata' => $backup_data['metadata']
1115 ],
1116 'message' => 'Settings restored from backup successfully'
1117 ], 200);
1118
1119 } catch (\Exception $e) {
1120 return new WP_Error(
1121 'restore_failed',
1122 'Settings restore failed: ' . $e->getMessage(),
1123 ['status' => 500]
1124 );
1125 }
1126 }
1127
1128 /**
1129 * Detect settings conflicts
1130 *
1131 * @since 1.0.0
1132 *
1133 * @param WP_REST_Request $request Request object
1134 * @return WP_REST_Response Response object
1135 */
1136 public function detect_settings_conflicts(WP_REST_Request $request): WP_REST_Response {
1137 try {
1138 $categories = $request->get_param('categories') ?? array_keys($this->setting_categories);
1139
1140 // Get all settings for analysis
1141 $all_settings = [];
1142 foreach ($categories as $category) {
1143 if (isset($this->setting_categories[$category])) {
1144 $all_settings[$category] = $this->settings_manager->get_settings($category);
1145 }
1146 }
1147
1148 // Analyze conflicts
1149 $conflicts = $this->analyze_cross_category_conflicts($all_settings);
1150
1151 // Get conflict resolution suggestions
1152 $resolution_suggestions = $this->generate_conflict_resolution_suggestions($conflicts);
1153
1154 return new WP_REST_Response([
1155 'success' => true,
1156 'data' => [
1157 'conflicts' => $conflicts,
1158 'resolution_suggestions' => $resolution_suggestions,
1159 'analyzed_categories' => count($all_settings),
1160 'conflict_count' => count($conflicts),
1161 'analysis_timestamp' => current_time('mysql')
1162 ],
1163 'message' => 'Settings conflicts analysis completed'
1164 ], 200);
1165
1166 } catch (\Exception $e) {
1167 return new WP_REST_Response([
1168 'success' => false,
1169 'error' => 'Conflict detection failed: ' . $e->getMessage()
1170 ], 500);
1171 }
1172 }
1173
1174 /**
1175 * Resolve settings conflicts
1176 *
1177 * @since 1.0.0
1178 *
1179 * @param WP_REST_Request $request Request object
1180 * @return WP_REST_Response|WP_Error Response object or error
1181 */
1182 public function resolve_settings_conflicts(WP_REST_Request $request) {
1183 try {
1184 $resolutions = $request->get_param('resolutions');
1185
1186 // Validate resolutions
1187 if (empty($resolutions) || !is_array($resolutions)) {
1188 return new WP_Error(
1189 'invalid_resolutions',
1190 'Conflict resolutions must be provided as an array',
1191 ['status' => 400]
1192 );
1193 }
1194
1195 $resolution_results = [];
1196
1197 foreach ($resolutions as $resolution) {
1198 $conflict_id = $resolution['conflict_id'] ?? '';
1199 $resolution_action = $resolution['action'] ?? '';
1200 $resolution_data = $resolution['data'] ?? [];
1201
1202 try {
1203 $result = $this->apply_conflict_resolution($conflict_id, $resolution_action, $resolution_data);
1204 $resolution_results[$conflict_id] = $result;
1205 } catch (\Exception $e) {
1206 $resolution_results[$conflict_id] = [
1207 'success' => false,
1208 'error' => $e->getMessage()
1209 ];
1210 }
1211 }
1212
1213 return new WP_REST_Response([
1214 'success' => true,
1215 'data' => [
1216 'resolution_results' => $resolution_results,
1217 'resolved_conflicts' => count($resolution_results),
1218 'resolution_timestamp' => current_time('mysql')
1219 ],
1220 'message' => 'Settings conflicts resolution completed'
1221 ], 200);
1222
1223 } catch (\Exception $e) {
1224 return new WP_Error(
1225 'resolution_failed',
1226 'Conflict resolution failed: ' . $e->getMessage(),
1227 ['status' => 500]
1228 );
1229 }
1230 }
1231
1232 /**
1233 * Reset settings to defaults
1234 *
1235 * @since 1.0.0
1236 *
1237 * @param WP_REST_Request $request Request object
1238 * @return WP_REST_Response|WP_Error Response object or error
1239 */
1240 public function reset_settings(WP_REST_Request $request) {
1241 try {
1242 $categories = $request->get_param('categories') ?? array_keys($this->setting_categories);
1243 $create_backup = $request->get_param('create_backup') ?? true;
1244
1245 // Create backup before reset if requested
1246 $backup_id = null;
1247 if ($create_backup) {
1248 $backup_id = $this->create_pre_reset_backup($categories);
1249 }
1250
1251 $reset_results = [];
1252
1253 foreach ($categories as $category) {
1254 if (!isset($this->setting_categories[$category])) {
1255 continue;
1256 }
1257
1258 try {
1259 // Get default settings
1260 $default_settings = [];
1261 if (isset($this->seo_managers[$category])) {
1262 $default_settings = $this->seo_managers[$category]->get_default_settings($category);
1263 }
1264
1265 // Reset to defaults
1266 $reset_success = $this->settings_manager->update_settings($default_settings, $category);
1267
1268 // Also reset through specific SEO manager if available
1269 if (isset($this->seo_managers[$category])) {
1270 $manager_reset = $this->seo_managers[$category]->save_settings('site', null, $default_settings);
1271 $reset_success = $reset_success && $manager_reset;
1272 }
1273
1274 $reset_results[$category] = [
1275 'success' => $reset_success,
1276 'default_settings_count' => count($default_settings)
1277 ];
1278
1279 } catch (\Exception $e) {
1280 $reset_results[$category] = [
1281 'success' => false,
1282 'error' => $e->getMessage()
1283 ];
1284 }
1285 }
1286
1287 // Update settings metadata
1288 $this->update_settings_metadata();
1289
1290 return new WP_REST_Response([
1291 'success' => true,
1292 'data' => [
1293 'reset_results' => $reset_results,
1294 'backup_id' => $backup_id,
1295 'reset_categories' => count($reset_results),
1296 'reset_timestamp' => current_time('mysql')
1297 ],
1298 'message' => 'Settings reset to defaults completed'
1299 ], 200);
1300
1301 } catch (\Exception $e) {
1302 return new WP_Error(
1303 'reset_failed',
1304 'Settings reset failed: ' . $e->getMessage(),
1305 ['status' => 500]
1306 );
1307 }
1308 }
1309
1310 /**
1311 * Bulk operations for settings management
1312 *
1313 * @since 1.0.0
1314 *
1315 * @param WP_REST_Request $request Request object
1316 * @return WP_REST_Response|WP_Error Response object or error
1317 */
1318 public function bulk_operations(WP_REST_Request $request) {
1319 try {
1320 $operation = $request->get_param('operation');
1321 $items = $request->get_param('items') ?? [];
1322 $options = $request->get_param('options') ?? [];
1323
1324 // Validate input
1325 if (empty($operation) || empty($items)) {
1326 return new WP_Error(
1327 'missing_parameters',
1328 'Operation and items are required',
1329 ['status' => 400]
1330 );
1331 }
1332
1333 $results = [];
1334 $errors = [];
1335
1336 foreach ($items as $item) {
1337 try {
1338 switch ($operation) {
1339 case 'validate_settings':
1340 $result = $this->validate_category_settings_bulk($item);
1341 break;
1342 case 'update_settings':
1343 $result = $this->update_category_settings_bulk($item);
1344 break;
1345 case 'export_settings':
1346 $result = $this->export_category_settings_bulk($item);
1347 break;
1348 case 'reset_settings':
1349 $result = $this->reset_category_settings_bulk($item);
1350 break;
1351 default:
1352 throw new \Exception("Unsupported operation: {$operation}");
1353 }
1354
1355 $results[] = [
1356 'item' => $item,
1357 'success' => true,
1358 'data' => $result
1359 ];
1360
1361 } catch (\Exception $e) {
1362 $errors[] = [
1363 'item' => $item,
1364 'error' => $e->getMessage()
1365 ];
1366 }
1367 }
1368
1369 return new WP_REST_Response([
1370 'success' => empty($errors),
1371 'data' => [
1372 'results' => $results,
1373 'errors' => $errors,
1374 'total_processed' => count($items),
1375 'successful' => count($results),
1376 'failed' => count($errors)
1377 ],
1378 'message' => "Bulk {$operation} operation completed"
1379 ], 200);
1380
1381 } catch (\Exception $e) {
1382 return new WP_Error(
1383 'bulk_operation_failed',
1384 'Bulk operation failed: ' . $e->getMessage(),
1385 ['status' => 500]
1386 );
1387 }
1388 }
1389
1390 /**
1391 * Add performance indexes to database tables
1392 *
1393 * @since 1.0.0
1394 *
1395 * @param WP_REST_Request $request Request object
1396 * @return WP_REST_Response|WP_Error Response object
1397 */
1398 public function add_performance_indexes(WP_REST_Request $request): WP_REST_Response|WP_Error {
1399 try {
1400 // Import the Database_Schema class
1401 if (!class_exists('ThinkRank\\Database\\Database_Schema')) {
1402 require_once THINKRANK_PLUGIN_DIR . 'includes/database/class-database-schema.php';
1403 }
1404
1405 $schema = new \ThinkRank\Database\Database_Schema();
1406 $success = $schema->add_performance_indexes();
1407
1408 if ($success) {
1409 return new WP_REST_Response([
1410 'success' => true,
1411 'message' => 'Performance indexes added successfully',
1412 'data' => [
1413 'indexes_added' => true,
1414 'timestamp' => current_time('mysql')
1415 ]
1416 ], 200);
1417 } else {
1418 return new WP_REST_Response([
1419 'success' => false,
1420 'message' => 'Some performance indexes could not be added. Check error logs for details.',
1421 'data' => [
1422 'indexes_added' => false,
1423 'timestamp' => current_time('mysql')
1424 ]
1425 ], 200);
1426 }
1427
1428 } catch (\Exception $e) {
1429 return new WP_Error(
1430 'performance_indexes_failed',
1431 'Failed to add performance indexes: ' . $e->getMessage(),
1432 ['status' => 500]
1433 );
1434 }
1435 }
1436
1437 /**
1438 * Permission callbacks
1439 */
1440
1441 /**
1442 * Check permissions for reading settings data
1443 *
1444 * @since 1.0.0
1445 *
1446 * @return bool Permission status
1447 */
1448 public function check_read_permissions(): bool {
1449 return current_user_can('read');
1450 }
1451
1452 /**
1453 * Check permissions for managing settings
1454 *
1455 * @since 1.0.0
1456 *
1457 * @return bool Permission status
1458 */
1459 public function check_manage_permissions(): bool {
1460 return current_user_can('manage_options');
1461 }
1462
1463 /**
1464 * Helper methods
1465 */
1466
1467 /**
1468 * Get last settings update timestamp
1469 *
1470 * @since 1.0.0
1471 *
1472 * @return string|null Last update timestamp
1473 */
1474 private function get_last_settings_update(): ?string {
1475 $result = get_option('thinkrank_settings_last_updated');
1476 return $result !== false ? $result : null;
1477 }
1478
1479 /**
1480 * Get settings version
1481 *
1482 * @since 1.0.0
1483 *
1484 * @return string Settings version
1485 */
1486 private function get_settings_version(): string {
1487 return get_option('thinkrank_settings_version', '1.0.0');
1488 }
1489
1490 /**
1491 * Get schema version
1492 *
1493 * @since 1.0.0
1494 *
1495 * @return string Schema version
1496 */
1497 private function get_schema_version(): string {
1498 return get_option('thinkrank_schema_version', '1.0.0');
1499 }
1500
1501 /**
1502 * Get category last update timestamp
1503 *
1504 * @since 1.0.0
1505 *
1506 * @param string $category Category name
1507 * @return string|null Last update timestamp
1508 */
1509 private function get_category_last_update(string $category): ?string {
1510 $result = get_option("thinkrank_settings_{$category}_last_updated");
1511 return $result !== false ? $result : null;
1512 }
1513
1514 /**
1515 * Update settings metadata
1516 *
1517 * @since 1.0.0
1518 */
1519 private function update_settings_metadata(): void {
1520 update_option('thinkrank_settings_last_updated', current_time('mysql'));
1521
1522 // Increment version
1523 $current_version = $this->get_settings_version();
1524 $version_parts = explode('.', $current_version);
1525 $version_parts[2] = (int)$version_parts[2] + 1;
1526 $new_version = implode('.', $version_parts);
1527
1528 update_option('thinkrank_settings_version', $new_version);
1529 }
1530
1531 /**
1532 * Update category metadata
1533 *
1534 * @since 1.0.0
1535 *
1536 * @param string $category Category name
1537 */
1538 private function update_category_metadata(string $category): void {
1539 update_option("thinkrank_settings_{$category}_last_updated", current_time('mysql'));
1540 }
1541
1542 /**
1543 * Analyze cross-category conflicts
1544 *
1545 * @since 1.0.0
1546 *
1547 * @param array $settings Settings data
1548 * @return array Conflict analysis
1549 */
1550 private function analyze_cross_category_conflicts(array $settings): array {
1551 $conflicts = [];
1552
1553 // Example conflict detection logic
1554 // This would be enhanced with actual conflict detection algorithms
1555
1556 // Check for conflicting meta title settings
1557 $title_conflicts = $this->detect_title_conflicts($settings);
1558 if (!empty($title_conflicts)) {
1559 $conflicts = array_merge($conflicts, $title_conflicts);
1560 }
1561
1562 // Check for conflicting schema settings
1563 $schema_conflicts = $this->detect_schema_conflicts($settings);
1564 if (!empty($schema_conflicts)) {
1565 $conflicts = array_merge($conflicts, $schema_conflicts);
1566 }
1567
1568 return $conflicts;
1569 }
1570
1571 /**
1572 * Format export data
1573 *
1574 * @since 1.0.0
1575 *
1576 * @param array $export_data Export data
1577 * @param array $metadata Metadata
1578 * @param string $format Export format
1579 * @return string Formatted export data
1580 */
1581 private function format_export_data(array $export_data, array $metadata, string $format): string {
1582 $full_export = [
1583 'metadata' => $metadata,
1584 'settings' => $export_data
1585 ];
1586
1587 switch ($format) {
1588 case 'json':
1589 return wp_json_encode($full_export, JSON_PRETTY_PRINT);
1590 case 'yaml':
1591 // Would implement YAML formatting
1592 return wp_json_encode($full_export, JSON_PRETTY_PRINT);
1593 case 'xml':
1594 // Would implement XML formatting
1595 return wp_json_encode($full_export, JSON_PRETTY_PRINT);
1596 default:
1597 return wp_json_encode($full_export, JSON_PRETTY_PRINT);
1598 }
1599 }
1600
1601 /**
1602 * Parse import data
1603 *
1604 * @since 1.0.0
1605 *
1606 * @param string $import_data Import data
1607 * @param string $format Import format
1608 * @return array|false Parsed data or false on failure
1609 */
1610 private function parse_import_data(string $import_data, string $format) {
1611 switch ($format) {
1612 case 'json':
1613 $decoded = json_decode($import_data, true);
1614 return $decoded['settings'] ?? $decoded;
1615 case 'yaml':
1616 // Would implement YAML parsing
1617 $decoded = json_decode($import_data, true);
1618 return $decoded['settings'] ?? $decoded;
1619 case 'xml':
1620 // Would implement XML parsing
1621 $decoded = json_decode($import_data, true);
1622 return $decoded['settings'] ?? $decoded;
1623 default:
1624 return false;
1625 }
1626 }
1627
1628 /**
1629 * Save settings backup
1630 *
1631 * @since 1.0.0
1632 *
1633 * @param array $backup_data Backup data
1634 * @param array $backup_metadata Backup metadata
1635 * @return string|false Backup ID or false on failure
1636 */
1637 private function save_settings_backup(array $backup_data, array $backup_metadata) {
1638 $backup_id = uniqid('backup_', true);
1639
1640 $backup_record = [
1641 'backup_id' => $backup_id,
1642 'metadata' => $backup_metadata,
1643 'settings' => $backup_data
1644 ];
1645
1646 $saved = update_option("thinkrank_backup_{$backup_id}", $backup_record);
1647
1648 if ($saved) {
1649 // Add to backup index
1650 $backup_index = get_option('thinkrank_backup_index', []);
1651 $backup_index[$backup_id] = $backup_metadata;
1652 update_option('thinkrank_backup_index', $backup_index);
1653
1654 return $backup_id;
1655 }
1656
1657 return false;
1658 }
1659
1660 /**
1661 * Load settings backup
1662 *
1663 * @since 1.0.0
1664 *
1665 * @param string $backup_id Backup ID
1666 * @return array|false Backup data or false on failure
1667 */
1668 private function load_settings_backup(string $backup_id) {
1669 return get_option("thinkrank_backup_{$backup_id}", false);
1670 }
1671
1672 /**
1673 * Argument validation methods
1674 */
1675
1676 /**
1677 * Get arguments for global settings endpoints
1678 *
1679 * @since 1.0.0
1680 *
1681 * @return array Arguments array
1682 */
1683 private function get_global_settings_args(): array {
1684 return [
1685 'settings' => [
1686 'required' => true,
1687 'type' => 'object',
1688 'description' => 'Global settings to update across categories'
1689 ],
1690 'validate' => [
1691 'required' => false,
1692 'type' => 'boolean',
1693 'default' => true,
1694 'description' => 'Whether to validate settings before updating'
1695 ]
1696 ];
1697 }
1698
1699 /**
1700 * Get arguments for category settings endpoints
1701 *
1702 * @since 1.0.0
1703 *
1704 * @return array Arguments array
1705 */
1706 private function get_category_settings_args(): array {
1707 return [
1708 'settings' => [
1709 'required' => true,
1710 'type' => 'object',
1711 'description' => 'Category settings to update'
1712 ],
1713 'validate' => [
1714 'required' => false,
1715 'type' => 'boolean',
1716 'default' => true,
1717 'description' => 'Whether to validate settings before updating'
1718 ]
1719 ];
1720 }
1721
1722 /**
1723 * Get arguments for validation endpoint
1724 *
1725 * @since 1.0.0
1726 *
1727 * @return array Arguments array
1728 */
1729 private function get_validation_args(): array {
1730 return [
1731 'settings' => [
1732 'required' => true,
1733 'type' => 'object',
1734 'description' => 'Settings to validate'
1735 ],
1736 'categories' => [
1737 'required' => false,
1738 'type' => 'array',
1739 'items' => [
1740 'type' => 'string',
1741 'enum' => array_keys($this->setting_categories)
1742 ],
1743 'description' => 'Categories to validate'
1744 ]
1745 ];
1746 }
1747
1748 /**
1749 * Get arguments for export endpoint
1750 *
1751 * @since 1.0.0
1752 *
1753 * @return array Arguments array
1754 */
1755 private function get_export_args(): array {
1756 return [
1757 'categories' => [
1758 'required' => false,
1759 'type' => 'array',
1760 'items' => [
1761 'type' => 'string',
1762 'enum' => array_keys($this->setting_categories)
1763 ],
1764 'description' => 'Categories to export'
1765 ],
1766 'format' => [
1767 'required' => false,
1768 'type' => 'string',
1769 'enum' => ['json', 'yaml', 'xml'],
1770 'default' => 'json',
1771 'description' => 'Export format'
1772 ],
1773 'include_metadata' => [
1774 'required' => false,
1775 'type' => 'boolean',
1776 'default' => true,
1777 'description' => 'Whether to include metadata in export'
1778 ]
1779 ];
1780 }
1781
1782 /**
1783 * Get arguments for import endpoint
1784 *
1785 * @since 1.0.0
1786 *
1787 * @return array Arguments array
1788 */
1789 private function get_import_args(): array {
1790 return [
1791 'import_data' => [
1792 'required' => true,
1793 'type' => 'string',
1794 'description' => 'Settings data to import'
1795 ],
1796 'format' => [
1797 'required' => false,
1798 'type' => 'string',
1799 'enum' => ['json', 'yaml', 'xml'],
1800 'default' => 'json',
1801 'description' => 'Import format'
1802 ],
1803 'validate' => [
1804 'required' => false,
1805 'type' => 'boolean',
1806 'default' => true,
1807 'description' => 'Whether to validate before importing'
1808 ],
1809 'overwrite_existing' => [
1810 'required' => false,
1811 'type' => 'boolean',
1812 'default' => false,
1813 'description' => 'Whether to overwrite existing settings'
1814 ]
1815 ];
1816 }
1817
1818 /**
1819 * Get arguments for backup endpoint
1820 *
1821 * @since 1.0.0
1822 *
1823 * @return array Arguments array
1824 */
1825 private function get_backup_args(): array {
1826 return [
1827 'backup_name' => [
1828 'required' => false,
1829 'type' => 'string',
1830 'description' => 'Name for the backup'
1831 ],
1832 'categories' => [
1833 'required' => false,
1834 'type' => 'array',
1835 'items' => [
1836 'type' => 'string',
1837 'enum' => array_keys($this->setting_categories)
1838 ],
1839 'description' => 'Categories to backup'
1840 ],
1841 'description' => [
1842 'required' => false,
1843 'type' => 'string',
1844 'description' => 'Backup description'
1845 ]
1846 ];
1847 }
1848
1849 /**
1850 * Get arguments for restore endpoint
1851 *
1852 * @since 1.0.0
1853 *
1854 * @return array Arguments array
1855 */
1856 private function get_restore_args(): array {
1857 return [
1858 'backup_id' => [
1859 'required' => true,
1860 'type' => 'string',
1861 'description' => 'Backup ID to restore from'
1862 ],
1863 'categories' => [
1864 'required' => false,
1865 'type' => 'array',
1866 'items' => [
1867 'type' => 'string',
1868 'enum' => array_keys($this->setting_categories)
1869 ],
1870 'description' => 'Categories to restore'
1871 ],
1872 'create_restore_point' => [
1873 'required' => false,
1874 'type' => 'boolean',
1875 'default' => true,
1876 'description' => 'Whether to create restore point before restoring'
1877 ]
1878 ];
1879 }
1880
1881 /**
1882 * Get arguments for conflict resolution endpoint
1883 *
1884 * @since 1.0.0
1885 *
1886 * @return array Arguments array
1887 */
1888 private function get_conflict_resolution_args(): array {
1889 return [
1890 'resolutions' => [
1891 'required' => true,
1892 'type' => 'array',
1893 'items' => [
1894 'type' => 'object'
1895 ],
1896 'description' => 'Conflict resolutions to apply'
1897 ]
1898 ];
1899 }
1900
1901 /**
1902 * Get arguments for reset endpoint
1903 *
1904 * @since 1.0.0
1905 *
1906 * @return array Arguments array
1907 */
1908 private function get_reset_args(): array {
1909 return [
1910 'categories' => [
1911 'required' => false,
1912 'type' => 'array',
1913 'items' => [
1914 'type' => 'string',
1915 'enum' => array_keys($this->setting_categories)
1916 ],
1917 'description' => 'Categories to reset'
1918 ],
1919 'create_backup' => [
1920 'required' => false,
1921 'type' => 'boolean',
1922 'default' => true,
1923 'description' => 'Whether to create backup before reset'
1924 ]
1925 ];
1926 }
1927
1928 /**
1929 * Get arguments for bulk operations endpoint
1930 *
1931 * @since 1.0.0
1932 *
1933 * @return array Arguments array
1934 */
1935 private function get_bulk_operations_args(): array {
1936 return [
1937 'operation' => [
1938 'required' => true,
1939 'type' => 'string',
1940 'enum' => ['validate_settings', 'update_settings', 'export_settings', 'reset_settings'],
1941 'description' => 'Bulk operation type'
1942 ],
1943 'items' => [
1944 'required' => true,
1945 'type' => 'array',
1946 'items' => [
1947 'type' => 'object'
1948 ],
1949 'description' => 'Items to process in bulk'
1950 ],
1951 'options' => [
1952 'required' => false,
1953 'type' => 'object',
1954 'description' => 'Bulk operation options'
1955 ]
1956 ];
1957 }
1958
1959 /**
1960 * Placeholder implementations for methods referenced but not yet implemented
1961 * These would be enhanced with actual conflict detection and resolution algorithms
1962 */
1963
1964 private function detect_title_conflicts(array $settings): array {
1965 return []; // Would implement actual title conflict detection
1966 }
1967
1968 private function detect_schema_conflicts(array $settings): array {
1969 return []; // Would implement actual schema conflict detection
1970 }
1971
1972 private function generate_conflict_resolution_suggestions(array $conflicts): array {
1973 return []; // Would implement actual resolution suggestions
1974 }
1975
1976 private function apply_conflict_resolution(string $conflict_id, string $action, array $data): array {
1977 return ['success' => true, 'action' => $action]; // Would implement actual resolution
1978 }
1979
1980 private function create_restore_point(): string {
1981 return uniqid('restore_point_', true); // Would implement actual restore point creation
1982 }
1983
1984 private function create_pre_reset_backup(array $categories): string {
1985 return uniqid('pre_reset_backup_', true); // Would implement actual pre-reset backup
1986 }
1987
1988 private function validate_category_settings_bulk(array $item): array {
1989 return ['validation' => 'passed']; // Would implement bulk validation
1990 }
1991
1992 private function update_category_settings_bulk(array $item): array {
1993 return ['update' => 'successful']; // Would implement bulk update
1994 }
1995
1996 private function export_category_settings_bulk(array $item): array {
1997 return ['export' => 'completed']; // Would implement bulk export
1998 }
1999
2000 private function reset_category_settings_bulk(array $item): array {
2001 return ['reset' => 'completed']; // Would implement bulk reset
2002 }
2003 }
2004