diff --git a/app/code/Magento/Eav/Model/Attribute/Data/Image.php b/app/code/Magento/Eav/Model/Attribute/Data/Image.php index d61a8b5fda5b1..dd2fa48058151 100644 --- a/app/code/Magento/Eav/Model/Attribute/Data/Image.php +++ b/app/code/Magento/Eav/Model/Attribute/Data/Image.php @@ -5,7 +5,7 @@ */ namespace Magento\Eav\Model\Attribute\Data; -use Magento\Framework\Filesystem\ExtendedDriverInterface; +use Magento\RemoteStorage\Driver\RemoteDriverInterface; /** * EAV Entity Attribute Image File Data Model @@ -29,7 +29,7 @@ protected function _validateByRules($value) { $label = __($this->getAttribute()->getStoreLabel()); $rules = $this->getAttribute()->getValidateRules(); - $localStorage = !$this->_directory->getDriver() instanceof ExtendedDriverInterface; + $localStorage = !$this->_directory->getDriver() instanceof RemoteDriverInterface; $imageProp = $localStorage ? @getimagesize($value['tmp_name']) : $this->_directory->getDriver()->getMetadata($value['tmp_name']); diff --git a/app/code/Magento/Eav/composer.json b/app/code/Magento/Eav/composer.json index 5636b0d05841c..29c6f66f038ea 100644 --- a/app/code/Magento/Eav/composer.json +++ b/app/code/Magento/Eav/composer.json @@ -11,7 +11,8 @@ "magento/module-catalog": "*", "magento/module-config": "*", "magento/module-media-storage": "*", - "magento/module-store": "*" + "magento/module-store": "*", + "magento/module-remote-storage": "*" }, "type": "magento2-module", "license": [ diff --git a/app/code/Magento/MediaGallerySynchronization/Model/CreateAssetFromFile.php b/app/code/Magento/MediaGallerySynchronization/Model/CreateAssetFromFile.php index 19c2569695d56..d5490a77cf31b 100644 --- a/app/code/Magento/MediaGallerySynchronization/Model/CreateAssetFromFile.php +++ b/app/code/Magento/MediaGallerySynchronization/Model/CreateAssetFromFile.php @@ -15,6 +15,7 @@ use Magento\MediaGalleryApi\Api\Data\AssetInterfaceFactory; use Magento\MediaGallerySynchronization\Model\Filesystem\GetFileInfo; use Magento\MediaGallerySynchronizationApi\Model\CreateAssetFromFileInterface; +use Magento\RemoteStorage\Driver\RemoteDriverInterface; /** * Create media asset object based on the file information @@ -75,7 +76,7 @@ public function execute(string $path): AssetInterface $absolutePath = $this->getMediaDirectory()->getAbsolutePath($path); $driver = $this->getMediaDirectory()->getDriver(); - if ($driver instanceof Filesystem\ExtendedDriverInterface) { + if ($driver instanceof RemoteDriverInterface) { $meta = $driver->getMetadata($absolutePath); } else { /** diff --git a/app/code/Magento/MediaGallerySynchronization/composer.json b/app/code/Magento/MediaGallerySynchronization/composer.json index f9d642dd02568..3e9a446d572fe 100644 --- a/app/code/Magento/MediaGallerySynchronization/composer.json +++ b/app/code/Magento/MediaGallerySynchronization/composer.json @@ -6,7 +6,8 @@ "magento/framework": "*", "magento/module-media-gallery-api": "*", "magento/module-media-gallery-synchronization-api": "*", - "magento/framework-message-queue": "*" + "magento/framework-message-queue": "*", + "magento/module-remote-storage": "*" }, "type": "magento2-module", "license": [ diff --git a/app/code/Magento/RemoteStorage/Driver/RemoteDriverInterface.php b/app/code/Magento/RemoteStorage/Driver/RemoteDriverInterface.php index fc108bb388cb5..11044ece9fad8 100644 --- a/app/code/Magento/RemoteStorage/Driver/RemoteDriverInterface.php +++ b/app/code/Magento/RemoteStorage/Driver/RemoteDriverInterface.php @@ -7,12 +7,12 @@ namespace Magento\RemoteStorage\Driver; -use Magento\Framework\Filesystem\ExtendedDriverInterface; +use Magento\Framework\Filesystem\DriverInterface; /** * Remote storage driver. */ -interface RemoteDriverInterface extends ExtendedDriverInterface +interface RemoteDriverInterface extends DriverInterface { /** * Test storage connection. diff --git a/lib/internal/Magento/Framework/File/Mime.php b/lib/internal/Magento/Framework/File/Mime.php index d61f5054990e8..2e8804cf003e5 100644 --- a/lib/internal/Magento/Framework/File/Mime.php +++ b/lib/internal/Magento/Framework/File/Mime.php @@ -15,7 +15,7 @@ * Utility for mime type retrieval * * @deprecated - * @see Filesystem\ExtendedDriverInterface::getMetadata() + * @see Filesystem\DriverInterface::getMetadata() */ class Mime { @@ -113,12 +113,16 @@ public function getMimeType($file) throw new FileSystemException(__("File '$file' doesn't exist")); } - if ($driver instanceof Filesystem\ExtendedDriverInterface) { - return $driver->getMetadata($file)['mimetype']; + $mimeType = ''; + if ($driver instanceof Filesystem\DriverInterface) { + $mimeType = $driver->getMetadata($file)['mimetype'] ?? ''; } - $mime = new Filesystem\Driver\File\Mime(); + if (!$mimeType) { + $mime = new Filesystem\Driver\File\Mime(); + $mimeType = $mime->getMimeType($file); + } - return $mime->getMimeType($file); + return $mimeType; } } diff --git a/lib/internal/Magento/Framework/File/Test/Unit/MimeTest.php b/lib/internal/Magento/Framework/File/Test/Unit/MimeTest.php index db42e03363236..e4d288190d2ad 100644 --- a/lib/internal/Magento/Framework/File/Test/Unit/MimeTest.php +++ b/lib/internal/Magento/Framework/File/Test/Unit/MimeTest.php @@ -56,7 +56,7 @@ class MimeTest extends TestCase protected function setUp(): void { $this->localDriverMock = $this->getMockForAbstractClass(Filesystem\DriverInterface::class); - $this->remoteDriverMock = $this->getMockForAbstractClass(Filesystem\ExtendedDriverInterface::class); + $this->remoteDriverMock = $this->getMockForAbstractClass(Filesystem\DriverInterface::class); $this->localDirectoryMock = $this->getMockForAbstractClass(Filesystem\Directory\WriteInterface::class); $this->localDirectoryMock->method('getDriver') @@ -83,7 +83,8 @@ public function testGetMimeTypeNonexistentFileException(): void ->method('isExists') ->with('nonexistent.file') ->willReturn(true); - + $this->localDriverMock->method('getMetadata') + ->willThrowException(new FileSystemException(__('File \'nonexistent.file\' doesn\'t exist'))); $file = 'nonexistent.file'; $this->object->getMimeType($file); } @@ -103,7 +104,8 @@ public function testGetMimeType($file, $expectedType): void ->method('isExists') ->with($file) ->willReturn(true); - + $this->localDriverMock->method('getMetadata') + ->willReturn(['mimetype' => $expectedType]); $actualType = $this->object->getMimeType($file); self::assertSame($expectedType, $actualType); } diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/File.php b/lib/internal/Magento/Framework/Filesystem/Driver/File.php index 3ed9b24a0316c..b49c4c0ba0c93 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/File.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/File.php @@ -8,6 +8,7 @@ namespace Magento\Framework\Filesystem\Driver; use Magento\Framework\Exception\FileSystemException; +use Magento\Framework\Filesystem\Driver\File\Mime; use Magento\Framework\Filesystem\DriverInterface; use Magento\Framework\Filesystem\Glob; use Magento\Framework\Phrase; @@ -1096,4 +1097,68 @@ public function getRealPathSafety($path) return rtrim(implode(DIRECTORY_SEPARATOR, $realPath), DIRECTORY_SEPARATOR); } + + /** + * Retrieve file metadata. + * + * @param string $path + * + * @return array + * @throws FileSystemException + */ + public function getMetadata(string $path): array + { + if (!$this->isExists($path) || !$this->isFile($path)) { + throw new FileSystemException(__("File '$path' doesn't exist")); + } + + $file = new \SplFileInfo($path); + + $mimeType = $this->getFileMimeType($path); + + if ($this->isFileAnImage($mimeType)) { + $imageInfo = getimagesize($path); + $mimeType = $imageInfo['mime'] ?? $mimeType; + } + + return [ + 'path' => $file->getPath(), + 'dirname' => dirname($file->getPath()), + 'basename' => $file->getBasename(), + 'extension' => $file->getExtension(), + 'filename' => $file->getFilename(), + 'timestamp' => $file->getMTime(), + 'size' => $file->getSize(), + 'mimetype' => $mimeType, + 'extra' => [ + 'image-width' => $imageInfo[0] ?? 0, + 'image-height' => $imageInfo[1] ?? 0 + ] + ]; + } + + /** + * Checks whether file is an image + * + * @param string $mimeType + * + * @return bool + */ + protected function isFileAnImage(string $mimeType): bool + { + return strstr($mimeType, 'image/'); + } + + /** + * Returns file mime type + * + * @param string $path + * + * @return string + * @throws FileSystemException + */ + private function getFileMimeType(string $path): string + { + return Mime::getMimeInstance()->getMimeType($path); + } } diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/File/Mime.php b/lib/internal/Magento/Framework/Filesystem/Driver/File/Mime.php index 4634e3dd1018d..b830c6ca489b1 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/File/Mime.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/File/Mime.php @@ -93,6 +93,11 @@ class Mime 'inode/x-empty', ]; + /** + * @var Mime + */ + private static $instance = null; + /** * Get mime type of a file * @@ -125,6 +130,20 @@ public function getMimeType(string $path): string return $result; } + /** + * Get Mime instance + * + * @return static + */ + public static function getMimeInstance(): Mime + { + if (null === static::$instance) { + static::$instance = new static(); + } + + return static::$instance; + } + /** * Get mime type by the native mime_content_type function. * diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/Http.php b/lib/internal/Magento/Framework/Filesystem/Driver/Http.php index 273425183577e..fc1e4017bc6bf 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/Http.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/Http.php @@ -8,6 +8,7 @@ namespace Magento\Framework\Filesystem\Driver; +use League\Flysystem\AdapterInterface; use Magento\Framework\Exception\FileSystemException; /** @@ -22,6 +23,11 @@ class Http extends File */ protected $scheme = 'http'; + /** + * @var AdapterInterface + */ + private $adapter; + /** * Checks if path exists * @@ -228,6 +234,46 @@ public function getAbsolutePath($basePath, $path, $scheme = null) return $this->getScheme() . $basePath . $path; } + /** + * Retrieve file metadata. + * + * @param string $path + * + * @return array + * @throws FileSystemException + */ + public function getMetadata(string $path): array + { + if (!$this->isExists($path)) { + throw new FileSystemException(__("File '$path' doesn't exist")); + } + + $fileStat = $this->stat($path); + $mimeType = $fileStat['type'] ?? ''; + + $file = new \SplFileInfo($path); + + if ($this->isFileAnImage($mimeType)) { + $imageInfo = getimagesize($this->getScheme() . $path); + $mimeType = $imageInfo['mime'] ?? $mimeType; + } + + return [ + 'path' => $file->getPath(), + 'dirname' => dirname($file->getPath()), + 'basename' => $file->getBasename(), + 'extension' => $file->getExtension(), + 'filename' => $file->getFilename(), + 'timestamp' => isset($fileStat['mtime']) ? strtotime($fileStat['mtime']) : 0, + 'size' => $fileStat['size'] ?? 0, + 'mimetype' => $mimeType, + 'extra' => [ + 'image-width' => $imageInfo[0] ?? 0, + 'image-height' => $imageInfo[1] ?? 0 + ] + ]; + } + /** * Return path with scheme * diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/StatefulFile.php b/lib/internal/Magento/Framework/Filesystem/Driver/StatefulFile.php index 4cccb4e46406d..82c803e746869 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/StatefulFile.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/StatefulFile.php @@ -565,4 +565,17 @@ public function getRealPathSafety($path) { return $this->driverFile->getRealPathSafety($path); } + + /** + * Retrieve file metadata + * + * @param string $path + * + * @return array + * @throws FileSystemException + */ + public function getMetadata(string $path): array + { + return $this->driverFile->getMetadata($path); + } } diff --git a/lib/internal/Magento/Framework/Filesystem/DriverInterface.php b/lib/internal/Magento/Framework/Filesystem/DriverInterface.php index 706077522c675..986f9d24a4123 100644 --- a/lib/internal/Magento/Framework/Filesystem/DriverInterface.php +++ b/lib/internal/Magento/Framework/Filesystem/DriverInterface.php @@ -393,4 +393,31 @@ public function getRealPathSafety($path); * @return mixed */ public function getRelativePath($basePath, $path = null); + + /** + * Retrieve file metadata. + * + * Implementation must return associative array with next keys: + * + * ``` + * [ + * 'path', + * 'dirname', + * 'basename', + * 'extension', + * 'filename', + * 'timestamp', + * 'size', + * 'mimetype', + * 'extra' => [ + * 'image-width', + * 'image-height' + * ] + * ]; + * + * @param string $path Absolute path to file + * @return array + * @throws FileSystemException + */ + public function getMetadata(string $path): array; } diff --git a/lib/internal/Magento/Framework/Filesystem/ExtendedDriverInterface.php b/lib/internal/Magento/Framework/Filesystem/ExtendedDriverInterface.php deleted file mode 100644 index c2643d7c54e79..0000000000000 --- a/lib/internal/Magento/Framework/Filesystem/ExtendedDriverInterface.php +++ /dev/null @@ -1,50 +0,0 @@ - [ - * 'image-width', - * 'image-height' - * ] - * ]; - * - * @param string $path Absolute path to file - * @return array - * @throws FileSystemException - * - * @deprecated Method will be moved to DriverInterface - */ - public function getMetadata(string $path): array; -} diff --git a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/File/MimeTest.php b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/File/MimeTest.php index 4e34d497d86af..c2b83c579230d 100644 --- a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/File/MimeTest.php +++ b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/File/MimeTest.php @@ -51,6 +51,15 @@ public function testGetMimeType(string $file, string $expectedType): void self::assertSame($expectedType, $actualType); } + /** + * Test for getMimeInstance + */ + public function testGetMimeInstance(): void + { + $mime = Mime::getMimeInstance(); + $this->assertInstanceOf(Mime::class, $mime); + } + /** * @return array */ diff --git a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/File/_files/magento.jpg b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/File/_files/magento.jpg new file mode 100644 index 0000000000000..c377daf8fb0b3 Binary files /dev/null and b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/File/_files/magento.jpg differ diff --git a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/FileTest.php b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/FileTest.php index 9c82ce6bbc35b..939da53fb1eb3 100644 --- a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/FileTest.php +++ b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/FileTest.php @@ -7,6 +7,7 @@ namespace Magento\Framework\Filesystem\Test\Unit\Driver; +use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Filesystem\Driver\File; use PHPUnit\Framework\TestCase; @@ -98,6 +99,29 @@ public function testGetRealPathSafety(string $path, string $expected) $this->assertEquals($expected, $file->getRealPathSafety($path)); } + /** + * Test for getMetaData + * + * @dataProvider dataProviderForTestGetMetaData + * @param string $path + * @param array $expected + * @param bool $isFileExist + * @throws FileSystemException + */ + public function testGetMetaData(string $path, array $expected, bool $isFileExist): void + { + $file = new File(); + if ($isFileExist) { + $fileMetadata = $file->getMetadata($path); + $this->assertIsArray($fileMetadata); + $this->assertGetMetadata($expected, $fileMetadata); + } else { + $this->expectException(FileSystemException::class); + $this->expectExceptionMessage('File \'' . $path . '\' doesn\'t exist'); + $file->getMetadata($path); + } + } + /** * Data provider for testGetRealPathSafety; * @@ -122,4 +146,155 @@ public function dataProviderForTestGetRealPathSafety(): array ['/1/2\\3\\\.', '/1/2/3'] ]; } + + /** + * Data provider for testGetMetaData + * + * @return array + */ + public function dataProviderForTestGetMetaData(): array + { + return [ + 'generic mime type' => [ + 'path' => __DIR__ . '/File/_files/blank.html', + 'expected' => [ + 'path' => __DIR__ . '/File/_files', + 'dirname' => __DIR__ . '/File', + 'basename' => 'blank.html', + 'extension' => 'html', + 'filename' => 'blank.html', + 'timestamp' => 1615451439, + 'size' => 108, + 'mimetype' => 'text/html', + 'extra' => [ + 'image-width' => 0, + 'image-height' => 0 + ] + ], + 'is a file exists' => true + ], + 'javascript' => [ + 'path' => __DIR__ . '/File/_files/javascript.js', + 'expected' => [ + 'path' => __DIR__ . '/File/_files', + 'dirname' => __DIR__ . '/File', + 'basename' => 'javascript.js', + 'extension' => 'js', + 'filename' => 'javascript.js', + 'timestamp' => 1615451439, + 'size' => 114, + 'mimetype' => 'application/javascript', + 'extra' => [ + 'image-width' => 0, + 'image-height' => 0 + ] + ], + 'is a file exists' => true + ], + 'tmp image' => [ + 'path' => __DIR__ . '/File/_files/magento', + 'expected' => [ + 'path' => __DIR__ . '/File/_files', + 'dirname' => __DIR__ . '/File', + 'basename' => 'magento', + 'extension' => '', + 'filename' => 'magento', + 'timestamp' => 1609751204, + 'size' => 55303, + 'mimetype' => 'image/jpeg', + 'extra' => [ + 'image-width' => 1154, + 'image-height' => 587 + ] + ], + 'is a file exists' => true + ], + 'image' => [ + 'path' => __DIR__ . '/File/_files/magento.jpg', + 'expected' => [ + 'path' => __DIR__ . '/File/_files', + 'dirname' => __DIR__ . '/File', + 'basename' => 'magento.jpg', + 'extension' => 'jpg', + 'filename' => 'magento.jpg', + 'timestamp' => 1609751204, + 'size' => 55303, + 'mimetype' => 'image/jpeg', + 'extra' => [ + 'image-width' => 1154, + 'image-height' => 587 + ] + ], + 'is a file exists' => true + ], + 'weird extension' => [ + 'path' => __DIR__ . '/File/_files/file.weird', + 'expected' => [ + 'path' => __DIR__ . '/File/_files', + 'dirname' => __DIR__ . '/File', + 'basename' => 'file.weird', + 'extension' => 'weird', + 'filename' => 'file.weird', + 'timestamp' => 1615451439, + 'size' => 5, + 'mimetype' => 'application/octet-stream', + 'extra' => [ + 'image-width' => 0, + 'image-height' => 0 + ] + ], + 'is a file exists' => true + ], + 'weird uppercase extension' => [ + 'path' => __DIR__ . '/File/_files/UPPERCASE.WEIRD', + 'expected' => [ + 'path' => __DIR__ . '/File/_files', + 'dirname' => __DIR__ . '/File', + 'basename' => 'UPPERCASE.WEIRD', + 'extension' => 'WEIRD', + 'filename' => 'UPPERCASE.WEIRD', + 'timestamp' => 1615451439, + 'size' => 5, + 'mimetype' => 'application/octet-stream', + 'extra' => [ + 'image-width' => 0, + 'image-height' => 0 + ] + ], + 'is a file exists' => true + ], + 'non-existent file' => [ + 'path' => __DIR__ . '/File/_files/nonExistentFile.html', + 'expected' => [], + 'is a file exists' => false + ], + 'directory' => [ + 'path' => __DIR__ . '/File/_files/', + 'expected' => [], + 'is a file exists' => false + ] + ]; + } + + /** + * Compares fileMetadata with the expected result. + * We can't use assertEqual to compare arrays because we don't know the values of the file timestamp. + * Timestamp is the time of the last modification of the file. + * + * @param array $expected + * @param array $fileMetadata + * + * @return void + */ + private function assertGetMetadata(array $expected, array $fileMetadata): void + { + foreach ($expected as $key => $item) { + $this->assertArrayHasKey($key, $fileMetadata); + if ($key === 'timestamp') { + $this->assertIsInt($fileMetadata[$key]); + continue; + } + $this->assertEquals($item, $fileMetadata[$key]); + } + } } diff --git a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpTest.php b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpTest.php index c811cc013217f..6f70192813b8c 100644 --- a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpTest.php +++ b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpTest.php @@ -215,4 +215,70 @@ public function testFileOpen(): void self::$fsockopen = $fsockopenResult; $this->assertEquals($fsockopenResult, (new Http())->fileOpen('example.com', 'r')); } + + /** + * Test for getMetaData + * + * @dataProvider dataProviderForTestGetMetaData + * @param string $filePath + * @param array $headers + * @param array $expected + * + * @throws FileSystemException + */ + public function testGetMetadata($filePath, $headers, $expected): void + { + self::$headers = $headers; + $http = new Http(); + if (strpos($headers[0], '200 OK') === false) { + $this->expectException(FileSystemException::class); + $this->expectExceptionMessage('File \'' . $filePath . '\' doesn\'t exist'); + $http->getMetadata($filePath); + } else { + $metadata = $http->getMetadata($filePath); + $this->assertEquals($metadata, $expected); + } + } + + /** + * Data provider for testGetMetaData + * + * @return array + */ + public function dataProviderForTestGetMetaData(): array + { + return [ + 'existing file' => [ + 'file_path' => 'example.com/file/1.pdf', + 'headers' => [ + 0 => 'HTTP/1.0 200 OK', + 'Content-Length' => 128, + 'Content-Type' => 'application/pdf', + 'Last-Modified' => 'Sat, 31 Mar 2021 01:36:20 GMT', + 'Content-Disposition' => 1024, + ], + 'expected' => [ + 'path' => 'example.com/file', + 'dirname' => 'example.com', + 'basename' => '1.pdf', + 'extension' => 'pdf', + 'filename' => '1.pdf', + 'timestamp' => 1617413780, + 'size' => 128, + 'mimetype' => 'application/pdf', + 'extra' => [ + 'image-width' => 0, + 'image-height' => 0 + ] + ] + ], + 'non-existent file' => [ + 'file_path' => 'example.com/file/2.pdf', + 'headers' => [ + 0 => 'HTTP/1.0 404 Not Found' + ], + 'expected' => [] + ] + ]; + } } diff --git a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpsTest.php b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpsTest.php index 5d3ae672d2221..b9c3fe5494605 100644 --- a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpsTest.php +++ b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpsTest.php @@ -22,6 +22,7 @@ protected function setUp(): void public function testFileOpen() { + HttpTest::$fsockopen = self::$fSockOpen; $this->assertEquals(self::$fSockOpen, (new Https())->fileOpen('example.com', 'r')); } }