- Adds Queue router

- Updates logic for Queue and Supervisor
- #227
This commit is contained in:
MrCasual
2015-11-22 23:07:30 -05:00
parent d46c9d5412
commit fa96c4697d
5 changed files with 256 additions and 10 deletions

45
lib/Config/PublicAPI.php Normal file
View File

@@ -0,0 +1,45 @@
<?php
namespace MailPoet\Config;
use MailPoet\Queue\Queue;
if(!defined('ABSPATH')) exit;
class PublicAPI {
function __construct() {
# http://example.com/?mailpoet-api&section=&action=&payload=
$this->api = isset($_GET['mailpoet-api']) ? true : false;
$this->section = isset($_GET['section']) ? $_GET['section'] : false;
$this->action = isset($_GET['action']) ?
str_replace('_', '', lcfirst(ucwords($_GET['action'], '_'))) :
false;
$this->payload = isset($_GET['payload']) ?
json_decode(urldecode($_GET['payload']), true) :
false;
}
function init() {
if(!$this->api && !$this->section) return;
if(method_exists($this, $this->section)) {
call_user_func(
array(
$this,
$this->section
));
} else {
header('HTTP/1.0 404 Not Found');
}
exit;
}
function queue() {
$queue = new Queue($this->payload);
if(method_exists($queue, $this->action)) {
call_user_func(
array(
$queue,
$this->action
));
}
}
}

125
lib/Queue/Queue.php Normal file
View File

@@ -0,0 +1,125 @@
<?php
namespace MailPoet\Queue;
use MailPoet\Models\Setting;
use MailPoet\Util\Security;
require_once(ABSPATH . 'wp-includes/pluggable.php');
if(!defined('ABSPATH')) exit;
class Queue {
function __construct($payload = array()) {
set_time_limit(0);
ignore_user_abort();
list ($this->queue, $this->queueData) = $this->getQueue();
$this->refreshedToken = $this->refreshToken();
$this->payload = $payload;
}
function start() {
if(!isset($this->payload['token'])) {
$this->abortWithError('missing token');
}
$queue = $this->queue;
$queueData = $this->queueData;
if(!$queue) {
$queue = Setting::create();
$queue->name = 'queue';
$queue->value = serialize(array('status' => 'stopped'));
$queue->save();
}
if(!preg_match('!stopped|paused!', $queueData['status'])
) {
$queueData = array(
'status' => 'started',
'token' => $this->refreshedToken,
'executionCounter' => ($queueData['status'] === 'paused') ?
$queueData['executionCounter']
: 0,
'log' => array(
'token' => $this->payload['token'],
'message' => 'started'
)
);
$queue->value = serialize($queueData);
$queue->save();
$this->callSelf();
} else {
$queueData['log'] = array(
'token' => $this->payload['token'],
'status' => 'already started'
);
$queue->value = serialize($queueData);
$queue->save();
}
}
function process() {
if(!$this->queue || $this->queueData['status'] !== 'started') {
$this->abortWithError('not running');
}
if(!isset($this->payload['token']) ||
$this->payload['token'] !== $this->queueData['token']
) {
$this->abortWithError('invalid token');
}
/*
* LOGIC WILL HAPPEN HERE
*
*/
sleep(30);
// after each execution, read queue in case its status was modified
list($queue, $queueData) = $this->getQueue();
$queueData['executionCounter']++;
$queueData['token'] = $this->refreshedToken;
$queue->value = serialize($queueData);
$queue->save();
$this->callSelf();
}
function callSelf() {
$payload = json_encode(array('token' => $this->refreshedToken));
$args = array(
'timeout' => 1,
'user-agent' => 'MailPoet (www.mailpoet.com)'
);
wp_remote_get(
site_url() .
'/?mailpoet-api&section=queue&action=process&payload=' . urlencode($payload),
$args
);
exit;
}
function abortWithError($error) {
wp_send_json(
array(
'result' => false,
'error' => $error
));
exit;
}
function getQueue() {
$queue = Setting::where('name', 'queue')
->findOne();
return array(
($queue) ? $queue : null,
($queue) ? unserialize($queue->value) : null
);
}
function checkAuthorization() {
if(!current_user_can('manage_options')) {
header('HTTP/1.0 401 Not Authorized');
exit;
}
}
function refreshToken() {
return Security::generateRandomString(5);
}
}

