Development

/branches/1.1/lib/util/sfToolkit.class.php

You must first sign up to be able to contribute.

root/branches/1.1/lib/util/sfToolkit.class.php

Revision 19980, 19.1 kB (checked in by nicolas, 5 years ago)

[1.1, 1.2, 1.3] fixed the order where the tasks was loaded (fixes #4766, #5348), plus fixed case when sfToolkit::getPhpCli() could misbehave with custom user PATH

  • Property svn:mime-type set to text/x-php
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Rev Date
Line 
1 <?php
2
3 /*
4  * This file is part of the symfony package.
5  * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
6  * (c) 2004-2006 Sean Kerr <sean@code-box.org>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 /**
13  * sfToolkit provides basic utility methods.
14  *
15  * @package    symfony
16  * @subpackage util
17  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
18  * @author     Sean Kerr <sean@code-box.org>
19  * @version    SVN: $Id$
20  */
21 class sfToolkit
22 {
23   /**
24    * Extract the class or interface name from filename.
25    *
26    * @param  string $filename  A filename.
27    *
28    * @return string A class or interface name, if one can be extracted, otherwise null.
29    */
30   public static function extractClassName($filename)
31   {
32     $retval = null;
33
34     if (self::isPathAbsolute($filename))
35     {
36       $filename = basename($filename);
37     }
38
39     $pattern = '/(.*?)\.(class|interface)\.php/i';
40
41     if (preg_match($pattern, $filename, $match))
42     {
43       $retval = $match[1];
44     }
45
46     return $retval;
47   }
48
49   /**
50    * Clear all files in a given directory.
51    *
52    * @param string $directory  An absolute filesystem path to a directory.
53    */
54   public static function clearDirectory($directory)
55   {
56     if (!is_dir($directory))
57     {
58       return;
59     }
60
61     // open a file point to the cache dir
62     $fp = opendir($directory);
63
64     // ignore names
65     $ignore = array('.', '..', 'CVS', '.svn');
66
67     while (($file = readdir($fp)) !== false)
68     {
69       if (!in_array($file, $ignore))
70       {
71         if (is_link($directory.'/'.$file))
72         {
73           // delete symlink
74           unlink($directory.'/'.$file);
75         }
76         else if (is_dir($directory.'/'.$file))
77         {
78           // recurse through directory
79           self::clearDirectory($directory.'/'.$file);
80
81           // delete the directory
82           rmdir($directory.'/'.$file);
83         }
84         else
85         {
86           // delete the file
87           unlink($directory.'/'.$file);
88         }
89       }
90     }
91
92     // close file pointer
93     closedir($fp);
94   }
95
96   /**
97    * Clear all files and directories corresponding to a glob pattern.
98    *
99    * @param string $pattern  An absolute filesystem pattern.
100    */
101   public static function clearGlob($pattern)
102   {
103     $files = glob($pattern);
104
105     // order is important when removing directories
106     sort($files);
107
108     foreach ($files as $file)
109     {
110       if (is_dir($file))
111       {
112         // delete directory
113         self::clearDirectory($file);
114       }
115       else
116       {
117         // delete file
118         unlink($file);
119       }
120     }
121   }
122
123   /**
124    * Determine if a filesystem path is absolute.
125    *
126    * @param  path $path  A filesystem path.
127    *
128    * @return bool true, if the path is absolute, otherwise false.
129    */
130   public static function isPathAbsolute($path)
131   {
132     if ($path[0] == '/' || $path[0] == '\\' ||
133         (strlen($path) > 3 && ctype_alpha($path[0]) &&
134          $path[1] == ':' &&
135          ($path[2] == '\\' || $path[2] == '/')
136         )
137        )
138     {
139       return true;
140     }
141
142     return false;
143   }
144
145   /**
146    * Determine if a lock file is present.
147    *
148    * @param  string  $lockFile             Name of the lock file.
149    * @param  integer $maxLockFileLifeTime  A max amount of life time for the lock file.
150    *
151    * @return bool true, if the lock file is present, otherwise false.
152    */
153   public static function hasLockFile($lockFile, $maxLockFileLifeTime = 0)
154   {
155     $isLocked = false;
156     if (is_readable($lockFile) && ($last_access = fileatime($lockFile)))
157     {
158       $now = time();
159       $timeDiff = $now - $last_access;
160
161       if (!$maxLockFileLifeTime || $timeDiff < $maxLockFileLifeTime)
162       {
163         $isLocked = true;
164       }
165       else
166       {
167         $isLocked = @unlink($lockFile) ? false : true;
168       }
169     }
170
171     return $isLocked;
172   }
173
174   /**
175    * Strips comments from php source code
176    *
177    * @param  string $source  PHP source code.
178    *
179    * @return string Comment free source code.
180    */
181   public static function stripComments($source)
182   {
183     if (!sfConfig::get('sf_strip_comments', true) || !function_exists('token_get_all'))
184     {
185       return $source;
186     }
187
188     $ignore = array(T_COMMENT => true, T_DOC_COMMENT => true);
189     $output = '';
190
191     foreach (token_get_all($source) as $token)
192     {
193       // array
194       if (isset($token[1]))
195       {
196         // no action on comments
197         if (!isset($ignore[$token[0]]))
198         {
199           // anything else -> output "as is"
200           $output .= $token[1];
201         }
202       }
203       else
204       {
205         // simple 1-character token
206         $output .= $token;
207       }
208     }
209
210     return $output;
211   }
212
213   /**
214    * Strip slashes recursively from array
215    *
216    * @param  array $value  the value to strip
217    *
218    * @return array clean value with slashes stripped
219    */
220   public static function stripslashesDeep($value)
221   {
222     return is_array($value) ? array_map(array('sfToolkit', 'stripslashesDeep'), $value) : stripslashes($value);
223   }
224
225   // code from php at moechofe dot com (array_merge comment on php.net)
226   /*
227    * array arrayDeepMerge ( array array1 [, array array2 [, array ...]] )
228    *
229    * Like array_merge
230    *
231    *  arrayDeepMerge() merges the elements of one or more arrays together so
232    * that the values of one are appended to the end of the previous one. It
233    * returns the resulting array.
234    *  If the input arrays have the same string keys, then the later value for
235    * that key will overwrite the previous one. If, however, the arrays contain
236    * numeric keys, the later value will not overwrite the original value, but
237    * will be appended.
238    *  If only one array is given and the array is numerically indexed, the keys
239    * get reindexed in a continuous way.
240    *
241    * Different from array_merge
242    *  If string keys have arrays for values, these arrays will merge recursively.
243    */
244   public static function arrayDeepMerge()
245   {
246     switch (func_num_args())
247     {
248       case 0:
249         return false;
250       case 1:
251         return func_get_arg(0);
252       case 2:
253         $args = func_get_args();
254         $args[2] = array();
255         if (is_array($args[0]) && is_array($args[1]))
256         {
257           foreach (array_unique(array_merge(array_keys($args[0]),array_keys($args[1]))) as $key)
258           {
259             $isKey0 = array_key_exists($key, $args[0]);
260             $isKey1 = array_key_exists($key, $args[1]);
261             if ($isKey0 && $isKey1 && is_array($args[0][$key]) && is_array($args[1][$key]))
262             {
263               $args[2][$key] = self::arrayDeepMerge($args[0][$key], $args[1][$key]);
264             }
265             else if ($isKey0 && $isKey1)
266             {
267               $args[2][$key] = $args[1][$key];
268             }
269             else if (!$isKey1)
270             {
271               $args[2][$key] = $args[0][$key];
272             }
273             else if (!$isKey0)
274             {
275               $args[2][$key] = $args[1][$key];
276             }
277           }
278           return $args[2];
279         }
280         else
281         {
282           return $args[1];
283         }
284       default :
285         $args = func_get_args();
286         $args[1] = sfToolkit::arrayDeepMerge($args[0], $args[1]);
287         array_shift($args);
288         return call_user_func_array(array('sfToolkit', 'arrayDeepMerge'), $args);
289         break;
290     }
291   }
292
293   /**
294    * Converts string to array
295    *
296    * @param  string $string  the value to convert to array
297    *
298    * @return array
299    */
300   public static function stringToArray($string)
301   {
302     preg_match_all('/
303       \s*(\w+)              # key                               \\1
304       \s*=\s*               # =
305       (\'|")?               # values may be included in \' or " \\2
306       (.*?)                 # value                             \\3
307       (?(2) \\2)            # matching \' or " if needed        \\4
308       \s*(?:
309         (?=\w+\s*=) | \s*$  # followed by another key= or the end of the string
310       )
311     /x', $string, $matches, PREG_SET_ORDER);
312
313     $attributes = array();
314     foreach ($matches as $val)
315     {
316       $attributes[$val[1]] = self::literalize($val[3]);
317     }
318
319     return $attributes;
320   }
321
322   /**
323    * Finds the type of the passed value, returns the value as the new type.
324    *
325    * @param  string $value
326    * @param  bool   $quoted  Quote?
327    *
328    * @return mixed
329    */
330   public static function literalize($value, $quoted = false)
331   {
332     // lowercase our value for comparison
333     $value  = trim($value);
334     $lvalue = strtolower($value);
335
336     if (in_array($lvalue, array('null', '~', '')))
337     {
338       $value = null;
339     }
340     else if (in_array($lvalue, array('true', 'on', '+', 'yes')))
341     {
342       $value = true;
343     }
344     else if (in_array($lvalue, array('false', 'off', '-', 'no')))
345     {
346       $value = false;
347     }
348     else if (ctype_digit($value))
349     {
350       $value = (int) $value;
351     }
352     else if (is_numeric($value))
353     {
354       $value = (float) $value;
355     }
356     else
357     {
358       $value = self::replaceConstants($value);
359       if ($quoted)
360       {
361         $value = '\''.str_replace('\'', '\\\'', $value).'\'';
362       }
363     }
364
365     return $value;
366   }
367
368   /**
369    * Replaces constant identifiers in a scalar value.
370    *
371    * @param  string $value  the value to perform the replacement on
372    *
373    * @return string the value with substitutions made
374    */
375   public static function replaceConstants($value)
376   {
377     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;
378   }
379
380   /**
381    * Returns subject replaced with regular expression matchs
382    *
383    * @param mixed $search        subject to search
384    * @param array $replacePairs  array of search => replace pairs
385    */
386   public static function pregtr($search, $replacePairs)
387   {
388     return preg_replace(array_keys($replacePairs), array_values($replacePairs), $search);
389   }
390
391   /**
392    * Checks if array values are empty
393    *
394    * @param  array $array  the array to check
395    * @return boolean true if empty, otherwise false
396    */
397   public static function isArrayValuesEmpty($array)
398   {
399     static $isEmpty = true;
400     foreach ($array as $value)
401     {
402       $isEmpty = (is_array($value)) ? self::isArrayValuesEmpty($value) : (strlen($value) == 0);
403       if (!$isEmpty)
404       {
405         break;
406       }
407     }
408
409     return $isEmpty;
410   }
411
412   /**
413    * Checks if a string is an utf8.
414    *
415    * Yi Stone Li<yili@yahoo-inc.com>
416    * Copyright (c) 2007 Yahoo! Inc. All rights reserved.
417    * Licensed under the BSD open source license
418    *
419    * @param string
420    *
421    * @return bool true if $string is valid UTF-8 and false otherwise.
422    */
423   public static function isUTF8($string)
424   {
425     for ($idx = 0, $strlen = strlen($string); $idx < $strlen; $idx++)
426     {
427       $byte = ord($string[$idx]);
428
429       if ($byte & 0x80)
430       {
431         if (($byte & 0xE0) == 0xC0)
432         {
433           // 2 byte char
434           $bytes_remaining = 1;
435         }
436         else if (($byte & 0xF0) == 0xE0)
437         {
438           // 3 byte char
439           $bytes_remaining = 2;
440         }
441         else if (($byte & 0xF8) == 0xF0)
442         {
443           // 4 byte char
444           $bytes_remaining = 3;
445         }
446         else
447         {
448           return false;
449         }
450
451         if ($idx + $bytes_remaining >= $strlen)
452         {
453           return false;
454         }
455
456         while ($bytes_remaining--)
457         {
458           if ((ord($string[++$idx]) & 0xC0) != 0x80)
459           {
460             return false;
461           }
462         }
463       }
464     }
465
466     return true;
467   }
468
469   /**
470    * Returns a reference to an array value for a path.
471    *
472    * @param array  $values   The values to search
473    * @param string $name     The token name
474    * @param array  $default  Default if not found
475    *
476    * @return array reference
477    */
478   public static function &getArrayValueForPathByRef(&$values, $name, $default = null)
479   {
480     if (false === $offset = strpos($name, '['))
481     {
482       $return = $default;
483       if (isset($values[$name]))
484       {
485         $return = &$values[$name];
486       }
487       return $return;
488     }
489
490     if (!isset($values[substr($name, 0, $offset)]))
491     {
492       return $default;
493     }
494
495     $array = &$values[substr($name, 0, $offset)];
496
497     while (false !== $pos = strpos($name, '[', $offset))
498     {
499       $end = strpos($name, ']', $pos);
500       if ($end == $pos + 1)
501       {
502         // reached a []
503         if (!is_array($array))
504         {
505           return $default;
506         }
507         break;
508       }
509       else if (!isset($array[substr($name, $pos + 1, $end - $pos - 1)]))
510       {
511         return $default;
512       }
513       else if (is_array($array))
514       {
515         $array = &$array[substr($name, $pos + 1, $end - $pos - 1)];
516         $offset = $end;
517       }
518       else
519       {
520         return $default;
521       }
522     }
523
524     return $array;
525   }
526
527   /**
528    * Returns an array value for a path.
529    *
530    * @param array  $values   The values to search
531    * @param string $name     The token name
532    * @param array  $default  Default if not found
533    *
534    * @return array
535    */
536   public static function getArrayValueForPath($values, $name, $default = null)
537   {
538     if (false === $offset = strpos($name, '['))
539     {
540       return isset($values[$name]) ? $values[$name] : $default;
541     }
542
543     if (!isset($values[substr($name, 0, $offset)]))
544     {
545       return $default;
546     }
547
548     $array = $values[substr($name, 0, $offset)];
549
550     while (false !== $pos = strpos($name, '[', $offset))
551     {
552       $end = strpos($name, ']', $pos);
553       if ($end == $pos + 1)
554       {
555         // reached a []
556         if (!is_array($array))
557         {
558           return $default;
559         }
560         break;
561       }
562       else if (!isset($array[substr($name, $pos + 1, $end - $pos - 1)]))
563       {
564         return $default;
565       }
566       else if (is_array($array))
567       {
568         $array = $array[substr($name, $pos + 1, $end - $pos - 1)];
569         $offset = $end;
570       }
571       else
572       {
573         return $default;
574       }
575     }
576
577     return $array;
578   }
579
580   /**
581    * Returns true if the a path exists for the given array.
582    *
583    * @param array  $values  The values to search
584    * @param string $name    The token name
585    *
586    * @return bool
587    */
588   public static function hasArrayValueForPath($values, $name)
589   {
590     if (false === $offset = strpos($name, '['))
591     {
592       return array_key_exists($name, $values);
593     }
594
595     if (!isset($values[substr($name, 0, $offset)]))
596     {
597       return false;
598     }
599
600     $array = $values[substr($name, 0, $offset)];
601     while (false !== $pos = strpos($name, '[', $offset))
602     {
603       $end = strpos($name, ']', $pos);
604       if ($end == $pos + 1)
605       {
606         // reached a []
607         return is_array($array);
608       }
609       else if (!isset($array[substr($name, $pos + 1, $end - $pos - 1)]))
610       {
611         return false;
612       }
613       else if (is_array($array))
614       {
615         $array = $array[substr($name, $pos + 1, $end - $pos - 1)];
616         $offset = $end;
617       }
618       else
619       {
620         return false;
621       }
622     }
623
624     return true;
625   }
626
627   /**
628    * Removes a path for the given array.
629    *
630    * @param array  $values   The values to search
631    * @param string $name     The token name
632    * @param mixed  $default  The default value to return if the name does not exist
633    */
634   public static function removeArrayValueForPath(&$values, $name, $default = null)
635   {
636     if (false === $offset = strpos($name, '['))
637     {
638       if (isset($values[$name]))
639       {
640         $value = $values[$name];
641         unset($values[$name]);
642
643         return $value;
644       }
645       else
646       {
647         return $default;
648       }
649     }
650
651     if (!isset($values[substr($name, 0, $offset)]))
652     {
653       return $default;
654     }
655
656     $value = &$values[substr($name, 0, $offset)];
657
658     while (false !== $pos = strpos($name, '[', $offset))
659     {
660       $end = strpos($name, ']', $pos);
661       if ($end == $pos + 1)
662       {
663         // reached a []
664         if (!is_array($value))
665         {
666           return $default;
667         }
668         break;
669       }
670       else if (!isset($value[substr($name, $pos + 1, $end - $pos - 1)]))
671       {
672         return $default;
673       }
674       else if (is_array($value))
675       {
676         $parent = &$value;
677         $key = substr($name, $pos + 1, $end - $pos - 1);
678         $value = &$value[$key];
679         $offset = $end;
680       }
681       else
682       {
683         return $default;
684       }
685     }
686
687     if ($key)
688     {
689       unset($parent[$key]);
690     }
691
692     return $value;
693   }
694
695   /**
696    * Get path to php cli.
697    *
698    * @throws sfException If no php cli found
699    * @return string
700    */
701   public static function getPhpCli()
702   {
703     $path = getenv('PATH') ? getenv('PATH') : getenv('Path');
704     $suffixes = DIRECTORY_SEPARATOR == '\\' ? (getenv('PATHEXT') ? explode(PATH_SEPARATOR, getenv('PATHEXT')) : array('.exe', '.bat', '.cmd', '.com')) : array('');
705     foreach (array('php5', 'php') as $phpCli)
706     {
707       foreach ($suffixes as $suffix)
708       {
709         foreach (explode(PATH_SEPARATOR, $path) as $dir)
710         {
711           if (is_file($file = $dir.DIRECTORY_SEPARATOR.$phpCli.$suffix) && is_executable($file))
712           {
713             return $file;
714           }
715         }
716       }
717     }
718
719     throw new sfException('Unable to find PHP executable.');
720   }
721
722   /**
723    * From PEAR System.php
724    *
725    * LICENSE: This source file is subject to version 3.0 of the PHP license
726    * that is available through the world-wide-web at the following URI:
727    * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
728    * the PHP License and are unable to obtain it through the web, please
729    * send a note to license@php.net so we can mail you a copy immediately.
730    *
731    * @author     Tomas V.V.Cox <cox@idecnet.com>
732    * @copyright  1997-2006 The PHP Group
733    * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
734    */
735   public static function getTmpDir()
736   {
737     if (DIRECTORY_SEPARATOR == '\\')
738     {
739       if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP'))
740       {
741         return $var;
742       }
743       if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP'))
744       {
745         return $var;
746       }
747       if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir'))
748       {
749         return $var;
750       }
751
752       return getenv('SystemRoot').'\temp';
753     }
754
755     if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR'))
756     {
757       return $var;
758     }
759
760     return '/tmp';
761   }
762
763   /**
764    * Converts strings to UTF-8 via iconv. NB, the result may not by UTF-8 if the conversion failed.
765    *
766    * This file comes from Prado (BSD License)
767    *
768    * @param  string $string string to convert to UTF-8
769    * @param  string $from   current encoding
770    *
771    * @return string UTF-8 encoded string, original string if iconv failed.
772    */
773   static public function I18N_toUTF8($string, $from)
774   {
775     $from = strtoupper($from);
776     if ($from != 'UTF-8')
777     {
778       $s = iconv($from,'UTF-8',$string);  // to UTF-8
779
780       return $s !== false ? $s : $string; // it could return false
781     }
782
783     return $string;
784   }
785
786   /**
787    * Converts UTF-8 strings to a different encoding. NB. The result may not have been encoded if iconv fails.
788    *
789    * This file comes from Prado (BSD License)
790    *
791    * @param  string $string  the UTF-8 string for conversion
792    * @param  string $to      new encoding
793    *
794    * @return string encoded string.
795    */
796   static public function I18N_toEncoding($string, $to)
797   {
798     $to = strtoupper($to);
799     if ($to != 'UTF-8')
800     {
801       $s = iconv('UTF-8', $to, $string);
802
803       return $s !== false ? $s : $string;
804     }
805
806     return $string;
807   }
808 }
809
Note: See TracBrowser for help on using the browser.