Files
interblue.pl/modules/amazzingblog/amazzingblog.php
2024-10-25 14:16:28 +02:00

4121 lines
165 KiB
PHP

<?php
/**
* 2007-2017 Amazzing
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
*
* @author Amazzing <mail@amazzing.ru>
* @copyright 2007-2017 Amazzing
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
*/
class AmazzingBlog extends Module
{
public $empty_date = '0000-00-00 00:00:00';
public function __construct()
{
if (!defined('_PS_VERSION_')) {
exit;
}
$this->name = 'amazzingblog';
$this->tab = 'front_office_features';
$this->version = '1.3.1';
$this->author = 'Amazzing';
$this->need_instance = 0;
$this->bootstrap = true;
$this->module_key = '40276b75d9bf50788fddf308cda2ca59';
parent::__construct();
$this->displayName = $this->l('Amazzing blog');
$this->description = $this->l('Blog for PrestaShop');
$this->prepareGlobals();
}
public function prepareGlobals()
{
$this->db = Db::getInstance();
$this->id_lang = $this->context->language->id;
$this->id_shop = $this->context->shop->id;
$this->img_dir = $this->_path.'views/img/uploads/';
$this->img_dir_local = $this->local_path.'views/img/uploads/';
$this->admin_controller = 'AdminBlog';
$this->root_id = 1;
$this->slug = 'blog';
if (Module::isInstalled($this->name)) {
$this->general_settings = $this->getSettings('general');
if ($this->friendly_url = Configuration::get('PS_REWRITING_SETTINGS')) {
$this->defineCustomSlug();
}
}
$this->is_17 = Tools::substr(_PS_VERSION_, 0, 3) === '1.7';
}
public function defineCustomSlug()
{
$this->slug = 'blog';
$this->slug_other_languages = array();
$data = $this->db->executeS('
SELECT link_rewrite, id_lang FROM '._DB_PREFIX_.'a_blog_category_lang
WHERE id_shop = '.$this->id_shop.' AND id_category = '.(int)$this->root_id.'
');
foreach ($data as $d) {
if ($d['id_lang'] == $this->id_lang && $d['link_rewrite']) {
$this->slug = $d['link_rewrite'];
} else {
$this->slug_other_languages[$d['id_lang']] = $d['link_rewrite'];
}
}
}
public function getSettings($type, $force_query = false)
{
if (empty($this->settings[$type]) || $force_query) {
$settings = $this->db->getValue('
SELECT value FROM '._DB_PREFIX_.'a_blog_settings
WHERE name = \''.pSQL($type).'\'
AND id_shop = '.(int)$this->context->shop->id.'
');
$this->settings[$type] = $settings ? Tools::jsonDecode($settings, true) : array();
if (in_array($type, array('post', 'postlist')) && !$this->general_settings['user_comments']) {
$this->settings[$type]['show_comments'] = 0;
}
}
return $this->settings[$type];
}
public function saveSettings($type, $data = array(), $forced_shop_ids = array())
{
if (!$required_settings = $this->getSettingsFields($type)) {
$this->throwError($this->l('Undefined settings type'));
}
$to_save = array();
foreach ($required_settings as $name => $field) {
$to_save[$name] = isset($data[$name]) ? $data[$name] : $field['value'];
if ($name == 'notif_email' && $to_save[$name] && !Validate::isEmail($to_save[$name])) {
$this->throwError($this->l('Please use a correct e-mail'));
}
if ($name == 'avatar' || $type == 'img') {
$value = explode('*', $to_save[$name]);
$w = $value[0];
$h = !empty($value[1]) ? $value[1] : 0;
if (!$w || !$h || !Validate::isInt($w) || !Validate::isInt($h)) {
$this->throwError($this->l('Incorrect format: ').' '.implode('*', $value));
}
$to_save[$name] = $w.'*'.$h;
}
}
$rows = array();
$encoded_data = Tools::jsonEncode($to_save);
$shop_ids = $forced_shop_ids ? $forced_shop_ids : $this->shop_ids;
foreach ($shop_ids as $id_shop) {
$rows[] = '(\''.pSQL($type).'\', '.(int)$id_shop.', \''.pSQL($encoded_data).'\')';
}
if ($rows) {
$this->db->execute('REPLACE INTO '._DB_PREFIX_.'a_blog_settings VALUES '.implode(', ', $rows));
}
return $to_save;
}
public function install()
{
$installed = true;
$this->shop_ids = Shop::getShops(false, null, true);
if (!$this->prepareDatabase()
|| !parent::install()
|| !$this->prepareInitialSettings()
|| !$this->prepareDemoContent()
|| !$this->registerHook('displayHeader')
|| !$this->registerHook('displayBackofficeHeader')
|| !$this->registerHook('displayAdminProductsExtra')
|| !$this->registerHook('actionProductSave')
|| !$this->registerHook('moduleRoutes')
|| !$this->addTabs()
) {
$installed = false;
}
return $installed;
}
public function getTables()
{
$tables = array(
'a_blog_post' => '(
id_post int(10) unsigned NOT NULL AUTO_INCREMENT,
id_category_default int(10) unsigned NOT NULL,
active tinyint(1) NOT NULL DEFAULT 1,
cover varchar(32) NOT NULL,
main_img varchar(32) NOT NULL,
author int(10) NOT NULL,
date_add datetime NOT NULL,
publish_from datetime NOT NULL,
publish_to datetime NOT NULL,
PRIMARY KEY (id_post),
KEY id_category_default (id_category_default),
KEY active (active),
KEY date_add (date_add),
KEY publish_from (publish_from),
KEY publish_to (publish_to),
KEY author (author)
)',
'a_blog_post_stats' => '(
id_post int(10) unsigned NOT NULL,
views int(10) unsigned NOT NULL default 0,
comments int(10) unsigned NOT NULL default 0,
likes int(10) unsigned NOT NULL default 0,
PRIMARY KEY (id_post),
KEY views (views),
KEY comments (comments),
KEY likes (likes)
)',
'a_blog_post_lang' => '(
id_post int(10) unsigned NOT NULL,
id_shop int(10) unsigned NOT NULL,
id_lang int(10) unsigned NOT NULL,
link_rewrite varchar(255) NOT NULL,
title text NOT NULL,
meta_title varchar(255) NOT NULL,
meta_description varchar(255) NOT NULL,
meta_keywords varchar(255) NOT NULL,
content text NOT NULL,
date_upd datetime NOT NULL,
PRIMARY KEY (id_post, id_shop, id_lang),
KEY date_upd (date_upd)
)',
'a_blog_category' => '(
id_category int(10) unsigned NOT NULL AUTO_INCREMENT,
id_parent int(10) unsigned NOT NULL,
active tinyint(1) NOT NULL DEFAULT 1,
level_depth int(10) unsigned NOT NULL,
position int(10) NOT NULL,
date_add datetime NOT NULL,
date_upd datetime NOT NULL,
PRIMARY KEY (id_category),
KEY id_parent (id_parent),
KEY active (active),
KEY date_add (date_add),
KEY date_upd (date_upd)
)',
'a_blog_category_lang' => '(
id_category int(10) unsigned NOT NULL,
id_shop int(10) unsigned NOT NULL,
id_lang int(10) unsigned NOT NULL,
link_rewrite varchar(255) NOT NULL,
title text NOT NULL,
meta_title varchar(255) NOT NULL,
meta_description varchar(255) NOT NULL,
meta_keywords varchar(255) NOT NULL,
description text NOT NULL,
PRIMARY KEY (id_category, id_shop, id_lang)
)',
'a_blog_post_category' => '(
id_category int(10) unsigned NOT NULL,
id_post int(10) unsigned NOT NULL,
position int(10) unsigned NOT NULL,
PRIMARY KEY (id_category, id_post)
)',
'a_blog_tag' => '(
id_tag int(10) unsigned NOT NULL AUTO_INCREMENT,
id_lang int(10) unsigned NOT NULL,
tag_url varchar(64) NOT NULL,
tag_name varchar(64) NOT NULL,
PRIMARY KEY (id_tag),
KEY id_lang (id_lang),
KEY tag_url (tag_url),
KEY tag_name (tag_name)
)',
'a_blog_post_tag' => '(
id_post int(10) unsigned NOT NULL,
id_tag int(10) unsigned NOT NULL,
PRIMARY KEY (id_post, id_tag)
)',
'a_blog_block' => '(
id_block int(10) unsigned NOT NULL AUTO_INCREMENT,
hook_name varchar(64) NOT NULL,
position int(10) unsigned NOT NULL,
active tinyint(1) NOT NULL,
settings text NOT NULL,
PRIMARY KEY (id_block)
)',
'a_blog_block_lang' => '(
id_block int(10) unsigned NOT NULL,
id_shop int(10) unsigned NOT NULL,
id_lang int(10) unsigned NOT NULL,
title text NOT NULL,
PRIMARY KEY (id_block, id_shop, id_lang)
)',
'a_blog_comment' => '(
id_comment int(10) unsigned NOT NULL AUTO_INCREMENT,
id_shop int(10) unsigned NOT NULL,
id_post int(10) unsigned NOT NULL,
id_user int(10) unsigned NOT NULL,
active tinyint(1) NOT NULL DEFAULT 0,
approved_by int(10) unsigned NOT NULL DEFAULT 0,
notif_sent tinyint(1) NOT NULL DEFAULT 0,
content text NOT NULL,
date_add datetime NOT NULL,
date_upd datetime NOT NULL,
ip varchar(32) NOT NULL,
answers text NOT NULL,
PRIMARY KEY (id_comment),
KEY id_post (id_post),
KEY active (active),
KEY ip (ip)
)',
'a_blog_user' => '(
id_user int(10) unsigned NOT NULL AUTO_INCREMENT,
id_guest int(10) unsigned NOT NULL,
user_name text NOT NULL,
avatar text NOT NULL,
PRIMARY KEY (id_user),
KEY id_guest (id_guest)
)',
'a_blog_settings' => '(
name varchar(16) NOT NULL,
id_shop int(10) unsigned NOT NULL,
value text NOT NULL,
PRIMARY KEY (name, id_shop)
)',
'a_blog_hook_settings' => '(
hook_name varchar(64) NOT NULL,
id_shop int(10) unsigned NOT NULL,
exc_type tinyint(1) NOT NULL DEFAULT 1 ,
exc_controllers text NOT NULL,
PRIMARY KEY (hook_name, id_shop)
)',
'a_blog_related_products' => '(
id_post int(10) unsigned NOT NULL,
id_product int(10) unsigned NOT NULL,
position_post int(10) unsigned NOT NULL DEFAULT 0,
position_product int(10) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (id_post, id_product)
)',
);
return $tables;
}
public function prepareDatabase()
{
$sql = array();
$tables = $this->getTables();
foreach ($tables as $k => $query) {
$sql[] = 'CREATE TABLE IF NOT EXISTS `'.bqSQL(_DB_PREFIX_.$k).'` '.$query.'
ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8';
}
return $this->runSql($sql);
}
public function prepareInitialSettings()
{
include_once('classes/BlogFields.php');
$this->fields = new BlogFields();
return $this->saveSettings('general')
&& $this->saveSettings('post')
&& $this->saveSettings('postlist')
&& $this->saveSettings('category')
&& $this->saveSettings('comment')
&& $this->saveSettings('img');
}
public function prepareDemoContent()
{
$prepared = true;
if (!is_file($this->local_path.'defaults/data.zip') ||
!$this->importData($this->local_path.'defaults/data.zip')) {
$root_category_data = array(
'id_category' => $this->root_id,
'active' => 1,
'id_parent' => 0,
'position' => 0,
'multilang' => array(),
);
foreach (Language::getLanguages() as $lang) {
$root_category_data['multilang']['title'][$lang['id_lang']] = $this->l('Blog');
$root_category_data['multilang']['link_rewrite'][$lang['id_lang']] = $this->slug;
$root_category_data['multilang']['description'][$lang['id_lang']] = '';
}
$prepared &= $this->saveCategory($root_category_data);
}
$this->addRelatedBlocksIfRequired();
return $prepared;
}
public function addRelatedBlocksIfRequired()
{
$initial_shop_ids = !empty($this->shop_ids) ? $this->shop_ids : Shop::getContextListShopID();
$this->shop_ids = Shop::getShops(false, null, true);
$id_lang = $this->context->language->id;
$required_block_types = array(
'post_relatedtoproduct' => array(
'hook_name' => 'displayFooterProduct',
'multilang' => array('title' => array($id_lang => $this->l('Related posts'))),
),
'product_relatedtopost' => array(
'hook_name' => 'displayPostFooter',
'multilang' => array('title' => array($id_lang => $this->l('Related products'))),
),
);
$current_blocks = $this->db->executeS('SELECT * FROM '._DB_PREFIX_.'a_blog_block');
foreach ($current_blocks as $b) {
$settings = Tools::jsonDecode($b['settings'], true);
if (isset($settings['type']) && isset($required_block_types[$settings['type']])) {
unset($required_block_types[$settings['type']]);
}
}
$block_fields = $this->fields->getBlockFields();
foreach ($required_block_types as $type => $block_data) {
$block_data['active'] = 1;
$block_data['id_block'] = 0;
// make sure all fields are submitted
foreach ($block_fields as $field_name => $field) {
if (empty($field['multilang'])) {
if (Tools::substr($field_name, 0, 9) === 'carousel_') {
$field_name = str_replace('carousel_', '', $field_name);
$block_data['settings']['carousel'][$field_name] = $field['value'];
} else {
$block_data['settings'][$field_name] = $field['value'];
}
}
}
if ($type == 'product_relatedtopost') {
$block_data['settings']['carousel']['i'] = '5';
$block_data['settings']['carousel']['i_1200'] = '4';
$block_data['settings']['carousel']['i_992'] = '3';
$block_data['settings']['carousel']['i_768'] = '2';
$block_data['settings']['carousel']['i_480'] = '1';
}
$block_data['settings']['exceptions'] = array();
$block_data['settings']['type'] = $type;
$this->saveBlock($block_data);
}
$this->shop_ids = $initial_shop_ids;
}
public function addTabs()
{
$parent_tab = new Tab();
$parent_tab->name = array();
foreach (Language::getLanguages() as $language) {
$parent_tab->name[$language['id_lang']] = $this->l('Blog');
}
$parent_tab->class_name = $this->admin_controller;
$parent_tab->id_parent = 0;
$parent_tab->module = $this->name;
$parent_tab->add();
return true;
}
public function uninstall()
{
$sql = array();
$tables = $this->getTables();
foreach (array_keys($tables) as $name) {
$sql[] = 'DROP TABLE IF EXISTS `'.bqSQL(_DB_PREFIX_.$name).'`';
}
if ($ret = $this->runSql($sql)) {
$this->removeAllImages();
// remove tabs
$tab_id = Tab::getIdFromClassName($this->admin_controller);
$tab = new Tab($tab_id);
$tab->delete();
$ret &= parent::uninstall();
}
return $ret;
}
public function removeAllImages()
{
$this->recursiveRemove($this->img_dir_local.'posts/', true);
$this->recursiveRemove($this->img_dir_local.'categories/', true);
$this->recursiveRemove($this->img_dir_local.'avatars/', true);
}
public function runSql($sql)
{
foreach ($sql as $s) {
if (!$this->db->execute($s)) {
return false;
}
}
return true;
}
public function hookModuleRoutes()
{
$routes = array(
'module-amazzingblog-blog' => array(
'controller' => 'blog',
'rule' => $this->slug.'/{rewrite}',
'keywords' => array('rewrite' => array('regexp' => '[\/\+_a-zA-Z0-9-\pL]*')),
'params' => array('fc' => 'module', 'module' => $this->name),
),
);
return $routes;
}
public function hookDisplayBackOfficeHeader()
{
$this->context->controller->addCSS($this->_path.'views/css/blog-icons.css', 'all');
if (Tools::getValue('configure') == $this->name) {
$this->context->controller->addJquery();
$this->context->controller->addJqueryUI('ui.sortable');
$this->context->controller->addJQueryUI('ui.datetimepicker');
$this->context->controller->addJQueryPlugin('tagify');
$this->context->controller->css_files[$this->_path.'views/css/back.css?'.$this->version] = 'all';
if ($this->is_17) {
$this->context->controller->css_files[$this->_path.'views/css/back-17.css?'.$this->version] = 'all';
}
$this->context->controller->css_files[$this->_path.'views/css/common-classes.css?'.$this->version] = 'all';
$this->context->controller->js_files[] = $this->_path.'views/js/back.js?'.$this->version;
// tinyMCE
$this->context->controller->addJS(__PS_BASE_URI__.'js/tiny_mce/tiny_mce.js');
if (file_exists(_PS_ROOT_DIR_.'/js/admin/tinymce.inc.js')) {
$this->context->controller->addJS(__PS_BASE_URI__.'js/admin/tinymce.inc.js');
} else { // retro-compatibility
$this->context->controller->addJS(__PS_BASE_URI__.'js/tinymce.inc.js');
}
}
if (Tools::getValue('controller') == 'AdminProducts') {
$this->context->controller->addJqueryUI('ui.sortable');
}
}
public function getContent()
{
$this->failed_txt = $this->l('Failed');
$this->saved_txt = $this->l('Saved');
$this->shop_ids = Shop::getContextListShopID();
$this->special_img_types = array(
'cover' => $this->l('cover'),
'main_img' => $this->l('main image')
);
include_once('classes/BlogFields.php');
$this->fields = new BlogFields();
$this->img_settings = $this->getImgSettings();
if (Tools::isSubmit('ajax') && Tools::isSubmit('action')) {
$action_method = 'ajax'.Tools::getValue('action');
$this->$action_method();
}
if (Tools::getValue('action') == 'exportData') {
$this->exportData();
}
$iso = $this->context->language->iso_code;
$mce_additional_css_files = array(
$this->_path.'views/css/mce-styles.css?'.$this->version,
);
if (!$this->is_17) {
$mce_additional_css_files[] = _THEME_CSS_DIR_.'global.css';
// for 1.7 it should be _THEME_CSS_DIR_.'theme.css'
// but for some reason if it is included in content_css,
// mce html and body get hardcoded inline styles overflow-y: hidden
}
$js_strings = array(
'iso' => file_exists(_PS_ROOT_DIR_.'/js/tiny_mce/langs/'.$iso.'.js') ? $iso : 'en',
'mce_additional_css_files' => implode(', ', $mce_additional_css_files),
'ad' => dirname($_SERVER['PHP_SELF']),
'savedTxt' => $this->saved_txt,
'failedTxt' => $this->failed_txt,
'saveFisrt' => $this->l('Please save settings'),
'areYouSureTxt' => $this->l('Are you sure?'),
'ab_ajax_path' => $this->getConfigPagePath().'&ajax=1',
);
$js_vars = array(
'PS_ALLOW_ACCENTED_CHARS_URL' => (int)Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL'),
'specialTypes' => Tools::jsonEncode(array_keys($this->special_img_types)),
'is_17' => (int)$this->is_17,
'id_lang_current' => (int)$this->context->language->id,
);
// plain js for retro-compatibility
$js = '<script type="text/javascript">';
foreach ($js_strings as $name => $value) {
$js .= "\nvar $name = '".$this->escapeApostrophe($value)."';";
}
foreach ($js_vars as $name => $value) {
$js .= "\nvar $name = ".$value.";";
}
$js .= "\n</script>";
$html = $this->displayForm();
// retro-compatibility
$html .= $this->display(__FILE__, 'views/templates/admin/dynamic-modal.tpl');
return $js.$html;
}
public function escapeApostrophe($string)
{
return str_replace("'", "\'", $string);
}
public function exportData()
{
$languages = Language::getLanguages(false);
$all_shop_ids = Shop::getShops(false, null, true);
$lang_id_iso = array();
foreach ($languages as $lang) {
$lang_id_iso[$lang['id_lang']] = $lang['iso_code'];
}
$id_shop_default = Configuration::get('PS_SHOP_DEFAULT');
$id_lang_default = Configuration::get('PS_LANG_DEFAULT');
$tables_to_export = array_keys($this->getTables());
$tables_to_export[] = 'hook_module';
$tables_to_export = array_combine($tables_to_export, $tables_to_export);
if (!$include_comments = Tools::getValue('include_comments')) {
unset($tables_to_export['a_blog_comment']);
unset($tables_to_export['a_blog_user']);
}
if (!$include_related_products = Tools::getValue('include_related_products')) {
unset($tables_to_export['a_blog_related_products']);
}
$export_data = array();
foreach ($tables_to_export as $table_name) {
$ret = array();
$data_from_db = $this->db->executeS('SELECT * FROM `'.bqSQL(_DB_PREFIX_.$table_name).'`');
if (strpos($table_name, '_lang') !== false) {
foreach ($data_from_db as $row) {
$id_shop = $row['id_shop'] == $id_shop_default ? 'ID_SHOP_DEFAULT' : $row['id_shop'];
$iso = $row['id_lang'] == $id_lang_default ? 'LANG_ISO_DEFAULT' : $lang_id_iso[$row['id_lang']];
// if ($id_shop != 'ID_SHOP_DEFAULT' || $iso != 'LANG_ISO_DEFAULT') continue;
$ret[$id_shop][$row[key($row)]][$iso] = $row;
}
} elseif ($table_name == 'a_blog_tag') {
foreach ($data_from_db as $row) {
$iso = $row['id_lang'] == $id_lang_default ? 'LANG_ISO_DEFAULT' : $lang_id_iso[$row['id_lang']];
// if ($iso != 'LANG_ISO_DEFAULT') continue;
$ret[$iso][] = $row;
}
} elseif (in_array($table_name, array('a_blog_settings', 'a_blog_comment'))) {
foreach ($data_from_db as $row) {
$id_shop = $row['id_shop'] == $id_shop_default ? 'ID_SHOP_DEFAULT' : $row['id_shop'];
// if ($id_shop != 'ID_SHOP_DEFAULT') continue;
$ret[$id_shop][] = $row;
}
} elseif ($table_name == 'hook_module') {
foreach ($data_from_db as $row) {
if ($row['id_module'] != $this->id) {
continue;
}
$id_shop = $row['id_shop'] == $id_shop_default ? 'ID_SHOP_DEFAULT' : $row['id_shop'];
// if ($id_shop != 'ID_SHOP_DEFAULT') continue;
$hook_name = Hook::getNameByid($row['id_hook']);
$ret[$id_shop][$hook_name] = $row['position'];
}
} else {
$ret = $data_from_db;
}
if (isset($ret['ID_SHOP_DEFAULT'])) {
foreach ($all_shop_ids as $id_shop) {
if ($id_shop != $id_shop_default && !isset($ret[$id_shop])) {
$ret[$id_shop] = array();
}
}
}
$export_data[$table_name] = $ret;
}
$tmp_zip_file = tempnam($this->local_path.'tmp', 'zip');
$zip = new ZipArchive();
$zip->open($tmp_zip_file, ZipArchive::OVERWRITE);
$zip->addFromString('data.txt', Tools::jsonEncode($export_data));
$this->addToZipRecursively($zip, $this->img_dir_local.'posts/');
$this->addToZipRecursively($zip, $this->img_dir_local.'categories/');
$this->addToZipRecursively($zip, $this->img_dir_local.'avatars/');
$zip->close();
$archive_name = 'backup-'.date('d-m-Y');
if (!$include_comments) {
$archive_name .= '-no-comments';
}
if (!$include_related_products) {
$archive_name .= '-no-related-products';
}
$archive_name .= '.zip';
header('Content-Type: application/zip');
header('Content-Length: '.filesize($tmp_zip_file));
header('Content-Disposition: attachment; filename="'.$archive_name.'"');
readfile($tmp_zip_file);
unlink($tmp_zip_file);
return '';
}
public function addToZipRecursively(&$zip, $dir)
{
$structure = glob(rtrim($dir, '/').'/*');
if (is_array($structure)) {
foreach ($structure as $file) {
if (is_dir($file)) {
$this->addToZipRecursively($zip, $file);
} elseif (is_file($file)) {
$zip->addFile($file, str_replace($this->img_dir_local, 'uploads/', $file));
}
}
}
}
public function ajaxImportData()
{
if ($this->importData()) {
$ret = array('upd_html' => utf8_encode($this->import_response.$this->displayForm()));
} else {
$ret = array('errors' => $this->import_response);
}
exit(Tools::jsonEncode($ret));
}
public function importData($zip_file = false)
{
$tmp_dir = $this->local_path.'tmp/';
$exctracted_contents_dir = $tmp_dir.'uploaded_extracted/';
$tmp_zip_file = $tmp_dir.'uploaded.zip';
if (!$zip_file) {
if (!isset($_FILES['zipped_data'])) {
return $this->clearFilesAndSetError($this->l('File not uploaded'));
}
$uploaded_file = $_FILES['zipped_data'];
$type = $uploaded_file['type'];
$accepted_types = array(
'application/zip',
'application/x-zip-compressed',
'multipart/x-zip',
'application/x-compressed'
);
if (!in_array($type, $accepted_types)) {
return $this->clearFilesAndSetError($this->l('Please upload a valid zip file'));
}
if (!move_uploaded_file($uploaded_file['tmp_name'], $tmp_zip_file)) {
return $this->clearFilesAndSetError($this->failed_txt);
}
} else {
Tools::copy($zip_file, $tmp_zip_file);
}
if (!Tools::ZipExtract($tmp_zip_file, $exctracted_contents_dir)
|| !file_exists($exctracted_contents_dir.'data.txt')) {
return $this->clearFilesAndSetError($this->l('This is not a valid backup file'));
}
$imported_data = Tools::jsonDecode(Tools::file_get_contents($exctracted_contents_dir.'data.txt'), true);
if (!$include_comments = Tools::getValue('include_comments')) {
unset($imported_data['a_blog_comment']);
unset($imported_data['a_blog_user']);
}
if (!Tools::getValue('include_related_products')) {
unset($imported_data['a_blog_related_products']);
}
$languages = Language::getLanguages(false);
$lang_iso_id = array();
foreach ($languages as $lang) {
$lang_iso_id[$lang['iso_code']] = $lang['id_lang'];
}
$id_lang_default = Configuration::get('PS_LANG_DEFAULT');
$shop_ids = Shop::getShops(false, null, true);
$tables = array_keys($this->getTables());
$tables_to_fill = $hooks_data = array();
foreach ($tables as $table_name) {
$rows = array();
if (!isset($imported_data[$table_name])) {
$imported_data[$table_name] = array();
}
if (strpos($table_name, '_lang') !== false) {
foreach ($shop_ids as $id_shop) {
$key = isset($imported_data[$table_name][$id_shop]) ? $id_shop : 'ID_SHOP_DEFAULT';
$data = $imported_data[$table_name][$key];
foreach ($data as $multilang) {
foreach ($lang_iso_id as $iso => $id_lang) {
$key = isset($multilang[$iso]) ? $iso : 'LANG_ISO_DEFAULT';
$lang_row = $multilang[$key];
$lang_row['id_shop'] = $id_shop;
$lang_row['id_lang'] = $id_lang;
$rows[] = $lang_row;
}
}
}
} elseif ($table_name == 'a_blog_tag') {
$data = $imported_data[$table_name];
// tags should be filled only for matching languages
foreach ($data as $iso => $tag_rows) {
if ($iso == 'LANG_ISO_DEFAULT') {
$id_lang = $id_lang_default;
} elseif (isset($lang_iso_id[$iso])) {
$id_lang = $lang_iso_id[$iso];
} else {
$id_lang = false;
}
if ($id_lang) {
foreach ($tag_rows as $tag_row) {
$tag_row['id_lang'] = $id_lang;
$rows[] = $tag_row;
}
}
}
} elseif (in_array($table_name, array('a_blog_settings', 'a_blog_comment'))) {
foreach ($shop_ids as $id_shop) {
$key = isset($imported_data[$table_name][$id_shop]) ? $id_shop : 'ID_SHOP_DEFAULT';
if (isset($imported_data[$table_name][$key])) {
$data = $imported_data[$table_name][$key];
foreach ($data as $row) {
$row['id_shop'] = $id_shop;
$rows[] = $row;
}
}
}
} elseif ($table_name == 'a_blog_post_stats' && !$include_comments) {
foreach ($imported_data[$table_name] as $row) {
$row['comments'] = 0;
$rows[] = $row;
}
} elseif ($table_name == 'a_blog_post') {
foreach ($imported_data[$table_name] as $row) {
// retro compatibility
$row['publish_from'] = isset($row['publish_from']) ? $row['publish_from'] : $row['date_add'];
$row['publish_to'] = isset($row['publish_to']) ? $row['publish_to'] : '';
$rows[] = $row;
}
} else {
$rows = $imported_data[$table_name];
}
$tables_to_fill[$table_name] = $rows;
}
$sql = array();
foreach ($tables_to_fill as $table_name => $rows_to_insert) {
$db_columns = $this->db->executeS('SHOW COLUMNS FROM '._DB_PREFIX_.pSQL($table_name));
$column_names = array();
foreach ($db_columns as $col) {
$column_names[$col['Field']] = $col['Field'];
}
$sql[] = 'TRUNCATE '._DB_PREFIX_.pSQL($table_name);
$rows = array();
foreach ($rows_to_insert as $row) {
$values = array();
foreach ($column_names as $col_name) {
if (!isset($row[$col_name])) {
$err = $this->l('Database tables don\'t match (%s).');
return $this->clearFilesAndSetError(sprintf($err, _DB_PREFIX_.$table_name));
} else {
$value = $row[$col_name];
$allow_html = in_array($col_name, array('content', 'description'));
$value = pSQL((_PS_MAGIC_QUOTES_GPC_ ? addslashes($value) : $value ), $allow_html);
}
$values[] = $value;
}
$rows[] = '(\''.implode('\', \'', $values).'\')';
}
if (!$rows || !$column_names) {
continue;
}
$sql[] = '
REPLACE INTO '._DB_PREFIX_.pSQL($table_name).'
('.implode(', ', array_map('pSQL', $column_names)).')
VALUES '.implode(', ', $rows).'
';
}
if ($imported = $this->runSql($sql)) {
// register hooks
$hooks_to_register = array();
foreach ($imported_data['a_blog_block'] as $b) {
$hooks_to_register[$b['hook_name']] = 1;
}
foreach ($shop_ids as $id_shop) {
foreach (array_keys($hooks_to_register) as $hook_name) {
$this->registerHook($hook_name, array($id_shop));
}
}
$this->removeAllImages();
// upload new images
Tools::ZipExtract($tmp_zip_file, $this->local_path.'views/img/');
unlink($this->local_path.'views/img/data.txt');
// save original shop context, because it will be changed while setting up hooks & positions
$original_shop_context = Shop::getContext();
$original_shop_context_id = null;
if ($original_shop_context == Shop::CONTEXT_GROUP) {
$original_shop_context_id = $this->context->shop->id_shop_group;
} elseif ($original_shop_context == Shop::CONTEXT_SHOP) {
$original_shop_context_id = $this->context->shop->id;
}
if (!empty($imported_data['hook_module'])) {
foreach ($shop_ids as $id_shop) {
$key = isset($imported_data['hook_module'][$id_shop]) ? $id_shop : 'ID_SHOP_DEFAULT';
$hooks_data[$id_shop] = $imported_data['hook_module'][$key];
}
}
foreach ($hooks_data as $id_shop => $hook_list) {
foreach ($hook_list as $hook_name => $position) {
if ($id_shop != $this->context->shop->id) {
Cache::clean('hook_module_list');
Shop::setContext(Shop::CONTEXT_SHOP, $id_shop);
}
$id_hook = Hook::getIdByName($hook_name);
$this->registerHook($hook_name, array($id_shop));
$this->updatePosition($id_hook, 0, $position);
}
}
Shop::setContext($original_shop_context, $original_shop_context_id);
// make sure all settings are properly saved for all shops
$settings = array('general', 'img', 'post', 'postlist', 'category', 'comment');
foreach ($shop_ids as $id_shop) {
foreach ($settings as $type) {
$saved_settings = $this->db->getValue('
SELECT value FROM '._DB_PREFIX_.'a_blog_settings
WHERE name = \''.pSQL($type).'\'
AND id_shop = '.(int)$id_shop.'
');
$saved_settings = Tools::jsonDecode($saved_settings, true);
$this->saveSettings($type, $saved_settings, array($id_shop));
}
}
// update settings data for the new form
$this->general_settings = $this->getSettings('general', true);
$this->import_response = $this->displayConfirmation($this->l('Data was successfully imported'));
} else {
$this->import_response = $this->displayError($this->l('An error occured while importing data'));
}
$this->recursiveRemove($tmp_dir, true);
return $imported;
}
private function displayForm()
{
$available_hooks = $this->getAvailableHooks();
$blocks = $this->getBlocks();
$hooks = array();
foreach ($blocks as $block) {
$hooks[$block['hook_name']] = isset($hooks[$block['hook_name']]) ? $hooks[$block['hook_name']] + 1 : 1;
unset($available_hooks[$block['hook_name']]);
}
arsort($hooks);
$hooks += $available_hooks;
$pagination_settings = array();
foreach (array('post', 'comment') as $resource) {
$pagination_settings[$resource] = $this->getPaginationSettings($resource);
}
$order_by = Tools::getValue('order_by', 'publish_from');
$order_way = Tools::getValue('order_way', 'DESC');
$comment_filters = array(
'id_post' => array(
'label' => $this->l('Filter by post'),
'options' => $this->getFullList('post'),
),
'id_user' => array(
'label' => $this->l('Filter by user'),
'options' => $this->getFullList('user'),
),
'active' => array(
'label' => $this->l('Filter by status'),
'options' => array(
'1' => $this->l('Visible'),
'0' => $this->l('Hidden'),
),
),
);
$this->context->smarty->assign(array(
'languages' => Language::getLanguages(false),
'id_lang_current' => $this->id_lang,
'posts' => $this->getPostListInfos($pagination_settings['post'], $order_by, $order_way),
'total_posts_num' => $pagination_settings['post']['total'],
'order_by' => $order_by,
'order_way' => $order_way,
'pagination_posts' => $this->renderPagination($pagination_settings['post']),
'sorted_categories' => $this->getSortedCategories(),
'total_cats_num' => $this->getTotal('category'),
'authors' => $this->getAuthorOptions(),
'root_id' => $this->root_id,
'comments' => $this->getCommentListInfos($pagination_settings['comment'], 'date_add', 'DESC'),
'total_comments_num' => $pagination_settings['comment']['total'],
'comment_filters' => $comment_filters,
'pagination_comments' => $this->renderPagination($pagination_settings['comment']),
'new_comments_num' => $this->getTotal('comment', array('approved_by' => '0')),
'settings_types' => array(
'post' => $this->l('Post page'),
'postlist' => $this->l('Post list'),
'category' => $this->l('Category page'),
'comment' => $this->l('Comments'),
'img' => $this->l('Images'),
'general' => $this->l('General'),
),
'avatars_dir' => $this->img_dir.'avatars/',
'hooks' => $hooks,
'blocks' => $blocks,
'id_lang_current' => $this->id_lang,
'img_settings' => $this->img_settings,
'sorting_options' => $this->getSortingOptions(),
'tags_options' => $this->getTagsOptions(),
'state_options' => $this->getStateOptions(),
'documentation_link' => $this->_path.'readme_en.pdf',
'info_links' => array(
'changelog' => $this->_path.'Readme.md?v='.$this->version,
'documentation' => $this->_path.'readme_en.pdf?v='.$this->version,
'contact' => 'https://addons.prestashop.com/en/contact-us?id_product=22905',
'modules' => 'http://addons.prestashop.com/en/2_community-developer?contributor=64815',
),
'files_update_warnings' => $this->getFilesUpdadeWarnings(),
'blog' => $this,
));
return $this->display(__FILE__, 'views/templates/admin/configure.tpl');
}
public function getFilesUpdadeWarnings()
{
$warnings = $customizable_layout_files = array();
$locations = array(
'/css/' => 'css',
'/js/' => 'js',
'/templates/admin/' => 'tpl',
'/templates/hook/' => 'tpl',
'/templates/front/' => 'tpl',
);
foreach ($locations as $loc => $ext) {
$loc = 'views'.$loc;
$files = glob($this->local_path.$loc.'*.'.$ext);
foreach ($files as $file) {
$customizable_layout_files[] = '/'.$loc.basename($file);
}
}
foreach ($customizable_layout_files as $file) {
$ext = pathinfo($file, PATHINFO_EXTENSION);
if ($this->is_17) {
$customized_file_path = _PS_THEME_DIR_.'modules/'.$this->name.$file;
} else {
$customized_file_path = _PS_THEME_DIR_.($ext != 'tpl' ? $ext.'/' : '').'modules/'.$this->name.$file;
}
if (file_exists($customized_file_path)) {
$original_file_path = $this->local_path.$file;
$original_rows = file($original_file_path);
$original_identifier = trim(array_pop($original_rows));
$customized_rows = file($customized_file_path);
$customized_identifier = trim(array_pop($customized_rows));
if ($original_identifier != $customized_identifier) {
$warnings[$file] = $original_identifier;
}
}
}
return $warnings;
}
public function getAuthorOptions()
{
$authors_data = $this->db->executeS('
SELECT e.id_employee AS author, e.firstname, e.lastname FROM '._DB_PREFIX_.'employee e
');
$options = array();
foreach ($authors_data as $a) {
$options[$a['author']] = $a['firstname'].' '.$a['lastname'];
}
return $options;
}
public function getFullList($resource = 'post')
{
$sorted_list = array();
$data = array();
switch ($resource) {
case 'post':
$query = '
SELECT p.id_post AS id, pl.title as name
FROM '._DB_PREFIX_.'a_blog_comment c
LEFT JOIN '._DB_PREFIX_.'a_blog_post p ON p.id_post = c.id_post
LEFT JOIN '._DB_PREFIX_.'a_blog_post_lang pl ON pl.id_post = p.id_post
WHERE c.id_shop IN ('.implode(', ', array_map('intval', $this->shop_ids)).')
AND pl.id_lang = '.(int)$this->id_lang.'
';
break;
case 'user':
$query = '
SELECT c.id_user AS id, u.user_name as name
FROM '._DB_PREFIX_.'a_blog_comment c
LEFT JOIN '._DB_PREFIX_.'a_blog_user u ON u.id_user = c.id_user
WHERE id_shop IN ('.implode(', ', array_map('intval', $this->shop_ids)).')
';
break;
}
$data = $this->db->executeS($query);
foreach ($data as $d) {
$sorted_list[$d['id']] = $d['name'];
}
return $sorted_list;
}
public function getTotal($resource = 'post', $additional_filters = array())
{
$query = '';
$imploded_shop_ids = empty($this->shop_ids) ? $this->context->shop->id : implode(', ', $this->shop_ids);
switch ($resource) {
case 'post':
case 'category':
$identifier = 'id_'.$resource;
$query = new DbQuery();
$query->select('COUNT(DISTINCT main.'.pSQL($identifier).')');
$query->from('a_blog_'.pSQL($resource), 'main');
$query->innerJoin(
'a_blog_'.pSQL($resource).'_lang',
'lang',
'lang.'.pSQL($identifier).' = main.'.pSQL($identifier)
);
if ($resource == 'post') {
$this->addDateAndStateAssociation($query, $additional_filters, 'main');
$this->addJoinFiltersAssociation($query, $additional_filters, 'main');
}
foreach ($additional_filters as $name => $value) {
if ($value != '-') {
$query->where('main.'.pSQL($name).' = \''.pSQL($value).'\'');
}
}
$query->where('lang.id_shop IN ('.pSQL($imploded_shop_ids).')');
break;
case 'comment':
$query = new DbQuery();
$query->select('COUNT(DISTINCT c.id_comment)');
$query->from('a_blog_comment', 'c');
$query->innerJoin('a_blog_post', 'p', 'c.id_post = p.id_post');
$query->where('c.id_shop IN ('.pSQL($imploded_shop_ids).')');
foreach ($additional_filters as $name => $value) {
if ($value != '-') {
$query->where('c.'.pSQL($name).' = \''.pSQL($value).'\'');
}
}
break;
}
$num = $query ? $this->db->getValue($query) : 0;
return $num;
}
public function addJoinFiltersAssociation($query, &$additional_filters, $alias = 'p')
{
$join_filters = array('id_category', 'id_tag');
foreach ($join_filters as $col_name) {
if (!empty($additional_filters[$col_name]) &&
(int)$additional_filters[$col_name]) {
if (!is_array($additional_filters[$col_name])) {
$additional_filters[$col_name] = array($additional_filters[$col_name]);
}
$ids = implode(', ', array_map('intval', $additional_filters[$col_name]));
$table_name = str_replace('id_', '', $col_name);
$join_str = pSQL($alias).'.id_post = '.pSQL($table_name).'.id_post
AND '.pSQL($table_name).'.'.pSQL($col_name).' IN ('.pSQL($ids).')';
$query->innerJoin(
'a_blog_post_'.pSQL($table_name),
pSQL($table_name),
$join_str
);
unset($additional_filters[$col_name]);
}
}
}
public function addDateAndStateAssociation($query, &$additional_filters = array(), $alias = 'p')
{
$now = date('Y-m-d H:i:s');
if (in_array($this->context->controller->controller_type, array('front', 'modulefront'))) {
$this->onlyPublishedAssociation($query, $alias, $now);
} else {
$query->select('DATEDIFF('.pSQL($alias).'.publish_from, \''.pSQL($now).'\') AS days_before_publish');
$query->select('DATEDIFF(\''.pSQL($now).'\', '.pSQL($alias).'.publish_to) AS days_expired');
if (!empty($additional_filters['state']) && $additional_filters['state'] != '-') {
switch ($additional_filters['state']) {
case 'visible':
$query->where(pSQL($alias).'.active = 1');
break;
case 'hidden':
$query->where(pSQL($alias).'.active = 0');
break;
case 'published':
$this->onlyPublishedAssociation($query, $alias, $now);
break;
case 'not_published_yet':
$query->where(pSQL($alias).'.publish_from > \''.pSQL($now).'\'');
break;
case 'expired':
$query->where(pSQL($alias).'.publish_to <> \''.pSQL($this->empty_date).'\'');
$query->where(pSQL($alias).'.publish_to < \''.pSQL($now).'\'');
break;
}
}
unset($additional_filters['state']);
}
}
public function onlyPublishedAssociation($query, $alias = 'p', $now = false)
{
$now = !$now ? date('Y-m-d H:i:s') : $now;
$query->where(pSQL($alias).'.publish_from <= \''.pSQL($now).'\'');
$query->where(pSQL($alias).'.publish_to = \''.pSQL($this->empty_date).'\'
OR '.pSQL($alias).'.publish_to >= \''.pSQL($now).'\'');
}
public function getPaginationSettings($resource = 'post', $additional_filters = array(), $forced_page = false)
{
if ($npp = Tools::getValue('npp')) {
$this->context->cookie->__set('ab_user_npp', $npp);
} elseif (!empty($this->context->cookie->ab_user_npp)) {
$npp = $this->context->cookie->ab_user_npp;
} else {
$npp = 10;
}
$settings = array(
'p' => $forced_page ? $forced_page : Tools::getValue('p', 1),
'total' => Tools::getValue('total', $this->getTotal($resource, $additional_filters)),
'npp' => $npp,
'npp_options' => $this->getNppOptions(),
);
return $settings;
}
public function getNppOptions()
{
return array(5 => 5, 10 => 10, 20 => 20, 100 => 100);
}
public function getSortingOptions()
{
$options = array(
'p.id_post' => $this->l('ID'),
'date_add' => $this->l('Date added'),
'date_upd' => $this->l('Date modified'),
'publish_from' => $this->l('Publication date'),
'views' => $this->l('Views'),
'comments' => $this->l('Comments'),
'position' => $this->l('Position'),
// 'pl.title' => $this->l('Title'),
);
return $options;
}
public function getStateOptions()
{
$options = array(
'visible' => $this->l('Visible'),
'hidden' => $this->l('Hidden'),
'published' => $this->l('Published'),
'not_published_yet' => $this->l('Not published yet'),
'expired' => $this->l('Expired'),
);
return $options;
}
public function getTagsOptions()
{
$options = $lang_id_iso = array();
$lang_data = $this->db->executeS('SELECT id_lang, iso_code FROM '._DB_PREFIX_.'lang');
foreach ($lang_data as $ld) {
$lang_id_iso[$ld['id_lang']] = $ld['iso_code'];
}
$all_tags = $this->db->executeS('
SELECT * FROM '._DB_PREFIX_.'a_blog_tag t
INNER JOIN '._DB_PREFIX_.'a_blog_post_tag pt
ON pt.id_tag = t.id_tag
');
foreach ($all_tags as $t) {
$id_lang = $t['id_lang'];
$iso_code = isset($lang_id_iso[$id_lang]) ? $lang_id_iso[$id_lang] : '--';
$options[$iso_code][$t['id_tag']] = $t['tag_name'];
}
return $options;
}
public function renderPagination($settings)
{
$this->context->smarty->assign(array(
'settings' => $settings
));
return $this->display(__FILE__, 'views/templates/front/pagination.tpl');
}
public function getCommentListInfos(
$pagination_settings,
$order_by,
$order_way,
$additional_filters = array(),
$id_comment = false
) {
if ($pagination_settings['npp'] == 'all') {
$pagination_settings['npp'] = $pagination_settings['total'];
}
$query = new DbQuery();
$query->select('c.*, u.*, bpl.title AS post_title, e.firstname AS approved_by_name');
$query->from('a_blog_comment', 'c');
$query->leftJoin('a_blog_user', 'u', 'u.id_user = c.id_user');
$query->leftJoin('a_blog_post_lang', 'bpl', 'bpl.id_post = c.id_post AND bpl.id_shop = c.id_shop');
$query->leftJoin('employee', 'e', 'e.id_employee = c.approved_by');
$query->where('bpl.id_lang = '.(int)$this->id_lang);
$query->where('c.id_shop IN ('.implode(', ', $this->shop_ids).')');
foreach ($additional_filters as $name => $value) {
if ($value != '-') {
$query->where('c.'.$name.' = '.(int)$value);
}
}
if ($id_comment) {
$query->where('c.id_comment = '.(int)$id_comment);
}
$query->orderBy('approved_by ASC, '.pSQL($order_by).' '.pSQL($order_way));
if (!$id_comment) {
$limit = $pagination_settings['npp'];
$offset = ($pagination_settings['p'] - 1) * $pagination_settings['npp'];
$query->limit($limit, $offset);
}
$comments = $id_comment ? $this->db->getRow($query) : $this->db->executeS($query);
return $comments;
}
public function ajaxDisplayListItems()
{
$resource = Tools::getValue('resource');
$additional_filters = $this->unserialize(Tools::getValue('filters'));
$pagination_settings = $this->getPaginationSettings($resource, $additional_filters);
$pagination_html = $this->renderPagination($pagination_settings);
$order_by = Tools::getValue('order_by', 'publish_from');
$order_way = Tools::getValue('order_way', 'DESC');
$items = array();
switch ($resource) {
case 'post':
$items = $this->getPostListInfos($pagination_settings, $order_by, $order_way, $additional_filters);
break;
case 'comment':
$items = $this->getCommentListInfos($pagination_settings, 'date_add', 'DESC', $additional_filters);
break;
}
$items_html = '';
$smarty_array = array(
'blog' => $this,
'order_by' => $order_by,
'order_way' => $order_way,
);
if ($resource == 'comment') {
$smarty_array['avatars_dir'] = $this->img_dir.'avatars/';
$smarty_array['blog'] = $this;
}
foreach ($items as $item) {
$smarty_array[$resource] = $item;
$this->context->smarty->assign($smarty_array);
$items_html .= $this->display(__FILE__, 'views/templates/admin/'.$resource.'-form.tpl');
}
if (!$items_html) {
$items_html = $this->display(__FILE__, 'views/templates/admin/no-items.tpl');
}
$ret = array(
'items_html' => utf8_encode($items_html),
'total' => $pagination_settings['total'],
'pagination_html' => utf8_encode($pagination_html),
);
exit(Tools::jsonEncode($ret));
}
public function ajaxUpdatePostPositions()
{
$id_post = Tools::getValue('id_post');
$id_cat = Tools::getValue('id_cat');
$new_position = Tools::getValue('new_position');
$p = Tools::getValue('p');
$npp = Tools::getValue('npp');
$order_way = Tools::getValue('order_way');
$saved = $this->updatePostPositions($id_post, $id_cat, $new_position, $order_way, $p, $npp);
exit(Tools::jsonEncode(array('saved' => $saved)));
}
public function updatePostPositions($id_post, $id_cat, $new_position, $order_way = 'ASC', $p = 1, $npp = 0)
{
$posts = $this->db->executeS('
SELECT * FROM '._DB_PREFIX_.'a_blog_post_category
WHERE id_category = '.(int)$id_cat.'
ORDER BY position '.pSQL($order_way).'
');
$ordered = array();
$key = 0;
foreach ($posts as $k => $post) {
if ($post['id_post'] == 0) {
$this->db->execute('
DELETE FROM '._DB_PREFIX_.'a_blog_post_category WHERE id_post = 0
');
} else {
$ordered[] = $post['id_post'];
if ($post['id_post'] == $id_post) {
$key = $k;
}
}
}
$position_global = (($p - 1) * (int)$npp) + $new_position;
$out = array_splice($ordered, $key, 1);
array_splice($ordered, $position_global - 1, 0, $out);
$saved = true;
if ($ordered) {
$i = 1;
$upd_rows = array();
foreach ($ordered as $id_post) {
$upd_rows[] = '('.(int)$id_cat.', '.(int)$id_post.', '.(int)$i++.')';
}
$saved &= $this->db->execute('
REPLACE INTO '._DB_PREFIX_.'a_blog_post_category
VALUES '.implode(', ', $upd_rows).'
');
}
return $saved;
}
public function getImgSettings()
{
$fields = $this->fields->getImgSettingsFields();
$saved_settings = $this->getSettings('img');
if (is_array($saved_settings)) {
foreach ($saved_settings as $name => $value) {
if (isset($fields[$name])) {
$fields[$name]['value'] = $value;
}
}
}
return $fields;
}
public function getImgSrc($resource_type, $id, $size, $img_name)
{
$src = '';
$dir = $resource_type == 'category' ? 'categories' : 'posts';
$path = $dir.'/'.$id.'/'.$size.'/'.$img_name;
if (is_file($this->img_dir_local.$path)) {
$src = $this->img_dir.$path;
}
return $src;
}
public function getPostListInfos($pagination_settings, $order_by, $order_way, $additional_filters = array())
{
if ($order_by == 'position') {
$order_way = 'ASC';
}
if ($pagination_settings['npp'] == 'all') {
$pagination_settings['npp'] = $pagination_settings['total'];
}
$query = new DbQuery();
$query->select('p.*, pl.*, ps.views, ps.comments, ps.likes, cl.title AS cat_title, e.firstname, e.lastname');
$query->from('a_blog_post', 'p');
$query->leftJoin('a_blog_post_lang', 'pl', 'p.id_post = pl.id_post');
$query->leftJoin('a_blog_post_stats', 'ps', 'p.id_post = ps.id_post');
$query->leftJoin('a_blog_category_lang', 'cl', 'p.id_category_default = cl.id_category');
$query->leftJoin('employee', 'e', 'p.author = e.id_employee');
if (!empty($additional_filters['author']) && (int)$additional_filters['author']) {
$query->where('p.author = '.(int)$additional_filters['author']);
}
if (!empty($additional_filters['active'])) {
$query->where('p.active = '.(int)$additional_filters['active']);
}
if (!empty($additional_filters['post_ids'])) {
$query->where('p.id_post IN ('.pSQL($additional_filters['post_ids'].')'));
}
$query->where('pl.id_lang = '.(int)$this->id_lang);
if (!empty($this->shop_ids)) {
$query->where('pl.id_shop IN ('.implode(', ', $this->shop_ids).')');
} else {
$query->where('pl.id_shop = '.(int)$this->context->shop->id);
}
$this->addDateAndStateAssociation($query, $additional_filters);
$this->addJoinFiltersAssociation($query, $additional_filters);
$query->groupBy('pl.id_post');
$query->orderBy(pSQL($order_by).' '.pSQL($order_way));
$limit = $pagination_settings['npp'];
$offset = ($pagination_settings['p'] - 1) * $pagination_settings['npp'];
$query->limit($limit, $offset);
$posts = $this->db->executeS($query);
foreach ($posts as &$p) {
$p['tags'] = $this->getPostTags($p['id_post'], $this->id_lang, false);
}
return $posts;
}
public function getCategoryListInfos($settings)
{
if ($settings['type'] == 'c_selected') {
$imploded_ids = $this->formatIDs($settings['cat_ids']);
} elseif ($settings['type'] == 'c_children') {
$imploded_parent_ids = $this->formatIDs($settings['parent_ids']);
if (!$imploded_parent_ids) {
$imploded_parent_ids = $this->root_id;
}
}
$id_lang = $this->context->language->id;
$id_shop = $this->context->shop->id;
$categories = $this->db->executeS('
SELECT * FROM '._DB_PREFIX_.'a_blog_category c
INNER JOIN '._DB_PREFIX_.'a_blog_category_lang cl
ON cl.id_category = c.id_category AND cl.id_lang = '.(int)$id_lang.' AND cl.id_shop = '.(int)$id_shop.'
WHERE c.active = 1 AND c.id_category <> '.(int)$this->root_id.
(!empty($imploded_ids) ? ' AND c.id_category IN ('.pSQL($imploded_ids).')' : '').
(!empty($imploded_parent_ids) ? ' AND c.id_parent IN ('.pSQL($imploded_parent_ids).')' : '').'
');
foreach ($categories as &$c) {
$c['id'] = $c['id_category'];
$c['url'] = $this->getCategoryLink($c['id_category'], $c['link_rewrite']);
// $c['img'] = ...
}
return $categories;
}
public function getProductListInfos($ids, $settings)
{
if (!$imploded_ids = $this->formatIDs(implode(',', $ids))) {
return array();
}
if (!$this->is_17 && Configuration::get('PS_CATALOG_MODE')) {
$settings['price'] = $settings['add_to_cart'] = 0;
}
$id_lang = $this->context->language->id;
$id_shop = $this->context->shop->id;
$show_cat = !empty($settings['product_cat']);
$show_man = !empty($settings['product_man']);
$products_infos = array();
$now = date('Y-m-d H:i:s');
$nb_days_new = Configuration::get('PS_NB_DAYS_NEW_PRODUCT');
$query_order_by = '';
if ($settings['product_order_by'] == 'date_add' || $settings['product_order_by'] == 'date_upd') {
$query_order_by = 'ORDER BY product_shop.'.$settings['product_order_by'].' DESC';
} elseif ($settings['product_order_by'] == 'random') {
shuffle($ids);
}
$products_data = $this->db->executeS('
SELECT p.*, product_shop.*, pl.*, image.id_image, il.legend,
'.($show_cat ? 'cl.name AS cat_name, cl.link_rewrite as cat_link_rewrite, ' : '').'
'.($show_man ? 'm.name AS man_name, ' : '').'
DATEDIFF(\''.pSQL($now).'\', p.date_add) < '.(int)$nb_days_new.' AS new
FROM '._DB_PREFIX_.'product p
'.Shop::addSqlAssociation('product', 'p').'
INNER JOIN '._DB_PREFIX_.'product_lang pl
ON (pl.id_product = p.id_product
AND pl.id_shop = '.(int)$id_shop.' AND pl.id_lang = '.(int)$id_lang.')
'.($show_cat ? '
LEFT JOIN '._DB_PREFIX_.'category_lang cl
ON (cl.id_category = product_shop.id_category_default
AND cl.id_shop = '.(int)$id_shop.' AND cl.id_lang = '.(int)$id_lang.')
' : '').'
'.($show_man ? '
LEFT JOIN '._DB_PREFIX_.'manufacturer m
ON m.id_manufacturer = p.id_manufacturer AND m.active = 1
' : '').'
LEFT JOIN '._DB_PREFIX_.'image image
ON (image.id_product = p.id_product AND image.cover = 1)
LEFT JOIN '._DB_PREFIX_.'image_lang il
ON (il.id_image = image.id_image AND il.id_lang = '.(int)$id_lang.')
WHERE p.id_product IN ('.pSQL($imploded_ids).')
'.($query_order_by ? pSQL($query_order_by) : '').'
');
$second_images = array();
if (!empty($settings['second_image'])) {
$second_images_data = $this->db->executeS('
SELECT i.id_product, i.id_image
FROM '._DB_PREFIX_.'image i
'.Shop::addSqlAssociation('image', 'i').'
WHERE i.id_product IN ('.pSQL($imploded_ids).')
AND i.cover IS NULL
GROUP BY i.id_product
');
foreach ($second_images_data as $d) {
$second_images[$d['id_product']] = $d['id_image'];
}
}
$positions = array_flip($ids);
foreach ($products_data as $pd) {
$id = $pd['id_product'];
$pd = Product::getProductProperties($id_lang, $pd);
if ($this->is_17) {
$pd = $this->presentProduct($pd);
unset($pd['flags']['discount']);
} else {
// retro-compatibility
$pd['url'] = $pd['link'];
$pd['flags'] = array();
if (!empty($pd['new'])) {
$pd['flags']['new'] = array('type' => 'new', 'label' => $this->l('New'));
}
$pd['has_discount'] = !empty($pd['specific_prices']['reduction']);
$pd['discount_type'] = $pd['specific_prices']['reduction_type'];
$pd['discount_amount'] = $pd['specific_prices']['reduction'];
if ($pd['discount_type'] == 'percentage') {
$pd['discount_percentage'] = '-'.($pd['discount_amount'] * 100).'%';
} else {
$pd['discount_amount'] = Tools::displayPrice($pd['discount_amount']);
}
$pd['regular_price'] = Tools::displayPrice($pd['price_without_reduction']);
$pd['price'] = Tools::displayPrice($pd['price']);
}
if ($pd['has_discount']) {
$pd['discount_value'] = '-'.ltrim($pd['discount_'.$pd['discount_type']], '-');
}
$image_type = $settings['product_img_type'] != 'original' ? $settings['product_img_type'] : null;
$link_rewrite = $pd['link_rewrite'];
$pd['img_src'] = $this->context->link->getImageLink($link_rewrite, $pd['id_image'], $image_type);
if (!empty($second_images[$id])) {
$src = $this->context->link->getImageLink($link_rewrite, $second_images[$id], $image_type);
$pd['second_img_src'] = $src;
}
if ($show_man && !empty($pd['id_manufacturer'])) {
$alias = Tools::str2url($pd['man_name']);
$pd['man_url'] = $this->getItemUrl('manufacturer', $pd['id_manufacturer'], $alias);
if ($show_man != 1) {
$pd['man_img_src'] = $this->getImageUrl('manufacturer', $pd['id_manufacturer'], $show_man);
}
}
if ($show_cat && !empty($pd['id_category_default'])) {
$pd['cat_url'] = $this->getItemUrl('category', $pd['id_category_default'], $pd['cat_link_rewrite']);
}
$products_infos[$positions[$id]] = $pd;
}
if (!$query_order_by) {
ksort($products_infos);
}
return $products_infos;
}
public function presentProduct($product_data)
{
if (!isset($this->factory_presenter)) {
$factory = new ProductPresenterFactory($this->context, new TaxConfiguration());
$this->factory_presenter = $factory->getPresenter();
$this->factory_settings = $factory->getPresentationSettings();
}
return $this->factory_presenter->present($this->factory_settings, $product_data, $this->context->language);
}
public function getItemUrl($item_type, $id, $alias = null)
{
$url = '#';
$method = 'get'.Tools::ucfirst($item_type).'Link';
if (is_callable(array($this->context->link, $method))) {
$url = $this->context->link->$method($id, $alias);
}
return $url;
}
public function getImageUrl($resource_type, $id, $image_type)
{
if ($image_type == '--') {
return false;
}
$first_char = Tools::substr($resource_type, 0, 1);
$local_dir = _PS_IMG_DIR_.$first_char.'/';
$dir = _PS_IMG_.$first_char.'/';
$img = $id.($image_type != 'original' ? '-'.$image_type : '').'.jpg';
$default_img = $this->context->language->iso_code.'-default-'.$image_type.'.jpg';
return file_exists($local_dir.$img) ? $dir.$img : $dir.$default_img;
}
public function getAvailableHooks()
{
$methods = get_class_methods(__CLASS__);
$methods_to_exclude = array('hookDisplayBackOfficeHeader', 'hookDisplayHeader',
'hookDisplayAdminProductsExtra');
$available_hooks = array();
foreach ($methods as $m) {
if (Tools::substr($m, 0, 11) === 'hookDisplay' && !in_array($m, $methods_to_exclude)) {
$available_hooks[str_replace('hookDisplay', 'display', $m)] = 0;
}
}
// ksort($available_hooks);
return $available_hooks;
}
public function getBlocks()
{
$blocks = $this->db->executeS('
SELECT * FROM '._DB_PREFIX_.'a_blog_block b
LEFT JOIN '._DB_PREFIX_.'a_blog_block_lang bl ON bl.id_block = b.id_block
WHERE id_lang = '.(int)$this->id_lang.'
AND id_shop IN ('.implode(', ', array_map('intval', $this->shop_ids)).')
GROUP BY b.id_block
');
foreach ($blocks as &$b) {
$settings = Tools::jsonDecode($b['settings'], true);
if (!empty($settings['exceptions'])) {
$b['exc_note'] = $this->getExceptionsNote($settings['exceptions']);
}
}
return $blocks;
}
public function getSortedCategories()
{
$result = $this->db->executeS('
SELECT * FROM '._DB_PREFIX_.'a_blog_category c
LEFT JOIN '._DB_PREFIX_.'a_blog_category_lang cl
ON c.id_category = cl.id_category
WHERE id_lang = '.(int)$this->id_lang.'
AND id_shop IN ('.implode(', ', array_map('intval', $this->shop_ids)).')
GROUP BY c.id_category
');
$sorted_categories = array();
foreach ($result as $r) {
$sorted_categories[$r['id_parent']][] = $r;
}
return $sorted_categories;
}
public function ajaxToggleParam()
{
$resource = Tools::strtolower(Tools::getValue('resource'));
$param_name = Tools::getValue('param_name');
$param_value = Tools::getValue('param_value');
if ($param_name == 'approved_by') {
$param_value = $this->context->employee->id;
}
$table_name = _DB_PREFIX_.'a_blog_'.$resource;
$id = Tools::getValue('id');
$identifier = 'id_'.$resource;
if (!$param_name || !$resource) {
$this->throwError($this->l('Parameters not provided correctly'));
}
$update_query = '
UPDATE '.bqSQL($table_name).'
SET '.bqSQL($param_name).' = '.(int)$param_value.'
WHERE '.bqSQL($identifier).' = '.(int)$id.'
';
$ret = array('success' => $this->db->execute($update_query));
if ($resource == 'comment') {
$ret['updated_html'] = utf8_encode($this->renderCommentAdmin($id));
}
exit(Tools::jsonEncode($ret));
}
public function renderCommentAdmin($id_comment)
{
$pagination_settings = $this->getPaginationSettings('comment');
$comment = $this->getCommentListInfos($pagination_settings, 'date_add', 'DESC', array(), $id_comment);
$this->context->smarty->assign(array(
'comment' => $comment,
'avatars_dir' => $this->img_dir.'avatars/',
'blog' => $this,
));
return $this->display(__FILE__, 'views/templates/admin/comment-form.tpl');
}
public function ajaxCallBlockForm()
{
$id_block = Tools::getValue('id');
$hook_name = Tools::getValue('hook_name');
$full = Tools::getValue('full');
$ret = array(
'form' => utf8_encode($this->callBlockForm($id_block, $hook_name, $full)),
);
exit(Tools::jsonEncode($ret));
}
public function callBlockForm($id_block, $hook_name, $full)
{
$block_data = $this->db->getRow('
SELECT * FROM '._DB_PREFIX_.'a_blog_block
WHERE id_block = '.(int)$id_block.'
');
$block_data_lang = $this->db->executeS('
SELECT * FROM '._DB_PREFIX_.'a_blog_block_lang
WHERE id_block = '.(int)$id_block.'
AND id_shop = '.(int)$this->context->shop->id.'
');
$block = array(
'id_block' => (int)$id_block,
'active' => 1,
'hook_name' => $hook_name,
'editable_fields' => $this->fields->getBlockFields(),
);
if ($id_block && $block_data) {
$translatable_fields = array();
foreach (array_keys($block) as $name) {
if (isset($block_data[$name])) {
$block[$name] = $block_data[$name];
}
}
$settings = Tools::jsonDecode($block_data['settings'], true);
foreach ($block['editable_fields'] as $name => &$field) {
if (!isset($field['multilang'])) {
if (Tools::substr($name, 0, 9) === 'carousel_') {
$name = str_replace('carousel_', '', $name);
$field['value'] = $settings['carousel'][$name];
} elseif (Tools::substr($name, 0, 8) === 'related_') {
$name = str_replace('related_', '', $name);
$field['value'] = $settings['related'][$name];
} elseif (Tools::substr($name, 0, 11) === 'exceptions_') {
$name = explode('_', $name);
if (isset($settings[$name[0]][$name[1]][$name[2]])) {
$field['value'] = $settings[$name[0]][$name[1]][$name[2]];
}
} elseif (isset($settings[$name])) {
$field['value'] = $settings[$name];
}
} elseif (isset($field['multilang'])) {
$translatable_fields[] = $name;
}
}
foreach ($block_data_lang as $bdl) {
foreach ($translatable_fields as $field_name) {
if (isset($bdl[$field_name])) {
$block['editable_fields'][$field_name]['value'][$bdl['id_lang']] = $bdl[$field_name];
}
}
}
}
if (!$id_block) {
if ($this->isColumnHook($hook_name)) {
$block['editable_fields']['compact']['value'] = 1;
$block['editable_fields']['show_tags']['value'] = 0;
}
if ($hook_name == 'displayPostFooter') {
$block['editable_fields']['type']['value'] = 'product_relatedtopost';
$block['editable_fields']['carousel_i']['value'] = '5';
$block['editable_fields']['carousel_i_1200']['value'] = '4';
$block['editable_fields']['carousel_i_992']['value'] = '3';
$block['editable_fields']['carousel_i_768']['value'] = '2';
$block['editable_fields']['carousel_i_480']['value'] = '1';
} elseif ($hook_name == 'displayPostAfterComments') {
$block['editable_fields']['type']['value'] = 'post_relatedtopost';
} elseif ($hook_name == 'displayFooterProduct') {
$block['editable_fields']['type']['value'] = 'post_relatedtoproduct';
}
}
$block['title'] = $block['editable_fields']['title']['value'][$this->id_lang];
if (!empty($settings['exceptions'])) {
$block['exc_note'] = $this->getExceptionsNote($settings['exceptions']);
}
$this->context->smarty->assign(array(
'block' => $block,
'sorted_categories' => $this->getSortedCategories(),
'root_id' => $this->root_id,
'languages' => Language::getLanguages(false),
'id_lang_current' => $this->id_lang,
'multishop_note' => count(Shop::getContextListShopID()) > 1,
'full' => $full,
));
return $this->display(__FILE__, 'views/templates/admin/block-form.tpl');
}
public function getExceptionsNote($exceptions)
{
$exc_note = '';
$exceptions_txt = array();
if (!empty($exceptions['page']['type'])) {
$exceptions_txt[] = $this->l('on selected pages');
}
if (!empty($exceptions['customer']['type'])) {
$exceptions_txt[] = $this->l('for selected customers');
}
if ($exceptions_txt) {
$exc_note = sprintf($this->l('Displayed %s'), implode('/', $exceptions_txt));
}
return $exc_note;
}
public function getSettingsFields($type, $fill_values = false)
{
if (empty($this->fields)) {
include_once('classes/BlogFields.php');
$this->fields = new BlogFields();
}
$method = 'get'.Tools::ucfirst($type).'SettingsFields';
if (method_exists($this->fields, $method)) {
$fields = $this->fields->$method();
if ($fill_values) {
foreach ($this->getSettings($type) as $name => $value) {
if (!empty($fields[$name])) {
$fields[$name]['value'] = $value;
}
}
}
} else {
$fields = false;
}
return $fields;
}
public function ajaxCallSettingsForm()
{
$type = Tools::strtolower(Tools::getValue('type'));
if ($fields = $this->getSettingsFields($type, true)) {
$this->context->smarty->assign(array(
'type' => $type,
'settings' => $fields,
));
$form_html = $this->display(__FILE__, 'views/templates/admin/settings-form.tpl');
} else {
$form_html = $this->displayError($this->l('No settings available for this resource'));
}
$ret = array(
'form_html' => utf8_encode($form_html),
);
exit(Tools::jsonEncode($ret));
}
public function ajaxSaveSettings()
{
$type = Tools::getValue('type');
$data = $this->unserialize(Tools::getValue('data'));
$ret = array(
'saved' => $this->saveSettings($type, $data),
);
exit(Tools::jsonEncode($ret));
}
public function ajaxCallHookSettingsForm()
{
$hook_name = Tools::getValue('hook_name');
$settings_type = Tools::getValue('settings_type');
$method = 'getHook'.Tools::ucfirst($settings_type).'Settings';
if (!is_callable(array($this, $method))) {
$this->throwError($this->l('This type of settings is not supported'));
}
$this->context->smarty->assign(array(
'settings' => $this->$method($hook_name),
'settings_type' => $settings_type,
'hook_name' => $hook_name,
));
$form_html = $this->display($this->local_path, 'views/templates/admin/hook-'.$settings_type.'-form.tpl');
$ret = array(
'form_html' => utf8_encode($form_html),
);
exit(Tools::jsonEncode($ret));
}
public function getHookExceptionsSettings($hook_name)
{
$exc_data = $this->db->executeS('
SELECT exc_type, exc_controllers
FROM '._DB_PREFIX_.'a_blog_hook_settings
WHERE hook_name = \''.pSQL($hook_name).'\'
AND id_shop IN ('.pSQL(implode(', ', $this->shop_ids)).')
');
$type = 0;
$current_exceptions = array();
foreach ($exc_data as $row) {
if (!$type || $row['id_shop'] == $this->context->controller->id_shop) {
$type = $row['exc_type'];
}
$current_exceptions += explode(',', $row['exc_controllers']);
}
$current_exceptions = array_flip($current_exceptions);
$sorted_exceptions = array(
'core' => array(
'group_name' => $this->l('Core pages'),
'values' => array(),
),
'modules' => array(
'group_name' => $this->l('Module pages'),
'values' => array(),
),
);
$front_controllers = $this->getFrontControllers();
foreach ($front_controllers as $fc) {
$sorted_exceptions['core']['values'][$fc] = (int)isset($current_exceptions[$fc]);
}
$module_front_controllers = Dispatcher::getModuleControllers('front');
foreach ($module_front_controllers as $module_name => $controllers) {
foreach ($controllers as $controller_name) {
$key = 'module-'.$module_name.'-'.$controller_name;
$sorted_exceptions['modules']['values'][$key] = (int)isset($current_exceptions[$key]);
}
}
$settings = array(
'type' => $type,
'exceptions' => $sorted_exceptions,
);
return $settings;
}
public function getFrontControllers()
{
$controllers = array_keys(Dispatcher::getControllers(_PS_FRONT_CONTROLLER_DIR_));
// retro compatibility
$controllers = array_combine($controllers, $controllers);
$controllers['auth'] = 'authentication';
$controllers['compare'] = 'productscomparison';
return $controllers;
}
public function getHookPositionsSettings($hook_name)
{
$hook_modules = Hook::getModulesFromHook(Hook::getIdByName($hook_name));
$sorted = array();
foreach ($hook_modules as $m) {
if ($instance = Module::getInstanceByName($m['name'])) {
$logo_src = false;
if (file_exists(_PS_MODULE_DIR_.$instance->name.'/logo.png')) {
$logo_src = _MODULE_DIR_.$instance->name.'/logo.png';
}
$sorted[$m['id_module']] = array(
'name' => $instance->name,
'position' => $m['m.position'],
'enabled' => $instance->isEnabledForShopContext(),
'display_name' => $instance->displayName,
'description' => $instance->description,
'logo_src' => $logo_src,
);
if ($m['id_module'] == $this->id) {
$sorted[$m['id_module']]['current'] = 1;
}
}
}
return $sorted;
}
public function ajaxSaveHookSettings()
{
$hook_name = Tools::getValue('hook_name');
$id_hook = Hook::getIdByName($hook_name);
$settings_type = Tools::getValue('settings_type');
$saved = false;
if ($settings_type == 'exceptions') {
$exc_type = Tools::getValue('exceptions_type');
if ($exc_controllers = implode(',', Tools::getValue('exceptions'))) {
$rows = array();
foreach ($this->shop_ids as $id_shop) {
$row = '\''.pSQL($hook_name).'\', '.(int)$id_shop.', '.
(int)$exc_type.', \''.pSQL($exc_controllers).'\'';
$rows[] = '('.$row.')';
}
$saved = $this->db->execute('
INSERT INTO '._DB_PREFIX_.'a_blog_hook_settings
(hook_name, id_shop, exc_type, exc_controllers)
VALUES '.implode(', ', $rows).'
ON DUPLICATE KEY UPDATE
exc_type = VALUES(exc_type),
exc_controllers = VALUES(exc_controllers)
');
} else {
$imploded_shop_ids = implode(', ', $this->shop_ids);
$saved = $this->db->execute('
DELETE FROM '._DB_PREFIX_.'a_blog_hook_settings
WHERE hook_name = \''.pSQL($hook_name).'\'
AND id_shop IN ('.pSQL($imploded_shop_ids).')
');
}
// make sure native exceptions are not used
$saved = $this->unregisterExceptions($id_hook, $this->shop_ids);
} elseif ($settings_type == 'position') {
$id_module = Tools::getValue('id_module');
$new_position = Tools::getValue('new_position');
$way = Tools::getValue('way');
if ($module = Module::getInstanceById($id_module)) {
$saved = $module->updatePosition($id_hook, $way, $new_position);
}
}
$ret = array(
'saved' => $saved
);
exit(Tools::jsonEncode($ret));
}
public function ajaxProcessModule()
{
$id_module = Tools::getValue('id_module');
$hook_name = Tools::getValue('hook_name');
$act = Tools::getValue('act');
$module = Module::getInstanceById($id_module);
$saved = false;
if (Validate::isLoadedObject($module)) {
switch ($act) {
case 'disable':
$module->disable();
$saved = !$module->isEnabledForShopContext();
break;
case 'unhook':
$saved = $module->unregisterHook(Hook::getIdByName($hook_name));
break;
case 'uninstall':
if ($id_module != $this->id) {
$saved = $module->uninstall();
}
break;
case 'enable':
$saved = $module->enable();
break;
}
}
$ret = array ('saved' => $saved);
exit(Tools::jsonEncode($ret));
}
public function ajaxSave()
{
$resource = Tools::getValue('resource');
$data = $this->unserialize(Tools::getValue('data'));
$save_method = 'save'.$resource;
$this->verifyMethod($save_method);
$call_method = 'call'.$resource.'Form';
$this->verifyMethod($call_method);
$id = $this->$save_method($data);
if ($resource == 'Category') {
$this->context->smarty->assign(array(
'sorted_categories' => $this->getSortedCategories(),
'root_id' => $this->root_id,
'type' => 'full',
));
$tree = $this->display(__FILE__, 'views/templates/admin/category-tree.tpl');
$ret = array(
'tree' => utf8_encode($tree),
);
} else {
$ret = array(
'form' => utf8_encode($this->$call_method($id, Tools::getValue('full'))),
'id' => $id,
);
}
$ret['total'] = $this->getTotal(Tools::strtolower($resource));
exit(Tools::jsonEncode($ret));
}
public function formatIDs($ids_string, $return_string = true)
{
$ids = array_map('intval', explode(',', $ids_string));
$ids = array_combine($ids, $ids);
unset($ids[0]);
return $return_string ? implode(',', $ids) : $ids;
}
public function saveBlock($block_data)
{
$id_block = $block_data['id_block'];
$active = $block_data['active'];
$hook_name = $block_data['hook_name'];
$id_lang_default = Configuration::get('PS_LANG_DEFAULT');
$settings = $block_data['settings'];
// verify fields
$settings['post_ids'] = $this->formatIDs($settings['post_ids']);
$settings['cat_ids'] = $this->formatIDs($settings['cat_ids']);
$settings['parent_ids'] = $this->formatIDs($settings['parent_ids']);
foreach ($settings['exceptions'] as $key => &$exc) {
if ($exc['type'] && Tools::substr($exc['type'], -4) != '_all') {
$exc['ids'] = $this->formatIDs($exc['ids']);
if (!$exc['ids']) {
$exc['type'] = ($key == 'page') ? $exc['type'].'_all' : '0';
}
} else {
$exc['ids'] = '';
}
}
$data_multilang = $block_data['multilang'];
$editable_fields = $this->fields->getBlockFields();
foreach ($data_multilang as $name => $data) {
if (!empty($editable_fields[$name]['required']) && empty($data[$id_lang_default])) {
$lang_iso = Language::getIsoById($id_lang_default);
$display_name = $editable_fields[$name]['display_name'];
$txt = sprintf($this->l('Please specify %1$s (%2$s)'), $display_name, $lang_iso);
$this->throwError($txt);
}
}
$settings = Tools::jsonEncode($settings);
$saved = $this->db->execute('
INSERT INTO '._DB_PREFIX_.'a_blog_block VALUES
('.(int)$id_block.', \''.pSQL($hook_name).'\', 0, '.(int)$active.', \''.pSQL($settings).'\')
ON DUPLICATE KEY UPDATE
hook_name = VALUES(hook_name),
settings = VALUES(settings)
');
if (!$id_block) {
$id_block = $this->db->Insert_ID();
}
$lang_rows = array();
foreach ($this->shop_ids as $id_shop) {
foreach ($data_multilang as $name) {
foreach ($name as $id_lang => $value) {
if (!$value && !empty($name[$id_lang_default])) {
$value = $name[$id_lang_default];
}
$lang_rows[] = '('.(int)$id_block.', '.(int)$id_shop.', '.(int)$id_lang.', \''.pSQL($value).'\')';
}
}
}
if ($lang_rows) {
$saved &= $this->db->execute('
REPLACE INTO '._DB_PREFIX_.'a_blog_block_lang
VALUES '.implode(', ', $lang_rows).'
');
}
if ($saved) {
foreach ($this->shop_ids as $id_shop) {
if (!$this->isRegisteredInHookConsideringShop($hook_name, $id_shop)) {
$saved &= $this->registerHook($hook_name, array($id_shop));
}
}
}
return $saved ? (int)$id_block : false;
}
public function ajaxCallCategoryForm()
{
$id_category = Tools::getValue('id_category');
$id_parent = Tools::getValue('id_parent');
$ret = array(
'category_form' => utf8_encode($this->callCategoryForm($id_category, $id_parent)),
);
exit(Tools::jsonEncode($ret));
}
public function callCategoryForm($id_category, $id_parent = false)
{
$category_data = $this->db->getRow('
SELECT * FROM '._DB_PREFIX_.'a_blog_category
WHERE id_category = '.(int)$id_category.'
');
$category_data_lang = $this->db->executeS('
SELECT * FROM '._DB_PREFIX_.'a_blog_category_lang
WHERE id_category = '.(int)$id_category.'
AND id_shop = '.(int)$this->context->shop->id.'
');
$category = array(
'id_category' => (int)$id_category,
'position' => 0,
'active' => 1,
'editable_fields' => $this->fields->getCategoryFields($id_parent),
);
if ($id_category && $category_data) {
$translatable_fields = array();
foreach (array_keys($category) as $name) {
if (isset($category_data[$name])) {
$category[$name] = $category_data[$name];
}
}
foreach ($category['editable_fields'] as $name => &$field) {
if (!isset($field['multilang']) && isset($category_data[$name])) {
$field['value'] = $category_data[$name];
} elseif (isset($field['multilang'])) {
$translatable_fields[] = $name;
}
}
foreach ($category_data_lang as $cdl) {
foreach ($translatable_fields as $field_name) {
if (isset($cdl[$field_name])) {
$category['editable_fields'][$field_name]['value'][$cdl['id_lang']] = $cdl[$field_name];
}
}
}
}
$category['title'] = $category['editable_fields']['title']['value'][$this->id_lang];
$this->context->smarty->assign(array(
'category' => $category,
'sorted_categories' => $this->getSortedCategories(),
'root_id' => $this->root_id,
'languages' => Language::getLanguages(false),
'id_lang_current' => $this->id_lang,
'multishop_note' => count(Shop::getContextListShopID()) > 1,
));
return $this->display(__FILE__, 'views/templates/admin/category-form.tpl');
}
public function saveCategory($category_data)
{
$id_category = $category_data['id_category'];
$id_parent = $category_data['id_parent'];
$active = $category_data['active'];
$level_depth = 0;
if ($id_parent) {
$level_depth = $this->db->getValue('
SELECT level_depth FROM '._DB_PREFIX_.'a_blog_category WHERE id_category = '.(int)$id_parent.'
');
$level_depth = (int)$level_depth + 1;
}
$position = 0;
$date = date('Y-m-d H:i:s');
$data_multilang = $category_data['multilang'];
$multilang_fields = $this->fields->getCategoryFields(false, true);
$lang_rows = $this->prepareMultilangRows('category', $data_multilang, $multilang_fields, $id_category);
$saved = $this->db->execute('
INSERT INTO '._DB_PREFIX_.'a_blog_category VALUES (
'.(int)$id_category.',
'.(int)$id_parent.',
'.(int)$active.',
'.(int)$level_depth.',
'.(int)$position.',
\''.pSQL($date).'\',
\''.pSQL($date).'\')
ON DUPLICATE KEY UPDATE
id_parent = VALUES(id_parent),
level_depth = VALUES(level_depth),
date_upd = VALUES(date_upd),
active = VALUES(active)
');
if (!$id_category) {
$id_category = $this->db->Insert_ID();
foreach ($lang_rows as &$row) {
$row = '('.(int)$id_category.', '.ltrim($row, '(0, ');
}
}
if ($saved && $id_category) {
$lang_columns = 'id_category, id_shop, id_lang, '.implode(', ', array_keys($data_multilang));
$saved &= $this->db->execute('
REPLACE INTO '._DB_PREFIX_.'a_blog_category_lang ('.pSQL($lang_columns).')
VALUES '.implode(', ', $lang_rows).'
');
}
return $saved ? (int)$id_category : false;
}
public function deleteCategory($id_category)
{
if ($id_category == 1) {
return false;
}
$deleted = $this->db->execute('
DELETE FROM '._DB_PREFIX_.'a_blog_category_lang
WHERE id_category = '.(int)$id_category.'
AND id_shop IN ('.implode(', ', array_map('intval', $this->shop_ids)).')
');
$exists = $this->db->getValue(
'SELECT * FROM '._DB_PREFIX_.'a_blog_category_lang WHERE id_category = '.(int)$id_category
);
if (!$exists) {
foreach (array('a_blog_category', 'a_blog_post_category') as $table) {
$deleted &= $this->db->execute('
DELETE FROM `'._DB_PREFIX_.bqSQL($table).'` WHERE id_category = '.(int)$id_category.'
');
}
}
// update default category if it was assigned to some posts
$posts_to_update = $this->db->executeS('
SELECT id_post FROM '._DB_PREFIX_.'a_blog_post WHERE id_category_default = '.(int)$id_category.'
');
$position = (int)$this->db->getValue('
SELECT MAX(position) FROM '._DB_PREFIX_.'a_blog_post_category WHERE id_category = '.(int)$this->root_id.'
');
$post_ids = $cat_rows = array();
foreach ($posts_to_update as $post) {
$post_ids[] = (int)$post['id_post'];
if (!$this->isPostPositioned($post['id_post'], $this->root_id)) {
$position++;
$cat_rows[] = '('.(int)$this->root_id.', '.(int)$post['id_post'].', '.(int)$position.')';
}
}
if ($post_ids) {
$this->db->execute('
UPDATE '._DB_PREFIX_.'a_blog_post SET id_category_default = '.(int)$this->root_id.'
WHERE id_post IN ('.implode(', ', $post_ids).')
');
}
if ($cat_rows) {
$this->db->execute('
REPLACE INTO '._DB_PREFIX_.'a_blog_post_category
VALUES '.implode(', ', $cat_rows).'
');
}
// end updating default category
$children = $this->db->executeS('
SELECT id_category FROM '._DB_PREFIX_.'a_blog_category WHERE id_parent = '.(int)$id_category.'
');
foreach ($children as $child) {
$this->deleteCategory($child['id_category']);
}
return $deleted;
}
public function addNewPost()
{
$post_data = array(
'id_post' => 0,
'active' => 0,
'author' => $this->context->employee->id,
'id_category_default' => $this->root_id,
'cat_ids' => array($this->root_id),
'publish_from' => '',
'publish_to' => '',
);
$title = $this->l('New post');
$link_rewrite = Tools::str2url($title);
$languages = Language::getLanguages(false);
foreach ($languages as $lang) {
$id_lang = $lang['id_lang'];
$post_data['multilang']['title'][$id_lang] = $title;
$post_data['multilang']['meta_title'][$id_lang] = $title;
$post_data['multilang']['link_rewrite'][$id_lang] = $link_rewrite;
}
return $this->savePost($post_data);
}
public function ajaxCallPostForm()
{
$id_post = Tools::getValue('id');
$id_post = $id_post ? $id_post : $this->addNewPost();
$ret = array(
'form' => utf8_encode($this->callPostForm($id_post)),
);
exit(Tools::jsonEncode($ret));
}
public function getPostTags($id_post, $id_lang = false, $implode = true)
{
$tags = array();
$raw_data = $this->db->executeS('
SELECT t.* FROM '._DB_PREFIX_.'a_blog_tag t
INNER JOIN '._DB_PREFIX_.'a_blog_post_tag pt
ON pt.id_tag = t.id_tag AND pt.id_post = '.(int)$id_post.'
'.($id_lang ? ' WHERE t.id_lang = '.(int)$id_lang : '').'
');
foreach ($raw_data as $d) {
$tags[$d['id_lang']][$d['tag_url']] = $d['tag_name'];
}
foreach ($tags as &$t) {
ksort($t);
$t = !$implode ? $t : implode(',', $t);
}
if ($id_lang) {
$tags = isset($tags[$id_lang]) ? $tags[$id_lang] : array();
}
return $tags;
}
public function callPostForm($id_post, $full = true)
{
$query = new DbQuery();
$query->select('p.*, ps.views, ps.comments, ps.likes, cl.title AS cat_title, e.firstname, e.lastname');
$query->from('a_blog_post', 'p');
$query->leftJoin('a_blog_post_stats', 'ps', 'p.id_post = ps.id_post');
$query->leftJoin('employee', 'e', 'p.author = e.id_employee');
$c_join = 'p.id_category_default = cl.id_category AND cl.id_lang = '.(int)$this->id_lang.'
AND cl.id_shop = '.(int)$this->context->shop->id;
$query->leftJoin('a_blog_category_lang', 'cl', $c_join);
$query->where('p.id_post = '.(int)$id_post);
$this->addDateAndStateAssociation($query);
$post_data = $this->db->getRow($query);
$post_data_multilang = $this->db->executeS('
SELECT * FROM '._DB_PREFIX_.'a_blog_post_lang
WHERE id_post = '.(int)$id_post.'
AND id_shop IN ('.implode(', ', array_map('intval', $this->shop_ids)).')
');
$categories_db = $this->db->executeS('
SELECT pc.*, cl.title FROM '._DB_PREFIX_.'a_blog_post_category pc
LEFT JOIN '._DB_PREFIX_.'a_blog_category_lang cl ON cl.id_category = pc.id_category
WHERE id_post = '.(int)$id_post.'
AND id_lang = '.(int)$this->id_lang.'
');
$categories = array();
foreach ($categories_db as $cat) {
$categories[$cat['id_category']] = $cat['title'];
}
if (!$categories) {
$categories[$this->root_id] = $this->db->getValue('
SELECT title FROM '._DB_PREFIX_.'a_blog_category_lang
WHERE id_lang = '.(int)$this->id_lang.'
AND id_category = '.(int)$this->root_id.'
');
}
$post = array(
'id_post' => 0,
'id_category_default' => $this->root_id,
'active' => 1,
'author' => $this->context->employee->id,
'editable_fields' => $this->fields->getPostFields(false),
'views' => 0,
'comments' => 0,
'date_add' => '',
'date_upd' => '',
'days_before_publish' => 0,
'days_expired' => 0,
'publish_from' => $this->empty_date,
'publish_to' => $this->empty_date,
'cover' => '',
'main_img' => '',
// additional data
'cat_title' => '',
'firstname' => '',
'lastname' => '',
);
$post['editable_fields']['categories']['value'] = $categories;
if ($id_post && $post_data) {
$translatable_fields = array();
foreach (array_keys($post) as $name) {
if (isset($post_data[$name])) {
$post[$name] = $post_data[$name];
}
}
$related_ids = $this->getRelatedIDs('post', $id_post);
$related_items = $related_ids ? $this->getBasicInfos('product', $related_ids) : array();
$post['editable_fields']['related_products']['value'] = $related_ids;
$post['editable_fields']['related_products']['related_items'] = $related_items;
foreach ($post['editable_fields'] as $name => &$field) {
if (!isset($field['multilang']) && isset($post_data[$name])) {
$field['value'] = $post_data[$name];
} elseif (isset($field['multilang'])) {
$translatable_fields[] = $name;
}
}
foreach ($post_data_multilang as $pdm) {
// date_upd is stored in multilang table because it is connected to id_shop
if (!$post['date_upd'] || $pdm['id_lang'] == $this->context->language->id) {
$post['date_upd'] = $post['editable_fields']['date_upd']['value'] = $pdm['date_upd'];
}
foreach ($translatable_fields as $field_name) {
if (isset($pdm[$field_name])) {
$post['editable_fields'][$field_name]['value'][$pdm['id_lang']] = $pdm[$field_name];
}
}
}
$post['editable_fields']['tags']['value'] = $this->getPostTags($id_post);
$post['editable_fields']['images']['value'] = $this->getPostImages($id_post, true);
}
$post['title'] = $post['editable_fields']['title']['value'][$this->id_lang];
$publish_from = $post['publish_from'] != $this->empty_date ? $post['publish_from'] : $post['date_add'];
$post['editable_fields']['publish_from']['value'] = $publish_from;
$publish_to = $post['publish_to'] != $this->empty_date ? $post['publish_to'] : '';
$post['editable_fields']['publish_to']['value'] = $publish_to;
$this->context->smarty->assign(array(
'post' => $post,
'post_tabs' => $this->fields->getPostTabs(),
'current_tab' => 'content',
'sorted_categories' => $this->getSortedCategories(),
'root_id' => $this->root_id,
'languages' => Language::getLanguages(false),
'id_lang_current' => $this->id_lang,
'image_types' => $this->img_settings,
'multishop_note' => count($this->shop_ids) > 1,
'full' => $full,
'blog' => $this,
));
return $this->display(__FILE__, 'views/templates/admin/post-form.tpl');
}
public function saveTag($tag_name, $id_lang)
{
$tag_url = Tools::str2url($tag_name);
$row = '(\'\', '.(int)$id_lang.', \''.pSQL($tag_url).'\', \''.pSQL($tag_name).'\')';
$this->db->execute('INSERT INTO '._DB_PREFIX_.'a_blog_tag VALUES '.$row);
return $this->db->Insert_ID();
}
public function savePostTags($id_post, $tags_multilang)
{
$tag_rows = $all_tags = array();
$raw_tags_data = $this->db->executeS('
SELECT * FROM '._DB_PREFIX_.'a_blog_tag
');
foreach ($raw_tags_data as $rtd) {
$all_tags[$rtd['id_lang']][$rtd['tag_name']] = $rtd['id_tag'];
}
foreach ($tags_multilang as $id_lang => $tags) {
$tags = explode(',', $tags);
foreach ($tags as $tag) {
if (!$tag || !Validate::isGenericName($tag)) {
continue;
}
$id_tag = isset($all_tags[$id_lang][$tag]) ? $all_tags[$id_lang][$tag] : $this->saveTag($tag, $id_lang);
$tag_rows[] = '('.(int)$id_post.', '.(int)$id_tag.')';
}
}
$saved = $this->db->execute('DELETE FROM '._DB_PREFIX_.'a_blog_post_tag WHERE id_post = '.(int)$id_post);
if ($tag_rows) {
$saved &= $this->db->execute('
INSERT INTO '._DB_PREFIX_.'a_blog_post_tag VALUES '.implode(', ', $tag_rows).'
ON DUPLICATE KEY UPDATE id_tag = VALUES(id_tag)
');
}
$this->clearUnusedTags();
return $saved;
}
public function clearUnusedTags()
{
$current_tags = $this->db->executeS('
SELECT t.id_tag, pt.id_post FROM '._DB_PREFIX_.'a_blog_tag t
LEFT JOIN '._DB_PREFIX_.'a_blog_post_tag pt ON pt.id_tag = t.id_tag
');
foreach ($current_tags as $t) {
if (!$t['id_post']) {
$this->db->execute('DELETE FROM '._DB_PREFIX_.'a_blog_tag WHERE id_tag = '.(int)$t['id_tag']);
}
}
}
public function getRelatedColumns($resource_type)
{
if ($resource_type == 'post') {
$columns = array('id_post', 'id_product', 'position_product');
} else {
$columns = array('id_product', 'id_post', 'position_post');
}
return $columns;
}
public function saveRelatedIDs($resource_type, $resource_id, $related_ids_imploded)
{
$saved = true;
if (!$resource_id) {
return $saved;
}
$related_ids_imploded = $this->formatIDs($related_ids_imploded);
$related_ids = explode(',', $related_ids_imploded);
$columns = $this->getRelatedColumns($resource_type);
$saved &= $this->db->execute('
DELETE FROM '._DB_PREFIX_.'a_blog_related_products
WHERE '.pSQL($columns[0]).' = '.(int)$resource_id.'
'.($related_ids_imploded ? ' AND '.pSQL($columns[1]).' NOT IN ('.pSQL($related_ids_imploded).')' : '').'
');
$rows = array();
foreach ($related_ids as $position => $id) {
if ($resource_id && $id) {
$rows [] = '('.(int)$resource_id.', '.(int)$id.', '.(int)$position.')';
}
}
if ($rows) {
$saved &= $this->db->execute('
INSERT INTO '._DB_PREFIX_.'a_blog_related_products
('.pSQL(implode(', ', $columns)).')
VALUES '.implode(', ', $rows).'
ON DUPLICATE KEY UPDATE
id_post = VALUES(id_post),
id_product = VALUES(id_product),
'.pSQL($columns[2]).' = VALUES('.pSQL($columns[2]).')
');
}
return $saved;
}
public function getRelatedIDs($resource_type, $resource_id, $implode = true)
{
$columns = $this->getRelatedColumns($resource_type);
$ids = $this->db->executeS('
SELECT * FROM '._DB_PREFIX_.'a_blog_related_products
WHERE id_post > 0 AND id_product > 0 AND '.pSQL($columns[0]).' = '.(int)$resource_id.'
ORDER BY '.pSQL($columns[2]).' ASC
');
foreach ($ids as &$id) {
$id = $id[$columns[1]];
}
return $implode ? implode(',', $ids) : $ids;
}
public function ajaxGetAutocompleteMatches()
{
$type = Tools::getValue('type');
$query = Tools::getValue('q');
$excluded_ids = Tools::getValue('excluded_ids');
$limit = Tools::getValue('limit');
$included_ids = '';
if ((int)$query) {
$included_ids = (int)$query;
$query = '';
$limit = 1;
} elseif (Tools::strlen($query) < 3) {
return '';
}
$matches = $this->getBasicInfos($type, $included_ids, $query, $excluded_ids, $limit);
foreach ($matches as &$m) {
$m = $m['id'].' - '.$m['name'];
}
$result = implode("\n", $matches);
exit($result);
}
public function getBasicInfos($type, $included_ids = '', $q = '', $excluded_ids = '', $limit = '')
{
$db_vars = $type == 'post' ? array('a_blog_post_lang', 'id_post', 'title') :
array('product_lang', 'id_product', 'name');
$id_lang = $this->context->language->id;
$imploded_shop_ids = implode(',', Shop::getContextListShopID());
$included_ids = $this->formatIDs($included_ids);
$excluded_ids = $this->formatIDs($excluded_ids);
$items = $this->db->executeS('
SELECT DISTINCT('.pSQL($db_vars[1]).') AS id, '.pSQL($db_vars[2]).' AS name
FROM '._DB_PREFIX_.pSQL($db_vars[0]).'
WHERE id_lang = '.(int)$id_lang.' AND id_shop IN ('.pSQL($imploded_shop_ids).')
'.($q ? ' AND '.pSQL($db_vars[2]).' LIKE \'%'.pSQL($q).'%\'' : '').'
'.($included_ids ? ' AND '.pSQL($db_vars[1]).' IN ('.pSQL($included_ids).')' : '').'
'.($excluded_ids ? ' AND '.pSQL($db_vars[1]).' NOT IN ('.pSQL($excluded_ids).')' : '').'
'.($included_ids ? ' ORDER BY FIELD('.pSQL($db_vars[1]).', '.pSQL($included_ids).')' : '').'
'.((int)$limit ? ' LIMIT '.(int)$limit : '').'
');
return $items;
}
public function savePost($post_data)
{
$id_post = $post_data['id_post'];
$id_category_default = $post_data['id_category_default'];
$active = $post_data['active'];
$cover = $main_img = '';
$author = $post_data['author'];
$date = date('Y-m-d H:i:s');
if (!$post_data['publish_from']) {
$post_data['publish_from'] = $date;
}
$publish_dates = array('from' => $post_data['publish_from'], 'to' => $post_data['publish_to']);
foreach ($publish_dates as $k => $v) {
if ($v && !Validate::isDate($v)) {
$this->throwError($this->l('Wrong date format').': publish_'.$k);
}
}
$cat_ids = $post_data['cat_ids'];
if (!$cat_ids) {
$this->throwError($this->l('Please, select at least one category'));
}
$data_multilang = $post_data['multilang'];
$multilang_fields = $this->fields->getPostFields(true);
$lang_rows = $this->prepareMultilangRows('post', $data_multilang, $multilang_fields, $id_post);
$saved = $this->db->execute('
INSERT INTO '._DB_PREFIX_.'a_blog_post VALUES (
'.(int)$id_post.',
'.(int)$id_category_default.',
'.(int)$active.',
\''.pSQL($cover).'\',
\''.pSQL($main_img).'\',
'.(int)$author.',
\''.pSQL($date).'\',
\''.pSQL($publish_dates['from']).'\',
\''.pSQL($publish_dates['to']).'\')
ON DUPLICATE KEY UPDATE
id_category_default = VALUES(id_category_default),
author = VALUES(author),
active = VALUES(active),
publish_from = VALUES(publish_from),
publish_to = VALUES(publish_to)
');
if (!$id_post) {
$id_post = $this->db->Insert_ID();
foreach ($lang_rows as &$row) {
$row = '('.(int)$id_post.', '.ltrim($row, '(0, ');
}
}
if ($saved && $id_post) {
// prepare cat_rows
$current_positions = $cat_rows = array();
$current_rows = $this->db->executeS('
SELECT * FROM '._DB_PREFIX_.'a_blog_post_category
WHERE id_post = '.(int)$id_post.'
');
foreach ($current_rows as $r) {
$current_positions[$r['id_category']] = $r['position'];
}
foreach ($cat_ids as $id_cat) {
$position = isset($current_positions[$id_cat]) ? $current_positions[$id_cat]: 0;
$cat_rows[] = '('.(int)$id_cat.', '.(int)$id_post.', '.(int)$position.')';
}
$saved &= $this->db->execute('
DELETE FROM '._DB_PREFIX_.'a_blog_post_category
WHERE id_post = '.(int)$id_post.'
');
$saved &= $this->db->execute('
REPLACE INTO '._DB_PREFIX_.'a_blog_post_category
VALUES '.implode(', ', $cat_rows).'
');
$lang_columns = 'id_post, id_shop, id_lang, '.implode(', ', array_keys($data_multilang)).', date_upd';
foreach ($lang_rows as &$row) {
$row = rtrim($row, ')').', \''.pSQL($date).'\')';
}
$saved &= $this->db->execute('
REPLACE INTO '._DB_PREFIX_.'a_blog_post_lang ('.pSQL($lang_columns).')
VALUES '.implode(', ', $lang_rows).'
');
if ($saved && !$post_data['id_post']) {
$saved &= $this->db->execute('
INSERT INTO '._DB_PREFIX_.'a_blog_post_stats (id_post) VALUES ('.(int)$id_post.')
');
}
foreach ($cat_ids as $id_cat) {
if (!$this->isPostPositioned($id_post, $id_cat)) {
$saved &= $this->updatePostPositions($id_post, $id_cat, 1);
}
}
$saved &= $this->savePostTags($id_post, $post_data['multilang']['tags']);
$saved &= $this->saveRelatedIDs('post', $id_post, $post_data['related_products']);
}
return $saved ? (int)$id_post : false;
}
public function prepareMultilangRows($resource_type, &$data_lang, $multilang_fields, $id)
{
$languages_to_submit = array_keys(current($data_lang));
$id_lang_default = Configuration::get('PS_LANG_DEFAULT');
$lang_rows = $data_lang_sorted = array();
foreach ($this->shop_ids as $id_shop) {
foreach ($languages_to_submit as $id_lang) {
$lang_row = (int)$id.', '.(int)$id_shop.', '.(int)$id_lang;
foreach ($multilang_fields as $name => $f) {
// set missing data_multilang in order to insert all columns properly
$data_lang_sorted[$name] = isset($data_lang[$name]) ? $data_lang[$name] : $f['value'];
$id_lang_source = !empty($data_lang_sorted[$name][$id_lang]) ? $id_lang : $id_lang_default;
$value = $data_lang_sorted[$name][$id_lang_source];
$error = false;
$validate = !empty($f['validate']) ? $f['validate'] : false;
if (!empty($f['required']) && empty($value)) {
$error = $this->l('Please specify %s (%s)');
} elseif (!empty($validate) && !Validate::$validate($value)) {
$error = $this->l('%s (%s) is incorrect');
}
if ($error) {
$lang_iso = Language::getIsoById($id_lang_default);
$this->throwError(sprintf($error, Tools::strtolower($f['display_name']), $lang_iso));
}
if ($name == 'link_rewrite') {
// integer values are reserved by page numbers
$value = (int)$value ? '_'.$value : $value;
// make sure link_rewrite is unique
$suffix = $reserved_by_id = 0;
do {
$new_value = $value.($suffix ? '-'.$suffix : '');
foreach (array('post', 'category') as $type) {
$reserved_by_id = $this->db->getValue('
SELECT `id_'.bqSQL($type).'`
FROM `'._DB_PREFIX_.'a_blog_'.bqSQL($type).'_lang`
WHERE `link_rewrite` = \''.pSQL($new_value).'\'
AND `id_lang` = '.(int)$id_lang.'
'.($resource_type == $type ? 'AND `id_'.bqSQL($type).'` <> '.(int)$id : '').'
');
if ($reserved_by_id) {
$suffix = !$suffix ? 2 : $suffix + 1;
break;
}
}
} while ($reserved_by_id);
$value = $new_value;
}
$allow_html = in_array($name, array('content', 'description')) ? true : false;
$lang_row .= ', \''.pSQL($value, $allow_html).'\'';
}
$lang_rows[] = '('.$lang_row.')';
}
}
$data_lang = $data_lang_sorted;
return $lang_rows;
}
public function isPostPositioned($id_post, $id_cat)
{
$positioned = $this->db->getValue('
SELECT position FROM '._DB_PREFIX_.'a_blog_post_category
WHERE id_post = '.(int)$id_post.' AND id_category = '.(int)$id_cat.'
');
return (bool)$positioned;
}
public function hookDisplayAdminProductsExtra($params)
{
$id_product = !empty($params['id_product']) ? $params['id_product'] : Tools::getValue('id_product');
$related_ids = $this->formatIDs($this->getRelatedIDs('product', $id_product));
$config_path = $this->getConfigPagePath();
$this->context->smarty->assign(array(
'id_product' => $id_product,
'imploded_post_ids' => $related_ids,
'related_post_items' => $related_ids ? $this->getBasicInfos('post', $related_ids) : array(),
'ab_config_path' => $config_path,
'is_17' => $this->is_17,
));
$js = '
<script type="text/javascript">
var ab_ajax_path = "'.$config_path.'&ajax=1";
</script>
';
return $js.$this->display(__FILE__, 'views/templates/admin/product-tab.tpl');
}
public function getConfigPagePath()
{
return 'index.php?controller=AdminModules&configure='.$this->name.
'&token='.Tools::getAdminTokenLite('AdminModules');
}
public function hookActionProductSave()
{
if (Tools::isSubmit('related_post_ids')) {
$id_product = Tools::getValue('id_product');
$related_post_ids = Tools::getValue('related_post_ids');
$this->saveRelatedIDs('product', $id_product, $related_post_ids);
}
}
public function ajaxDelete()
{
$id = Tools::getValue('id');
$resource = Tools::getValue('resource');
$method = 'delete'.$resource;
$this->verifyMethod($method);
$ret = array(
'deleted' => $this->$method($id),
'total' => $this->getTotal(Tools::strtolower($resource)),
);
exit(Tools::jsonEncode($ret));
}
public function ajaxDeleteCategory()
{
$ret = array(
'deleted' => $this->deleteCategory(Tools::getValue('id_category')),
'total' => $this->getTotal('category'),
);
exit(Tools::jsonEncode($ret));
}
public function verifyMethod($method_name)
{
if (!method_exists($this, $method_name)) {
$this->throwError($this->l('Unknown method:').' '.$method_name);
}
}
public function deleteBlock($id_block)
{
$deleted = $this->db->execute('
DELETE FROM '._DB_PREFIX_.'a_blog_block_lang
WHERE id_block = '.(int)$id_block.'
AND id_shop IN ('.implode(', ', array_map('intval', $this->shop_ids)).')
');
$exists = $this->db->getValue('
SELECT * FROM '._DB_PREFIX_.'a_blog_block_lang WHERE id_block = '.(int)$id_block.'
');
if ($deleted && !$exists) {
$deleted &= $this->db->execute('
DELETE FROM '._DB_PREFIX_.'a_blog_block WHERE id_block = '.(int)$id_block.'
');
}
return $deleted;
}
public function deletePost($id_post)
{
$deleted = $this->db->execute('
DELETE FROM '._DB_PREFIX_.'a_blog_post_lang
WHERE id_post = '.(int)$id_post.'
AND id_shop IN ('.implode(', ', array_map('intval', $this->shop_ids)).')
');
$exists = $this->db->getValue('SELECT * FROM '._DB_PREFIX_.'a_blog_post_lang WHERE id_post = '.(int)$id_post);
if ($deleted && !$exists) {
$deleted &= $this->db->execute('
DELETE FROM '._DB_PREFIX_.'a_blog_post WHERE id_post = '.(int)$id_post.';
DELETE FROM '._DB_PREFIX_.'a_blog_post_category WHERE id_post = '.(int)$id_post.';
DELETE FROM '._DB_PREFIX_.'a_blog_post_stats WHERE id_post = '.(int)$id_post.';
DELETE FROM '._DB_PREFIX_.'a_blog_comment WHERE id_post = '.(int)$id_post.';
DELETE FROM '._DB_PREFIX_.'a_blog_related_products WHERE id_post = '.(int)$id_post.';
');
}
if ($deleted) {
$this->recursiveRemove($this->img_dir_local.'posts/'.$id_post.'/');
}
return $deleted;
}
public function deleteComment($id_comment)
{
$id_post = $this->db->getValue(
'SELECT id_post FROM '._DB_PREFIX_.'a_blog_comment WHERE id_comment = '.(int)$id_comment
);
$deleted = $this->db->execute(
'DELETE FROM '._DB_PREFIX_.'a_blog_comment WHERE id_comment = '.(int)$id_comment
);
$total = $this->db->getValue(
'SELECT COUNT(*) FROM '._DB_PREFIX_.'a_blog_comment WHERE id_post = '.(int)$id_post
);
$this->addPostStats($id_post, 'comments', $total);
return $deleted;
}
public function ajaxUploadImages()
{
$id_post = Tools::getValue('id_post');
$post_dir_local = $this->img_dir_local.'posts/'.$id_post.'/';
$post_dir = $this->img_dir.'posts/'.$id_post.'/';
if (!file_exists($post_dir_local)) {
mkdir($post_dir_local, 0755);
Tools::copy($this->local_path.'index.php', $post_dir_local.'index.php');
}
$saved_images = array();
$num = count($this->getPostImages($id_post));
$sizes = array();
foreach ($this->img_settings as $type => $settings) {
$sizes[$type] = $settings['value'];
}
$special_imgs_verified = false;
foreach ($_FILES as $file) {
$saved_img = $this->saveSubmittedImage($file, $post_dir_local, ++$num, $sizes);
$key = $saved_img;
if (!$special_imgs_verified) {
foreach (array_keys($this->special_img_types) as $type) {
if (!$this->getPostImg($type, $id_post)) {
$this->setPostImg($type, $id_post, $saved_img);
}
}
$special_imgs_verified = true;
}
$saved_images[$key] = $post_dir.'m/'.$saved_img;
}
ksort($saved_images);
$smarty_array = array(
'images' => $saved_images,
'image_types' => $this->img_settings,
);
foreach (array_keys($this->special_img_types) as $type) {
$smarty_array[$type] = $this->getPostImg($type, $id_post);
}
$this->context->smarty->assign($smarty_array);
$image_set_html = $this->display(__FILE__, 'views/templates/admin/post-images.tpl');
$ret = array('saved_images_html' => utf8_encode($image_set_html));
exit(Tools::jsonEncode($ret));
}
public function saveSubmittedImage($file, $location, $prefix, $sizes, $keep_original = true)
{
if (!isset($file['tmp_name']) || empty($file['tmp_name']) || !empty($this->errors)) {
return '';
}
$max_size = 10485760; // 10 mb
// Check image validity
if ($error = ImageManager::validateUpload($file, Tools::getMaxUploadSize($max_size))) {
$this->throwError($error);
}
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
$new_img_name = $this->getNewFilename($location, $prefix).'.'.$ext;
if (!move_uploaded_file($file['tmp_name'], $location.$new_img_name)) {
$this->throwError($this->l('Error: image was not copied'));
}
foreach ($sizes as $type => $dimentions) {
$path = $location.'/'.$type.'/';
if (!file_exists($path)) {
mkdir($path, 0755);
Tools::copy($this->local_path.'index.php', $path.'index.php');
}
$path .= $new_img_name;
$dimentions = explode('*', $dimentions);
$w = $dimentions[0];
$h = $dimentions[1];
if (!$this->imageResizeModified($location.$new_img_name, $path, $w, $h, $ext)) {
$this->throwError($this->l('Error: image was not resized'));
}
}
if (!$keep_original) {
unlink($location.$new_img_name);
}
return $new_img_name;
}
public function getPostImg($type, $id_post, $check_existence = true)
{
$sql = 'SELECT '.pSQL($type).' FROM '._DB_PREFIX_.'a_blog_post WHERE id_post = '.(int)$id_post;
$img = $this->db->getValue($sql);
if ($img && $check_existence && !is_file($this->img_dir_local.'posts/'.$id_post.'/'.$img)) {
$img = false;
}
return $img;
}
public function ajaxSetPostImg()
{
$type = Tools::getValue('type');
$id_post = Tools::getValue('id_post');
$img = Tools::getValue('img');
$ret = array(
'success' => $this->setPostImg($type, $id_post, $img),
$type => $img,
);
exit(Tools::jsonEncode($ret));
}
public function setPostImg($type, $id_post, $img)
{
return $this->db->execute(
'UPDATE '._DB_PREFIX_.'a_blog_post SET '.pSQL($type).' = \''.pSQL($img).'\' WHERE id_post = '.(int)$id_post
);
}
public function getPostImages($id_post, $add_path = false)
{
$sorted = array();
$post_images = glob($this->img_dir_local.'posts/'.$id_post.'/*');
foreach ($post_images as $img) {
if (getimagesize($img)) {
$img_name = basename($img);
$key = current(explode('-', $img_name));
$sorted[$key] = $img_name;
if ($add_path) {
$sorted[$key] = $this->img_dir.'posts/'.$id_post.'/m/'.$sorted[$key];
}
}
}
ksort($sorted);
return $sorted;
}
public function ajaxDeleteImg()
{
$id_post = Tools::getValue('id_post');
$img = Tools::getValue('img');
$deleted = $this->deleteImg($id_post, $img);
$post_images = $this->getPostImages($id_post);
$current = current($post_images);
foreach (array_keys($this->special_img_types) as $type) {
if ($this->getPostImg($type, $id_post, false) == $img && !empty($current)) {
$this->setPostImg($type, $id_post, $current);
}
}
$ret = array(
'success' => $deleted,
'cover' => $this->getPostImg('cover', $id_post),
'main_img' => $this->getPostImg('main_img', $id_post),
);
exit(Tools::jsonEncode($ret));
}
public function deleteImg($id_post, $img)
{
$res = true;
$post_dir = $this->img_dir_local.'posts/'.$id_post.'/';
$res &= unlink($post_dir.$img);
if (empty($this->img_settings)) {
$this->img_settings = $this->getImgSettings();
}
foreach (array_keys($this->img_settings) as $type) {
$res &= unlink($post_dir.$type.'/'.$img);
}
return $res;
}
public function getNewFilename($location, $prefix = '')
{
$prefix = $prefix ? $prefix.'-' : '';
do {
$filename = uniqid($prefix);
} while (file_exists($location.$filename));
return $filename;
}
public function ajaxRegenerateThumbnails()
{
$type = Tools::getValue('type');
$id_post = (int)Tools::getValue('id_post');
$ret = array();
// first run
if (!$id_post) {
$post_ids = $this->db->executeS('SELECT id_post FROM '._DB_PREFIX_.'a_blog_post');
foreach ($post_ids as &$p) {
$p = $p['id_post'];
}
$ret['post_ids'] = $post_ids;
} else {
$location = $this->img_dir_local.'posts/'.$id_post.'/';
$post_images = glob($location.'*');
$total = 0;
foreach ($post_images as $src_img) {
if (getimagesize($src_img)) {
$img_name = basename($src_img);
$ext = pathinfo($img_name, PATHINFO_EXTENSION);
$dest_img = $location.$type.'/'.$img_name;
$size = explode('*', $this->img_settings[$type]['value']);
$w = $size[0];
$h = $size[1];
$this->imageResizeModified($src_img, $dest_img, $w, $h, $ext);
$total++;
}
}
$ret['id_post'] = $id_post;
$ret['total_regenerated'] = $total;
}
exit(Tools::jsonEncode($ret));
}
public function unserialize($string)
{
$params = array();
parse_str($string, $params);
return $params;
}
public function getCategoryLink($id_category, $link_rewrite = false, $page = 1)
{
$url = $this->getBaseUri();
if ($id_category != $this->root_id) {
if ($this->friendly_url) {
$link_rewrite = $link_rewrite ? $link_rewrite : $this->getLinkRewriteById('category', $id_category);
$url .= $link_rewrite.'/';
} else {
$url .= (strpos($url, '?') ? '&' : '?').'id_category='.(int)$id_category;
}
}
$url = $this->addPageNumber($url, $page);
return $url;
}
public function getPostLink($id_post, $link_rewrite = false)
{
$url = $this->getBaseUri();
if ($this->friendly_url) {
$link_rewrite = $link_rewrite ? $link_rewrite : $this->getLinkRewriteById('post', $id_post);
$url .= $link_rewrite;
} else {
$url .= (strpos($url, '?') ? '&' : '?').'id_post='.(int)$id_post;
}
return $url;
}
public function getTagLink($tag_url, $page = 1)
{
$url = $this->getBaseUri();
$tag_url = is_array($tag_url) ? implode('+', $tag_url) : $tag_url;
if ($this->friendly_url) {
$url .= 'tags/'.$tag_url.'/';
} else {
$url .= (strpos($url, '?') ? '&' : '?').'tags='.$tag_url;
}
$url = $this->addPageNumber($url, $page);
return $url;
}
public function addPageNumber($url, $page)
{
if ($page > 1) {
$url = rtrim($url, '/');
$url .= $this->friendly_url ? '/'.$page.'/' : (strpos($url, '?') ? '&' : '?').'page='.$page;
}
return $url;
}
public function getBaseUri($params = array())
{
if (empty($this->base_uri)) {
$this->base_uri = $this->context->link->getModuleLink($this->name, 'blog');
}
if ($params) {
$this->base_uri .= (strpos($this->base_uri, '?') ? '&' : '?').http_build_query($params);
}
return $this->base_uri;
}
public function getIdByLinkRewrite($resource_type, $link_rewrite)
{
$id = $this->db->getValue('
SELECT id_'.pSQL($resource_type).' FROM '._DB_PREFIX_.'a_blog_'.pSQL($resource_type).'_lang
WHERE link_rewrite = \''.pSQL($link_rewrite).'\'
AND id_lang = '.(int)$this->id_lang.'
AND id_shop = '.(int)$this->id_shop.'
');
return $id;
}
public function getLinkRewriteById($resource_type, $id)
{
$link_rewrite = $this->db->getValue('
SELECT link_rewrite FROM '._DB_PREFIX_.'a_blog_'.pSQL($resource_type).'_lang
WHERE id_'.pSQL($resource_type).' = '.(int)$id.'
AND id_lang = '.(int)$this->id_lang.'
AND id_shop = '.(int)$this->id_shop.'
');
return $link_rewrite;
}
public function getAuthorNameById($id)
{
$name = $this->db->getRow('
SELECT firstname, lastname FROM '._DB_PREFIX_.'employee WHERE id_employee = '.(int)$id.'
');
return $name['firstname'].' '.$name['lastname'];
}
public function getResourceTitleById($id, $resource_type)
{
$table_name = 'a_blog_'.$resource_type.'_lang';
$title = $this->db->getValue('
SELECT title FROM `'._DB_PREFIX_.bqSQL($table_name).'`
WHERE `id_'.bqSQL($resource_type).'` = '.(int)$id.'
AND `id_lang` = '.(int)$this->context->language->id.'
');
return $title;
}
public function getPostTagsIds($id_post)
{
$query = 'SELECT id_tag FROM '._DB_PREFIX_.'a_blog_post_tag
WHERE id_post = '.(int)$id_post;
return $this->getSortedDataFromDb($query, 'id_tag');
}
public function getPostCategoriesIds($id_post)
{
$query = 'SELECT id_category FROM '._DB_PREFIX_.'a_blog_post_category
WHERE id_post = '.(int)$id_post;
return $this->getSortedDataFromDb($query, 'id_category');
}
public function getSortedDataFromDb($query, $value_col, $key_col = false)
{
$sorted = array();
$raw_data = $this->db->executeS($query);
foreach ($raw_data as $k => $d) {
$key = $key_col ? $d[$key_col] : $k;
$sorted[$key] = $d[$value_col];
}
return $sorted;
}
public function getBlockItems($settings)
{
$items = array();
$resource_type = current(explode('_', $settings['type']));
if ($resource_type == 'post') {
$order_by = $settings['type'] == 'post_random' ? 'RAND()' : 'publish_from';
$order_way = 'DESC';
$additional_filters = array('active' => 1);
if ($settings['type'] == 'post_mostviewed') {
$order_by = 'views';
} elseif ($settings['type'] == 'post_selected' && !empty($settings['post_ids'])) {
$additional_filters['post_ids'] = $settings['post_ids'];
} elseif ($settings['type'] == 'post_relatedtopost' && !empty($this->context->controller->id_post)) {
$id_post = $this->context->controller->id_post;
$related_ids = array();
foreach (array('category', 'tag') as $key) {
if (!empty($settings['related'][$key])) {
$identifier = 'id_'.$key;
$query = 'SELECT '.pSQL($identifier).' FROM '._DB_PREFIX_.'a_blog_post_'.pSQL($key).'
WHERE id_post = '.(int)$id_post;
$key_ids = $this->getSortedDataFromDb($query, $identifier);
if ($key_ids) {
$imploded_ids = implode(', ', $key_ids);
$query = 'SELECT * FROM '._DB_PREFIX_.'a_blog_post_'.pSQL($key).'
WHERE '.pSQL($identifier).' IN ('.pSQL($imploded_ids).') AND id_post <> '.(int)$id_post;
$related_ids += $this->getSortedDataFromDb($query, 'id_post', 'id_post');
}
}
}
if ($related_ids) {
$additional_filters['post_ids'] = implode(',', $related_ids);
} else {
$additional_filters['post_ids'] = '-1';
}
} elseif ($settings['type'] == 'post_relatedtoproduct') {
if (!$related_ids = $this->formatIDs($this->getRelatedIDs('product', Tools::getValue('id_product')))) {
return array();
}
$additional_filters['post_ids'] = $related_ids;
$order_by = 'FIELD(p.id_post, '.$related_ids.')';
$order_way = 'ASC';
}
$pagination_settings = $this->getPaginationSettings('post');
$pagination_settings['npp'] = $settings['num'];
$pagination_settings['p'] = 1;
$items = $this->getPostListInfos(
$pagination_settings,
$order_by,
$order_way,
$additional_filters
);
} elseif ($resource_type == 'product') {
if (!empty($this->context->controller->id_post)) {
$related_ids = $this->getRelatedIDs('post', $this->context->controller->id_post, false);
$items = $this->getProductListInfos($related_ids, $settings);
}
} elseif ($resource_type == 'category') {
$items = $this->getCategoryListInfos($settings);
}
return $items;
}
public function redirectIfTrailingSlashIsMissing()
{
$request = false;
if (isset($_SERVER['REQUEST_URI'])) {
$request = $_SERVER['REQUEST_URI'];
} elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) {
$request = $_SERVER['HTTP_X_REWRITE_URL'];
}
if ($request && Tools::substr($request, - (Tools::strlen($this->slug) + 1)) == '/'.$this->slug) {
Tools::redirect($this->getBaseURI());
}
}
public function hookDisplayHeader()
{
$this->redirectIfTrailingSlashIsMissing();
$this->context->controller->addJqueryPlugin('bxslider');
$this->addCSS('front.css');
if (!empty($this->general_settings['load_icon_fonts'])) {
$this->addCSS('icons.css');
}
$this->addJS('front.js');
Media::addJsDef(array(
'isMobile' => $this->isMobile(),
));
if (!empty($this->context->controller->og_image)) {
$og = '<meta property="og:image" content="'.$this->context->controller->og_image.'">';
return $og;
}
}
public function isMobile()
{
if (empty($this->is_mobile)) {
if (is_callable(array($this->context, 'isMobile'))) {
$this->is_mobile = $this->context->isMobile();
} else {
$this->is_mobile = $this->context->getMobileDetect()->isMobile();
}
}
return $this->is_mobile;
}
public function addRoutesForOtherLanguages($resource_type, $resource_id)
{
if (empty($this->slug_other_languages)) {
return;
}
$rewrite_data = $this->db->executeS('
SELECT link_rewrite, id_lang
FROM '._DB_PREFIX_.'a_blog_'.pSQL($resource_type).'_lang
WHERE id_'.pSQL($resource_type).' = '.(int)$resource_id.'
AND id_lang <> '.(int)$this->id_lang.'
AND id_shop = '.(int)$this->id_shop.'
');
$dispatcher = Dispatcher::getInstance();
foreach ($rewrite_data as $data) {
$link_rewrite = $data['link_rewrite'];
if ($resource_type == 'category' && $resource_id == $this->root_id) {
$link_rewrite = '';
}
$id_lang = $data['id_lang'];
if (!empty($this->slug_other_languages[$id_lang])) {
$slug = $this->slug_other_languages[$id_lang];
$dispatcher->addRoute(
'module-amazzingblog-blog',
$slug.'/'.$link_rewrite,
'blog',
$id_lang,
array('rewrite' => array('regexp' => '[_a-zA-Z0-9-\pL]*')),
array('fc' => 'module', 'module' => $this->name),
$this->id_shop
);
}
}
}
public function prepareHeaderData($resource_type, $resource_id)
{
$this->addRoutesForOtherLanguages($resource_type, $resource_id);
$this->addJS($resource_type.'.js');
$this->addCSS($resource_type.'.css');
if ($resource_type == ' category') {
if ($this->is_17) {
$this->addCSS('category-17.css');
}
} elseif ($resource_type == 'post') {
$this->addCSS('related-products.css');
}
Media::addJsDef(array(
'ab_id_'.$resource_type => $resource_id,
'ab_ajax_path' => $this->getBaseUri(),
));
}
public function addJS($file, $custom_path = '')
{
$path = ($custom_path ? $custom_path : 'modules/'.$this->name.'/views/js/').$file;
if ($this->is_17) {
$params = array('server' => $custom_path ? 'remote' : 'local');
$this->context->controller->registerJavascript(sha1($path), $path, $params);
} else {
$path = $custom_path ? $path : __PS_BASE_URI__.$path;
$this->context->controller->addJS($path);
// $this->context->controller->js_files[] = $path.'?'.microtime(true); // debug
}
}
public function addCSS($file, $custom_path = '', $media = 'all')
{
$path = ($custom_path ? $custom_path : 'modules/'.$this->name.'/views/css/').$file;
if ($this->is_17) {
$params = array('media' => $media, 'server' => $custom_path ? 'remote' : 'local');
$this->context->controller->registerStylesheet(sha1($path), $path, $params);
} else {
$path = $custom_path ? $path : __PS_BASE_URI__.$path;
$this->context->controller->addCSS($path, $media);
// $this->context->controller->css_files[$path.'?'.microtime(true)] = $media; // debug
}
}
public function addPostStats($id_post, $col, $value = false)
{
$value = $value !== false ? $value : $col.' + 1';
$this->db->execute('
INSERT INTO '._DB_PREFIX_.'a_blog_post_stats
(`id_post`, `'.bqSQL($col).'`)
VALUES ('.(int)$id_post.', '.pSQL($value).')
ON DUPLICATE KEY UPDATE `'.bqSQL($col).'` = '.pSQL($value).'
');
}
public function getCommentUser($id_comment)
{
$sql = 'SELECT id_user FROM '._DB_PREFIX_.'a_blog_comment WHERE id_comment = '.(int)$id_comment;
return $this->db->getValue($sql);
}
public function ajaxEditComment()
{
$comment_settings = $this->getSettings('comment');
$id_comment = Tools::getValue('id_comment');
$id_user = $this->getCommentUser($id_comment);
$user_name = $this->getValueAndValidate('user_name', 'isLabel', true);
$content = $this->getValueAndValidate('content', 'isCleanHtml', true, $comment_settings['max_chars']);
if (!empty($this->errors)) {
$this->throwError($this->errors, false);
}
$this->verifyUserName($user_name, $id_user);
$saved = $this->db->execute('
UPDATE '._DB_PREFIX_.'a_blog_comment bc, '._DB_PREFIX_.'a_blog_user u SET
bc.content = \''.pSQL($content).'\',
u.user_name = \''.pSQL($user_name).'\'
WHERE bc.id_comment = '.(int)$id_comment.'
AND u.id_user = bc.id_user
');
if (isset($_FILES['avatar_file'])) {
$sizes = array('avatars' => $comment_settings['avatar']);
$new_avatar = $this->saveSubmittedImage($_FILES['avatar_file'], $this->img_dir_local, false, $sizes, false);
if ($new_avatar) {
$avatar_prev = $this->getCommentAvatar($id_comment);
$this->db->execute('
UPDATE '._DB_PREFIX_.'a_blog_user SET
avatar = \''.pSQL($new_avatar).'\' WHERE avatar = \''.pSQL($avatar_prev).'\'
');
$avatar_prev = $this->img_dir_local.'avatars/'.$avatar_prev;
if (empty($this->errors) && is_file($avatar_prev)) {
unlink($avatar_prev);
}
}
}
$ret = array('updated_html' => $saved ? utf8_encode($this->renderCommentAdmin($id_comment)) : '');
exit(Tools::jsonEncode($ret));
}
public function getCommentAvatar($id_comment)
{
$avatar = $this->db->getValue('
SELECT u.avatar FROM '._DB_PREFIX_.'a_blog_comment c
INNER JOIN '._DB_PREFIX_.'a_blog_user u ON u.id_user = c.id_user
WHERE c.id_comment = '.(int)$id_comment.'
');
return $avatar;
}
public function ajaxSendNotification()
{
$comment_settings = $this->getSettings('comment');
$id_comment = Tools::getValue('id_comment');
$comment_data = $this->db->getRow('
SELECT pl.title, c.*, u.user_name
FROM '._DB_PREFIX_.'a_blog_comment c
LEFT JOIN '._DB_PREFIX_.'a_blog_user u ON c.id_user = u.id_user
LEFT JOIN '._DB_PREFIX_.'a_blog_post_lang pl
ON pl.id_post = c.id_post AND pl.id_lang = '.(int)$this->id_lang.'
WHERE c.id_comment = '.(int)$id_comment.'
');
if (!$comment_data['notif_sent'] && $comment_settings['notif_email']) {
$subject = Configuration::get('PS_SHOP_NAME').': '.$this->l('New comment submitted');
$content = strip_tags($this->bbCodeToHTML($comment_data['content'], false));
$body = $comment_data['title']."\n\n".$comment_data['user_name'].":\n".$content;
if ($sent = $this->sendEmailNotification($comment_settings['notif_email'], $subject, $body)) {
$this->db->execute('
UPDATE '._DB_PREFIX_.'a_blog_comment SET notif_sent = 1 WHERE id_comment = '.(int)$id_comment.'
');
}
}
$ret = array('sent' => $sent);
exit(Tools::jsonEncode($ret));
}
public function sendEmailNotification($to, $subject, $body)
{
if (!Validate::isEmail($to)) {
return false;
}
$from = 'noreply@'.str_replace('www.', '', $_SERVER['HTTP_HOST']);
if (!Validate::isEmail($from)) {
$from = Configuration::get('PS_SHOP_EMAIL');
}
$smtp = $smtp_server = $smtp_login = $smtp_pass = $smtp_encryption = false;
$type = 'text/plain';
$smtp_port = 25;
return Mail::sendMailTest(
$smtp,
$smtp_server,
$body,
$subject,
$type,
$to,
$from,
$smtp_login,
$smtp_pass,
$smtp_port,
$smtp_encryption
);
}
public function verifyIp($ip)
{
$comment_settings = $this->getSettings('comment');
$date_limit = date('Y-m-d H:i:s', strtotime('-1 hour', time()));
$count = $this->db->getValue('
SELECT COUNT(*) FROM '._DB_PREFIX_.'a_blog_comment
WHERE ip = \''.$ip.'\' AND date_add > \''.pSQL($date_limit).'\'
AND id_shop = '.(int)$this->context->shop->id.'
');
if ($count >= $comment_settings['max_comments']) {
$this->throwError($this->l('You cannot post comments so often'));
}
}
public function verifyUserName($user_name, $id_user = false)
{
$sql = 'SELECT * FROM '._DB_PREFIX_.'a_blog_user WHERE user_name = \''.pSQL($user_name).'\'';
if ($id_user) {
$sql .= ' AND id_user <> '.(int)$id_user;
}
if ($this->db->getValue($sql)) {
$err = array('user_name' => $this->l('This name is used by someone else'));
$this->throwError($err, false);
}
}
public function ajaxSubmitComment()
{
$comment_settings = $this->getSettings('comment');
$ip = Tools::getRemoteAddr();
$id_comment = 0;
$id_shop = $this->context->shop->id;
$id_post = Tools::getValue('id_post');
$content = $this->getValueAndValidate('content', 'isCleanHtml', true, $comment_settings['max_chars']);
$user_name = $this->getValueAndValidate('user_name', 'isLabel', true);
if (!empty($this->errors)) {
$this->throwError($this->errors, false);
}
$this->verifyIp($ip);
if (empty($this->context->cookie->id_guest)) {
Guest::setNewGuest($this->context->cookie);
}
$id_user = $this->saveUserData($this->context->cookie->id_guest, $user_name);
$active = 1;
$approved_by = $notif_sent = 0;
$date = date('Y-m-d H:i:s');
$answers = '';
$saved = $this->db->execute('
REPLACE INTO '._DB_PREFIX_.'a_blog_comment VALUES (
'.(int)$id_comment.',
'.(int)$id_shop.',
'.(int)$id_post.',
'.(int)$id_user.',
'.(int)$active.',
'.(int)$approved_by.',
'.(int)$notif_sent.',
\''.pSQL($content).'\',
\''.pSQL($date).'\',
\''.pSQL($date).'\',
\''.pSQL($ip).'\',
\''.pSQL($answers).'\')
');
if (!$id_comment) {
$id_comment = $this->db->Insert_ID();
}
$new_comment_html = '';
if ($saved) {
$this->addPostStats($id_post, 'comments');
$comment = $this->db->getRow('
SELECT * FROM '._DB_PREFIX_.'a_blog_comment c
LEFT JOIN '._DB_PREFIX_.'a_blog_user bu ON bu.id_user = c.id_user
WHERE c.id_comment = '.(int)$id_comment.'
');
$this->context->smarty->assign(array(
'comment' => $comment,
'avatars_dir' => $this->img_dir.'avatars/',
'blog' => $this,
));
if (!empty($comment_settings['instant_publish'])) {
$new_comment_html = $this->display(__FILE__, 'views/templates/front/comment.tpl');
} else {
$msg = $this->l('Thank you for your comment. It will be published soon');
$new_comment_html = $this->displayConfirmation($msg);
}
}
$ret = array(
'new_comment_html' => utf8_encode($new_comment_html),
'id_comment' => $id_comment,
);
exit(Tools::jsonEncode($ret));
}
public function saveUserData($id_guest, $user_name)
{
$comment_settings = $this->getSettings('comment');
$user_data = $this->getUserData($id_guest);
$this->verifyUserName($user_name, $user_data['id_user']);
$requires_saving = !$user_data['id_user'] ? true : ($user_data['user_name'] != $user_name ? true : false);
if (isset($_FILES['avatar_file'])) {
$sizes = array('avatars' => $comment_settings['avatar']);
$new_avatar = $this->saveSubmittedImage($_FILES['avatar_file'], $this->img_dir_local, false, $sizes, false);
if ($new_avatar) {
$avatar_prev = $this->img_dir_local.'avatars/'.$user_data['avatar'];
if (empty($this->errors) && is_file($avatar_prev)) {
unlink($avatar_prev);
}
$user_data['avatar'] = $new_avatar;
$requires_saving = true;
}
}
if (!empty($this->errors)) {
$this->throwError($this->errors, false);
}
if ($requires_saving) {
$this->db->execute('
REPLACE INTO '._DB_PREFIX_.'a_blog_user VALUES (
'.(int)$user_data['id_user'].',
'.(int)$id_guest.',
\''.pSQL($user_name).'\',
\''.pSQL($user_data['avatar']).'\')
');
if (!$user_data['id_user']) {
$user_data['id_user'] = $this->db->Insert_ID();
}
}
return $user_data['id_user'];
}
public function getUserData($id_guest)
{
$user_data = $this->db->getRow('
SELECT * FROM '._DB_PREFIX_.'a_blog_user
WHERE id_guest = '.(int)$id_guest.'
');
if (!$id_guest || !$user_data) {
$user_data = array(
'id_user' => '',
'avatar' => '',
'user_name' => $this->context->customer->firstname,
);
}
return $user_data;
}
public function getValueAndValidate($val, $validate, $required = false, $max_chars = 256)
{
$value = Tools::getValue($val);
if ($required && $value == '') {
$this->errors[$val] = $this->l('Please, fill in this field');
} elseif (!Validate::$validate($value)) {
$this->errors[$val] = $this->l('Incorrect value');
} elseif (is_string($value) && Tools::strlen(pSQL($value)) > $max_chars) {
$this->errors[$val] = $this->l('Max characters limit exceeded');
}
return $value;
}
public function getFullControllerName()
{
if (!isset($this->full_controller_name)) {
$controller = Tools::getValue('controller');
if (Tools::getValue('fc') == 'module' && Tools::isSubmit('module')) {
$controller = 'module-'.Tools::getValue('module').'-'.$controller;
}
$this->full_controller_name = $controller;
}
return $this->full_controller_name;
}
public function getCombinedIDs($ids_string)
{
$ids = $ids_string ? explode(',', $ids_string) : array();
return array_combine($ids, $ids);
}
public function displayNativeHook($hook_name)
{
$current_controller = $this->getFullControllerName();
$current_id = Tools::getValue('id_'.$current_controller);
if ($current_controller == 'module-amazzingblog-blog') {
if (isset($this->context->controller->id_post)) {
$current_controller = 'ab_post';
$current_id = $this->context->controller->id_post;
} elseif (isset($this->context->controller->id_category)) {
$current_controller = 'ab_category';
$current_id = $this->context->controller->id_category;
}
}
$hook_settings = $this->db->getRow('
SELECT * FROM '._DB_PREFIX_.'a_blog_hook_settings
WHERE hook_name = \''.pSQL($hook_name).'\'
');
if (!empty($hook_settings['exc_type'])) {
$type = $hook_settings['exc_type'];
$controllers = array_flip(explode(',', $hook_settings['exc_controllers']));
if (($type == 1 && isset($controllers[$current_controller])) ||
($type == 2 && !isset($controllers[$current_controller]))) {
return;
}
}
$blocks = $this->db->executeS('
SELECT * FROM '._DB_PREFIX_.'a_blog_block b
INNER JOIN '._DB_PREFIX_.'a_blog_block_lang bl
ON b.id_block = bl.id_block
AND bl.id_lang = '.(int)$this->id_lang.'
AND bl.id_shop = '.(int)$this->context->shop->id.'
WHERE active = 1 AND hook_name = \''.pSQL($hook_name).'\'
');
foreach ($blocks as $k => &$block) {
$block['settings'] = Tools::jsonDecode($block['settings'], true);
if (!empty($block['settings']['exceptions'])) {
if ($allowed_controller = str_replace('_all', '', $block['settings']['exceptions']['page']['type'])) {
$allowed_ids = $this->getCombinedIDs($block['settings']['exceptions']['page']['ids']);
if ($allowed_controller != $current_controller ||
($allowed_ids && !isset($allowed_ids[$current_id]))) {
unset($blocks[$k]);
continue;
}
}
if ($customer_exceptions = $block['settings']['exceptions']['customer']['type']) {
$allowed_ids = $this->getCombinedIDs($block['settings']['exceptions']['customer']['ids']);
if ($customer_exceptions == 'customer' && !isset($allowed_ids[$this->context->customer->id])) {
unset($blocks[$k]);
continue;
} elseif ($customer_exceptions == 'group' &&
!array_intersect($this->context->customer->getGroups(), $allowed_ids)) {
unset($blocks[$k]);
continue;
}
}
}
if ($block['settings']['display_type'] == 'carousel') {
$block['encoded_carousel_settings'] = Tools::jsonEncode($block['settings']['carousel']);
}
if ($items = $this->getBlockItems($block['settings'])) {
$block['items'] = $items;
} else {
unset($blocks[$k]);
}
}
$this->context->smarty->assign(array(
'hook_name' => $hook_name,
'is_column_hook' => $this->isColumnHook($hook_name),
'blocks' => $blocks,
'all_link' => $this->getBaseUri(),
'blog' => $this,
'is_17' => $this->is_17,
'currency_iso_code' => $this->context->currency->iso_code,
'cart_page_url' => $this->context->link->getPageLink('cart', true),
));
return $this->display(__FILE__, 'views/templates/hook/blocks.tpl');
}
public function isColumnHook($hook_name)
{
return Tools::substr($hook_name, -6) == 'Column';
}
public function hookDisplayLeftColumn()
{
return $this->displayNativeHook('displayLeftColumn');
}
public function hookDisplayRightColumn()
{
return $this->displayNativeHook('displayRighColumn');
}
public function hookDisplayHome()
{
return $this->displayNativeHook('displayHome');
}
public function hookDisplayPostFooter()
{
return $this->displayNativeHook('displayPostFooter');
}
public function hookDisplayPostAfterComments()
{
return $this->displayNativeHook('displayPostAfterComments');
}
public function hookDisplayFooterProduct()
{
return $this->displayNativeHook('displayFooterProduct');
}
public function hookDisplayBlog1()
{
return $this->displayNativeHook('displayBlog1');
}
public function hookDisplayBlog2()
{
return $this->displayNativeHook('displayBlog2');
}
public function hookDisplayBlog3()
{
return $this->displayNativeHook('displayBlog3');
}
public function prepareDate($date)
{
$month_names = $this->getMonthNames();
$result = array(
'd' => Tools::substr($date, 8, 2),
'm' => $month_names[Tools::substr($date, 5, 2)],
'y' => Tools::substr($date, 0, 4),
);
return $result;
}
public function getMonthNames()
{
$names = array(
'01' => $this->l('JAN'),
'02' => $this->l('FEB'),
'03' => $this->l('MAR'),
'04' => $this->l('APR'),
'05' => $this->l('MAY'),
'06' => $this->l('JUN'),
'07' => $this->l('JUL'),
'08' => $this->l('AUG'),
'09' => $this->l('SEP'),
'10' => $this->l('OCT'),
'11' => $this->l('NOV'),
'12' => $this->l('DEC'),
);
return $names;
}
public function isRegisteredInHookConsideringShop($hook_name, $id_shop)
{
$sql = 'SELECT COUNT(*)
FROM '._DB_PREFIX_.'hook_module hm
LEFT JOIN '._DB_PREFIX_.'hook h ON (h.id_hook = hm.id_hook)
WHERE h.name = \''.pSQL($hook_name).'\'
AND hm.id_shop = '.(int)$id_shop.'
AND hm.id_module = '.(int)$this->id;
return $this->db->getValue($sql);
}
public function bbCodeToHTML($bbtext, $nl2br = true)
{
$bbtags = array(
'[b]' => '<span class="b">', '[/b]' => '</span>',
'[i]' => '<span class="i">', '[/i]' => '</span>',
'[u]' => '<span class="u">', '[/u]' => '</span>',
'[img]' => '<img src="', '[/img]' => '" />',
);
$bbtext = html_entity_decode(str_ireplace(array_keys($bbtags), array_values($bbtags), $bbtext));
if ($nl2br) {
$bbtext = Tools::nl2br($bbtext);
}
return $bbtext;
}
/**
* Copy of ImageMagager::resize with slight modifications for resizing without white borders
*/
public function imageResizeModified(
$src_file,
$dst_file,
$dst_width = null,
$dst_height = null,
$file_type = 'jpg',
$force_type = false
) {
if (PHP_VERSION_ID < 50300) {
clearstatcache();
} else {
clearstatcache(true, $src_file);
}
if (!file_exists($src_file) || !filesize($src_file)) {
$this->throwError($this->l('File doesn\'t exist'));
}
list($src_width, $src_height, $type) = getimagesize($src_file);
// If PS_IMAGE_QUALITY is activated, the generated image will be a PNG with .jpg as a file extension.
// This allow for higher quality and for transparency. JPG source files will also benefit from a higher quality
// because JPG reencoding by GD, even with max quality setting, degrades the image.
if (Configuration::get('PS_IMAGE_QUALITY') == 'png_all'
|| (Configuration::get('PS_IMAGE_QUALITY') == 'png' && $type == IMAGETYPE_PNG) && !$force_type) {
$file_type = 'png';
}
if (!$src_width) {
$this->throwError($this->l('Image dimentions could not be defined'));
}
if (!$dst_width) {
$dst_width = $src_width;
}
if (!$dst_height) {
$dst_height = $src_height;
}
$src_image = ImageManager::create($type, $src_file);
$width_diff = $dst_width / $src_width;
$height_diff = $dst_height / $src_height;
if ($width_diff > 1 && $height_diff > 1) {
$next_width = $src_width;
$next_height = $src_height;
} else {
if ($width_diff < $height_diff) {
$next_height = $dst_height;
$next_width = round(($src_width * $next_height) / $src_height);
// $dst_width = (int)(!Configuration::get('PS_IMAGE_GENERATION_METHOD') ? $dst_width : $next_width);
} else {
$next_width = $dst_width;
$next_height = round($src_height * $dst_width / $src_width);
// $dst_height = (int)(!Configuration::get('PS_IMAGE_GENERATION_METHOD') ? $dst_height : $next_height);
}
}
if (!ImageManager::checkImageMemoryLimit($src_file)) {
$this->throwError($this->l('Not enought memory to process image'));
}
$dest_image = imagecreatetruecolor($dst_width, $dst_height);
// If image is a PNG and the output is PNG, fill with transparency. Else fill with white background.
if ($file_type == 'png' && $type == IMAGETYPE_PNG) {
imagealphablending($dest_image, false);
imagesavealpha($dest_image, true);
$transparent = imagecolorallocatealpha($dest_image, 255, 255, 255, 127);
imagefilledrectangle($dest_image, 0, 0, $dst_width, $dst_height, $transparent);
} else {
$white = imagecolorallocate($dest_image, 255, 255, 255);
imagefilledrectangle($dest_image, 0, 0, $dst_width, $dst_height, $white);
}
$w = ($dst_width - $next_width) / 2;
$h = ($dst_height - $next_height) / 2;
imagecopyresampled(
$dest_image,
$src_image,
(int)$w,
(int)$h,
0,
0,
$next_width,
$next_height,
$src_width,
$src_height
);
return (ImageManager::write($file_type, $dest_image, $dst_file));
}
public function clearFilesAndSetError($error)
{
$this->recursiveRemove($this->local_path.'tmp/', true);
if (Tools::isSubmit('ajax')) {
$this->throwError($error);
}
$this->context->controller->errors[] = $error;
return false;
}
public function recursiveRemove($dir, $top_level = false, $files_to_keep = array())
{
if ($top_level) {
$files_to_keep[] = 'index.php';
}
$structure = glob(rtrim($dir, '/').'/*');
if (is_array($structure)) {
foreach ($structure as $file) {
if (is_dir($file)) {
$this->recursiveRemove($file);
} elseif (is_file($file) && !in_array(basename($file), $files_to_keep)) {
unlink($file);
}
}
}
if (!$top_level) {
rmdir($dir);
}
}
public function throwError($errors, $render_html = true)
{
if (!is_array($errors)) {
$errors = array($errors);
}
$html = '<div class="thrown-errors">'.$this->displayError(implode('<br>', $errors)).'</div>';
if (!Tools::isSubmit('ajax')) {
return $html;
} elseif ($render_html) {
$errors = utf8_encode($html);
}
die(Tools::jsonEncode(array('errors' => $errors)));
}
}