1212/**
1313 * Object to manipulate files and folders.
1414 */
15- class FileSystemHelperBase implements FileSystemHelper
15+ final class FileSystemHelperBase implements FileSystemHelper
1616{
17- private ?string $ baseFolder ;
17+ private readonly ?string $ baseFolder ;
1818
1919 public function __construct (?string $ baseFolder = null )
2020 {
21+ $ validatedBaseFolder = null ;
22+
2123 if ($ baseFolder !== null ) {
22- $ baseFolder = str_replace (
23- [ '\\' , ' / ' ],
24- \ DIRECTORY_SEPARATOR ,
25- trim ( $ baseFolder )
26- );
27- }
24+ $ validatedBaseFolder = str_replace ([ '\\' , ' / ' ], \ DIRECTORY_SEPARATOR , trim ( $ baseFolder ));
25+ if ( $ validatedBaseFolder === '' ) {
26+ throw $ this -> createException (
27+ " Base folder can't be empty. Set non empty string or null "
28+ );
29+ }
2830
29- if ($ baseFolder === '' ) {
30- throw $ this ->createException (
31- "Base folder can't be empty. Set non empty string or null "
32- );
31+ $ validatedBaseFolder = realpath ($ validatedBaseFolder );
32+ if ($ validatedBaseFolder === false ) {
33+ throw $ this ->createException (
34+ "Base folder '%s' doesn't exist " ,
35+ $ baseFolder
36+ );
37+ }
3338 }
3439
35- $ this ->baseFolder = $ baseFolder ;
40+ $ this ->baseFolder = $ validatedBaseFolder ;
3641 }
3742
3843 /**
@@ -204,6 +209,9 @@ public function mkdir(SplFileInfo|string $path, int $mode = 0777): SplFileInfo
204209 true
205210 );
206211
212+ // recoursive directory creation sometimes can't set permissions for nested folder
213+ chmod ($ dir ->getPathname (), $ mode );
214+
207215 return $ dir ;
208216 }
209217
@@ -228,7 +236,12 @@ public function emptyDir(SplFileInfo|string $path): void
228236 {
229237 $ dir = $ this ->makeFileInfoAndCheckBasePath ($ path );
230238
231- if (!$ dir ->isDir ()) {
239+ if ($ dir ->isFile ()) {
240+ throw $ this ->createException (
241+ "Can't empty directory '%s' because it's a file " ,
242+ $ dir
243+ );
244+ } elseif (!$ dir ->isDir ()) {
232245 throw $ this ->createException (
233246 "Directory '%s' must exist to be emptied " ,
234247 $ dir
@@ -320,7 +333,7 @@ private function makeFileInfoAndCheckBasePath(SplFileInfo|string $data): SplFile
320333 {
321334 $ data = $ this ->makeFileInfo ($ data );
322335
323- if ($ this ->baseFolder !== null && mb_strpos ($ data ->getPathName (), $ this ->baseFolder ) !== 0 ) {
336+ if ($ this ->baseFolder !== null && strpos ($ data ->getPathName (), $ this ->baseFolder ) !== 0 ) {
324337 throw $ this ->createException (
325338 "Not allowed path '%s'. All paths must be within base directory '%s' " ,
326339 $ data ,
@@ -341,9 +354,7 @@ private function makeFileInfoAndCheckBasePath(SplFileInfo|string $data): SplFile
341354 */
342355 private function runPhpFunction (string $ functionName , ...$ params ): void
343356 {
344- $ res = (bool ) \call_user_func_array ($ functionName , $ params );
345-
346- if (!$ res ) {
357+ if (\call_user_func_array ($ functionName , $ params ) === false ) {
347358 throw $ this ->createException (
348359 "Got false result from '%s' function " ,
349360 $ functionName
@@ -361,14 +372,10 @@ private function runPhpFunction(string $functionName, ...$params): void
361372 */
362373 private function createException (string $ message , ...$ params ): FileSystemException
363374 {
364- $ stringifyParams = array_map (
365- fn (SplFileInfo |string $ item ): string => $ item instanceof SplFileInfo ? $ item ->getPathName () : $ item ,
366- $ params
367- );
375+ array_unshift ($ params , $ message );
368376
369- $ message = rtrim ($ message , '. ' ) . '. ' ;
370- array_unshift ($ stringifyParams , $ message );
371- $ compiledMessage = (string ) \call_user_func_array ('sprintf ' , $ stringifyParams );
377+ /** @var string */
378+ $ compiledMessage = \call_user_func_array ('sprintf ' , $ params );
372379
373380 return new FileSystemException ($ compiledMessage );
374381 }
0 commit comments