Development

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

You must first sign up to be able to contribute.

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

Revision 29525, 18.4 kB (checked in by fabien, 4 years ago)

[1.3, 1.4] fixed a warning (closes #8547)

  • Property svn:mime-type set to text/x-php
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
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     if (false === $files = glob($pattern))
104     {
105       return;
106     }
107
108     // order is important when removing directories
109     sort($files);
110
111     foreach ($files as $file)
112     {
113       if (is_dir($file))
114       {
115         // delete directory
116         self::clearDirectory($file);
117       }
118       else
119       {
120         // delete file
121         unlink($file);
122       }
123     }
124   }
125
126   /**
127    * Determine if a filesystem path is absolute.
128    *
129    * @param  path $path  A filesystem path.
130    *
131    * @return bool true, if the path is absolute, otherwise false.
132    */
133   public static function isPathAbsolute($path)
134   {
135     if ($path[0] == '/' || $path[0] == '\\' ||
136         (strlen($path) > 3 && ctype_alpha($path[0]) &&
137          $path[1] == ':' &&
138          ($path[2] == '\\' || $path[2] == '/')
139         )
140        )
141     {
142       return true;
143     }
144
145     return false;
146   }
147
148   /**
149    * Strips comments from php source code
150    *
151    * @param  string $source  PHP source code.
152    *
153    * @return string Comment free source code.
154    */
155   public static function stripComments($source)
156   {
157     if (!function_exists('token_get_all'))
158     {
159       return $source;
160     }
161
162     $ignore = array(T_COMMENT => true, T_DOC_COMMENT => true);
163     $output = '';
164
165     foreach (token_get_all($source) as $token)
166     {
167       // array
168       if (isset($token[1]))
169       {
170         // no action on comments
171         if (!isset($ignore[$token[0]]))
172         {
173           // anything else -> output "as is"
174           $output .= $token[1];
175         }
176       }
177       else
178       {
179         // simple 1-character token
180         $output .= $token;
181       }
182     }
183
184     return $output;
185   }
186
187   /**
188    * Strip slashes recursively from array
189    *
190    * @param  array $value  the value to strip
191    *
192    * @return array clean value with slashes stripped
193    */
194   public static function stripslashesDeep($value)
195   {
196     return is_array($value) ? array_map(array('sfToolkit', 'stripslashesDeep'), $value) : stripslashes($value);
197   }
198
199   // code from php at moechofe dot com (array_merge comment on php.net)
200   /*
201    * array arrayDeepMerge ( array array1 [, array array2 [, array ...]] )
202    *
203    * Like array_merge
204    *
205    *  arrayDeepMerge() merges the elements of one or more arrays together so
206    * that the values of one are appended to the end of the previous one. It
207    * returns the resulting array.
208    *  If the input arrays have the same string keys, then the later value for
209    * that key will overwrite the previous one. If, however, the arrays contain
210    * numeric keys, the later value will not overwrite the original value, but
211    * will be appended.
212    *  If only one array is given and the array is numerically indexed, the keys
213    * get reindexed in a continuous way.
214    *
215    * Different from array_merge
216    *  If string keys have arrays for values, these arrays will merge recursively.
217    */
218   public static function arrayDeepMerge()
219   {
220     switch (func_num_args())
221     {
222       case 0:
223         return false;
224       case 1:
225         return func_get_arg(0);
226       case 2:
227         $args = func_get_args();
228         $args[2] = array();
229         if (is_array($args[0]) && is_array($args[1]))
230         {
231           foreach (array_unique(array_merge(array_keys($args[0]),array_keys($args[1]))) as $key)
232           {
233             $isKey0 = array_key_exists($key, $args[0]);
234             $isKey1 = array_key_exists($key, $args[1]);
235             if ($isKey0 && $isKey1 && is_array($args[0][$key]) && is_array($args[1][$key]))
236             {
237               $args[2][$key] = self::arrayDeepMerge($args[0][$key], $args[1][$key]);
238             }
239             else if ($isKey0 && $isKey1)
240             {
241               $args[2][$key] = $args[1][$key];
242             }
243             else if (!$isKey1)
244             {
245               $args[2][$key] = $args[0][$key];
246             }
247             else if (!$isKey0)
248             {
249               $args[2][$key] = $args[1][$key];
250             }
251           }
252           return $args[2];
253         }
254         else
255         {
256           return $args[1];
257         }
258       default :
259         $args = func_get_args();
260         $args[1] = sfToolkit::arrayDeepMerge($args[0], $args[1]);
261         array_shift($args);
262         return call_user_func_array(array('sfToolkit', 'arrayDeepMerge'), $args);
263         break;
264     }
265   }
266
267   /**
268    * Converts string to array
269    *
270    * @param  string $string  the value to convert to array
271    *
272    * @return array
273    */
274   public static function stringToArray($string)
275   {
276     preg_match_all('/
277       \s*(\w+)              # key                               \\1
278       \s*=\s*               # =
279       (\'|")?               # values may be included in \' or " \\2
280       (.*?)                 # value                             \\3
281       (?(2) \\2)            # matching \' or " if needed        \\4
282       \s*(?:
283         (?=\w+\s*=) | \s*$  # followed by another key= or the end of the string
284       )
285     /x', $string, $matches, PREG_SET_ORDER);
286
287     $attributes = array();
288     foreach ($matches as $val)
289     {
290       $attributes[$val[1]] = self::literalize($val[3]);
291     }
292
293     return $attributes;
294   }
295
296   /**
297    * Finds the type of the passed value, returns the value as the new type.
298    *
299    * @param  string $value
300    * @param  bool   $quoted  Quote?
301    *
302    * @return mixed
303    */
304   public static function literalize($value, $quoted = false)
305   {
306     // lowercase our value for comparison
307     $value  = trim($value);
308     $lvalue = strtolower($value);
309
310     if (in_array($lvalue, array('null', '~', '')))
311     {
312       $value = null;
313     }
314     else if (in_array($lvalue, array('true', 'on', '+', 'yes')))
315     {
316       $value = true;
317     }
318     else if (in_array($lvalue, array('false', 'off', '-', 'no')))
319     {
320       $value = false;
321     }
322     else if (ctype_digit($value))
323     {
324       $value = (int) $value;
325     }
326     else if (is_numeric($value))
327     {
328       $value = (float) $value;
329     }
330     else
331     {
332       $value = self::replaceConstants($value);
333       if ($quoted)
334       {
335         $value = '\''.str_replace('\'', '\\\'', $value).'\'';
336       }
337     }
338
339     return $value;
340   }
341
342   /**
343    * Replaces constant identifiers in a scalar value.
344    *
345    * @param  string $value  the value to perform the replacement on
346    *
347    * @return string the value with substitutions made
348    */
349   public static function replaceConstants($value)
350   {
351     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;
352   }
353
354   /**
355    * Returns subject replaced with regular expression matchs
356    *
357    * @param mixed $search        subject to search
358    * @param array $replacePairs  array of search => replace pairs
359    */
360   public static function pregtr($search, $replacePairs)
361   {
362     return preg_replace(array_keys($replacePairs), array_values($replacePairs), $search);
363   }
364
365   /**
366    * Checks if array values are empty
367    *
368    * @param  array $array  the array to check
369    * @return boolean true if empty, otherwise false
370    */
371   public static function isArrayValuesEmpty($array)
372   {
373     static $isEmpty = true;
374     foreach ($array as $value)
375     {
376       $isEmpty = (is_array($value)) ? self::isArrayValuesEmpty($value) : (strlen($value) == 0);
377       if (!$isEmpty)
378       {
379         break;
380       }
381     }
382
383     return $isEmpty;
384   }
385
386   /**
387    * Checks if a string is an utf8.
388    *
389    * Yi Stone Li<yili@yahoo-inc.com>
390    * Copyright (c) 2007 Yahoo! Inc. All rights reserved.
391    * Licensed under the BSD open source license
392    *
393    * @param string
394    *
395    * @return bool true if $string is valid UTF-8 and false otherwise.
396    */
397   public static function isUTF8($string)
398   {
399     for ($idx = 0, $strlen = strlen($string); $idx < $strlen; $idx++)
400     {
401       $byte = ord($string[$idx]);
402
403       if ($byte & 0x80)
404       {
405         if (($byte & 0xE0) == 0xC0)
406         {
407           // 2 byte char
408           $bytes_remaining = 1;
409         }
410         else if (($byte & 0xF0) == 0xE0)
411         {
412           // 3 byte char
413           $bytes_remaining = 2;
414         }
415         else if (($byte & 0xF8) == 0xF0)
416         {
417           // 4 byte char
418           $bytes_remaining = 3;
419         }
420         else
421         {
422           return false;
423         }
424
425         if ($idx + $bytes_remaining >= $strlen)
426         {
427           return false;
428         }
429
430         while ($bytes_remaining--)
431         {
432           if ((ord($string[++$idx]) & 0xC0) != 0x80)
433           {
434             return false;
435           }
436         }
437       }
438     }
439
440     return true;
441   }
442
443   /**
444    * Returns a reference to an array value for a path.
445    *
446    * @param array  $values   The values to search
447    * @param string $name     The token name
448    * @param array  $default  Default if not found
449    *
450    * @return array reference
451    */
452   public static function &getArrayValueForPathByRef(&$values, $name, $default = null)
453   {
454     if (false === $offset = strpos($name, '['))
455     {
456       $return = $default;
457       if (isset($values[$name]))
458       {
459         $return = &$values[$name];
460       }
461       return $return;
462     }
463
464     if (!isset($values[substr($name, 0, $offset)]))
465     {
466       return $default;
467     }
468
469     $array = &$values[substr($name, 0, $offset)];
470
471     while (false !== $pos = strpos($name, '[', $offset))
472     {
473       $end = strpos($name, ']', $pos);
474       if ($end == $pos + 1)
475       {
476         // reached a []
477         if (!is_array($array))
478         {
479           return $default;
480         }
481         break;
482       }
483       else if (!isset($array[substr($name, $pos + 1, $end - $pos - 1)]))
484       {
485         return $default;
486       }
487       else if (is_array($array))
488       {
489         $array = &$array[substr($name, $pos + 1, $end - $pos - 1)];
490         $offset = $end;
491       }
492       else
493       {
494         return $default;
495       }
496     }
497
498     return $array;
499   }
500
501   /**
502    * Returns an array value for a path.
503    *
504    * @param array  $values   The values to search
505    * @param string $name     The token name
506    * @param array  $default  Default if not found
507    *
508    * @return array
509    */
510   public static function getArrayValueForPath($values, $name, $default = null)
511   {
512     if (false === $offset = strpos($name, '['))
513     {
514       return isset($values[$name]) ? $values[$name] : $default;
515     }
516
517     if (!isset($values[substr($name, 0, $offset)]))
518     {
519       return $default;
520     }
521
522     $array = $values[substr($name, 0, $offset)];
523
524     while (false !== $pos = strpos($name, '[', $offset))
525     {
526       $end = strpos($name, ']', $pos);
527       if ($end == $pos + 1)
528       {
529         // reached a []
530         if (!is_array($array))
531         {
532           return $default;
533         }
534         break;
535       }
536       else if (!isset($array[substr($name, $pos + 1, $end - $pos - 1)]))
537       {
538         return $default;
539       }
540       else if (is_array($array))
541       {
542         $array = $array[substr($name, $pos + 1, $end - $pos - 1)];
543         $offset = $end;
544       }
545       else
546       {
547         return $default;
548       }
549     }
550
551     return $array;
552   }
553
554   /**
555    * Returns true if the a path exists for the given array.
556    *
557    * @param array  $values  The values to search
558    * @param string $name    The token name
559    *
560    * @return bool
561    */
562   public static function hasArrayValueForPath($values, $name)
563   {
564     if (false === $offset = strpos($name, '['))
565     {
566       return array_key_exists($name, $values);
567     }
568
569     if (!isset($values[substr($name, 0, $offset)]))
570     {
571       return false;
572     }
573
574     $array = $values[substr($name, 0, $offset)];
575     while (false !== $pos = strpos($name, '[', $offset))
576     {
577       $end = strpos($name, ']', $pos);
578       if ($end == $pos + 1)
579       {
580         // reached a []
581         return is_array($array);
582       }
583       else if (!isset($array[substr($name, $pos + 1, $end - $pos - 1)]))
584       {
585         return false;
586       }
587       else if (is_array($array))
588       {
589         $array = $array[substr($name, $pos + 1, $end - $pos - 1)];
590         $offset = $end;
591       }
592       else
593       {
594         return false;
595       }
596     }
597
598     return true;
599   }
600
601   /**
602    * Removes a path for the given array.
603    *
604    * @param array  $values   The values to search
605    * @param string $name     The token name
606    * @param mixed  $default  The default value to return if the name does not exist
607    */
608   public static function removeArrayValueForPath(&$values, $name, $default = null)
609   {
610     if (false === $offset = strpos($name, '['))
611     {
612       if (isset($values[$name]))
613       {
614         $value = $values[$name];
615         unset($values[$name]);
616
617         return $value;
618       }
619       else
620       {
621         return $default;
622       }
623     }
624
625     if (!isset($values[substr($name, 0, $offset)]))
626     {
627       return $default;
628     }
629
630     $value = &$values[substr($name, 0, $offset)];
631
632     while (false !== $pos = strpos($name, '[', $offset))
633     {
634       $end = strpos($name, ']', $pos);
635       if ($end == $pos + 1)
636       {
637         // reached a []
638         if (!is_array($value))
639         {
640           return $default;
641         }
642         break;
643       }
644       else if (!isset($value[substr($name, $pos + 1, $end - $pos - 1)]))
645       {
646         return $default;
647       }
648       else if (is_array($value))
649       {
650         $parent = &$value;
651         $key = substr($name, $pos + 1, $end - $pos - 1);
652         $value = &$value[$key];
653         $offset = $end;
654       }
655       else
656       {
657         return $default;
658       }
659     }
660
661     if ($key)
662     {
663       unset($parent[$key]);
664     }
665
666     return $value;
667   }
668
669   /**
670    * Get path to php cli.
671    *
672    * @throws sfException If no php cli found
673    * @return string
674    */
675   public static function getPhpCli()
676   {
677     $path = getenv('PATH') ? getenv('PATH') : getenv('Path');
678     $suffixes = DIRECTORY_SEPARATOR == '\\' ? (getenv('PATHEXT') ? explode(PATH_SEPARATOR, getenv('PATHEXT')) : array('.exe', '.bat', '.cmd', '.com')) : array('');
679     foreach (array('php5', 'php') as $phpCli)
680     {
681       foreach ($suffixes as $suffix)
682       {
683         foreach (explode(PATH_SEPARATOR, $path) as $dir)
684         {
685           if (is_file($file = $dir.DIRECTORY_SEPARATOR.$phpCli.$suffix) && is_executable($file))
686           {
687             return $file;
688           }
689         }
690       }
691     }
692
693     throw new sfException('Unable to find PHP executable.');
694   }
695
696   /**
697    * DEPRECATED. Use sys_get_temp_dir() directly (available since PHP 5.2.1).
698    */
699   public static function getTmpDir()
700   {
701     return sys_get_temp_dir();
702   }
703
704   /**
705    * Converts strings to UTF-8 via iconv. NB, the result may not by UTF-8 if the conversion failed.
706    *
707    * This file comes from Prado (BSD License)
708    *
709    * @param  string $string string to convert to UTF-8
710    * @param  string $from   current encoding
711    *
712    * @return string UTF-8 encoded string, original string if iconv failed.
713    */
714   static public function I18N_toUTF8($string, $from)
715   {
716     $from = strtoupper($from);
717     if ($from != 'UTF-8')
718     {
719       $s = iconv($from,'UTF-8',$string);  // to UTF-8
720
721       return $s !== false ? $s : $string; // it could return false
722     }
723
724     return $string;
725   }
726
727   /**
728    * Converts UTF-8 strings to a different encoding. NB. The result may not have been encoded if iconv fails.
729    *
730    * This file comes from Prado (BSD License)
731    *
732    * @param  string $string  the UTF-8 string for conversion
733    * @param  string $to      new encoding
734    *
735    * @return string encoded string.
736    */
737   static public function I18N_toEncoding($string, $to)
738   {
739     $to = strtoupper($to);
740     if ($to != 'UTF-8')
741     {
742       $s = iconv('UTF-8', $to, $string);
743
744       return $s !== false ? $s : $string;
745     }
746
747     return $string;
748   }
749
750   /**
751    * Adds a path to the PHP include_path setting.
752    *
753    * @param   mixed  $path     Single string path or an array of paths
754    * @param   string $position Either 'front' or 'back'
755    *
756    * @return  string The old include path
757    */
758   static public function addIncludePath($path, $position = 'front')
759   {
760     if (is_array($path))
761     {
762       foreach ('front' == $position ? array_reverse($path) : $path as $p)
763       {
764         self::addIncludePath($p, $position);
765       }
766
767       return;
768     }
769
770     $paths = explode(PATH_SEPARATOR, get_include_path());
771
772     // remove what's already in the include_path
773     if (false !== $key = array_search(realpath($path), array_map('realpath', $paths)))
774     {
775       unset($paths[$key]);
776     }
777
778     switch ($position)
779     {
780       case 'front':
781         array_unshift($paths, $path);
782         break;
783       case 'back':
784         $paths[] = $path;
785         break;
786       default:
787         throw new InvalidArgumentException(sprintf('Unrecognized position: "%s"', $position));
788     }
789
790     return set_include_path(join(PATH_SEPARATOR, $paths));
791   }
792 }
793
Note: See TracBrowser for help on using the browser.