Adds version support to public API

This commit is contained in:
Vlad
2017-04-09 21:38:10 -04:00
parent 6566622167
commit a9c80c031f
28 changed files with 131 additions and 35 deletions

View File

@ -5,6 +5,7 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function(MailPoet, jQuery,
options: {}, options: {},
defaults: { defaults: {
url: null, url: null,
api_version: null,
endpoint: null, endpoint: null,
action: null, action: null,
token: null, token: null,
@ -26,10 +27,16 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function(MailPoet, jQuery,
if(this.options.token === null) { if(this.options.token === null) {
this.options.token = window.mailpoet_token; 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() { getParams: function() {
return { return {
action: 'mailpoet', action: 'mailpoet',
api_version: this.options.api_version,
token: this.options.token, token: this.options.token,
endpoint: this.options.endpoint, endpoint: this.options.endpoint,
method: this.options.action, method: this.options.action,

View File

@ -8,6 +8,7 @@ use MailPoet\WP\Hooks;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class API { class API {
private $_api_version;
private $_endpoint; private $_endpoint;
private $_method; private $_method;
private $_token; private $_token;
@ -16,15 +17,17 @@ class API {
private $_endpoint_class; private $_endpoint_class;
private $_data = array(); private $_data = array();
const CURRENT_VERSION = 1;
function __construct() { function __construct() {
$this->addEndpointNamespace(__NAMESPACE__ . "\\Endpoints"); $this->addEndpointNamespace(__NAMESPACE__ . "\\Endpoints");
} }
function init() { function init() {
// Admin Security token // admin security token and API version
add_action( add_action(
'admin_head', 'admin_head',
array($this, 'setToken') array($this, 'setTokenAndAPIVersion')
); );
// ajax (logged in users) // ajax (logged in users)
@ -61,6 +64,13 @@ class API {
} }
function getRequestData($data) { function getRequestData($data) {
$this->_api_version = sprintf(
'v%s',
isset($data['api_version'])
? $data['api_version']
: self::CURRENT_VERSION
);
$this->_endpoint = isset($data['endpoint']) $this->_endpoint = isset($data['endpoint'])
? Helpers::underscoreToCamelCase(trim($data['endpoint'])) ? Helpers::underscoreToCamelCase(trim($data['endpoint']))
: null; : null;
@ -87,7 +97,7 @@ class API {
$error_response->send(); $error_response->send();
} else { } else {
foreach($this->_endpoint_namespaces as $namespace) { 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)) { if(class_exists($class_name)) {
$this->_endpoint_class = $class_name; $this->_endpoint_class = $class_name;
} }
@ -164,13 +174,16 @@ class API {
return wp_verify_nonce($this->_token, 'mailpoet_token'); return wp_verify_nonce($this->_token, 'mailpoet_token');
} }
function setToken() { function setTokenAndAPIVersion() {
$global = '<script type="text/javascript">'; $global = '<script type="text/javascript">';
$global .= 'var mailpoet_token = "'; $global .= 'var mailpoet_token = "%s";';
$global .= Security::generateToken(); $global .= 'var mailpoet_api_version = %s;';
$global .= '";';
$global .= '</script>'; $global .= '</script>';
echo $global; echo sprintf(
$global,
Security::generateToken(),
self::CURRENT_VERSION
);
} }
function addEndpointNamespace($namespace) { function addEndpointNamespace($namespace) {
@ -180,4 +193,12 @@ class API {
function getEndpointNamespaces() { function getEndpointNamespaces() {
return $this->_endpoint_namespaces; return $this->_endpoint_namespaces;
} }
}
function getRequestedEndpointClass() {
return $this->_endpoint_class;
}
function getRequestedAPIVersion() {
return $this->_api_version;
}
}

View File

@ -1,5 +1,5 @@
<?php <?php
namespace MailPoet\API\Endpoints; namespace MailPoet\API\Endpoints\v1;
use MailPoet\API\Endpoint as APIEndpoint; use MailPoet\API\Endpoint as APIEndpoint;
use MailPoet\WP\Posts as WPPosts; use MailPoet\WP\Posts as WPPosts;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace MailPoet\API\Endpoints; namespace MailPoet\API\Endpoints\v1;
use MailPoet\API\Endpoint as APIEndpoint; use MailPoet\API\Endpoint as APIEndpoint;
use MailPoet\API\Error as APIError; use MailPoet\API\Error as APIError;
use MailPoet\Models\CustomField; use MailPoet\Models\CustomField;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace MailPoet\API\Endpoints; namespace MailPoet\API\Endpoints\v1;
use MailPoet\API\Endpoint as APIEndpoint; use MailPoet\API\Endpoint as APIEndpoint;
use MailPoet\API\Error as APIError; use MailPoet\API\Error as APIError;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace MailPoet\API\Endpoints; namespace MailPoet\API\Endpoints\v1;
use MailPoet\API\Endpoint as APIEndpoint; use MailPoet\API\Endpoint as APIEndpoint;
use MailPoet\Subscribers\ImportExport\Import\MailChimp; use MailPoet\Subscribers\ImportExport\Import\MailChimp;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace MailPoet\API\Endpoints; namespace MailPoet\API\Endpoints\v1;
use MailPoet\API\Endpoint as APIEndpoint; use MailPoet\API\Endpoint as APIEndpoint;
use MailPoet\API\Error as APIError; use MailPoet\API\Error as APIError;
use MailPoet\Mailer\MailerLog; use MailPoet\Mailer\MailerLog;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace MailPoet\API\Endpoints; namespace MailPoet\API\Endpoints\v1;
use MailPoet\API\Endpoint as APIEndpoint; use MailPoet\API\Endpoint as APIEndpoint;
use MailPoet\API\Error as APIError; use MailPoet\API\Error as APIError;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace MailPoet\API\Endpoints; namespace MailPoet\API\Endpoints\v1;
use MailPoet\API\Endpoint as APIEndpoint; use MailPoet\API\Endpoint as APIEndpoint;
use MailPoet\API\Error as APIError; use MailPoet\API\Error as APIError;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace MailPoet\API\Endpoints; namespace MailPoet\API\Endpoints\v1;
use MailPoet\API\Endpoint as APIEndpoint; use MailPoet\API\Endpoint as APIEndpoint;
use MailPoet\API\Error as APIError; use MailPoet\API\Error as APIError;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace MailPoet\API\Endpoints; namespace MailPoet\API\Endpoints\v1;
use MailPoet\API\Endpoint as APIEndpoint; use MailPoet\API\Endpoint as APIEndpoint;
use MailPoet\API\Error as APIError; use MailPoet\API\Error as APIError;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace MailPoet\API\Endpoints; namespace MailPoet\API\Endpoints\v1;
use Carbon\Carbon; use Carbon\Carbon;
use MailPoet\API\Endpoint as APIEndpoint; use MailPoet\API\Endpoint as APIEndpoint;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace MailPoet\API\Endpoints; namespace MailPoet\API\Endpoints\v1;
use MailPoet\API\Endpoint as APIEndpoint; use MailPoet\API\Endpoint as APIEndpoint;
use MailPoet\API\Error as APIError; use MailPoet\API\Error as APIError;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace MailPoet\API\Endpoints; namespace MailPoet\API\Endpoints\v1;
use MailPoet\API\Endpoint as APIEndpoint; use MailPoet\API\Endpoint as APIEndpoint;
use MailPoet\Config\Activator; use MailPoet\Config\Activator;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace MailPoet\API\Endpoints; namespace MailPoet\API\Endpoints\v1;
use MailPoet\API\Endpoint as APIEndpoint; use MailPoet\API\Endpoint as APIEndpoint;
use MailPoet\API\Error as APIError; use MailPoet\API\Error as APIError;
use MailPoet\API\Access as APIAccess; use MailPoet\API\Access as APIAccess;

View File

@ -5,7 +5,8 @@ use MailPoet\API\SuccessResponse;
// required to be able to use wp_delete_user() // required to be able to use wp_delete_user()
require_once(ABSPATH.'wp-admin/includes/user.php'); require_once(ABSPATH.'wp-admin/includes/user.php');
require_once('APITestNamespacedEndpointStub.php'); require_once('APITestNamespacedEndpointStubV1.php');
require_once('APITestNamespacedEndpointStubV2.php');
class APITest extends MailPoetTest { class APITest extends MailPoetTest {
function _before() { function _before() {
@ -66,7 +67,41 @@ class APITest extends MailPoetTest {
expect($namespaces[1])->equals($namespace); expect($namespaces[1])->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"; $namespace = "MailPoet\\Some\\Name\\Space\\Endpoints";
$this->api->addEndpointNamespace($namespace); $this->api->addEndpointNamespace($namespace);
@ -81,6 +116,21 @@ class APITest extends MailPoetTest {
expect($response->getData()['data'])->equals($data['data']); 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() { function _after() {
wp_delete_user($this->wp_user_id); wp_delete_user($this->wp_user_id);
} }

View File

@ -1,6 +1,6 @@
<?php <?php
namespace MailPoet\Some\Name\Space\Endpoints; namespace MailPoet\API\Endpoints\v1;
use MailPoet\API\Endpoint as APIEndpoint; use MailPoet\API\Endpoint as APIEndpoint;
use MailPoet\API\Access as APIAccess; use MailPoet\API\Access as APIAccess;

View File

@ -0,0 +1,18 @@
<?php
namespace MailPoet\API\Endpoints\v2;
use MailPoet\API\Access as APIAccess;
use MailPoet\API\Endpoint as APIEndpoint;
if(!defined('ABSPATH')) exit;
class NamespacedEndpointStub extends APIEndpoint {
public $permissions = array(
'testVersion' => APIAccess::ALL
);
function testVersion() {
return $this->successResponse('version_test_succeeded');
}
}

View File

@ -1,6 +1,6 @@
<?php <?php
use MailPoet\API\Endpoints\CustomFields; use MailPoet\API\Endpoints\v1\CustomFields;
use MailPoet\API\Response as APIResponse; use MailPoet\API\Response as APIResponse;
use MailPoet\Models\CustomField; use MailPoet\Models\CustomField;

View File

@ -1,5 +1,5 @@
<?php <?php
use MailPoet\API\Endpoints\Forms; use MailPoet\API\Endpoints\v1\Forms;
use MailPoet\API\Response as APIResponse; use MailPoet\API\Response as APIResponse;
use MailPoet\Models\Form; use MailPoet\Models\Form;
use MailPoet\Models\Segment; use MailPoet\Models\Segment;

View File

@ -1,6 +1,6 @@
<?php <?php
use MailPoet\API\Endpoints\Mailer; use MailPoet\API\Endpoints\v1\Mailer;
use MailPoet\API\Response as APIResponse; use MailPoet\API\Response as APIResponse;
use MailPoet\Mailer\MailerLog; use MailPoet\Mailer\MailerLog;

View File

@ -1,6 +1,6 @@
<?php <?php
use MailPoet\API\Response as APIResponse; use MailPoet\API\Response as APIResponse;
use MailPoet\API\Endpoints\NewsletterTemplates; use MailPoet\API\Endpoints\v1\NewsletterTemplates;
use MailPoet\Models\NewsletterTemplate; use MailPoet\Models\NewsletterTemplate;
class NewsletterTemplatesTest extends MailPoetTest { class NewsletterTemplatesTest extends MailPoetTest {

View File

@ -3,7 +3,7 @@ use Carbon\Carbon;
use Codeception\Util\Fixtures; use Codeception\Util\Fixtures;
use Codeception\Util\Stub; use Codeception\Util\Stub;
use Helper\WordPressHooks as WPHooksHelper; use Helper\WordPressHooks as WPHooksHelper;
use MailPoet\API\Endpoints\Newsletters; use MailPoet\API\Endpoints\v1\Newsletters;
use MailPoet\API\Response as APIResponse; use MailPoet\API\Response as APIResponse;
use MailPoet\Models\Newsletter; use MailPoet\Models\Newsletter;
use MailPoet\Models\NewsletterOptionField; use MailPoet\Models\NewsletterOptionField;

View File

@ -1,5 +1,5 @@
<?php <?php
use MailPoet\API\Endpoints\Segments; use MailPoet\API\Endpoints\v1\Segments;
use MailPoet\API\Response as APIResponse; use MailPoet\API\Response as APIResponse;
use MailPoet\Models\Segment; use MailPoet\Models\Segment;

View File

@ -1,7 +1,7 @@
<?php <?php
use Codeception\Util\Stub; use Codeception\Util\Stub;
use MailPoet\API\Endpoints\Services; use MailPoet\API\Endpoints\v1\Services;
use MailPoet\API\Response as APIResponse; use MailPoet\API\Response as APIResponse;
use MailPoet\Services\Bridge; use MailPoet\Services\Bridge;

View File

@ -1,7 +1,7 @@
<?php <?php
use MailPoet\API\Response as APIResponse; use MailPoet\API\Response as APIResponse;
use MailPoet\API\Error as APIError; use MailPoet\API\Error as APIError;
use MailPoet\API\Endpoints\Settings; use MailPoet\API\Endpoints\v1\Settings;
use MailPoet\Models\Setting; use MailPoet\Models\Setting;
class SettingsTest extends MailPoetTest { class SettingsTest extends MailPoetTest {

View File

@ -1,7 +1,7 @@
<?php <?php
use Helper\WordPressHooks as WPHooksHelper; use Helper\WordPressHooks as WPHooksHelper;
use MailPoet\API\Response as APIResponse; use MailPoet\API\Response as APIResponse;
use MailPoet\API\Endpoints\Setup; use MailPoet\API\Endpoints\v1\Setup;
use MailPoet\Models\Setting; use MailPoet\Models\Setting;
class SetupTest extends MailPoetTest { class SetupTest extends MailPoetTest {

View File

@ -1,7 +1,7 @@
<?php <?php
use Codeception\Util\Fixtures; use Codeception\Util\Fixtures;
use MailPoet\API\Endpoints\Subscribers; use MailPoet\API\Endpoints\v1\Subscribers;
use MailPoet\API\Response as APIResponse; use MailPoet\API\Response as APIResponse;
use MailPoet\Models\Form; use MailPoet\Models\Form;
use MailPoet\Models\Subscriber; use MailPoet\Models\Subscriber;