@@ -54,7 +54,11 @@ class AmazonS3 extends Common {
5454
5555 private bool $ serverSideCopyEnabled ;
5656
57- /** Failure counter keyed by endpoint fingerprint. Static so sibling mounts share state within a request. */
57+ /**
58+ * Keyed by endpoint fingerprint. Static because sibling mounts share state within a request.
59+ *
60+ * @psalm-suppress ImpureStaticProperty MUST persist across per-mount instances within a request.
61+ */
5862 private static array $ serverSideCopyFailureCounter = [];
5963
6064 /** Fast path MUST stay disabled for the remainder of the request after this many consecutive S3Exceptions per endpoint. */
@@ -818,7 +822,7 @@ public function writeStream(string $path, $stream, ?int $size = null): int {
818822 return $ size ;
819823 }
820824
821- #[Override]
825+ #[\ Override]
822826 public function getDirectDownload (string $ path ): array |false {
823827 if (!$ this ->isUsePresignedUrl ()) {
824828 return false ;
@@ -848,7 +852,7 @@ public function getDirectDownload(string $path): array|false {
848852 ];
849853 }
850854
851- #[Override]
855+ #[\ Override]
852856 public function getDirectDownloadById (string $ fileId ): array |false {
853857 if (!$ this ->isUsePresignedUrl ()) {
854858 return false ;
@@ -858,7 +862,7 @@ public function getDirectDownloadById(string $fileId): array|false {
858862 return $ this ->getDirectDownload ($ entry ->getPath ());
859863 }
860864
861- #[Override]
865+ #[\ Override]
862866 public function copyFromStorage (IStorage $ sourceStorage , string $ sourceInternalPath , string $ targetInternalPath , bool $ preserveMtime = false ): bool {
863867 if ($ preserveMtime === true ) {
864868 return parent ::copyFromStorage ($ sourceStorage , $ sourceInternalPath , $ targetInternalPath , $ preserveMtime );
@@ -887,7 +891,7 @@ public function copyFromStorage(IStorage $sourceStorage, string $sourceInternalP
887891 }
888892 }
889893
890- #[Override]
894+ #[\ Override]
891895 public function moveFromStorage (IStorage $ sourceStorage , string $ sourceInternalPath , string $ targetInternalPath ): bool {
892896 $ eligibility = $ this ->evaluateFastPathEligibility ($ sourceStorage , $ sourceInternalPath );
893897 if ($ eligibility === null ) {
@@ -964,10 +968,7 @@ private function handleFastPathFailure(S3Exception $exception, string $targetKey
964968 }
965969
966970 /**
967- * Returns null when the terminal storage is not an AmazonS3. Otherwise returns the
968- * unwrapped storage plus the Jail-translated path.
969- *
970- * @return array{0: self, 1: string}|null
971+ * @return array{0: self, 1: string}|null Unwrapped storage and Jail-translated path, or null when the terminal storage is not AmazonS3.
971972 */
972973 private function unwrapSource (IStorage $ sourceStorage , string $ sourceInternalPath ): ?array {
973974 $ current = $ sourceStorage ;
@@ -991,10 +992,7 @@ private function isSameS3Endpoint(self $other): bool {
991992 }
992993
993994 /**
994- * Normalised endpoint identity tuple. Two AmazonS3 instances with identical fingerprints
995- * target the same S3 endpoint under the same access-key ID.
996- *
997- * @return list<string>
995+ * @return list<string> Endpoint identity tuple including access-key ID so distinct credentials against the same host do not collide.
998996 */
999997 private function endpointFingerprint (): array {
1000998 return [
@@ -1091,8 +1089,7 @@ private function copyObjectFromForeignBucket(
10911089 }
10921090
10931091 /**
1094- * Delete the source after a successful server-side copy. Roll back the destination on
1095- * cleanup failure to mirror AmazonS3::rename() semantics and to let the caller retry.
1092+ * Roll back the destination on cleanup failure to mirror AmazonS3::rename() semantics and let the caller retry.
10961093 */
10971094 private function deleteSourceAfterMove (self $ source , string $ sourcePath , string $ targetPath ): bool {
10981095 $ deleted = $ source ->is_dir ($ sourcePath ) ? $ source ->rmdir ($ sourcePath ) : $ source ->unlink ($ sourcePath );
0 commit comments