PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/app/code/core/Mage/Core/Helper/Data.php

https://bitbucket.org/andrewjleavitt/magestudy
PHP | 791 lines | 468 code | 68 blank | 255 comment | 93 complexity | 91178ab2333171ed8bbaea93254698e4 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. /**
  27. * Core data helper
  28. *
  29. * @author Magento Core Team <core@magentocommerce.com>
  30. */
  31. class Mage_Core_Helper_Data extends Mage_Core_Helper_Abstract
  32. {
  33. const XML_PATH_DEFAULT_COUNTRY = 'general/country/default';
  34. const XML_PATH_PROTECTED_FILE_EXTENSIONS = 'general/file/protected_extensions';
  35. const XML_PATH_PUBLIC_FILES_VALID_PATHS = 'general/file/public_files_valid_paths';
  36. /**
  37. * @var Mage_Core_Model_Encryption
  38. */
  39. protected $_encryptor = null;
  40. /**
  41. * @return Mage_Core_Model_Encryption
  42. */
  43. public function getEncryptor()
  44. {
  45. if ($this->_encryptor === null) {
  46. $encryptionModel = (string)Mage::getConfig()->getNode('global/helpers/core/encryption_model');
  47. if ($encryptionModel) {
  48. $this->_encryptor = new $encryptionModel;
  49. } else {
  50. $this->_encryptor = Mage::getModel('core/encryption');
  51. }
  52. $this->_encryptor->setHelper($this);
  53. }
  54. return $this->_encryptor;
  55. }
  56. /**
  57. * Convert and format price value for current application store
  58. *
  59. * @param float $value
  60. * @param bool $format
  61. * @param bool $includeContainer
  62. * @return mixed
  63. */
  64. public static function currency($value, $format = true, $includeContainer = true)
  65. {
  66. return self::currencyByStore($value, null, $format, $includeContainer);
  67. }
  68. /**
  69. * Convert and format price value for specified store
  70. *
  71. * @param float $value
  72. * @param int|Mage_Core_Model_Store $store
  73. * @param bool $format
  74. * @param bool $includeContainer
  75. * @return mixed
  76. */
  77. public static function currencyByStore($value, $store = null, $format = true, $includeContainer = true)
  78. {
  79. try {
  80. if (!($store instanceof Mage_Core_Model_Store)) {
  81. $store = Mage::app()->getStore($store);
  82. }
  83. $value = $store->convertPrice($value, $format, $includeContainer);
  84. }
  85. catch (Exception $e){
  86. $value = $e->getMessage();
  87. }
  88. return $value;
  89. }
  90. /**
  91. * Format and convert currency using current store option
  92. *
  93. * @param float $value
  94. * @param bool $includeContainer
  95. * @return string
  96. */
  97. public function formatCurrency($value, $includeContainer = true)
  98. {
  99. return $this->currency($value, true, $includeContainer);
  100. }
  101. /**
  102. * Formats price
  103. *
  104. * @param float $price
  105. * @param bool $includeContainer
  106. * @return string
  107. */
  108. public function formatPrice($price, $includeContainer = true)
  109. {
  110. return Mage::app()->getStore()->formatPrice($price, $includeContainer);
  111. }
  112. /**
  113. * Format date using current locale options
  114. *
  115. * @param date|Zend_Date|null $date in GMT timezone
  116. * @param string $format
  117. * @param bool $showTime
  118. * @return string
  119. */
  120. public function formatDate($date=null, $format='short', $showTime=false)
  121. {
  122. if (Mage_Core_Model_Locale::FORMAT_TYPE_FULL !==$format &&
  123. Mage_Core_Model_Locale::FORMAT_TYPE_LONG !==$format &&
  124. Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM !==$format &&
  125. Mage_Core_Model_Locale::FORMAT_TYPE_SHORT !==$format) {
  126. return $date;
  127. }
  128. if (!($date instanceof Zend_Date) && $date && !strtotime($date)) {
  129. return '';
  130. }
  131. if (is_null($date)) {
  132. $date = Mage::app()->getLocale()->date(Mage::getSingleton('core/date')->gmtTimestamp(), null, null);
  133. }
  134. elseif (!$date instanceof Zend_Date) {
  135. $date = Mage::app()->getLocale()->date(strtotime($date), null, null, $showTime);
  136. }
  137. if ($showTime) {
  138. $format = Mage::app()->getLocale()->getDateTimeFormat($format);
  139. }
  140. else {
  141. $format = Mage::app()->getLocale()->getDateFormat($format);
  142. }
  143. return $date->toString($format);
  144. }
  145. /**
  146. * Format time using current locale options
  147. *
  148. * @param date|Zend_Date|null $time
  149. * @param string $format
  150. * @param bool $showTime
  151. * @return string
  152. */
  153. public function formatTime($time=null, $format='short', $showDate=false)
  154. {
  155. if (Mage_Core_Model_Locale::FORMAT_TYPE_FULL !==$format &&
  156. Mage_Core_Model_Locale::FORMAT_TYPE_LONG !==$format &&
  157. Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM !==$format &&
  158. Mage_Core_Model_Locale::FORMAT_TYPE_SHORT !==$format) {
  159. return $time;
  160. }
  161. if (is_null($time)) {
  162. $date = Mage::app()->getLocale()->date(time());
  163. }
  164. elseif ($time instanceof Zend_Date) {
  165. $date = $time;
  166. }
  167. else {
  168. $date = Mage::app()->getLocale()->date(strtotime($time));
  169. }
  170. if ($showDate) {
  171. $format = Mage::app()->getLocale()->getDateTimeFormat($format);
  172. }
  173. else {
  174. $format = Mage::app()->getLocale()->getTimeFormat($format);
  175. }
  176. return $date->toString($format);
  177. }
  178. /**
  179. * Encrypt data using application key
  180. *
  181. * @param string $data
  182. * @return string
  183. */
  184. public function encrypt($data)
  185. {
  186. if (!Mage::isInstalled()) {
  187. return $data;
  188. }
  189. return $this->getEncryptor()->encrypt($data);
  190. }
  191. /**
  192. * Decrypt data using application key
  193. *
  194. * @param string $data
  195. * @return string
  196. */
  197. public function decrypt($data)
  198. {
  199. if (!Mage::isInstalled()) {
  200. return $data;
  201. }
  202. return $this->getEncryptor()->decrypt($data);
  203. }
  204. public function validateKey($key)
  205. {
  206. return $this->getEncryptor()->validateKey($key);
  207. }
  208. public function getRandomString($len, $chars=null)
  209. {
  210. if (is_null($chars)) {
  211. $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  212. }
  213. mt_srand(10000000*(double)microtime());
  214. for ($i = 0, $str = '', $lc = strlen($chars)-1; $i < $len; $i++) {
  215. $str .= $chars[mt_rand(0, $lc)];
  216. }
  217. return $str;
  218. }
  219. /**
  220. * Generate salted hash from password
  221. *
  222. * @param string $password
  223. * @param string|integer|boolean $salt
  224. */
  225. public function getHash($password, $salt = false)
  226. {
  227. return $this->getEncryptor()->getHash($password, $salt);
  228. }
  229. public function validateHash($password, $hash)
  230. {
  231. return $this->getEncryptor()->validateHash($password, $hash);
  232. }
  233. /**
  234. * Retrieve store identifier
  235. *
  236. * @param mixed $store
  237. * @return int
  238. */
  239. public function getStoreId($store=null)
  240. {
  241. return Mage::app()->getStore($store)->getId();
  242. }
  243. public function removeAccents($string, $german=false)
  244. {
  245. static $replacements;
  246. if (empty($replacements[$german])) {
  247. $subst = array(
  248. // single ISO-8859-1 letters
  249. 192=>'A', 193=>'A', 194=>'A', 195=>'A', 196=>'A', 197=>'A', 199=>'C',
  250. 208=>'D', 200=>'E', 201=>'E', 202=>'E', 203=>'E', 204=>'I', 205=>'I',
  251. 206=>'I', 207=>'I', 209=>'N', 210=>'O', 211=>'O', 212=>'O', 213=>'O',
  252. 214=>'O', 216=>'O', 138=>'S', 217=>'U', 218=>'U', 219=>'U', 220=>'U',
  253. 221=>'Y', 142=>'Z', 224=>'a', 225=>'a', 226=>'a', 227=>'a', 228=>'a',
  254. 229=>'a', 231=>'c', 232=>'e', 233=>'e', 234=>'e', 235=>'e', 236=>'i',
  255. 237=>'i', 238=>'i', 239=>'i', 241=>'n', 240=>'o', 242=>'o', 243=>'o',
  256. 244=>'o', 245=>'o', 246=>'o', 248=>'o', 154=>'s', 249=>'u', 250=>'u',
  257. 251=>'u', 252=>'u', 253=>'y', 255=>'y', 158=>'z',
  258. // HTML entities
  259. 258=>'A', 260=>'A', 262=>'C', 268=>'C', 270=>'D', 272=>'D', 280=>'E',
  260. 282=>'E', 286=>'G', 304=>'I', 313=>'L', 317=>'L', 321=>'L', 323=>'N',
  261. 327=>'N', 336=>'O', 340=>'R', 344=>'R', 346=>'S', 350=>'S', 354=>'T',
  262. 356=>'T', 366=>'U', 368=>'U', 377=>'Z', 379=>'Z', 259=>'a', 261=>'a',
  263. 263=>'c', 269=>'c', 271=>'d', 273=>'d', 281=>'e', 283=>'e', 287=>'g',
  264. 305=>'i', 322=>'l', 314=>'l', 318=>'l', 324=>'n', 328=>'n', 337=>'o',
  265. 341=>'r', 345=>'r', 347=>'s', 351=>'s', 357=>'t', 355=>'t', 367=>'u',
  266. 369=>'u', 378=>'z', 380=>'z',
  267. // ligatures
  268. 198=>'Ae', 230=>'ae', 140=>'Oe', 156=>'oe', 223=>'ss',
  269. );
  270. if ($german) {
  271. // umlauts
  272. $subst = array_merge($subst, array(
  273. 196=>'Ae', 228=>'ae', 214=>'Oe', 246=>'oe', 220=>'Ue', 252=>'ue'
  274. ));
  275. }
  276. $replacements[$german] = array();
  277. foreach ($subst as $k=>$v) {
  278. $replacements[$german][$k<256 ? chr($k) : '&#'.$k.';'] = $v;
  279. }
  280. }
  281. // convert string from default database format (UTF-8)
  282. // to encoding which replacement arrays made with (ISO-8859-1)
  283. if ($s = @iconv('UTF-8', 'ISO-8859-1', $string)) {
  284. $string = $s;
  285. }
  286. // Replace
  287. $string = strtr($string, $replacements[$german]);
  288. return $string;
  289. }
  290. public function isDevAllowed($storeId=null)
  291. {
  292. $allow = true;
  293. $allowedIps = Mage::getStoreConfig('dev/restrict/allow_ips', $storeId);
  294. $remoteAddr = Mage::helper('core/http')->getRemoteAddr();
  295. if (!empty($allowedIps) && !empty($remoteAddr)) {
  296. $allowedIps = preg_split('#\s*,\s*#', $allowedIps, null, PREG_SPLIT_NO_EMPTY);
  297. if (array_search($remoteAddr, $allowedIps) === false
  298. && array_search(Mage::helper('core/http')->getHttpHost(), $allowedIps) === false) {
  299. $allow = false;
  300. }
  301. }
  302. return $allow;
  303. }
  304. /**
  305. * Get information about available cache types
  306. *
  307. * @return array
  308. */
  309. public function getCacheTypes()
  310. {
  311. $types = array();
  312. $config = Mage::getConfig()->getNode(Mage_Core_Model_Cache::XML_PATH_TYPES);
  313. foreach ($config->children() as $type=>$node) {
  314. $types[$type] = (string)$node->label;
  315. }
  316. return $types;
  317. }
  318. /**
  319. * Get information about available cache beta types
  320. *
  321. * @return array
  322. */
  323. public function getCacheBetaTypes()
  324. {
  325. $types = array();
  326. $config = Mage::getConfig()->getNode('global/cache/betatypes');
  327. if ($config) {
  328. foreach ($config->children() as $type=>$node) {
  329. $types[$type] = (string)$node->label;
  330. }
  331. }
  332. return $types;
  333. }
  334. /**
  335. * Copy data from object|array to object|array containing fields
  336. * from fieldset matching an aspect.
  337. *
  338. * Contents of $aspect are a field name in target object or array.
  339. * If '*' - will be used the same name as in the source object or array.
  340. *
  341. * @param string $fieldset
  342. * @param string $aspect
  343. * @param array|Varien_Object $source
  344. * @param array|Varien_Object $target
  345. * @param string $root
  346. * @return boolean
  347. */
  348. public function copyFieldset($fieldset, $aspect, $source, $target, $root='global')
  349. {
  350. if (!(is_array($source) || $source instanceof Varien_Object)
  351. || !(is_array($target) || $target instanceof Varien_Object)) {
  352. return false;
  353. }
  354. $fields = Mage::getConfig()->getFieldset($fieldset, $root);
  355. if (!$fields) {
  356. return false;
  357. }
  358. $sourceIsArray = is_array($source);
  359. $targetIsArray = is_array($target);
  360. $result = false;
  361. foreach ($fields as $code=>$node) {
  362. if (empty($node->$aspect)) {
  363. continue;
  364. }
  365. if ($sourceIsArray) {
  366. $value = isset($source[$code]) ? $source[$code] : null;
  367. } else {
  368. $value = $source->getDataUsingMethod($code);
  369. }
  370. $targetCode = (string)$node->$aspect;
  371. $targetCode = $targetCode == '*' ? $code : $targetCode;
  372. if ($targetIsArray) {
  373. $target[$targetCode] = $value;
  374. } else {
  375. $target->setDataUsingMethod($targetCode, $value);
  376. }
  377. $result = true;
  378. }
  379. $eventName = sprintf('core_copy_fieldset_%s_%s', $fieldset, $aspect);
  380. Mage::dispatchEvent($eventName, array(
  381. 'target' => $target,
  382. 'source' => $source,
  383. 'root' => $root
  384. ));
  385. return $result;
  386. }
  387. /**
  388. * Decorate a plain array of arrays or objects
  389. * The array actually can be an object with Iterator interface
  390. *
  391. * Keys with prefix_* will be set:
  392. * *_is_first - if the element is first
  393. * *_is_odd / *_is_even - for odd/even elements
  394. * *_is_last - if the element is last
  395. *
  396. * The respective key/attribute will be set to element, depending on object it is or array.
  397. * Varien_Object is supported.
  398. *
  399. * $forceSetAll true will cause to set all possible values for all elements.
  400. * When false (default), only non-empty values will be set.
  401. *
  402. * @param mixed $array
  403. * @param string $prefix
  404. * @param bool $forceSetAll
  405. * @return mixed
  406. */
  407. public function decorateArray($array, $prefix = 'decorated_', $forceSetAll = false)
  408. {
  409. // check if array or an object to be iterated given
  410. if (!(is_array($array) || is_object($array))) {
  411. return $array;
  412. }
  413. $keyIsFirst = "{$prefix}is_first";
  414. $keyIsOdd = "{$prefix}is_odd";
  415. $keyIsEven = "{$prefix}is_even";
  416. $keyIsLast = "{$prefix}is_last";
  417. $count = count($array); // this will force Iterator to load
  418. $i = 0;
  419. $isEven = false;
  420. foreach ($array as $key => $element) {
  421. if (is_object($element)) {
  422. $this->_decorateArrayObject($element, $keyIsFirst, (0 === $i), $forceSetAll || (0 === $i));
  423. $this->_decorateArrayObject($element, $keyIsOdd, !$isEven, $forceSetAll || !$isEven);
  424. $this->_decorateArrayObject($element, $keyIsEven, $isEven, $forceSetAll || $isEven);
  425. $isEven = !$isEven;
  426. $i++;
  427. $this->_decorateArrayObject($element, $keyIsLast, ($i === $count), $forceSetAll || ($i === $count));
  428. }
  429. elseif (is_array($element)) {
  430. if ($forceSetAll || (0 === $i)) {
  431. $array[$key][$keyIsFirst] = (0 === $i);
  432. }
  433. if ($forceSetAll || !$isEven) {
  434. $array[$key][$keyIsOdd] = !$isEven;
  435. }
  436. if ($forceSetAll || $isEven) {
  437. $array[$key][$keyIsEven] = $isEven;
  438. }
  439. $isEven = !$isEven;
  440. $i++;
  441. if ($forceSetAll || ($i === $count)) {
  442. $array[$key][$keyIsLast] = ($i === $count);
  443. }
  444. }
  445. }
  446. return $array;
  447. }
  448. private function _decorateArrayObject($element, $key, $value, $dontSkip) {
  449. if ($dontSkip) {
  450. if ($element instanceof Varien_Object) {
  451. $element->setData($key, $value);
  452. }
  453. else {
  454. $element->$key = $value;
  455. }
  456. }
  457. }
  458. /**
  459. * Transform an assoc array to SimpleXMLElement object
  460. * Array has some limitations. Appropriate exceptions will be thrown
  461. *
  462. * @param array $array
  463. * @param string $rootName
  464. * @return SimpleXMLElement
  465. * @throws Exception
  466. */
  467. public function assocToXml(array $array, $rootName = '_')
  468. {
  469. if (empty($rootName) || is_numeric($rootName)) {
  470. throw new Exception('Root element must not be empty or numeric');
  471. }
  472. $xmlstr = <<<XML
  473. <?xml version='1.0' encoding='UTF-8' standalone='yes'?>
  474. <$rootName></$rootName>
  475. XML;
  476. $xml = new SimpleXMLElement($xmlstr);
  477. foreach ($array as $key => $value) {
  478. if (is_numeric($key)) {
  479. throw new Exception('Array root keys must not be numeric.');
  480. }
  481. }
  482. return self::_assocToXml($array, $rootName, $xml);
  483. }
  484. /**
  485. * Function, that actually recursively transforms array to xml
  486. *
  487. * @param array $array
  488. * @param string $rootName
  489. * @param SimpleXMLElement $xml
  490. * @return SimpleXMLElement
  491. * @throws Exception
  492. */
  493. private function _assocToXml(array $array, $rootName, SimpleXMLElement &$xml)
  494. {
  495. $hasNumericKey = false;
  496. $hasStringKey = false;
  497. foreach ($array as $key => $value) {
  498. if (!is_array($value)) {
  499. if (is_string($key)) {
  500. if ($key === $rootName) {
  501. throw new Exception('Associative key must not be the same as its parent associative key.');
  502. }
  503. $hasStringKey = true;
  504. $xml->$key = $value;
  505. }
  506. elseif (is_int($key)) {
  507. $hasNumericKey = true;
  508. $xml->{$rootName}[$key] = $value;
  509. }
  510. }
  511. else {
  512. self::_assocToXml($value, $key, $xml->$key);
  513. }
  514. }
  515. if ($hasNumericKey && $hasStringKey) {
  516. throw new Exception('Associative and numeric keys must not be mixed at one level.');
  517. }
  518. return $xml;
  519. }
  520. /**
  521. * Transform SimpleXMLElement to associative array
  522. * SimpleXMLElement must be conform structure, generated by assocToXml()
  523. *
  524. * @param SimpleXMLElement $xml
  525. * @return array
  526. */
  527. public function xmlToAssoc(SimpleXMLElement $xml)
  528. {
  529. $array = array();
  530. foreach ($xml as $key => $value) {
  531. if (isset($value->$key)) {
  532. $i = 0;
  533. foreach ($value->$key as $v) {
  534. $array[$key][$i++] = (string)$v;
  535. }
  536. }
  537. else {
  538. // try to transform it into string value, trimming spaces between elements
  539. $array[$key] = trim((string)$value);
  540. if (empty($array[$key]) && !empty($value)) {
  541. $array[$key] = self::xmlToAssoc($value);
  542. }
  543. // untrim strings values
  544. else {
  545. $array[$key] = (string)$value;
  546. }
  547. }
  548. }
  549. return $array;
  550. }
  551. /**
  552. * Encode the mixed $valueToEncode into the JSON format
  553. *
  554. * @param mixed $valueToEncode
  555. * @param boolean $cycleCheck Optional; whether or not to check for object recursion; off by default
  556. * @param array $options Additional options used during encoding
  557. * @return string
  558. */
  559. public function jsonEncode($valueToEncode, $cycleCheck = false, $options = array())
  560. {
  561. $json = Zend_Json::encode($valueToEncode, $cycleCheck, $options);
  562. /* @var $inline Mage_Core_Model_Translate_Inline */
  563. $inline = Mage::getSingleton('core/translate_inline');
  564. if ($inline->isAllowed()) {
  565. $inline->setIsJson(true);
  566. $inline->processResponseBody($json);
  567. $inline->setIsJson(false);
  568. }
  569. return $json;
  570. }
  571. /**
  572. * Decodes the given $encodedValue string which is
  573. * encoded in the JSON format
  574. *
  575. * @param string $encodedValue
  576. * @return mixed
  577. */
  578. public function jsonDecode($encodedValue, $objectDecodeType = Zend_Json::TYPE_ARRAY)
  579. {
  580. return Zend_Json::decode($encodedValue, $objectDecodeType);
  581. }
  582. /**
  583. * Generate a hash from unique ID
  584. * @param $prefix
  585. * @return string
  586. */
  587. public function uniqHash($prefix = '')
  588. {
  589. return $prefix . md5(uniqid(microtime(), true));
  590. }
  591. /**
  592. * Merge specified files into one
  593. *
  594. * By default will not merge, if there is already merged file exists and it
  595. * was modified after its components
  596. * If target file is specified, will attempt to write merged contents into it,
  597. * otherwise will return merged content
  598. * May apply callback to each file contents. Callback gets parameters:
  599. * (<existing system filename>, <file contents>)
  600. * May filter files by specified extension(s)
  601. * Returns false on error
  602. *
  603. * @param array $srcFiles
  604. * @param string|false $targetFile - file path to be written
  605. * @param bool $mustMerge
  606. * @param callback $beforeMergeCallback
  607. * @param array|string $extensionsFilter
  608. * @return bool|string
  609. */
  610. public function mergeFiles(array $srcFiles, $targetFile = false, $mustMerge = false,
  611. $beforeMergeCallback = null, $extensionsFilter = array())
  612. {
  613. try {
  614. // check whether merger is required
  615. $shouldMerge = $mustMerge || !$targetFile;
  616. if (!$shouldMerge) {
  617. if (!file_exists($targetFile)) {
  618. $shouldMerge = true;
  619. } else {
  620. $targetMtime = filemtime($targetFile);
  621. foreach ($srcFiles as $file) {
  622. if (!file_exists($file) || @filemtime($file) > $targetMtime) {
  623. $shouldMerge = true;
  624. break;
  625. }
  626. }
  627. }
  628. }
  629. // merge contents into the file
  630. if ($shouldMerge) {
  631. if ($targetFile && !is_writeable(dirname($targetFile))) {
  632. // no translation intentionally
  633. throw new Exception(sprintf('Path %s is not writeable.', dirname($targetFile)));
  634. }
  635. // filter by extensions
  636. if ($extensionsFilter) {
  637. if (!is_array($extensionsFilter)) {
  638. $extensionsFilter = array($extensionsFilter);
  639. }
  640. if (!empty($srcFiles)){
  641. foreach ($srcFiles as $key => $file) {
  642. $fileExt = strtolower(pathinfo($file, PATHINFO_EXTENSION));
  643. if (!in_array($fileExt, $extensionsFilter)) {
  644. unset($srcFiles[$key]);
  645. }
  646. }
  647. }
  648. }
  649. if (empty($srcFiles)) {
  650. // no translation intentionally
  651. throw new Exception('No files to compile.');
  652. }
  653. $data = '';
  654. foreach ($srcFiles as $file) {
  655. if (!file_exists($file)) {
  656. continue;
  657. }
  658. $contents = file_get_contents($file) . "\n";
  659. if ($beforeMergeCallback && is_callable($beforeMergeCallback)) {
  660. $contents = call_user_func($beforeMergeCallback, $file, $contents);
  661. }
  662. $data .= $contents;
  663. }
  664. if (!$data) {
  665. // no translation intentionally
  666. throw new Exception(sprintf("No content found in files:\n%s", implode("\n", $srcFiles)));
  667. }
  668. if ($targetFile) {
  669. file_put_contents($targetFile, $data, LOCK_EX);
  670. } else {
  671. return $data; // no need to write to file, just return data
  672. }
  673. }
  674. return true; // no need in merger or merged into file successfully
  675. } catch (Exception $e) {
  676. Mage::logException($e);
  677. }
  678. return false;
  679. }
  680. /**
  681. * Return default country code
  682. *
  683. * @param Mage_Core_Model_Store|string|int $store
  684. * @return string
  685. */
  686. public function getDefaultCountry($store = null)
  687. {
  688. return Mage::getStoreConfig(self::XML_PATH_DEFAULT_COUNTRY, $store);
  689. }
  690. /**
  691. * Return list with protected file extensions
  692. *
  693. * @param Mage_Core_Model_Store|string|int $store
  694. * @return array
  695. */
  696. public function getProtectedFileExtensions($store = null)
  697. {
  698. return Mage::getStoreConfig(self::XML_PATH_PROTECTED_FILE_EXTENSIONS, $store);
  699. }
  700. /**
  701. * Return list with public files valid paths
  702. *
  703. * @return array
  704. */
  705. public function getPublicFilesValidPath()
  706. {
  707. return Mage::getStoreConfig(self::XML_PATH_PUBLIC_FILES_VALID_PATHS);
  708. }
  709. /**
  710. * Check LFI protection
  711. *
  712. * @throws Mage_Core_Exception
  713. * @param string $name
  714. * @return bool
  715. */
  716. public function checkLfiProtection($name)
  717. {
  718. if (preg_match('#\.\.[\\\/]#', $name)) {
  719. throw new Mage_Core_Exception($this->__('Requested file may not include parent directory traversal ("../", "..\\" notation)'));
  720. }
  721. return true;
  722. }
  723. }