1111namespace Behat \Gherkin ;
1212
1313use Behat \Gherkin \Exception \FilesystemException ;
14+ use ErrorException ;
1415use JsonException ;
1516use RecursiveDirectoryIterator ;
1617use RecursiveIteratorIterator ;
1718use SplFileInfo ;
1819
20+ use function assert ;
21+
1922/**
2023 * @internal
2124 */
@@ -26,12 +29,18 @@ final class Filesystem
2629 */
2730 public static function readFile (string $ fileName ): string
2831 {
29- $ data = @file_get_contents ($ fileName );
30- if ($ data === false ) {
31- throw new FilesystemException ("Failed to read file: $ fileName " );
32+ try {
33+ $ result = self ::callSafely (static fn () => file_get_contents ($ fileName ));
34+ } catch (ErrorException $ e ) {
35+ throw new FilesystemException (
36+ sprintf ('File "%s" cannot be read: %s ' , $ fileName , $ e ->getMessage ()),
37+ previous: $ e ,
38+ );
3239 }
3340
34- return $ data ;
41+ assert ($ result !== false , 'file_get_contents() should not return false without emitting a PHP warning ' );
42+
43+ return $ result ;
3544 }
3645
3746 /**
@@ -43,7 +52,7 @@ public static function readJsonFileArray(string $fileName): array
4352 {
4453 $ result = json_decode (self ::readFile ($ fileName ), true , flags: JSON_THROW_ON_ERROR );
4554
46- \ assert (is_array ($ result ), 'File must contain JSON with an array at its root ' );
55+ assert (is_array ($ result ), 'File must contain JSON with an array at its root ' );
4756
4857 return $ result ;
4958 }
@@ -67,4 +76,53 @@ public static function findFilesRecursively(string $path, string $pattern): arra
6776
6877 return $ found ;
6978 }
79+
80+ public static function getLastModified (string $ fileName ): int
81+ {
82+ try {
83+ $ result = self ::callSafely (static fn () => filemtime ($ fileName ));
84+ } catch (ErrorException $ e ) {
85+ throw new FilesystemException (
86+ sprintf ('Last modification time of file "%s" cannot be found: %s ' , $ fileName , $ e ->getMessage ()),
87+ previous: $ e ,
88+ );
89+ }
90+
91+ assert ($ result !== false , 'filemtime() should not return false without emitting a PHP warning ' );
92+
93+ return $ result ;
94+ }
95+
96+ public static function getRealPath (string $ path ): string
97+ {
98+ $ result = realpath ($ path );
99+
100+ if ($ result === false ) {
101+ throw new FilesystemException ("Cannot retrieve the real path of $ path " );
102+ }
103+
104+ return $ result ;
105+ }
106+
107+ /**
108+ * @template TResult
109+ *
110+ * @param (callable(): TResult) $callback
111+ *
112+ * @return TResult
113+ *
114+ * @throws ErrorException
115+ */
116+ private static function callSafely (callable $ callback ): mixed
117+ {
118+ set_error_handler (
119+ static fn (int $ severity , string $ message , string $ file , int $ line ) => throw new ErrorException ($ message , 0 , $ severity , $ file , $ line )
120+ );
121+
122+ try {
123+ return $ callback ();
124+ } finally {
125+ restore_error_handler ();
126+ }
127+ }
70128}
0 commit comments