Files
hotel/modules/blocknewsletter/controllers/admin/AdminNewsletterController.php

641 lines
26 KiB
PHP

<?php
/**
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License version 3.0
* that is bundled with this package in the file LICENSE.md
* It is also available through the world-wide-web at this URL:
* https://opensource.org/license/osl-3-0-php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to support@qloapps.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade this module to a newer
* versions in the future. If you wish to customize this module for your needs
* please refer to https://store.webkul.com/customisation-guidelines for more information.
*
* @author Webkul IN
* @copyright Since 2010 Webkul
* @license https://opensource.org/license/osl-3-0-php Open Software License version 3.0
*/
class AdminNewsletterController extends ModuleAdminController
{
public function __construct()
{
$this->bootstrap = true;
$this->table = 'merged';
$this->identifier = 'id_merged';
$this->allow_export = true;
$this->_filterCustomer = '';
$this->_filterNewsletter = '';
parent::__construct();
$this->addRowAction('viewCustomer');
$this->addRowAction('delete');
$genderList = array();
$genders = Gender::getGenders($this->context->language->id);
foreach ($genders as $gender) {
$genderList[$gender->id_gender] = $gender->name;
}
$this->fields_list = array(
'id_merged' => array(
'title' => $this->l('ID'),
'filter_type' => 'int',
'filter_keys' => array(
'customer' => 'c.`id_customer`',
'newsletter' => 'n.`id`',
),
),
'id_gender' => array(
'title' => $this->l('Social Title'),
'type' => 'select',
'list' => $genderList,
'filter_type' => 'int',
'filter_key' => 'id_gender',
'filter_keys' => array(
'customer' => 'c.`id_gender`',
),
),
'firstname' => array(
'title' => $this->l('First Name'),
'filter_keys' => array(
'customer' => 'c.`firstname`',
),
),
'lastname' => array(
'title' => $this->l('Last Name'),
'filter_keys' => array(
'customer' => 'c.`lastname`',
),
),
'email' => array(
'title' => $this->l('Email'),
'filter_keys' => array(
'customer' => 'c.`email`',
'newsletter' => 'n.`email`',
),
),
'subscribed' => array(
'title' => $this->l('Subscribed'),
'type' => 'bool',
'active' => 'subscribed',
'filter_keys' => array(
'customer' => 'c.`newsletter`',
'newsletter' => 'n.`active`',
),
'ajax' => true,
'search' => false,
'orderby' => false,
),
'newsletter_date_add' => array(
'title' => $this->l('Subscribed On'),
'type' => 'datetime',
'filter_keys' => array(
'customer' => 'c.`newsletter_date_add`',
'newsletter' => 'n.`newsletter_date_add`',
),
),
);
$this->list_no_link = true;
$this->bulk_actions = array(
'divider' => array(
'text' => 'divider'
),
'delete' => array(
'text' => $this->l('Delete selected'),
'confirm' => $this->l('Delete selected items?'),
'icon' => 'icon-trash'
)
);
$this->_conf[101] = $this->l('The customer has been unsubscribed from newsletter successfully.');
$this->_conf[102] = $this->l('The selection has been unsubscribed from newsletter successfully.');
}
public function displayEnableLink($token, $id, $value, $active, $id_category = null, $id_product = null)
{
$tpl = $this->context->smarty->createTemplate(
$this->module->getTemplatePath(
'/views/templates/admin/'.$this->tpl_folder.'/helpers/list/list_action_enable.tpl'
)
);
$tpl->assign(array(
'enabled' => (bool) $value,
'url_enable' => self::$currentIndex.'&action=unsubscribeNewsletter&'.$this->identifier.'='.$id.
'&token='.($token != null ? $token : $this->token),
));
return $tpl->fetch();
}
public function displayViewCustomerLink($token, $id, $name = null)
{
if (Customer::customerIdExistsStatic($id)) {
$tpl = $this->context->smarty->createTemplate(
$this->module->getTemplatePath(
'/views/templates/admin/'.$this->tpl_folder.'/helpers/list/view-customer-link.tpl'
)
);
$tpl->assign(array(
'id_merged' => $id,
'disabled' => !Validate::isUnsignedInt($id),
));
return $tpl->fetch();
} else {
$this->addRowActionSkipList('viewCustomer', $id);
}
}
public function initToolbar()
{
parent::initToolbar();
unset($this->toolbar_btn['save']);
$this->toolbar_btn['export'] = array(
'href' => self::$currentIndex.'&export'.$this->table.'&token='.$this->token,
'desc' => $this->l('Export')
);
}
public function initToolbarTitle()
{
$this->toolbar_title = $this->l('Configuration');
}
public function initContent()
{
parent::initContent();
if ($this->display == 'options') {
$this->content = $this->renderOptions();
$this->content .= $this->renderList();
$this->content .= $this->renderFormExport();
$this->context->smarty->assign(array('content' => $this->content));
unset($this->toolbar_btn['save']);
}
}
public function renderOptions()
{
$this->fields_options = array(
'general' => array(
'title' => $this->l('Configuration'),
'icon' => 'icon-cogs',
'fields' => array(
'NW_VERIFICATION_EMAIL' => array(
'type' => 'bool',
'title' => $this->l('Would you like to send a verification email after subscription?'),
'validation' => 'isBool',
'cast' => 'intval',
),
'NW_CONFIRMATION_EMAIL' => array(
'type' => 'bool',
'title' => $this->l('Would you like to send a confirmation email after subscription?'),
'validation' => 'isBool',
'cast' => 'intval',
),
'NW_VOUCHER_CODE' => array(
'type' => 'text',
'title' => $this->l('Welcome voucher code'),
'desc' => sprintf(
$this->l('You can create a voucher from %s page. Leave blank to disable this feature.'),
'<a href="'.$this->context->link->getAdminLink('AdminCartRules').'" target="_blank">'.$this->l('Cart Rules').'</a>'
),
'class' => 'fixed-width-xl',
'validation' => 'isUnsignedInt',
'required' => true,
'cast' => 'intval',
),
),
'submit' => array(
'title' => $this->l('Save'),
'name' => 'submitNewsletterOptions',
)
),
);
return parent::renderOptions();
}
public function renderList()
{
$this->tpl_list_vars['title'] = $this->l('Subscribers');
$this->tpl_list_vars['icon'] = 'icon-list';
return parent::renderList();
}
public function renderFormExport()
{
$this->fields_form = array(
'legend' => array(
'title' => $this->l('Export Email Addresses'),
'icon' => 'icon-share-alt'
),
'description' => $this->l('Use this option to export list of email addresses as a .CSV file.'),
'input' => array(
array(
'type' => 'select',
'label' => $this->l('Newsletter subscribers'),
'name' => 'subscribersType',
'class' => 'fixed-width-xl',
'options' => array(
'query' => array(
array(
'id' => Blocknewsletter::EXPORT_ALL_SUBSCRIBERS,
'name' => $this->l('All subscribers'),
),
array(
'id' => Blocknewsletter::EXPORT_SUBSCRIBERS_WITH_ACCOUNT,
'name' => $this->l('Subscribers with account'),
),
array(
'id' => Blocknewsletter::EXPORT_SUBSCRIBERS_WITHOUT_ACCOUNT,
'name' => $this->l('Subscribers without account'),
),
array(
'id' => Blocknewsletter::EXPORT_NON_SUBSCRIBERS,
'name' => $this->l('Non-subscribers'),
),
),
'id' => 'id',
'name' => 'name'
),
'desc' => $this->l('Filter customers who have subscribed to the newsletter or not, and who have an account or not.'),
),
),
'submit' => array(
'title' => $this->l('Export .CSV file'),
'icon' => 'process-icon- icon-share-alt',
'id' => 'submit-export-email-addresses',
'name' => 'submitExportEmailAddresses',
),
);
return parent::renderForm();
}
public function postProcess()
{
if (Tools::isSubmit('submitNewsletterOptions')) {
$voucherCode = Tools::getValue('NW_VOUCHER_CODE');
if (Tools::strlen($voucherCode) > 0) {
if (!Validate::isDiscountName($voucherCode)) {
$this->errors[] = $this->l('The voucher code is invalid.');
} elseif (!CartRule::cartRuleExists($voucherCode)) {
$this->errors[] = $this->l('The voucher code does not exist.');
}
}
if (!count($this->errors)) {
Configuration::updateValue('NW_VERIFICATION_EMAIL', Tools::getValue('NW_VERIFICATION_EMAIL'));
Configuration::updateValue('NW_CONFIRMATION_EMAIL', Tools::getValue('NW_CONFIRMATION_EMAIL'));
Configuration::updateValue('NW_VOUCHER_CODE', $voucherCode);
Tools::redirectAdmin(self::$currentIndex.'&conf=6&token='.$this->token);
}
} elseif (Tools::isSubmit('submitExportEmailAddresses')) {
$subscribersType = Tools::getValue('subscribersType');
$subscribers = $this->module->getSubscribers($subscribersType);
if (count($subscribers)) {
array_unshift($subscribers, $this->module->getExportCsvHeader());
$fileName = 'newsletter_emails_'.date('YmdHis').'.csv';
$filePath = $this->module->getLocalPath().'export/'.$fileName;
$fileHandle = fopen($filePath, 'w+');
foreach ($subscribers as $subscriber) {
fputcsv($fileHandle, $subscriber, ';', escape: "");
}
if (Tools::file_exists_cache($filePath)) {
if (ob_get_level() && ob_get_length() > 0) {
ob_end_clean();
}
header('Content-Type: text/csv');
header('Content-Type: application/force-download; charset=UTF-8');
header('Cache-Control: no-store, no-cache');
header('Content-Disposition: attachment; filename="'.$fileName.'"');
@set_time_limit(0);
readfile($filePath);
exit;
}
} else {
$this->errors[] = $this->l('No email addresses found to export.');
}
}
parent::postProcess();
}
private function unsubscribeNewsletter($idMerged)
{
$result = false;
$email = '';
if (preg_match('/(^N)/', $idMerged)) {
$idMerged = (int) substr($idMerged, 1);
$email = Db::getInstance()->getValue(
'SELECT n.`email`
FROM `'._DB_PREFIX_.'newsletter` n
WHERE n.`id` = '.(int) $idMerged
);
} else {
$objCustomer = new Customer($idMerged);
if (Validate::isLoadedObject($objCustomer)) {
$email = $objCustomer->email;
} else {
$this->errors[] = $this->l('Customer object can not be loaded.');
}
}
if ($email && !count($this->errors)) {
$registrationStatus = $this->module->isNewsletterRegistered($email);
if ($registrationStatus < 1) {
$this->errors[] = $this->l('This email address is not registered.');
}
if (!($result = $this->module->unregister($email, $registrationStatus))) {
$this->errors[] = $this->l('An error occurred while attempting to unsubscribe.');
}
}
return $result;
}
public function processUnsubscribeNewsletter()
{
$idMerged = Tools::getValue('id_merged');
if ($this->unsubscribeNewsletter($idMerged)) {
Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&conf=101');
} else {
$this->errors[] = $this->l('Newsletter unsubscription failed. Please try again.');
}
}
public function processDelete()
{
$idMerged = Tools::getValue('id_merged');
if ($this->unsubscribeNewsletter($idMerged)) {
Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&conf=101');
} else {
$this->errors[] = $this->l('Newsletter unsubscription failed. Please try again.');
}
}
public function processBulkDelete()
{
$result = true;
if (is_array($this->boxes) && !empty($this->boxes)) {
foreach ($this->boxes as $idMerged) {
$deleteOk = $this->unsubscribeNewsletter($idMerged);
$result &= $deleteOk;
if (!$deleteOk) {
$this->errors[] = sprintf($this->l('Can\'t delete #%d'), $idMerged);
}
}
if ($result) {
Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&conf=2');
} else {
$this->errors[] = $this->l('Something went wrong. Please try again.');
}
} else {
$this->errors[] = $this->l('You must select at least one element to delete.');
}
}
public function getList(
$id_lang,
$orderBy = null,
$orderWay = null,
$start = 0,
$limit = null,
$idLangShop = false
) {
$useLimit = true;
if ($limit === false) {
$useLimit = false;
} elseif (empty($limit)) {
if (isset($this->context->cookie->{$this->list_id.'_pagination'}) && $this->context->cookie->{$this->list_id.'_pagination'}) {
$limit = $this->context->cookie->{$this->list_id.'_pagination'};
} else {
$limit = $this->_default_pagination;
}
}
$prefix = 'newsletter';
if (empty($orderBy)) {
if ($this->context->cookie->{$prefix.$this->list_id.'Orderby'}) {
$orderBy = $this->context->cookie->{$prefix.$this->list_id.'Orderby'};
} elseif ($this->_orderBy) {
$orderBy = $this->_orderBy;
} else {
$orderBy = $this->_defaultOrderBy;
}
}
if (empty($orderWay)) {
if ($this->context->cookie->{$prefix.$this->list_id.'Orderway'}) {
$orderWay = $this->context->cookie->{$prefix.$this->list_id.'Orderway'};
} elseif ($this->_orderWay) {
$orderWay = $this->_orderWay;
} else {
$orderWay = $this->_defaultOrderWay;
}
}
$sqlWhere = '';
do {
$sqlWhere = ' '.(isset($this->_where) ? $this->_where.' ' : '').
($this->deleted ? 'AND a.`deleted` = 0 ' : '').
(isset($this->_filter) ? $this->_filter : '').
(isset($this->_group) ? $this->_group.' ' : '');
$this->_orderBy = $orderBy;
$this->_orderWay = $orderWay = Tools::strtoupper($orderWay);
$sqlOrderBy = ' ORDER BY '.$orderBy.' '.pSQL($orderWay);
$sqlLimit = ' '.(($useLimit === true) ? ' LIMIT '.(int) $start.', '.(int) $limit : '');
$this->_listsql = 'SELECT c.`id_customer` AS id_merged, gl.`name` AS id_gender, c.`email`, c.`firstname`, c.`lastname`, c.`newsletter` AS subscribed, c.`newsletter_date_add`
FROM `'._DB_PREFIX_.'customer` c
LEFT JOIN '._DB_PREFIX_.'gender_lang gl ON (gl.`id_gender` = c.`id_gender` AND gl.`id_lang` = '.(int) $this->context->language->id.')
WHERE c.`newsletter` = 1 '.$this->_filterCustomer.'
UNION
SELECT CONCAT(\'N\', n.`id`) AS id_merged, NULL AS id_gender, n.`email`, NULL AS firstname, NULL AS lastname, n.`active` AS subscribed, n.`newsletter_date_add`
FROM `'._DB_PREFIX_.'newsletter` n WHERE n.`active` = 1 '.$this->_filterNewsletter.$sqlOrderBy;
$listCount = 'SELECT FOUND_ROWS() AS `'._DB_PREFIX_.$this->table.'`';
$this->_list = Db::getInstance()->executeS($this->_listsql, true, false);
if ($this->_list === false) {
$this->_list_error = Db::getInstance()->getMsgError();
break;
}
$this->_listTotal = Db::getInstance()->getValue($listCount, false);
if ($useLimit === true) {
$start = (int) $start - (int) $limit;
if ($start < 0) {
break;
}
} else {
break;
}
} while (empty($this->_list));
Hook::exec('action'.$this->controller_name.'ListingResultsModifier', array(
'list' => &$this->_list,
'list_total' => &$this->_listTotal,
));
}
public function processFilter()
{
Hook::exec('action'.$this->controller_name.'ListingFieldsModifier', array(
'fields' => &$this->fields_list,
));
$this->ensureListIdDefinition();
$prefix = $this->getCookieFilterPrefix();
if (isset($this->list_id)) {
foreach ($_POST as $key => $value) {
if ($value === '') {
unset($this->context->cookie->{$prefix.$key});
} elseif (stripos($key, $this->list_id.'Filter_') === 0) {
$this->context->cookie->{$prefix.$key} = !is_array($value) ? $value : json_encode($value);
} elseif (stripos($key, 'submitFilter') === 0) {
$this->context->cookie->$key = !is_array($value) ? $value : json_encode($value);
}
}
foreach ($_GET as $key => $value) {
if (stripos($key, $this->list_id.'Filter_') === 0) {
$this->context->cookie->{$prefix.$key} = !is_array($value) ? $value : json_encode($value);
} elseif (stripos($key, 'submitFilter') === 0) {
$this->context->cookie->$key = !is_array($value) ? $value : json_encode($value);
}
if (stripos($key, $this->list_id.'Orderby') === 0 && Validate::isOrderBy($value)) {
if ($value === '' || $value == $this->_defaultOrderBy) {
unset($this->context->cookie->{$prefix.$key});
} else {
$this->context->cookie->{$prefix.$key} = $value;
}
} elseif (stripos($key, $this->list_id.'Orderway') === 0 && Validate::isOrderWay($value)) {
if ($value === '' || $value == $this->_defaultOrderWay) {
unset($this->context->cookie->{$prefix.$key});
} else {
$this->context->cookie->{$prefix.$key} = $value;
}
}
}
}
$filters = $this->context->cookie->getFamily($prefix.$this->list_id.'Filter_');
foreach ($filters as $key => $value) {
if ($value != null && !strncmp($key, $prefix.$this->list_id.'Filter_', 7 + Tools::strlen($prefix.$this->list_id))) {
$key = Tools::substr($key, 7 + Tools::strlen($prefix.$this->list_id));
if (!array_key_exists($key, $this->fields_list)) {
continue;
}
$field = $this->fields_list[$key];
foreach ($field['filter_keys'] as $table => $filterKey) {
$key = $filterKey;
$type = (array_key_exists('filter_type', $field) ? $field['filter_type'] : (array_key_exists('type', $field) ? $field['type'] : false));
if (($type == 'date' || $type == 'datetime' || $type == 'range') && is_string($value)) {
$value = json_decode($value, true);
}
$sqlFilter = '';
// only for date filtering (from, to)
if (is_array($value)) {
if ($type == 'range') {
if (isset($value[0]) && !empty($value[0])) {
if (!Validate::isUnsignedInt($value[0])) {
$this->errors[] = Tools::displayError('The \'From\' value is invalid');
} else {
$sqlFilter .= ' AND '.pSQL($key).' >= '.pSQL($value[0]);
}
}
if (isset($value[1]) && !empty($value[1])) {
if (!Validate::isUnsignedInt($value[1])) {
$this->errors[] = Tools::displayError('The \'From\' value is invalid');
} elseif (isset($value[0]) && !empty($value[0]) && $value[0] > $value[1]) {
$this->errors[] = Tools::displayError('The \'To\' value cannot be less than from value');
} else {
$sqlFilter .= ' AND '.pSQL($key).' <= '.pSQL($value[1]);
}
}
} else {
if (isset($value[0]) && !empty($value[0])) {
if (!Validate::isDate($value[0])) {
$this->errors[] = Tools::displayError('The \'From\' date format is invalid (YYYY-MM-DD)');
} else {
$sqlFilter .= ' AND '.pSQL($key).' >= \''.pSQL(Tools::dateFrom($value[0])).'\'';
}
}
if (isset($value[1]) && !empty($value[1])) {
if (!Validate::isDate($value[1])) {
$this->errors[] = Tools::displayError('The \'To\' date format is invalid (YYYY-MM-DD)');
} elseif (isset($value[0]) && !empty($value[0]) && strtotime($value[0]) > strtotime($value[1])) {
$this->errors[] = Tools::displayError('The \'To\' date cannot be before than from date');
} else {
$sqlFilter .= ' AND '.pSQL($key).' <= \''.pSQL(Tools::dateTo($value[1])).'\'';
}
}
}
} else {
$sqlFilter .= ' AND ';
if ($type == 'int' || $type == 'bool') {
$sqlFilter .= pSQL($key).' = '.(int) $value.' ';
} elseif ($type == 'decimal') {
$sqlFilter .= pSQL($key).' = '.(float) $value.' ';
} elseif ($type == 'select') {
$sqlFilter .= pSQL($key).' = \''.pSQL($value).'\' ';
} elseif ($type == 'price') {
$value = (float) str_replace(',', '.', $value);
$sqlFilter .= pSQL($key).' = '.pSQL(trim($value)).' ';
} else {
$sqlFilter .= pSQL($key).' LIKE \'%'.pSQL(trim($value)).'%\' ';
}
}
if ($table == 'customer') {
$this->_filterCustomer .= $sqlFilter;
} elseif ($table == 'newsletter') {
$this->_filterNewsletter .= $sqlFilter;
}
}
}
}
}
}