├── Module.php ├── ModuleOverride.php └── README.md /Module.php: -------------------------------------------------------------------------------- 1 | 6 | * @version 0.1a 7 | * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) 8 | */ 9 | class ModuleOverride 10 | { 11 | /** 12 | * The current module name who loaded 13 | * @var string 14 | */ 15 | protected $module_name; 16 | 17 | /** 18 | * Path of module core (in modules/ dir) 19 | * @var string 20 | */ 21 | protected $module_core_path; 22 | 23 | /** 24 | * Filemtime of all overrided module 25 | * @var array 26 | */ 27 | protected $overrided_module; 28 | 29 | /** 30 | * Constructor 31 | * Init the constant and property 32 | * @param string $moduleName 33 | */ 34 | protected function __construct($moduleName) 35 | { 36 | $this->module_name = $moduleName; 37 | 38 | if(!defined('_PS_THEME_CACHE_DIR_')) 39 | define('_PS_THEME_CACHE_DIR_', _PS_THEME_DIR_.'cache'.DS.'modules'.DS); 40 | 41 | if(!is_dir(_PS_THEME_CACHE_DIR_)) 42 | mkdir(_PS_THEME_CACHE_DIR_, 0705); 43 | 44 | $this->module_core_path = _PS_THEME_CACHE_DIR_.$this->module_name.'.core.php'; 45 | 46 | if(file_exists(_PS_THEME_CACHE_DIR_.'module_index.php')) 47 | $this->overrided_module = include _PS_THEME_CACHE_DIR_.'module_index.php'; 48 | 49 | if(!is_array($this->overrided_module)) 50 | $this->overrided_module = array(); 51 | } 52 | 53 | /** 54 | * Load the right classes 55 | * @param string $moduleName 56 | * @static 57 | */ 58 | public static function load($moduleName) 59 | { 60 | $self = new self($moduleName); 61 | $self->_load(); 62 | } 63 | 64 | /** 65 | * Load all classes for this module 66 | */ 67 | protected function _load() 68 | { 69 | // If not override, then we load basic file 70 | if(!file_exists(_PS_THEME_DIR_.'modules/'.$this->module_name.'/'.$this->module_name.'.php')) 71 | { 72 | if(file_exists(_PS_MODULE_DIR_.$this->module_name.'/'.$this->module_name.'.php')) 73 | { 74 | include_once _PS_MODULE_DIR_.$this->module_name.'/'.$this->module_name.'.php'; 75 | } 76 | } 77 | else 78 | { 79 | // else we load the parent class 80 | $this->loadOverridedModule(); 81 | // and the child class 82 | require_once _PS_THEME_DIR_.'modules/'.$this->module_name.'/'.$this->module_name.'.php'; 83 | } 84 | } 85 | 86 | 87 | /** 88 | * Load and generate the parent classe 89 | */ 90 | protected function loadOverridedModule() 91 | { 92 | if(!file_exists($this->module_core_path) || $this->hasChanged()) 93 | $this->generateCodeModuleFile(); 94 | require_once $this->module_core_path; 95 | } 96 | 97 | /** 98 | * Generate the parent class (with change name) 99 | * and update the filemtime file 100 | */ 101 | protected function generateCodeModuleFile() 102 | { 103 | // Rewrite the name class 104 | $moduleCore = preg_replace('/class\s+([a-zA-Z0-9_-]+)/', 'class $1Module', file_get_contents(_PS_MODULE_DIR_.$this->module_name.'/'.$this->module_name.'.php')); 105 | // Rewrite the dirname rules 106 | $moduleCore = preg_replace('/dirname\(__FILE__\)/i', '\''._PS_MODULE_DIR_.$this->module_name.'\'', $moduleCore); 107 | // Replace the private methods by protected (for allowed rewrite in extended classes) 108 | $moduleCore = str_ireplace('private', 'protected', $moduleCore); 109 | 110 | file_put_contents($this->module_core_path, $moduleCore, LOCK_EX); 111 | $this->overrided_module[$this->module_name] = filemtime(_PS_MODULE_DIR_.$this->module_name.'/'.$this->module_name.'.php'); 112 | $this->generateIndex(); 113 | } 114 | 115 | /** 116 | * Return true if the file of parent class was a change 117 | * @return bool 118 | */ 119 | protected function hasChanged() 120 | { 121 | return !array_key_exists($this->module_name, $this->overrided_module) || $this->overrided_module[$this->module_name] != filemtime(_PS_MODULE_DIR_.$this->module_name.'/'.$this->module_name.'.php'); 122 | } 123 | 124 | /** 125 | * Generate file width array of filetime 126 | */ 127 | protected function generateIndex() 128 | { 129 | $content = 'overrided_module, true).'; ?>'; 130 | 131 | // Write classes index on disc to cache it 132 | $filename = _PS_THEME_CACHE_DIR_.'module_index.php'; 133 | if ((file_exists($filename) && !is_writable($filename)) || !is_writable(dirname($filename))) 134 | { 135 | header('HTTP/1.1 503 temporarily overloaded'); 136 | // Cannot use PrestaShopException in this context 137 | die($filename.' is not writable, please give write permissions (chmod 666) on this file.'); 138 | } 139 | else 140 | { 141 | // Let's write index content in cache file 142 | // In order to be sure that this file is correctly written, a check is done on the file content 143 | $loop_protection = 0; 144 | do 145 | { 146 | $integrity_is_ok = false; 147 | file_put_contents($filename, $content, LOCK_EX); 148 | if ($loop_protection++ > 10) 149 | break; 150 | 151 | // If the file content end with PHP tag, integrity of the file is ok 152 | if (preg_match('#\?>\s*$#', file_get_contents($filename))) 153 | $integrity_is_ok = true; 154 | } 155 | while (!$integrity_is_ok); 156 | 157 | if (!$integrity_is_ok) 158 | { 159 | file_put_contents($filename, '', LOCK_EX); 160 | // Cannot use PrestaShopException in this context 161 | die('Your file '.$filename.' is corrupted. Please remove this file, a new one will be regenerated automatically'); 162 | } 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Prestashop override module PHP 2 | 3 | Allow overrrided prestashop module php in `themes/[YOURTHEME]/modules/[THEMODULE]/[THEMODULE].php` 4 | 5 | 6 | ## Installation 7 | 8 | It's very simple, clone (or download) the two classes and paste into `override/module/` director and it's over. 9 | very simple right? 10 | 11 | ## Usage 12 | 13 | Create the same filename of the original module 14 | 15 | `themes/my_theme/modules/blocksearch/blocksearch.php` 16 | 17 | Declare you class and extend the mother with added Module suffix 18 | 19 | ```php 20 | registerHook('displayLeftColumn')) 36 | return false; 37 | return true; 38 | } 39 | 40 | public function hookLeftColumn($params) 41 | { 42 | if (!$this->isCached('blocksearch.tpl', $this->getCacheId())) 43 | { 44 | $this->calculHookCommon($params); 45 | $this->smarty->assign('blocksearch_type', 'block'); 46 | } 47 | return $this->display(__FILE__, 'blocksearch.tpl', $this->getCacheId()); 48 | } 49 | } 50 | ``` --------------------------------------------------------------------------------