PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.0
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.0
28.6 28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 All 130 releases
wordpress-seo / src / schema-aggregator / user-interface / site-schema-aggregator-route.php

site-schema-aggregator-route.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 28.0, at src/schema-aggregator/user-interface/site-schema-aggregator-route.php

209 lines 6.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
3 namespace Yoast\WP\SEO\Schema_Aggregator\User_Interface;
4
5 use Exception;
6 use WP_Error;
7 use WP_REST_Request;
8 use WP_REST_Response;
9 use Yoast\WP\SEO\Helpers\Capability_Helper;
10 use Yoast\WP\SEO\Helpers\Post_Type_Helper;
11 use Yoast\WP\SEO\Main;
12 use Yoast\WP\SEO\Routes\Route_Interface;
13 use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command;
14 use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command_Handler;
15 use Yoast\WP\SEO\Schema_Aggregator\Application\Cache\Manager;
16 use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config;
17 use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Aggregator_Conditional;
18
19 /**
20 * Handles the route to represent a site's schema as JSON.
21 *
22 * @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded
23 */
24 class Site_Schema_Aggregator_Route implements Route_Interface {
25 /**
26 * Represents the site schema prefix.
27 *
28 * @var string
29 */
30 public const ROUTE_PREFIX = 'schema-aggregator';
31
32 /**
33 * Represents route to view the schema.
34 *
35 * @var string
36 */
37 public const GET_SCHEMA_ROUTE = self::ROUTE_PREFIX . '/get-schema';
38
39 /**
40 * The configuration instance.
41 *
42 * @var Config
43 */
44 private $config;
45
46 /**
47 * The capability helper instance.
48 *
49 * @var Capability_Helper
50 */
51 private $capability_helper;
52
53 /**
54 * The command handler instance.
55 *
56 * @var Aggregate_Site_Schema_Command_Handler
57 */
58 private $aggregate_site_schema_command_handler;
59
60 /**
61 * The cache manager instance.
62 *
63 * @var Manager
64 */
65 private $cache_manager;
66
67 /**
68 * The post type helper instance.
69 *
70 * @var Post_Type_Helper
71 */
72 private $post_type_helper;
73
74 /**
75 * Returns the conditional for this route.
76 *
77 * @return array<string> The conditionals that must be met to load this.
78 */
79 public static function get_conditionals() {
80 return [ Schema_Aggregator_Conditional::class ];
81 }
82
83 /**
84 * Site_Schema_Aggregator_Route constructor.
85 *
86 * @param Config $config The config object.
87 * @param Capability_Helper $capability_helper The capability helper.
88 * @param Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler The command handler.
89 * @param Manager $cache_manager The cache manager.
90 * @param Post_Type_Helper $post_type_helper The post type helper.
91 */
92 public function __construct(
93 Config $config,
94 Capability_Helper $capability_helper,
95 Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler,
96 Manager $cache_manager,
97 Post_Type_Helper $post_type_helper
98 ) {
99 $this->config = $config;
100 $this->capability_helper = $capability_helper;
101 $this->aggregate_site_schema_command_handler = $aggregate_site_schema_command_handler;
102 $this->cache_manager = $cache_manager;
103 $this->post_type_helper = $post_type_helper;
104 }
105
106 /**
107 * Registers routes with WordPress.
108 *
109 * @return void
110 */
111 public function register_routes() {
112 $base_route_config = [
113 'methods' => 'GET',
114 'callback' => [ $this, 'aggregate_site_schema' ],
115 'permission_callback' => [ $this, 'get_permission_callback' ],
116 'args' => [
117 'post_type' => [
118 'required' => true,
119 'validate_callback' => static function ( $param ) {
120 return \is_string( $param ) && \preg_match( '/^[a-z0-9_-]+$/', $param ) && \post_type_exists( $param );
121 },
122 'sanitize_callback' => 'sanitize_key',
123 ],
124 ],
125 ];
126
127 $schema_aggregator_route_page = $base_route_config;
128 $schema_aggregator_route_page['args']['page'] = [
129 'default' => 1,
130 'validate_callback' => [ $this, 'validate_page' ],
131 'sanitize_callback' => 'absint',
132 ];
133
134 \register_rest_route( Main::API_V1_NAMESPACE, self::GET_SCHEMA_ROUTE . '/(?P<post_type>[a-z0-9_-]+)', $base_route_config );
135 \register_rest_route( Main::API_V1_NAMESPACE, self::GET_SCHEMA_ROUTE . '/(?P<post_type>[a-z0-9_-]+)/(?P<page>\d+)', $schema_aggregator_route_page );
136 }
137
138 /**
139 * Permission callback for the route.
140 *
141 * @return bool True if the user has permission, false otherwise.
142 */
143 public function get_permission_callback(): bool {
144 return true;
145 }
146
147 /**
148 * Returns a JSON representation of a site.
149 *
150 * @param WP_REST_Request $request The request object.
151 *
152 * @return WP_REST_Response|WP_Error The success or failure response.
153 */
154 public function aggregate_site_schema( WP_REST_Request $request ) {
155 $post_type = $request->get_param( 'post_type' );
156
157 if ( ! $this->post_type_helper->is_indexable( $post_type ) ) {
158 return new WP_Error(
159 'wpseo_post_type_not_indexable',
160 \sprintf( 'The post type "%s" is excluded from search results.', $post_type ),
161 [ 'status' => 404 ],
162 );
163 }
164
165 $page = ( $request->get_param( 'page' ) ?? 1 );
166
167 if ( ! $this->validate_page( (string) $page ) ) {
168 return new WP_Error(
169 'rest_invalid_param',
170 \sprintf( 'Invalid parameter(s): %s', 'page' ),
171 [ 'status' => 400 ],
172 );
173 }
174
175 $per_page = $this->config->get_per_page( $post_type );
176
177 $output = $this->cache_manager->get( $post_type, $page, $per_page );
178 if ( $output === null ) {
179 try {
180 $output = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page, $post_type ) );
181 $this->cache_manager->set( $post_type, $page, $per_page, $output );
182
183 } catch ( Exception $exception ) {
184 return new WP_Error(
185 'wpseo_aggregate_site_schema_error',
186 $exception->getMessage(),
187 (object) [],
188 );
189 }
190 }
191 $response = \rest_ensure_response( $output );
192
193 $response->header( 'Cache-Control', 'public, max-age=300' );
194
195 return $response;
196 }
197
198 /**
199 * Validates the page parameter.
200 *
201 * @param string $page The page parameter to validate.
202 *
203 * @return bool True if the page is valid, false otherwise.
204 */
205 public function validate_page( string $page ): bool {
206 return \is_numeric( $page ) && $page > 0 && $page < \PHP_INT_MAX;
207 }
208 }
209