diff --git a/admin-dev/ajax.php b/admin-dev/ajax.php index 876370c4c..2919c874e 100644 --- a/admin-dev/ajax.php +++ b/admin-dev/ajax.php @@ -562,11 +562,11 @@ if (Tools::isSubmit('getHookableList')) die('{"hasError" : true, "errors" : ["Live Edit : This functionnality has been disabled"]}'); /* PrestaShop demo mode*/ - if (!strlen(Tools::getValue('hooks_list'))) + if (!count(Tools::getValue('hooks_list'))) die('{"hasError" : true, "errors" : ["Live Edit : no module on this page"]}'); - $modules_list = explode(',', Tools::getValue('modules_list')); - $hooks_list = explode(',', Tools::getValue('hooks_list')); + $modules_list = Tools::getValue('modules_list'); + $hooks_list = Tools::getValue('hooks_list'); $hookableList = array(); foreach ($modules_list as $module) @@ -629,35 +629,34 @@ if (Tools::isSubmit('saveHook')) $res = true; $hookableList = array(); - foreach ($hooks_list as $hook) + // $_POST['hook'] is an array of id_module + $hooks_list = Tools::getValue('hook'); + foreach ($hooks_list as $id_hook => $modules) { - $hook = trim($hook); - if (!$hook) - continue; - - $sql = 'DELETE FROM '._DB_PREFIX_.'hook_module - WHERE id_hook = ( SELECT id_hook - FROM '._DB_PREFIX_.'hook - WHERE `name` = \''.pSQL($hook).'\' LIMIT 1 - ) + // 1st, drop all previous hooked modules + $sql = 'DELETE FROM `'._DB_PREFIX_.'hook_module` + WHERE `id_hook` = '.(int)$id_hook.' AND id_shop = '.$id_shop; $res &= Db::getInstance()->execute($sql); - $hookedModules = explode(',', Tools::getValue($hook)); + $i = 1; $value = ''; $ids = array(); - foreach ($hookedModules as $module) + // then prepare sql query to rehook all chosen modules(id_module, id_shop, id_hook, position) + // position is i (autoincremented) + foreach ($modules as $id_module) { - $id = explode('_', $module); - if (!in_array($id[1], $ids)) + if (!in_array($id_module, $ids)) { - $ids[] = $id[1]; - $value .= '('.(int)$id[1].', '.$id_shop.', (SELECT id_hook FROM `'._DB_PREFIX_.'hook` WHERE `name` = \''.pSQL($hook).'\' LIMIT 0, 1), '.$i.'),'; + $ids[] = $id_module; + $value .= '('.(int)$id_module.', '.$id_shop.', '.(int)$id_hook.', '.$i.'),'; } $i++; } $value = rtrim($value, ','); - $res &= Db::getInstance()->execute('INSERT INTO '._DB_PREFIX_.'hook_module (id_module, id_shop, id_hook, position) VALUES '.$value); + $res &= Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'hook_module` + (id_module, id_shop, id_hook, position) + VALUES '.$value); } if ($res) diff --git a/classes/Controller.php b/classes/Controller.php index 8579d8e89..f5b307835 100644 --- a/classes/Controller.php +++ b/classes/Controller.php @@ -73,6 +73,9 @@ abstract class ControllerCore protected $status = ''; protected $redirect_after = null; + + /** hook_list is used with liveEdit */ + public $hook_list = array(); /** * check that the controller is available for the current user/visitor */ diff --git a/classes/FrontController.php b/classes/FrontController.php index 80740b60c..a890329e3 100755 --- a/classes/FrontController.php +++ b/classes/FrontController.php @@ -374,6 +374,13 @@ class FrontControllerCore extends Controller public function initContent() { $this->process(); + + $this->context->smarty->assign(array( + 'HOOK_HEADER' => Hook::exec('displayHeader'), + 'HOOK_TOP' => Hook::exec('displayTop'), + 'HOOK_LEFT_COLUMN' => Hook::exec('displayLeftColumn'), + 'HOOK_RIGHT_COLUMN' => Hook::exec('displayRightColumn', array('cart' => $this->context->cart)), + )); } public function initCursedPage() @@ -393,23 +400,40 @@ class FrontControllerCore extends Controller public function display() { Tools::safePostVars(); - $this->context->smarty->assign('errors', $this->errors); - if ($this->display_header) - $this->context->smarty->display(_PS_THEME_DIR_.'header.tpl'); - - if ($this->template) - $this->context->smarty->display($this->template); - - if ($this->display_footer) - $this->context->smarty->display(_PS_THEME_DIR_.'footer.tpl'); - - // live edit - if (Tools::isSubmit('live_edit') AND $ad = Tools::getValue('ad') AND (Tools::getValue('liveToken') == sha1(Tools::getValue('ad')._COOKIE_KEY_))) + // assign css_files and js_files at the very last time + if ((Configuration::get('PS_CSS_THEME_CACHE') OR Configuration::get('PS_JS_THEME_CACHE')) AND is_writable(_PS_THEME_DIR_.'cache')) { - $this->context->smarty->assign(array('ad' => $ad, 'live_edit' => true)); - $this->context->smarty->display(_PS_ALL_THEMES_DIR_.'live_edit.tpl'); + // CSS compressor management + if (Configuration::get('PS_CSS_THEME_CACHE')) + $this->css_files = Media::cccCSS($this->css_files); + //JS compressor management + if (Configuration::get('PS_JS_THEME_CACHE')) + $this->js_files = Media::cccJs($this->js_files); } + + $this->context->smarty->assign('css_files', $this->css_files); + $this->context->smarty->assign('js_files', array_unique($this->js_files)); + + $this->context->smarty->assign(array( + 'errors' => $this->errors, + 'display_header' => $this->display_header, + 'display_footer' => $this->display_footer, + 'template' => $this->context->smarty->fetch($this->template), + )); + + + + + if (Tools::isSubmit('live_edit')) + { + $this->context->smarty->assign('live_edit', $this->getLiveEditFooter()); + } + + + $this->context->smarty->display(_PS_THEME_DIR_.'layout.tpl'); + + return true; } /* Display a maintenance page if shop is closed */ @@ -549,31 +573,37 @@ class FrontControllerCore extends Controller 'priceDisplayPrecision' => _PS_PRICE_DISPLAY_PRECISION_, 'content_only' => (int)Tools::getValue('content_only') )); - $this->context->smarty->assign(array( - 'HOOK_HEADER' => Hook::exec('header'), - 'HOOK_TOP' => Hook::exec('top'), - 'HOOK_LEFT_COLUMN' => Hook::exec('leftColumn') - )); - if ((Configuration::get('PS_CSS_THEME_CACHE') OR Configuration::get('PS_JS_THEME_CACHE')) AND is_writable(_PS_THEME_DIR_.'cache')) - { - // CSS compressor management - if (Configuration::get('PS_CSS_THEME_CACHE')) - $this->css_files = Media::cccCSS($this->css_files); - //JS compressor management - if (Configuration::get('PS_JS_THEME_CACHE')) - $this->js_files = Media::cccJs($this->js_files); - } - $this->context->smarty->assign('css_files', $this->css_files); - $this->context->smarty->assign('js_files', array_unique($this->js_files)); + + } public function initFooter() { $this->context->smarty->assign(array( - 'HOOK_RIGHT_COLUMN' => Hook::exec('rightColumn', array('cart' => $this->context->cart)), 'HOOK_FOOTER' => Hook::exec('footer'), )); + + + } + + public function getLiveEditFooter(){ + if (Tools::isSubmit('live_edit') + && ($ad = Tools::getValue('ad')) + && (Tools::getValue('liveToken') == sha1(Tools::getValue('ad')._COOKIE_KEY_)) + ) + { + $data = $this->context->smarty->createData(); + $data->assign(array( + 'ad' => $ad, + 'live_edit' => true, + 'hook_list' => $this->hook_list, + 'id_shop' => $this->context->shop->getId(true) + )); + return $this->context->smarty->createTemplate(_PS_ALL_THEMES_DIR_.'live_edit.tpl', $data)->fetch(); + } + else + return ''; } public function productSort() diff --git a/classes/Hook.php b/classes/Hook.php index 14aad0bec..560a6bb55 100644 --- a/classes/Hook.php +++ b/classes/Hook.php @@ -62,7 +62,7 @@ class HookCore extends ObjectModel return false; $hook_alias_list = Db::getInstance()->executeS('SELECT * FROM `'._DB_PREFIX_.'hook_alias`'); foreach ($hook_alias_list as $ha) - self::$_hook_alias[strtolower($ha['alias'])] = $ha['name']; + self::$_hook_alias[strtolower($ha['name'])] = $ha['alias']; return true; } @@ -220,7 +220,9 @@ class HookCore extends ObjectModel // Get retrocompatible hook name $retro_hook_name = Hook::getRetroHookName($hook_name); - // Get cookie and cart + if (!in_array($hook_name, Context::getContext()->controller->hook_list)) + Context::getContext()->controller->hook_list[Hook::getIdByName($hook_name)] = $hook_name; + $live_edit = false; if (!isset($hookArgs['cookie']) || !$hookArgs['cookie']) $hookArgs['cookie'] = $context->cookie; diff --git a/js/hookLiveEdit.js b/js/hookLiveEdit.js index d9a401908..d7cc85522 100644 --- a/js/hookLiveEdit.js +++ b/js/hookLiveEdit.js @@ -3,123 +3,158 @@ var hooks_list = new Array(); var hookable_list = new Array(); var timer; $(document).ready(function() { - $('body').css('margin-bottom', '45px'); - $('#fancy').fancybox({ - autoDimensions: true, - autoScale: true, - width: 300, - height: 300, - padding: 0, - hideOnOverlayClick: false, - hideOnContentClick: false, - showCloseButton: false - }); - $('#live_edit_feedback_str').html(''); - $('a').each(function() { - var href = $(this).attr('href'); - var search = $(this).attr('search'); - var hrefAdd = 'live_edit&liveToken=' + get('liveToken') + '&ad=' + get('ad') + '&id_shop=' + get('id_shop'); - if (href != undefined && href != '#' && href.substr(0, baseDir.length) == baseDir) { - if (search.length == 0) { - $(this).attr('search', hrefAdd); - } else { - $(this).attr('search', search + '&' + hrefAdd); - } - } - }); - getHookableList(); - $('.unregisterHook').unbind('click').click(function() { - id = $(this).attr('id'); - $(this).parent().parent().parent().fadeOut('slow', function() { - $(this).remove(); - }); - return false; - }); - $('#cancelMove').unbind('click').click(function() { - $('#' + cancelMove + '').sortable('cancel'); - return false; - }); - $('#saveLiveEdit').unbind('click').click(function() { - saveModulePosition(); - return false; - }); - $('#closeLiveEdit').unbind('click').click(function() { - $("#live_edit_feedback_str").html('

