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

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

754 lines 23.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Social Media API Endpoints Class
4 *
5 * REST API endpoints for social media meta management including Open Graph,
6 * Twitter Cards, social media preview, and image optimization with proper
7 * authentication and comprehensive error handling.
8 *
9 * @package ThinkRank
10 * @subpackage API
11 * @since 1.0.0
12 */
13
14 declare(strict_types=1);
15
16 namespace ThinkRank\API;
17
18 use ThinkRank\SEO\Social_Meta_Manager;
19 use WP_REST_Controller;
20 use WP_REST_Request;
21 use WP_REST_Response;
22 use WP_Error;
23
24 /**
25 * Social Media API Endpoints Class
26 *
27 * Provides REST API endpoints for social media operations including
28 * Open Graph generation, Twitter Cards, social media preview, and
29 * image optimization with proper authentication and validation.
30 *
31 * @since 1.0.0
32 */
33 class Social_Media_Endpoint extends WP_REST_Controller {
34
35 /**
36 * Social Meta Manager instance
37 *
38 * @since 1.0.0
39 * @var Social_Meta_Manager
40 */
41 private Social_Meta_Manager $social_manager;
42
43 /**
44 * API namespace
45 *
46 * @since 1.0.0
47 * @var string
48 */
49 protected $namespace = 'thinkrank/v1';
50
51 /**
52 * API resource base
53 *
54 * @since 1.0.0
55 * @var string
56 */
57 protected $rest_base = 'social-media';
58
59 /**
60 * Constructor
61 *
62 * @since 1.0.0
63 */
64 public function __construct() {
65 $this->social_manager = new Social_Meta_Manager();
66 }
67
68 /**
69 * Register API routes
70 *
71 * @since 1.0.0
72 */
73 public function register_routes(): void {
74 // Social media settings management
75 register_rest_route(
76 $this->namespace,
77 '/' . $this->rest_base . '/settings',
78 [
79 [
80 'methods' => 'GET',
81 'callback' => [$this, 'get_settings'],
82 'permission_callback' => [$this, 'check_read_permissions']
83 ],
84 [
85 'methods' => 'POST',
86 'callback' => [$this, 'update_settings'],
87 'permission_callback' => [$this, 'check_manage_permissions'],
88 'args' => $this->get_settings_args()
89 ]
90 ]
91 );
92
93 // Social media settings validation
94 register_rest_route(
95 $this->namespace,
96 '/' . $this->rest_base . '/validate',
97 [
98 [
99 'methods' => 'POST',
100 'callback' => [$this, 'validate_settings'],
101 'permission_callback' => [$this, 'check_read_permissions'],
102 'args' => $this->get_settings_args()
103 ]
104 ]
105 );
106
107 // Generate social media preview
108 register_rest_route(
109 $this->namespace,
110 '/' . $this->rest_base . '/preview',
111 [
112 [
113 'methods' => 'POST',
114 'callback' => [$this, 'generate_preview'],
115 'permission_callback' => [$this, 'check_read_permissions'],
116 'args' => $this->get_preview_args()
117 ]
118 ]
119 );
120
121 // Optimize image for social platforms
122 register_rest_route(
123 $this->namespace,
124 '/' . $this->rest_base . '/optimize-image',
125 [
126 [
127 'methods' => 'POST',
128 'callback' => [$this, 'optimize_image'],
129 'permission_callback' => [$this, 'check_manage_permissions'],
130 'args' => $this->get_optimize_image_args()
131 ]
132 ]
133 );
134
135 // Get social meta for context
136 register_rest_route(
137 $this->namespace,
138 '/' . $this->rest_base . '/(?P<context_type>[a-zA-Z]+)/(?P<context_id>\d+)',
139 [
140 [
141 'methods' => 'GET',
142 'callback' => [$this, 'get_social_meta'],
143 'permission_callback' => [$this, 'check_read_permissions'],
144 'args' => $this->get_context_args()
145 ],
146 [
147 'methods' => 'POST',
148 'callback' => [$this, 'save_social_meta'],
149 'permission_callback' => [$this, 'check_manage_permissions'],
150 'args' => array_merge($this->get_context_args(), $this->get_social_meta_args())
151 ]
152 ]
153 );
154
155 // Generate Open Graph tags
156 register_rest_route(
157 $this->namespace,
158 '/' . $this->rest_base . '/generate-og',
159 [
160 [
161 'methods' => 'POST',
162 'callback' => [$this, 'generate_og_tags'],
163 'permission_callback' => [$this, 'check_read_permissions'],
164 'args' => $this->get_generate_tags_args()
165 ]
166 ]
167 );
168
169 // Generate Twitter Card tags
170 register_rest_route(
171 $this->namespace,
172 '/' . $this->rest_base . '/generate-twitter',
173 [
174 [
175 'methods' => 'POST',
176 'callback' => [$this, 'generate_twitter_tags'],
177 'permission_callback' => [$this, 'check_read_permissions'],
178 'args' => $this->get_generate_tags_args()
179 ]
180 ]
181 );
182 }
183
184 /**
185 * Get social media settings
186 *
187 * @since 1.0.0
188 *
189 * @param WP_REST_Request $request Request object
190 * @return WP_REST_Response Response object
191 */
192 public function get_settings(WP_REST_Request $request): WP_REST_Response {
193 try {
194 $context_type = $request->get_param('context_type') ?? 'site';
195 $context_id = $request->get_param('context_id');
196
197 // Get settings from Social Meta Manager
198 $settings = $this->social_manager->get_settings($context_type, $context_id);
199
200 // Get settings schema for validation
201 $schema = $this->social_manager->get_settings_schema($context_type);
202
203 return new WP_REST_Response([
204 'success' => true,
205 'data' => [
206 'settings' => $settings,
207 'schema' => $schema,
208 'context_type' => $context_type,
209 'context_id' => $context_id
210 ],
211 'message' => 'Social media settings retrieved successfully'
212 ], 200);
213
214 } catch (\Exception $e) {
215 return new WP_REST_Response([
216 'success' => false,
217 'error' => 'Failed to retrieve settings: ' . $e->getMessage()
218 ], 500);
219 }
220 }
221
222 /**
223 * Update social media settings
224 *
225 * @since 1.0.0
226 *
227 * @param WP_REST_Request $request Request object
228 * @return WP_REST_Response|WP_Error Response object or error
229 */
230 public function update_settings(WP_REST_Request $request) {
231 try {
232 $settings = $request->get_param('settings');
233 $context_type = $request->get_param('context_type') ?? 'site';
234 $context_id = $request->get_param('context_id');
235 $validation_context = $request->get_param('validation_context') ?? 'all';
236
237 if (empty($settings)) {
238 return new WP_REST_Response([
239 'success' => false,
240 'error' => 'Settings data is required'
241 ], 400);
242 }
243
244 // Validate settings with context
245 $validation = $this->social_manager->validate_settings($settings, $validation_context);
246 if (!$validation['valid']) {
247 return new WP_Error(
248 'validation_failed',
249 'Settings validation failed',
250 [
251 'status' => 400,
252 'validation_errors' => $validation['errors'],
253 'validation_warnings' => $validation['warnings']
254 ]
255 );
256 }
257
258 // Save settings
259 $result = $this->social_manager->save_settings($context_type, $context_id, $settings);
260
261 if ($result) {
262 // Get updated settings
263 $updated_settings = $this->social_manager->get_settings($context_type, $context_id);
264
265 return new WP_REST_Response([
266 'success' => true,
267 'data' => [
268 'settings' => $updated_settings,
269 'validation' => $validation,
270 'context_type' => $context_type,
271 'context_id' => $context_id
272 ],
273 'message' => 'Social media settings updated successfully'
274 ], 200);
275 } else {
276 throw new \Exception('Failed to save settings');
277 }
278
279 } catch (\Exception $e) {
280 return new WP_REST_Response([
281 'success' => false,
282 'error' => 'Settings update failed: ' . $e->getMessage()
283 ], 500);
284 }
285 }
286
287 /**
288 * Validate social media settings
289 *
290 * @since 1.0.0
291 *
292 * @param WP_REST_Request $request Request object
293 * @return WP_REST_Response|WP_Error Response object
294 */
295 public function validate_settings(WP_REST_Request $request): WP_REST_Response|WP_Error {
296 try {
297 $settings = $request->get_param('settings') ?? [];
298 $context_type = $request->get_param('context_type') ?? 'site';
299 $validation_context = $request->get_param('validation_context') ?? 'all';
300
301 // Validate settings using the enhanced Social Meta Manager with tab-specific context
302 $validation = $this->social_manager->validate_settings($settings, $validation_context);
303
304 return new WP_REST_Response([
305 'success' => true,
306 'data' => $validation
307 ], 200);
308
309 } catch (\Exception $e) {
310 return new WP_Error(
311 'validation_error',
312 'Failed to validate social media settings: ' . $e->getMessage(),
313 ['status' => 500]
314 );
315 }
316 }
317
318 /**
319 * Generate social media preview
320 *
321 * @since 1.0.0
322 *
323 * @param WP_REST_Request $request Request object
324 * @return WP_REST_Response|WP_Error Response object or error
325 */
326 public function generate_preview(WP_REST_Request $request) {
327 try {
328 $data = $request->get_param('data') ?? [];
329 $platform = $request->get_param('platform') ?? 'facebook';
330
331 // Validate platform
332 $supported_platforms = ['facebook', 'twitter', 'linkedin', 'pinterest'];
333 if (!in_array($platform, $supported_platforms, true)) {
334 return new WP_Error(
335 'invalid_platform',
336 'Unsupported platform for preview generation',
337 ['status' => 400]
338 );
339 }
340
341 // Generate preview
342 $preview_data = $this->social_manager->preview_social_post($data, $platform);
343
344 return new WP_REST_Response([
345 'success' => true,
346 'data' => $preview_data,
347 'message' => 'Social media preview generated successfully'
348 ], 200);
349
350 } catch (\Exception $e) {
351 return new WP_Error(
352 'preview_failed',
353 'Social media preview generation failed: ' . $e->getMessage(),
354 ['status' => 500]
355 );
356 }
357 }
358
359 /**
360 * Optimize image for social platforms
361 *
362 * @since 1.0.0
363 *
364 * @param WP_REST_Request $request Request object
365 * @return WP_REST_Response|WP_Error Response object or error
366 */
367 public function optimize_image(WP_REST_Request $request) {
368 try {
369 $image_url = $request->get_param('image_url');
370 $platform = $request->get_param('platform') ?? 'facebook';
371
372 // Validate image URL
373 if (!filter_var($image_url, FILTER_VALIDATE_URL)) {
374 return new WP_Error(
375 'invalid_image_url',
376 'Invalid image URL provided',
377 ['status' => 400]
378 );
379 }
380
381 // Optimize image
382 $optimized_image = $this->social_manager->optimize_social_image($image_url, $platform);
383
384 return new WP_REST_Response([
385 'success' => true,
386 'data' => $optimized_image,
387 'message' => 'Image optimized successfully'
388 ], 200);
389
390 } catch (\Exception $e) {
391 return new WP_Error(
392 'optimization_failed',
393 'Image optimization failed: ' . $e->getMessage(),
394 ['status' => 500]
395 );
396 }
397 }
398
399 /**
400 * Get social meta for context
401 *
402 * @since 1.0.0
403 *
404 * @param WP_REST_Request $request Request object
405 * @return WP_REST_Response|WP_Error Response object or error
406 */
407 public function get_social_meta(WP_REST_Request $request) {
408 try {
409 $context_type = $request->get_param('context_type');
410 $context_id = (int) $request->get_param('context_id');
411
412 // Validate context
413 if (!$this->validate_context($context_type, $context_id)) {
414 return new WP_Error(
415 'invalid_context',
416 'Invalid context type or ID provided',
417 ['status' => 400]
418 );
419 }
420
421 // Get social meta data
422 $social_meta = $this->social_manager->get_output_data($context_type, $context_id);
423
424 return new WP_REST_Response([
425 'success' => true,
426 'data' => $social_meta,
427 'message' => 'Social meta retrieved successfully'
428 ], 200);
429
430 } catch (\Exception $e) {
431 return new WP_Error(
432 'retrieval_failed',
433 'Social meta retrieval failed: ' . $e->getMessage(),
434 ['status' => 500]
435 );
436 }
437 }
438
439 /**
440 * Save social meta for context
441 *
442 * @since 1.0.0
443 *
444 * @param WP_REST_Request $request Request object
445 * @return WP_REST_Response|WP_Error Response object or error
446 */
447 public function save_social_meta(WP_REST_Request $request) {
448 try {
449 $context_type = $request->get_param('context_type');
450 $context_id = (int) $request->get_param('context_id');
451 $social_data = $request->get_param('social_data') ?? [];
452
453 // Validate context
454 if (!$this->validate_context($context_type, $context_id)) {
455 return new WP_Error(
456 'invalid_context',
457 'Invalid context type or ID provided',
458 ['status' => 400]
459 );
460 }
461
462 // Save social meta data
463 $result = $this->social_manager->save_settings($social_data, $context_type, $context_id);
464
465 if ($result) {
466 return new WP_REST_Response([
467 'success' => true,
468 'data' => $result,
469 'message' => 'Social meta saved successfully'
470 ], 200);
471 } else {
472 throw new \Exception('Failed to save social meta data');
473 }
474
475 } catch (\Exception $e) {
476 return new WP_Error(
477 'save_failed',
478 'Social meta save failed: ' . $e->getMessage(),
479 ['status' => 500]
480 );
481 }
482 }
483
484 /**
485 * Generate Open Graph tags
486 *
487 * @since 1.0.0
488 *
489 * @param WP_REST_Request $request Request object
490 * @return WP_REST_Response|WP_Error Response object or error
491 */
492 public function generate_og_tags(WP_REST_Request $request) {
493 try {
494 $data = $request->get_param('data') ?? [];
495 $context = $request->get_param('context') ?? 'site';
496 $platform = $request->get_param('platform') ?? 'facebook';
497
498 // Generate Open Graph tags
499 $og_tags = $this->social_manager->generate_og_tags($data, $context, $platform);
500
501 return new WP_REST_Response([
502 'success' => true,
503 'data' => $og_tags,
504 'message' => 'Open Graph tags generated successfully'
505 ], 200);
506
507 } catch (\Exception $e) {
508 return new WP_Error(
509 'og_generation_failed',
510 'Open Graph generation failed: ' . $e->getMessage(),
511 ['status' => 500]
512 );
513 }
514 }
515
516 /**
517 * Generate Twitter Card tags
518 *
519 * @since 1.0.0
520 *
521 * @param WP_REST_Request $request Request object
522 * @return WP_REST_Response|WP_Error Response object or error
523 */
524 public function generate_twitter_tags(WP_REST_Request $request) {
525 try {
526 $data = $request->get_param('data') ?? [];
527 $context = $request->get_param('context') ?? 'site';
528
529 // Generate Twitter Card tags
530 $twitter_tags = $this->social_manager->generate_twitter_tags($data, $context);
531
532 return new WP_REST_Response([
533 'success' => true,
534 'data' => $twitter_tags,
535 'message' => 'Twitter Card tags generated successfully'
536 ], 200);
537
538 } catch (\Exception $e) {
539 return new WP_Error(
540 'twitter_generation_failed',
541 'Twitter Card generation failed: ' . $e->getMessage(),
542 ['status' => 500]
543 );
544 }
545 }
546
547 /**
548 * Check read permissions
549 *
550 * @since 1.0.0
551 *
552 * @return bool Permission status
553 */
554 public function check_read_permissions(): bool {
555 return current_user_can('edit_posts');
556 }
557
558 /**
559 * Check manage permissions
560 *
561 * @since 1.0.0
562 *
563 * @return bool Permission status
564 */
565 public function check_manage_permissions(): bool {
566 return current_user_can('manage_options');
567 }
568
569 /**
570 * Validate context type and ID
571 *
572 * @since 1.0.0
573 *
574 * @param string $context_type Context type
575 * @param int|null $context_id Context ID
576 * @return bool Validation status
577 */
578 private function validate_context(string $context_type, ?int $context_id): bool {
579 $valid_types = ['site', 'post', 'page', 'product'];
580
581 if (!in_array($context_type, $valid_types, true)) {
582 return false;
583 }
584
585 if ($context_type !== 'site' && (!$context_id || $context_id <= 0)) {
586 return false;
587 }
588
589 if ($context_id && !get_post($context_id)) {
590 return false;
591 }
592
593 return true;
594 }
595
596 /**
597 * Get arguments for preview endpoint
598 *
599 * @since 1.0.0
600 *
601 * @return array Arguments array
602 */
603 private function get_preview_args(): array {
604 return [
605 'data' => [
606 'required' => true,
607 'type' => 'object',
608 'description' => 'Content data for preview generation'
609 ],
610 'platform' => [
611 'required' => false,
612 'type' => 'string',
613 'enum' => ['facebook', 'twitter', 'linkedin', 'pinterest'],
614 'default' => 'facebook',
615 'description' => 'Target platform for preview'
616 ]
617 ];
618 }
619
620 /**
621 * Get arguments for image optimization endpoint
622 *
623 * @since 1.0.0
624 *
625 * @return array Arguments array
626 */
627 private function get_optimize_image_args(): array {
628 return [
629 'image_url' => [
630 'required' => true,
631 'type' => 'string',
632 'format' => 'uri',
633 'description' => 'Image URL to optimize'
634 ],
635 'platform' => [
636 'required' => false,
637 'type' => 'string',
638 'enum' => ['facebook', 'twitter', 'linkedin', 'pinterest'],
639 'default' => 'facebook',
640 'description' => 'Target platform for optimization'
641 ]
642 ];
643 }
644
645 /**
646 * Get arguments for context endpoints
647 *
648 * @since 1.0.0
649 *
650 * @return array Arguments array
651 */
652 private function get_context_args(): array {
653 return [
654 'context_type' => [
655 'required' => true,
656 'type' => 'string',
657 'enum' => ['site', 'post', 'page', 'product'],
658 'description' => 'Context type'
659 ],
660 'context_id' => [
661 'required' => true,
662 'type' => 'integer',
663 'minimum' => 1,
664 'description' => 'Context ID'
665 ]
666 ];
667 }
668
669 /**
670 * Get arguments for social meta save endpoint
671 *
672 * @since 1.0.0
673 *
674 * @return array Arguments array
675 */
676 private function get_social_meta_args(): array {
677 return [
678 'social_data' => [
679 'required' => true,
680 'type' => 'object',
681 'description' => 'Social media meta data to save'
682 ]
683 ];
684 }
685
686 /**
687 * Get arguments for tag generation endpoints
688 *
689 * @since 1.0.0
690 *
691 * @return array Arguments array
692 */
693 private function get_generate_tags_args(): array {
694 return [
695 'data' => [
696 'required' => true,
697 'type' => 'object',
698 'description' => 'Content data for tag generation'
699 ],
700 'context' => [
701 'required' => false,
702 'type' => 'string',
703 'enum' => ['site', 'post', 'page', 'product'],
704 'default' => 'site',
705 'description' => 'Context type'
706 ],
707 'platform' => [
708 'required' => false,
709 'type' => 'string',
710 'enum' => ['facebook', 'twitter', 'linkedin', 'pinterest'],
711 'default' => 'facebook',
712 'description' => 'Target platform (for Open Graph only)'
713 ]
714 ];
715 }
716
717 /**
718 * Get arguments for settings endpoints
719 *
720 * @since 1.0.0
721 *
722 * @return array Arguments array
723 */
724 private function get_settings_args(): array {
725 return [
726 'settings' => [
727 'required' => true,
728 'type' => 'object',
729 'description' => 'Social media settings to save'
730 ],
731 'context_type' => [
732 'required' => false,
733 'type' => 'string',
734 'enum' => ['site', 'post', 'page', 'product'],
735 'default' => 'site',
736 'description' => 'Context type'
737 ],
738 'context_id' => [
739 'required' => false,
740 'type' => 'integer',
741 'minimum' => 1,
742 'description' => 'Context ID (required for non-site contexts)'
743 ],
744 'validation_context' => [
745 'required' => false,
746 'type' => 'string',
747 'enum' => ['all', 'open-graph', 'twitter-cards', 'platforms', 'preview'],
748 'default' => 'all',
749 'description' => 'Validation context for focused validation'
750 ]
751 ];
752 }
753 }
754