229 lines
17 KiB
PHP
229 lines
17 KiB
PHP
<?php
|
|
namespace AIOSEO\Plugin\Pro\Api;
|
|
|
|
// Exit if accessed directly.
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
use AIOSEO\Plugin\Common\Api as CommonApi;
|
|
|
|
/**
|
|
* Api class for the admin.
|
|
*
|
|
* @since 4.0.0
|
|
*/
|
|
class Api extends CommonApi\Api {
|
|
/**
|
|
* The routes we use in the rest API.
|
|
*
|
|
* @since 4.0.0
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $proRoutes = [
|
|
// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound, Generic.Files.LineLength.MaxExceeded
|
|
'GET' => [
|
|
'network-robots/(?P<siteId>[\d]+|network)' => [ 'callback' => [ 'Network', 'fetchSiteRobots' ], 'access' => 'manage_network' ],
|
|
'schema/templates' => [ 'callback' => [ 'Schema', 'getTemplates' ], 'access' => 'aioseo_page_schema_settings' ],
|
|
'search-statistics/stats/seo-statistics' => [ 'callback' => [ 'SearchStatistics\SearchStatistics', 'getSeoStatistics' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/stats/keywords' => [ 'callback' => [ 'SearchStatistics\SearchStatistics', 'getKeywords' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/stats/content-rankings' => [ 'callback' => [ 'SearchStatistics\SearchStatistics', 'getContentRankings' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/post-detail' => [ 'callback' => [ 'SearchStatistics\SearchStatistics', 'getPostDetail' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/post-detail/seo-statistics' => [ 'callback' => [ 'SearchStatistics\SearchStatistics', 'getPostDetailSeoStatistics' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/post-detail/keywords' => [ 'callback' => [ 'SearchStatistics\SearchStatistics', 'getPostDetailKeywords' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/post-detail/focus-keyword' => [ 'callback' => [ 'SearchStatistics\SearchStatistics', 'getPostDetailFocusKeywordTrend' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/pagespeed' => [ 'callback' => [ 'SearchStatistics\SearchStatistics', 'getPageSpeed' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/seo-analysis' => [ 'callback' => [ 'SearchStatistics\SearchStatistics', 'getSeoAnalysis' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/inspection-result' => [ 'callback' => [ 'SearchStatistics\SearchStatistics', 'getInspectionResult' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/index-status/objects' => [ 'callback' => [ 'SearchStatistics\IndexStatus', 'fetchObjects' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/index-status/overview' => [ 'callback' => [ 'SearchStatistics\IndexStatus', 'fetchOverview' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/keyword-rank-tracker/groups' => [ 'callback' => [ 'SearchStatistics\KeywordRankTracker', 'fetchGroups' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/keyword-rank-tracker/keywords' => [ 'callback' => [ 'SearchStatistics\KeywordRankTracker', 'fetchKeywords' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/keyword-rank-tracker/related-keywords' => [ 'callback' => [ 'SearchStatistics\KeywordRankTracker', 'fetchRelatedKeywords' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'seo-revisions/(?P<context>post|term)/(?P<id>[\d]+)' => [ 'callback' => [ 'SeoRevisions', 'getRevisions' ], 'access' => 'aioseo_page_seo_revisions_settings' ],
|
|
'seo-revisions/diff' => [ 'callback' => [ 'SeoRevisions', 'getRevisionsDiff' ], 'access' => 'aioseo_page_seo_revisions_settings' ],
|
|
'seo-analysis/issues' => [ 'callback' => [ 'SeoAnalysis', 'getIssues' ], 'access' => 'aioseo_seo_analysis_settings' ],
|
|
'seo-analysis/issues/(?P<objectType>[\a-z]+)/(?P<objectId>[\0-9z]+)' => [ 'callback' => [ 'SeoAnalysis', 'getIssuesByObject' ], 'access' => 'aioseo_seo_analysis_settings' ],
|
|
'seo-analysis/objects/(?P<issueCode>[\a-z]+)' => [ 'callback' => [ 'SeoAnalysis', 'getObjectsByIssueCode' ], 'access' => 'aioseo_seo_analysis_settings' ],
|
|
'seo-analysis/objects' => [ 'callback' => [ 'SeoAnalysis', 'getObjects' ], 'access' => 'aioseo_seo_analysis_settings' ],
|
|
'seo-analysis/objects-scan-percent' => [ 'callback' => [ 'SeoAnalysis', 'getObjectsScanPercent' ], 'access' => 'aioseo_seo_analysis_settings' ],
|
|
// Redirects
|
|
'redirects/options' => [ 'callback' => [ 'Redirects', 'getOptions' ], 'access' => 'aioseo_redirects_settings' ],
|
|
'redirects/export/(?P<server>apache|nginx)' => [ 'callback' => [ 'Redirects', 'exportServer' ], 'access' => 'aioseo_redirects_settings' ],
|
|
'redirects/export-logs/(?P<type>redirect|404)' => [ 'callback' => [ 'Redirects', 'exportLogs' ], 'access' => 'aioseo_redirects_settings' ],
|
|
'redirects/server/test' => [ 'callback' => [ 'Redirects', 'serverTest' ], 'access' => 'aioseo_redirects_manage' ],
|
|
'redirects/(?P<context>post|term)/(?P<id>[\d]+)' => [ 'callback' => [ 'Redirects', 'getRedirects' ], 'access' => [ 'aioseo_redirects_manage', 'aioseo_page_redirects_manage' ] ],
|
|
'redirects/manual-redirects/(?P<hash>[a-zA-Z0-9]+)' => [ 'callback' => [ 'Redirects', 'getManualRedirects' ], 'access' => 'aioseo_redirects_manage' ]
|
|
],
|
|
'POST' => [
|
|
'activate' => [ 'callback' => [ 'License', 'activateLicense' ], 'access' => 'aioseo_general_settings' ],
|
|
'deactivate' => [ 'callback' => [ 'License', 'deactivateLicense' ], 'access' => 'aioseo_general_settings' ],
|
|
'multisite' => [ 'callback' => [ 'License', 'multisite' ], 'access' => 'aioseo_general_settings' ],
|
|
'activated' => [ 'callback' => [ 'License', 'activated' ], 'access' => 'aioseo_general_settings' ],
|
|
'network-sites/(?P<filter>all|activated|deactivated)' => [ 'callback' => [ 'Network', 'fetchSites' ], 'access' => 'manage_network' ],
|
|
'network-robots/(?P<siteId>[\d]+|network)' => [ 'callback' => [ 'Network', 'saveNetworkRobots' ], 'access' => 'manage_network' ],
|
|
'notification/local-business-organization-reminder' => [ 'callback' => [ 'Notifications', 'localBusinessOrganizationReminder' ], 'access' => 'any' ],
|
|
'notification/news-publication-name-reminder' => [ 'callback' => [ 'Notifications', 'newsPublicationNameReminder' ], 'access' => 'any' ],
|
|
'notification/v3-migration-local-business-number-reminder' => [ 'callback' => [ 'Notifications', 'migrationLocalBusinessNumberReminder' ], 'access' => 'any' ],
|
|
'notification/v3-migration-local-business-country-reminder' => [ 'callback' => [ 'Notifications', 'migrationLocalBusinessCountryReminder' ], 'access' => 'any' ],
|
|
'notification/import-local-business-country-reminder' => [ 'callback' => [ 'Notifications', 'importLocalBusinessCountryReminder' ], 'access' => 'any' ],
|
|
'notification/import-local-business-type-reminder' => [ 'callback' => [ 'Notifications', 'importLocalBusinessTypeReminder' ], 'access' => 'any' ],
|
|
'notification/import-local-business-number-reminder' => [ 'callback' => [ 'Notifications', 'importLocalBusinessNumberReminder' ], 'access' => 'any' ],
|
|
'notification/import-local-business-fax-reminder' => [ 'callback' => [ 'Notifications', 'importLocalBusinessFaxReminder' ], 'access' => 'any' ],
|
|
'notification/import-local-business-currencies-reminder' => [ 'callback' => [ 'Notifications', 'importLocalBusinessCurrenciesReminder' ], 'access' => 'any' ],
|
|
'schema/templates' => [ 'callback' => [ 'Schema', 'addTemplate' ], 'access' => 'aioseo_page_schema_settings' ],
|
|
'schema/validator/output' => [ 'callback' => [ 'Schema', 'getValidatorOutput' ], 'access' => 'aioseo_page_schema_settings' ],
|
|
'search-statistics/stats/keywords/posts' => [ 'callback' => [ 'SearchStatistics\SearchStatistics', 'getPagesByKeywords' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/keyword-rank-tracker/keywords' => [ 'callback' => [ 'SearchStatistics\KeywordRankTracker', 'insertKeywords' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/keyword-rank-tracker/groups' => [ 'callback' => [ 'SearchStatistics\KeywordRankTracker', 'insertGroups' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/keyword-rank-tracker/relationships' => [ 'callback' => [ 'SearchStatistics\KeywordRankTracker', 'updateRelationships' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/keyword-rank-tracker/statistics' => [ 'callback' => [ 'SearchStatistics\KeywordRankTracker', 'fetchStatistics' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'seo-revisions/(?P<id>[\d]+)' => [ 'callback' => [ 'SeoRevisions', 'updateRevision' ], 'access' => 'aioseo_page_seo_revisions_settings' ],
|
|
'seo-revisions/restore/(?P<id>[\d]+)' => [ 'callback' => [ 'SeoRevisions', 'restoreRevision' ], 'access' => 'aioseo_page_seo_revisions_settings' ],
|
|
'seo-analysis/issues/(?P<id>[\d]+)/ignore' => [ 'callback' => [ 'SeoAnalysis', 'ignoreIssue' ], 'access' => 'aioseo_seo_analysis_settings' ],
|
|
'seo-analysis/objects/(?P<id>[\d]+)/keywords' => [ 'callback' => [ 'SeoAnalysis', 'addFocusKeyword' ], 'access' => 'aioseo_seo_analysis_settings' ],
|
|
// Redirects
|
|
'redirects/(?P<filter>enabled|disabled|all)' => [ 'callback' => [ 'Redirects', 'fetchRedirects' ], 'access' => [ 'aioseo_redirects_manage', 'aioseo_page_redirects_manage' ] ],
|
|
'redirects/(?P<slug>logs|404)/(?P<filter>all)' => [ 'callback' => [ 'Redirects', 'fetchLogs' ], 'access' => [ 'aioseo_redirects_manage', 'aioseo_page_redirects_manage' ] ],
|
|
'redirects/bulk/(?P<action>enable|disable|reset-hits)' => [ 'callback' => [ 'Redirects', 'bulk' ], 'access' => [ 'aioseo_redirects_manage', 'aioseo_page_redirects_manage' ] ],
|
|
'redirects' => [ 'callback' => [ 'Redirects', 'create' ], 'access' => [ 'aioseo_redirects_manage', 'aioseo_page_redirects_manage' ] ],
|
|
'redirects/(?P<id>[\d]+)' => [ 'callback' => [ 'Redirects', 'update' ], 'access' => [ 'aioseo_redirects_manage', 'aioseo_page_redirects_manage' ] ],
|
|
'redirects/posts' => [ 'callback' => [ 'Redirects', 'getPosts' ], 'access' => 'aioseo_redirects_manage' ],
|
|
'redirects/export/(?P<type>htaccess|nginx|json)' => [ 'callback' => [ 'Redirects', 'export' ], 'access' => 'aioseo_redirects_settings' ],
|
|
'redirects/import' => [ 'callback' => [ 'Redirects', 'import' ], 'access' => 'aioseo_redirects_settings' ],
|
|
'redirects/import-plugins' => [ 'callback' => [ 'Settings', 'importPlugins', 'AIOSEO\Plugin\Pro\Redirects\Api' ], 'access' => 'aioseo_redirects_settings' ],
|
|
'redirects/import-csv' => [ 'callback' => [ 'Redirects', 'importCsv' ], 'access' => 'aioseo_redirects_settings' ],
|
|
'redirects/(?P<id>[\d]+/test)' => [ 'callback' => [ 'Redirects', 'test' ], 'access' => [ 'aioseo_redirects_manage', 'aioseo_page_redirects_manage' ] ]
|
|
],
|
|
'PUT' => [
|
|
'schema/templates' => [ 'callback' => [ 'Schema', 'updateTemplate' ], 'access' => 'aioseo_page_schema_settings' ],
|
|
'search-statistics/keyword-rank-tracker/groups/(?P<id>[\d]+)' => [ 'callback' => [ 'SearchStatistics\KeywordRankTracker', 'updateGroup' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/keyword-rank-tracker/keywords/(?P<id>[\d]+)' => [ 'callback' => [ 'SearchStatistics\KeywordRankTracker', 'updateKeyword' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
],
|
|
'DELETE' => [
|
|
'schema/templates' => [ 'callback' => [ 'Schema', 'deleteTemplate' ], 'access' => 'aioseo_page_schema_settings' ],
|
|
'seo-revisions/(?P<id>[\d]+)' => [ 'callback' => [ 'SeoRevisions', 'deleteRevision' ], 'access' => 'aioseo_page_seo_revisions_settings' ],
|
|
'search-statistics/keyword-rank-tracker/groups' => [ 'callback' => [ 'SearchStatistics\KeywordRankTracker', 'deleteGroups' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
'search-statistics/keyword-rank-tracker/keywords' => [ 'callback' => [ 'SearchStatistics\KeywordRankTracker', 'deleteKeywords' ], 'access' => 'aioseo_search_statistics_settings' ],
|
|
// Redirects
|
|
'redirects/logs/(?P<slug>logs|404)' => [ 'callback' => [ 'Redirects', 'deleteLog' ], 'access' => 'aioseo_redirects_manage' ],
|
|
'redirects/(?P<id>[\d]+)' => [ 'callback' => [ 'Redirects', 'delete' ], 'access' => [ 'aioseo_redirects_manage', 'aioseo_page_redirects_manage' ] ],
|
|
'redirects/bulk' => [ 'callback' => [ 'Redirects', 'bulkDelete' ], 'access' => 'aioseo_redirects_manage' ]
|
|
]
|
|
// phpcs:enable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound, Generic.Files.LineLength.MaxExceeded
|
|
];
|
|
|
|
/**
|
|
* Get all the routes to register.
|
|
*
|
|
* @since 4.0.0
|
|
*
|
|
* @return array An array of routes.
|
|
*/
|
|
protected function getRoutes() {
|
|
$routes = array_merge_recursive( parent::getRoutes(), $this->proRoutes );
|
|
$addonsRoutes = array_filter( aioseo()->addons->doAddonFunction( 'api', 'getRoutes' ) );
|
|
|
|
foreach ( $addonsRoutes as $addonRoute ) {
|
|
$routes = array_replace_recursive(
|
|
$addonRoute,
|
|
$routes
|
|
);
|
|
}
|
|
|
|
return $routes;
|
|
}
|
|
|
|
/**
|
|
* Pass any API class back to an addon to run a similar method.
|
|
*
|
|
* @since 4.1.0
|
|
*
|
|
* @param \WP_REST_Request $request The original request.
|
|
* @param \WP_REST_Response $response An optional response.
|
|
* @param string $apiClass The class to call.
|
|
* @param string $apiMethod The method to call on the class.
|
|
* @return mixed Anything the addon needs to return.
|
|
*/
|
|
public static function addonsApi( $request, $response, $apiClass, $apiMethod ) {
|
|
$loadedAddons = aioseo()->addons->getLoadedAddons();
|
|
if ( ! empty( $loadedAddons ) ) {
|
|
foreach ( $loadedAddons as $addon ) {
|
|
$class = new \ReflectionClass( $addon );
|
|
$addonClass = $class->getNamespaceName() . $apiClass;
|
|
$classExists = class_exists( $addonClass );
|
|
$methodExists = method_exists( $addonClass, $apiMethod );
|
|
if ( $classExists && $methodExists ) {
|
|
$response = call_user_func_array( [ $addonClass, $apiMethod ], [ $request, $response ] );
|
|
}
|
|
}
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* Validates access from the routes array.
|
|
*
|
|
* @since 4.1.6
|
|
*
|
|
* @param \WP_REST_Request $request The REST Request.
|
|
* @return bool True if validated, false if not.
|
|
*/
|
|
public function validateAccess( $request ) {
|
|
$routeData = $this->getRouteData( $request );
|
|
if ( empty( $routeData ) || empty( $routeData['access'] ) ) {
|
|
return false;
|
|
}
|
|
|
|
// Admins always have access.
|
|
if ( aioseo()->access->isAdmin() ) {
|
|
return true;
|
|
}
|
|
|
|
switch ( $routeData['access'] ) {
|
|
case 'any':
|
|
// The user has access if he has any of our capabilities.
|
|
$user = wp_get_current_user();
|
|
$aioseoCaps = aioseo()->access->getCapabilityList();
|
|
foreach ( $user->get_role_caps() as $capability => $enabled ) {
|
|
if ( $enabled && in_array( $capability, $aioseoCaps, true ) ) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
case 'options':
|
|
// Check that user has access to any of the options pages.
|
|
$user = wp_get_current_user();
|
|
$aioseoCaps = aioseo()->access->getCapabilityList();
|
|
|
|
// Remove all caps that start with aioseo_page_
|
|
$aioseoCaps = array_filter( $aioseoCaps, function( $capability ) {
|
|
return strpos( $capability, 'aioseo_page_' ) !== 0;
|
|
} );
|
|
|
|
foreach ( $user->get_role_caps() as $capability => $enabled ) {
|
|
if ( $enabled && in_array( $capability, $aioseoCaps, true ) ) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
default:
|
|
// The user has access if he has any of the required capabilities.
|
|
if ( ! is_array( $routeData['access'] ) ) {
|
|
$routeData['access'] = [ $routeData['access'] ];
|
|
}
|
|
|
|
foreach ( $routeData['access'] as $access ) {
|
|
if ( current_user_can( $access ) ) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
} |