View File

@@ -4,22 +4,24 @@ namespace MailPoet\Queue;
use Carbon\Carbon; use Carbon\Carbon;
use MailPoet\Config\Env; use MailPoet\Config\Env;
use MailPoet\Models\Setting; use MailPoet\Models\Setting;
use MailPoet\Util\Security;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class Supervisor { class Supervisor {
function __construct() { function __construct($forceStart = false) {
$this->forceStart = $forceStart;
$this->checkDBReadiness(); $this->checkDBReadiness();
list ($this->queue, $this->queueData) = $this->getQueue(); list ($this->queue, $this->queueData) = $this->getQueue();
} }
function checkQueue() { function checkQueue() {
if(!$this->queue) { if(!$this->queue) {
$this->startQueue(); return $this->startQueue();
} else { } else {
if($this->queueData['status'] === 'paused' && if(!$this->forceStart && ($this->queueData['status'] === 'paused' ||
$this->queueData['status'] === 'stopped' $this->queueData['status'] === 'stopped'
) { )) {
return; return;
} }
$currentTime = Carbon::now('UTC'); $currentTime = Carbon::now('UTC');
@@ -32,13 +34,29 @@ class Supervisor {
$this->queueData['status'] = 'paused'; $this->queueData['status'] = 'paused';
$this->queue->value = serialize($this->queueData); $this->queue->value = serialize($this->queueData);
$this->queue->save(); $this->queue->save();
$this->startQueue(); return $this->startQueue();
} }
} }
function startQueue() { function startQueue() {
stream_context_set_default(array('http' => array('method' => 'HEAD'))); $args = array(
get_headers(home_url() . '/?mailpoet-api&section=queue&action=start', 1); 'timeout' => 1,
'user-agent' => 'MailPoet (www.mailpoet.com)'
);
$token = Security::generateRandomString(5);
$payload = json_encode(
array(
'token' => $token
)
);
wp_remote_get(
site_url() .
'/?mailpoet-api&section=queue&action=start&payload=' .
urlencode($payload),
$args
);
list ($queue, $queueData) = $this->getQueue();
return ($queueData && $queueData['token'] === $token) ? true : false;
} }
function getQueue() { function getQueue() {
@@ -53,9 +71,10 @@ class Supervisor {
function checkDBReadiness() { function checkDBReadiness() {
$db = \ORM::forTable('') $db = \ORM::forTable('')
->rawQuery('SELECT COUNT(*) as settings FROM information_schema.tables ' . ->rawQuery(
'WHERE table_schema = "' . Env::$db_name . '" ' . 'SELECT COUNT(*) as settings FROM information_schema.tables ' .
'AND table_name = "' . MP_SETTINGS_TABLE . '";' 'WHERE table_schema = "' . Env::$db_name . '" ' .
'AND table_name = "' . MP_SETTINGS_TABLE . '";'
) )
->findOne() ->findOne()
->asArray(); ->asArray();

51
lib/Router/Queue.php Normal file
View File

@@ -0,0 +1,51 @@
<?php
namespace MailPoet\Router;
use MailPoet\Queue\Supervisor;
if(!defined('ABSPATH')) exit;
class Queue {
function start() {
$supervisor = new Supervisor();
wp_send_json(
array(
'result' => ($supervisor->checkQueue($forceStart = true)) ?
true :
false
)
);
}
function pause() {
wp_send_json(
array(
'result' => ($this->updateQueueStatus('paused') ?
true :
false
)
)
);
}
function stop() {
wp_send_json(
array(
'result' => ($this->updateQueueStatus('stopped') ?
true :
false
)
)
);
}
private function updateQueueStatus($status) {
$queue = new \MailPoet\Queue\Queue();
if(!$queue->queue || $queue->queueData['status'] !== 'started') {
return false;
}
$queue->queueData['status'] = $status;
$queue->queue->value = serialize($queue->queueData);
return $queue->queue->save();
}
}

View File

@@ -1,8 +1,14 @@
<?php <?php
namespace MailPoet\Util; namespace MailPoet\Util;
require_once(ABSPATH . 'wp-includes/pluggable.php');
class Security { class Security {
static function generateToken() { static function generateToken() {
return wp_create_nonce('mailpoet_token'); return wp_create_nonce('mailpoet_token');
} }
static function generateRandomString($length) {
return substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, $length);
}
} }