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

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