You are here

abstract class Glob in Zircon Profile 8

Same name and namespace in other branches
  1. 8.0 vendor/zendframework/zend-stdlib/src/Glob.php \Zend\Stdlib\Glob

Wrapper for glob with fallback if GLOB_BRACE is not available.

Hierarchy

  • class \Zend\Stdlib\Glob

Expanded class hierarchy of Glob

File

vendor/zendframework/zend-stdlib/src/Glob.php, line 15

Namespace

Zend\Stdlib
View source
abstract class Glob {

  /**#@+
   * Glob constants.
   */
  const GLOB_MARK = 0x1;
  const GLOB_NOSORT = 0x2;
  const GLOB_NOCHECK = 0x4;
  const GLOB_NOESCAPE = 0x8;
  const GLOB_BRACE = 0x10;
  const GLOB_ONLYDIR = 0x20;
  const GLOB_ERR = 0x40;

  /**#@-*/

  /**
   * Find pathnames matching a pattern.
   *
   * @see    http://docs.php.net/glob
   * @param  string  $pattern
   * @param  int $flags
   * @param  bool $forceFallback
   * @return array
   * @throws Exception\RuntimeException
   */
  public static function glob($pattern, $flags = 0, $forceFallback = false) {
    if (!defined('GLOB_BRACE') || $forceFallback) {
      return static::fallbackGlob($pattern, $flags);
    }
    return static::systemGlob($pattern, $flags);
  }

  /**
   * Use the glob function provided by the system.
   *
   * @param  string  $pattern
   * @param  int     $flags
   * @return array
   * @throws Exception\RuntimeException
   */
  protected static function systemGlob($pattern, $flags) {
    if ($flags) {
      $flagMap = [
        self::GLOB_MARK => GLOB_MARK,
        self::GLOB_NOSORT => GLOB_NOSORT,
        self::GLOB_NOCHECK => GLOB_NOCHECK,
        self::GLOB_NOESCAPE => GLOB_NOESCAPE,
        self::GLOB_BRACE => GLOB_BRACE,
        self::GLOB_ONLYDIR => GLOB_ONLYDIR,
        self::GLOB_ERR => GLOB_ERR,
      ];
      $globFlags = 0;
      foreach ($flagMap as $internalFlag => $globFlag) {
        if ($flags & $internalFlag) {
          $globFlags |= $globFlag;
        }
      }
    }
    else {
      $globFlags = 0;
    }
    ErrorHandler::start();
    $res = glob($pattern, $globFlags);
    $err = ErrorHandler::stop();
    if ($res === false) {
      throw new Exception\RuntimeException("glob('{$pattern}', {$globFlags}) failed", 0, $err);
    }
    return $res;
  }

  /**
   * Expand braces manually, then use the system glob.
   *
   * @param  string  $pattern
   * @param  int     $flags
   * @return array
   * @throws Exception\RuntimeException
   */
  protected static function fallbackGlob($pattern, $flags) {
    if (!$flags & self::GLOB_BRACE) {
      return static::systemGlob($pattern, $flags);
    }
    $flags &= ~self::GLOB_BRACE;
    $length = strlen($pattern);
    $paths = [];
    if ($flags & self::GLOB_NOESCAPE) {
      $begin = strpos($pattern, '{');
    }
    else {
      $begin = 0;
      while (true) {
        if ($begin === $length) {
          $begin = false;
          break;
        }
        elseif ($pattern[$begin] === '\\' && $begin + 1 < $length) {
          $begin++;
        }
        elseif ($pattern[$begin] === '{') {
          break;
        }
        $begin++;
      }
    }
    if ($begin === false) {
      return static::systemGlob($pattern, $flags);
    }
    $next = static::nextBraceSub($pattern, $begin + 1, $flags);
    if ($next === null) {
      return static::systemGlob($pattern, $flags);
    }
    $rest = $next;
    while ($pattern[$rest] !== '}') {
      $rest = static::nextBraceSub($pattern, $rest + 1, $flags);
      if ($rest === null) {
        return static::systemGlob($pattern, $flags);
      }
    }
    $p = $begin + 1;
    while (true) {
      $subPattern = substr($pattern, 0, $begin) . substr($pattern, $p, $next - $p) . substr($pattern, $rest + 1);
      $result = static::fallbackGlob($subPattern, $flags | self::GLOB_BRACE);
      if ($result) {
        $paths = array_merge($paths, $result);
      }
      if ($pattern[$next] === '}') {
        break;
      }
      $p = $next + 1;
      $next = static::nextBraceSub($pattern, $p, $flags);
    }
    return array_unique($paths);
  }

  /**
   * Find the end of the sub-pattern in a brace expression.
   *
   * @param  string  $pattern
   * @param  int $begin
   * @param  int $flags
   * @return int|null
   */
  protected static function nextBraceSub($pattern, $begin, $flags) {
    $length = strlen($pattern);
    $depth = 0;
    $current = $begin;
    while ($current < $length) {
      if (!$flags & self::GLOB_NOESCAPE && $pattern[$current] === '\\') {
        if (++$current === $length) {
          break;
        }
        $current++;
      }
      else {
        if ($pattern[$current] === '}' && $depth-- === 0 || $pattern[$current] === ',' && $depth === 0) {
          break;
        }
        elseif ($pattern[$current++] === '{') {
          $depth++;
        }
      }
    }
    return $current < $length ? $current : null;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
Glob::fallbackGlob protected static function Expand braces manually, then use the system glob.
Glob::glob public static function Find pathnames matching a pattern.
Glob::GLOB_BRACE constant
Glob::GLOB_ERR constant
Glob::GLOB_MARK constant
Glob::GLOB_NOCHECK constant
Glob::GLOB_NOESCAPE constant
Glob::GLOB_NOSORT constant
Glob::GLOB_ONLYDIR constant
Glob::nextBraceSub protected static function Find the end of the sub-pattern in a brace expression.
Glob::systemGlob protected static function Use the glob function provided by the system.