607 lines
17 KiB
PHP
607 lines
17 KiB
PHP
<?php
|
|
/**
|
|
* Since 2013 Ovidiu Cimpean.
|
|
*
|
|
* Ovidiu Cimpean - Newsletter Pro © All rights reserved.
|
|
*
|
|
* DISCLAIMER
|
|
*
|
|
* Do not edit, modify or copy this file.
|
|
* If you wish to customize it, contact us at addons4prestashop@gmail.com.
|
|
*
|
|
* @author Ovidiu Cimpean <addons4prestashop@gmail.com>
|
|
* @copyright Since 2013 Ovidiu Cimpean
|
|
* @license Do not edit, modify or copy this file
|
|
*
|
|
* @version Release: 4
|
|
*/
|
|
|
|
class NewsletterProSend extends ObjectModel
|
|
{
|
|
public $id_newsletter_pro_tpl_history;
|
|
|
|
public $template;
|
|
|
|
public $active;
|
|
|
|
public $state;
|
|
|
|
public $emails_count;
|
|
|
|
public $emails_success;
|
|
|
|
public $emails_error;
|
|
|
|
public $emails_completed;
|
|
|
|
public $error_msg;
|
|
|
|
public $date;
|
|
|
|
/**
|
|
* The states are available in javascript
|
|
* If there are changes at this states, is required to change also the javascript file view/js/send_manager.js.
|
|
*/
|
|
const STATE_DEFAULT = 0;
|
|
|
|
const STATE_PAUSE = 1;
|
|
|
|
const STATE_IN_PROGRESS = 2;
|
|
|
|
const STATE_DONE = 3;
|
|
|
|
/**
|
|
* Variables.
|
|
*/
|
|
public $progress_success = 0;
|
|
|
|
public $progress_errors = 0;
|
|
|
|
public static $definition = [
|
|
'table' => 'newsletter_pro_send',
|
|
'primary' => 'id_newsletter_pro_send',
|
|
'fields' => [
|
|
'id_newsletter_pro_tpl_history' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
|
'template' => ['type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true],
|
|
'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
|
'state' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
|
'emails_count' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
|
'emails_error' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
|
'emails_success' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
|
'emails_completed' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
|
'error_msg' => ['type' => self::TYPE_HTML, 'validate' => 'isString'],
|
|
'date' => ['type' => self::TYPE_DATE, 'validate' => 'isDateFormat'],
|
|
],
|
|
];
|
|
|
|
public function __construct($id = null)
|
|
{
|
|
parent::__construct($id);
|
|
}
|
|
|
|
public static function newInstance($id = null)
|
|
{
|
|
return new self($id);
|
|
}
|
|
|
|
public static function getActiveId()
|
|
{
|
|
return (int) Db::getInstance()->getValue('
|
|
SELECT `id_newsletter_pro_send`
|
|
FROM `'._DB_PREFIX_.'newsletter_pro_send`
|
|
WHERE `active` = 1
|
|
AND `id_newsletter_pro_send` = (
|
|
SELECT MAX(`id_newsletter_pro_send`)
|
|
FROM `'._DB_PREFIX_.'newsletter_pro_send`
|
|
)
|
|
');
|
|
}
|
|
|
|
public function updateProgress()
|
|
{
|
|
$result = Db::getInstance()->execute('
|
|
UPDATE `'._DB_PREFIX_.'newsletter_pro_send`
|
|
SET
|
|
`emails_success` = `emails_success` + '.(int) $this->progress_success.',
|
|
`emails_error` = `emails_error` + '.(int) $this->progress_errors.',
|
|
`emails_completed` = `emails_completed` + '.((int) $this->progress_success + (int) $this->progress_errors).'
|
|
WHERE `id_newsletter_pro_send` = '.(int) $this->id.'
|
|
');
|
|
|
|
$this->progress_success = 0;
|
|
$this->progress_errors = 0;
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function updateDefaults($ignore = [])
|
|
{
|
|
$fields = [
|
|
'id_newsletter_pro_tpl_history' => (int) $this->id_newsletter_pro_tpl_history,
|
|
'template' => pSQL($this->template),
|
|
'active' => (int) $this->active,
|
|
'state' => (int) $this->state,
|
|
'emails_count' => (int) $this->emails_count,
|
|
'date' => pSQL($this->date),
|
|
];
|
|
|
|
if (!empty($ignore)) {
|
|
foreach ($ignore as $key) {
|
|
if (isset($fields[$key])) {
|
|
unset($fields[$key]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $this->updateFields($fields);
|
|
}
|
|
|
|
public function updateAll($ignore = [])
|
|
{
|
|
return $this->updateProgress() && $this->updateDefaults($ignore);
|
|
}
|
|
|
|
public function progressSuccess()
|
|
{
|
|
++$this->progress_success;
|
|
}
|
|
|
|
public function progressErrors()
|
|
{
|
|
++$this->progress_errors;
|
|
}
|
|
|
|
public function statePause()
|
|
{
|
|
$this->state = self::STATE_PAUSE;
|
|
$this->active = 1;
|
|
|
|
return $this->updateFields([
|
|
'state' => $this->state,
|
|
'active' => $this->active,
|
|
]);
|
|
}
|
|
|
|
public function stateDone()
|
|
{
|
|
$this->state = self::STATE_DONE;
|
|
$this->active = 0;
|
|
|
|
return $this->updateFields([
|
|
'state' => $this->state,
|
|
'active' => $this->active,
|
|
]);
|
|
}
|
|
|
|
public function stateInProgress()
|
|
{
|
|
$this->state = self::STATE_IN_PROGRESS;
|
|
$this->active = 1;
|
|
|
|
return $this->updateFields([
|
|
'state' => $this->state,
|
|
'active' => $this->active,
|
|
]);
|
|
}
|
|
|
|
public function stateDefault()
|
|
{
|
|
$this->state = self::STATE_DEFAULT;
|
|
$this->active = 1;
|
|
|
|
return $this->updateFields([
|
|
'state' => $this->state,
|
|
'active' => $this->active,
|
|
]);
|
|
}
|
|
|
|
public function setState($state)
|
|
{
|
|
$this->state = $state;
|
|
|
|
return $this->updateFields([
|
|
'state' => $this->state,
|
|
]);
|
|
}
|
|
|
|
private function getStepsIdsCallback($row)
|
|
{
|
|
return !empty($row) ? $row['id_newsletter_pro_send_step'] : false;
|
|
}
|
|
|
|
public function getStepsIds($step_active = false, $limit = 0)
|
|
{
|
|
$results = Db::getInstance()->executeS('
|
|
SELECT `id_newsletter_pro_send_step`
|
|
FROM `'._DB_PREFIX_.'newsletter_pro_send_step`
|
|
WHERE `id_newsletter_pro_send` = '.(int) $this->id.'
|
|
'.($step_active ? ' AND `step_active` = 1' : '').'
|
|
ORDER BY `id_newsletter_pro_send_step`
|
|
'.($limit > 0 ? ' LIMIT '.(int) $limit : '').'
|
|
');
|
|
|
|
return array_map([$this, 'getStepsIdsCallback'], $results);
|
|
}
|
|
|
|
public function markNewsletterAsDone($time = 120)
|
|
{
|
|
$id = (int) Db::getInstance()->getValue('
|
|
SELECT `id_newsletter_pro_send`
|
|
FROM `'._DB_PREFIX_.'newsletter_pro_send_step`
|
|
WHERE `id_newsletter_pro_send` = '.(int) $this->id.'
|
|
AND id_newsletter_pro_send_step = (SELECT MAX(`id_newsletter_pro_send_step`)
|
|
FROM `'._DB_PREFIX_.'newsletter_pro_send_step`
|
|
WHERE `id_newsletter_pro_send` = '.(int) $this->id.')
|
|
AND DATE_ADD(`date_modified`, INTERVAL '.(int) $time.' SECOND) <= NOW()
|
|
');
|
|
|
|
if ((int) $id > 0) {
|
|
return (int) Db::getInstance()->update('newsletter_pro_send', [
|
|
'state' => NewsletterProSend::STATE_DONE,
|
|
'active' => 0,
|
|
], '`id_newsletter_pro_send` = '.(int) $id);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public function getCurrentStepId()
|
|
{
|
|
$id = (int) Db::getInstance()->getValue('
|
|
SELECT `id_newsletter_pro_send_step`
|
|
FROM `'._DB_PREFIX_.'newsletter_pro_send_step`
|
|
WHERE `id_newsletter_pro_send` = '.(int) $this->id.'
|
|
AND `step_active` = 1
|
|
ORDER BY `id_newsletter_pro_send_step`
|
|
');
|
|
|
|
return $id;
|
|
}
|
|
|
|
public function getStepsIdAndConnectionsId($step_active = false, $closed_connection = false, $limit = 0)
|
|
{
|
|
$results = Db::getInstance()->executeS('
|
|
SELECT
|
|
ss.`id_newsletter_pro_send_step`,
|
|
sc.`id_newsletter_pro_send_connection`,
|
|
sc.`state`
|
|
FROM `'._DB_PREFIX_.'newsletter_pro_send_step` ss
|
|
LEFT JOIN `'._DB_PREFIX_.'newsletter_pro_send_connection` sc
|
|
ON (
|
|
ss.`id_newsletter_pro_send_connection` = sc.`id_newsletter_pro_send_connection`
|
|
)
|
|
WHERE ss.`id_newsletter_pro_send` = '.(int) $this->id.'
|
|
'.($step_active ? ' AND ss.`step_active` = 1' : '').'
|
|
ORDER BY ss.`id_newsletter_pro_send_step`
|
|
');
|
|
|
|
$ids = [];
|
|
|
|
foreach ($results as $row) {
|
|
if ($closed_connection) {
|
|
if (NewsletterProSendConnection::STATE_CLOSE == (int) $row['state']) {
|
|
$ids[(int) $row['id_newsletter_pro_send_step']] = (int) $row['id_newsletter_pro_send_connection'];
|
|
}
|
|
} else {
|
|
$ids[(int) $row['id_newsletter_pro_send_step']] = (int) $row['id_newsletter_pro_send_connection'];
|
|
}
|
|
}
|
|
|
|
if ($limit > 0) {
|
|
$slice_ids = [];
|
|
foreach ($ids as $id_step => $id_connection) {
|
|
if (count($slice_ids) < $limit) {
|
|
$slice_ids[$id_step] = $id_connection;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $slice_ids;
|
|
}
|
|
|
|
return $ids;
|
|
}
|
|
|
|
public function getFirstFreeStepIdAndOpenConnection()
|
|
{
|
|
$result = Db::getInstance()->getRow('
|
|
SELECT ss.`id_newsletter_pro_send_step`,
|
|
sc.`id_newsletter_pro_send_connection`
|
|
FROM `'._DB_PREFIX_.'newsletter_pro_send_step` ss
|
|
INNER JOIN `'._DB_PREFIX_.'newsletter_pro_send_connection` sc
|
|
ON (
|
|
ss.`id_newsletter_pro_send_connection` = sc.`id_newsletter_pro_send_connection`
|
|
AND sc.`state` = 0
|
|
)
|
|
WHERE ss.`id_newsletter_pro_send` = '.(int) $this->id.'
|
|
AND ss.`step_active` = 1
|
|
AND sc.`script_uid` IS NULL
|
|
ORDER BY ss.`id_newsletter_pro_send_step`
|
|
');
|
|
|
|
if (empty($result)) {
|
|
return 0;
|
|
}
|
|
|
|
Db::getInstance()->execute('
|
|
UPDATE `'._DB_PREFIX_.'newsletter_pro_send_connection`
|
|
SET `state` = 1, `script_uid` = "'.pSQL(NewsletterProSendConnection::getScriptUid()).'"
|
|
WHERE id_newsletter_pro_send_connection = '.(int) $result['id_newsletter_pro_send_connection'].'
|
|
AND `state` = 0
|
|
AND `script_uid` IS NULL;
|
|
');
|
|
|
|
if (!Db::getInstance()->Affected_Rows()) {
|
|
return 0;
|
|
}
|
|
|
|
NewsletterProShutdown::register([$this, 'shutdownDbCloseConnection'], [(int) $result['id_newsletter_pro_send_connection']]);
|
|
|
|
return (int) $result['id_newsletter_pro_send_step'];
|
|
}
|
|
|
|
public function shutdownDbCloseConnection($id_connection)
|
|
{
|
|
Db::getInstance()->execute('
|
|
UPDATE `'._DB_PREFIX_.'newsletter_pro_send_connection`
|
|
SET `state` = 0, `script_uid` = NULL
|
|
WHERE id_newsletter_pro_send_connection = '.(int) $id_connection.'
|
|
AND `state` = 1
|
|
AND `script_uid` = "'.pSQL(NewsletterProSendConnection::getScriptUid()).'"
|
|
');
|
|
|
|
if (Db::getInstance()->Affected_Rows()) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public function getInfo()
|
|
{
|
|
return Db::getInstance()->getRow('
|
|
SELECT `active`, `state`
|
|
FROM `'._DB_PREFIX_.'newsletter_pro_send`
|
|
WHERE `id_newsletter_pro_send` = '.(int) $this->id.'
|
|
');
|
|
}
|
|
|
|
public function isActive()
|
|
{
|
|
$value = (int) Db::getInstance()->getValue('
|
|
SELECT `active`
|
|
FROM `'._DB_PREFIX_.'newsletter_pro_send`
|
|
WHERE `id_newsletter_pro_send` = '.(int) $this->id.'
|
|
');
|
|
|
|
$this->active = $value;
|
|
|
|
return $value;
|
|
}
|
|
|
|
public function getState()
|
|
{
|
|
$value = (int) Db::getInstance()->getValue('
|
|
SELECT `state`
|
|
FROM `'._DB_PREFIX_.'newsletter_pro_send`
|
|
WHERE `id_newsletter_pro_send` = '.(int) $this->id.'
|
|
');
|
|
|
|
$this->state = (int) $value;
|
|
|
|
return $this->state;
|
|
}
|
|
|
|
public function isPause($state = null)
|
|
{
|
|
$state = isset($state) ? $state : $this->getState();
|
|
|
|
return self::STATE_PAUSE == $state;
|
|
}
|
|
|
|
public function isDefault($state = null)
|
|
{
|
|
$state = isset($state) ? $state : $this->getState();
|
|
|
|
return self::STATE_DEFAULT == $state;
|
|
}
|
|
|
|
public function isInProgress($state = null)
|
|
{
|
|
$state = isset($state) ? $state : $this->getState();
|
|
|
|
return self::STATE_IN_PROGRESS == $state;
|
|
}
|
|
|
|
public function isDone($state = null)
|
|
{
|
|
$state = isset($state) ? $state : $this->getState();
|
|
|
|
return self::STATE_DONE == $state;
|
|
}
|
|
|
|
public function updateFields($fields = [], $override_values = true)
|
|
{
|
|
if ($override_values) {
|
|
foreach ($fields as $field => $value) {
|
|
$this->{$field} = $value;
|
|
}
|
|
}
|
|
|
|
return Db::getInstance()->update('newsletter_pro_send', $fields, '`id_newsletter_pro_send` = '.(int) $this->id, 0, true);
|
|
}
|
|
|
|
public function getEmailsToSend($limit = null)
|
|
{
|
|
if (!isset($limit)) {
|
|
$limit = (int) NewsletterPro::getInstance()->step;
|
|
}
|
|
|
|
$steps_id = $this->getStepsIds(true);
|
|
$emails = [];
|
|
|
|
if ($steps_id) {
|
|
foreach ($steps_id as $id) {
|
|
$send_step = NewsletterProSendStep::newInstance($id);
|
|
$emails_to_send = $send_step->getEmailsToSend();
|
|
|
|
$emails = array_merge($emails, $emails_to_send);
|
|
|
|
if (count($emails) >= $limit) {
|
|
$emails = array_slice($emails, 0, $limit);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $emails;
|
|
}
|
|
|
|
public function getEmailsSent($limit = null, $get_errors = true, $reverse = false, $get_last_emails = false)
|
|
{
|
|
if (!isset($limit)) {
|
|
$limit = (int) NewsletterPro::getInstance()->step;
|
|
}
|
|
|
|
$steps_id = $this->getStepsIds(true);
|
|
|
|
if ($get_last_emails) {
|
|
$steps_id = array_reverse($this->getStepsIds(false));
|
|
}
|
|
|
|
return $this->getEmailsSentDefault($steps_id, $limit, $get_errors, $reverse);
|
|
}
|
|
|
|
private function getEmailsSentDefault($steps_id, $limit = null, $get_errors = true, $reverse = false)
|
|
{
|
|
$emails = [];
|
|
$emails_error = [];
|
|
|
|
if ($steps_id) {
|
|
foreach ($steps_id as $id) {
|
|
$send_step = NewsletterProSendStep::newInstance($id);
|
|
$emails_sent = $send_step->getEmailsSent(0, $reverse);
|
|
|
|
if ($get_errors) {
|
|
$error_msg = $send_step->getErrorMsg();
|
|
foreach ($error_msg as $errors) {
|
|
foreach ($errors as $error => $emails_e) {
|
|
foreach ($emails_e as $email_e) {
|
|
$emails_error[$email_e][] = $error;
|
|
$emails_error[$email_e] = array_unique($emails_error[$email_e]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$emails = array_merge($emails, $emails_sent);
|
|
|
|
if (count($emails) >= $limit) {
|
|
$emails = array_slice($emails, 0, $limit);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($get_errors) {
|
|
foreach ($emails as $key => $item) {
|
|
if (isset($emails_error[$item['email']])) {
|
|
$emails[$key]['errors'] = $emails_error[$item['email']];
|
|
} else {
|
|
$emails[$key]['errors'] = [];
|
|
}
|
|
}
|
|
}
|
|
|
|
return $emails;
|
|
}
|
|
|
|
public function getRemaining()
|
|
{
|
|
$remaining = (int) $this->emails_count - (int) $this->emails_completed;
|
|
|
|
if ($remaining >= 0) {
|
|
return $remaining;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
public static function getLastId()
|
|
{
|
|
return (int) Db::getInstance()->getValue('
|
|
SELECT MAX(`id_newsletter_pro_send`)
|
|
FROM `'._DB_PREFIX_.'newsletter_pro_send`
|
|
WHERE 1
|
|
');
|
|
}
|
|
|
|
public function shutdown()
|
|
{
|
|
NewsletterProShutdown::register([$this, 'registerShutdown']);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function registerShutdown()
|
|
{
|
|
if (0 == count($this->getStepsIds(true))) {
|
|
$this->state = NewsletterProSend::STATE_DONE;
|
|
$this->active = 0;
|
|
$this->updateAll();
|
|
} elseif ($this->isInProgress()) {
|
|
$this->state = NewsletterProSend::STATE_DEFAULT;
|
|
$this->updateAll();
|
|
} else {
|
|
$this->updateAll(['state', 'active']);
|
|
}
|
|
}
|
|
|
|
public static function exportPrivacy($email)
|
|
{
|
|
$response = new NewsletterProPrivacyDataResponse(NewsletterProPrivacyDataResponse::TYPE_EXPORT, 'newsletter_pro_send', $email);
|
|
|
|
try {
|
|
// nothing to export
|
|
} catch (Exception $e) {
|
|
$response->addException($e);
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
|
|
public static function privacySerach($email)
|
|
{
|
|
$response = new NewsletterProPrivacyDataResponse(NewsletterProPrivacyDataResponse::TYPE_SEARCH, 'newsletter_pro_send', $email);
|
|
|
|
try {
|
|
$count = (int) Db::getInstance()->getValue('
|
|
SELECT COUNT(*) FROM `'._DB_PREFIX_.'newsletter_pro_send`
|
|
WHERE `error_msg` REGEXP "'.pSQL(preg_quote($email)).'[^A-Za-z0-9]"
|
|
');
|
|
$response->addToCount($count);
|
|
} catch (Exception $e) {
|
|
$response->addException($e);
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
|
|
public static function clearPrivacy($email)
|
|
{
|
|
$response = new NewsletterProPrivacyDataResponse(NewsletterProPrivacyDataResponse::TYPE_CLEAR, 'newsletter_pro_send', $email);
|
|
|
|
try {
|
|
if (Db::getInstance()->update('newsletter_pro_send', [
|
|
'error_msg' => serialize([]),
|
|
], '`error_msg` REGEXP "'.pSQL(preg_quote($email)).'[^A-Za-z0-9]"')) {
|
|
$response->addToCount(Db::getInstance()->Affected_Rows());
|
|
}
|
|
} catch (Exception $e) {
|
|
$response->addException($e);
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
}
|