Files
piratepoet/lib/API/JSON/API.php
amine-mp b6c864e7a1 Change the JSON API error message
[MAILPOET-1103]
2017-10-10 09:45:50 +01:00

204 lines
6.4 KiB
PHP

<?php
namespace MailPoet\API\JSON;
use MailPoet\Config\AccessControl;
use MailPoet\Util\Helpers;
use MailPoet\Util\Security;
use MailPoet\WP\Hooks;
if(!defined('ABSPATH')) exit;
class API {
private $_request_api_version;
private $_request_endpoint;
private $_request_method;
private $_request_token;
private $_request_endpoint_class;
private $_request_data = array();
private $_endpoint_namespaces = array();
private $_available_api_versions = array(
'v1'
);
private $access_control;
const CURRENT_VERSION = 'v1';
function __construct(AccessControl $access_control) {
$this->access_control = $access_control;
foreach($this->_available_api_versions as $available_api_version) {
$this->addEndpointNamespace(
sprintf('%s\%s', __NAMESPACE__, $available_api_version),
$available_api_version
);
}
}
function init() {
// admin security token and API version
add_action(
'admin_head',
array($this, 'setTokenAndAPIVersion')
);
// ajax (logged in users)
add_action(
'wp_ajax_mailpoet',
array($this, 'setupAjax')
);
// ajax (logged out users)
add_action(
'wp_ajax_nopriv_mailpoet',
array($this, 'setupAjax')
);
}
function setupAjax() {
Hooks::doAction('mailpoet_api_setup', array($this));
$this->setRequestData($_POST);
if($this->checkToken() === false) {
$error_message = __('Sorry, but we couldn\'t connect to the MailPoet server. Please refresh the web page and try again.', 'mailpoet');
$error_response = $this->createErrorResponse(Error::UNAUTHORIZED, $error_message, Response::STATUS_UNAUTHORIZED);
return $error_response->send();
}
$response = $this->processRoute();
$response->send();
}
function setRequestData($data) {
$this->_request_api_version = !empty($data['api_version']) ? $data['api_version']: false;
$this->_request_endpoint = isset($data['endpoint'])
? Helpers::underscoreToCamelCase(trim($data['endpoint']))
: null;
// JS part of /wp-admin/customize.php does not like a 'method' field in a form widget
$method_param_name = isset($data['mailpoet_method']) ? 'mailpoet_method' : 'method';
$this->_request_method = isset($data[$method_param_name])
? Helpers::underscoreToCamelCase(trim($data[$method_param_name]))
: null;
$this->_request_token = isset($data['token'])
? trim($data['token'])
: null;
if(!$this->_request_endpoint || !$this->_request_method || !$this->_request_api_version) {
$error_message = __('Invalid API request.', 'mailpoet');
$error_response = $this->createErrorResponse(Error::BAD_REQUEST, $error_message, Response::STATUS_BAD_REQUEST);
return $error_response;
} else if(!empty($this->_endpoint_namespaces[$this->_request_api_version])) {
foreach($this->_endpoint_namespaces[$this->_request_api_version] as $namespace) {
$endpoint_class = sprintf(
'%s\%s',
$namespace,
ucfirst($this->_request_endpoint)
);
if(class_exists($endpoint_class)) {
$this->_request_endpoint_class = $endpoint_class;
break;
}
}
$this->_request_data = isset($data['data'])
? stripslashes_deep($data['data'])
: array();
// remove reserved keywords from data
if(is_array($this->_request_data) && !empty($this->_request_data)) {
// filter out reserved keywords from data
$reserved_keywords = array(
'token',
'endpoint',
'method',
'api_version',
'mailpoet_method', // alias of 'method'
'mailpoet_redirect'
);
$this->_request_data = array_diff_key(
$this->_request_data,
array_flip($reserved_keywords)
);
}
}
}
function processRoute() {
try {
if(empty($this->_request_endpoint_class)) {
throw new \Exception(__('Invalid API endpoint.', 'mailpoet'));
}
$endpoint = new $this->_request_endpoint_class();
if(!method_exists($endpoint, $this->_request_method)) {
throw new \Exception(__('Invalid API endpoint method.', 'mailpoet'));
}
// check the accessibility of the requested endpoint's action
// by default, an endpoint's action is considered "private"
if(!$this->validatePermissions($this->_request_method, $endpoint->permissions)) {
$error_message = __('You do not have the required permissions.', 'mailpoet');
$error_response = $this->createErrorResponse(Error::FORBIDDEN, $error_message, Response::STATUS_FORBIDDEN);
return $error_response;
}
$response = $endpoint->{$this->_request_method}($this->_request_data);
return $response;
} catch(\Exception $e) {
$error_message = $e->getMessage();
$error_response = $this->createErrorResponse(Error::BAD_REQUEST, $error_message, Response::STATUS_BAD_REQUEST);
return $error_response;
}
}
function validatePermissions($request_method, $permissions) {
// validate method permission if defined, otherwise validate global permission
return(!empty($permissions['methods'][$request_method])) ?
$this->access_control->validatePermission($permissions['methods'][$request_method]) :
$this->access_control->validatePermission($permissions['global']);
}
function checkToken() {
return wp_verify_nonce($this->_request_token, 'mailpoet_token');
}
function setTokenAndAPIVersion() {
$global = '<script type="text/javascript">';
$global .= 'var mailpoet_token = "%s";';
$global .= 'var mailpoet_api_version = "%s";';
$global .= '</script>';
echo sprintf(
$global,
Security::generateToken(),
self::CURRENT_VERSION
);
}
function addEndpointNamespace($namespace, $version) {
if(!empty($this->_endpoint_namespaces[$version][$namespace])) return;
$this->_endpoint_namespaces[$version][] = $namespace;
}
function getEndpointNamespaces() {
return $this->_endpoint_namespaces;
}
function getRequestedEndpointClass() {
return $this->_request_endpoint_class;
}
function getRequestedAPIVersion() {
return $this->_request_api_version;
}
function createErrorResponse($error_type, $error_message, $response_status) {
$error_response = new ErrorResponse(
array(
$error_type => $error_message
),
array(),
$response_status
);
return $error_response;
}
}