diff --git a/assets/js/src/queue.jsx b/assets/js/src/queue.jsx index 63d52af2ca..f083859a16 100644 --- a/assets/js/src/queue.jsx +++ b/assets/js/src/queue.jsx @@ -11,64 +11,89 @@ define( MailPoet, classNames ) { - var QueueDaemonControl = React.createClass({ + var QueueControl = React.createClass({ getInitialState: function () { - return (queueDaemon) ? { - status: queueDaemon.status, - timeSinceStart: queueDaemon.time_since_start, - timeSinceUpdate: queueDaemon.time_since_update, - counter: queueDaemon.counter - } : null; + return (queueDaemon) ? queueDaemon : null; }, getDaemonData: function () { MailPoet.Ajax.post({ endpoint: 'queue', - action: 'getQueueStatus' + action: 'getDaemonStatus' }).done(function (response) { - this.setState({ - status: response.status, - timeSinceStart: response.time_since_start, - timeSinceUpdate: response.time_since_update, - counter: response.counter, - }); + jQuery('.button-primary').removeClass('disabled'); + if (!response) { + this.replaceState(); + } else { + this.setState(response); + } }.bind(this)); }, - componentDidMount: function () { - this.getDaemonData; - setInterval(this.getDaemonData, 5000); + componentDidMount: function componentDidMount() { + if (this.isMounted()) { + this.getDaemonData; + setInterval(this.getDaemonData, 5000); + } + }, + controlDaemon: function (action) { + jQuery('.button-primary').addClass('disabled'); + MailPoet.Ajax.post({ + endpoint: 'queue', + action: 'controlDaemon', + data: {'action': action} + }).done(function (response) { + if (!response) { + this.replaceState(); + } else { + this.setState(response); + } + }.bind(this)); }, render: function () { if (!this.state) { - return ( -
- Woops, daemon is not running ;\ -
- ) + return +
+ Woops, daemon is not running ;\ +
+ } + switch (this.state.status) { + case 'started': + return ( +
+
+ Queue daemon is running. +
+
+ It was started + {this.state.timeSinceStart} and last executed + {this.state.timeSinceUpdate} for a total of + {this.state.counter} times (once every 30 seconds, unless it was interrupted and restarted). +
+
+ Stop   + Pause +
+
+ ); + break; + case 'paused': + case 'stopped': + return ( +
+ Daemon is {this.state.status} +
+
+ Start +
+ ) + break; } - return ( -
-
- Queue is currently {this.state.status}. -
-
- It was started - {this.state.timeSinceStart} and was last executed - {this.state.timeSinceUpdate} for a total of - {this.state.counter} times (once every 30 seconds, unless it was interrupted and restarted). -
-
-
- -
-
- ); } }); let container = document.getElementById('queue_container'); if (container) { ReactDOM.render( - , - container + , + document.getElementById('queue_status') ) } } diff --git a/lib/Queue/BootStrapMenu.php b/lib/Queue/BootStrapMenu.php index fede4d0c08..b8657adb4a 100644 --- a/lib/Queue/BootStrapMenu.php +++ b/lib/Queue/BootStrapMenu.php @@ -16,13 +16,13 @@ class BootStrapMenu { return ($this->daemon) ? array_merge( array( - 'time_since_start' => + 'timeSinceStart' => Carbon::createFromFormat( 'Y-m-d H:i:s', $this->daemon->created_at, 'UTC' )->diffForHumans(), - 'time_since_update' => + 'timeSinceUpdate' => Carbon::createFromFormat( 'Y-m-d H:i:s', $this->daemon->updated_at, diff --git a/lib/Queue/Daemon.php b/lib/Queue/Daemon.php index 1a56b33188..1012cf1f0a 100644 --- a/lib/Queue/Daemon.php +++ b/lib/Queue/Daemon.php @@ -28,7 +28,10 @@ class Daemon { if(!$daemon) { $daemon = Setting::create(); $daemon->name = 'daemon'; - $daemon->value = json_encode(array('status' => 'stopped')); + $daemon->value = json_encode( + array( + 'status' => 'stopped', + )); $daemon->save(); } if($daemonData['status'] !== 'started') { @@ -36,7 +39,7 @@ class Daemon { $daemonData = array( 'status' => 'started', 'token' => $this->refreshedToken, - 'counter' => ($daemonData['status'] === 'paused') ? + 'counter' => $daemonData['status'] === 'paused' ? $daemonData['counter'] : 0 ); @@ -67,7 +70,7 @@ class Daemon { $worker = new Worker(); $worker->process(); $elapsedTime = microtime(true) - $this->timer; - if ($elapsedTime < 30) { + if($elapsedTime < 30) { sleep(30 - $elapsedTime); } @@ -90,11 +93,11 @@ class Daemon { } function refreshToken() { - return Security::generateRandomString(5); + return Security::generateRandomString(); } function manageSession($action) { - switch ($action) { + switch($action) { case 'start': if(session_id()) { session_write_close(); diff --git a/lib/Queue/Supervisor.php b/lib/Queue/Supervisor.php index f0ab8e6f9d..cdd13cd1ab 100644 --- a/lib/Queue/Supervisor.php +++ b/lib/Queue/Supervisor.php @@ -17,11 +17,11 @@ class Supervisor { } function checkDaemon() { - if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH'])) return; if(!$this->daemon) { return $this->startDaemon(); } else { - if(!$this->forceStart && ($this->daemonData['status'] === 'paused' || + if(!$this->forceStart && ( + $this->daemonData['status'] === 'paused' || $this->daemonData['status'] === 'stopped' ) ) { @@ -33,8 +33,13 @@ class Supervisor { $this->daemon->updated_at, 'UTC' ); $timeSinceLastStart = $currentTime->diffInSeconds($lastUpdateTime); - if($timeSinceLastStart < 50) return; - $this->daemonData['status'] = 'paused'; + if(!$this->forceStart && $timeSinceLastStart < 50) return; + if( + ($this->forceStart && $this->daemonData['status'] === 'paused') || + !$this->forceStart + ) { + $this->daemonData['status'] = 'paused'; + } $this->daemon->value = json_encode($this->daemonData); $this->daemon->save(); return $this->startDaemon(); diff --git a/lib/Router/Queue.php b/lib/Router/Queue.php index f4d8bd004d..5f3bcc57e2 100644 --- a/lib/Router/Queue.php +++ b/lib/Router/Queue.php @@ -1,26 +1,24 @@ ($supervisor->checkDaemon($forceStart = true)) ? - true : - false - ) - ); - } - - function update($data) { - switch ($data['action']) { + function controlDaemon($data) { + switch($data['action']) { + case 'start': + $supervisor = new Supervisor($forceStart = true); + wp_send_json( + array( + 'result' => $supervisor->checkDaemon() ? + true : + false + ) + ); + break; case 'stop': $status = 'stopped'; break; @@ -43,9 +41,8 @@ class Queue { ); } - function getQueueStatus() { + function getDaemonStatus() { $daemon = new \MailPoet\Queue\BootStrapMenu(); wp_send_json($daemon->bootStrap()); - } } \ No newline at end of file diff --git a/lib/Util/Security.php b/lib/Util/Security.php index 34614456e0..72ea638fd7 100644 --- a/lib/Util/Security.php +++ b/lib/Util/Security.php @@ -8,7 +8,14 @@ class Security { return wp_create_nonce('mailpoet_token'); } - static function generateRandomString($length) { - return substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, $length); + static function generateRandomString($length = 5) { + // non-cryptographically strong random generator + return substr( + md5( + uniqid( + mt_rand(), true) + ), + 0, + (!is_int($length) || $length <= 5 || $length >= 32) ? 5 : $length); } } \ No newline at end of file diff --git a/views/queue.html b/views/queue.html index b039644703..3a837d77c1 100644 --- a/views/queue.html +++ b/views/queue.html @@ -1,7 +1,10 @@ <% extends 'layout.html' %> <% block content %> -
+
+
+
+