PageRenderTime 53ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/app/code/core/Mage/Core/Model/Design/Package.php

https://bitbucket.org/andrewjleavitt/magestudy
PHP | 834 lines | 488 code | 82 blank | 264 comment | 75 complexity | 886a8a1d104d517f703a453a9c91157b MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, GPL-2.0, WTFPL
  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Mage
  22. * @package Mage_Core
  23. * @copyright Copyright (c) 2010 Magento Inc. (http://www.magentocommerce.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. class Mage_Core_Model_Design_Package
  27. {
  28. const DEFAULT_AREA = 'frontend';
  29. const DEFAULT_PACKAGE = 'default';
  30. const DEFAULT_THEME = 'default';
  31. const BASE_PACKAGE = 'base';
  32. /**
  33. * @deprecated after 1.4.0.0-alpha3
  34. */
  35. const FALLBACK_THEME = 'default';
  36. private static $_regexMatchCache = array();
  37. private static $_customThemeTypeCache = array();
  38. /**
  39. * Current Store for generation ofr base_dir and base_url
  40. *
  41. * @var string|integer|Mage_Core_Model_Store
  42. */
  43. protected $_store = null;
  44. /**
  45. * Package area
  46. *
  47. * @var string
  48. */
  49. protected $_area;
  50. /**
  51. * Package name
  52. *
  53. * @var string
  54. */
  55. protected $_name;
  56. /**
  57. * Package theme
  58. *
  59. * @var string
  60. */
  61. protected $_theme;
  62. /**
  63. * Package root directory
  64. *
  65. * @var string
  66. */
  67. protected $_rootDir;
  68. /**
  69. * Directory of the css file
  70. * Using only to transmit additional parametr in callback functions
  71. * @var string
  72. */
  73. protected $_callbackFileDir;
  74. protected $_config = null;
  75. /**
  76. * Whether theme/skin hierarchy should be checked via fallback mechanism
  77. * @TODO: implement setter for this value
  78. * @var bool
  79. */
  80. protected $_shouldFallback = true;
  81. /**
  82. * Set store
  83. *
  84. * @param string|integer|Mage_Core_Model_Store $store
  85. * @return Mage_Core_Model_Design_Package
  86. */
  87. public function setStore($store)
  88. {
  89. $this->_store = $store;
  90. return $this;
  91. }
  92. /**
  93. * Retrieve store
  94. *
  95. * @return string|integer|Mage_Core_Model_Store
  96. */
  97. public function getStore()
  98. {
  99. if ($this->_store === null) {
  100. return Mage::app()->getStore();
  101. }
  102. return $this->_store;
  103. }
  104. /**
  105. * Set package area
  106. *
  107. * @param string $area
  108. * @return Mage_Core_Model_Design_Package
  109. */
  110. public function setArea($area)
  111. {
  112. $this->_area = $area;
  113. return $this;
  114. }
  115. /**
  116. * Retrieve package area
  117. *
  118. * @return unknown
  119. */
  120. public function getArea()
  121. {
  122. if (is_null($this->_area)) {
  123. $this->_area = self::DEFAULT_AREA;
  124. }
  125. return $this->_area;
  126. }
  127. /**
  128. * Set package name
  129. * In case of any problem, the default will be set.
  130. *
  131. * @param string $name
  132. * @return Mage_Core_Model_Design_Package
  133. */
  134. public function setPackageName($name = '')
  135. {
  136. if (empty($name)) {
  137. // see, if exceptions for user-agents defined in config
  138. $customPackage = $this->_checkUserAgentAgainstRegexps('design/package/ua_regexp');
  139. if ($customPackage) {
  140. $this->_name = $customPackage;
  141. }
  142. else {
  143. $this->_name = Mage::getStoreConfig('design/package/name', $this->getStore());
  144. }
  145. }
  146. else {
  147. $this->_name = $name;
  148. }
  149. // make sure not to crash, if wrong package specified
  150. if (!$this->designPackageExists($this->_name, $this->getArea())) {
  151. $this->_name = self::DEFAULT_PACKAGE;
  152. }
  153. return $this;
  154. }
  155. /**
  156. * Set store/package/area at once, and get respective values, that were before
  157. *
  158. * $storePackageArea must be assoc array. The keys may be:
  159. * 'store', 'package', 'area'
  160. *
  161. * @param array $storePackageArea
  162. * @return array
  163. */
  164. public function setAllGetOld($storePackageArea)
  165. {
  166. $oldValues = array();
  167. if (array_key_exists('store', $storePackageArea)) {
  168. $oldValues['store'] = $this->getStore();
  169. $this->setStore($storePackageArea['store']);
  170. }
  171. if (array_key_exists('area', $storePackageArea)) {
  172. $oldValues['area'] = $this->getArea();
  173. $this->setArea($storePackageArea['area']);
  174. }
  175. if (array_key_exists('package', $storePackageArea)) {
  176. $oldValues['package'] = $this->getPackageName();
  177. $this->setPackageName($storePackageArea['package']);
  178. }
  179. return $oldValues;
  180. }
  181. /**
  182. * Retrieve package name
  183. *
  184. * @return string
  185. */
  186. public function getPackageName()
  187. {
  188. if (null === $this->_name) {
  189. $this->setPackageName();
  190. }
  191. return $this->_name;
  192. }
  193. public function designPackageExists($packageName, $area = self::DEFAULT_AREA)
  194. {
  195. return is_dir(Mage::getBaseDir('design') . DS . $area . DS . $packageName);
  196. }
  197. /**
  198. * Declare design package theme params
  199. * Polymorph method:
  200. * 1) if 1 parameter specified, sets everything to this value
  201. * 2) if 2 parameters, treats 1st as key and 2nd as value
  202. *
  203. * @return Mage_Core_Model_Design_Package
  204. */
  205. public function setTheme()
  206. {
  207. switch (func_num_args()) {
  208. case 1:
  209. foreach (array('layout', 'template', 'skin', 'locale') as $type) {
  210. $this->_theme[$type] = func_get_arg(0);
  211. }
  212. break;
  213. case 2:
  214. $this->_theme[func_get_arg(0)] = func_get_arg(1);
  215. break;
  216. default:
  217. throw Mage::exception(Mage::helper('core')->__('Wrong number of arguments for %s', __METHOD__));
  218. }
  219. return $this;
  220. }
  221. public function getTheme($type)
  222. {
  223. if (empty($this->_theme[$type])) {
  224. $this->_theme[$type] = Mage::getStoreConfig('design/theme/'.$type, $this->getStore());
  225. if ($type!=='default' && empty($this->_theme[$type])) {
  226. $this->_theme[$type] = $this->getTheme('default');
  227. if (empty($this->_theme[$type])) {
  228. $this->_theme[$type] = self::DEFAULT_THEME;
  229. }
  230. // "locale", "layout", "template"
  231. }
  232. }
  233. // + "default", "skin"
  234. // set exception value for theme, if defined in config
  235. $customThemeType = $this->_checkUserAgentAgainstRegexps("design/theme/{$type}_ua_regexp");
  236. if ($customThemeType) {
  237. $this->_theme[$type] = $customThemeType;
  238. }
  239. return $this->_theme[$type];
  240. }
  241. public function getDefaultTheme()
  242. {
  243. return self::DEFAULT_THEME;
  244. }
  245. public function updateParamDefaults(array &$params)
  246. {
  247. if ($this->getStore()) {
  248. $params['_store'] = $this->getStore();
  249. }
  250. if (empty($params['_area'])) {
  251. $params['_area'] = $this->getArea();
  252. }
  253. if (empty($params['_package'])) {
  254. $params['_package'] = $this->getPackageName();
  255. }
  256. if (empty($params['_theme'])) {
  257. $params['_theme'] = $this->getTheme( (isset($params['_type'])) ? $params['_type'] : '' );
  258. }
  259. if (empty($params['_default'])) {
  260. $params['_default'] = false;
  261. }
  262. return $this;
  263. }
  264. public function getBaseDir(array $params)
  265. {
  266. $this->updateParamDefaults($params);
  267. $baseDir = (empty($params['_relative']) ? Mage::getBaseDir('design').DS : '').
  268. $params['_area'].DS.$params['_package'].DS.$params['_theme'].DS.$params['_type'];
  269. return $baseDir;
  270. }
  271. public function getSkinBaseDir(array $params=array())
  272. {
  273. $params['_type'] = 'skin';
  274. $this->updateParamDefaults($params);
  275. $baseDir = (empty($params['_relative']) ? Mage::getBaseDir('skin').DS : '').
  276. $params['_area'].DS.$params['_package'].DS.$params['_theme'];
  277. return $baseDir;
  278. }
  279. public function getLocaleBaseDir(array $params=array())
  280. {
  281. $params['_type'] = 'locale';
  282. $this->updateParamDefaults($params);
  283. $baseDir = (empty($params['_relative']) ? Mage::getBaseDir('design').DS : '').
  284. $params['_area'].DS.$params['_package'].DS.$params['_theme'] . DS . 'locale' . DS .
  285. Mage::app()->getLocale()->getLocaleCode();
  286. return $baseDir;
  287. }
  288. public function getSkinBaseUrl(array $params=array())
  289. {
  290. $params['_type'] = 'skin';
  291. $this->updateParamDefaults($params);
  292. $baseUrl = Mage::getBaseUrl('skin', isset($params['_secure'])?(bool)$params['_secure']:null)
  293. .$params['_area'].'/'.$params['_package'].'/'.$params['_theme'].'/';
  294. return $baseUrl;
  295. }
  296. /**
  297. * Check whether requested file exists in specified theme params
  298. *
  299. * Possible params:
  300. * - _type: layout|template|skin|locale
  301. * - _package: design package, if not set = default
  302. * - _theme: if not set = default
  303. * - _file: path relative to theme root
  304. *
  305. * @see Mage_Core_Model_Config::getBaseDir
  306. * @param string $file
  307. * @param array $params
  308. * @return string|false
  309. */
  310. public function validateFile($file, array $params)
  311. {
  312. $fileName = $this->_renderFilename($file, $params);
  313. $testFile = (empty($params['_relative']) ? '' : Mage::getBaseDir('design') . DS) . $fileName;
  314. if (!file_exists($testFile)) {
  315. return false;
  316. }
  317. return $fileName;
  318. }
  319. /**
  320. * Get filename by specified theme parameters
  321. *
  322. * @param array $file
  323. * @param $params
  324. * @return string
  325. */
  326. protected function _renderFilename($file, array $params)
  327. {
  328. switch ($params['_type']) {
  329. case 'skin':
  330. $dir = $this->getSkinBaseDir($params);
  331. break;
  332. case 'locale':
  333. $dir = $this->getLocaleBasedir($params);
  334. break;
  335. default:
  336. $dir = $this->getBaseDir($params);
  337. break;
  338. }
  339. return $dir . DS . $file;
  340. }
  341. /**
  342. * Check for files existence by specified scheme
  343. *
  344. * If fallback enabled, the first found file will be returned. Otherwise the base package / default theme file,
  345. * regardless of found or not.
  346. * If disabled, the lookup won't be performed to spare filesystem calls.
  347. *
  348. * @param string $file
  349. * @param array &$params
  350. * @param array $fallbackScheme
  351. * @return string
  352. */
  353. protected function _fallback($file, array &$params, array $fallbackScheme = array(array()))
  354. {
  355. if ($this->_shouldFallback) {
  356. foreach ($fallbackScheme as $try) {
  357. $params = array_merge($params, $try);
  358. $filename = $this->validateFile($file, $params);
  359. if ($filename) {
  360. return $filename;
  361. }
  362. }
  363. $params['_package'] = self::BASE_PACKAGE;
  364. $params['_theme'] = self::DEFAULT_THEME;
  365. }
  366. return $this->_renderFilename($file, $params);
  367. }
  368. /**
  369. * Use this one to get existing file name with fallback to default
  370. *
  371. * $params['_type'] is required
  372. *
  373. * @param string $file
  374. * @param array $params
  375. * @return string
  376. */
  377. public function getFilename($file, array $params)
  378. {
  379. Varien_Profiler::start(__METHOD__);
  380. $this->updateParamDefaults($params);
  381. $result = $this->_fallback($file, $params, array(
  382. array(),
  383. array('_theme' => $this->getFallbackTheme()),
  384. array('_theme' => self::DEFAULT_THEME),
  385. ));
  386. Varien_Profiler::stop(__METHOD__);
  387. return $result;
  388. }
  389. /**
  390. * Default theme getter
  391. * @return string
  392. */
  393. public function getFallbackTheme()
  394. {
  395. return Mage::getStoreConfig('design/theme/default', $this->getStore());
  396. }
  397. public function getLayoutFilename($file, array $params=array())
  398. {
  399. $params['_type'] = 'layout';
  400. return $this->getFilename($file, $params);
  401. }
  402. public function getTemplateFilename($file, array $params=array())
  403. {
  404. $params['_type'] = 'template';
  405. return $this->getFilename($file, $params);
  406. }
  407. public function getLocaleFileName($file, array $params=array())
  408. {
  409. $params['_type'] = 'locale';
  410. return $this->getFilename($file, $params);
  411. }
  412. /**
  413. * Get skin file url
  414. *
  415. * @param string $file
  416. * @param array $params
  417. * @return string
  418. */
  419. public function getSkinUrl($file = null, array $params = array())
  420. {
  421. Varien_Profiler::start(__METHOD__);
  422. if (empty($params['_type'])) {
  423. $params['_type'] = 'skin';
  424. }
  425. if (empty($params['_default'])) {
  426. $params['_default'] = false;
  427. }
  428. $this->updateParamDefaults($params);
  429. if (!empty($file)) {
  430. $result = $this->_fallback($file, $params, array(
  431. array(),
  432. array('_theme' => $this->getFallbackTheme()),
  433. array('_theme' => self::DEFAULT_THEME),
  434. ));
  435. }
  436. $result = $this->getSkinBaseUrl($params) . (empty($file) ? '' : $file);
  437. Varien_Profiler::stop(__METHOD__);
  438. return $result;
  439. }
  440. /**
  441. * Design packages list getter
  442. * @return array
  443. */
  444. public function getPackageList()
  445. {
  446. $directory = Mage::getBaseDir('design') . DS . 'frontend';
  447. return $this->_listDirectories($directory);
  448. }
  449. /**
  450. * Design package (optional) themes list getter
  451. * @param string $package
  452. * @return string
  453. */
  454. public function getThemeList($package = null)
  455. {
  456. $result = array();
  457. if (is_null($package)){
  458. foreach ($this->getPackageList() as $package){
  459. $result[$package] = $this->getThemeList($package);
  460. }
  461. } else {
  462. $directory = Mage::getBaseDir('design') . DS . 'frontend' . DS . $package;
  463. $result = $this->_listDirectories($directory);
  464. }
  465. return $result;
  466. }
  467. /**
  468. * Directories lister utility method
  469. *
  470. * @param string $path
  471. * @param string|false $fullPath
  472. * @return array
  473. */
  474. private function _listDirectories($path, $fullPath = false)
  475. {
  476. $result = array();
  477. $dir = opendir($path);
  478. if ($dir) {
  479. while ($entry = readdir($dir)) {
  480. if (substr($entry, 0, 1) == '.' || !is_dir($path . DS . $entry)){
  481. continue;
  482. }
  483. if ($fullPath) {
  484. $entry = $path . DS . $entry;
  485. }
  486. $result[] = $entry;
  487. }
  488. unset($entry);
  489. closedir($dir);
  490. }
  491. return $result;
  492. }
  493. /**
  494. * Get regex rules from config and check user-agent against them
  495. *
  496. * Rules must be stored in config as a serialized array(['regexp']=>'...', ['value'] => '...')
  497. * Will return false or found string.
  498. *
  499. * @param string $regexpsConfigPath
  500. * @return mixed
  501. */
  502. protected function _checkUserAgentAgainstRegexps($regexpsConfigPath)
  503. {
  504. if (empty($_SERVER['HTTP_USER_AGENT'])) {
  505. return false;
  506. }
  507. if (!empty(self::$_customThemeTypeCache[$regexpsConfigPath])) {
  508. return self::$_customThemeTypeCache[$regexpsConfigPath];
  509. }
  510. $configValueSerialized = Mage::getStoreConfig($regexpsConfigPath, $this->getStore());
  511. if (!$configValueSerialized) {
  512. return false;
  513. }
  514. $regexps = @unserialize($configValueSerialized);
  515. if (empty($regexps)) {
  516. return false;
  517. }
  518. return self::getPackageByUserAgent($regexps, $regexpsConfigPath);
  519. }
  520. /**
  521. * Return package name based on design exception rules
  522. *
  523. * @param array $rules - design exception rules
  524. * @param string $regexpsConfigPath
  525. */
  526. public static function getPackageByUserAgent(array $rules, $regexpsConfigPath = 'path_mock')
  527. {
  528. foreach ($rules as $rule) {
  529. if (!empty(self::$_regexMatchCache[$rule['regexp']][$_SERVER['HTTP_USER_AGENT']])) {
  530. self::$_customThemeTypeCache[$regexpsConfigPath] = $rule['value'];
  531. return $rule['value'];
  532. }
  533. $regexp = '/' . trim($rule['regexp'], '/') . '/';
  534. if (@preg_match($regexp, $_SERVER['HTTP_USER_AGENT'])) {
  535. self::$_regexMatchCache[$rule['regexp']][$_SERVER['HTTP_USER_AGENT']] = true;
  536. self::$_customThemeTypeCache[$regexpsConfigPath] = $rule['value'];
  537. return $rule['value'];
  538. }
  539. }
  540. return false;
  541. }
  542. /**
  543. * Merge specified javascript files and return URL to the merged file on success
  544. *
  545. * @param $files
  546. * @return string
  547. */
  548. public function getMergedJsUrl($files)
  549. {
  550. $targetFilename = md5(implode(',', $files)) . '.js';
  551. $targetDir = $this->_initMergerDir('js');
  552. if (!$targetDir) {
  553. return '';
  554. }
  555. if ($this->_mergeFiles($files, $targetDir . DS . $targetFilename, false, null, 'js')) {
  556. return Mage::getBaseUrl('media', Mage::app()->getRequest()->isSecure()) . 'js/' . $targetFilename;
  557. }
  558. return '';
  559. }
  560. /**
  561. * Merge specified css files and return URL to the merged file on success
  562. *
  563. * @param $files
  564. * @return string
  565. */
  566. public function getMergedCssUrl($files)
  567. {
  568. // secure or unsecure
  569. $isSecure = Mage::app()->getRequest()->isSecure();
  570. $mergerDir = $isSecure ? 'css_secure' : 'css';
  571. $targetDir = $this->_initMergerDir($mergerDir);
  572. if (!$targetDir) {
  573. return '';
  574. }
  575. // base hostname & port
  576. $baseMediaUrl = Mage::getBaseUrl('media', $isSecure);
  577. $hostname = parse_url($baseMediaUrl, PHP_URL_HOST);
  578. $port = parse_url($baseMediaUrl, PHP_URL_PORT);
  579. if (false === $port) {
  580. $port = $isSecure ? 443 : 80;
  581. }
  582. // merge into target file
  583. $targetFilename = md5(implode(',', $files) . "|{$hostname}|{$port}") . '.css';
  584. if ($this->_mergeFiles($files, $targetDir . DS . $targetFilename, false, array($this, 'beforeMergeCss'), 'css')) {
  585. return $baseMediaUrl . $mergerDir . '/' . $targetFilename;
  586. }
  587. return '';
  588. }
  589. /**
  590. * Merges files into one and saves it into DB (if DB file storage is on)
  591. *
  592. * @see Mage_Core_Helper_Data::mergeFiles()
  593. * @param array $srcFiles
  594. * @param string|false $targetFile - file path to be written
  595. * @param bool $mustMerge
  596. * @param callback $beforeMergeCallback
  597. * @param array|string $extensionsFilter
  598. * @return bool|string
  599. */
  600. protected function _mergeFiles(array $srcFiles, $targetFile = false, $mustMerge = false, $beforeMergeCallback = null, $extensionsFilter = array())
  601. {
  602. if (Mage::helper('core/file_storage_database')->checkDbUsage()) {
  603. if (!file_exists($targetFile)) {
  604. Mage::helper('core/file_storage_database')->saveFileToFilesystem($targetFile);
  605. }
  606. if (file_exists($targetFile)) {
  607. $filemtime = filemtime($targetFile);
  608. } else {
  609. $filemtime = null;
  610. }
  611. $result = Mage::helper('core')->mergeFiles($srcFiles, $targetFile, $mustMerge, $beforeMergeCallback, $extensionsFilter);
  612. if ($result && (filemtime($targetFile) > $filemtime)) {
  613. Mage::helper('core/file_storage_database')->saveFile($targetFile);
  614. }
  615. return $result;
  616. } else {
  617. return Mage::helper('core')->mergeFiles($srcFiles, $targetFile, $mustMerge, $beforeMergeCallback, $extensionsFilter);
  618. }
  619. }
  620. /**
  621. * Remove all merged js/css files
  622. *
  623. * @return bool
  624. */
  625. public function cleanMergedJsCss()
  626. {
  627. $result = (bool)$this->_initMergerDir('js', true);
  628. $result = (bool)$this->_initMergerDir('css', true) && $result;
  629. return (bool)$this->_initMergerDir('css_secure', true) && $result;
  630. }
  631. /**
  632. * Make sure merger dir exists and writeable
  633. * Also can clean it up
  634. *
  635. * @param string $dirRelativeName
  636. * @param bool $cleanup
  637. */
  638. protected function _initMergerDir($dirRelativeName, $cleanup = false)
  639. {
  640. $mediaDir = Mage::getBaseDir('media');
  641. try {
  642. $dir = Mage::getBaseDir('media') . DS . $dirRelativeName;
  643. if ($cleanup) {
  644. Varien_Io_File::rmdirRecursive($dir);
  645. Mage::helper('core/file_storage_database')->deleteFolder($dir);
  646. }
  647. if (!is_dir($dir)) {
  648. mkdir($dir);
  649. }
  650. return is_writeable($dir) ? $dir : false;
  651. } catch (Exception $e) {
  652. Mage::logException($e);
  653. }
  654. return false;
  655. }
  656. /**
  657. * Before merge css callback function
  658. *
  659. * @param string $file
  660. * @param string $contents
  661. * @return string
  662. */
  663. public function beforeMergeCss($file, $contents)
  664. {
  665. $this->_setCallbackFileDir($file);
  666. $cssImport = '/@import\\s+([\'"])(.*?)[\'"]/';
  667. $contents = preg_replace_callback($cssImport, array($this, '_cssMergerImportCallback'), $contents);
  668. $cssUrl = '/url\\(\\s*([^\\)\\s]+)\\s*\\)?/';
  669. $contents = preg_replace_callback($cssUrl, array($this, '_cssMergerUrlCallback'), $contents);
  670. return $contents;
  671. }
  672. /**
  673. * Set file dir for css file
  674. *
  675. * @param string $file
  676. */
  677. protected function _setCallbackFileDir($file)
  678. {
  679. $file = str_replace(Mage::getBaseDir().DS, '', $file);
  680. $this->_callbackFileDir = dirname($file);
  681. }
  682. /**
  683. * Callback function replaces relative links for @import matches in css file
  684. *
  685. * @param array $match
  686. * @return string
  687. */
  688. protected function _cssMergerImportCallback($match)
  689. {
  690. $quote = $match[1];
  691. $uri = $this->_prepareUrl($match[2]);
  692. return "@import {$quote}{$uri}{$quote}";
  693. }
  694. /**
  695. * Callback function replaces relative links for url() matches in css file
  696. *
  697. * @param array $match
  698. * @return string
  699. */
  700. protected function _cssMergerUrlCallback($match)
  701. {
  702. $quote = ($match[1][0] == "'" || $match[1][0] == '"') ? $match[1][0] : '';
  703. $uri = ($quote == '') ? $match[1] : substr($match[1], 1, strlen($match[1]) - 2);
  704. $uri = $this->_prepareUrl($uri);
  705. return "url({$quote}{$uri}{$quote})";
  706. }
  707. /**
  708. * Prepare url for css replacement
  709. *
  710. * @param string $uri
  711. * @return string
  712. */
  713. protected function _prepareUrl($uri)
  714. {
  715. // check absolute or relative url
  716. if (!preg_match('/^https?:/i', $uri) && !preg_match('/^\//i', $uri)) {
  717. $fileDir = '';
  718. $pathParts = explode(DS, $uri);
  719. $fileDirParts = explode(DS, $this->_callbackFileDir);
  720. $store = $this->getStore();
  721. if ($store->isAdmin()) {
  722. $secure = $store->isAdminUrlSecure();
  723. } else {
  724. $secure = $store->isFrontUrlSecure() && Mage::app()->getRequest()->isSecure();
  725. }
  726. if ('skin' == $fileDirParts[0]) {
  727. $baseUrl = Mage::getBaseUrl('skin', $secure);
  728. $fileDirParts = array_slice($fileDirParts, 1);
  729. } elseif ('media' == $fileDirParts[0]) {
  730. $baseUrl = Mage::getBaseUrl('media', $secure);
  731. $fileDirParts = array_slice($fileDirParts, 1);
  732. } else {
  733. $baseUrl = Mage::getBaseUrl('web', $secure);
  734. }
  735. foreach ($pathParts as $key=>$part) {
  736. if ($part == '.' || $part == '..') {
  737. unset($pathParts[$key]);
  738. }
  739. if ($part == '..' && count($fileDirParts)) {
  740. $fileDirParts = array_slice($fileDirParts, 0, count($fileDirParts) - 1);
  741. }
  742. }
  743. if (count($fileDirParts)) {
  744. $fileDir = implode('/', $fileDirParts).'/';
  745. }
  746. $uri = $baseUrl.$fileDir.implode('/', $pathParts);
  747. }
  748. return $uri;
  749. }
  750. }