' + confirmClose + '

' + confirm + '' + cancel + '

'); - $("#fancy").attr('href', '#live_edit_feedback'); - $("#fancy").trigger("click"); - }); - $('.add_module_live_edit').unbind('click').click(function() { - $("#live_edit_feedback_str").html('
'); - $("#fancy").attr('href', '#live_edit_feedback'); - $("#fancy").trigger("click"); - var id = $(this).attr('id'); - getHookableModuleList(id.substr(4, id.length)); - return false; - }); - $('.dndHook').each(function() { - var id_hook = $(this).attr('id'); - var new_target = ''; - var old_target = ''; - var cancel = false; - $('#' + id_hook + '').sortable({ - opacity: 0.5, - cursor: 'move', - connectWith: '.dndHook', - receive: function(event, ui) { - if (new_target == '') { - new_target = event.target.id; - } - }, - start: function(event, ui) { - new_target = ui.item[0].parentNode.id; - }, - stop: function(event, ui) { - if (cancel) { - $(this).sortable('cancel'); - } else { - old_target = event.target.id; - cancelMove = old_target; - if (new_target == '') new_target = old_target; - } - }, - change: function(event, ui) { - new_target = $(ui.placeholder).parent().attr('id'); - ids = ui.item[0].id.split('_'); - if ($.inArray(ids[5], hookable_list[new_target]) != -1) { - cancel = false; - ui.placeholder.css({ - visibility: 'visible', - border: '1px solid #72CB67', - background: '#DFFAD3' - }); - } else { - ui.placeholder.css({ - visibility: 'visible', - border: '1px solid #EC9B9B', - background: '#FAE2E3' - }); - cancel = true; - } - } - }); - $('#' + id_hook + '').disableSelection(); - }); -}); + // do some place for submit button + $('body').css('margin-bottom', '45px'); + // this is the result box, which will "pop up" the succeed or fail result + $('#fancy').fancybox({ + autoDimensions: true, + autoScale: true, + width: 300, + height: 300, + padding: 0, + hideOnOverlayClick: false, + hideOnContentClick: false, + showCloseButton: false + }); + + $('#live_edit_feedback_str').html(''); + // add liveToken in each link to navigate into the shop and keeping the liveedit mode + $('a').each(function() { + var href = $(this).attr('href'); + var search = $(this).attr('search'); + var hrefAdd = 'live_edit&liveToken=' + get('liveToken') + '&ad=' + get('ad') + '&id_shop=' + get('id_shop'); + if (href != undefined && href != '#' && href.substr(0, baseDir.length) == baseDir) { + if (search.length == 0) + { + $(this).attr('search', hrefAdd); + } + else + { + $(this).attr('search', search + '&' + hrefAdd); + } + } + }); + // populate + getHookableList(); + $('.unregisterHook').unbind('click').click(function() { + id = $(this).attr('id'); + $(this).parent().parent().parent().fadeOut('slow', function() { + $(this).remove(); + }); + return false; + }); + $('#cancelMove').unbind('click').click(function() { + $('#' + cancelMove + '').sortable('cancel'); + return false; + }); + $('#saveLiveEdit').unbind('click').click(function() { + saveModulePosition(); + return false; + }); + $('#closeLiveEdit').unbind('click').click(function() { + $("#live_edit_feedback_str").html('

