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 / abilities / content / class-list-content-items.php

class-list-content-items.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 2.7.0, at includes/abilities/content/class-list-content-items.php

245 lines 6.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * List content items ability.
4 *
5 * @package ThinkRank\Abilities\Content
6 */
7
8 declare(strict_types=1);
9
10 namespace ThinkRank\Abilities\Content;
11
12 use ThinkRank\Abilities\Ability_Base;
13
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit; // Exit if accessed directly.
16 }
17
18 /**
19 * Lists posts/pages or terms that can be targeted by ThinkRank abilities.
20 */
21 class List_Content_Items extends Ability_Base {
22 /**
23 * Constructor.
24 */
25 public function __construct() {
26 $this->id = 'thinkrank/list-content-items';
27 $this->label = __( 'List ThinkRank Content Items', 'thinkrank' );
28 $this->description = __( 'List posts, pages, custom post types, or taxonomy terms to find the IDs needed for ThinkRank SEO actions. Use list-content-types first to see which post types and taxonomies are available.', 'thinkrank' );
29 }
30
31 /**
32 * {@inheritDoc}
33 *
34 * @return array<string, bool|float|string>
35 */
36 public function get_annotations() {
37 return [
38 'readonly' => true,
39 'destructive' => false,
40 'idempotent' => true,
41 'priority' => 1.0,
42 'openWorldHint' => false,
43 ];
44 }
45
46 /**
47 * {@inheritDoc}
48 *
49 * @return array<string, mixed>
50 */
51 public function get_input_schema() {
52 return [
53 'type' => 'object',
54 'additionalProperties' => false,
55 'properties' => [
56 'object_type' => [
57 'type' => 'string',
58 'enum' => [ 'post', 'term' ],
59 'default' => 'post',
60 'description' => __( 'Whether to list post objects or taxonomy terms.', 'thinkrank' ),
61 ],
62 'type_name' => [
63 'type' => 'string',
64 'description' => __( 'The post type slug or taxonomy slug to list.', 'thinkrank' ),
65 ],
66 'search' => [
67 'type' => 'string',
68 'description' => __( 'Optional search query for titles or term names.', 'thinkrank' ),
69 ],
70 'page' => [
71 'type' => 'integer',
72 'default' => 1,
73 'minimum' => 1,
74 'description' => __( 'Results page number.', 'thinkrank' ),
75 ],
76 'per_page' => [
77 'type' => 'integer',
78 'default' => 20,
79 'minimum' => 1,
80 'maximum' => 100,
81 'description' => __( 'Results per page.', 'thinkrank' ),
82 ],
83 ],
84 'required' => [ 'type_name' ],
85 ];
86 }
87
88 /**
89 * {@inheritDoc}
90 *
91 * @return array<string, mixed>
92 */
93 public function get_output_schema() {
94 return [
95 'type' => 'object',
96 'properties' => [
97 'object_type' => [ 'type' => 'string' ],
98 'type_name' => [ 'type' => 'string' ],
99 'items' => [
100 'type' => 'array',
101 'items' => [
102 'type' => 'object',
103 'properties' => [
104 'id' => [ 'type' => 'integer' ],
105 'label' => [ 'type' => 'string' ],
106 'status' => [ 'type' => 'string' ],
107 'slug' => [ 'type' => 'string' ],
108 ],
109 ],
110 ],
111 ],
112 ];
113 }
114
115 /**
116 * Execute ability.
117 *
118 * @param array<string, mixed> $input Ability input payload.
119 * @return array<string, mixed>|\WP_Error
120 */
121 public function execute( $input ) {
122 $object_type = isset( $input['object_type'] ) ? sanitize_key( (string) $input['object_type'] ) : 'post';
123 $type_name = isset( $input['type_name'] ) ? sanitize_key( (string) $input['type_name'] ) : '';
124 $search = isset( $input['search'] ) ? sanitize_text_field( (string) $input['search'] ) : '';
125 $page = isset( $input['page'] ) ? max( 1, (int) $input['page'] ) : 1;
126 $per_page = isset( $input['per_page'] ) ? max( 1, min( 100, (int) $input['per_page'] ) ) : 20;
127
128 if ( empty( $type_name ) ) {
129 return new \WP_Error(
130 'thinkrank_missing_type_name',
131 __( 'A post type or taxonomy slug is required.', 'thinkrank' ),
132 [ 'status' => 400 ]
133 );
134 }
135
136 if ( 'term' === $object_type && ! taxonomy_exists( $type_name ) ) {
137 return new \WP_Error(
138 'thinkrank_invalid_taxonomy',
139 __( 'The provided taxonomy slug does not exist.', 'thinkrank' ),
140 [ 'status' => 400 ]
141 );
142 }
143
144 if ( 'term' !== $object_type && ! post_type_exists( $type_name ) ) {
145 return new \WP_Error(
146 'thinkrank_invalid_post_type',
147 __( 'The provided post type slug does not exist.', 'thinkrank' ),
148 [ 'status' => 400 ]
149 );
150 }
151
152 $items = 'term' === $object_type
153 ? $this->list_terms( $type_name, $search, $page, $per_page )
154 : $this->list_posts( $type_name, $search, $page, $per_page );
155
156 return [
157 'object_type' => $object_type,
158 'type_name' => $type_name,
159 'items' => $items,
160 ];
161 }
162
163 /**
164 * List posts for a post type.
165 *
166 * @param string $post_type Post type slug.
167 * @param string $search Search query.
168 * @param int $page Page number.
169 * @param int $per_page Results per page.
170 * @return array<int, array<string, int|string>>
171 */
172 private function list_posts( $post_type, $search, $page, $per_page ) {
173 $query = new \WP_Query(
174 [
175 'post_type' => $post_type,
176 'post_status' => [ 'publish', 'draft', 'private', 'future' ],
177 'posts_per_page' => $per_page,
178 'paged' => $page,
179 's' => $search,
180 'orderby' => 'date',
181 'order' => 'DESC',
182 ]
183 );
184
185 $items = [];
186
187 foreach ( $query->posts as $post ) {
188 if ( ! $post instanceof \WP_Post ) {
189 continue;
190 }
191
192 $items[] = [
193 'id' => (int) $post->ID,
194 'label' => $post->post_title,
195 'status' => $post->post_status,
196 'slug' => $post->post_name,
197 ];
198 }
199
200 return $items;
201 }
202
203 /**
204 * List terms for a taxonomy.
205 *
206 * @param string $taxonomy Taxonomy slug.
207 * @param string $search Search query.
208 * @param int $page Page number.
209 * @param int $per_page Results per page.
210 * @return array<int, array<string, int|string>>
211 */
212 private function list_terms( $taxonomy, $search, $page, $per_page ) {
213 $terms = get_terms(
214 [
215 'taxonomy' => $taxonomy,
216 'hide_empty' => false,
217 'search' => $search,
218 'number' => $per_page,
219 'offset' => ( $page - 1 ) * $per_page,
220 ]
221 );
222
223 if ( is_wp_error( $terms ) || ! is_array( $terms ) ) {
224 return [];
225 }
226
227 $items = [];
228
229 foreach ( $terms as $term ) {
230 if ( ! $term instanceof \WP_Term ) {
231 continue;
232 }
233
234 $items[] = [
235 'id' => (int) $term->term_id,
236 'label' => $term->name,
237 'status' => 'active',
238 'slug' => $term->slug,
239 ];
240 }
241
242 return $items;
243 }
244 }
245