Skip to content
This repository has been archived by the owner on Jan 31, 2020. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'zf2/master' into feature/mail
Browse files Browse the repository at this point in the history
  • Loading branch information
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 0 deletions.
209 changes: 209 additions & 0 deletions src/Glob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Stdlib
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\Stdlib;

/**
* Wrapper for glob with fallback if GLOB_BRACE is not available.
*
* @category Zend
* @package Zend_Stdlib
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Glob
{
/**#@+
* Glob constants.
*/
const GLOB_MARK = 0x01;
const GLOB_NOSORT = 0x02;
const GLOB_NOCHECK = 0x04;
const GLOB_NOESCAPE = 0x08;
const GLOB_BRACE = 0x10;
const GLOB_ONLYDIR = 0x20;
const GLOB_ERR = 0x30;
/**#@-*/

/**
* Find pathnames matching a pattern.
*
* @see http://docs.php.net/glob
* @param string $pattern
* @param integer $flags
* @param boolean $forceFallback
* @return array|false
*/
public static function glob($pattern, $flags, $forceFallback = false)
{
if (!defined('GLOB_BRACE') || $forceFallback) {
return self::fallbackGlob($pattern, $flags);
} else {
return self::systemGlob($pattern, $flags);
}
}

/**
* Use the glob function provided by the system.
*
* @param string $pattern
* @param integer $flags
* @return array|false
*/
protected static function systemGlob($pattern, $flags)
{
if ($flags) {
$flagMap = array(
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;
}

return glob($pattern, $globFlags);
}

/**
* Expand braces manually, then use the system glob.
*
* @param string $pattern
* @param integer $flags
* @return array|false
*/
protected static function fallbackGlob($pattern, $flags)
{
if (!$flags & self::GLOB_BRACE) {
return self::systemGlob($pattern, $flags);
}

$flags &= ~self::GLOB_BRACE;
$length = strlen($pattern);
$paths = array();

if ($flags & self::GLOB_NOESCAPE) {
$begin = strpos($pattern, '{');
} else {
$begin = 0;

while (true) {
if ($begin === $length) {
$begin = false;
break;
} else if ($pattern[$begin] === '\\' && ($begin + 1) < $length) {
$begin++;
} else if ($pattern[$begin] === '{') {
break;
}

$begin++;
}
}

if ($begin === false) {
return self::systemGlob($pattern, $flags);
}

$next = self::nextBraceSub($pattern, $begin + 1, $flags);

if ($next === null) {
return self::systemGlob($pattern, $flags);
}

$rest = $next;

while ($pattern[$rest] !== '}') {
$rest = self::nextBraceSub($pattern, $rest + 1, $flags);

if ($rest === null) {
return self::systemGlob($pattern, $flags);
}
}

$p = $begin + 1;

while (true) {
$subPattern = substr($pattern, 0, $begin)
. substr($pattern, $p, $next - $p)
. substr($pattern, $rest + 1);

$result = self::fallbackGlob($subPattern, $flags | self::GLOB_BRACE);

if ($result) {
$paths = array_merge($paths, $result);
}

if ($pattern[$next] === '}') {
break;
}

$p = $next + 1;
$next = self::nextBraceSub($pattern, $p, $flags);
}

return array_unique($paths);
}

/**
* Find the end of the sub-pattern in a brace expression.
*
* @param string $pattern
* @param integer $begin
* @param integer $flags
* @return integer|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;
} else if ($pattern[$current++] === '{') {
$depth++;
}
}
}

return ($current < $length ? $current : null);
}
}
41 changes: 41 additions & 0 deletions test/GlobTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Stdlib
* @subpackage UnitTests
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id:$
*/

namespace ZendTest\Stdlib;

use PHPUnit_Framework_TestCase as TestCase,
Zend\Stdlib\Glob;

class GlobTest extends TestCase
{
public function testFallback()
{
if (!defined('GLOB_BRACE')) {
$this->markTestSkipped('GLOB_BRACE not available');
}

$this->assertEquals(
glob(__DIR__ . '/_files/{alph,bet}a', GLOB_BRACE),
Glob::glob(__DIR__ . '/_files/{alph,bet}a', Glob::GLOB_BRACE, true)
);
}
}
Empty file added test/_files/alpha
Empty file.
Empty file added test/_files/beta
Empty file.
Empty file added test/_files/delta
Empty file.
Empty file added test/_files/gamma
Empty file.

0 comments on commit af68643

Please sign in to comment.