- Refactors API

- Updates existing classes to use the refactored API methods
This commit is contained in:
Vlad
2016-07-05 14:45:40 -04:00
parent 38199dc96f
commit cb2faec8b2
16 changed files with 195 additions and 117 deletions

71
lib/API/API.php Normal file
View File

@ -0,0 +1,71 @@
<?php
namespace MailPoet\API;
use MailPoet\Util\Helpers;
if(!defined('ABSPATH')) exit;
class API {
public $api_request;
public $endpoint;
public $action;
public $data;
const API_NAME = 'mailpoet_api';
const ENDPOINT_NAMESCAPE = '\MailPoet\API\Endpoints\\';
function __construct() {
$this->api_request = isset($_GET[self::API_NAME]) ? true : false;
$this->endpoint = isset($_GET['endpoint']) ?
Helpers::underscoreToCamelCase($_GET['endpoint']) :
false;
$this->endpoint = self::ENDPOINT_NAMESCAPE . ucfirst($this->endpoint);
$this->action = isset($_GET['action']) ?
Helpers::underscoreToCamelCase($_GET['action']) :
false;
$this->data = $this->validateRequestData();
}
function init() {
if(!$this->api_request) return;
if(!$this->endpoint) {
$this->terminateRequest(404, __('Invalid API endpoint.'));
}
$this->callEndpoint($this->endpoint, $this->action, $this->data);
}
function callEndpoint($endpoint, $action, $data) {
if(!method_exists($endpoint, $action)) {
$this->terminateRequest(404, __('Invalid API action.'));
}
call_user_func(
array(
$endpoint,
$action
),
$data
);
}
function validateRequestData() {
if(!isset($_GET['data'])) return false;
$data = base64_decode($_GET['data']);
return (is_serialized($data)) ?
unserialize($data) :
$this->terminateRequest(404, __('Invalid API data format.'));
}
static function buildRequest($endpoint, $action, $data) {
$params = array(
self::API_NAME => '',
'endpoint' => $endpoint,
'action' => $action,
'data' => $data
);
return add_query_arg($params, home_url());
}
function terminateRequest($code, $message) {
status_header($code, $message);
exit;
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace MailPoet\API\Endpoints;
use MailPoet\Cron\Daemon;
if(!defined('ABSPATH')) exit;
class Queue {
const ENDPOINT = 'queue';
const ACTION_RUN = 'run';
static function run($data) {
$queue = new Daemon($data);
$queue->run();
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace MailPoet\API\Endpoints;
use MailPoet\Subscription as UserSubscription;
if(!defined('ABSPATH')) exit;
class Subscription {
const ENDPOINT = 'subscription';
static function confirm($data) {
$subscription = new UserSubscription\Pages('confirm', $data);
}
static function manage($data) {
$subscription = new UserSubscription\Pages('manage', $data);
}
static function unsubscribe($data) {
$subscription = new UserSubscription\Pages('unsubscribe', $data);
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace MailPoet\API\Endpoints;
use MailPoet\Statistics\Track\Clicks;
use MailPoet\Statistics\Track\Opens;
if(!defined('ABSPATH')) exit;
class Track {
const ENDPOINT = 'track';
const ACTION_CLICK = 'click';
const ACTION_OPEN = 'open';
static function click($data) {
$clicks = new Clicks($data);
$clicks->track();
}
static function open($data) {
$opens = new Opens($data);
$opens->track();
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace MailPoet\API\Endpoints;
use MailPoet\Newsletter\ViewInBrowser as NewsletterViewInBrowser;
if(!defined('ABSPATH')) exit;
class ViewInBrowser {
const ENDPOINT = 'view_in_browser';
const ACTION_VIEW = 'view';
static function view($data) {
$viewer = new NewsletterViewInBrowser($data);
$viewer->view();
}
}

View File

@ -49,7 +49,7 @@ class Initializer {
function onInit() { function onInit() {
$this->setupRouter(); $this->setupRouter();
$this->setupPublicAPI(); $this->setupAPI();
$this->setupPages(); $this->setupPages();
} }
@ -171,13 +171,9 @@ class Initializer {
$hooks->init(); $hooks->init();
} }
function setupPublicAPI() { function setupAPI() {
try { $API = new \MailPoet\API\API();
$publicAPI = new PublicAPI(); $API->init();
$publicAPI->init();
} catch(\Exception $e) {
// continue execution
}
} }
function runQueueSupervisor() { function runQueueSupervisor() {

View File

@ -1,84 +0,0 @@
<?php
namespace MailPoet\Config;
use MailPoet\Cron\Daemon;
use MailPoet\Newsletter\ViewInBrowser;
use MailPoet\Statistics\Track\Clicks;
use MailPoet\Statistics\Track\Opens;
use MailPoet\Subscription;
use MailPoet\Util\Helpers;
if(!defined('ABSPATH')) exit;
class PublicAPI {
public $api;
public $endpoint;
public $action;
public $data;
function __construct() {
# http://example.com/?mailpoet&endpoint=&action=&data=
$this->api = isset($_GET['mailpoet']) ? true : false;
$this->endpoint = isset($_GET['endpoint']) ?
Helpers::underscoreToCamelCase($_GET['endpoint']) :
false;
$this->action = isset($_GET['action']) ?
Helpers::underscoreToCamelCase($_GET['action']) :
false;
$this->data = $this->getAndValidateData();
}
function init() {
if(!$this->api || !$this->endpoint) return;
$this->_checkAndCallMethod($this, $this->endpoint, $terminate_request = true);
}
function queue() {
$queue = new Daemon($this->data);
$this->_checkAndCallMethod($queue, $this->action);
}
function subscription() {
$subscription = new Subscription\Pages($this->action, $this->data);
$this->_checkAndCallMethod($subscription, $this->action);
}
function track() {
if($this->action === 'click') {
$track_class = new Clicks($this->data);
}
if($this->action === 'open') {
$track_class = new Opens($this->data);
}
if(!isset($track_class)) return;
$track_class->track();
}
function viewInBrowser() {
$viewer = new ViewInBrowser($this->data);
$viewer->view();
}
private function _checkAndCallMethod($class, $method, $terminate_request = false) {
if(!method_exists($class, $method)) {
if(!$terminate_request) return;
header('HTTP/1.0 404 Not Found');
exit;
}
call_user_func(
array(
$class,
$method
)
);
}
function getAndValidateData() {
if (!isset($_GET['data'])) return false;
$data = base64_decode($_GET['data']);
if (!is_serialized($data)) {
throw new \Exception(__('Invalid data format.'));
}
return unserialize($data);
}
}

View File

@ -1,6 +1,8 @@
<?php <?php
namespace MailPoet\Cron; namespace MailPoet\Cron;
use MailPoet\API\API;
use MailPoet\API\Endpoints\Queue as QueueAPI;
use MailPoet\Models\Setting; use MailPoet\Models\Setting;
use MailPoet\Util\Security; use MailPoet\Util\Security;
@ -39,8 +41,11 @@ class CronHelper {
static function accessDaemon($token, $timeout = self::DAEMON_REQUEST_TIMEOUT) { static function accessDaemon($token, $timeout = self::DAEMON_REQUEST_TIMEOUT) {
$data = serialize(array('token' => $token)); $data = serialize(array('token' => $token));
$url = '/?mailpoet&endpoint=queue&action=run&data=' . $url = API::buildRequest(
base64_encode($data); QueueAPI::ENDPOINT,
QueueAPI::ACTION_RUN,
base64_encode($data)
);
$args = array( $args = array(
'timeout' => $timeout, 'timeout' => $timeout,
'user-agent' => 'MailPoet (www.mailpoet.com) Cron' 'user-agent' => 'MailPoet (www.mailpoet.com) Cron'

View File

@ -56,7 +56,7 @@ class Daemon {
// its status has changed // its status has changed
$daemon = CronHelper::getDaemon(); $daemon = CronHelper::getDaemon();
if(!$daemon || $daemon['token'] !== $this->data['token']) { if(!$daemon || $daemon['token'] !== $this->data['token']) {
self::terminate(); $this->terminateRequest();
} }
$daemon['counter']++; $daemon['counter']++;
$this->abortIfStopped($daemon); $this->abortIfStopped($daemon);
@ -70,12 +70,12 @@ class Daemon {
function abortIfStopped($daemon) { function abortIfStopped($daemon) {
if($daemon['status'] === self::STATUS_STOPPED) { if($daemon['status'] === self::STATUS_STOPPED) {
self::terminate(); $this->terminateRequest();
} }
if($daemon['status'] === self::STATUS_STOPPING) { if($daemon['status'] === self::STATUS_STOPPING) {
$daemon['status'] = self::STATUS_STOPPED; $daemon['status'] = self::STATUS_STOPPED;
CronHelper::saveDaemon($daemon); CronHelper::saveDaemon($daemon);
self::terminate(); $this->terminateRequest();
} }
} }
@ -85,10 +85,10 @@ class Daemon {
function callSelf() { function callSelf() {
CronHelper::accessDaemon($this->token, self::REQUEST_TIMEOUT); CronHelper::accessDaemon($this->token, self::REQUEST_TIMEOUT);
self::terminate(); $this->terminateRequest();
} }
function terminate() { function terminateRequest() {
exit; exit;
} }
} }

View File

@ -1,9 +1,10 @@
<?php <?php
namespace MailPoet\Newsletter\Links; namespace MailPoet\Newsletter\Links;
use MailPoet\API\API;
use MailPoet\API\Endpoints\Track as TrackAPI;
use MailPoet\Models\NewsletterLink; use MailPoet\Models\NewsletterLink;
use MailPoet\Newsletter\Shortcodes\Shortcodes; use MailPoet\Newsletter\Shortcodes\Shortcodes;
use MailPoet\Util\Helpers;
use MailPoet\Util\Security; use MailPoet\Util\Security;
class Links { class Links {
@ -61,13 +62,11 @@ class Links {
'hash' => $hash, 'hash' => $hash,
'url' => $extracted_link['link'] 'url' => $extracted_link['link']
); );
$params = array( $tracked_link = API::buildRequest(
'mailpoet' => '', TrackAPI::ENDPOINT,
'endpoint' => 'track', TrackAPI::ACTION_CLICK,
'action' => 'click', self::DATA_TAG . '-' . $hash
'data' => self::DATA_TAG . '-' . $hash
); );
$tracked_link = add_query_arg($params, home_url());
// first, replace URL in the extracted HTML source with encoded link // first, replace URL in the extracted HTML source with encoded link
$tracked_link_html_source = str_replace( $tracked_link_html_source = str_replace(
$extracted_link['link'], $tracked_link, $extracted_link['link'], $tracked_link,

View File

@ -1,6 +1,8 @@
<?php <?php
namespace MailPoet\Newsletter\Renderer\PostProcess; namespace MailPoet\Newsletter\Renderer\PostProcess;
use MailPoet\API\API;
use MailPoet\API\Endpoints\Track as TrackAPI;
use MailPoet\Newsletter\Links\Links; use MailPoet\Newsletter\Links\Links;
use MailPoet\Newsletter\Renderer\Renderer; use MailPoet\Newsletter\Renderer\Renderer;
@ -9,10 +11,14 @@ class OpenTracking {
$DOM = new \pQuery(); $DOM = new \pQuery();
$DOM = $DOM->parseStr($template); $DOM = $DOM->parseStr($template);
$template = $DOM->query('body'); $template = $DOM->query('body');
$url = API::buildRequest(
TrackAPI::ENDPOINT,
TrackAPI::ACTION_OPEN,
Links::DATA_TAG
);
$open_tracking_image = sprintf( $open_tracking_image = sprintf(
'<img alt="" class="" src="%s/%s"/>', '<img alt="" class="" src="%s"/>',
home_url(), $url
esc_attr('?mailpoet&endpoint=track&action=open&data=' . Links::DATA_TAG)
); );
$template->html($template->html() . $open_tracking_image); $template->html($template->html() . $open_tracking_image);
return $DOM->__toString(); return $DOM->__toString();

View File

@ -1,6 +1,8 @@
<?php <?php
namespace MailPoet\Newsletter; namespace MailPoet\Newsletter;
use MailPoet\API\API;
use MailPoet\API\Endpoints\ViewInBrowser;
use MailPoet\Models\Subscriber; use MailPoet\Models\Subscriber;
class Url { class Url {
@ -33,8 +35,9 @@ class Url {
$queue $queue
); );
$params = array( $params = array(
'mailpoet' => '', API::API_NAME,
'endpoint' => 'view_in_browser', 'endpoint' => ViewInBrowser::ENDPOINT,
'action' => ViewInBrowser::ACTION_VIEW,
'data' => base64_encode(serialize($data)) 'data' => base64_encode(serialize($data))
); );
return add_query_arg($params, home_url()); return add_query_arg($params, home_url());

View File

@ -70,7 +70,7 @@ class ViewInBrowser {
} }
private function abort() { private function abort() {
header('HTTP/1.0 404 Not Found'); status_header(404);
exit; exit;
} }
} }

View File

@ -89,7 +89,7 @@ class Clicks {
} }
function abort() { function abort() {
header('HTTP/1.0 404 Not Found'); status_header(404);
exit; exit;
} }

View File

@ -14,6 +14,7 @@ use \MailPoet\Form\Renderer as FormRenderer;
use \MailPoet\Form\Block\Date as FormBlockDate; use \MailPoet\Form\Block\Date as FormBlockDate;
class Pages { class Pages {
// TODO: possible refactor
const DEMO_EMAIL = 'demo@mailpoet.com'; const DEMO_EMAIL = 'demo@mailpoet.com';
private $action; private $action;

View File

@ -1,10 +1,13 @@
<?php <?php
namespace MailPoet\Subscription; namespace MailPoet\Subscription;
use \MailPoet\Models\Subscriber; use MailPoet\API\API;
use \MailPoet\Models\Setting; use MailPoet\API\Endpoints\Subscription;
use MailPoet\Models\Subscriber;
use MailPoet\Models\Setting;
class Url { class Url {
// TODO: possible refactor
static function getConfirmationUrl($subscriber = false) { static function getConfirmationUrl($subscriber = false) {
$post = get_post(Setting::getValue('subscription.pages.confirmation')); $post = get_post(Setting::getValue('subscription.pages.confirmation'));
return self::getSubscriptionUrl($post, 'confirm', $subscriber); return self::getSubscriptionUrl($post, 'confirm', $subscriber);
@ -43,7 +46,8 @@ class Url {
} }
$params = array( $params = array(
'endpoint=subscription', API::API_NAME,
'endpoint='.Subscription::ENDPOINT,
'action='.$action, 'action='.$action,
'data='.rtrim(base64_encode(serialize($data)), '=') 'data='.rtrim(base64_encode(serialize($data)), '=')
); );