Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 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: sfToolkit.class.php 29525 2010-05-19 13:01:43Z fabien $
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 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
451
   */
452
  public static function getArrayValueForPath($values, $name, $default = null)
453
  {
454
    if (false === $offset = strpos($name, '['))
455
    {
456
      return isset($values[$name]) ? $values[$name] : $default;
457
    }
458
 
459
    if (!isset($values[substr($name, 0, $offset)]))
460
    {
461
      return $default;
462
    }
463
 
464
    $array = $values[substr($name, 0, $offset)];
465
 
466
    while (false !== $pos = strpos($name, '[', $offset))
467
    {
468
      $end = strpos($name, ']', $pos);
469
      if ($end == $pos + 1)
470
      {
471
        // reached a []
472
        if (!is_array($array))
473
        {
474
          return $default;
475
        }
476
        break;
477
      }
478
      else if (!isset($array[substr($name, $pos + 1, $end - $pos - 1)]))
479
      {
480
        return $default;
481
      }
482
      else if (is_array($array))
483
      {
484
        $array = $array[substr($name, $pos + 1, $end - $pos - 1)];
485
        $offset = $end;
486
      }
487
      else
488
      {
489
        return $default;
490
      }
491
    }
492
 
493
    return $array;
494
  }
495
 
496
  /**
497
   * Get path to php cli.
498
   *
499
   * @throws sfException If no php cli found
500
   * @return string
501
   */
502
  public static function getPhpCli()
503
  {
504
    $path = getenv('PATH') ? getenv('PATH') : getenv('Path');
505
    $suffixes = DIRECTORY_SEPARATOR == '\\' ? (getenv('PATHEXT') ? explode(PATH_SEPARATOR, getenv('PATHEXT')) : array('.exe', '.bat', '.cmd', '.com')) : array('');
506
    foreach (array('php5', 'php') as $phpCli)
507
    {
508
      foreach ($suffixes as $suffix)
509
      {
510
        foreach (explode(PATH_SEPARATOR, $path) as $dir)
511
        {
512
          if (is_file($file = $dir.DIRECTORY_SEPARATOR.$phpCli.$suffix) && is_executable($file))
513
          {
514
            return $file;
515
          }
516
        }
517
      }
518
    }
519
 
520
    throw new sfException('Unable to find PHP executable.');
521
  }
522
 
523
  /**
524
   * Converts strings to UTF-8 via iconv. NB, the result may not by UTF-8 if the conversion failed.
525
   *
526
   * This file comes from Prado (BSD License)
527
   *
528
   * @param  string $string string to convert to UTF-8
529
   * @param  string $from   current encoding
530
   *
531
   * @return string UTF-8 encoded string, original string if iconv failed.
532
   */
533
  static public function I18N_toUTF8($string, $from)
534
  {
535
    $from = strtoupper($from);
536
    if ($from != 'UTF-8')
537
    {
538
      $s = iconv($from,'UTF-8',$string);  // to UTF-8
539
 
540
      return $s !== false ? $s : $string; // it could return false
541
    }
542
 
543
    return $string;
544
  }
545
 
546
  /**
547
   * Converts UTF-8 strings to a different encoding. NB. The result may not have been encoded if iconv fails.
548
   *
549
   * This file comes from Prado (BSD License)
550
   *
551
   * @param  string $string  the UTF-8 string for conversion
552
   * @param  string $to      new encoding
553
   *
554
   * @return string encoded string.
555
   */
556
  static public function I18N_toEncoding($string, $to)
557
  {
558
    $to = strtoupper($to);
559
    if ($to != 'UTF-8')
560
    {
561
      $s = iconv('UTF-8', $to, $string);
562
 
563
      return $s !== false ? $s : $string;
564
    }
565
 
566
    return $string;
567
  }
568
 
569
  /**
570
   * Adds a path to the PHP include_path setting.
571
   *
572
   * @param   mixed  $path     Single string path or an array of paths
573
   * @param   string $position Either 'front' or 'back'
574
   *
575
   * @return  string The old include path
576
   */
577
  static public function addIncludePath($path, $position = 'front')
578
  {
579
    if (is_array($path))
580
    {
581
      foreach ('front' == $position ? array_reverse($path) : $path as $p)
582
      {
583
        self::addIncludePath($p, $position);
584
      }
585
 
586
      return;
587
    }
588
 
589
    $paths = explode(PATH_SEPARATOR, get_include_path());
590
 
591
    // remove what's already in the include_path
592
    if (false !== $key = array_search(realpath($path), array_map('realpath', $paths)))
593
    {
594
      unset($paths[$key]);
595
    }
596
 
597
    switch ($position)
598
    {
599
      case 'front':
600
        array_unshift($paths, $path);
601
        break;
602
      case 'back':
603
        $paths[] = $path;
604
        break;
605
      default:
606
        throw new InvalidArgumentException(sprintf('Unrecognized position: "%s"', $position));
607
    }
608
 
609
    return set_include_path(join(PATH_SEPARATOR, $paths));
610
  }
611
}