* @package Combodo\iTop\Dependencies * * @since 3.2.0 N°7331 class creation to have managers for both Composer and NPM (only Composer was existing before) */ abstract class AbstractFolderAnalyzer { /** * Questionnable folder is a folder name that seems like it doesn't need to be package as it only contain * unnecessary files (e.g. lib test or example files) * * Parenthesis around alternation as it is eager (see linked ref), and we really want to use start / end of string * `^test|examples$i` would match Tester for example * `^(test|examples)$i` is not ! * * @since 3.2.0 N°7175 update regexp to also remove `examples` folder * @link https://www.regular-expressions.info/alternation.html RegExp alternation reference */ public const QUESTIONNABLE_FILES_REGEXP = '/^(tests?|examples?|htdocs?|demos?|.github|.idea)$/i'; /** * @param string $sFileName * * @return false|int as {@see \preg_match()} * @uses static::QUESTIONNABLE_FILES_REGEXP * @uses \preg_match() */ public static function IsQuestionnableFile(string $sFileName): false|int { return preg_match(static::QUESTIONNABLE_FILES_REGEXP, $sFileName); } /** * @return string Relative path to the root folder of the dependencies (e.g. "lib" for composer, "node_modules" for npm, ...) from iTop app. root */ abstract protected function GetDependenciesRootFolderRelPath(): string; /** * @return string Absolute path to the root folder of the dependencies */ public function GetDependenciesRootFolderAbsPath(): string { return $this->GetApprootPathWithSlashes().$this->GetDependenciesRootFolderRelPath(); } /** * @return string APPROOT constant but with slashes instead of DIRECTORY_SEPARATOR. * This ease writing our paths, as we can use '/' for every platform. */ final protected function GetApprootPathWithSlashes(): string { return str_replace(DIRECTORY_SEPARATOR, '/', APPROOT); } /** * @param bool $bCheckQuestionableFilesOnly If true, only questionnable folders {@see \Combodo\iTop\Dependencies\AbstractFolderAnalyzer::IsQuestionnableFile()} will be listed * * @return array List of all subdirs of the dependencies folder that are {@see IsQuestionnableFile}. * Warning : each path contains slashes (meaning on Windows you'll get eg `C:/Dev/wamp64/www/itop-27/lib/goaop/framework/tests`) */ public function ListAllFilesAbsPaths(bool $bCheckQuestionableFilesOnly = true): array { $aAllTestDirs = []; $sPath = realpath($this->GetDependenciesRootFolderAbsPath()); $oDirectoryIterator = new RecursiveDirectoryIterator($sPath, FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS); $iterator = new RecursiveIteratorIterator( $oDirectoryIterator, RecursiveIteratorIterator::CHILD_FIRST ); /** @var DirectoryIterator $file */ foreach ($iterator as $file) { $sDirName = $file->getFilename(); if ($bCheckQuestionableFilesOnly && !static::IsQuestionnableFile($sDirName)) { continue; } $sTestPathDir = $file->getRealpath(); $sTestPathDir = str_replace('\\', '/', $sTestPathDir); $aAllTestDirs[] = $sTestPathDir; } return $aAllTestDirs; } /** * @return array Array of absolute paths to allowed questionnable folders */ abstract public function ListAllowedFilesRelPaths(): array; /** * @return array Array of absolute paths to allowed folders */ public function ListAllowedFilesAbsPaths(): array { return array_map(fn ($sRelPath): string => $this->GetDependenciesRootFolderAbsPath().$sRelPath, $this->ListAllowedFilesRelPaths()); } /** * @return array Array of relative paths (from dependencies root folder {@see static::GetDependenciesRootFolderAbsPath()}) to denied folders */ abstract public function ListDeniedFilesRelPaths(): array; /** * @return array Array of absolute paths to denied folders */ public function ListDeniedFilesAbsPaths(): array { return array_map(fn ($sRelPath): string => $this->GetDependenciesRootFolderAbsPath().$sRelPath, $this->ListDeniedFilesRelPaths()); } /** * @return array Array of absolute paths to questionnable denied test folders that need to be marked as allowed or denied */ public function ListDeniedButStillPresentFilesAbsPaths(): array { $aDeniedTestDir = $this->ListDeniedFilesAbsPaths(); $aAllTestDir = $this->ListAllFilesAbsPaths(false); return array_intersect($aDeniedTestDir, $aAllTestDir); } }