├── README.md ├── module └── helper.php ├── mvcoverride.php └── mvcoverride.xml /README.md: -------------------------------------------------------------------------------- 1 | Hi everyone, 2 | 3 | thank you for your interest for this plugin. 4 | 5 | Unfortunately, I am running out of time these days, so I won't update it. 6 | 7 | If anyone has a solution to make it better, please feel free to fork it. 8 | 9 | Maybe, I'll come back in a few months, but right now I have a big project that will take all my energies. 10 | 11 | 12 | plg_mvcoverride 13 | =============== 14 | 15 | Joomla plugin to override Joomla MVC. 16 | 17 | Plugin used (and updated for j!3) in these joomla docs : 18 | 19 | [How to override the component mvc from the Joomla! core - Joomla! Documentation](http://docs.joomla.org/How_to_override_the_component_mvc_from_the_Joomla!_core) 20 | 21 | The joomla 2.5.x version is here : 22 | 23 | Plugin Override - Joomla! Extensions Directory 24 | 25 | http://extensions.joomla.org/extensions/style-a-design/templating/15611 26 | 27 | ###Usage example 28 | For a component : 29 | >/templates/yourtemplate/code/com_search/views/search/view.html.php 30 | 31 | For a module : 32 | >/templates/yourtemplate/code/module_name/helper.php 33 | 34 | 35 | ###Issue 36 | No more issue ATM. 37 | 38 | Alex Chartier found a working solution. 39 | 40 | If someone finds an issue, please tell us. 41 | -------------------------------------------------------------------------------- /module/helper.php: -------------------------------------------------------------------------------- 1 | mark('beforeRenderModule ' . $module->module . ' (' . $module->title . ')'); 39 | } 40 | 41 | $app = JFactory::getApplication(); 42 | 43 | // Record the scope. 44 | $scope = $app->scope; 45 | 46 | // Set scope to component name 47 | $app->scope = $module->module; 48 | 49 | // Get module parameters 50 | $params = new JRegistry; 51 | $params->loadString($module->params); 52 | 53 | // Get the template 54 | $template = $app->getTemplate(); 55 | 56 | // Get module path 57 | $module->module = preg_replace('/[^A-Z0-9_\.-]/i', '', $module->module); 58 | $path = JPATH_BASE . '/modules/' . $module->module . '/' . $module->module . '.php'; 59 | self::addIncludePath(JPATH_BASE . '/modules'); 60 | 61 | // Load the module 62 | // $module->user is a check for 1.0 custom modules and is deprecated refactoring 63 | if (empty($module->user)) 64 | { 65 | $lang = JFactory::getLanguage(); 66 | 67 | // 1.5 or Core then 1.6 3PD 68 | $lang->load($module->module, JPATH_BASE, null, false, false) || 69 | $lang->load($module->module, dirname($path), null, false, false) || 70 | $lang->load($module->module, JPATH_BASE, $lang->getDefault(), false, false) || 71 | $lang->load($module->module, dirname($path), $lang->getDefault(), false, false); 72 | 73 | $content = ''; 74 | ob_start(); 75 | include JPath::find(self::addIncludePath(),$module->module . '/' . $module->module . '.php'); 76 | $module->content = ob_get_contents() . $content; 77 | ob_end_clean(); 78 | } 79 | 80 | // Load the module chrome functions 81 | if (!$chrome) 82 | { 83 | $chrome = array(); 84 | } 85 | 86 | include_once JPATH_THEMES . '/system/html/modules.php'; 87 | $chromePath = JPATH_THEMES . '/' . $template . '/html/modules.php'; 88 | 89 | if (!isset($chrome[$chromePath])) 90 | { 91 | if (file_exists($chromePath)) 92 | { 93 | include_once $chromePath; 94 | } 95 | 96 | $chrome[$chromePath] = true; 97 | } 98 | 99 | // Check if the current module has a style param to override template module style 100 | $paramsChromeStyle = $params->get('style'); 101 | 102 | if ($paramsChromeStyle) 103 | { 104 | $attribs['style'] = preg_replace('/^(system|' . $template . ')\-/i', '', $paramsChromeStyle); 105 | } 106 | 107 | // Make sure a style is set 108 | if (!isset($attribs['style'])) 109 | { 110 | $attribs['style'] = 'none'; 111 | } 112 | 113 | // Dynamically add outline style 114 | if ($app->input->getBool('tp') && JComponentHelper::getParams('com_templates')->get('template_positions_display')) 115 | { 116 | $attribs['style'] .= ' outline'; 117 | } 118 | 119 | foreach (explode(' ', $attribs['style']) as $style) 120 | { 121 | $chromeMethod = 'modChrome_' . $style; 122 | 123 | // Apply chrome and render module 124 | if (function_exists($chromeMethod)) 125 | { 126 | $module->style = $attribs['style']; 127 | 128 | ob_start(); 129 | $chromeMethod($module, $params, $attribs); 130 | $module->content = ob_get_contents(); 131 | ob_end_clean(); 132 | } 133 | } 134 | 135 | // Revert the scope 136 | $app->scope = $scope; 137 | 138 | if (constant('JDEBUG')) 139 | { 140 | JProfiler::getInstance('Application')->mark('afterRenderModule ' . $module->module . ' (' . $module->title . ')'); 141 | } 142 | 143 | return $module->content; 144 | } 145 | 146 | /** 147 | * Get the path to a layout for a module 148 | * 149 | * @param string $module The name of the module 150 | * @param string $layout The name of the module layout. If alternative layout, in the form template:filename. 151 | * 152 | * @return string The path to the module layout 153 | * 154 | * @since 11.1 155 | */ 156 | public static function getLayoutPath($module, $layout = 'default') 157 | { 158 | $template = JFactory::getApplication()->getTemplate(); 159 | $defaultLayout = $layout; 160 | 161 | if (strpos($layout, ':') !== false) 162 | { 163 | // Get the template and file name from the string 164 | $temp = explode(':', $layout); 165 | $template = ($temp[0] == '_') ? $template : $temp[0]; 166 | $layout = $temp[1]; 167 | $defaultLayout = ($temp[1]) ? $temp[1] : 'default'; 168 | } 169 | 170 | // Build the template and base path for the layout 171 | $templatePaths = array( 172 | JPATH_THEMES . '/' . $template . '/html/' . $module, 173 | JPATH_BASE . '/modules/' . $module . '/tmpl', 174 | ); 175 | $dPath = JPATH_BASE . '/modules/' . $module . '/tmpl/default.php'; 176 | 177 | // If the template has a layout override use it 178 | if ($tPath = JPath::find($templatePaths,$defaultLayout.'.php')) 179 | { 180 | return $tPath; 181 | } 182 | else 183 | { 184 | return $dPath; 185 | } 186 | } 187 | 188 | /** 189 | * Add a directory where JModuleHelper should search for module. You may 190 | * either pass a string or an array of directories. 191 | * 192 | * @param string $path A path to search. 193 | * 194 | * @return array An array with directory elements 195 | * 196 | * @since 11.1 197 | */ 198 | public static function addIncludePath($path = '') 199 | { 200 | // Force path to array 201 | settype($path, 'array'); 202 | 203 | // Loop through the path directories 204 | foreach ($path as $dir) 205 | { 206 | if (!empty($dir) && !in_array($dir, self::$includePaths)) 207 | { 208 | jimport('joomla.filesystem.path'); 209 | array_unshift(self::$includePaths, JPath::clean($dir)); 210 | 211 | //fix to override include path priority 212 | self::$includePaths = array_reverse(self::$includePaths); 213 | } 214 | } 215 | 216 | return self::$includePaths; 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /mvcoverride.php: -------------------------------------------------------------------------------- 1 | getShortVersion(), "3.8", "lt")) 21 | { 22 | if (version_compare($jV->getShortVersion(), "3", "lt")) 23 | $loc = '/joomla/application/module/'; 24 | else 25 | $loc = '/cms/module/'; 26 | 27 | //override JModuleHelper library class 28 | $moduleHelperContent = JFile::read(JPATH_LIBRARIES . $loc . 'helper.php'); 29 | $moduleHelperContent = str_replace('JModuleHelper', 'JModuleHelperLibraryDefault', $moduleHelperContent); 30 | $moduleHelperContent = str_replace('input->get('option'); 52 | 53 | if( empty($option) && JFactory::getApplication()->isSite() ) { 54 | $menuDefault = JFactory::getApplication()->getMenu()->getDefault(); 55 | if ($menuDefault == 0) return; 56 | 57 | $componentID = $menuDefault->componentid; 58 | $db = JFactory::getDBO(); 59 | 60 | //corrected by vdrover 61 | $db->setQuery('SELECT * FROM #__extensions WHERE extension_id ='.$db->quote($componentID)); 62 | $component = $db->loadObject(); 63 | $option = $component->element; 64 | } 65 | 66 | //get files that can be overrided 67 | $componentOverrideFiles = $this->loadComponentFiles($option); 68 | //application name 69 | $applicationName = JFactory::getApplication()->getName(); 70 | //template name 71 | $template = JFactory::getApplication()->getTemplate(); 72 | 73 | //code paths 74 | $includePath = array(); 75 | //template code path 76 | $includePath[] = JPATH_THEMES.'/'.$template.'/code'; 77 | //base extensions path 78 | $includePath[] = JPATH_BASE.'/code'; 79 | 80 | JModelLegacy::addIncludePath(JPATH_BASE.'/code/modules'); 81 | JModelLegacy::addIncludePath(JPATH_THEMES.'/'.$template.'/code/modules'); 82 | 83 | 84 | //constants to replace JPATH_COMPONENT, JPATH_COMPONENT_SITE and JPATH_COMPONENT_ADMINISTRATOR 85 | define('JPATH_SOURCE_COMPONENT',JPATH_BASE.'/components/'.$option); 86 | define('JPATH_SOURCE_COMPONENT_SITE',JPATH_SITE.'/components/'.$option); 87 | define('JPATH_SOURCE_COMPONENT_ADMINISTRATOR',JPATH_ADMINISTRATOR.'/components/'.$option); 88 | 89 | //loading override files 90 | if( !empty($componentOverrideFiles) ){ 91 | foreach($componentOverrideFiles as $componentFile) 92 | { 93 | if($filePath = $this->findPath($includePath,$componentFile)) 94 | { 95 | //include the original code and replace class name add a Default on 96 | if ($this->params->get('extendDefault',0)) 97 | { 98 | $bufferFile = file_get_contents(JPATH_BASE.'/components/'.$componentFile); 99 | //detect if source file use some constants 100 | preg_match_all('/JPATH_COMPONENT(_SITE|_ADMINISTRATOR)|JPATH_COMPONENT/i', $bufferFile, $definesSource); 101 | 102 | $bufferOverrideFile = file_get_contents($filePath); 103 | //detect if override file use some constants 104 | preg_match_all('/JPATH_COMPONENT(_SITE|_ADMINISTRATOR)|JPATH_COMPONENT/i', $bufferOverrideFile, $definesSourceOverride); 105 | 106 | // Append "Default" to the class name (ex. ClassNameDefault). We insert the new class name into the original regex match to get 107 | $rx = '/class *[a-z0-0]* *(extends|{)/i'; 108 | 109 | preg_match($rx, $bufferFile, $classes); 110 | 111 | $parts = explode(' ',$classes[0]); 112 | 113 | $originalClass = $parts[1]; 114 | $replaceClass = $originalClass.'Default'; 115 | 116 | if (count($definesSourceOverride[0])) 117 | { 118 | 119 | //throw new Exception(JText::_('Ckjhkjhkjh')); 120 | throw new Exception(JText::_('Plugin MVC Override','Your override file use constants, please replace code constants
JPATH_COMPONENT -> JPATH_SOURCE_COMPONENT,
JPATH_COMPONENT_SITE -> JPATH_SOURCE_COMPONENT_SITE and
JPATH_COMPONENT_ADMINISTRATOR -> JPATH_SOURCE_COMPONENT_ADMINISTRATOR')); 121 | } 122 | else 123 | { 124 | //replace original class name by default 125 | $bufferContent = str_replace($originalClass,$replaceClass,$bufferFile); 126 | 127 | //replace JPATH_COMPONENT constants if found, because we are loading before define these constants 128 | if (count($definesSource[0])) 129 | { 130 | $bufferContent = preg_replace(array('/JPATH_COMPONENT/','/JPATH_COMPONENT_SITE/','/JPATH_COMPONENT_ADMINISTRATOR/'),array('JPATH_SOURCE_COMPONENT','JPATH_SOURCE_COMPONENT_SITE','JPATH_SOURCE_COMPONENT_ADMINISTRATOR'),$bufferContent); 131 | } 132 | 133 | // Change private methods to protected methods 134 | if ($this->params->get('changePrivate',0)) 135 | { 136 | $bufferContent = preg_replace('/private *function/i', 'protected function', $bufferContent); 137 | } 138 | 139 | // Finally we can load the base class 140 | eval('?>'.$bufferContent.PHP_EOL.'?>'); 141 | 142 | require_once $filePath; 143 | } 144 | } 145 | else 146 | { 147 | require_once $filePath; 148 | } 149 | } 150 | } 151 | } 152 | } 153 | 154 | /** 155 | * loadComponentFiles function. 156 | * 157 | * @access private 158 | * @param mixed $option 159 | * @return void 160 | */ 161 | private function loadComponentFiles($option) 162 | { 163 | $JPATH_COMPONENT = JPATH_BASE.'/components/'.$option; 164 | $files = array(); 165 | 166 | //check if default controller exists 167 | if (JFile::exists($JPATH_COMPONENT.'/controller.php')) 168 | { 169 | $files[] = $JPATH_COMPONENT.'/controller.php'; 170 | } 171 | 172 | //check if controllers folder exists 173 | if (JFolder::exists($JPATH_COMPONENT.'/controllers')) 174 | { 175 | $controllers = JFolder::files($JPATH_COMPONENT.'/controllers', '.php', false, true); 176 | $files = array_merge($files, $controllers); 177 | } 178 | 179 | //check if models folder exists 180 | if (JFolder::exists($JPATH_COMPONENT.'/models')) 181 | { 182 | $models = JFolder::files($JPATH_COMPONENT.'/models', '.php', false, true); 183 | $files = array_merge($files, $models); 184 | } 185 | 186 | //check if views folder exists 187 | if (JFolder::exists($JPATH_COMPONENT.'/views')) 188 | { 189 | //reading view folders 190 | $views = JFolder::folders($JPATH_COMPONENT.'/views'); 191 | foreach ($views as $view) 192 | { 193 | //get view formats files 194 | $viewsFiles = JFolder::files($JPATH_COMPONENT.'/views/'.$view, '.php', false, true); 195 | $files = array_merge($files, $viewsFiles); 196 | } 197 | } 198 | 199 | $return = array(); 200 | //cleaning files 201 | foreach ($files as $file) 202 | { 203 | $file = JPath::clean($file); 204 | $file = substr($file, strlen(JPATH_BASE.'/components/')); 205 | $return[] = $file; 206 | } 207 | 208 | return $return; 209 | } 210 | /** 211 | * findPath function. 212 | * Replacement for JPATH::find, if the target path is a symlink JPATH::find fails 213 | * 214 | * @access private 215 | * @param mixed $option 216 | * @return void 217 | */ 218 | private function findPath($paths, $file) 219 | { 220 | // Force to array 221 | if (!is_array($paths) && !($paths instanceof Iterator)) 222 | { 223 | settype($paths, 'array'); 224 | } 225 | 226 | // Start looping through the path set 227 | foreach ($paths as $path) 228 | { 229 | // Get the path to the file 230 | $fullname = $path . '/' . $file; 231 | 232 | if (file_exists($fullname)) 233 | { 234 | return $fullname; 235 | } 236 | } 237 | 238 | // Could not find the file in the set of paths 239 | return false; 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /mvcoverride.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | System - MVC Override 4 | Julio Pontes - modified by Alex Chartier and Ghazal 5 | December 2014 6 | Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved. 7 | http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL 8 | http://twitter.com/juliopontes 9 | 3.3 10 | Provides a component MVC override. 11 | 12 | mvcoverride.php 13 | module 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 |
29 |
30 | --------------------------------------------------------------------------------