Created
April 12, 2012 03:44
-
-
Save colinmollenhour/2364485 to your computer and use it in GitHub Desktop.
Magento merged CS/JSS improvements
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Magento | |
* | |
* NOTICE OF LICENSE | |
* | |
* This source file is subject to the Open Software License (OSL 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/osl-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 [email protected] so we can send you a copy immediately. | |
* | |
* DISCLAIMER | |
* | |
* Do not edit or add to this file if you wish to upgrade Magento to newer | |
* versions in the future. If you wish to customize Magento for your | |
* needs please refer to http://www.magentocommerce.com for more information. | |
* | |
* @category Mage | |
* @package Mage_Core | |
* @copyright Copyright (c) 2010 Magento Inc. (http://www.magentocommerce.com) | |
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) | |
*/ | |
class Template_Core_Model_Design_Package extends Mage_Core_Model_Design_Package | |
{ | |
const CACHE_KEY = 'design_merged'; | |
const CACHE_TAG = 'design_merged'; | |
protected $_locked = FALSE; | |
protected $_baseMergedUrl; | |
/** | |
* Merge specified css files and return URL to the merged file on success | |
* | |
* @param $files | |
* @return string | |
*/ | |
public function getMergedCssUrl($files) | |
{ | |
// Find the most recent modified time of all files to include in target filename hash so that | |
// modifications invalidate browser's caching | |
$filenamesHash = md5(implode(',', $files)); | |
$newestCacheKey = 'DESIGN_NEWEST_CSS_'.$filenamesHash; | |
if( ! Mage::app()->useCache(self::CACHE_KEY) || ! ($newest = Mage::app()->loadCache($newestCacheKey))) { | |
$newest = 0; | |
foreach($files as $file) { | |
$mtime = filemtime($file); | |
if($mtime > $newest) $newest = $mtime; | |
} | |
Mage::app()->saveCache($newest, $newestCacheKey, array(self::CACHE_TAG)); | |
} | |
$targetFilename = md5(implode('-',array( | |
Mage::getBaseUrl('skin'), // In case skin url is updated | |
$filenamesHash, // In case file is added or removed | |
$newest, // In case file is updated | |
isset($_SERVER['HTTPS']), // Vary for http/https in skin image urls | |
))); | |
$targetDir = $this->_initMergerDir('css'); | |
if (!$targetDir) { | |
return ''; | |
} | |
$targetPath = $targetDir . DS . $targetFilename; | |
// Check for minified version (minified by external app) | |
if(file_exists($targetPath.'-min.css')) { | |
return $this->_getBaseMergedUrl() . 'css/' . $targetFilename.'-min.css'; | |
} | |
// Check for non-minified version | |
else if(file_exists($targetPath.'.css')) { | |
return $this->_getBaseMergedUrl() . 'css/' . $targetFilename.'.css'; | |
} | |
// Files need to be merged | |
if (Mage::helper('core')->mergeFiles($files, $targetPath.'.css', false, array($this, 'beforeMergeCss'), 'css')) { | |
return $this->_getBaseMergedUrl() . 'css/' . $targetFilename.'.css'; | |
} | |
return ''; | |
} | |
/** | |
* Merge specified javascript files and return URL to the merged file on success | |
* | |
* @param $files | |
* @return string | |
*/ | |
public function getMergedJsUrl($files) | |
{ | |
// Find the most recent modified time of all files to include in target filename hash so that | |
// modifications invalidate browser's caching | |
$filenamesHash = md5(implode(',', $files)); | |
$newestCacheKey = 'DESIGN_NEWEST_JS_'.$filenamesHash; | |
if( ! Mage::app()->useCache(self::CACHE_KEY) || ! ($newest = Mage::app()->loadCache($newestCacheKey))) { | |
$newest = 0; | |
foreach($files as $file) { | |
$mtime = filemtime($file); | |
if($mtime > $newest) $newest = $mtime; | |
} | |
Mage::app()->saveCache($newest, $newestCacheKey, array(self::CACHE_TAG)); | |
} | |
$targetFilename = md5(implode('-',array( | |
Mage::getBaseUrl('skin'), // In case skin url is updated | |
$filenamesHash, // In case file is added or removed | |
$newest, // In case file is updated | |
))); | |
$targetDir = $this->_initMergerDir('js'); | |
if (!$targetDir) { | |
return ''; | |
} | |
$targetPath = $targetDir . DS . $targetFilename; | |
// Check for minified version (minified by external app) | |
if(file_exists($targetPath.'-min.js')) { | |
return $this->_getBaseMergedUrl() . 'js/' . $targetFilename.'-min.js'; | |
} | |
// Check for non-minified version | |
else if(file_exists($targetPath.'.js')) { | |
return $this->_getBaseMergedUrl() . 'js/' . $targetFilename.'.js'; | |
} | |
// Files need to be merged | |
if (Mage::helper('core')->mergeFiles($files, $targetPath.'.js', false, null, 'js')) { | |
return $this->_getBaseMergedUrl() . 'js/' . $targetFilename.'.js'; | |
} | |
return ''; | |
} | |
/** | |
* Equivalent to Mage::getBaseUrl('merged') without overriding Mage_Core_Model_Store | |
* | |
* @return string | |
*/ | |
protected function _getBaseMergedUrl() | |
{ | |
if( ! $this->_baseMergedUrl) { | |
$this->_baseMergedUrl = Mage::app()->getStore()->getConfig( | |
'web/'.(Mage::app()->getStore()->isCurrentlySecure() ? 'secure' : 'unsecure').'/base_merged_url' | |
); | |
} | |
return $this->_baseMergedUrl; | |
} | |
/** | |
* Overridden to do nothing since there is never any reason to clean these with the new hashing scheme | |
* | |
* @return bool | |
*/ | |
public function cleanMergedJsCss() | |
{ | |
return TRUE; | |
} | |
/** | |
* Make sure merger dir exists and writeable | |
* Also can clean it up | |
* MODIFIED to not remove the directory itself since it is watched by inotify | |
* | |
* @param string $dirRelativeName | |
* @param bool $cleanup | |
* @return bool|string | |
*/ | |
protected function _initMergerDir($dirRelativeName, $cleanup = false) | |
{ | |
try { | |
$dir = Mage::getBaseDir('media') . DS . $dirRelativeName; | |
if ($cleanup && is_dir($dir)) { | |
array_map('unlink', glob("$dir/*.*")); | |
} | |
if (!is_dir($dir)) { | |
mkdir($dir); | |
} | |
return is_writeable($dir) ? $dir : false; | |
} catch (Exception $e) { | |
Mage::logException($e); | |
} | |
return false; | |
} | |
/** | |
* Prepare url for css replacement | |
* MODIFIED to use real skin url (for CDN compatibility) | |
* | |
* @param string $uri | |
* @return string | |
*/ | |
protected function _prepareUrl($uri) | |
{ | |
// check absolute or relative url | |
if (!preg_match('/^[http|https]/i', $uri) && !preg_match('/^\//i', $uri)) { | |
$fileDir = ''; | |
$pathParts = explode(DS, $uri); | |
$fileDirParts = explode(DS, $this->_callbackFileDir); | |
foreach ($pathParts as $key=>$part) { | |
if ($part == '.' || $part == '..') { | |
unset($pathParts[$key]); | |
} | |
if ($part == '..' && count($fileDirParts)) { | |
$fileDirParts = array_slice($fileDirParts, 0, count($fileDirParts) - 1); | |
} | |
} | |
if (count($fileDirParts)) { | |
$fileDir = implode('/', $fileDirParts).'/'; | |
} | |
$uri = $fileDir.implode('/', $pathParts); | |
if (substr($uri,0,5) == 'skin/') { | |
$uri = Mage::getBaseUrl('skin').substr($uri,5); | |
} else { | |
$uri = Mage::getBaseUrl('web').$uri; | |
} | |
} | |
return $uri; | |
} | |
/** | |
* Takes one or two parameters (set all or set one type) | |
* | |
* Overridden to allow a theme to be "locked", so that later code cannot override the theme (e.g. for mobile version) | |
* | |
* @return \Template_Core_Model_Design_Package | |
*/ | |
public function setTheme() | |
{ | |
if($this->_locked) { | |
return $this; | |
} | |
switch (func_num_args()) { | |
case 1: | |
foreach (array('layout', 'template', 'skin', 'locale') as $type) { | |
$this->_theme[$type] = func_get_arg(0); | |
} | |
break; | |
case 2: | |
$this->_theme[func_get_arg(0)] = func_get_arg(1); | |
break; | |
default: | |
throw Mage::exception(Mage::helper('core')->__('Wrong number of arguments for %s', __METHOD__)); | |
} | |
return $this; | |
} | |
/** | |
* Overridden to allow a package to be "locked", so that later code cannot override the theme (e.g. for mobile version) | |
* | |
* @param string $name | |
* @return Mage_Core_Model_Design_Package | |
*/ | |
public function setPackageName($name = '') | |
{ | |
if($this->_locked) { | |
return $this; | |
} | |
return parent::setPackageName($name); | |
} | |
/** | |
* Locks the theme and package to the existing theme and package | |
*/ | |
public function lockPackageTheme() | |
{ | |
$this->_locked = TRUE; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment