Skip to content

Commit

Permalink
Add ComandFileDiscovery::setSearchDepth(). The search depth applies t…
Browse files Browse the repository at this point in the history
…o each search location, unless there are no search locations, in which case it applies to the base directory.
  • Loading branch information
greg-1-anderson committed Sep 9, 2016
1 parent f87d1c9 commit 560885c
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 6 deletions.
62 changes: 57 additions & 5 deletions src/CommandFileDiscovery.php
Expand Up @@ -38,6 +38,8 @@ class CommandFileDiscovery
protected $searchPattern = '*Commands.php';
/** @var boolean */
protected $includeFilesAtBase = true;
/** @var integer */
protected $searchDepth = 2;

public function __construct()
{
Expand Down Expand Up @@ -86,6 +88,18 @@ public function addExclude($exclude)
return $this;
}

/**
* Set the search depth. By default, fills immediately in the
* base directory are searched, plus all of the search locations
* to this specified depth. If the search locations is set to
* an empty array, then the base directory is searched to this
* depth.
*/
public function setSearchDepth($searchDepth)
{
$this->searchDepth = $searchDepth;
}

/**
* Set the list of search locations to examine in each directory where
* command files may be found. This replaces whatever was there before.
Expand Down Expand Up @@ -188,7 +202,7 @@ public function discover($directoryList, $baseNamespace = '')
* can be found. This will reduce the need to search through many unrelated
* files.
*
* The valid search locations include:
* The default search locations include:
*
* .
* CliTools
Expand All @@ -203,20 +217,57 @@ protected function discoverCommandFiles($directory, $baseNamespace)
// In the search location itself, we will search for command files
// immediately inside the directory only.
if ($this->includeFilesAtBase) {
$commandFiles = $this->discoverCommandFilesInLocation($directory, '== 0', $baseNamespace);
$commandFiles = $this->discoverCommandFilesInLocation(
$directory,
$this->getBaseDirectorySearchDepth(),
$baseNamespace
);
}

// In the other search locations,
foreach ($this->searchLocations as $location) {
$itemsNamespace = $this->joinNamespace([$baseNamespace, $location]);
$commandFiles = array_merge(
$commandFiles,
$this->discoverCommandFilesInLocation("$directory/$location", '< 2', $itemsNamespace)
$this->discoverCommandFilesInLocation(
"$directory/$location",
$this->getSearchDepth(),
$itemsNamespace
)
);
}
return $commandFiles;
}

/**
* Return a Finder search depth appropriate for our selected search depth.
*
* @return string
*/
protected function getSearchDepth()
{
return $this->searchDepth <= 0 ? '== 0' : '< ' . $this->searchDepth;
}

/**
* Return a Finder search depth for the base directory. If the
* searchLocations array has been populated, then we will only search
* for files immediately inside the base directory; no traversal into
* deeper directories will be done, as that would conflict with the
* specification provided by the search locations. If there is no
* search location, then we will search to whatever depth was specified
* by the client.
*
* @return string
*/
protected function getBaseDirectorySearchDepth()
{
if (!empty($this->searchLocations)) {
return '== 0';
}
return $this->getSearchDepth();
}

/**
* Search for command files in just one particular location. Returns
* an associative array mapping from the pathname of the file to the
Expand All @@ -238,13 +289,14 @@ protected function discoverCommandFilesInLocation($directory, $depth, $baseNames

$commands = [];
foreach ($finder as $file) {
$relativePathName = $file->getRelativePathname();
$relativeNamespaceAndClassname = str_replace(
['/', '.php'],
['\\', ''],
$file->getRelativePathname()
$relativePathName
);
$classname = $this->joinNamespace([$baseNamespace, $relativeNamespaceAndClassname]);
$commandFilePath = $this->joinPaths([$directory, $file->getRelativePathname()]);
$commandFilePath = $this->joinPaths([$directory, $relativePathName]);
$commands[$commandFilePath] = $classname;
}

Expand Down
41 changes: 40 additions & 1 deletion tests/testCommandFileDiscovery.php
Expand Up @@ -17,7 +17,8 @@ function testCommandDiscovery()
$commandFileNamespaces = array_values($commandFiles);

// Ensure that the command files that we expected to
// find were all found.
// find were all found. We don't find anything in
// 'beta' because only 'alpha' is in the search path.
$this->assertContains('./src/ExampleCommandFile.php', $commandFilePaths);
$this->assertContains('./src/alpha/AlphaCommandFile.php', $commandFilePaths);
$this->assertContains('./src/alpha/Inclusive/IncludedCommandFile.php', $commandFilePaths);
Expand All @@ -35,4 +36,42 @@ function testCommandDiscovery()
// know that the length of the array_keys must be the same as the
// length of the array_values.
}

function testDeepCommandDiscovery()
{
$discovery = new CommandFileDiscovery();
$discovery
->setSearchPattern('*CommandFile.php')
->setSearchLocations([]);

chdir(__DIR__);
$commandFiles = $discovery->discover('.', '\Consolidation\TestUtils');

$commandFilePaths = array_keys($commandFiles);
$commandFileNamespaces = array_values($commandFiles);

// Ensure that the command files that we expected to
// find were all found. We find both 'alpha' and 'beta'
// items because the search locations is empty, which
// causes the search at the base directory to be deep.
// We do not find alpha/Inclusive, though, as the search
// depth is only 2, which excludes directories that are
// three levels deep.
$this->assertContains('./src/ExampleCommandFile.php', $commandFilePaths);
$this->assertContains('./src/alpha/AlphaCommandFile.php', $commandFilePaths);
$this->assertContains('./src/beta/BetaCommandFile.php', $commandFilePaths);

// Make sure that there are no additional items found.
$this->assertEquals(3, count($commandFilePaths));

// Ensure that the command file namespaces that we expected
// to be generated all match.
$this->assertContains('\Consolidation\TestUtils\ExampleCommandFile', $commandFileNamespaces);
$this->assertContains('\Consolidation\TestUtils\alpha\AlphaCommandFile', $commandFileNamespaces);
$this->assertContains('\Consolidation\TestUtils\beta\BetaCommandFile', $commandFileNamespaces);

// We do not need to test for additional namespace items, because we
// know that the length of the array_keys must be the same as the
// length of the array_values.
}
}

0 comments on commit 560885c

Please sign in to comment.