PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.0.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.0.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-pillar-content-endpoint.php

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

181 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Pillar Content API Endpoint Class
5 *
6 * REST API endpoints for fetching pillar content suggestions.
7 *
8 * @package ThinkRank
9 * @subpackage API
10 * @since 1.0.0
11 */
12
13 declare(strict_types=1);
14
15 namespace ThinkRank\API;
16
17 use WP_REST_Controller;
18 use WP_REST_Request;
19 use WP_REST_Response;
20 use WP_Query;
21 use WP_Error;
22
23 // Prevent direct access
24 if (!defined('ABSPATH')) {
25 exit;
26 }
27
28 /**
29 * Pillar Content API Endpoint Class
30 *
31 * @since 1.0.0
32 */
33 class Pillar_Content_Endpoint extends WP_REST_Controller {
34
35 /**
36 * API namespace
37 *
38 * @var string
39 */
40 protected $namespace = 'thinkrank/v1';
41
42 /**
43 * API resource base
44 *
45 * @var string
46 */
47 protected $rest_base = 'pillar-content';
48
49 /**
50 * Register API routes
51 *
52 * @return void
53 */
54 public function register_routes(): void {
55 register_rest_route(
56 $this->namespace,
57 '/' . $this->rest_base . '/suggestions',
58 [
59 [
60 'methods' => 'GET',
61 'callback' => [$this, 'get_suggestions'],
62 'permission_callback' => [$this, 'check_read_permissions'],
63 'args' => [
64 'post_id' => [
65 'required' => true,
66 'type' => 'integer',
67 'validate_callback' => function ($param, $request, $key) {
68 return is_numeric($param);
69 },
70 'sanitize_callback' => 'absint',
71 ],
72 ],
73 ]
74 ]
75 );
76 }
77
78 /**
79 * Get pillar content suggestions
80 *
81 * @param WP_REST_Request $request Request object
82 * @return WP_REST_Response|WP_Error Response object
83 */
84 public function get_suggestions(WP_REST_Request $request) {
85 $post_id = $request->get_param('post_id');
86
87 if (!$post_id) {
88 return new WP_Error(
89 'missing_post_id',
90 __('Post ID is required', 'thinkrank'),
91 ['status' => 400]
92 );
93 }
94
95 $post_type = get_post_type($post_id);
96 if (!$post_type) {
97 return new WP_Error(
98 'invalid_post_id',
99 __('Invalid Post ID', 'thinkrank'),
100 ['status' => 400]
101 );
102 }
103
104 // Check global settings for this post type
105 $all_settings = get_option('thinkrank_global_seo_settings', []);
106 $link_suggestions_enabled = true; // Default to true
107
108 if (isset($all_settings[$post_type]['link_suggestions'])) {
109 $link_suggestions_enabled = (bool) $all_settings[$post_type]['link_suggestions'];
110 }
111
112 if (!$link_suggestions_enabled) {
113 return new WP_REST_Response([], 200);
114 }
115
116 $taxonomies = get_object_taxonomies($post_type);
117 $tax_query = [];
118
119 if (!empty($taxonomies)) {
120 $tax_query['relation'] = 'OR';
121
122 foreach ($taxonomies as $taxonomy) {
123 $terms = get_the_terms($post_id, $taxonomy);
124 if ($terms && !is_wp_error($terms)) {
125 $term_ids = wp_list_pluck($terms, 'term_id');
126 if (!empty($term_ids)) {
127 $tax_query[] = [
128 'taxonomy' => $taxonomy,
129 'field' => 'term_id',
130 'terms' => $term_ids,
131 ];
132 $has_terms = true;
133 }
134 }
135 }
136 }
137
138 $args = [
139 'post_type' => $post_type,
140 'posts_per_page' => 5,
141 'post__not_in' => [$post_id],
142 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- admin-only endpoint listing pillar posts; there is no taxonomy to key this on.
143 'meta_query' => [
144 [
145 'key' => '_thinkrank_pillar_content',
146 'value' => '1',
147 'compare' => '=',
148 ]
149 ],
150 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- admin-only endpoint, optional filter.
151 'tax_query' => $tax_query,
152 'fields' => 'ids'
153 ];
154
155 $query = new WP_Query($args);
156 $suggestions = [];
157
158 if ($query->have_posts()) {
159 foreach ($query->posts as $p_id) {
160 $suggestions[] = [
161 'id' => $p_id,
162 'title' => get_the_title($p_id),
163 'permalink' => get_permalink($p_id),
164 'type' => get_post_type($p_id)
165 ];
166 }
167 }
168
169 return new WP_REST_Response($suggestions, 200);
170 }
171
172 /**
173 * Check if user can read posts
174 *
175 * @return bool
176 */
177 public function check_read_permissions() {
178 return current_user_can('edit_posts');
179 }
180 }
181