' + confirmClose + '

' + confirm + '' + cancel + '

'); + $("#fancy").attr('href', '#live_edit_feedback'); + $("#fancy").trigger("click"); + }); + $('.add_module_live_edit').unbind('click').click(function() { + $("#live_edit_feedback_str").html('
'); + $("#fancy").attr('href', '#live_edit_feedback'); + $("#fancy").trigger("click"); + var id = $(this).attr('id'); + getHookableModuleList(id.substr(4, id.length)); + return false; + }); + $('.dndHook').each(function() { + var id_hook = $(this).attr('id'); + var new_target_id = ''; + var old_target = ''; + var cancel = false; + $('#' + id_hook + '').sortable({ + opacity: 0.5, + cursor: 'move', + connectWith: '.dndHook', + receive: function(event, ui) { + if (new_target_id == '') { + new_target_id = event.target.id; + } + }, + start: function(event, ui) { + new_target_id = ui.item[0].parentNode.id; + }, + stop: function(event, ui) { + if (cancel) + { + $(this).sortable('cancel'); + } + else + { + old_target = event.target.id; + cancelMove = old_target; + if (new_target_id == '') + new_target_id = old_target; + ids = $(ui.item[0]).attr('id').split('_'); + newHookId = $("input[value="+new_target_id+"]").attr('name').substr(10); + newHookId = newHookId.substr(0, newHookId.length -1); + new_id = ids[0] + "_" + newHookId + "_" + ids[2] + "_" + ids[3]; + $(ui.item[0]).attr('id', new_id); + } + }, + change: function(evartent, ui) { + new_target_id = $(ui.placeholder).parent().attr('id'); + ids = ui.item[0].id.split('_'); + if ($.inArray(ids[5], hookable_list[new_target_id]) != -1) { + cancel = false; + ui.placeholder.css({ + visibility: 'visible', + border: '1px solid #72CB67', + background: '#DFFAD3' + }); + } + else + { + ui.placeholder.css({ + visibility: 'visible', + border: '1px solid #EC9B9B', + background: '#FAE2E3' + }); + cancel = true; + } + } + }); + // WTF + $('#' + id_hook + '').disableSelection(); + }); +}); +// init hookable_list function getHookableList() { + hooks_list = new Array(); + $("input[name^=hook_list]}").each(function(e){ + hooks_list.push($(this).val()); + // +$(this).val(); + }); + $.ajax({ - type: 'GET', + type: 'POST', url: baseDir + ad + '/ajax.php', async: true, dataType: 'json', - data: 'ajax=true&getHookableList&hooks_list=' + hooks_list + '&modules_list=' + modules_list + '&id_shop=' + get('id_shop'), + data: {ajax:"true", + 'getHookableList':1, + 'hooks_list' : hooks_list, + modules_list : modules_list, + id_shop : get('id_shop') + }, success: function(jsonData) { if (jsonData.hasError) { var errors = ''; for (error in jsonData.errors) //IE6 bug fix - if (error != 'indexOf') errors += jsonData.errors[error] + "\n"; - alert(errors); - } else hookable_list = jsonData; + if (error != 'indexOf') + errors += jsonData.errors[error] + "\n"; + alert(errors); + } + else + hookable_list = jsonData;// create and fill input array }, error: function(XMLHttpRequest, textStatus, errorThrown) { $('#live_edit_feedback_str').html('

