Merged in feature/from-pantheon (pull request #16)
code from pantheon * code from pantheon
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use WP_REST_Response;
|
||||
|
||||
/**
|
||||
* Abstract_Action_Route class.
|
||||
*
|
||||
* Abstract class for action routes.
|
||||
*/
|
||||
abstract class Abstract_Action_Route implements Route_Interface {
|
||||
|
||||
/**
|
||||
* Responds to an indexing request.
|
||||
*
|
||||
* @param array $objects The objects that have been indexed.
|
||||
* @param string $next_url The url that should be called to continue reindexing. False if done.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
protected function respond_with( $objects, $next_url ) {
|
||||
return new WP_REST_Response(
|
||||
[
|
||||
'objects' => $objects,
|
||||
'next_url' => $next_url,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\Actions\Indexing\Indexation_Action_Interface;
|
||||
|
||||
/**
|
||||
* Abstract_Indexation_Route class.
|
||||
*
|
||||
* Reindexing route for indexables.
|
||||
*/
|
||||
abstract class Abstract_Indexation_Route extends Abstract_Action_Route {
|
||||
|
||||
/**
|
||||
* Runs an indexing action and returns the response.
|
||||
*
|
||||
* @param Indexation_Action_Interface $indexation_action The indexing action.
|
||||
* @param string $url The url of the indexing route.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
protected function run_indexation_action( Indexation_Action_Interface $indexation_action, $url ) {
|
||||
$indexables = $indexation_action->index();
|
||||
|
||||
$next_url = false;
|
||||
if ( \count( $indexables ) >= $indexation_action->get_limit() ) {
|
||||
$next_url = \rest_url( $url );
|
||||
}
|
||||
|
||||
return $this->respond_with( $indexables, $next_url );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\Actions\Alert_Dismissal_Action;
|
||||
use Yoast\WP\SEO\Conditionals\No_Conditionals;
|
||||
use Yoast\WP\SEO\Main;
|
||||
|
||||
/**
|
||||
* Class Alert_Dismissal_Route.
|
||||
*/
|
||||
class Alert_Dismissal_Route implements Route_Interface {
|
||||
|
||||
use No_Conditionals;
|
||||
|
||||
/**
|
||||
* Represents the alerts route prefix.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const ROUTE_PREFIX = 'alerts';
|
||||
|
||||
/**
|
||||
* Represents the dismiss route.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const DISMISS_ROUTE = self::ROUTE_PREFIX . '/dismiss';
|
||||
|
||||
/**
|
||||
* Represents the full dismiss route.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FULL_DISMISS_ROUTE = Main::API_V1_NAMESPACE . '/' . self::DISMISS_ROUTE;
|
||||
|
||||
/**
|
||||
* Represents the alert dismissal action.
|
||||
*
|
||||
* @var Alert_Dismissal_Action
|
||||
*/
|
||||
protected $alert_dismissal_action;
|
||||
|
||||
/**
|
||||
* Constructs Alert_Dismissal_Route.
|
||||
*
|
||||
* @param Alert_Dismissal_Action $alert_dismissal_action The alert dismissal action.
|
||||
*/
|
||||
public function __construct( Alert_Dismissal_Action $alert_dismissal_action ) {
|
||||
$this->alert_dismissal_action = $alert_dismissal_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes() {
|
||||
$dismiss_route_args = [
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'dismiss' ],
|
||||
'permission_callback' => [ $this, 'can_dismiss' ],
|
||||
'args' => [
|
||||
'key' => [
|
||||
'validate_callback' => [ $this->alert_dismissal_action, 'is_allowed' ],
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::DISMISS_ROUTE, $dismiss_route_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismisses an alert.
|
||||
*
|
||||
* @param WP_REST_Request $request The request. This request should have a key param set.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function dismiss( WP_REST_Request $request ) {
|
||||
$success = $this->alert_dismissal_action->dismiss( $request['key'] );
|
||||
$status = $success === ( true ) ? 200 : 400;
|
||||
|
||||
return new WP_REST_Response(
|
||||
(object) [
|
||||
'success' => $success,
|
||||
'status' => $status,
|
||||
],
|
||||
$status
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the current user is allowed to dismiss alerts.
|
||||
*
|
||||
* @return bool Whether or not the current user is allowed to dismiss alerts.
|
||||
*/
|
||||
public function can_dismiss() {
|
||||
return \current_user_can( 'edit_posts' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\Actions\Configuration\First_Time_Configuration_Action;
|
||||
use Yoast\WP\SEO\Conditionals\No_Conditionals;
|
||||
use Yoast\WP\SEO\Main;
|
||||
|
||||
/**
|
||||
* First_Time_Configuration_Route class.
|
||||
*/
|
||||
class First_Time_Configuration_Route implements Route_Interface {
|
||||
|
||||
use No_Conditionals;
|
||||
|
||||
/**
|
||||
* Represents the first time configuration route.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const CONFIGURATION_ROUTE = '/configuration';
|
||||
|
||||
/**
|
||||
* Represents a site representation route.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const SITE_REPRESENTATION_ROUTE = '/site_representation';
|
||||
|
||||
/**
|
||||
* Represents a social profiles route.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const SOCIAL_PROFILES_ROUTE = '/social_profiles';
|
||||
|
||||
/**
|
||||
* Represents a person's social profiles route.
|
||||
*
|
||||
* @deprecated 20.2
|
||||
* @var string
|
||||
*/
|
||||
const PERSON_SOCIAL_PROFILES_ROUTE = '/person_social_profiles';
|
||||
|
||||
/**
|
||||
* Represents a route to enable/disable tracking.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const ENABLE_TRACKING_ROUTE = '/enable_tracking';
|
||||
|
||||
/**
|
||||
* Represents a route to check if current user has the correct capabilities to edit another user's profile.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const CHECK_CAPABILITY_ROUTE = '/check_capability';
|
||||
|
||||
/**
|
||||
* Represents a route to save the first time configuration state.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const SAVE_CONFIGURATION_STATE_ROUTE = '/save_configuration_state';
|
||||
|
||||
/**
|
||||
* Represents a route to save the first time configuration state.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const GET_CONFIGURATION_STATE_ROUTE = '/get_configuration_state';
|
||||
|
||||
/**
|
||||
* The first tinme configuration action.
|
||||
*
|
||||
* @var First_Time_Configuration_Action
|
||||
*/
|
||||
private $first_time_configuration_action;
|
||||
|
||||
/**
|
||||
* First_Time_Configuration_Route constructor.
|
||||
*
|
||||
* @param First_Time_Configuration_Action $first_time_configuration_action The first-time configuration action.
|
||||
*/
|
||||
public function __construct(
|
||||
First_Time_Configuration_Action $first_time_configuration_action
|
||||
) {
|
||||
$this->first_time_configuration_action = $first_time_configuration_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes() {
|
||||
$site_representation_route = [
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'set_site_representation' ],
|
||||
'permission_callback' => [ $this, 'can_manage_options' ],
|
||||
'args' => [
|
||||
'company_or_person' => [
|
||||
'type' => 'string',
|
||||
'enum' => [
|
||||
'company',
|
||||
'person',
|
||||
],
|
||||
'required' => true,
|
||||
],
|
||||
'company_name' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
'company_logo' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
'company_logo_id' => [
|
||||
'type' => 'integer',
|
||||
],
|
||||
'person_logo' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
'person_logo_id' => [
|
||||
'type' => 'integer',
|
||||
],
|
||||
'company_or_person_user_id' => [
|
||||
'type' => 'integer',
|
||||
],
|
||||
'description' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
],
|
||||
];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::CONFIGURATION_ROUTE . self::SITE_REPRESENTATION_ROUTE, $site_representation_route );
|
||||
|
||||
$social_profiles_route = [
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'set_social_profiles' ],
|
||||
'permission_callback' => [ $this, 'can_manage_options' ],
|
||||
'args' => [
|
||||
'facebook_site' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
'twitter_site' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
'other_social_urls' => [
|
||||
'type' => 'array',
|
||||
],
|
||||
],
|
||||
];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::CONFIGURATION_ROUTE . self::SOCIAL_PROFILES_ROUTE, $social_profiles_route );
|
||||
|
||||
$check_capability_route = [
|
||||
'methods' => 'GET',
|
||||
'callback' => [ $this, 'check_capability' ],
|
||||
'permission_callback' => [ $this, 'can_manage_options' ],
|
||||
'args' => [
|
||||
'user_id' => [
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::CONFIGURATION_ROUTE . self::CHECK_CAPABILITY_ROUTE, $check_capability_route );
|
||||
|
||||
$enable_tracking_route = [
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'set_enable_tracking' ],
|
||||
'permission_callback' => [ $this, 'can_manage_options' ],
|
||||
'args' => [
|
||||
'tracking' => [
|
||||
'type' => 'boolean',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::CONFIGURATION_ROUTE . self::ENABLE_TRACKING_ROUTE, $enable_tracking_route );
|
||||
|
||||
$save_configuration_state_route = [
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'save_configuration_state' ],
|
||||
'permission_callback' => [ $this, 'can_manage_options' ],
|
||||
'args' => [
|
||||
'finishedSteps' => [
|
||||
'type' => 'array',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::CONFIGURATION_ROUTE . self::SAVE_CONFIGURATION_STATE_ROUTE, $save_configuration_state_route );
|
||||
|
||||
$get_configuration_state_route = [
|
||||
[
|
||||
'methods' => 'GET',
|
||||
'callback' => [ $this, 'get_configuration_state' ],
|
||||
'permission_callback' => [ $this, 'can_manage_options' ],
|
||||
],
|
||||
];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::CONFIGURATION_ROUTE . self::GET_CONFIGURATION_STATE_ROUTE, $get_configuration_state_route );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the site representation values.
|
||||
*
|
||||
* @param WP_REST_Request $request The request.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function set_site_representation( WP_REST_Request $request ) {
|
||||
$data = $this
|
||||
->first_time_configuration_action
|
||||
->set_site_representation( $request->get_json_params() );
|
||||
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the social profiles values.
|
||||
*
|
||||
* @param WP_REST_Request $request The request.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function set_social_profiles( WP_REST_Request $request ) {
|
||||
$data = $this
|
||||
->first_time_configuration_action
|
||||
->set_social_profiles( $request->get_json_params() );
|
||||
|
||||
return new WP_REST_Response(
|
||||
[ 'json' => $data ]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current user has the correct capability to edit a specific user.
|
||||
*
|
||||
* @param WP_REST_Request $request The request.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function check_capability( WP_REST_Request $request ) {
|
||||
$data = $this
|
||||
->first_time_configuration_action
|
||||
->check_capability( $request->get_param( 'user_id' ) );
|
||||
|
||||
return new WP_REST_Response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables tracking.
|
||||
*
|
||||
* @param WP_REST_Request $request The request.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function set_enable_tracking( WP_REST_Request $request ) {
|
||||
$data = $this
|
||||
->first_time_configuration_action
|
||||
->set_enable_tracking( $request->get_json_params() );
|
||||
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current user has the right capability.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function can_manage_options() {
|
||||
return \current_user_can( 'wpseo_manage_options' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current user has the capability to edit a specific user.
|
||||
*
|
||||
* @param WP_REST_Request $request The request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function can_edit_user( WP_REST_Request $request ) {
|
||||
$response = $this->first_time_configuration_action->check_capability( $request->get_param( 'user_id' ) );
|
||||
return $response->success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current user has the capability to edit posts of other users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function can_edit_other_posts() {
|
||||
return \current_user_can( 'edit_others_posts' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the first time configuration state.
|
||||
*
|
||||
* @param WP_REST_Request $request The request.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function save_configuration_state( WP_REST_Request $request ) {
|
||||
$data = $this
|
||||
->first_time_configuration_action
|
||||
->save_configuration_state( $request->get_json_params() );
|
||||
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first time configuration state.
|
||||
*
|
||||
* @return WP_REST_Response the state of the configuration.
|
||||
*/
|
||||
public function get_configuration_state() {
|
||||
$data = $this
|
||||
->first_time_configuration_action
|
||||
->get_configuration_state();
|
||||
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/* DEPRECATED METHODS */
|
||||
|
||||
/**
|
||||
* Gets a person's social profiles values.
|
||||
*
|
||||
* @deprecated 20.2
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param WP_REST_Request $request The request.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function get_person_social_profiles( WP_REST_Request $request ) {
|
||||
\_deprecated_function( __METHOD__, 'Yoast SEO 20.2' );
|
||||
|
||||
$data = $this
|
||||
->first_time_configuration_action
|
||||
->get_person_social_profiles( $request->get_param( 'user_id' ) );
|
||||
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a person's social profiles values.
|
||||
*
|
||||
* @deprecated 20.2
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param WP_REST_Request $request The request.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function set_person_social_profiles( WP_REST_Request $request ) {
|
||||
\_deprecated_function( __METHOD__, 'Yoast SEO 20.2' );
|
||||
|
||||
$data = $this
|
||||
->first_time_configuration_action
|
||||
->set_person_social_profiles( $request->get_json_params() );
|
||||
|
||||
return new WP_REST_Response(
|
||||
[ 'json' => $data ]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\Actions\Importing\Importing_Action_Interface;
|
||||
use Yoast\WP\SEO\Conditionals\No_Conditionals;
|
||||
use Yoast\WP\SEO\Exceptions\Importing\Aioseo_Validation_Exception;
|
||||
use Yoast\WP\SEO\Main;
|
||||
use Yoast\WP\SEO\Services\Importing\Importable_Detector_Service;
|
||||
|
||||
/**
|
||||
* Importing_Route class.
|
||||
*
|
||||
* Importing route for importing from other SEO plugins.
|
||||
*/
|
||||
class Importing_Route extends Abstract_Action_Route {
|
||||
|
||||
use No_Conditionals;
|
||||
|
||||
/**
|
||||
* The import route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const ROUTE = '/import/(?P<plugin>[\w-]+)/(?P<type>[\w-]+)';
|
||||
|
||||
/**
|
||||
* List of available importers.
|
||||
*
|
||||
* @var Importing_Action_Interface[]
|
||||
*/
|
||||
protected $importers = [];
|
||||
|
||||
/**
|
||||
* The importable detector service.
|
||||
*
|
||||
* @var Importable_Detector_Service
|
||||
*/
|
||||
protected $importable_detector;
|
||||
|
||||
/**
|
||||
* Importing_Route constructor.
|
||||
*
|
||||
* @param Importable_Detector_Service $importable_detector The importable detector service.
|
||||
* @param Importing_Action_Interface ...$importers All available importers.
|
||||
*/
|
||||
public function __construct(
|
||||
Importable_Detector_Service $importable_detector,
|
||||
Importing_Action_Interface ...$importers
|
||||
) {
|
||||
$this->importable_detector = $importable_detector;
|
||||
$this->importers = $importers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes() {
|
||||
\register_rest_route(
|
||||
Main::API_V1_NAMESPACE,
|
||||
self::ROUTE,
|
||||
[
|
||||
'callback' => [ $this, 'execute' ],
|
||||
'permission_callback' => [ $this, 'is_user_permitted_to_import' ],
|
||||
'methods' => [ 'POST' ],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the rest request, but only if the respective action is enabled.
|
||||
*
|
||||
* @param mixed $data The request parameters.
|
||||
*
|
||||
* @return WP_REST_Response|false Response or false on non-existent route.
|
||||
*/
|
||||
public function execute( $data ) {
|
||||
$plugin = (string) $data['plugin'];
|
||||
$type = (string) $data['type'];
|
||||
|
||||
$next_url = $this->get_endpoint( $plugin, $type );
|
||||
|
||||
try {
|
||||
$importer = $this->get_importer( $plugin, $type );
|
||||
|
||||
if ( $importer === false || ! $importer->is_enabled() ) {
|
||||
return new WP_Error(
|
||||
'rest_no_route',
|
||||
'Requested importer not found',
|
||||
[
|
||||
'status' => 404,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$result = $importer->index();
|
||||
|
||||
if ( $result === false || \count( $result ) === 0 ) {
|
||||
$next_url = false;
|
||||
}
|
||||
|
||||
return $this->respond_with(
|
||||
$result,
|
||||
$next_url
|
||||
);
|
||||
} catch ( \Exception $exception ) {
|
||||
if ( $exception instanceof Aioseo_Validation_Exception ) {
|
||||
return new WP_Error(
|
||||
'wpseo_error_validation',
|
||||
$exception->getMessage(),
|
||||
[ 'stackTrace' => $exception->getTraceAsString() ]
|
||||
);
|
||||
}
|
||||
|
||||
return new WP_Error(
|
||||
'wpseo_error_indexing',
|
||||
$exception->getMessage(),
|
||||
[ 'stackTrace' => $exception->getTraceAsString() ]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the right importer for the given arguments.
|
||||
*
|
||||
* @param string $plugin The plugin to import from.
|
||||
* @param string $type The type of entity to import.
|
||||
*
|
||||
* @return Importing_Action_Interface|false The importer, or false if no importer was found.
|
||||
*/
|
||||
protected function get_importer( $plugin, $type ) {
|
||||
$importers = $this->importable_detector->filter_actions( $this->importers, $plugin, $type );
|
||||
|
||||
if ( \count( $importers ) !== 1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return \current( $importers );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the right endpoint for the given arguments.
|
||||
*
|
||||
* @param string $plugin The plugin to import from.
|
||||
* @param string $type The type of entity to import.
|
||||
*
|
||||
* @return string|false The endpoint for the given action or false on failure of finding the one.
|
||||
*/
|
||||
public function get_endpoint( $plugin, $type ) {
|
||||
if ( empty( $plugin ) || empty( $type ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Main::API_V1_NAMESPACE . "/import/{$plugin}/{$type}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the current user is allowed to import.
|
||||
*
|
||||
* @return bool Whether or not the current user is allowed to import.
|
||||
*/
|
||||
public function is_user_permitted_to_import() {
|
||||
return \current_user_can( 'activate_plugins' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\Actions\Indexables\Indexable_Head_Action;
|
||||
use Yoast\WP\SEO\Conditionals\Headless_Rest_Endpoints_Enabled_Conditional;
|
||||
use Yoast\WP\SEO\Main;
|
||||
|
||||
/**
|
||||
* Head route for indexables.
|
||||
*/
|
||||
class Indexables_Head_Route implements Route_Interface {
|
||||
|
||||
/**
|
||||
* The posts route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const HEAD_FOR_URL_ROUTE = 'get_head';
|
||||
|
||||
/**
|
||||
* The full posts route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FULL_HEAD_FOR_URL_ROUTE = Main::API_V1_NAMESPACE . '/' . self::HEAD_FOR_URL_ROUTE;
|
||||
|
||||
/**
|
||||
* The head action.
|
||||
*
|
||||
* @var Indexable_Head_Action
|
||||
*/
|
||||
private $head_action;
|
||||
|
||||
/**
|
||||
* Indexable_Indexation_Route constructor.
|
||||
*
|
||||
* @param Indexable_Head_Action $head_action The head action.
|
||||
*/
|
||||
public function __construct( Indexable_Head_Action $head_action ) {
|
||||
$this->head_action = $head_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the conditionals based in which this loadable should be active.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_conditionals() {
|
||||
return [ Headless_Rest_Endpoints_Enabled_Conditional::class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes() {
|
||||
$route_args = [
|
||||
'methods' => 'GET',
|
||||
'callback' => [ $this, 'get_head' ],
|
||||
'permission_callback' => '__return_true',
|
||||
'args' => [
|
||||
'url' => [
|
||||
'validate_callback' => [ $this, 'is_valid_url' ],
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::HEAD_FOR_URL_ROUTE, $route_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the head of a page for a given URL.
|
||||
*
|
||||
* @param WP_REST_Request $request The request. This request should have a url param set.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function get_head( WP_REST_Request $request ) {
|
||||
$url = \esc_url_raw( \utf8_uri_encode( $request['url'] ) );
|
||||
$data = $this->head_action->for_url( $url );
|
||||
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a url is a valid url.
|
||||
*
|
||||
* @param string $url The url to check.
|
||||
*
|
||||
* @return bool Whether or not the url is valid.
|
||||
*/
|
||||
public function is_valid_url( $url ) {
|
||||
if ( \filter_var( \utf8_uri_encode( $url ), \FILTER_VALIDATE_URL ) === false ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,429 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use Exception;
|
||||
use WP_Error;
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\Actions\Indexing\Indexable_General_Indexation_Action;
|
||||
use Yoast\WP\SEO\Actions\Indexing\Indexable_Indexing_Complete_Action;
|
||||
use Yoast\WP\SEO\Actions\Indexing\Indexable_Post_Indexation_Action;
|
||||
use Yoast\WP\SEO\Actions\Indexing\Indexable_Post_Type_Archive_Indexation_Action;
|
||||
use Yoast\WP\SEO\Actions\Indexing\Indexable_Term_Indexation_Action;
|
||||
use Yoast\WP\SEO\Actions\Indexing\Indexation_Action_Interface;
|
||||
use Yoast\WP\SEO\Actions\Indexing\Indexing_Complete_Action;
|
||||
use Yoast\WP\SEO\Actions\Indexing\Indexing_Prepare_Action;
|
||||
use Yoast\WP\SEO\Actions\Indexing\Post_Link_Indexing_Action;
|
||||
use Yoast\WP\SEO\Actions\Indexing\Term_Link_Indexing_Action;
|
||||
use Yoast\WP\SEO\Conditionals\No_Conditionals;
|
||||
use Yoast\WP\SEO\Helpers\Indexing_Helper;
|
||||
use Yoast\WP\SEO\Helpers\Options_Helper;
|
||||
use Yoast\WP\SEO\Main;
|
||||
|
||||
/**
|
||||
* Indexing_Route class.
|
||||
*
|
||||
* Indexing route for indexables.
|
||||
*/
|
||||
class Indexing_Route extends Abstract_Indexation_Route {
|
||||
|
||||
use No_Conditionals;
|
||||
|
||||
/**
|
||||
* The indexing complete route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const COMPLETE_ROUTE = 'indexing/complete';
|
||||
|
||||
/**
|
||||
* The full indexing complete route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FULL_COMPLETE_ROUTE = Main::API_V1_NAMESPACE . '/' . self::COMPLETE_ROUTE;
|
||||
|
||||
/**
|
||||
* The indexables complete route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const INDEXABLES_COMPLETE_ROUTE = 'indexing/indexables-complete';
|
||||
|
||||
/**
|
||||
* The full indexing complete route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FULL_INDEXABLES_COMPLETE_ROUTE = Main::API_V1_NAMESPACE . '/' . self::INDEXABLES_COMPLETE_ROUTE;
|
||||
|
||||
/**
|
||||
* The indexing prepare route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const PREPARE_ROUTE = 'indexing/prepare';
|
||||
|
||||
/**
|
||||
* The full indexing prepare route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FULL_PREPARE_ROUTE = Main::API_V1_NAMESPACE . '/' . self::PREPARE_ROUTE;
|
||||
|
||||
/**
|
||||
* The posts route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const POSTS_ROUTE = 'indexing/posts';
|
||||
|
||||
/**
|
||||
* The full posts route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FULL_POSTS_ROUTE = Main::API_V1_NAMESPACE . '/' . self::POSTS_ROUTE;
|
||||
|
||||
/**
|
||||
* The terms route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const TERMS_ROUTE = 'indexing/terms';
|
||||
|
||||
/**
|
||||
* The full terms route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FULL_TERMS_ROUTE = Main::API_V1_NAMESPACE . '/' . self::TERMS_ROUTE;
|
||||
|
||||
/**
|
||||
* The terms route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const POST_TYPE_ARCHIVES_ROUTE = 'indexing/post-type-archives';
|
||||
|
||||
/**
|
||||
* The full terms route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FULL_POST_TYPE_ARCHIVES_ROUTE = Main::API_V1_NAMESPACE . '/' . self::POST_TYPE_ARCHIVES_ROUTE;
|
||||
|
||||
/**
|
||||
* The general route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const GENERAL_ROUTE = 'indexing/general';
|
||||
|
||||
/**
|
||||
* The full general route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FULL_GENERAL_ROUTE = Main::API_V1_NAMESPACE . '/' . self::GENERAL_ROUTE;
|
||||
|
||||
/**
|
||||
* The posts route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const POST_LINKS_INDEXING_ROUTE = 'link-indexing/posts';
|
||||
|
||||
/**
|
||||
* The full posts route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FULL_POST_LINKS_INDEXING_ROUTE = Main::API_V1_NAMESPACE . '/' . self::POST_LINKS_INDEXING_ROUTE;
|
||||
|
||||
/**
|
||||
* The terms route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const TERM_LINKS_INDEXING_ROUTE = 'link-indexing/terms';
|
||||
|
||||
/**
|
||||
* The full terms route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FULL_TERM_LINKS_INDEXING_ROUTE = Main::API_V1_NAMESPACE . '/' . self::TERM_LINKS_INDEXING_ROUTE;
|
||||
|
||||
/**
|
||||
* The post indexing action.
|
||||
*
|
||||
* @var Indexable_Post_Indexation_Action
|
||||
*/
|
||||
protected $post_indexation_action;
|
||||
|
||||
/**
|
||||
* The term indexing action.
|
||||
*
|
||||
* @var Indexable_Term_Indexation_Action
|
||||
*/
|
||||
protected $term_indexation_action;
|
||||
|
||||
/**
|
||||
* The post type archive indexing action.
|
||||
*
|
||||
* @var Indexable_Post_Type_Archive_Indexation_Action
|
||||
*/
|
||||
protected $post_type_archive_indexation_action;
|
||||
|
||||
/**
|
||||
* Represents the general indexing action.
|
||||
*
|
||||
* @var Indexable_General_Indexation_Action
|
||||
*/
|
||||
protected $general_indexation_action;
|
||||
|
||||
/**
|
||||
* The prepare indexing action.
|
||||
*
|
||||
* @var Indexing_Prepare_Action
|
||||
*/
|
||||
protected $prepare_indexing_action;
|
||||
|
||||
/**
|
||||
* The indexable indexing complete action.
|
||||
*
|
||||
* @var Indexable_Indexing_Complete_Action
|
||||
*/
|
||||
protected $indexable_indexing_complete_action;
|
||||
|
||||
/**
|
||||
* The indexing complete action.
|
||||
*
|
||||
* @var Indexing_Complete_Action
|
||||
*/
|
||||
protected $indexing_complete_action;
|
||||
|
||||
/**
|
||||
* The post link indexing action.
|
||||
*
|
||||
* @var Post_Link_Indexing_Action
|
||||
*/
|
||||
protected $post_link_indexing_action;
|
||||
|
||||
/**
|
||||
* The term link indexing action.
|
||||
*
|
||||
* @var Term_Link_Indexing_Action
|
||||
*/
|
||||
protected $term_link_indexing_action;
|
||||
|
||||
/**
|
||||
* The options helper.
|
||||
*
|
||||
* @var Options_Helper
|
||||
*/
|
||||
protected $options_helper;
|
||||
|
||||
/**
|
||||
* The indexing helper.
|
||||
*
|
||||
* @var Indexing_Helper
|
||||
*/
|
||||
protected $indexing_helper;
|
||||
|
||||
/**
|
||||
* Indexing_Route constructor.
|
||||
*
|
||||
* @param Indexable_Post_Indexation_Action $post_indexation_action The post indexing action.
|
||||
* @param Indexable_Term_Indexation_Action $term_indexation_action The term indexing action.
|
||||
* @param Indexable_Post_Type_Archive_Indexation_Action $post_type_archive_indexation_action The post type archive indexing action.
|
||||
* @param Indexable_General_Indexation_Action $general_indexation_action The general indexing action.
|
||||
* @param Indexable_Indexing_Complete_Action $indexable_indexing_complete_action The complete indexing action.
|
||||
* @param Indexing_Complete_Action $indexing_complete_action The complete indexing action.
|
||||
* @param Indexing_Prepare_Action $prepare_indexing_action The prepare indexing action.
|
||||
* @param Post_Link_Indexing_Action $post_link_indexing_action The post link indexing action.
|
||||
* @param Term_Link_Indexing_Action $term_link_indexing_action The term link indexing action.
|
||||
* @param Options_Helper $options_helper The options helper.
|
||||
* @param Indexing_Helper $indexing_helper The indexing helper.
|
||||
*/
|
||||
public function __construct(
|
||||
Indexable_Post_Indexation_Action $post_indexation_action,
|
||||
Indexable_Term_Indexation_Action $term_indexation_action,
|
||||
Indexable_Post_Type_Archive_Indexation_Action $post_type_archive_indexation_action,
|
||||
Indexable_General_Indexation_Action $general_indexation_action,
|
||||
Indexable_Indexing_Complete_Action $indexable_indexing_complete_action,
|
||||
Indexing_Complete_Action $indexing_complete_action,
|
||||
Indexing_Prepare_Action $prepare_indexing_action,
|
||||
Post_Link_Indexing_Action $post_link_indexing_action,
|
||||
Term_Link_Indexing_Action $term_link_indexing_action,
|
||||
Options_Helper $options_helper,
|
||||
Indexing_Helper $indexing_helper
|
||||
) {
|
||||
$this->post_indexation_action = $post_indexation_action;
|
||||
$this->term_indexation_action = $term_indexation_action;
|
||||
$this->post_type_archive_indexation_action = $post_type_archive_indexation_action;
|
||||
$this->general_indexation_action = $general_indexation_action;
|
||||
$this->indexable_indexing_complete_action = $indexable_indexing_complete_action;
|
||||
$this->indexing_complete_action = $indexing_complete_action;
|
||||
$this->prepare_indexing_action = $prepare_indexing_action;
|
||||
$this->options_helper = $options_helper;
|
||||
$this->post_link_indexing_action = $post_link_indexing_action;
|
||||
$this->term_link_indexing_action = $term_link_indexing_action;
|
||||
$this->indexing_helper = $indexing_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the routes used to index indexables.
|
||||
*/
|
||||
public function register_routes() {
|
||||
$route_args = [
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'index_posts' ],
|
||||
'permission_callback' => [ $this, 'can_index' ],
|
||||
];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::POSTS_ROUTE, $route_args );
|
||||
|
||||
$route_args['callback'] = [ $this, 'index_terms' ];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::TERMS_ROUTE, $route_args );
|
||||
|
||||
$route_args['callback'] = [ $this, 'index_post_type_archives' ];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::POST_TYPE_ARCHIVES_ROUTE, $route_args );
|
||||
|
||||
$route_args['callback'] = [ $this, 'index_general' ];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::GENERAL_ROUTE, $route_args );
|
||||
|
||||
$route_args['callback'] = [ $this, 'prepare' ];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::PREPARE_ROUTE, $route_args );
|
||||
|
||||
$route_args['callback'] = [ $this, 'indexables_complete' ];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::INDEXABLES_COMPLETE_ROUTE, $route_args );
|
||||
|
||||
$route_args['callback'] = [ $this, 'complete' ];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::COMPLETE_ROUTE, $route_args );
|
||||
|
||||
$route_args['callback'] = [ $this, 'index_post_links' ];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::POST_LINKS_INDEXING_ROUTE, $route_args );
|
||||
|
||||
$route_args['callback'] = [ $this, 'index_term_links' ];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::TERM_LINKS_INDEXING_ROUTE, $route_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes a number of unindexed posts.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function index_posts() {
|
||||
return $this->run_indexation_action( $this->post_indexation_action, self::FULL_POSTS_ROUTE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes a number of unindexed terms.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function index_terms() {
|
||||
return $this->run_indexation_action( $this->term_indexation_action, self::FULL_TERMS_ROUTE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes a number of unindexed post type archive pages.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function index_post_type_archives() {
|
||||
return $this->run_indexation_action( $this->post_type_archive_indexation_action, self::FULL_POST_TYPE_ARCHIVES_ROUTE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes a number of unindexed general items.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function index_general() {
|
||||
return $this->run_indexation_action( $this->general_indexation_action, self::FULL_GENERAL_ROUTE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes a number of posts for post links.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function index_post_links() {
|
||||
return $this->run_indexation_action( $this->post_link_indexing_action, self::FULL_POST_LINKS_INDEXING_ROUTE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes a number of terms for term links.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function index_term_links() {
|
||||
return $this->run_indexation_action( $this->term_link_indexing_action, self::FULL_TERM_LINKS_INDEXING_ROUTE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the indexation.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function prepare() {
|
||||
$this->prepare_indexing_action->prepare();
|
||||
|
||||
return $this->respond_with( [], false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes the indexable indexation.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function indexables_complete() {
|
||||
$this->indexable_indexing_complete_action->complete();
|
||||
|
||||
return $this->respond_with( [], false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes the indexation.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function complete() {
|
||||
$this->indexing_complete_action->complete();
|
||||
|
||||
return $this->respond_with( [], false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the current user is allowed to index.
|
||||
*
|
||||
* @return bool Whether or not the current user is allowed to index.
|
||||
*/
|
||||
public function can_index() {
|
||||
return \current_user_can( 'edit_posts' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs an indexing action and returns the response.
|
||||
*
|
||||
* @param Indexation_Action_Interface $indexation_action The indexing action.
|
||||
* @param string $url The url of the indexing route.
|
||||
*
|
||||
* @return WP_REST_Response|WP_Error The response, or an error when running the indexing action failed.
|
||||
*/
|
||||
protected function run_indexation_action( Indexation_Action_Interface $indexation_action, $url ) {
|
||||
try {
|
||||
return parent::run_indexation_action( $indexation_action, $url );
|
||||
} catch ( Exception $exception ) {
|
||||
$this->indexing_helper->indexing_failed();
|
||||
|
||||
return new WP_Error(
|
||||
'wpseo_error_indexing',
|
||||
$exception->getMessage(),
|
||||
[ 'stackTrace' => $exception->getTraceAsString() ]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\Actions\Integrations_Action;
|
||||
use Yoast\WP\SEO\Conditionals\No_Conditionals;
|
||||
use Yoast\WP\SEO\Main;
|
||||
|
||||
/**
|
||||
* Integrations_Route class.
|
||||
*/
|
||||
class Integrations_Route implements Route_Interface {
|
||||
|
||||
use No_Conditionals;
|
||||
|
||||
/**
|
||||
* Represents the integrations route.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const INTEGRATIONS_ROUTE = '/integrations';
|
||||
|
||||
/**
|
||||
* Represents a route to set the state of an integration.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const SET_ACTIVE_ROUTE = '/set_active';
|
||||
|
||||
/**
|
||||
* The integrations action.
|
||||
*
|
||||
* @var Integrations_Action
|
||||
*/
|
||||
private $integrations_action;
|
||||
|
||||
/**
|
||||
* Integrations_Route constructor.
|
||||
*
|
||||
* @param Integrations_Action $integrations_action The integrations action.
|
||||
*/
|
||||
public function __construct(
|
||||
Integrations_Action $integrations_action
|
||||
) {
|
||||
$this->integrations_action = $integrations_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes() {
|
||||
$set_active_route = [
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'set_integration_active' ],
|
||||
'permission_callback' => [ $this, 'can_manage_options' ],
|
||||
'args' => [
|
||||
'active' => [
|
||||
'type' => 'boolean',
|
||||
'required' => true,
|
||||
],
|
||||
'integration' => [
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::INTEGRATIONS_ROUTE . self::SET_ACTIVE_ROUTE, $set_active_route );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current user has the right capability.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function can_manage_options() {
|
||||
return \current_user_can( 'wpseo_manage_options' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets integration state.
|
||||
*
|
||||
* @param WP_REST_Request $request The request.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function set_integration_active( WP_REST_Request $request ) {
|
||||
$params = $request->get_json_params();
|
||||
$integration_name = $params['integration'];
|
||||
$value = $params['active'];
|
||||
|
||||
$data = $this
|
||||
->integrations_action
|
||||
->set_integration_active( $integration_name, $value );
|
||||
|
||||
return new WP_REST_Response(
|
||||
[ 'json' => $data ]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\Conditionals\No_Conditionals;
|
||||
use Yoast\WP\SEO\Main;
|
||||
|
||||
/**
|
||||
* Meta_Search_Route class
|
||||
*/
|
||||
class Meta_Search_Route implements Route_Interface {
|
||||
|
||||
use No_Conditionals;
|
||||
|
||||
/**
|
||||
* Represents meta search route.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const META_SEARCH_ROUTE = '/meta/search';
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes() {
|
||||
$route = [
|
||||
[
|
||||
'methods' => 'GET',
|
||||
'callback' => [ $this, 'search_meta' ],
|
||||
'permission_callback' => [ $this, 'permission_check' ],
|
||||
],
|
||||
];
|
||||
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::META_SEARCH_ROUTE, $route );
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the permission check.
|
||||
*
|
||||
* @param WP_REST_Request $request The request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function permission_check( $request ) {
|
||||
if ( ! isset( $request['post_id'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$post_type = \get_post_type( $request['post_id'] );
|
||||
$post_type_object = \get_post_type_object( $post_type );
|
||||
|
||||
return \current_user_can( $post_type_object->cap->edit_posts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches meta fields of a given post.
|
||||
*
|
||||
* @param WP_REST_Request $request The REST request.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function search_meta( $request ) {
|
||||
$post_id = $request['post_id'];
|
||||
$query = $request['query'];
|
||||
$meta = \get_post_custom( $post_id );
|
||||
$matches = [];
|
||||
|
||||
foreach ( $meta as $key => $values ) {
|
||||
if ( \substr( $key, 0, \strlen( $query ) ) !== $query ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( empty( $query ) && \substr( $key, 0, 1 ) === '_' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip custom field values that are serialized.
|
||||
if ( \is_serialized( $values[0] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$matches[] = [
|
||||
'key' => $key,
|
||||
'value' => $values[0],
|
||||
];
|
||||
|
||||
if ( \count( $matches ) >= 25 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return \rest_ensure_response( [ 'meta' => $matches ] );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use Yoast\WP\SEO\Loadable_Interface;
|
||||
|
||||
/**
|
||||
* Route interface.
|
||||
*/
|
||||
interface Route_Interface extends Loadable_Interface {
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes();
|
||||
}
|
||||
248
wp/wp-content/plugins/wordpress-seo/src/routes/semrush-route.php
Normal file
248
wp/wp-content/plugins/wordpress-seo/src/routes/semrush-route.php
Normal file
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\Actions\SEMrush\SEMrush_Login_Action;
|
||||
use Yoast\WP\SEO\Actions\SEMrush\SEMrush_Options_Action;
|
||||
use Yoast\WP\SEO\Actions\SEMrush\SEMrush_Phrases_Action;
|
||||
use Yoast\WP\SEO\Conditionals\SEMrush_Enabled_Conditional;
|
||||
use Yoast\WP\SEO\Main;
|
||||
|
||||
/**
|
||||
* SEMrush_Route class.
|
||||
*/
|
||||
class SEMrush_Route implements Route_Interface {
|
||||
|
||||
/**
|
||||
* The SEMrush route prefix.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const ROUTE_PREFIX = 'semrush';
|
||||
|
||||
/**
|
||||
* The authenticate route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const AUTHENTICATION_ROUTE = self::ROUTE_PREFIX . '/authenticate';
|
||||
|
||||
/**
|
||||
* The country code option route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const COUNTRY_CODE_OPTION_ROUTE = self::ROUTE_PREFIX . '/country_code';
|
||||
|
||||
/**
|
||||
* The request related keyphrases route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const RELATED_KEYPHRASES_ROUTE = self::ROUTE_PREFIX . '/related_keyphrases';
|
||||
|
||||
/**
|
||||
* The full login route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FULL_AUTHENTICATION_ROUTE = Main::API_V1_NAMESPACE . '/' . self::AUTHENTICATION_ROUTE;
|
||||
|
||||
/**
|
||||
* The full country code option route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FULL_COUNTRY_CODE_OPTION_ROUTE = Main::API_V1_NAMESPACE . '/' . self::COUNTRY_CODE_OPTION_ROUTE;
|
||||
|
||||
/**
|
||||
* The login action.
|
||||
*
|
||||
* @var SEMrush_Login_Action
|
||||
*/
|
||||
private $login_action;
|
||||
|
||||
/**
|
||||
* The options action.
|
||||
*
|
||||
* @var SEMrush_Options_Action
|
||||
*/
|
||||
private $options_action;
|
||||
|
||||
/**
|
||||
* The phrases action.
|
||||
*
|
||||
* @var SEMrush_Phrases_Action
|
||||
*/
|
||||
private $phrases_action;
|
||||
|
||||
/**
|
||||
* Returns the conditionals based in which this loadable should be active.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_conditionals() {
|
||||
return [ SEMrush_Enabled_Conditional::class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* SEMrush_Route constructor.
|
||||
*
|
||||
* @param SEMrush_Login_Action $login_action The login action.
|
||||
* @param SEMrush_Options_Action $options_action The options action.
|
||||
* @param SEMrush_Phrases_Action $phrases_action The phrases action.
|
||||
*/
|
||||
public function __construct(
|
||||
SEMrush_Login_Action $login_action,
|
||||
SEMrush_Options_Action $options_action,
|
||||
SEMrush_Phrases_Action $phrases_action
|
||||
) {
|
||||
$this->login_action = $login_action;
|
||||
$this->options_action = $options_action;
|
||||
$this->phrases_action = $phrases_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes() {
|
||||
$authentication_route_args = [
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'authenticate' ],
|
||||
'permission_callback' => [ $this, 'can_use_semrush' ],
|
||||
'args' => [
|
||||
'code' => [
|
||||
'validate_callback' => [ $this, 'has_valid_code' ],
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::AUTHENTICATION_ROUTE, $authentication_route_args );
|
||||
|
||||
$set_country_code_option_route_args = [
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'set_country_code_option' ],
|
||||
'permission_callback' => [ $this, 'can_use_semrush' ],
|
||||
'args' => [
|
||||
'country_code' => [
|
||||
'validate_callback' => [ $this, 'has_valid_country_code' ],
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::COUNTRY_CODE_OPTION_ROUTE, $set_country_code_option_route_args );
|
||||
|
||||
$related_keyphrases_route_args = [
|
||||
'methods' => 'GET',
|
||||
'callback' => [ $this, 'get_related_keyphrases' ],
|
||||
'permission_callback' => [ $this, 'can_use_semrush' ],
|
||||
'args' => [
|
||||
'keyphrase' => [
|
||||
'validate_callback' => [ $this, 'has_valid_keyphrase' ],
|
||||
'required' => true,
|
||||
],
|
||||
'country_code' => [
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::RELATED_KEYPHRASES_ROUTE, $related_keyphrases_route_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates with SEMrush.
|
||||
*
|
||||
* @param WP_REST_Request $request The request. This request should have a code param set.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function authenticate( WP_REST_Request $request ) {
|
||||
$data = $this
|
||||
->login_action
|
||||
->authenticate( $request['code'] );
|
||||
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SEMrush country code option.
|
||||
*
|
||||
* @param WP_REST_Request $request The request. This request should have a country code param set.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function set_country_code_option( WP_REST_Request $request ) {
|
||||
$data = $this
|
||||
->options_action
|
||||
->set_country_code( $request['country_code'] );
|
||||
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a valid code was returned.
|
||||
*
|
||||
* @param string $code The code to check.
|
||||
*
|
||||
* @return bool Whether or not the code is valid.
|
||||
*/
|
||||
public function has_valid_code( $code ) {
|
||||
return $code !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a valid keyphrase is provided.
|
||||
*
|
||||
* @param string $keyphrase The keyphrase to check.
|
||||
*
|
||||
* @return bool Whether or not the keyphrase is valid.
|
||||
*/
|
||||
public function has_valid_keyphrase( $keyphrase ) {
|
||||
return \trim( $keyphrase ) !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the related keyphrases based on the passed keyphrase and database code.
|
||||
*
|
||||
* @param WP_REST_Request $request The request. This request should have a keyphrase and country_code param set.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function get_related_keyphrases( WP_REST_Request $request ) {
|
||||
$data = $this
|
||||
->phrases_action
|
||||
->get_related_keyphrases(
|
||||
$request['keyphrase'],
|
||||
$request['country_code']
|
||||
);
|
||||
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a valid country code was submitted.
|
||||
*
|
||||
* @param string $country_code The country code to check.
|
||||
*
|
||||
* @return bool Whether or not the country code is valid.
|
||||
*/
|
||||
public function has_valid_country_code( $country_code ) {
|
||||
return ( $country_code !== '' && \preg_match( '/^[a-z]{2}$/', $country_code ) === 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the current user is allowed to edit post/pages and thus use the SEMrush integration.
|
||||
*
|
||||
* @return bool Whether or not the current user is allowed to use SEMrush.
|
||||
*/
|
||||
public function can_use_semrush() {
|
||||
return \current_user_can( 'edit_posts' ) || \current_user_can( 'edit_pages' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\Conditionals\Addon_Installation_Conditional;
|
||||
use Yoast\WP\SEO\Main;
|
||||
|
||||
/**
|
||||
* Supported_Features_Route class.
|
||||
*/
|
||||
class Supported_Features_Route implements Route_Interface {
|
||||
|
||||
/**
|
||||
* Represents the supported features route.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const SUPPORTED_FEATURES_ROUTE = '/supported-features';
|
||||
|
||||
/**
|
||||
* Returns the conditionals based in which this loadable should be active.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_conditionals() {
|
||||
return [
|
||||
Addon_Installation_Conditional::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes() {
|
||||
$supported_features_route = [
|
||||
'methods' => 'GET',
|
||||
'callback' => [ $this, 'get_supported_features' ],
|
||||
'permission_callback' => '__return_true',
|
||||
];
|
||||
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::SUPPORTED_FEATURES_ROUTE, $supported_features_route );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of features supported by this yoast seo installation.
|
||||
*
|
||||
* @return WP_REST_Response a list of features supported by this yoast seo installation.
|
||||
*/
|
||||
public function get_supported_features() {
|
||||
return new WP_REST_Response(
|
||||
[
|
||||
'addon-installation' => 1,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
331
wp/wp-content/plugins/wordpress-seo/src/routes/wincher-route.php
Normal file
331
wp/wp-content/plugins/wordpress-seo/src/routes/wincher-route.php
Normal file
@@ -0,0 +1,331 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\Actions\Wincher\Wincher_Account_Action;
|
||||
use Yoast\WP\SEO\Actions\Wincher\Wincher_Keyphrases_Action;
|
||||
use Yoast\WP\SEO\Actions\Wincher\Wincher_Login_Action;
|
||||
use Yoast\WP\SEO\Conditionals\Wincher_Enabled_Conditional;
|
||||
use Yoast\WP\SEO\Main;
|
||||
|
||||
/**
|
||||
* Wincher_Route class.
|
||||
*/
|
||||
class Wincher_Route implements Route_Interface {
|
||||
|
||||
/**
|
||||
* The Wincher route prefix.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const ROUTE_PREFIX = 'wincher';
|
||||
|
||||
/**
|
||||
* The authorize route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const AUTHORIZATION_URL_ROUTE = self::ROUTE_PREFIX . '/authorization-url';
|
||||
|
||||
/**
|
||||
* The authenticate route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const AUTHENTICATION_ROUTE = self::ROUTE_PREFIX . '/authenticate';
|
||||
|
||||
/**
|
||||
* The track bulk keyphrases route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const KEYPHRASES_TRACK_ROUTE = self::ROUTE_PREFIX . '/keyphrases/track';
|
||||
|
||||
/**
|
||||
* The keyphrases route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const TRACKED_KEYPHRASES_ROUTE = self::ROUTE_PREFIX . '/keyphrases';
|
||||
|
||||
/**
|
||||
* The untrack keyphrase route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const UNTRACK_KEYPHRASE_ROUTE = self::ROUTE_PREFIX . '/keyphrases/untrack';
|
||||
|
||||
/**
|
||||
* The check limit route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const CHECK_LIMIT_ROUTE = self::ROUTE_PREFIX . '/account/limit';
|
||||
|
||||
/**
|
||||
* The upgrade campaign route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const UPGRADE_CAMPAIGN_ROUTE = self::ROUTE_PREFIX . '/account/upgrade-campaign';
|
||||
|
||||
/**
|
||||
* The login action.
|
||||
*
|
||||
* @var Wincher_Login_Action
|
||||
*/
|
||||
private $login_action;
|
||||
|
||||
/**
|
||||
* The account action.
|
||||
*
|
||||
* @var Wincher_Account_Action
|
||||
*/
|
||||
private $account_action;
|
||||
|
||||
/**
|
||||
* The keyphrases action.
|
||||
*
|
||||
* @var Wincher_Keyphrases_Action
|
||||
*/
|
||||
private $keyphrases_action;
|
||||
|
||||
/**
|
||||
* Returns the conditionals based in which this loadable should be active.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_conditionals() {
|
||||
return [ Wincher_Enabled_Conditional::class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Wincher_Route constructor.
|
||||
*
|
||||
* @param Wincher_Login_Action $login_action The login action.
|
||||
* @param Wincher_Account_Action $account_action The account action.
|
||||
* @param Wincher_Keyphrases_Action $keyphrases_action The keyphrases action.
|
||||
*/
|
||||
public function __construct(
|
||||
Wincher_Login_Action $login_action,
|
||||
Wincher_Account_Action $account_action,
|
||||
Wincher_Keyphrases_Action $keyphrases_action
|
||||
) {
|
||||
$this->login_action = $login_action;
|
||||
$this->account_action = $account_action;
|
||||
$this->keyphrases_action = $keyphrases_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes() {
|
||||
$authorize_route_args = [
|
||||
'methods' => 'GET',
|
||||
'callback' => [ $this, 'get_authorization_url' ],
|
||||
'permission_callback' => [ $this, 'can_use_wincher' ],
|
||||
];
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::AUTHORIZATION_URL_ROUTE, $authorize_route_args );
|
||||
|
||||
$authentication_route_args = [
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'authenticate' ],
|
||||
'permission_callback' => [ $this, 'can_use_wincher' ],
|
||||
'args' => [
|
||||
'code' => [
|
||||
'validate_callback' => [ $this, 'has_valid_code' ],
|
||||
'required' => true,
|
||||
],
|
||||
'websiteId' => [
|
||||
'validate_callback' => [ $this, 'has_valid_website_id' ],
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::AUTHENTICATION_ROUTE, $authentication_route_args );
|
||||
|
||||
$track_keyphrases_route_args = [
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'track_keyphrases' ],
|
||||
'permission_callback' => [ $this, 'can_use_wincher' ],
|
||||
'args' => [
|
||||
'keyphrases' => [
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::KEYPHRASES_TRACK_ROUTE, $track_keyphrases_route_args );
|
||||
|
||||
$get_keyphrases_route_args = [
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'get_tracked_keyphrases' ],
|
||||
'permission_callback' => [ $this, 'can_use_wincher' ],
|
||||
'args' => [
|
||||
'keyphrases' => [
|
||||
'required' => false,
|
||||
],
|
||||
'permalink' => [
|
||||
'required' => false,
|
||||
],
|
||||
'startAt' => [
|
||||
'required' => false,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::TRACKED_KEYPHRASES_ROUTE, $get_keyphrases_route_args );
|
||||
|
||||
$delete_keyphrase_route_args = [
|
||||
'methods' => 'DELETE',
|
||||
'callback' => [ $this, 'untrack_keyphrase' ],
|
||||
'permission_callback' => [ $this, 'can_use_wincher' ],
|
||||
];
|
||||
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::UNTRACK_KEYPHRASE_ROUTE, $delete_keyphrase_route_args );
|
||||
|
||||
$check_limit_route_args = [
|
||||
'methods' => 'GET',
|
||||
'callback' => [ $this, 'check_limit' ],
|
||||
'permission_callback' => [ $this, 'can_use_wincher' ],
|
||||
];
|
||||
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::CHECK_LIMIT_ROUTE, $check_limit_route_args );
|
||||
|
||||
$get_upgrade_campaign_route_args = [
|
||||
'methods' => 'GET',
|
||||
'callback' => [ $this, 'get_upgrade_campaign' ],
|
||||
'permission_callback' => [ $this, 'can_use_wincher' ],
|
||||
];
|
||||
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::UPGRADE_CAMPAIGN_ROUTE, $get_upgrade_campaign_route_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the authorization URL.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function get_authorization_url() {
|
||||
$data = $this->login_action->get_authorization_url();
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates with Wincher.
|
||||
*
|
||||
* @param WP_REST_Request $request The request. This request should have a code param set.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function authenticate( WP_REST_Request $request ) {
|
||||
$data = $this
|
||||
->login_action
|
||||
->authenticate( $request['code'], (string) $request['websiteId'] );
|
||||
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Posts keyphrases to track.
|
||||
*
|
||||
* @param WP_REST_Request $request The request. This request should have a code param set.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function track_keyphrases( WP_REST_Request $request ) {
|
||||
$limits = $this->account_action->check_limit();
|
||||
|
||||
if ( $limits->status !== 200 ) {
|
||||
return new WP_REST_Response( $limits, $limits->status );
|
||||
}
|
||||
|
||||
$data = $this->keyphrases_action->track_keyphrases( $request['keyphrases'], $limits );
|
||||
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tracked keyphrases via POST.
|
||||
* This is done via POST, so we don't potentially run into URL limit issues when a lot of long keyphrases are tracked.
|
||||
*
|
||||
* @param WP_REST_Request $request The request. This request should have a code param set.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function get_tracked_keyphrases( WP_REST_Request $request ) {
|
||||
$data = $this->keyphrases_action->get_tracked_keyphrases( $request['keyphrases'], $request['permalink'], $request['startAt'] );
|
||||
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Untracks the tracked keyphrase.
|
||||
*
|
||||
* @param WP_REST_Request $request The request. This request should have a code param set.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function untrack_keyphrase( WP_REST_Request $request ) {
|
||||
$data = $this->keyphrases_action->untrack_keyphrase( $request['keyphraseID'] );
|
||||
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the account limit.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function check_limit() {
|
||||
$data = $this->account_action->check_limit();
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the upgrade campaign.
|
||||
* If it's not a free user, no campaign is returned.
|
||||
*
|
||||
* @return WP_REST_Response The response.
|
||||
*/
|
||||
public function get_upgrade_campaign() {
|
||||
$data = $this->account_action->get_upgrade_campaign();
|
||||
return new WP_REST_Response( $data, $data->status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a valid code was returned.
|
||||
*
|
||||
* @param string $code The code to check.
|
||||
*
|
||||
* @return bool Whether the code is valid.
|
||||
*/
|
||||
public function has_valid_code( $code ) {
|
||||
return $code !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a valid website_id was returned.
|
||||
*
|
||||
* @param int $website_id The website_id to check.
|
||||
*
|
||||
* @return bool Whether the website_id is valid.
|
||||
*/
|
||||
public function has_valid_website_id( $website_id ) {
|
||||
return ! empty( $website_id ) && \is_int( $website_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the current user is allowed to publish post/pages and thus use the Wincher integration.
|
||||
*
|
||||
* @return bool Whether the current user is allowed to use Wincher.
|
||||
*/
|
||||
public function can_use_wincher() {
|
||||
return \current_user_can( 'publish_posts' ) || \current_user_can( 'publish_pages' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\Conditionals\No_Conditionals;
|
||||
use Yoast\WP\SEO\Helpers\Options_Helper;
|
||||
use Yoast\WP\SEO\Main;
|
||||
|
||||
/**
|
||||
* Workouts_Route class.
|
||||
*/
|
||||
class Workouts_Route implements Route_Interface {
|
||||
|
||||
use No_Conditionals;
|
||||
|
||||
/**
|
||||
* Represents workouts route.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const WORKOUTS_ROUTE = '/workouts';
|
||||
|
||||
/**
|
||||
* The Options helper.
|
||||
*
|
||||
* @var Options_Helper
|
||||
*/
|
||||
private $options_helper;
|
||||
|
||||
/**
|
||||
* Workouts_Route constructor.
|
||||
*
|
||||
* @param Options_Helper $options_helper The options helper.
|
||||
*/
|
||||
public function __construct(
|
||||
Options_Helper $options_helper
|
||||
) {
|
||||
$this->options_helper = $options_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes() {
|
||||
$edit_others_posts = static function() {
|
||||
return \current_user_can( 'edit_others_posts' );
|
||||
};
|
||||
|
||||
$workouts_route = [
|
||||
[
|
||||
'methods' => 'GET',
|
||||
'callback' => [ $this, 'get_workouts' ],
|
||||
'permission_callback' => $edit_others_posts,
|
||||
],
|
||||
[
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'set_workouts' ],
|
||||
'permission_callback' => $edit_others_posts,
|
||||
'args' => $this->get_workouts_routes_args(),
|
||||
],
|
||||
];
|
||||
|
||||
\register_rest_route( Main::API_V1_NAMESPACE, self::WORKOUTS_ROUTE, $workouts_route );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the workouts as configured for the site.
|
||||
*
|
||||
* @return WP_REST_Response the configuration of the workouts.
|
||||
*/
|
||||
public function get_workouts() {
|
||||
$workouts_option = $this->options_helper->get( 'workouts_data' );
|
||||
|
||||
/**
|
||||
* Filter: 'Yoast\WP\SEO\workouts_options' - Allows adding workouts options by the add-ons.
|
||||
*
|
||||
* @api array $workouts_option The content of the `workouts_data` option in Free.
|
||||
*/
|
||||
$workouts_option = \apply_filters( 'Yoast\WP\SEO\workouts_options', $workouts_option );
|
||||
|
||||
return new WP_REST_Response(
|
||||
[ 'json' => $workouts_option ]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the workout configuration.
|
||||
*
|
||||
* @param WP_REST_Request $request The request object.
|
||||
*
|
||||
* @return WP_REST_Response the configuration of the workouts.
|
||||
*/
|
||||
public function set_workouts( $request ) {
|
||||
$workouts_data = $request->get_json_params();
|
||||
|
||||
/**
|
||||
* Filter: 'Yoast\WP\SEO\workouts_route_save' - Allows the add-ons to save the options data in their own options.
|
||||
*
|
||||
* @api mixed|null $result The result of the previous saving operation.
|
||||
*
|
||||
* @param array $workouts_data The full set of workouts option data to save.
|
||||
*/
|
||||
$result = \apply_filters( 'Yoast\WP\SEO\workouts_route_save', null, $workouts_data );
|
||||
|
||||
return new WP_REST_Response(
|
||||
[ 'json' => $result ]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the args for all the registered workouts.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_workouts_routes_args() {
|
||||
$args_array = [];
|
||||
|
||||
/**
|
||||
* Filter: 'Yoast\WP\SEO\workouts_route_args' - Allows the add-ons add their own arguments to the route registration.
|
||||
*
|
||||
* @api array $args_array The array of arguments for the route registration.
|
||||
*/
|
||||
return \apply_filters( 'Yoast\WP\SEO\workouts_route_args', $args_array );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
<?php // phpcs:ignore Yoast.Files.FileName.InvalidClassFileName -- Reason: this explicitly concerns the Yoast head fields.
|
||||
|
||||
namespace Yoast\WP\SEO\Routes;
|
||||
|
||||
use Yoast\WP\SEO\Actions\Indexables\Indexable_Head_Action;
|
||||
use Yoast\WP\SEO\Conditionals\Headless_Rest_Endpoints_Enabled_Conditional;
|
||||
use Yoast\WP\SEO\Helpers\Post_Helper;
|
||||
use Yoast\WP\SEO\Helpers\Post_Type_Helper;
|
||||
use Yoast\WP\SEO\Helpers\Taxonomy_Helper;
|
||||
|
||||
/**
|
||||
* Yoast_Head_REST_Field class.
|
||||
*
|
||||
* Registers the yoast head REST field.
|
||||
* Not technically a route but behaves the same so is included here.
|
||||
*/
|
||||
class Yoast_Head_REST_Field implements Route_Interface {
|
||||
|
||||
/**
|
||||
* The name of the Yoast head field.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const YOAST_HEAD_ATTRIBUTE_NAME = 'yoast_head';
|
||||
|
||||
/**
|
||||
* The name of the Yoast head JSON field.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const YOAST_JSON_HEAD_ATTRIBUTE_NAME = 'yoast_head_json';
|
||||
|
||||
/**
|
||||
* The post type helper.
|
||||
*
|
||||
* @var Post_Type_Helper
|
||||
*/
|
||||
protected $post_type_helper;
|
||||
|
||||
/**
|
||||
* The taxonomy helper.
|
||||
*
|
||||
* @var Taxonomy_Helper
|
||||
*/
|
||||
protected $taxonomy_helper;
|
||||
|
||||
/**
|
||||
* The post helper.
|
||||
*
|
||||
* @var Post_Helper
|
||||
*/
|
||||
protected $post_helper;
|
||||
|
||||
/**
|
||||
* The head action.
|
||||
*
|
||||
* @var Indexable_Head_Action
|
||||
*/
|
||||
protected $head_action;
|
||||
|
||||
/**
|
||||
* Returns the conditionals based in which this loadable should be active.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_conditionals() {
|
||||
return [ Headless_Rest_Endpoints_Enabled_Conditional::class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Yoast_Head_REST_Field constructor.
|
||||
*
|
||||
* @param Post_Type_Helper $post_type_helper The post type helper.
|
||||
* @param Taxonomy_Helper $taxonomy_helper The taxonomy helper.
|
||||
* @param Post_Helper $post_helper The post helper.
|
||||
* @param Indexable_Head_Action $head_action The head action.
|
||||
*/
|
||||
public function __construct(
|
||||
Post_Type_Helper $post_type_helper,
|
||||
Taxonomy_Helper $taxonomy_helper,
|
||||
Post_Helper $post_helper,
|
||||
Indexable_Head_Action $head_action
|
||||
) {
|
||||
$this->post_type_helper = $post_type_helper;
|
||||
$this->taxonomy_helper = $taxonomy_helper;
|
||||
$this->post_helper = $post_helper;
|
||||
$this->head_action = $head_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes() {
|
||||
$public_post_types = $this->post_type_helper->get_indexable_post_types();
|
||||
|
||||
foreach ( $public_post_types as $post_type ) {
|
||||
$this->register_rest_fields( $post_type, 'for_post' );
|
||||
}
|
||||
|
||||
$public_taxonomies = $this->taxonomy_helper->get_indexable_taxonomies();
|
||||
|
||||
foreach ( $public_taxonomies as $taxonomy ) {
|
||||
if ( $taxonomy === 'post_tag' ) {
|
||||
$taxonomy = 'tag';
|
||||
}
|
||||
$this->register_rest_fields( $taxonomy, 'for_term' );
|
||||
}
|
||||
|
||||
$this->register_rest_fields( 'user', 'for_author' );
|
||||
$this->register_rest_fields( 'type', 'for_post_type_archive' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the head for a post.
|
||||
*
|
||||
* @param array $params The rest request params.
|
||||
* @param string $format The desired output format.
|
||||
*
|
||||
* @return string|null The head.
|
||||
*/
|
||||
public function for_post( $params, $format = self::YOAST_HEAD_ATTRIBUTE_NAME ) {
|
||||
if ( ! isset( $params['id'] ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( ! $this->post_helper->is_post_indexable( $params['id'] ) ) {
|
||||
return null;
|
||||
}
|
||||
$obj = $this->head_action->for_post( $params['id'] );
|
||||
|
||||
return $this->render_object( $obj, $format );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the head for a term.
|
||||
*
|
||||
* @param array $params The rest request params.
|
||||
* @param string $format The desired output format.
|
||||
*
|
||||
* @return string|null The head.
|
||||
*/
|
||||
public function for_term( $params, $format = self::YOAST_HEAD_ATTRIBUTE_NAME ) {
|
||||
$obj = $this->head_action->for_term( $params['id'] );
|
||||
|
||||
return $this->render_object( $obj, $format );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the head for an author.
|
||||
*
|
||||
* @param array $params The rest request params.
|
||||
* @param string $format The desired output format.
|
||||
*
|
||||
* @return string|null The head.
|
||||
*/
|
||||
public function for_author( $params, $format = self::YOAST_HEAD_ATTRIBUTE_NAME ) {
|
||||
$obj = $this->head_action->for_author( $params['id'] );
|
||||
|
||||
return $this->render_object( $obj, $format );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the head for a post type archive.
|
||||
*
|
||||
* @param array $params The rest request params.
|
||||
* @param string $format The desired output format.
|
||||
*
|
||||
* @return string|null The head.
|
||||
*/
|
||||
public function for_post_type_archive( $params, $format = self::YOAST_HEAD_ATTRIBUTE_NAME ) {
|
||||
if ( $params['slug'] === 'post' ) {
|
||||
$obj = $this->head_action->for_posts_page();
|
||||
}
|
||||
elseif ( ! $this->post_type_helper->has_archive( $params['slug'] ) ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
$obj = $this->head_action->for_post_type_archive( $params['slug'] );
|
||||
}
|
||||
|
||||
return $this->render_object( $obj, $format );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the Yoast rest fields.
|
||||
*
|
||||
* @param string $object_type The object type.
|
||||
* @param string $callback The function name of the callback.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function register_rest_fields( $object_type, $callback ) {
|
||||
// Output metadata in page head meta tags.
|
||||
\register_rest_field( $object_type, self::YOAST_HEAD_ATTRIBUTE_NAME, [ 'get_callback' => [ $this, $callback ] ] );
|
||||
// Output metadata in a json object in a head meta tag.
|
||||
\register_rest_field( $object_type, self::YOAST_JSON_HEAD_ATTRIBUTE_NAME, [ 'get_callback' => [ $this, $callback ] ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the correct property for the Yoast head.
|
||||
*
|
||||
* @param stdObject $head The Yoast head.
|
||||
* @param string $format The format to return.
|
||||
*
|
||||
* @return string|array|null The output value. String if HTML was requested, array otherwise.
|
||||
*/
|
||||
protected function render_object( $head, $format = self::YOAST_HEAD_ATTRIBUTE_NAME ) {
|
||||
if ( $head->status === 404 ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch ( $format ) {
|
||||
case self::YOAST_HEAD_ATTRIBUTE_NAME:
|
||||
return $head->html;
|
||||
case self::YOAST_JSON_HEAD_ATTRIBUTE_NAME:
|
||||
return $head->json;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user