diff --git a/assets/js/src/ajax.js b/assets/js/src/ajax.js index 3878a3582a..eccef1c790 100644 --- a/assets/js/src/ajax.js +++ b/assets/js/src/ajax.js @@ -5,6 +5,7 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function(MailPoet, jQuery, options: {}, defaults: { url: null, + api_version: null, endpoint: null, action: null, token: null, @@ -26,10 +27,16 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function(MailPoet, jQuery, if(this.options.token === null) { this.options.token = window.mailpoet_token; } + + // set default API version + if(this.options.api_version === null) { + this.options.api_version = window.mailpoet_api_version; + } }, getParams: function() { return { action: 'mailpoet', + api_version: this.options.api_version, token: this.options.token, endpoint: this.options.endpoint, method: this.options.action, diff --git a/lib/API/API.php b/lib/API/API.php index 030ffdd408..f70f0f257e 100644 --- a/lib/API/API.php +++ b/lib/API/API.php @@ -8,6 +8,7 @@ use MailPoet\WP\Hooks; if(!defined('ABSPATH')) exit; class API { + private $_api_version; private $_endpoint; private $_method; private $_token; @@ -16,15 +17,17 @@ class API { private $_endpoint_class; private $_data = array(); + const CURRENT_VERSION = 1; + function __construct() { $this->addEndpointNamespace(__NAMESPACE__ . "\\Endpoints"); } function init() { - // Admin Security token + // admin security token and API version add_action( 'admin_head', - array($this, 'setToken') + array($this, 'setTokenAndAPIVersion') ); // ajax (logged in users) @@ -61,6 +64,13 @@ class API { } function getRequestData($data) { + $this->_api_version = sprintf( + 'v%s', + isset($data['api_version']) + ? $data['api_version'] + : self::CURRENT_VERSION + ); + $this->_endpoint = isset($data['endpoint']) ? Helpers::underscoreToCamelCase(trim($data['endpoint'])) : null; @@ -87,7 +97,7 @@ class API { $error_response->send(); } else { foreach($this->_endpoint_namespaces as $namespace) { - $class_name = $namespace . "\\" . ucfirst($this->_endpoint); + $class_name = $namespace . "\\" . $this->_api_version . "\\" . ucfirst($this->_endpoint); if(class_exists($class_name)) { $this->_endpoint_class = $class_name; } @@ -164,13 +174,16 @@ class API { return wp_verify_nonce($this->_token, 'mailpoet_token'); } - function setToken() { + function setTokenAndAPIVersion() { $global = ''; - echo $global; + echo sprintf( + $global, + Security::generateToken(), + self::CURRENT_VERSION + ); } function addEndpointNamespace($namespace) { @@ -180,4 +193,12 @@ class API { function getEndpointNamespaces() { return $this->_endpoint_namespaces; } -} + + function getRequestedEndpointClass() { + return $this->_endpoint_class; + } + + function getRequestedAPIVersion() { + return $this->_api_version; + } +} \ No newline at end of file diff --git a/lib/API/Endpoints/AutomatedLatestContent.php b/lib/API/Endpoints/v1/AutomatedLatestContent.php similarity index 98% rename from lib/API/Endpoints/AutomatedLatestContent.php rename to lib/API/Endpoints/v1/AutomatedLatestContent.php index f45a59b90f..510e4c2c04 100644 --- a/lib/API/Endpoints/AutomatedLatestContent.php +++ b/lib/API/Endpoints/v1/AutomatedLatestContent.php @@ -1,5 +1,5 @@ equals($namespace); } - function testItCanCallAddedEndpoints() { + function testItDefaultsToCurrentAPIVersionWhenNoVersionIsSpecified() { + $namespace = "MailPoet\\Some\\Name\\Space\\Endpoints"; + $this->api->addEndpointNamespace($namespace); + + $data = array( + 'endpoint' => 'namespaced_endpoint_stub', + 'method' => 'test' + ); + $this->api->getRequestData($data); + expect($this->api->getRequestedEndpointClass())->equals( + sprintf( + 'MailPoet\API\Endpoints\v%d\NamespacedEndpointStub', + API::CURRENT_VERSION + ) + ); + } + + function testItAcceptsAndProcessesAPIVersion() { + $namespace = "MailPoet\\Some\\Name\\Space\\Endpoints"; + $this->api->addEndpointNamespace($namespace); + + $data = array( + 'endpoint' => 'namespaced_endpoint_stub', + 'api_version' => 2, + 'method' => 'test' + ); + $this->api->getRequestData($data); + + expect($this->api->getRequestedAPIVersion())->equals('v2'); + expect($this->api->getRequestedEndpointClass())->equals( + 'MailPoet\API\Endpoints\v2\NamespacedEndpointStub' + ); + } + + function testItCallsAddedEndpoints() { $namespace = "MailPoet\\Some\\Name\\Space\\Endpoints"; $this->api->addEndpointNamespace($namespace); @@ -81,6 +116,21 @@ class APITest extends MailPoetTest { expect($response->getData()['data'])->equals($data['data']); } + function testItCallsAddedEndpointsForSpecificAPIVersion() { + $namespace = "MailPoet\\Some\\Name\\Space\\Endpoints"; + $this->api->addEndpointNamespace($namespace); + + $data = array( + 'endpoint' => 'namespaced_endpoint_stub', + 'api_version' => 2, + 'method' => 'testVersion' + ); + $this->api->getRequestData($data); + $response = $this->api->processRoute(); + + expect($response->getData()['data'])->equals('version_test_succeeded'); + } + function _after() { wp_delete_user($this->wp_user_id); } diff --git a/tests/unit/API/APITestNamespacedEndpointStub.php b/tests/unit/API/APITestNamespacedEndpointStubV1.php similarity index 87% rename from tests/unit/API/APITestNamespacedEndpointStub.php rename to tests/unit/API/APITestNamespacedEndpointStubV1.php index 02b196f451..724922755e 100644 --- a/tests/unit/API/APITestNamespacedEndpointStub.php +++ b/tests/unit/API/APITestNamespacedEndpointStubV1.php @@ -1,6 +1,6 @@ APIAccess::ALL + ); + + function testVersion() { + return $this->successResponse('version_test_succeeded'); + } +} diff --git a/tests/unit/API/Endpoints/CustomFieldsTest.php b/tests/unit/API/Endpoints/v1/CustomFieldsTest.php similarity index 98% rename from tests/unit/API/Endpoints/CustomFieldsTest.php rename to tests/unit/API/Endpoints/v1/CustomFieldsTest.php index f1bba2aef0..a5a07298af 100644 --- a/tests/unit/API/Endpoints/CustomFieldsTest.php +++ b/tests/unit/API/Endpoints/v1/CustomFieldsTest.php @@ -1,6 +1,6 @@