TECHNICAL ERROR:

' + loadFail + '

' + close + '
'); @@ -149,6 +184,7 @@ function getHookableModuleList(hook) { }); } function saveModulePosition() { + $("input.dynamic-input-save-position").remove(); $("#live_edit_feedback_str").html('
'); $("#fancy").attr('href', '#live_edit_feedback'); $("#fancy").trigger("click"); @@ -157,47 +193,56 @@ function saveModulePosition() { str += '&' + hooks_list[i] + '='; $('#' + hooks_list[i] + ' > .dndModule').each(function() { ids = $(this).attr('id').split('_'); - str += ids[1] + '_' + ids[3] + ','; + $("#liveEdit-action-form") + .append(''); }); - str = str.substr(0, str.length - 1); + } + $("#liveEdit-action-form") + .append(''); + datas = $("#liveEdit-action-form").serializeArray(); + $.ajax({ - type: 'GET', - url: baseDir + ad + '/ajax.php', + type: 'POST', + url: baseDir + ad + "/ajax.php", async: true, dataType: 'json', - data: 'ajax=true&saveHook&hooks_list=' + hooks_list + str + '&id_shop=' + get('id_shop'), + data: datas, success: function(jsonData) { - $('#live_edit_feedback_str').html('

' + saveOK + '

