diff --git a/controllers/admin/AdminCustomerPreferencesController.php b/controllers/admin/AdminCustomerPreferencesController.php index f59179b87..a9e94ae53 100644 --- a/controllers/admin/AdminCustomerPreferencesController.php +++ b/controllers/admin/AdminCustomerPreferencesController.php @@ -115,7 +115,7 @@ public function __construct() ), 'PS_CUSTOMER_OPTIN' => array( 'title' => $this->l('Enable opt-in'), - 'hint' => $this->l('Display or not the opt-in tick box, to receive offers from the store\'s partners.'), + 'hint' => $this->l('Display or not the opt-in tick box, to receive offers from your hotel partners.'), 'validation' => 'isBool', 'cast' => 'intval', 'type' => 'bool' diff --git a/controllers/admin/AdminCustomersController.php b/controllers/admin/AdminCustomersController.php index 9aa3205f5..2a65dad0a 100644 --- a/controllers/admin/AdminCustomersController.php +++ b/controllers/admin/AdminCustomersController.php @@ -39,8 +39,8 @@ class AdminCustomersControllerCore extends AdminController public function __construct() { $this->bootstrap = true; - $this->required_database = true; - $this->required_fields = array('newsletter','optin'); + // $this->required_database = true; + // $this->required_fields = array('newsletter','optin'); $this->table = 'customer'; $this->className = 'Customer'; $this->lang = false; @@ -458,8 +458,9 @@ public function renderForm() 'label' => $this->l('Disabled') ) ), - 'disabled' => (bool)!Configuration::get('PS_CUSTOMER_NWSL'), - 'hint' => $this->l('This customer will receive your newsletter via email.') + 'disabled' => (bool)!Configuration::get('PS_CUSTOMER_NWSL'), + 'hint' => $this->l('This customer will receive your newsletter via email.'), + 'desc' => (bool)!Configuration::get('PS_CUSTOMER_NWSL') ? sprintf($this->l('This field is disabled as option \'Enable newsletter registration\' is disabled. You can change it from %sPreferences > Customers%s page.'), '', '') : '', ), array( 'type' => 'switch', diff --git a/controllers/front/OrderOpcController.php b/controllers/front/OrderOpcController.php index 0837f9a1d..639b8bb56 100644 --- a/controllers/front/OrderOpcController.php +++ b/controllers/front/OrderOpcController.php @@ -553,7 +553,7 @@ public function initContent() } Tools::safePostVars(); - $newsletter = Configuration::get('PS_CUSTOMER_NWSL') || (Module::isInstalled('blocknewsletter') && Module::getInstanceByName('blocknewsletter')->active); + $newsletter = Module::isInstalled('blocknewsletter') && Module::getInstanceByName('blocknewsletter')->active && Configuration::get('PS_CUSTOMER_NWSL'); $this->context->smarty->assign('birthday', (bool) Configuration::get('PS_CUSTOMER_BIRTHDATE')); $this->context->smarty->assign('newsletter', $newsletter); $this->context->smarty->assign('optin', (bool)Configuration::get('PS_CUSTOMER_OPTIN')); diff --git a/modules/blocknewsletter/blocknewsletter.css b/modules/blocknewsletter/blocknewsletter.css index 8928dd158..46b2e74c1 100644 --- a/modules/blocknewsletter/blocknewsletter.css +++ b/modules/blocknewsletter/blocknewsletter.css @@ -1,56 +1,189 @@ /* Block newsletter */ -#newsletter_block_left { - padding:7px; - border:1px solid #ccc; - background:#eee; -} -#newsletter_block_left .title_block, #newsletter_block_left h4 { - padding:0 0 12px 28px; - color:#666; - text-shadow:0 1px 0 #fff; - background:url(img/icon/newsletter.png) no-repeat 0 0 transparent; -} -#newsletter_block_left p {padding:0;} - -#newsletter_block_left p.success_inline { - color: #418B19; - text-align: center; - font-weight: bold; -} -#newsletter_block_left p.warning_inline { - color: #DA0F00; - text-align: center; - font-weight: bold; -} - -#newsletter_block_left input.inputNew { - position: relative; - top: -1px; - padding:0 5px; - height:20px; - width:148px; - border:1px solid #ccc; - border-right:none; - -moz-border-radius-topleft: 3px; - -moz-border-radius-bottomleft: 3px; - -webkit-border-radius-topleft: 3px; - -webkit-border-radius-bottomleft: 3px; - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; - font-size:10px; - color:#999; -} -*:first-child+html #newsletter_block_left input.inputNew {position:static;}/* hack ie 7 */ - -#newsletter_block_left input.button_mini { - position:relative; - left:-2px; - height:23px; - width:24px; - border:0; - text-indent:-5000px; - background:url(img/bg_bt_newsletter_ok.png) no-repeat 0 0; - cursor:pointer -} -*:first-child+html #newsletter_block_left input.button_mini {padding-left:24px !important;}/* hack ie 7 */ +#columns #newsletter_block_left .form-group { + margin-bottom: 0; } + #columns #newsletter_block_left .form-group .form-control { + max-width: 222px; + display: inline-block; + margin-right: 6px; } + @media (min-width: 768px) and (max-width: 1199px) { + #columns #newsletter_block_left .form-group .form-control { + margin-bottom: 10px; + margin-right: 0; } } +#columns #newsletter_block_left .success_inline, #columns #newsletter_block_left .warning_inline { + text-align: left; + padding: 1px 0 0 0; + margin-bottom: -19px; } +#columns #newsletter_block_left .success_inline { + color: #418B19; } +#columns #newsletter_block_left .warning_inline { + color: #f13340; } +/* Block newsletter footer */ +#footer #newsletter_block_left { + overflow: hidden; + /*width: 50%;*//*by webkul*/ + float: left; + padding: 13px 15px 7px 15px; + height: 70px;/*by webkul*/ + margin-bottom: 0; } + @media (max-width: 992px) { + #footer #newsletter_block_left { + height: 100px; } + #newsletter_block_left .block_content + { + width: 350px; + margin: 10px auto 0px; + }} + @media (max-width: 400px) { + #newsletter_block_left .block_content + { + width: 273px; + }} + @media (max-width: 767px) { + #footer #newsletter_block_left { + /*width: 100%;*/ + height: auto; } } + #footer #newsletter_block_left h4 { + background: none; + float: left; + padding: 7px 16px 5px 0; + text-transform: none; + font-size: 21px; + line-height: 25px; + border: none; } + #footer #newsletter_block_left h4:after { + display: none; } + #footer #newsletter_block_left .block_content { + overflow: hidden; } + #footer #newsletter_block_left .form-group { + margin-bottom: 0; } + #footer #newsletter_block_left .form-group .form-control { + height: 45px; + max-width: 267px; + background: #3c3c3c; + border-color: #515151; + color: #fff; + padding: 10px 43px 10px 12px; + display: inline-block; + float: left; } + @media (max-width: 400px) { + #footer #newsletter_block_left .form-group .form-control{ + padding: 7px 43px 7px 6px; + height: 37px; + } + } + #footer #newsletter_block_left .form-group .form-control:focus { + -moz-box-shadow: black 0px 0px 0px; + -webkit-box-shadow: black 0px 0px 0px; + box-shadow: black 0px 0px 0px; } + #footer #newsletter_block_left .form-group .button-small { + margin-left: -43px; + border: none; + background: none; + text-align: center; + color: #908f8f; + padding: 8px; } + #footer #newsletter_block_left .form-group .button-small:before { + content: "\f138"; + font-family: "FontAwesome"; + font-size: 28px; + line-height: 28px; } + #footer #newsletter_block_left .form-group .button-small:hover { + color: #fff !important; } + #footer #newsletter_block_left .form-group .button-small span { + display: none; } + #footer #newsletter_block_left .warning_inline { + display: block; + color: #f13340; + font-size: 13px; + line-height: 26px; + clear: both; } + @media (min-width: 1200px) { + #footer #newsletter_block_left .warning_inline { + display: inline-block; + position: relative; + top: -35px; + margin-bottom: -35px; + left: 15px; + clear: none; } } + #footer #newsletter_block_left .newsletter-input { + max-width: 230px !important; }/*by webkul original 300px*/ + @media (max-width: 400px) { + #footer #newsletter_block_left .newsletter-input { + max-width: 190px !important; + } + } + +#newsletter-input::-webkit-input-placeholder { + color: #bfbfbf; +} + +#newsletter-input:-moz-placeholder { /* Firefox 18- */ + color: #bfbfbf; +} + +#newsletter-input::-moz-placeholder { /* Firefox 19+ */ + color: #bfbfbf; +} + +#newsletter-input:-ms-input-placeholder { + color: #bfbfbf; +} + +#blocknewsletter .message-block .alert { + position: relative; +} + +#blocknewsletter .message-block .alert.alert-dismissable .close { + position: absolute; + top: 0; + right: 0; + padding: 5px 10px; + opacity: 0.5; + color: #000; + text-shadow: none; +} + +#blocknewsletter .message-block .alert.alert-dismissable .close:hover { + color: #000; +} + +#blocknewsletter .loader { + margin-left: 10px; + position: relative; + top: 10px; +} + +#blocknewsletter .loader.loading { + display: inline-flex; + justify-content: center; +} + +#blocknewsletter .loader.loading::after { + content: ''; + width: 30px; + height: 30px; + border: 4px solid #dddddd; + border-top-color: transparent; + border-radius: 50%; + animation: loading 0.5s linear infinite; +} + +@-webkit-keyframes loading { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } +@-moz-keyframes loading { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } +@keyframes loading { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } + +/*# sourceMappingURL=blocknewsletter.css.map */ +.button.button-medium.newsletter-btn { + position: relative; + padding: 0px 20px; +} +#newsletter-input +{ + background-color: #3a3a3a; + border: 1px solid #868686; + color: #bfbfbf; + font-size: 13px; + height: 42px; + margin-bottom: 10px; +} diff --git a/modules/blocknewsletter/blocknewsletter.js b/modules/blocknewsletter/blocknewsletter.js index e69de29bb..488dc989a 100644 --- a/modules/blocknewsletter/blocknewsletter.js +++ b/modules/blocknewsletter/blocknewsletter.js @@ -0,0 +1,29 @@ +$(document).on('click', '#blocknewsletter .newsletter-btn', function (e) { + e.preventDefault(); + + $.ajax({ + url: url_newsletter_subscription, + type: 'POST', + dataType: 'JSON', + cache: false, + data: $(this).closest('form').serialize(), + beforeSend: function () { + let messageBlock = $('#blocknewsletter .message-block'); + $(messageBlock).fadeOut('fast'); + + $('#blocknewsletter .loader').show(); + }, + success: function (response) { + let messageBlock = $('#blocknewsletter .message-block'); + $(messageBlock).html(response.message_html).stop(true, true).fadeIn('fast'); + }, + error: function (jqXHR) { + if (jqXHR.readyState == 0) { + showErrorMessage(no_internet_txt); + } + }, + complete: function () { + $('#blocknewsletter .loader').hide(); + } + }); +}); diff --git a/modules/blocknewsletter/blocknewsletter.php b/modules/blocknewsletter/blocknewsletter.php index 1bca820ef..a7a0612d6 100644 --- a/modules/blocknewsletter/blocknewsletter.php +++ b/modules/blocknewsletter/blocknewsletter.php @@ -35,6 +35,11 @@ class Blocknewsletter extends Module const GUEST_REGISTERED = 1; const CUSTOMER_REGISTERED = 2; + const EXPORT_ALL_SUBSCRIBERS = 1; + const EXPORT_SUBSCRIBERS_WITH_ACCOUNT = 2; + const EXPORT_SUBSCRIBERS_WITHOUT_ACCOUNT = 3; + const EXPORT_NON_SUBSCRIBERS = 4; + public function __construct() { $this->name = 'blocknewsletter'; @@ -50,6 +55,7 @@ public function __construct() $this->description = $this->l('Adds a block for newsletter subscription.'); $this->confirmUninstall = $this->l('Are you sure that you want to delete all of your contacts?'); $this->ps_versions_compliancy = array('min' => '1.6', 'max' => _PS_VERSION_); + $this->secure_key = Tools::encrypt($this->name); $this->version = '2.2.2'; $this->author = 'PrestaShop'; @@ -63,9 +69,9 @@ public function __construct() ) ); - $this->_searched_email = null; - $this->_html = ''; + + $this->hookPrepared = false; } public function registerHooks() @@ -107,7 +113,7 @@ public function hookActionDeleteGDPRCustomer($customer) public function install() { - if (!parent::install() || !$this->registerHooks()) { + if (!parent::install() || !$this->registerHooks() || !$this->callInstallTab()) { return false; } Configuration::updateValue('NW_SALT', Tools::passwdGen(16)); @@ -126,206 +132,38 @@ public function install() ); } - public function uninstall() + public function callInstallTab() { - Db::getInstance()->execute('DROP TABLE '._DB_PREFIX_.'newsletter'); - return parent::uninstall(); + $result = $this->installTab('AdminParentNewsletter', 'Newsletter', false, true); + $result &= $this->installTab('AdminNewsletter', 'Configuration', 'AdminParentNewsletter', true); + + return $result; } - public function getContent() + public function installTab($className, $tabName, $tabParentName = false, $hidden = false) { - if (Tools::isSubmit('submitUpdate')) { - Configuration::updateValue('NW_CONFIRMATION_EMAIL', (bool)Tools::getValue('NW_CONFIRMATION_EMAIL')); - Configuration::updateValue('NW_VERIFICATION_EMAIL', (bool)Tools::getValue('NW_VERIFICATION_EMAIL')); - - $voucher = Tools::getValue('NW_VOUCHER_CODE'); - if ($voucher && !Validate::isDiscountName($voucher)) { - $this->_html .= $this->displayError($this->l('The voucher code is invalid.')); - } else { - Configuration::updateValue('NW_VOUCHER_CODE', pSQL($voucher)); - $this->_html .= $this->displayConfirmation($this->l('Settings updated')); - } - } elseif (Tools::isSubmit('subscribedmerged')) { - $id = Tools::getValue('id'); - - if (preg_match('/(^N)/', $id)) { - $id = (int)substr($id, 1); - $sql = 'UPDATE '._DB_PREFIX_.'newsletter SET active = 0 WHERE id = '.$id; - Db::getInstance()->execute($sql); - } else { - $c = new Customer((int)$id); - $c->newsletter = (int)!$c->newsletter; - $c->update(); - } - Tools::redirectAdmin( - $this->context->link->getAdminLink('AdminModules', false).'&configure='.$this->name.'&conf=4&token='. - Tools::getAdminTokenLite('AdminModules') - ); - } elseif (Tools::isSubmit('exportSubscribers')) { - $header = array('id', 'shop_name', 'gender', 'lastname', 'firstname', 'email', 'subscribed', 'subscribed_on'); // TODO - $array_to_export = array_merge(array($header), $this->getSubscribers()); - - $file_name = time().'.csv'; - $fd = fopen($this->getLocalPath().$file_name, 'w+'); - foreach ($array_to_export as $tab) { - $line = implode(';', $tab); - $line .= "\n"; - fwrite($fd, $line, 4096); - } - fclose($fd); - Tools::redirect(_PS_BASE_URL_.__PS_BASE_URI__.'modules/'.$this->name.'/'.$file_name); - } elseif (Tools::isSubmit('exportOnlyBlockNews')) { - $array_to_export = $this->getBlockNewsletterSubscriber(); - - $file_name = time().'.csv'; - $fd = fopen($this->getLocalPath().$file_name, 'w+'); - foreach ($array_to_export as $tab) { - $line = implode(';', $tab); - $line .= "\n"; - fwrite($fd, $line, 4096); - } - fclose($fd); - Tools::redirect(_PS_BASE_URL_.__PS_BASE_URI__.'modules/'.$this->name.'/'.$file_name); - } elseif (Tools::isSubmit('searchEmail')) { - $this->_searched_email = Tools::getValue('searched_email'); + $tab = new Tab(); + $tab->active = 1; + $tab->class_name = $className; + $tab->name = array(); + foreach (Language::getLanguages(false) as $lang) { + $tab->name[$lang['id_lang']] = $tabName; } - - $this->_html .= $this->renderForm(); - $this->_html .= $this->renderSearchForm(); - $this->_html .= $this->renderList(); - - $this->_html .= '
'; - - $this->_html .= $this->renderExportForm(); - - return $this->_html; - } - - public function renderList() - { - $fields_list = array( - - 'id' => array( - 'title' => $this->l('ID'), - 'search' => false, - ), - 'shop_name' => array( - 'title' => $this->l('Shop'), - 'search' => false, - ), - 'gender' => array( - 'title' => $this->l('Gender'), - 'search' => false, - ), - 'lastname' => array( - 'title' => $this->l('Lastname'), - 'search' => false, - ), - 'firstname' => array( - 'title' => $this->l('Firstname'), - 'search' => false, - ), - 'email' => array( - 'title' => $this->l('Email'), - 'search' => false, - ), - 'subscribed' => array( - 'title' => $this->l('Subscribed'), - 'type' => 'bool', - 'active' => 'subscribed', - 'search' => false, - ), - 'newsletter_date_add' => array( - 'title' => $this->l('Subscribed on'), - 'type' => 'date', - 'search' => false, - ) - ); - - if (!Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE')) { - unset($fields_list['shop_name']); + if ($tabParentName) { + $tab->id_parent = (int) Tab::getIdFromClassName($tabParentName); + } elseif ($hidden) { + $tab->id_parent = -1; + } else { + $tab->id_parent = 0; } + $tab->module = $this->name; - $helper_list = new HelperList(); - $helper_list->module = $this; - $helper_list->title = $this->l('Newsletter registrations'); - $helper_list->shopLinkType = ''; - $helper_list->no_link = true; - $helper_list->show_toolbar = true; - $helper_list->simple_header = false; - $helper_list->identifier = 'id'; - $helper_list->table = 'merged'; - $helper_list->currentIndex = $this->context->link->getAdminLink('AdminModules', false).'&configure='.$this->name; - $helper_list->token = Tools::getAdminTokenLite('AdminModules'); - $helper_list->actions = array('viewCustomer'); - $helper_list->toolbar_btn['export'] = array( - 'href' => $helper_list->currentIndex.'&exportSubscribers&token='.$helper_list->token, - 'desc' => $this->l('Export') - ); - - /* Before 1.6.0.7 displayEnableLink() could not be overridden in Module class - we declare another row action instead */ - if (version_compare(_PS_VERSION_, '1.6.0.7', '<')) { - unset($fields_list['subscribed']); - $helper_list->actions = array_merge($helper_list->actions, array('unsubscribe')); - } - - // This is needed for displayEnableLink to avoid code duplication - $this->_helperlist = $helper_list; - - /* Retrieve list data */ - $subscribers = $this->getSubscribers(); - $helper_list->listTotal = count($subscribers); - - /* Paginate the result */ - $page = ($page = Tools::getValue('submitFilter'.$helper_list->table)) ? $page : 1; - $pagination = ($pagination = Tools::getValue($helper_list->table.'_pagination')) ? $pagination : 50; - $subscribers = $this->paginateSubscribers($subscribers, $page, $pagination); - - return $helper_list->generateList($subscribers, $fields_list); - } - - public function displayViewCustomerLink($token = null, $id, $name = null) - { - $this->smarty->assign( - array( - 'href' => 'index.php?controller=AdminCustomers&id_customer='.(int)$id.'&updatecustomer&token='. - Tools::getAdminTokenLite('AdminCustomers'), - 'action' => $this->l('View'), - 'disable' => !((int)$id > 0), - ) - ); - return $this->display(__FILE__, 'views/templates/admin/list_action_viewcustomer.tpl'); + return $tab->add(); } - public function displayEnableLink($token, $id, $value, $active, $id_category = null, $id_product = null, $ajax = false) + public function getContent() { - $this->smarty->assign( - array( - 'ajax' => $ajax, - 'enabled' => (bool)$value, - 'url_enable' => $this->_helperlist->currentIndex.'&'.$this->_helperlist->identifier.'='.$id.'&'.$active. - $this->_helperlist->table.($ajax ? '&action='.$active.$this->_helperlist->table.'&ajax='. - (int)$ajax : '').((int)$id_category && (int)$id_product ? '&id_category='.(int)$id_category : ''). - '&token='.$token - ) - ); - return $this->display(__FILE__, 'views/templates/admin/list_action_enable.tpl'); - } - - public function displayUnsubscribeLink($token = null, $id, $name = null) - { - $this->smarty->assign( - array( - 'href' => $this->_helperlist->currentIndex.'&subscribedcustomer&'.$this->_helperlist->identifier.'='. - $id.'&token='.$token, - 'action' => $this->l('Unsubscribe'), - ) - ); - return $this->display(__FILE__, 'views/templates/admin/list_action_unsubscribe.tpl'); + Tools::redirectAdmin($this->context->link->getAdminLink('AdminNewsletter')); } /** @@ -338,7 +176,7 @@ public function displayUnsubscribeLink($token = null, $id, $name = null) * 1 = registered in block * 2 = registered in customer */ - protected function isNewsletterRegistered($customer_email) + public function isNewsletterRegistered($customer_email) { $sql = 'SELECT `email` FROM '._DB_PREFIX_.'newsletter @@ -368,14 +206,14 @@ protected function isNewsletterRegistered($customer_email) /** * Register in block newsletter */ - protected function newsletterRegistration() + public function newsletterRegistration() { if (empty($_POST['email']) || !Validate::isEmail($_POST['email'])) { return $this->error = $this->l('Invalid email address.'); } /* Unsubscription */ - elseif ($_POST['action'] == '1') { + elseif ($_POST['newsletter_action'] == '1') { $register_status = $this->isNewsletterRegistered($_POST['email']); if ($register_status < 1) { @@ -389,7 +227,7 @@ protected function newsletterRegistration() return $this->valid = $this->l('Unsubscription successful.'); } /* Subscription */ - elseif ($_POST['action'] == '0') { + elseif ($_POST['newsletter_action'] == '0') { $register_status = $this->isNewsletterRegistered($_POST['email']); if ($register_status > 0) { return $this->error = $this->l('This email address is already registered.'); @@ -429,47 +267,55 @@ protected function newsletterRegistration() } } - public function getSubscribers() + public function getExportCsvHeader() { - $dbquery = new DbQuery(); - $dbquery->select('c.`id_customer` AS `id`, s.`name` AS `shop_name`, gl.`name` AS `gender`, c.`lastname`, c.`firstname`, c.`email`, c.`newsletter` AS `subscribed`, c.`newsletter_date_add`'); - $dbquery->from('customer', 'c'); - $dbquery->leftJoin('shop', 's', 's.id_shop = c.id_shop'); - $dbquery->leftJoin('gender', 'g', 'g.id_gender = c.id_gender'); - $dbquery->leftJoin( - 'gender_lang', 'gl', 'g.id_gender = gl.id_gender AND gl.id_lang = '.(int)$this->context->employee->id_lang + return array( + $this->l('ID'), + $this->l('Social Title'), + $this->l('Email'), + $this->l('First Name'), + $this->l('Last Name'), + $this->l('Subscribed'), + $this->l('Date Added'), ); - $dbquery->where('c.`newsletter` = 1'); - if ($this->_searched_email) { - $dbquery->where('c.`email` LIKE \'%'.pSQL($this->_searched_email).'%\' '); - } + } - $customers = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($dbquery->build()); + public function getSubscribers($subscribersType) + { + $subscribers = array(); - $dbquery = new DbQuery(); - $dbquery->select( - 'CONCAT(\'N\', n.`id`) AS `id`, s.`name` AS `shop_name`, NULL AS `gender`, NULL AS `lastname`, NULL - AS `firstname`, n.`email`, n.`active` AS `subscribed`, n.`newsletter_date_add`' - ); - $dbquery->from('newsletter', 'n'); - $dbquery->leftJoin('shop', 's', 's.id_shop = n.id_shop'); - $dbquery->where('n.`active` = 1'); - if ($this->_searched_email) { - $dbquery->where('n.`email` LIKE \'%'.pSQL($this->_searched_email).'%\' '); + if (in_array( + $subscribersType, + array( + self::EXPORT_ALL_SUBSCRIBERS, + self::EXPORT_SUBSCRIBERS_WITH_ACCOUNT, + self::EXPORT_NON_SUBSCRIBERS, + ) + )) { + $sqlCustomer = 'SELECT c.`id_customer` AS id, gl.`name` AS 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` = '.($subscribersType == self::EXPORT_NON_SUBSCRIBERS ? '0' : '1'); + + $subscribers = array_merge($subscribers, Db::getInstance()->executeS($sqlCustomer)); } - $non_customers = Db::getInstance()->executeS($dbquery->build()); - - $subscribers = array_merge($customers, $non_customers); - - return $subscribers; - } + if (in_array( + $subscribersType, + array( + self::EXPORT_ALL_SUBSCRIBERS, + self::EXPORT_SUBSCRIBERS_WITHOUT_ACCOUNT, + self::EXPORT_NON_SUBSCRIBERS, + ) + )) { + $sqlNewsletter = 'SELECT CONCAT(\'N\', n.`id`) AS id, 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` = '.($subscribersType == self::EXPORT_NON_SUBSCRIBERS ? '0' : '1'); - public function paginateSubscribers($subscribers, $page = 1, $pagination = 50) - { - if (count($subscribers) > $pagination) { - $subscribers = array_slice($subscribers, $pagination * ($page - 1), $pagination); + $subscribers = array_merge($subscribers, Db::getInstance()->executeS($sqlNewsletter)); } + return $subscribers; } @@ -509,13 +355,13 @@ protected function register($email, $register_status) return false; } - protected function unregister($email, $register_status) + public function unregister($email, $register_status) { if ($register_status == self::GUEST_REGISTERED) { - $sql = 'DELETE FROM '._DB_PREFIX_.'newsletter WHERE `email` = \''.pSQL($_POST['email']).'\' AND id_shop = '. + $sql = 'DELETE FROM '._DB_PREFIX_.'newsletter WHERE `email` = \''.pSQL($email).'\' AND id_shop = '. $this->context->shop->id; } elseif ($register_status == self::CUSTOMER_REGISTERED) { - $sql = 'UPDATE '._DB_PREFIX_.'customer SET `newsletter` = 0 WHERE `email` = \''.pSQL($_POST['email']). + $sql = 'UPDATE '._DB_PREFIX_.'customer SET `newsletter` = 0 WHERE `email` = \''.pSQL($email). '\' AND id_shop = '.$this->context->shop->id; } @@ -649,6 +495,7 @@ protected function getToken($email, $register_status) */ public function confirmEmail($token) { + $errors = array(); $activated = false; if ($email = $this->getGuestEmailByToken($token)) { @@ -658,18 +505,20 @@ public function confirmEmail($token) } if (!$activated) { - return $this->l('This email is already registered and/or invalid.'); + $errors[] = $this->l('This email is already registered and/or invalid.'); } - if ($discount = Configuration::get('NW_VOUCHER_CODE')) { - $this->sendVoucher($email, $discount); - } + if (!count($errors)) { + if ($discount = Configuration::get('NW_VOUCHER_CODE')) { + $this->sendVoucher($email, $discount); + } - if (Configuration::get('NW_CONFIRMATION_EMAIL')) { - $this->sendConfirmationEmail($email); + if (Configuration::get('NW_CONFIRMATION_EMAIL')) { + $this->sendConfirmationEmail($email); + } } - return $this->l('Thank you for subscribing to our newsletter.'); + return $errors; } /** @@ -744,38 +593,25 @@ public function hookDisplayRightColumn($params) protected function _prepareHook($params) { - if (Tools::isSubmit('submitNewsletter')) { - $this->newsletterRegistration(); - if ($this->error) { - $this->smarty->assign( - array( - 'color' => 'red', - 'msg' => $this->error, - 'nw_value' => isset($_POST['email']) ? pSQL($_POST['email']) : false, - 'nw_error' => true, - 'action' => $_POST['action'] - ) - ); - } elseif ($this->valid) { - $this->smarty->assign( - array( - 'color' => 'green', - 'msg' => $this->valid, - 'nw_error' => false - ) - ); - } + if (!$this->hookPrepared) { + $this->context->smarty->assign(array( + 'csrf_token' => $this->secure_key, + )); + + Media::addJsDef(array( + 'url_newsletter_subscription' => $this->context->link->getModuleLink($this->name, 'subscription'), + )); + + $this->hookPrepared = true; } - $this->smarty->assign('this_path', $this->_path); } public function hookDisplayLeftColumn($params) { - if (!isset($this->prepared) || !$this->prepared) { - $this->_prepareHook($params); - } - $this->prepared = true; + $this->_prepareHook($params); + $this->smarty->assign(array('id_module' => $this->id)); + return $this->display(__FILE__, 'blocknewsletter.tpl'); } @@ -824,179 +660,39 @@ public function hookActionCustomerAccountAdd($params) return true; } - public function renderForm() - { - $fields_form = array( - 'form' => array( - 'legend' => array( - 'title' => $this->l('Settings'), - 'icon' => 'icon-cogs' - ), - 'input' => array( - array( - 'type' => 'switch', - 'label' => $this->l('Would you like to send a verification email after subscription?'), - 'name' => 'NW_VERIFICATION_EMAIL', - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - ), - array( - 'type' => 'switch', - 'label' => $this->l('Would you like to send a confirmation email after subscription?'), - 'name' => 'NW_CONFIRMATION_EMAIL', - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - ), - array( - 'type' => 'text', - 'label' => $this->l('Welcome voucher code'), - 'name' => 'NW_VOUCHER_CODE', - 'class' => 'fixed-width-md', - 'desc' => $this->l('Leave blank to disable by default.') - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ), - ); - - $helper = new HelperForm(); - $helper->show_toolbar = false; - $helper->table = $this->table; - $lang = new Language((int)Configuration::get('PS_LANG_DEFAULT')); - $helper->default_form_language = $lang->id; - $helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') ? Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') : 0; - $helper->identifier = $this->identifier; - $helper->submit_action = 'submitUpdate'; - $helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false).'&configure='.$this->name.'&tab_module='.$this->tab.'&module_name='.$this->name; - $helper->token = Tools::getAdminTokenLite('AdminModules'); - $helper->tpl_vars = array( - 'fields_value' => $this->getConfigFieldsValues(), - 'languages' => $this->context->controller->getLanguages(), - 'id_language' => $this->context->language->id - ); - - return $helper->generateForm(array($fields_form)); - } - - public function renderExportForm() - { - $fields_form = array( - 'form' => array( - 'legend' => array( - 'title' => $this->l('Export Newsletter Subscribers'), - 'icon' => 'icon-envelope' - ), - 'description' => $this->l('Generate a .CSV file based on Newsletter subscribers data. Only subscribers without an account on your website will be exported.'), - 'submit' => array( - 'title' => $this->l('Export .CSV file'), - 'class' => 'btn btn-default pull-right', - 'name' => 'submitExportmodule', - ) - ), - ); - - $helper = new HelperForm(); - $helper->table = $this->table; - $lang = new Language((int)Configuration::get('PS_LANG_DEFAULT')); - $helper->default_form_language = $lang->id; - $helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') ? Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') : 0; - $helper->identifier = $this->identifier; - $helper->submit_action = 'exportOnlyBlockNews'; - $helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false).'&configure='.$this->name.'&tab_module='.$this->tab.'&module_name='.$this->name; - $helper->token = Tools::getAdminTokenLite('AdminModules'); - $helper->tpl_vars = array( - 'fields_value' => $this->getConfigFieldsValues(), - 'languages' => $this->context->controller->getLanguages(), - 'id_language' => $this->context->language->id - ); - return $helper->generateForm(array($fields_form)); - } - - public function renderSearchForm() - { - $fields_form = array( - 'form' => array( - 'legend' => array( - 'title' => $this->l('Search for addresses'), - 'icon' => 'icon-search' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Email address to search'), - 'name' => 'searched_email', - 'class' => 'fixed-width-xxl', - 'desc' => $this->l('Example: contact@qloapps.com or @qloapps.com') - ), - ), - 'submit' => array( - 'title' => $this->l('Search'), - 'icon' => 'process-icon-refresh', - ) - ), - ); - - $helper = new HelperForm(); - $helper->table = $this->table; - $helper->identifier = $this->identifier; - $helper->submit_action = 'searchEmail'; - $helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false).'&configure='.$this->name.'&tab_module='.$this->tab.'&module_name='.$this->name; - $helper->token = Tools::getAdminTokenLite('AdminModules'); - $helper->tpl_vars = array( - 'fields_value' => array('searched_email' => $this->_searched_email), - 'languages' => $this->context->controller->getLanguages(), - 'id_language' => $this->context->language->id - ); + public function reset() + { + if (!$this->uninstall(false)) { + return false; + } + if (!$this->install(false)) { + return false; + } - return $helper->generateForm(array($fields_form)); + return true; } - public function getConfigFieldsValues() + public function uninstall($keep = true) { - return array( - 'NW_VERIFICATION_EMAIL' => Tools::getValue('NW_VERIFICATION_EMAIL', Configuration::get('NW_VERIFICATION_EMAIL')), - 'NW_CONFIRMATION_EMAIL' => Tools::getValue('NW_CONFIRMATION_EMAIL', Configuration::get('NW_CONFIRMATION_EMAIL')), - 'NW_VOUCHER_CODE' => Tools::getValue('NW_VOUCHER_CODE', Configuration::get('NW_VOUCHER_CODE')), - ); + if (!parent::uninstall() + || ($keep && !Db::getInstance()->execute('DROP TABLE IF EXISTS '._DB_PREFIX_.'newsletter')) + || !$this->uninstallTab() + ) { + return false; + } + + return true; } - public function getBlockNewsletterSubscriber() + public function uninstallTab() { - $rq_sql = 'SELECT `id`, `email`, `newsletter_date_add`, `ip_registration_newsletter` - FROM `'._DB_PREFIX_.'newsletter` - WHERE `active` = 1'; - - if (Context::getContext()->cookie->shopContext) { - $rq_sql .= ' AND `id_shop` = '.(int)Context::getContext()->shop->id; + $moduleTabs = Tab::getCollectionFromModule($this->name); + if (!empty($moduleTabs)) { + foreach ($moduleTabs as $moduleTab) { + $moduleTab->delete(); + } } - $rq = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($rq_sql); - - $header = array('id_customer', 'email', 'newsletter_date_add', 'ip_address', 'http_referer'); - $result = (is_array($rq) ? array_merge(array($header), $rq) : $header); - - return $result; + return true; } } diff --git a/modules/blocknewsletter/controllers/admin/AdminNewsletterController.php b/modules/blocknewsletter/controllers/admin/AdminNewsletterController.php new file mode 100644 index 000000000..2e19512ad --- /dev/null +++ b/modules/blocknewsletter/controllers/admin/AdminNewsletterController.php @@ -0,0 +1,637 @@ +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 = null, $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.'), + ''.$this->l('Cart Rules').'' + ), + '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); + } + + 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; + } + } + } + } + } +} diff --git a/modules/blocknewsletter/controllers/admin/index.php b/modules/blocknewsletter/controllers/admin/index.php new file mode 100644 index 000000000..81057586e --- /dev/null +++ b/modules/blocknewsletter/controllers/admin/index.php @@ -0,0 +1,29 @@ +content_only = true; + } + + public function checkAccess() + { + return strcmp(Tools::getValue('token', ''), $this->module->secure_key) === 0; + } + + public function displayAjaxSubscribeNewsletter() + { + $this->module->newsletterRegistration(); + + $this->context->smarty->assign(array( + 'message_type' => ($this->module->valid && !$this->module->error) ? 'success' : 'error', + 'message' => ($this->module->valid && !$this->module->error) ? $this->module->valid : $this->module->error, + )); + + $response = array( + 'status' => true, + 'message_html' => $this->context->smarty->fetch( + $this->module->getTemplatePath('subscription_execution.tpl') + ), + ); + + $this->ajaxDie(json_encode($response)); + } +} diff --git a/modules/blocknewsletter/controllers/front/verification.php b/modules/blocknewsletter/controllers/front/verification.php index a1950245e..29cbb4be1 100644 --- a/modules/blocknewsletter/controllers/front/verification.php +++ b/modules/blocknewsletter/controllers/front/verification.php @@ -29,14 +29,15 @@ */ class BlocknewsletterVerificationModuleFrontController extends ModuleFrontController { - private $message = ''; - /** * @see FrontController::postProcess() */ public function postProcess() { - $this->message = $this->module->confirmEmail(Tools::getValue('token')); + $this->errors = array_merge( + $this->errors, + $this->module->confirmEmail(Tools::getValue('token')) + ); } /** @@ -44,9 +45,23 @@ public function postProcess() */ public function initContent() { + $this->display_column_left = false; + $this->display_column_right = false; + parent::initContent(); - $this->context->smarty->assign('message', $this->message); $this->setTemplate('verification_execution.tpl'); } + + public function setMedia() + { + parent::setMedia(); + + $this->addCSS($this->module->getPathUri().'views/css/front/verification.css'); + $this->addJS($this->module->getPathUri().'views/js/front/verification.js'); + + Media::addJsDef(array( + 'homepage_url' => $this->context->link->getPageLink('index'), + )); + } } diff --git a/modules/blocknewsletter/export/index.php b/modules/blocknewsletter/export/index.php new file mode 100644 index 000000000..089d93577 --- /dev/null +++ b/modules/blocknewsletter/export/index.php @@ -0,0 +1,29 @@ +name)) - exit; - -$token = Tools::getValue('token'); - -require_once(dirname(__FILE__).'/../../header.php'); -echo $module->confirmEmail($token); -require_once(dirname(__FILE__).'/../../footer.php'); diff --git a/modules/blocknewsletter/views/css/front/index.php b/modules/blocknewsletter/views/css/front/index.php new file mode 100644 index 000000000..b721e4a71 --- /dev/null +++ b/modules/blocknewsletter/views/css/front/index.php @@ -0,0 +1,19 @@ + + + + diff --git a/modules/blocknewsletter/views/templates/admin/newsletter/helpers/list/view-customer-link.tpl b/modules/blocknewsletter/views/templates/admin/newsletter/helpers/list/view-customer-link.tpl new file mode 100644 index 000000000..be0718b96 --- /dev/null +++ b/modules/blocknewsletter/views/templates/admin/newsletter/helpers/list/view-customer-link.tpl @@ -0,0 +1,23 @@ +{** +* 2010-2024 Webkul. +* +* NOTICE OF LICENSE +* +* All right is reserved, +* Please go through LICENSE.txt file inside our module +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade this module to newer +* versions in the future. If you wish to customize this module for your +* needs please refer to CustomizationPolicy.txt file inside our module for more information. +* +* @author Webkul IN +* @copyright 2010-2024 Webkul IN +* @license LICENSE.txt +*} + + + + {l s='View' mod='blocknewsletter'} + diff --git a/modules/blocknewsletter/views/templates/front/subscription_execution.tpl b/modules/blocknewsletter/views/templates/front/subscription_execution.tpl new file mode 100644 index 000000000..9b043738f --- /dev/null +++ b/modules/blocknewsletter/views/templates/front/subscription_execution.tpl @@ -0,0 +1,25 @@ +{** + * 2010-2024 Webkul. + * + * NOTICE OF LICENSE + * + * All right is reserved, + * Please go through LICENSE.txt file inside our module + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade this module to newer + * versions in the future. If you wish to customize this module for your + * needs please refer to CustomizationPolicy.txt file inside our module for more information. + * + * @author Webkul IN + * @copyright 2010-2024 Webkul IN + * @license LICENSE.txt + *} + +{if isset($message_type) && isset($message)} + +{/if} diff --git a/modules/blocknewsletter/views/templates/front/verification_execution.tpl b/modules/blocknewsletter/views/templates/front/verification_execution.tpl index b3b3aff95..33edc1983 100644 --- a/modules/blocknewsletter/views/templates/front/verification_execution.tpl +++ b/modules/blocknewsletter/views/templates/front/verification_execution.tpl @@ -22,4 +22,21 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) * International Registered Trademark & Property of PrestaShop SA *} -{$message} \ No newline at end of file + +{include file="$tpl_dir./errors.tpl"} + +{if !count($errors)} ++ {l s='Thank you for subscribing to our newsletter.' mod='blocknewsletter'} +
+ ++ {l s='You will be redirected to home page in ' mod='blocknewsletter'} + {l s='5' mod='blocknewsletter'} + {l s='seconds.' mod='blocknewsletter'} +
+ + + {l s='Home Page' mod='blocknewsletter'} + +{/if} diff --git a/modules/blocknewsletter/views/templates/hook/blocknewsletter.tpl b/modules/blocknewsletter/views/templates/hook/blocknewsletter.tpl index be560aac7..6954c90c9 100644 --- a/modules/blocknewsletter/views/templates/hook/blocknewsletter.tpl +++ b/modules/blocknewsletter/views/templates/hook/blocknewsletter.tpl @@ -25,15 +25,20 @@' + alert_blocknewsletter + '
'); - $('html, body').animate({scrollTop: $('#columns').offset().top}, 'slow'); - } - - $(".submitNewsletter").on("click", function() - { - var email = $("#newsletter-input").val(); - if (email == "" || !validate_isEmail(email)) - { - $("#newsletter-input").popover({content: email_js_error, placement: "top", container: "body"}); - $("#newsletter-input").popover("show"); - return false; - } - - return true; - }); -}); \ No newline at end of file +}); diff --git a/themes/hotel-reservation-theme/modules/blocknewsletter/blocknewsletter.tpl b/themes/hotel-reservation-theme/modules/blocknewsletter/blocknewsletter.tpl index e902ecbc3..098f0889c 100644 --- a/themes/hotel-reservation-theme/modules/blocknewsletter/blocknewsletter.tpl +++ b/themes/hotel-reservation-theme/modules/blocknewsletter/blocknewsletter.tpl @@ -25,15 +25,20 @@