# wp-parsely/3.24.2/src/rest-api/stats/class-endpoint-related.php

Parse.ly, version 3.24.2. 143 lines.

- Page: https://pluginprobe.com/plugins/wp-parsely/3.24.2/code/src/rest-api/stats/class-endpoint-related.php
- Raw: https://pluginprobe.com/plugins/wp-parsely/3.24.2/raw/src/rest-api/stats/class-endpoint-related.php
- Modified: 2026-10-06T15:36:52+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/wp-parsely/3.24.2/code/src/rest-api/stats/class-endpoint-related.php#L10-L20`.

```php
<?php
/**
 * Stats API Endpoint: Related Posts
 *
 * @package Parsely
 * @since   3.17.0
 */

declare(strict_types=1);

namespace Parsely\REST_API\Stats;

use Parsely\REST_API\Base_Endpoint;
use Parsely\Services\Content_API\Content_API_Service;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;

/**
 * The Stats API Related Posts endpoint.
 *
 * Provides an endpoint for retrieving related posts to a given URL.
 *
 * @since 3.17.0
 */
class Endpoint_Related extends Base_Endpoint {
	use Post_Data_Trait;
	use Related_Posts_Trait;

	/**
	 * The Parse.ly Content API service.
	 *
	 * @since 3.17.0
	 *
	 * @var Content_API_Service $content_api
	 */
	public $content_api;

	/**
	 * Constructor.
	 *
	 * @since 3.17.0
	 *
	 * @param Stats_Controller $controller The controller.
	 */
	public function __construct( Stats_Controller $controller ) {
		parent::__construct( $controller );
		$this->content_api = $this->parsely->get_content_api();
	}

	/**
	 * Returns the endpoint's name.
	 *
	 * @since 3.17.0
	 *
	 * @return string
	 */
	public static function get_endpoint_name(): string {
		return 'related';
	}

	/**
	 * Registers the routes for the endpoint.
	 *
	 * @since 3.17.0
	 * @since 3.24.2 Registered the related posts arguments, and required an HTTP(S) URL with a host.
	 */
	public function register_routes(): void {
		/**
		 * GET /related
		 * Gets related posts.
		 */
		$this->register_rest_route(
			'/',
			array( 'GET' ),
			array( $this, 'get_related_posts' ),
			array_merge(
				array(
					'url' => array(
						'description'       => __( 'The URL of the post.', 'wp-parsely' ),
						'type'              => 'string',
						'pattern'           => '^https?://\S+$',
						'required'          => true,
						'validate_callback' => array( $this, 'validate_url' ),
					),
				),
				$this->get_related_posts_param_args()
			)
		);
	}

	/**
	 * API Endpoint: GET /stats/related
	 *
	 * Gets related posts for a given URL.
	 *
	 * @since 3.17.0
	 *
	 * @param WP_REST_Request $request The request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function get_related_posts( WP_REST_Request $request ) {
		$url = $request->get_param( 'url' );

		$related_posts = $this->get_related_posts_of_url( $request, $url );

		if ( is_wp_error( $related_posts ) ) {
			return $related_posts;
		}

		return new WP_REST_Response( array( 'data' => $related_posts ), 200 );
	}

	/**
	 * Validates that the URL has a host. The `pattern` argument checks the scheme.
	 *
	 * @since 3.24.2
	 *
	 * @param mixed $url The raw parameter value, as validation runs before type checks.
	 * @return true|WP_Error
	 */
	public function validate_url( $url ) {
		if ( ! is_string( $url ) || '' === (string) wp_parse_url( $url, PHP_URL_HOST ) ) {
			return new WP_Error( 'invalid_param', __( 'The parameter must be a URL with a host.', 'wp-parsely' ) );
		}

		return true;
	}

	/**
	 * Returns whether the endpoint is available for access by the current
	 * user.
	 *
	 * @since 3.17.0
	 *
	 * @param WP_REST_Request|null $request The request object.
	 * @return bool|WP_Error
	 */
	public function is_available_to_current_user( ?WP_REST_Request $request = null ) {
		return $this->validate_site_id_and_secret( false );
	}
}

```
