From f7b97fee7a90b7aa30087f7727c8dace3cddbc0f Mon Sep 17 00:00:00 2001 From: nPellicari Date: Tue, 6 Mar 2012 09:00:25 +0000 Subject: [PATCH] [*] FO : Add mobile detection and mobile theme dispatcher --- classes/Context.php | 52 ++++++++++++ classes/Dispatcher.php | 4 +- classes/controller/FrontController.php | 105 +++++++++++++++++++++--- config/defines_uri.inc.php | 21 +++++ controllers/front/ContactController.php | 4 +- controllers/front/ProductController.php | 21 +++-- themes/default/layout.tpl | 12 ++- 7 files changed, 197 insertions(+), 22 deletions(-) diff --git a/classes/Context.php b/classes/Context.php index f40f07fe8..a41986e7f 100644 --- a/classes/Context.php +++ b/classes/Context.php @@ -95,6 +95,58 @@ class ContextCore */ public $smarty; + /** + * @var boolean|string mobile device of the customer + */ + protected $mobile_device; + + /** + * @var boolean|string touch pad device of the customer + */ + protected $touchpad_device; + + public function getMobileDevice() + { + if (is_null($this->mobile_device)) + { + $this->mobile_device = false; + if ($this->checkMobileContext()) + if (preg_match('/(alcatel|amoi|android|avantgo|blackberry|benq|cell|cricket|docomo|elaine|htc|iemobile|iphone|ipaq|ipod|j2me|java|midp|mini|mmp|mobi\s|motorola|nec-|nokia|palm|panasonic|philips|phone|sagem|sharp|sie-|smartphone|sony|symbian|t-mobile|telus|up\.browser|up\.link|vodafone|wap|webos|wireless|xda|zte)/i', $_SERVER['HTTP_USER_AGENT'], $out)) + $this->mobile_device = $out[0]; + } + + return $this->mobile_device; + } + + protected function checkMobileContext() + { + return file_exists(_PS_THEME_MOBILE_DIR_) + && Configuration::get('PS_ALLOW_MOBILE_DEVICE') + && isset($_SERVER['HTTP_USER_AGENT']); + } + + protected function getTouchPadDevice() + { + if (is_null($this->touchpad_device)) + { + $this->touchpad_device = false; + if ($this->checkMobileContext()) + { + if (preg_match('/(xoom|ipad)/i', $_SERVER['HTTP_USER_AGENT'], $out)) + $this->touchpad_device = $out[0]; + if (strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'android') && !strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'mobile')) + $this->touchpad_device = 'android'; + + // for Galaxy tab + if (strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'android') + && (strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'sch-i800') + || strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'gt-p1000'))) + $this->touchpad_device = 'android'; + } + } + return $this->touchpad_device; + } + /** * Get a singleton context * diff --git a/classes/Dispatcher.php b/classes/Dispatcher.php index 4f417c341..6ad3142c3 100644 --- a/classes/Dispatcher.php +++ b/classes/Dispatcher.php @@ -251,7 +251,7 @@ class DispatcherCore $controllers['contactform'] = $controllers['contact']; if (!isset($controllers[$this->controller])) - $this->controller = 'pagenotfound'; + $this->controller = $this->controller_not_found; $controller_class = $controllers[$this->controller]; break; @@ -632,7 +632,7 @@ class DispatcherCore $controllers += Dispatcher::getControllersInDirectory($dir.$controller_filename.DIRECTORY_SEPARATOR); else if ($controller_filename != 'index.php') { - $key = str_replace(array('controller.php', '.php'), array('', ''), strtolower($controller_filename)); + $key = str_replace(array('controller.php', '.php'), '', strtolower($controller_filename)); $controllers[$key] = basename($controller_filename, '.php'); } } diff --git a/classes/controller/FrontController.php b/classes/controller/FrontController.php index c73356ec1..e40884983 100755 --- a/classes/controller/FrontController.php +++ b/classes/controller/FrontController.php @@ -295,6 +295,8 @@ class FrontControllerCore extends Controller } $this->context->smarty->assign(array( + // Usefull for layout.tpl + 'mobile_device' => $this->context->getMobileDevice(), 'link' => $link, 'cart' => $cart, 'currency' => $currency, @@ -323,6 +325,12 @@ class FrontControllerCore extends Controller 'b2b_enable' => (bool)Configuration::get('PS_B2B_ENABLE'), 'request' => $link->getPaginationLink(false, false, false, true) )); + + // Add the tpl files directory for mobile + if ($this->context->getMobileDevice() != false) + $this->context->smarty->assign(array( + 'tpl_mobile_uri' => _PS_THEME_MOBILE_DIR_, + )); // Deprecated $this->context->smarty->assign(array( @@ -346,6 +354,10 @@ class FrontControllerCore extends Controller 'js_dir' => _THEME_JS_DIR_, 'pic_dir' => _THEME_PROD_PIC_DIR_ ); + + // Add the images directory for mobile + if ($this->context->getMobileDevice() != false) + $assignArray['img_mobile_dir'] = _THEME_MOBILE_IMG_DIR_; foreach ($assignArray as $assignKey => $assignValue) if (substr($assignValue, 0, 1) == '/' || $protocol_content == 'https://') @@ -405,12 +417,23 @@ class FrontControllerCore extends Controller { $this->process(); - $this->context->smarty->assign(array( - 'HOOK_HEADER' => Hook::exec('displayHeader'), - 'HOOK_TOP' => Hook::exec('displayTop'), - 'HOOK_LEFT_COLUMN' => ($this->display_column_left ? Hook::exec('displayLeftColumn') : ''), - 'HOOK_RIGHT_COLUMN' => ($this->display_column_right ? Hook::exec('displayRightColumn', array('cart' => $this->context->cart)) : ''), - )); + if ($this->context->getMobileDevice() == false) + { + // These hooks aren't used for the mobile theme. + // Needed hooks are called in the tpl files. + $this->context->smarty->assign(array( + 'HOOK_HEADER' => Hook::exec('displayHeader'), + 'HOOK_TOP' => Hook::exec('displayTop'), + 'HOOK_LEFT_COLUMN' => ($this->display_column_left ? Hook::exec('displayLeftColumn') : ''), + 'HOOK_RIGHT_COLUMN' => ($this->display_column_right ? Hook::exec('displayRightColumn', array('cart' => $this->context->cart)) : ''), + )); + } + else + { + $this->context->smarty->assign(array( + 'HOOK_MOBILE_HEADER' => Hook::exec('displayMobileHeader'), + )); + } } /** @@ -432,7 +455,7 @@ class FrontControllerCore extends Controller $this->js_files = Media::cccJs($this->js_files); } - $this->context->smarty->assign('css_files', $this->css_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( @@ -490,7 +513,7 @@ class FrontControllerCore extends Controller $this->js_files = Media::cccJs($this->js_files); } - $this->context->smarty->assign('css_files', $this->css_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, @@ -498,11 +521,12 @@ class FrontControllerCore extends Controller 'display_footer' => $this->display_footer, )); - if (Tools::isSubmit('live_edit')) + // Don't use live edit if on mobile device + if ($this->context->getMobileDevice() == false && Tools::isSubmit('live_edit')) $this->context->smarty->assign('live_edit', $this->getLiveEditFooter()); // handle 1.4 theme (with layout.tpl missing) - if (file_exists(_PS_THEME_DIR_.'layout.tpl')) + if ($this->context->getMobileDevice() != false || file_exists(_PS_THEME_DIR_.'layout.tpl')) { if ($this->template) $this->context->smarty->assign('template', $this->context->smarty->fetch($this->template)); @@ -640,8 +664,28 @@ class FrontControllerCore extends Controller return false; } + /** + * Specific medias for mobile device. + */ + public function setMobileMedia() + { + $this->addCSS(_THEME_MOBILE_CSS_DIR_.'global.css', 'all'); + $this->addCSS(_THEME_MOBILE_CSS_DIR_.'jqm-docs.css', 'all'); + $this->addJS(_THEME_MOBILE_JS_DIR_.'jqm-docs.js'); + $this->addJS(_PS_JS_DIR_.'tools.js'); + $this->addJS(_THEME_MOBILE_JS_DIR_.'global.js'); + $this->addjqueryPlugin('fancybox'); + } + public function setMedia() { + // if website is accessed by mobile device + // @see FrontControllerCore::setMobileMedia() + if ($this->context->getMobileDevice() != false) + { + $this->setMobileMedia(); + return true; + } $this->addCSS(_THEME_CSS_DIR_.'global.css', 'all'); $this->addjquery(); $this->addjqueryPlugin('easing'); @@ -905,5 +949,46 @@ class FrontControllerCore extends Controller else return false; } + + /** + * This is overrided to manage is behaviour + * if a customer access to the site with mobile device. + */ + public function setTemplate($template) + { + if ($this->context->getMobileDevice() != false) + $this->setMobileTemplate($template); + else + parent::setTemplate($template); + } + + /** + * This checks if the template set is available for mobile themes, + * otherwise the front template is choosen. + */ + public function setMobileTemplate($template) + { + $mobile_template = ''; + $tpl_file = basename($template); + $dirname = dirname($template).(substr(dirname($template), -1, 1) == '/' ? '' : '/'); + + if ($dirname == _PS_THEME_DIR_) + { + if (file_exists(_PS_THEME_MOBILE_DIR_.$tpl_file)) + $template = _PS_THEME_MOBILE_DIR_.$tpl_file; + } + else if ($dirname == _PS_THEME_MOBILE_DIR_) + { + if (!file_exists(_PS_THEME_MOBILE_DIR_.$tpl_file) && file_exists(_PS_THEME_DIR_.$tpl_file)) + $template = _PS_THEME_DIR_.$tpl_file; + } + $assign = array(); + $assign['tpl_file'] = basename($tpl_file, '.tpl'); + if (isset($this->php_self)) + $assign['controller_name'] = $this->php_self; + + $this->context->smarty->assign($assign); + $this->template = $template; + } } diff --git a/config/defines_uri.inc.php b/config/defines_uri.inc.php index 74d3a70d8..baa5950e6 100644 --- a/config/defines_uri.inc.php +++ b/config/defines_uri.inc.php @@ -33,6 +33,27 @@ define('_THEME_IMG_DIR_', _THEME_DIR_.'img/'); define('_THEME_CSS_DIR_', _THEME_DIR_.'css/'); define('_THEME_JS_DIR_', _THEME_DIR_.'js/'); +/* For mobile devices */ +if (file_exists(_PS_THEME_DIR_.'mobile/')) +{ + define('_PS_THEME_MOBILE_DIR_', _PS_THEME_DIR_.'mobile/'); + define('_THEME_MOBILE_DIR_', _THEMES_DIR_._THEME_NAME_.'/mobile/'); +} +else +{ + define('_PS_THEME_MOBILE_DIR_', _PS_ROOT_DIR_.'/themes/default/mobile/'); + define('_THEME_MOBILE_DIR_', __PS_BASE_URI__.'themes/default/mobile/'); +} +define('_THEME_MOBILE_IMG_DIR_', _THEME_MOBILE_DIR_.'img/'); +define('_THEME_MOBILE_CSS_DIR_', _THEME_MOBILE_DIR_.'css/'); +define('_THEME_MOBILE_JS_DIR_', _THEME_MOBILE_DIR_.'js/'); + +/* For touch pad devices */ +define('_PS_THEME_TOUCHPAD_DIR_', _PS_THEME_DIR_.'touchpad/'); +define('_THEME_TOUCHPAD_DIR_', _THEMES_DIR_._THEME_NAME_.'/touchpad/'); +define('_THEME_TOUCHPAD_CSS_DIR_', _THEME_MOBILE_DIR_.'css/'); +define('_THEME_TOUCHPAD_JS_DIR_', _THEME_MOBILE_DIR_.'js/'); + /* Image URLs */ define('_PS_IMG_', __PS_BASE_URI__.'img/'); define('_PS_ADMIN_IMG_', _PS_IMG_.'admin/'); diff --git a/controllers/front/ContactController.php b/controllers/front/ContactController.php index 3e39e2b3d..293c005a5 100644 --- a/controllers/front/ContactController.php +++ b/controllers/front/ContactController.php @@ -194,7 +194,9 @@ class ContactControllerCore extends FrontController public function setMedia() { parent::setMedia(); - $this->addCSS(_THEME_CSS_DIR_.'contact-form.css'); + // These CSS isn't used for the mobile theme. + if ($this->context->getMobileDevice() == false) + $this->addCSS(_THEME_CSS_DIR_.'contact-form.css'); } /** diff --git a/controllers/front/ProductController.php b/controllers/front/ProductController.php index 6df70602e..f9438b337 100644 --- a/controllers/front/ProductController.php +++ b/controllers/front/ProductController.php @@ -41,13 +41,20 @@ class ProductControllerCore extends FrontController { parent::setMedia(); - $this->addCSS(_THEME_CSS_DIR_.'product.css'); - $this->addCSS(_PS_CSS_DIR_.'jquery.fancybox-1.3.4.css', 'screen'); - $this->addJqueryPlugin(array('fancybox', 'idTabs', 'scrollTo', 'serialScroll')); - $this->addJS(array( - _THEME_JS_DIR_.'tools.js', - _THEME_JS_DIR_.'product.js') - ); + if ($this->context->getMobileDevice() == false) + { + $this->addCSS(_THEME_CSS_DIR_.'product.css'); + $this->addCSS(_PS_CSS_DIR_.'jquery.fancybox-1.3.4.css', 'screen'); + $this->addJqueryPlugin(array('fancybox', 'idTabs', 'scrollTo', 'serialScroll')); + $this->addJS(array( + _THEME_JS_DIR_.'tools.js', + _THEME_JS_DIR_.'product.js' + )); + } + else + $this->addJS(array( + _THEME_MOBILE_JS_DIR_.'product.js' + )); if (Configuration::get('PS_DISPLAY_JQZOOM') == 1) $this->addJqueryPlugin('jqzoom'); diff --git a/themes/default/layout.tpl b/themes/default/layout.tpl index 7821fe344..74dbd1f30 100644 --- a/themes/default/layout.tpl +++ b/themes/default/layout.tpl @@ -23,14 +23,22 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) * International Registered Trademark & Property of PrestaShop SA *} +{assign var='header_file' value='./header.tpl'} +{assign var='footer_file' value='./footer.tpl'} +{if $mobile_device != false} + {assign var='header_file' value='./mobile/header.tpl'} + {assign var='footer_file' value='./mobile/footer.tpl'} + {assign var='HOOK_HEADER' value=''} +{/if} + {if !empty($display_header)} - {include file='./header.tpl' HOOK_HEADER=$HOOK_HEADER} + {include file=$header_file HOOK_HEADER=$HOOK_HEADER} {/if} {if !empty($template)} {$template} {/if} {if !empty($display_footer)} - {include file='./footer.tpl'} + {include file=$footer_file} {/if} {if !empty($live_edit)} {$live_edit}