' + close + '
'); + $('#live_edit_feedback_str').html('

' + saveOK + '

' + close + '
'); timer = setTimeout("hideFeedback()", 3000); }, error: function(XMLHttpRequest, textStatus, errorThrown) { $('#live_edit_feedback_str').html('

TECHNICAL ERROR:

' + unableToSaveModulePosition + '

' + close + '
'); } - }); +} +) + + return true; } function closeFancybox() { - clearTimeout(timer); - $.fancybox.close(); - $('#live_edit_feedback_str').html(''); + clearTimeout(timer); + $.fancybox.close(); + $('#live_edit_feedback_str').html(''); } function closeLiveEdit(){ window.location.href = window.location.protocol+'//'+window.location.host+window.location.pathname; } function hideFeedback() { - $('#live_edit_feed_back').fadeOut('slow', function() { - $.fancybox.close(); - $('#live_edit_feedback_str').html(''); - }); + $('#live_edit_feed_back').fadeOut('slow', function() { + $.fancybox.close(); + $('#live_edit_feedback_str').html(''); + }); }; function get(name) { - var regexS = "[\\?&]" + name + "=([^&#]*)"; - var regex = new RegExp(regexS); - var results = regex.exec(window.location.href); - if (results == null) { - return ""; - } else { - return results[1]; - } + var regexS = "[\\?&]" + name + "=([^&#]*)"; + var regex = new RegExp(regexS); + var results = regex.exec(window.location.href); + if (results == null) { + return ""; + } + else { + return results[1]; + } } diff --git a/themes/default/index.tpl b/themes/default/index.tpl index 04a4a1b6d..319d97a78 100644 --- a/themes/default/index.tpl +++ b/themes/default/index.tpl @@ -24,4 +24,4 @@ * International Registered Trademark & Property of PrestaShop SA *} -{$HOOK_HOME} \ No newline at end of file +{$HOOK_HOME} diff --git a/themes/default/layout.tpl b/themes/default/layout.tpl new file mode 100644 index 000000000..edbec661a --- /dev/null +++ b/themes/default/layout.tpl @@ -0,0 +1,37 @@ +{* +* 2007-2011 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2011 PrestaShop SA +* @version Release: $Revision$ +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} +{if isset($display_header)} + {include file='./header.tpl' HOOK_HEADER=$HOOK_HEADER} +{/if} +{if isset($template)} + {$template} +{/if} +{if isset($display_footer)} + {include file='./footer.tpl'} +{/if} +{if isset($live_edit)} + {$live_edit} +{/if} diff --git a/themes/live_edit.tpl b/themes/live_edit.tpl index 431c933c2..9cc7b0235 100644 --- a/themes/live_edit.tpl +++ b/themes/live_edit.tpl @@ -24,8 +24,8 @@ * International Registered Trademark & Property of PrestaShop SA *}
- +
+ + + {foreach from=$hook_list key=hook_id item=hook_name} + + {/foreach} + +