PHP_Compat
[ class tree: PHP_Compat ] [ index: PHP_Compat ] [ all elements ]

Source for file glob.php

Documentation is available at glob.php

  1. <?php
  2. // $Id: glob.php,v 1.7 2007/04/17 10:09:56 arpad Exp $
  3.  
  4.  
  5. if (!defined('GLOB_ERR')) {
  6.     define('GLOB_ERR'1);
  7. }
  8. if (!defined('GLOB_MARK')) {
  9.     define('GLOB_MARK'2);
  10. }
  11. if (!defined('GLOB_NOSORT')) {
  12.     define('GLOB_NOSORT'4);
  13. }
  14. if (!defined('GLOB_NOCHECK')) {
  15.     define('GLOB_NOCHECK'16);
  16. }
  17. if (!defined('GLOB_NOESCAPE')) {
  18.     define('GLOB_NOESCAPE'64);
  19. }
  20. if (!defined('GLOB_BRACE')) {
  21.     define('GLOB_BRACE'1024);
  22. }
  23. if (!defined('GLOB_ONLYDIR')) {
  24.     define('GLOB_ONLYDIR'8192);
  25. }
  26.  
  27. /**
  28.  * Replace glob()
  29.  *
  30.  * @category    PHP
  31.  * @package     PHP_Compat
  32.  * @license     LGPL - http://www.gnu.org/licenses/lgpl.html
  33.  * @copyright   2004-2007 Aidan Lister <aidan@php.net>, Arpad Ray <arpad@php.net>
  34.  * @link        http://php.net/glob
  35.  * @author      Arpad Ray <arpad@php.net>
  36.  * @version     $Revision: 1.7 $
  37.  * @since       PHP 4.3.0
  38.  * @require     PHP 3.0.9 (preg_replace)
  39.  */
  40. function php_compat_glob($pattern$flags = 0)
  41. {
  42.     $return_failure ($flags GLOB_NOCHECK? array($pattern: false;
  43.     
  44.     // build path to scan files
  45.     $path '.';
  46.     $wildcards_open '*?[';
  47.     $wildcards_close ']';
  48.     if ($flags GLOB_BRACE{
  49.         $wildcards_open .= '{';
  50.         $wildcards_close .= '}';
  51.     }
  52.     $prefix_length strcspn($pattern$wildcards_open);
  53.     if ($prefix_length{
  54.         if (DIRECTORY_SEPARATOR == '\\')  {
  55.             $sep ($flags GLOB_NOESCAPE'[\\\\/]' '(?:/|\\\\(?![' $wildcards_open $wildcards_close ']))';
  56.         else {
  57.             $sep '/';
  58.         }
  59.         if (preg_match('#^(.*)' $sep '#'substr($pattern0$prefix_length)$matches)) {
  60.             $path $matches[1];
  61.         }
  62.     }
  63.     $recurse (strpos($patternDIRECTORY_SEPARATOR$prefix_length!== false);
  64.     
  65.     // scan files
  66.     $files php_compat_glob_scan_helper($path$flags$recurse);
  67.     if ($files === false{
  68.         return $return_failure;
  69.     }
  70.  
  71.     // build preg pattern
  72.     $pattern php_compat_glob_convert_helper($pattern$flags);
  73.     $convert_patterns = array('/\{([^{}]*)\}/e''/\[([^\]]*)\]/e');
  74.     $convert_replacements = array(
  75.         'php_compat_glob_brace_helper(\'$1\', $flags)',
  76.         'php_compat_glob_charclass_helper(\'$1\', $flags)'
  77.     );
  78.     while ($flags GLOB_BRACE{
  79.         $new_pattern preg_replace($convert_patterns$convert_replacements$pattern);
  80.         if ($new_pattern == $pattern{
  81.             break;
  82.         }
  83.         $pattern $new_pattern;
  84.     }
  85.     $pattern '#^' $pattern '\z#';
  86.  
  87.     // process files
  88.     $results = array();
  89.     foreach ($files as $file => $dir{
  90.         if (!preg_match($pattern$file$matches)) {
  91.             continue;
  92.         }
  93.         if (($flags GLOB_ONLYDIR&& !$dir{
  94.             continue;
  95.         }
  96.         $file (($flags GLOB_MARK&& $dir$file DIRECTORY_SEPARATOR : $file;
  97.         if ($flags GLOB_BRACE{
  98.             // find last matching subpattern
  99.             $rank = 0;
  100.             for ($i = 1$matchc count($matches)$i $matchc$i++{
  101.                 if (strlen($matches[$i])) {
  102.                     $rank $i;
  103.                 }
  104.             }
  105.             $file = array($file$rank);
  106.         }
  107.         $results[$file;
  108.     }
  109.     
  110.     if ($flags GLOB_BRACE{
  111.         usort($results($flags GLOB_NOSORT'php_compat_glob_brace_nosort_helper' 'php_compat_glob_brace_sort_helper');
  112.     else if ($flags GLOB_NOSORT{
  113.         usort($results'php_compat_glob_nosort_helper');
  114.     else {
  115.         sort($results);
  116.     }
  117.     
  118.     // array_values() for php 4 +
  119.     $reindex = array();
  120.     foreach ($results as $result{
  121.         $reindex[($flags GLOB_BRACE$result[0$result;
  122.     }
  123.  
  124.     if (($flags GLOB_NOCHECK&& !count($reindex)) {
  125.         return $return_failure;
  126.     }
  127.     return $reindex;
  128. }
  129.  
  130. /**
  131.  * Scans a path
  132.  *
  133.  * @param string $path 
  134.  *   the path to scan
  135.  * @param int $flags 
  136.  *   the flags passed to glob()
  137.  * @param bool $recurse 
  138.  *   true to scan recursively
  139.  * @return mixed 
  140.  *   an array of files in the given path where the key is the path,
  141.  *   and the value is 1 if the file is a directory, 0 if it isn't.
  142.  *   Returns false on unrecoverable errors, or all errors when
  143.  *   GLOB_ERR is on.
  144.  */
  145. function php_compat_glob_scan_helper($path$flags$recurse = false)
  146. {
  147.     if (!is_readable($path)) {
  148.         return false;
  149.     }
  150.     $results = array();
  151.     if (is_dir($path)) {
  152.         $fp opendir($path);
  153.         if (!$fp{
  154.             return ($flags GLOB_ERR? false : array($path);
  155.         }
  156.         if ($path != '.'{
  157.             $results[$path= 1;
  158.         }
  159.         while (($file readdir($fp)) !== false{
  160.             if ($file[0== '.' || $file == '..'{
  161.                 continue;
  162.             }
  163.             $filepath ($path == '.'$file $path DIRECTORY_SEPARATOR . $file;
  164.             if (is_dir($filepath)) {
  165.                 $results[$filepath= 1;
  166.                 if (!$recurse{
  167.                     continue;
  168.                 }
  169.                 $files php_compat_glob_scan_helper($filepath$flags);
  170.                 if ($files === false{
  171.                     if ($flags GLOB_ERR{
  172.                         return false;
  173.                     }
  174.                     continue;
  175.                 }
  176.                 // array_merge for php 4 +
  177.                 foreach ($files as $rfile => $rdir{
  178.                     $results[$rfile$rdir;
  179.                 }
  180.                 continue;
  181.             }
  182.             $results[$filepath= 0;
  183.         }
  184.         closedir($fp);
  185.     else {
  186.         $results[$path= 0;
  187.     }
  188.     return $results;
  189. }
  190.  
  191. /**
  192.  * Converts a section of a glob pattern to a PCRE pattern
  193.  *
  194.  * @param string $input 
  195.  *   the pattern to convert
  196.  * @param int $flags 
  197.  *   the flags passed to glob()
  198.  * @return string 
  199.  *   the escaped input
  200.  */
  201. function php_compat_glob_convert_helper($input$flags)
  202. {
  203.     $opens = array(
  204.         '{' => array('}'0),
  205.         '[' => array(']'0),
  206.         '(' => array(')'0)
  207.     );
  208.     $ret '';
  209.     for ($i = 0$len strlen($input)$i $len$i++{
  210.         $skip = false;
  211.         $c $input[$i];
  212.         $escaped ($i && $input[$i - 1== '\\' && ($flags GLOB_NOCHECK == false));
  213.         
  214.         // skips characters classes and subpatterns, they are escaped in their respective helpers
  215.         foreach ($opens as $k => $v{
  216.             if ($v[1]{
  217.                 if ($c == $v[0&& !$escaped{
  218.                     --$opens[$k][1];
  219.                     $ret .= $c;
  220.                     continue 2;
  221.                 }
  222.                 $skip = true;
  223.             }
  224.         }
  225.         if (isset($opens[$c])) {
  226.             if (!$escaped{
  227.                 ++$opens[$c][1];
  228.             }
  229.             $ret .= $c;
  230.             continue;
  231.         }
  232.         if ($skip{
  233.             $ret .= $c;
  234.             continue;
  235.         }
  236.         
  237.         // converts wildcards
  238.         switch ($c{
  239.         case '*':
  240.             $ret .= $escaped '*' '.*';
  241.             continue 2;
  242.         case '?':
  243.             if ($escaped{
  244.                 continue;
  245.             }
  246.             $ret .= '.';
  247.             continue 2;
  248.         }
  249.         $ret .= preg_quote($c'#');
  250.     }
  251.     return $ret;
  252. }
  253.  
  254. /**
  255.  * Converts glob braces
  256.  *
  257.  * @param string $brace 
  258.  *   the contents of the braces to convert
  259.  * @param int $flags 
  260.  *   the flags passed to glob()
  261.  * @return string 
  262.  *   a PCRE subpattern of alternatives
  263.  */
  264. function php_compat_glob_brace_helper($brace$flags)
  265. {
  266.     $alternatives explode(','$brace);
  267.     for ($i count($alternatives)$i--;{
  268.         $alternatives[$iphp_compat_glob_convert_helper($alternatives[$i]$flags);
  269.     }
  270.     return '(?:(' implode(')|('$alternatives'))';
  271. }
  272.  
  273. /**
  274.  * Converts glob character classes
  275.  *
  276.  * @param string $class 
  277.  *   the contents of the class to convert
  278.  * @param int $flags 
  279.  *   the flags passed to glob()
  280.  * @return string 
  281.  *   a PCRE character class
  282.  */
  283. function php_compat_glob_charclass_helper($class$flags)
  284. {
  285.     if (strpos($class'-'!== false{
  286.         $class strtr($classarray('-' => '')) '-';
  287.     }
  288.     if (strpos($class']'!== false{
  289.         $class ']' strtr($classarray(']' => ''));
  290.     }
  291.     if (strpos($class'^'!== false{
  292.         $class '\^' strtr($classarray('^' => ''));
  293.     }
  294.     return '[' strtr($classarray('#' => '\#')) ']';
  295. }
  296.  
  297. /**
  298.  * Callback sort function for GLOB_NOSORT
  299.  *
  300.  * Sorts first by the base name, then in reverse by the extension
  301.  */
  302. {
  303.     $operands = array(array('full' => $a)array('full' => $b));
  304.     foreach ($operands as $k => $v{
  305.         $v['pos'strrpos($v['full']'.');
  306.         if ($v['pos'=== false{
  307.             $v['pos'strlen($v['full']- 1;
  308.         }
  309.         $v['slash'strrpos($v['full']DIRECTORY_SEPARATOR);
  310.         if ($v['slash'=== false{
  311.             $v['slash'strlen($v['full']- 1;
  312.         }
  313.         $operands[$k]['dir'substr($v['full']0$v['slash']);
  314.         $operands[$k]['base'substr($v['full']$v['slash']$v['pos'$v['slash']);
  315.         $operands[$k]['ext'substr($v['full']$v['pos'+ 1);
  316.     }
  317.     $dir_cmp strcmp($operands[0]['dir']$operands[1]['dir']);
  318.     if ($dir_cmp == 0{
  319.         $base_cmp strcmp($operands[0]['base']$operands[1]['base']);
  320.         if ($base_cmp == 0{
  321.             $ext_cmp strcmp($operands[0]['ext']$operands[1]['ext']);
  322.             return -$ext_cmp;
  323.         }
  324.         return $base_cmp;
  325.     }
  326.     return -$dir_cmp;
  327. }
  328.  
  329. /**
  330.  * Callback sort function for GLOB_BRACE
  331.  *
  332.  * Each argument should be an array where the first element is the
  333.  * file path, and the second is its rank. The rank is the number of
  334.  * alternatives between this match and the beginning of the brace.
  335.  */
  336. {
  337.     if ($a[1== $b[1]{
  338.         return strcmp($a[0]$b[0]);
  339.     }
  340.     return ($a[1$b[1]? -1 : 1;
  341. }
  342.  
  343. /**
  344.  * Callback sort function for (GLOB_BRACE | GLOB_NOSORT)
  345.  *
  346.  * Receives the same arguments php_compat_glob_brace_sort_helper()
  347.  */
  348. {
  349.     if ($a[1== $b[1]{
  350.         $len_a strlen($a[0]);
  351.         $len_b strlen($b[0]);
  352.         if ($len_a == $len_b
  353.             return -strcmp($a[0]$b[0]);
  354.         }
  355.         return ($len_a $len_b? -1 : 1;
  356.     }
  357.     return ($a[1$b[1]? -1 : 1;
  358. }
  359.  
  360. if (!function_exists('glob')) {
  361.     function glob($pattern$flags = 0)
  362.     {
  363.         return php_compat_glob($pattern$flags);
  364.     }
  365. }
  366.  
  367. ?>

Documentation generated on Mon, 11 Mar 2019 15:01:54 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.