PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/zendframework/zendframework/library/Zend/Stdlib/Glob.php

https://bitbucket.org/Evgenii/zf2t
PHP | 205 lines | 150 code | 15 blank | 40 comment | 17 complexity | 1e4f5302c6a25223f8f36b78956be47f MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\Stdlib;
  10. use Zend\Stdlib\Exception;
  11. use Zend\Stdlib\ErrorHandler;
  12. /**
  13. * Wrapper for glob with fallback if GLOB_BRACE is not available.
  14. */
  15. abstract class Glob
  16. {
  17. /**#@+
  18. * Glob constants.
  19. */
  20. const GLOB_MARK = 0x01;
  21. const GLOB_NOSORT = 0x02;
  22. const GLOB_NOCHECK = 0x04;
  23. const GLOB_NOESCAPE = 0x08;
  24. const GLOB_BRACE = 0x10;
  25. const GLOB_ONLYDIR = 0x20;
  26. const GLOB_ERR = 0x40;
  27. /**#@-*/
  28. /**
  29. * Find pathnames matching a pattern.
  30. *
  31. * @see http://docs.php.net/glob
  32. * @param string $pattern
  33. * @param int $flags
  34. * @param bool $forceFallback
  35. * @return array
  36. * @throws Exception\RuntimeException
  37. */
  38. public static function glob($pattern, $flags = 0, $forceFallback = false)
  39. {
  40. if (!defined('GLOB_BRACE') || $forceFallback) {
  41. return static::fallbackGlob($pattern, $flags);
  42. }
  43. return static::systemGlob($pattern, $flags);
  44. }
  45. /**
  46. * Use the glob function provided by the system.
  47. *
  48. * @param string $pattern
  49. * @param int $flags
  50. * @return array
  51. * @throws Exception\RuntimeException
  52. */
  53. protected static function systemGlob($pattern, $flags)
  54. {
  55. if ($flags) {
  56. $flagMap = array(
  57. self::GLOB_MARK => GLOB_MARK,
  58. self::GLOB_NOSORT => GLOB_NOSORT,
  59. self::GLOB_NOCHECK => GLOB_NOCHECK,
  60. self::GLOB_NOESCAPE => GLOB_NOESCAPE,
  61. self::GLOB_BRACE => GLOB_BRACE,
  62. self::GLOB_ONLYDIR => GLOB_ONLYDIR,
  63. self::GLOB_ERR => GLOB_ERR,
  64. );
  65. $globFlags = 0;
  66. foreach ($flagMap as $internalFlag => $globFlag) {
  67. if ($flags & $internalFlag) {
  68. $globFlags |= $globFlag;
  69. }
  70. }
  71. } else {
  72. $globFlags = 0;
  73. }
  74. ErrorHandler::start();
  75. $res = glob($pattern, $globFlags);
  76. $err = ErrorHandler::stop();
  77. if ($res === false) {
  78. throw new Exception\RuntimeException("glob('{$pattern}', {$globFlags}) failed", 0, $err);
  79. }
  80. return $res;
  81. }
  82. /**
  83. * Expand braces manually, then use the system glob.
  84. *
  85. * @param string $pattern
  86. * @param int $flags
  87. * @return array
  88. * @throws Exception\RuntimeException
  89. */
  90. protected static function fallbackGlob($pattern, $flags)
  91. {
  92. if (!$flags & self::GLOB_BRACE) {
  93. return static::systemGlob($pattern, $flags);
  94. }
  95. $flags &= ~self::GLOB_BRACE;
  96. $length = strlen($pattern);
  97. $paths = array();
  98. if ($flags & self::GLOB_NOESCAPE) {
  99. $begin = strpos($pattern, '{');
  100. } else {
  101. $begin = 0;
  102. while (true) {
  103. if ($begin === $length) {
  104. $begin = false;
  105. break;
  106. } elseif ($pattern[$begin] === '\\' && ($begin + 1) < $length) {
  107. $begin++;
  108. } elseif ($pattern[$begin] === '{') {
  109. break;
  110. }
  111. $begin++;
  112. }
  113. }
  114. if ($begin === false) {
  115. return static::systemGlob($pattern, $flags);
  116. }
  117. $next = static::nextBraceSub($pattern, $begin + 1, $flags);
  118. if ($next === null) {
  119. return static::systemGlob($pattern, $flags);
  120. }
  121. $rest = $next;
  122. while ($pattern[$rest] !== '}') {
  123. $rest = static::nextBraceSub($pattern, $rest + 1, $flags);
  124. if ($rest === null) {
  125. return static::systemGlob($pattern, $flags);
  126. }
  127. }
  128. $p = $begin + 1;
  129. while (true) {
  130. $subPattern = substr($pattern, 0, $begin)
  131. . substr($pattern, $p, $next - $p)
  132. . substr($pattern, $rest + 1);
  133. $result = static::fallbackGlob($subPattern, $flags | self::GLOB_BRACE);
  134. if ($result) {
  135. $paths = array_merge($paths, $result);
  136. }
  137. if ($pattern[$next] === '}') {
  138. break;
  139. }
  140. $p = $next + 1;
  141. $next = static::nextBraceSub($pattern, $p, $flags);
  142. }
  143. return array_unique($paths);
  144. }
  145. /**
  146. * Find the end of the sub-pattern in a brace expression.
  147. *
  148. * @param string $pattern
  149. * @param int $begin
  150. * @param int $flags
  151. * @return int|null
  152. */
  153. protected static function nextBraceSub($pattern, $begin, $flags)
  154. {
  155. $length = strlen($pattern);
  156. $depth = 0;
  157. $current = $begin;
  158. while ($current < $length) {
  159. if (!$flags & self::GLOB_NOESCAPE && $pattern[$current] === '\\') {
  160. if (++$current === $length) {
  161. break;
  162. }
  163. $current++;
  164. } else {
  165. if (($pattern[$current] === '}' && $depth-- === 0) || ($pattern[$current] === ',' && $depth === 0)) {
  166. break;
  167. } elseif ($pattern[$current++] === '{') {
  168. $depth++;
  169. }
  170. }
  171. }
  172. return ($current < $length ? $current : null);
  173. }
  174. }