diff --git a/config/mago-analyze-baseline.toml b/config/mago-analyze-baseline.toml index b07efd4..0f0e247 100644 --- a/config/mago-analyze-baseline.toml +++ b/config/mago-analyze-baseline.toml @@ -36,12 +36,6 @@ code = "mixed-assignment" message = "Assigning `mixed` type to a variable may lead to unexpected behavior." count = 4 -[[issues]] -file = "src/Command/InfoCommand.php" -code = "invalid-array-index" -message = "Invalid index type `int` used for array access on `string('kMGTPE')`." -count = 1 - [[issues]] file = "src/Command/InfoCommand.php" code = "invalid-array-index" @@ -60,12 +54,6 @@ code = "mixed-argument" message = 'Invalid argument type for argument #1 of `Cloudinary\Api\Admin\AssetsTrait::asset`: expected `string`, but found `mixed`.' count = 1 -[[issues]] -file = "src/Command/InfoCommand.php" -code = "possibly-invalid-operand" -message = "Possibly invalid type for right operand." -count = 1 - [[issues]] file = "src/Command/UploadCommand.php" code = "invalid-array-index" diff --git a/config/mago-lint-baseline.toml b/config/mago-lint-baseline.toml index 506cf5a..2f0900c 100644 --- a/config/mago-lint-baseline.toml +++ b/config/mago-lint-baseline.toml @@ -1,13 +1,13 @@ variant = "loose" -[[issues]] -file = "src/Command/InfoCommand.php" -code = "psl-math-functions" -message = "Use the Psl math function instead of the PHP counterpart." -count = 2 - [[issues]] file = "src/Factory/CloudinaryFactory.php" code = "no-isset" message = "Use of the `isset` construct." count = 1 + +[[issues]] +file = "src/Factory/CloudinaryFactory.php" +code = "psl-array-functions" +message = "Use the Psl array function instead of the PHP counterpart." +count = 5 diff --git a/config/mago.toml b/config/mago.toml index b0b5797..eacd3f4 100644 --- a/config/mago.toml +++ b/config/mago.toml @@ -30,9 +30,7 @@ interface-name = { enabled = false } trait-name = { enabled = false } yoda-conditions = { enabled = false } assertion-style = { style = "self" } -psl-array-functions = { enabled = false } psl-datetime = { enabled = false } -psl-string-functions = { enabled = false } [analyzer] plugins = ["psl"] diff --git a/config/phpstan-bootstrap.php b/config/phpstan-bootstrap.php new file mode 100644 index 0000000..ee8616c --- /dev/null +++ b/config/phpstan-bootstrap.php @@ -0,0 +1,36 @@ += 1024 && $unit < Iter\count($units) - 1) { + $size /= 1024; + $unit++; } - $exp = (int) (log($bytes) / log($unit)); - $pre = 'kMGTPE'; - $pre = $pre[$exp - 1]; - - return sprintf('%.1f %sB', $bytes / pow($unit, $exp), $pre); + return $unit === 0 ? $bytes . ' B' : Str\format('%.1f %s', $size, $units[$unit]); } } diff --git a/tests/Command/DisplaySnapshots.php b/tests/Command/DisplaySnapshots.php index a85fc1c..9440bfd 100644 --- a/tests/Command/DisplaySnapshots.php +++ b/tests/Command/DisplaySnapshots.php @@ -5,12 +5,10 @@ namespace Speicher210\CloudinaryBundle\Tests\Command; use PHPUnit\Framework\Assert; +use Psl\Env; +use Psl\File; use Psl\Regex; -use function file_get_contents; -use function file_put_contents; -use function getenv; - trait DisplaySnapshots { /** @@ -22,13 +20,11 @@ private static function assertDisplayMatchesSnapshot(string $snapshot, string $d { $file = __DIR__ . '/Expected/' . $snapshot . '.txt'; - if (getenv('UPDATE_SNAPSHOTS') === '1') { - file_put_contents($file, $display); + if (Env\get_var('UPDATE_SNAPSHOTS') === '1') { + File\write($file, $display, File\WriteMode::Truncate); } - $expected = file_get_contents($file); - Assert::assertIsString($expected, 'Missing snapshot ' . $file); - Assert::assertSame(self::normalizeDisplay($expected), self::normalizeDisplay($display)); + Assert::assertSame(self::normalizeDisplay(File\read($file)), self::normalizeDisplay($display)); } /** diff --git a/tests/Command/Expected/info-verbose.txt b/tests/Command/Expected/info-verbose.txt index 64e38da..e18ed10 100644 --- a/tests/Command/Expected/info-verbose.txt +++ b/tests/Command/Expected/info-verbose.txt @@ -6,12 +6,14 @@ bytes 2048 ----------- -------------- - ---------------------------------------------------------------------------------------------------------------- - Derived resources - ------ -------- -------- ---------------- ---------------------------------------------------------------------- - ID Format Size Transformation URL - ------ -------- -------- ---------------- ---------------------------------------------------------------------- - d1 webp 512 b w_100 https://res.cloudinary.com/demo/image/upload/w_100/folder/image.webp - d2 avif 2.0 kB w_200 https://res.cloudinary.com/demo/image/upload/w_200/folder/image.avif - d3 png 1.5 MB w_2000 https://res.cloudinary.com/demo/image/upload/w_2000/folder/image.png - ------ -------- -------- ---------------- ---------------------------------------------------------------------- + ----------------------------------------------------------------------------------------------------------------- + Derived resources + ------ -------- --------- ---------------- ---------------------------------------------------------------------- + ID Format Size Transformation URL + ------ -------- --------- ---------------- ---------------------------------------------------------------------- + d1 webp 512 B w_100 https://res.cloudinary.com/demo/image/upload/w_100/folder/image.webp + d2 avif 2.0 KiB w_200 https://res.cloudinary.com/demo/image/upload/w_200/folder/image.avif + d3 png 1.5 MiB w_2000 https://res.cloudinary.com/demo/image/upload/w_2000/folder/image.png + d4 gif 1.0 KiB w_10 https://res.cloudinary.com/demo/image/upload/w_10/folder/image.gif + d5 jpg 1.0 MiB w_1500 https://res.cloudinary.com/demo/image/upload/w_1500/folder/image.jpg + ------ -------- --------- ---------------- ---------------------------------------------------------------------- diff --git a/tests/Command/InfoCommandTest.php b/tests/Command/InfoCommandTest.php index 6d27d86..58ba9f5 100644 --- a/tests/Command/InfoCommandTest.php +++ b/tests/Command/InfoCommandTest.php @@ -71,6 +71,20 @@ private function adminReturningTheAsset(): Admin 'transformation' => 'w_2000', 'url' => 'https://res.cloudinary.com/demo/image/upload/w_2000/folder/image.png', ], + [ + 'id' => 'd4', + 'format' => 'gif', + 'bytes' => 1024, + 'transformation' => 'w_10', + 'url' => 'https://res.cloudinary.com/demo/image/upload/w_10/folder/image.gif', + ], + [ + 'id' => 'd5', + 'format' => 'jpg', + 'bytes' => 1_048_575, + 'transformation' => 'w_1500', + 'url' => 'https://res.cloudinary.com/demo/image/upload/w_1500/folder/image.jpg', + ], ], ], [], diff --git a/tests/Command/UploadCommandTest.php b/tests/Command/UploadCommandTest.php index 65c84ed..d99388f 100644 --- a/tests/Command/UploadCommandTest.php +++ b/tests/Command/UploadCommandTest.php @@ -9,20 +9,16 @@ use Override; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; +use Psl\Env; +use Psl\Filesystem; +use Psl\SecureRandom; use Psl\Type; +use Psl\Vec; use Speicher210\CloudinaryBundle\Cloudinary\Uploader; use Speicher210\CloudinaryBundle\Command\UploadCommand; use Symfony\Component\Console\Tester\CommandTester; -use function mkdir; use function preg_quote; -use function realpath; -use function rmdir; -use function sort; -use function sys_get_temp_dir; -use function touch; -use function uniqid; -use function unlink; /** * The table shows absolute paths, so its column widths depend on where the tests run: the display is not compared with @@ -33,29 +29,26 @@ final class UploadCommandTest extends TestCase { private const array FILE_NAMES = ['document.pdf', 'logo.png', 'photo.jpg']; + /** @var non-empty-string */ private string $directory; #[Override] protected function setUp(): void { - $directory = sys_get_temp_dir() . '/' . uniqid('cloudinary-bundle-upload-', true); - mkdir($directory); + $directory = Env\temp_dir() . '/cloudinary-bundle-upload-' . SecureRandom\string(16); + Filesystem\create_directory($directory); foreach (self::FILE_NAMES as $fileName) { - touch($directory . '/' . $fileName); + Filesystem\create_file($directory . '/' . $fileName); } // The command shows real paths, and the temporary directory may be behind a symbolic link. - $this->directory = Type\string()->assert(realpath($directory)); + $this->directory = Type\non_empty_string()->coerce(Filesystem\canonicalize($directory)); } #[Override] protected function tearDown(): void { - foreach (self::FILE_NAMES as $fileName) { - unlink($this->directory . '/' . $fileName); - } - - rmdir($this->directory); + Filesystem\delete_directory($this->directory, recursive: true); } public function testUploadsEveryFileWithThePrefixedFileNameAsPublicId(): void @@ -78,14 +71,13 @@ static function (mixed $file, array $options) use (&$uploads): ApiResponse { $commandTester->assertCommandIsSuccessful(); - sort($uploads); self::assertSame( [ [$this->directory . '/document.pdf', ['public_id' => 'uploads/document']], [$this->directory . '/logo.png', ['public_id' => 'uploads/logo']], [$this->directory . '/photo.jpg', ['public_id' => 'uploads/photo']], ], - $uploads, + Vec\sort($uploads), ); $display = $commandTester->getDisplay();