Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/1.x'
Browse files Browse the repository at this point in the history
* origin/1.x:
  Add path wildcard feature to Enumerator (#300)

Conflicts:
	composer.json
	composer.lock
  • Loading branch information
lisachenko committed Nov 28, 2016
2 parents 8a89d3a + bd98a07 commit c6117d7
Show file tree
Hide file tree
Showing 4 changed files with 260 additions and 17 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
},

"require-dev": {
"symfony/console": "^2.7|^3.0"
"symfony/console": "^2.7|^3.0",
"adlawson/vfs": "^0.12"
},

"suggest": {
Expand Down
108 changes: 105 additions & 3 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 33 additions & 13 deletions src/Instrument/FileSystem/Enumerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
class Enumerator
{

/**
* Path to the root directory, where enumeration should start
*
Expand All @@ -40,14 +41,14 @@ class Enumerator
* Initializes an enumerator
*
* @param string $rootDirectory Path to the root directory
* @param array $includePaths List of additional include paths
* @param array $excludePaths List of additional exclude paths
* @param array $includePaths List of additional include paths
* @param array $excludePaths List of additional exclude paths
*/
public function __construct($rootDirectory, array $includePaths = [], array $excludePaths = [])
{
$this->rootDirectory = $rootDirectory;
$this->includePaths = $includePaths;
$this->excludePaths = $excludePaths;
$this->includePaths = $includePaths;
$this->excludePaths = $excludePaths;
}

/**
Expand Down Expand Up @@ -78,24 +79,26 @@ public function enumerate()
public function getFilter()
{
$rootDirectory = $this->rootDirectory;
$includePaths = $this->includePaths;
$excludePaths = $this->excludePaths;
$includePaths = $this->includePaths;
$excludePaths = $this->excludePaths;

return function (\SplFileInfo $file) use ($rootDirectory, $includePaths, $excludePaths) {

return function(\SplFileInfo $file) use ($rootDirectory, $includePaths, $excludePaths) {
if ($file->getExtension() !== 'php') {
return false;
};

$realPath = $file->getRealPath();
$fullPath = $this->getFileFullPath($file);
$dir = dirname($fullPath);
// Do not touch files that not under rootDirectory
if (strpos($realPath, $rootDirectory) !== 0) {
if (strpos($fullPath, $rootDirectory) !== 0) {
return false;
}

if (!empty($includePaths)) {
$found = false;
foreach ($includePaths as $includePath) {
if (strpos($realPath, $includePath) === 0) {
foreach ($includePaths as $includePattern) {
if (fnmatch($includePattern, $dir)) {
$found = true;
break;
}
Expand All @@ -105,13 +108,30 @@ public function getFilter()
}
}

foreach ($excludePaths as $excludePath) {
if (strpos($realPath, $excludePath) === 0) {
foreach ($excludePaths as $excludePattern) {
if (fnmatch($excludePattern, $dir)) {
return false;
}
}

return true;
};
}

/**
* Return the real path of the given file
*
* This is used for testing purpose with virtual file system.
* In a vfs the 'realPath' methode will always return false.
* So we have a chance to mock this single function to return different path.
*
* @param \SplFileInfo $file
*
* @return string
*/
protected function getFileFullPath(\SplFileInfo $file)
{
return $file->getRealPath();
}

}
120 changes: 120 additions & 0 deletions tests/Go/Instrument/FileSystem/EnumeratorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?php

namespace Go\Instrument;

use Go\Instrument\FileSystem\Enumerator;
use org\bovigo\vfs\vfsStream;
use Vfs\FileSystem;

class EnumeratorTest extends \PHPUnit_Framework_TestCase
{

/** @var FileSystem */
protected static $fileSystem;

/**
* Set up fixture test folders and files
*
* @throws \Exception
* @return void
*/
public static function setUpBeforeClass()
{
static::$fileSystem = FileSystem::factory('vfs://');
static::$fileSystem->mount();

$testPaths = [
'/base/sub/test',
'/base/sub/sub/test'
];

// Setup some files we test against
foreach ($testPaths as $path) {
mkdir('vfs://' . $path, 0777, true);
touch('vfs://' . $path . DIRECTORY_SEPARATOR . 'TestClass.php');
}
}

public static function tearDownAfterClass()
{
static::$fileSystem->unmount();
}

/**
* @return array
*/
public function pathsProvider()
{
return [
[
// No include or exclude, every folder should be there
['vfs://base/sub/test', 'vfs://base/sub/sub/test'],
[],
[]
],
[
// Exclude double sub folder
['vfs://base/sub/test'],
[],
['vfs://base/sub/sub/test']
],
[
// Exclude all, expected shout be empty
[],
[],
['vfs://base/sub/test', 'vfs://base/sub/sub/test']
],
[
// Exclude all sub using wildcard
[],
[],
['vfs://base/*/test']
],
[
// Includepath using wildcard should not break
['vfs://base/sub/test', 'vfs://base/sub/sub/test'],
['vfs://base/*'],
[]
]
];
}

/**
* Test wildcard path matching for Enumerator.
*
* @dataProvider pathsProvider
*
* @param array $expectedPaths
* @param array $includePaths
* @param array $excludePaths
*/
public function testExclude($expectedPaths, $includePaths, $excludePaths)
{
$testPaths = [];

/** @var Enumerator $mock */
$mock = $this->getMockBuilder(Enumerator::class)
->setConstructorArgs(['vfs://base', $includePaths, $excludePaths])
->setMethods(['getFileFullPath'])
->getMock();

// Mock getFileRealPath method to provide a pathname
// VFS does not support getRealPath()
$mock->expects($this->any())
->method('getFileFullPath')
->will($this->returnCallback(function (\SplFileInfo $file) {
return $file->getPathname();
}));

$iterator = $mock->enumerate();

foreach ($iterator as $file) {
$testPaths[] = $file->getPath();
}

sort($testPaths);
sort($expectedPaths);

$this->assertEquals($expectedPaths, $testPaths);
}
}

0 comments on commit c6117d7

Please sign in to comment.