PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/util/sfToolkit.class.php

https://github.com/theodo/symfony1.0-backports
PHP | 580 lines | 407 code | 53 blank | 120 comment | 86 complexity | 448e663efa84417809882b93b6f68534 MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-3.0, BSD-3-Clause
  1. <?php
  2. /*
  3. * This file is part of the symfony package.
  4. * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
  5. * (c) 2004-2006 Sean Kerr <sean@code-box.org>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. /**
  11. * sfToolkit provides basic utility methods.
  12. *
  13. * @package symfony
  14. * @subpackage util
  15. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  16. * @author Sean Kerr <sean@code-box.org>
  17. * @version SVN: $Id$
  18. */
  19. class sfToolkit
  20. {
  21. /**
  22. * Extract the class or interface name from filename.
  23. *
  24. * @param string A filename.
  25. *
  26. * @return string A class or interface name, if one can be extracted, otherwise null.
  27. */
  28. public static function extractClassName($filename)
  29. {
  30. $retval = null;
  31. if (self::isPathAbsolute($filename))
  32. {
  33. $filename = basename($filename);
  34. }
  35. $pattern = '/(.*?)\.(class|interface)\.php/i';
  36. if (preg_match($pattern, $filename, $match))
  37. {
  38. $retval = $match[1];
  39. }
  40. return $retval;
  41. }
  42. /**
  43. * Clear all files in a given directory.
  44. *
  45. * @param string An absolute filesystem path to a directory.
  46. *
  47. * @return void
  48. */
  49. public static function clearDirectory($directory)
  50. {
  51. if (!is_dir($directory))
  52. {
  53. return;
  54. }
  55. // open a file point to the cache dir
  56. $fp = opendir($directory);
  57. // ignore names
  58. $ignore = array('.', '..', 'CVS', '.svn');
  59. while (($file = readdir($fp)) !== false)
  60. {
  61. if (!in_array($file, $ignore))
  62. {
  63. if (is_link($directory.'/'.$file))
  64. {
  65. // delete symlink
  66. unlink($directory.'/'.$file);
  67. }
  68. else if (is_dir($directory.'/'.$file))
  69. {
  70. // recurse through directory
  71. self::clearDirectory($directory.'/'.$file);
  72. // delete the directory
  73. rmdir($directory.'/'.$file);
  74. }
  75. else
  76. {
  77. // delete the file
  78. unlink($directory.'/'.$file);
  79. }
  80. }
  81. }
  82. // close file pointer
  83. closedir($fp);
  84. }
  85. /**
  86. * Clear all files and directories corresponding to a glob pattern.
  87. *
  88. * @param string An absolute filesystem pattern.
  89. *
  90. * @return void
  91. */
  92. public static function clearGlob($pattern)
  93. {
  94. $files = glob($pattern);
  95. // order is important when removing directories
  96. sort($files);
  97. foreach ($files as $file)
  98. {
  99. if (is_dir($file))
  100. {
  101. // delete directory
  102. self::clearDirectory($file);
  103. }
  104. else
  105. {
  106. // delete file
  107. unlink($file);
  108. }
  109. }
  110. }
  111. /**
  112. * Determine if a filesystem path is absolute.
  113. *
  114. * @param path A filesystem path.
  115. *
  116. * @return bool true, if the path is absolute, otherwise false.
  117. */
  118. public static function isPathAbsolute($path)
  119. {
  120. if ($path[0] == '/' || $path[0] == '\\' ||
  121. (strlen($path) > 3 && ctype_alpha($path[0]) &&
  122. $path[1] == ':' &&
  123. ($path[2] == '\\' || $path[2] == '/')
  124. )
  125. )
  126. {
  127. return true;
  128. }
  129. return false;
  130. }
  131. /**
  132. * Determine if a lock file is present.
  133. *
  134. * @param integer A max amount of life time for the lock file.
  135. *
  136. * @return bool true, if the lock file is present, otherwise false.
  137. */
  138. public static function hasLockFile($lockFile, $maxLockFileLifeTime = 0)
  139. {
  140. $isLocked = false;
  141. if (is_readable($lockFile) && ($last_access = fileatime($lockFile)))
  142. {
  143. $now = time();
  144. $timeDiff = $now - $last_access;
  145. if (!$maxLockFileLifeTime || $timeDiff < $maxLockFileLifeTime)
  146. {
  147. $isLocked = true;
  148. }
  149. else
  150. {
  151. $isLocked = @unlink($lockFile) ? false : true;
  152. }
  153. }
  154. return $isLocked;
  155. }
  156. public static function stripComments($source)
  157. {
  158. if (!sfConfig::get('sf_strip_comments', true) || !function_exists('token_get_all'))
  159. {
  160. return $source;
  161. }
  162. $ignore = array(T_COMMENT => true, T_DOC_COMMENT => true);
  163. $output = '';
  164. foreach (token_get_all($source) as $token)
  165. {
  166. // array
  167. if (isset($token[1]))
  168. {
  169. // no action on comments
  170. if (!isset($ignore[$token[0]]))
  171. {
  172. // anything else -> output "as is"
  173. $output .= $token[1];
  174. }
  175. }
  176. else
  177. {
  178. // simple 1-character token
  179. $output .= $token;
  180. }
  181. }
  182. return $output;
  183. }
  184. public static function stripslashesDeep($value)
  185. {
  186. return is_array($value) ? array_map(array('sfToolkit', 'stripslashesDeep'), $value) : stripslashes($value);
  187. }
  188. // code from php at moechofe dot com (array_merge comment on php.net)
  189. /*
  190. * array arrayDeepMerge ( array array1 [, array array2 [, array ...]] )
  191. *
  192. * Like array_merge
  193. *
  194. * arrayDeepMerge() merges the elements of one or more arrays together so
  195. * that the values of one are appended to the end of the previous one. It
  196. * returns the resulting array.
  197. * If the input arrays have the same string keys, then the later value for
  198. * that key will overwrite the previous one. If, however, the arrays contain
  199. * numeric keys, the later value will not overwrite the original value, but
  200. * will be appended.
  201. * If only one array is given and the array is numerically indexed, the keys
  202. * get reindexed in a continuous way.
  203. *
  204. * Different from array_merge
  205. * If string keys have arrays for values, these arrays will merge recursively.
  206. */
  207. public static function arrayDeepMerge()
  208. {
  209. switch (func_num_args())
  210. {
  211. case 0:
  212. return false;
  213. case 1:
  214. return func_get_arg(0);
  215. case 2:
  216. $args = func_get_args();
  217. $args[2] = array();
  218. if (is_array($args[0]) && is_array($args[1]))
  219. {
  220. foreach (array_unique(array_merge(array_keys($args[0]),array_keys($args[1]))) as $key)
  221. {
  222. $isKey0 = array_key_exists($key, $args[0]);
  223. $isKey1 = array_key_exists($key, $args[1]);
  224. if ($isKey0 && $isKey1 && is_array($args[0][$key]) && is_array($args[1][$key]))
  225. {
  226. $args[2][$key] = self::arrayDeepMerge($args[0][$key], $args[1][$key]);
  227. }
  228. else if ($isKey0 && $isKey1)
  229. {
  230. $args[2][$key] = $args[1][$key];
  231. }
  232. else if (!$isKey1)
  233. {
  234. $args[2][$key] = $args[0][$key];
  235. }
  236. else if (!$isKey0)
  237. {
  238. $args[2][$key] = $args[1][$key];
  239. }
  240. }
  241. return $args[2];
  242. }
  243. else
  244. {
  245. return $args[1];
  246. }
  247. default :
  248. $args = func_get_args();
  249. $args[1] = sfToolkit::arrayDeepMerge($args[0], $args[1]);
  250. array_shift($args);
  251. return call_user_func_array(array('sfToolkit', 'arrayDeepMerge'), $args);
  252. break;
  253. }
  254. }
  255. public static function stringToArray($string)
  256. {
  257. preg_match_all('/
  258. \s*(\w+) # key \\1
  259. \s*=\s* # =
  260. (\'|")? # values may be included in \' or " \\2
  261. (.*?) # value \\3
  262. (?(2) \\2) # matching \' or " if needed \\4
  263. \s*(?:
  264. (?=\w+\s*=) | \s*$ # followed by another key= or the end of the string
  265. )
  266. /x', $string, $matches, PREG_SET_ORDER);
  267. $attributes = array();
  268. foreach ($matches as $val)
  269. {
  270. $attributes[$val[1]] = self::literalize($val[3]);
  271. }
  272. return $attributes;
  273. }
  274. /**
  275. * Finds the type of the passed value, returns the value as the new type.
  276. *
  277. * @param string
  278. * @return mixed
  279. */
  280. public static function literalize($value, $quoted = false)
  281. {
  282. // lowercase our value for comparison
  283. $value = trim($value);
  284. $lvalue = strtolower($value);
  285. if (in_array($lvalue, array('null', '~', '')))
  286. {
  287. $value = null;
  288. }
  289. else if (in_array($lvalue, array('true', 'on', '+', 'yes')))
  290. {
  291. $value = true;
  292. }
  293. else if (in_array($lvalue, array('false', 'off', '-', 'no')))
  294. {
  295. $value = false;
  296. }
  297. else if (ctype_digit($value))
  298. {
  299. $value = (int) $value;
  300. }
  301. else if (is_numeric($value))
  302. {
  303. $value = (float) $value;
  304. }
  305. else
  306. {
  307. $value = self::replaceConstants($value);
  308. if ($quoted)
  309. {
  310. $value = '\''.str_replace('\'', '\\\'', $value).'\'';
  311. }
  312. }
  313. return $value;
  314. }
  315. /**
  316. * Replaces constant identifiers in a scalar value.
  317. *
  318. * @param string the value to perform the replacement on
  319. * @return string the value with substitutions made
  320. */
  321. public static function replaceConstants($value)
  322. {
  323. return is_string($value) ? preg_replace_callback('/%(.+?)%/', create_function('$v', 'return sfConfig::has(strtolower($v[1])) ? sfConfig::get(strtolower($v[1])) : "%{$v[1]}%";'), $value) : $value;
  324. }
  325. /**
  326. * Returns subject replaced with regular expression matchs
  327. *
  328. * @param mixed subject to search
  329. * @param array array of search => replace pairs
  330. */
  331. public static function pregtr($search, $replacePairs)
  332. {
  333. return preg_replace(array_keys($replacePairs), array_values($replacePairs), $search);
  334. }
  335. public static function isArrayValuesEmpty($array)
  336. {
  337. static $isEmpty = true;
  338. foreach ($array as $value)
  339. {
  340. $isEmpty = (is_array($value)) ? self::isArrayValuesEmpty($value) : (strlen($value) == 0);
  341. if (!$isEmpty)
  342. {
  343. break;
  344. }
  345. }
  346. return $isEmpty;
  347. }
  348. /**
  349. * Checks if a string is an utf8.
  350. *
  351. * Yi Stone Li<yili@yahoo-inc.com>
  352. * Copyright (c) 2007 Yahoo! Inc. All rights reserved.
  353. * Licensed under the BSD open source license
  354. *
  355. * @param string
  356. *
  357. * @return bool true if $string is valid UTF-8 and false otherwise.
  358. */
  359. public static function isUTF8($string)
  360. {
  361. for ($idx = 0, $strlen = strlen($string); $idx < $strlen; $idx++)
  362. {
  363. $byte = ord($string[$idx]);
  364. if ($byte & 0x80)
  365. {
  366. if (($byte & 0xE0) == 0xC0)
  367. {
  368. // 2 byte char
  369. $bytes_remaining = 1;
  370. }
  371. else if (($byte & 0xF0) == 0xE0)
  372. {
  373. // 3 byte char
  374. $bytes_remaining = 2;
  375. }
  376. else if (($byte & 0xF8) == 0xF0)
  377. {
  378. // 4 byte char
  379. $bytes_remaining = 3;
  380. }
  381. else
  382. {
  383. return false;
  384. }
  385. if ($idx + $bytes_remaining >= $strlen)
  386. {
  387. return false;
  388. }
  389. while ($bytes_remaining--)
  390. {
  391. if ((ord($string[++$idx]) & 0xC0) != 0x80)
  392. {
  393. return false;
  394. }
  395. }
  396. }
  397. }
  398. return true;
  399. }
  400. public static function &getArrayValueForPathByRef(&$values, $name, $default = null)
  401. {
  402. if (false !== ($offset = strpos($name, '[')))
  403. {
  404. if (isset($values[substr($name, 0, $offset)]))
  405. {
  406. $array = &$values[substr($name, 0, $offset)];
  407. while ($pos = strpos($name, '[', $offset))
  408. {
  409. $end = strpos($name, ']', $pos);
  410. if ($end == $pos + 1)
  411. {
  412. // reached a []
  413. break;
  414. }
  415. else if (!isset($array[substr($name, $pos + 1, $end - $pos - 1)]))
  416. {
  417. return $default;
  418. }
  419. else if (is_array($array))
  420. {
  421. $array = &$array[substr($name, $pos + 1, $end - $pos - 1)];
  422. $offset = $end;
  423. }
  424. else
  425. {
  426. return $default;
  427. }
  428. }
  429. return $array;
  430. }
  431. }
  432. return $default;
  433. }
  434. public static function getArrayValueForPath($values, $name, $default = null)
  435. {
  436. if (false !== ($offset = strpos($name, '[')))
  437. {
  438. if (isset($values[substr($name, 0, $offset)]))
  439. {
  440. $array = $values[substr($name, 0, $offset)];
  441. while ($pos = strpos($name, '[', $offset))
  442. {
  443. $end = strpos($name, ']', $pos);
  444. if ($end == $pos + 1)
  445. {
  446. // reached a []
  447. break;
  448. }
  449. else if (!isset($array[substr($name, $pos + 1, $end - $pos - 1)]))
  450. {
  451. return $default;
  452. }
  453. else if (is_array($array))
  454. {
  455. $array = $array[substr($name, $pos + 1, $end - $pos - 1)];
  456. $offset = $end;
  457. }
  458. else
  459. {
  460. return $default;
  461. }
  462. }
  463. return $array;
  464. }
  465. }
  466. return $default;
  467. }
  468. public static function getPhpCli()
  469. {
  470. $path = getenv('PATH') ? getenv('PATH') : getenv('Path');
  471. $suffixes = DIRECTORY_SEPARATOR == '\\' ? (getenv('PATHEXT') ? explode(PATH_SEPARATOR, getenv('PATHEXT')) : array('.exe', '.bat', '.cmd', '.com')) : array('');
  472. foreach (array('php5', 'php') as $phpCli)
  473. {
  474. foreach ($suffixes as $suffix)
  475. {
  476. foreach (explode(PATH_SEPARATOR, $path) as $dir)
  477. {
  478. $file = $dir.DIRECTORY_SEPARATOR.$phpCli.$suffix;
  479. if (is_executable($file))
  480. {
  481. return $file;
  482. }
  483. }
  484. }
  485. }
  486. throw new sfException('Unable to find PHP executable');
  487. }
  488. /**
  489. * From PEAR System.php
  490. *
  491. * LICENSE: This source file is subject to version 3.0 of the PHP license
  492. * that is available through the world-wide-web at the following URI:
  493. * http://www.php.net/license/3_0.txt. If you did not receive a copy of
  494. * the PHP License and are unable to obtain it through the web, please
  495. * send a note to license@php.net so we can mail you a copy immediately.
  496. *
  497. * @author Tomas V.V.Cox <cox@idecnet.com>
  498. * @copyright 1997-2006 The PHP Group
  499. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  500. */
  501. public static function getTmpDir()
  502. {
  503. if (DIRECTORY_SEPARATOR == '\\')
  504. {
  505. if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP'))
  506. {
  507. return $var;
  508. }
  509. if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP'))
  510. {
  511. return $var;
  512. }
  513. if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir'))
  514. {
  515. return $var;
  516. }
  517. return getenv('SystemRoot').'\temp';
  518. }
  519. if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR'))
  520. {
  521. return $var;
  522. }
  523. return '/tmp';
  524. }
  525. }