-
Notifications
You must be signed in to change notification settings - Fork 286
Expand file tree
/
Copy pathAbstractFolderAnalyzer.php
More file actions
140 lines (122 loc) · 4.88 KB
/
AbstractFolderAnalyzer.php
File metadata and controls
140 lines (122 loc) · 4.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Dependencies;
use FilesystemIterator;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
/**
* Class AbstractFolderAnalyzer
*
* Extend this class to enable a dependency manager such as Composer or NPM to clean unnecessary files after an installation or update of a package.
*
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @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);
}
}