@@ -126,18 +126,30 @@ public static function tell($stream, $uri = null): int
126126 }
127127
128128 /**
129- * Get the file status of a stream
129+ * Get the status of a file or stream
130130 *
131+ * @see stat()
131132 * @see fstat()
132- * @param resource $stream
133+ * @param Stringable|string| resource $resource
133134 * @param Stringable|string|null $uri
134135 * @return int[]
135136 * @throws FilesystemErrorException on failure.
136137 */
137- public static function stat ($ stream , $ uri = null ): array
138+ public static function stat ($ resource , $ uri = null ): array
138139 {
139- $ result = @fstat ($ stream );
140- return self ::throwOnFailure ($ result , 'Error getting file status of stream: %s ' , $ uri , $ stream );
140+ if (is_resource ($ resource )) {
141+ self ::assertResourceIsStream ($ resource );
142+ $ result = @fstat ($ resource );
143+ return self ::throwOnFailure ($ result , 'Error getting status of stream: %s ' , $ uri , $ resource );
144+ }
145+
146+ if (!Test::isStringable ($ resource )) {
147+ throw new InvalidArgumentTypeException (1 , 'resource ' , 'Stringable|string|resource ' , $ resource );
148+ }
149+
150+ $ resource = (string ) $ resource ;
151+ $ result = @stat ($ resource );
152+ return self ::throwOnFailure ($ result , 'Error getting file status: %s ' , $ resource );
141153 }
142154
143155 /**
@@ -181,8 +193,7 @@ public static function closePipe($pipe, ?string $command = null): int
181193 }
182194
183195 /**
184- * Get the entire contents of a file or the remaining contents of an open
185- * stream
196+ * Get the entire contents of a file or the remaining contents of a stream
186197 *
187198 * @see file_get_contents()
188199 * @see stream_get_contents()
@@ -233,7 +244,7 @@ public static function find(): RecursiveFilesystemIterator
233244 }
234245
235246 /**
236- * Get the end-of-line sequence used in a file
247+ * Get the end-of-line sequence used in a file or stream
237248 *
238249 * Recognised line endings are LF (`"\n"`), CRLF (`"\r\n"`) and CR (`"\r"`).
239250 *
@@ -247,17 +258,7 @@ public static function find(): RecursiveFilesystemIterator
247258 */
248259 public static function getEol ($ resource , $ uri = null ): ?string
249260 {
250- $ close = false ;
251- if (is_resource ($ resource )) {
252- self ::assertResourceIsStream ($ resource );
253- $ handle = $ resource ;
254- } elseif (Test::isStringable ($ resource )) {
255- $ uri = (string ) $ resource ;
256- $ handle = self ::open ($ uri , 'r ' );
257- $ close = true ;
258- } else {
259- throw new InvalidArgumentTypeException (1 , 'resource ' , 'Stringable|string|resource ' , $ resource );
260- }
261+ $ handle = self ::getStream ($ resource , 'r ' , $ close , $ uri );
261262
262263 $ line = fgets ($ handle );
263264
@@ -283,7 +284,7 @@ public static function getEol($resource, $uri = null): ?string
283284 }
284285
285286 /**
286- * Guess the indentation used in a file
287+ * Guess the indentation used in a file or stream
287288 *
288289 * Derived from VS Code's `indentationGuesser`.
289290 *
@@ -298,17 +299,7 @@ public static function guessIndentation(
298299 bool $ alwaysGuessTabSize = false ,
299300 $ uri = null
300301 ): Indentation {
301- $ close = false ;
302- if (is_resource ($ resource )) {
303- self ::assertResourceIsStream ($ resource );
304- $ handle = $ resource ;
305- } elseif (Test::isStringable ($ resource )) {
306- $ uri = (string ) $ resource ;
307- $ handle = self ::open ($ uri , 'r ' );
308- $ close = true ;
309- } else {
310- throw new InvalidArgumentTypeException (1 , 'resource ' , 'Stringable|string|resource ' , $ resource );
311- }
302+ $ handle = self ::getStream ($ resource , 'r ' , $ close , $ uri );
312303
313304 $ lines = 0 ;
314305 $ linesWithTabs = 0 ;
@@ -401,8 +392,7 @@ public static function guessIndentation(
401392 $ lineSpaces - 1 < strlen ($ _prevLine ) &&
402393 $ _line [$ lineSpaces ] !== ' ' &&
403394 $ _prevLine [$ lineSpaces - 1 ] === ' ' &&
404- $ _prevLine [-1 ] === ', ' &&
405- !(
395+ $ _prevLine [-1 ] === ', ' && !(
406396 $ default &&
407397 $ default ->InsertSpaces &&
408398 $ default ->TabSize === $ diffSpaces
@@ -450,14 +440,16 @@ public static function guessIndentation(
450440 /**
451441 * True if two paths refer to the same filesystem entry
452442 */
453- public static function is (string $ filename1 , string $ filename2 ): bool
443+ public static function same (string $ filename1 , string $ filename2 ): bool
454444 {
455445 if (!file_exists ($ filename1 ) || !file_exists ($ filename2 )) {
456446 return false ;
457447 }
458- $ inode = fileinode ($ filename1 );
459- return $ inode !== false &&
460- fileinode ($ filename2 ) === $ inode ;
448+ $ stat1 = self ::stat ($ filename1 );
449+ $ stat2 = self ::stat ($ filename2 );
450+ return
451+ $ stat1 ['dev ' ] === $ stat2 ['dev ' ] &&
452+ $ stat1 ['ino ' ] === $ stat2 ['ino ' ];
461453 }
462454
463455 /**
@@ -814,17 +806,7 @@ public static function writeCsv(
814806 bool $ bom = true ,
815807 $ uri = null
816808 ): void {
817- $ close = false ;
818- if (is_resource ($ resource )) {
819- self ::assertResourceIsStream ($ resource );
820- $ handle = $ resource ;
821- } elseif (Test::isStringable ($ resource )) {
822- $ uri = (string ) $ resource ;
823- $ handle = self ::open ($ uri , 'wb ' );
824- $ close = true ;
825- } else {
826- throw new InvalidArgumentTypeException (1 , 'resource ' , 'Stringable|string|resource ' , $ resource );
827- }
809+ $ handle = self ::getStream ($ resource , 'wb ' , $ close , $ uri );
828810
829811 if ($ utf16le ) {
830812 if (!extension_loaded ('iconv ' )) {
@@ -900,6 +882,28 @@ public static function fputcsv(
900882 );
901883 }
902884
885+ /**
886+ * @param Stringable|string|resource $resource
887+ * @param Stringable|string|null $uri
888+ * @param-out bool $close
889+ * @param-out Stringable|string|null $uri
890+ * @return resource
891+ */
892+ private static function getStream ($ resource , string $ mode , ?bool &$ close , &$ uri )
893+ {
894+ $ close = false ;
895+ if (is_resource ($ resource )) {
896+ self ::assertResourceIsStream ($ resource );
897+ return $ resource ;
898+ }
899+ if (Test::isStringable ($ resource )) {
900+ $ uri = (string ) $ resource ;
901+ $ close = true ;
902+ return self ::open ($ uri , $ mode );
903+ }
904+ throw new InvalidArgumentTypeException (1 , 'resource ' , 'Stringable|string|resource ' , $ resource );
905+ }
906+
903907 /**
904908 * @param resource $resource
905909 */
0 commit comments