Code owners
Assign users and groups as approvers for specific file changes. Learn more.
PathExclusionsTrait.php 3.28 KiB
<?php
declare(strict_types = 1);
namespace Drupal\package_manager\PathExcluder;
use Drupal\package_manager\Event\CollectPathsToExcludeEvent;
/**
* Contains methods for excluding paths from stage operations.
*/
trait PathExclusionsTrait {
/**
* The path locator service.
*
* @var \Drupal\package_manager\PathLocator
*/
protected $pathLocator;
/**
* The path factory service.
*
* @var \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface
*/
protected $pathFactory;
/**
* Flags paths to be excluded, relative to the web root.
*
* This should only be used for paths that, if they exist at all, are
* *guaranteed* to exist within the web root.
*
* @param \Drupal\package_manager\Event\CollectPathsToExcludeEvent|\Drupal\package_manager\Event\StageEvent $event
* The event object.
* @param string[] $paths
* The paths to exclude. These should be relative to the web root, and will
* be made relative to the project root.
*/
protected function excludeInWebRoot(CollectPathsToExcludeEvent $event, array $paths): void {
$web_root = $this->pathLocator->getWebRoot();
if ($web_root) {
$web_root .= '/';
}
foreach ($paths as $path) {
// Make the path relative to the project root by prefixing the web root.
$event->add([$web_root . $path]);
}
}
/**
* Flags paths to be excluded, relative to the project root.
*
* @param \Drupal\package_manager\Event\CollectPathsToExcludeEvent|\Drupal\package_manager\Event\StageEvent $event
* The event object.
* @param string[] $paths
* The paths to exclude. Absolute paths will be made relative to the project
* root; relative paths will be assumed to already be relative to the
* project root, and excluded as given.
*/
protected function excludeInProjectRoot(CollectPathsToExcludeEvent $event, array $paths): void {
$project_root = $this->pathLocator->getProjectRoot();
foreach ($paths as $path) {
if ($this->pathFactory->create($path)->isAbsolute()) {
if (!str_starts_with($path, $project_root)) {
throw new \LogicException("$path is not inside the project root: $project_root.");
}
}
// Make absolute paths relative to the project root.
$path = str_replace($project_root, '', $path);
$path = ltrim($path, '/');
$event->add([$path]);
}
}
/**
* Finds all directories in the project root matching the given name.
*
* @param string $directory_name
* The directory name to scan for.
*
* @return string[]
* All discovered absolute paths matching the given directory name.
*/
protected function scanForDirectoriesByName(string $directory_name): array {
$flags = \FilesystemIterator::UNIX_PATHS;
$flags |= \FilesystemIterator::CURRENT_AS_SELF;
$directories_tree = new \RecursiveDirectoryIterator($this->pathLocator->getProjectRoot(), $flags);
$filtered_directories = new \RecursiveIteratorIterator($directories_tree, \RecursiveIteratorIterator::SELF_FIRST);
$matched_directories = new \CallbackFilterIterator($filtered_directories,
fn (\RecursiveDirectoryIterator $current) => $current->isDir() && $current->getFilename() === $directory_name
);
return array_keys(iterator_to_array($matched_directories));
}
}