Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Latest
------

### Changes
* [#45](https://github.com/cleverage/archive-process-bundle/issues/45) The bundle throws exceptions implementing `ProcessExceptionInterface` of the process bundle instead of raw SPL exceptions (as [cleverage/process-bundle#317](https://github.com/cleverage/process-bundle/issues/317)): new `Exception\UnexpectedValueException` and `Exception\RuntimeException`, extending the SPL exceptions thrown before (same messages, the existing `catch` keep working). Add tests.
* [#43](https://github.com/cleverage/archive-process-bundle/issues/43) Composer: require PHP `^8.2` instead of `>=8.2` (PHP 9 is no longer accepted before being tested), remove the authorization of the `symfony/flex` plugin, which is not required (the CI installs it globally), as [cleverage/process-bundle#319](https://github.com/cleverage/process-bundle/issues/319).
* [#38](https://github.com/cleverage/archive-process-bundle/issues/38) Define the public API (Symfony BC promise, as [cleverage/process-bundle#279](https://github.com/cleverage/process-bundle/issues/279)): `ZipTask`, `UnzipTask` and `CleverAgeArchiveProcessBundle` are marked `@final since 2.3`, they will be `final` in 3.0: extending them triggers a deprecation with the Symfony `DebugClassLoader`. `CleverAgeArchiveProcessExtension` is marked `@internal`.
* [#37](https://github.com/cleverage/archive-process-bundle/issues/37) `CleverAgeArchiveProcessExtension::findServices()` loads the service definition files with a glob pattern instead of a `Finder` (same files, as [cleverage/process-bundle#271](https://github.com/cleverage/process-bundle/issues/271)), `symfony/finder` is no longer required. Add tests.
Expand Down
23 changes: 23 additions & 0 deletions src/Exception/RuntimeException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

/*
* This file is part of the CleverAge/ArchiveProcessBundle package.
*
* Copyright (c) Clever-Age
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace CleverAge\ArchiveProcessBundle\Exception;

use CleverAge\ProcessBundle\Exception\ProcessExceptionInterface;

/**
* Thrown by the bundle, can be caught with the ProcessExceptionInterface of the process bundle.
*/
class RuntimeException extends \RuntimeException implements ProcessExceptionInterface
{
}
23 changes: 23 additions & 0 deletions src/Exception/UnexpectedValueException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

/*
* This file is part of the CleverAge/ArchiveProcessBundle package.
*
* Copyright (c) Clever-Age
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace CleverAge\ArchiveProcessBundle\Exception;

use CleverAge\ProcessBundle\Exception\ProcessExceptionInterface;

/**
* Thrown by the bundle, can be caught with the ProcessExceptionInterface of the process bundle.
*/
class UnexpectedValueException extends \UnexpectedValueException implements ProcessExceptionInterface
{
}
12 changes: 7 additions & 5 deletions src/Task/UnzipTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace CleverAge\ArchiveProcessBundle\Task;

use CleverAge\ArchiveProcessBundle\Exception\RuntimeException;
use CleverAge\ArchiveProcessBundle\Exception\UnexpectedValueException;
use CleverAge\ProcessBundle\Model\AbstractConfigurableTask;
use CleverAge\ProcessBundle\Model\ProcessState;
use Symfony\Component\OptionsResolver\OptionsResolver;
Expand All @@ -30,7 +32,7 @@ public function execute(ProcessState $state): void
$state->setInput([]);
}
if (!\is_array($state->getInput())) {
throw new \UnexpectedValueException(\sprintf('UnzipTask expects an array or null input, %s given', get_debug_type($state->getInput())));
throw new UnexpectedValueException(\sprintf('UnzipTask expects an array or null input, %s given', get_debug_type($state->getInput())));
}
/**
* @var array{filename: string, destination: string} $options
Expand All @@ -39,19 +41,19 @@ public function execute(ProcessState $state): void
$filename = $options['filename'];

if (!file_exists($filename)) {
throw new \UnexpectedValueException("File does not exists: '{$filename}'");
throw new UnexpectedValueException("File does not exists: '{$filename}'");
}

if (!is_readable($filename)) {
throw new \UnexpectedValueException("File is not readable: '{$filename}'");
throw new UnexpectedValueException("File is not readable: '{$filename}'");
}

$dest = $options['destination'];

$zipArchive = new \ZipArchive();
$res = $zipArchive->open($filename);
if (true !== $res) {
throw new \RuntimeException("Unable to open file {$filename} with code {$res}");
throw new RuntimeException("Unable to open file {$filename} with code {$res}");
}

// The PHP warning is replaced by the exception below
Expand All @@ -60,7 +62,7 @@ public function execute(ProcessState $state): void
$error = error_get_last()['message'] ?? $zipArchive->getStatusString();
$zipArchive->close();
if (!$extracted) {
throw new \RuntimeException("Unable to extract file {$filename} to {$dest}: {$error}");
throw new RuntimeException("Unable to extract file {$filename} to {$dest}: {$error}");
}

$state->setOutput($dest);
Expand Down
14 changes: 8 additions & 6 deletions src/Task/ZipTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace CleverAge\ArchiveProcessBundle\Task;

use CleverAge\ArchiveProcessBundle\Exception\RuntimeException;
use CleverAge\ArchiveProcessBundle\Exception\UnexpectedValueException;
use CleverAge\ProcessBundle\Model\AbstractConfigurableTask;
use CleverAge\ProcessBundle\Model\ProcessState;
use Symfony\Component\OptionsResolver\OptionsResolver;
Expand All @@ -30,7 +32,7 @@ public function execute(ProcessState $state): void
$state->setInput([]);
}
if (!\is_array($state->getInput())) {
throw new \UnexpectedValueException(\sprintf('ZipTask expects an array or null input, %s given', get_debug_type($state->getInput())));
throw new UnexpectedValueException(\sprintf('ZipTask expects an array or null input, %s given', get_debug_type($state->getInput())));
}
/**
* @var array{filename: string, files: array<string>|string, files_base_path: string} $options
Expand All @@ -40,7 +42,7 @@ public function execute(ProcessState $state): void
$zip = new \ZipArchive();
$ret = $zip->open($options['filename'], \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
if (true !== $ret) {
throw new \RuntimeException("Fail to open file {$options['filename']} with code {$ret}");
throw new RuntimeException("Fail to open file {$options['filename']} with code {$ret}");
}

$files = $options['files'];
Expand All @@ -62,19 +64,19 @@ public function execute(ProcessState $state): void
$currentFilepath = $basePath.\DIRECTORY_SEPARATOR.$currentFilename;
}
if (!file_exists($currentFilepath)) {
throw new \UnexpectedValueException("File does not exists: '{$currentFilepath}'");
throw new UnexpectedValueException("File does not exists: '{$currentFilepath}'");
}
if (!is_readable($currentFilepath)) {
throw new \UnexpectedValueException("File is not readable: '{$currentFilepath}'");
throw new UnexpectedValueException("File is not readable: '{$currentFilepath}'");
}
if (false === $zip->addFile($currentFilepath, $currentFilename)) {
throw new \RuntimeException("Unable to add file {$currentFilepath} to zip");
throw new RuntimeException("Unable to add file {$currentFilepath} to zip");
}
}

// The archive is written on close: the PHP warning is replaced by the exception below
if (!@$zip->close()) {
throw new \RuntimeException("Unable to write zip file {$options['filename']}: {$zip->getStatusString()}");
throw new RuntimeException("Unable to write zip file {$options['filename']}: {$zip->getStatusString()}");
}

$state->setOutput($options['filename']);
Expand Down
53 changes: 53 additions & 0 deletions tests/Exception/SplExceptionsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

/*
* This file is part of the CleverAge/ArchiveProcessBundle package.
*
* Copyright (c) Clever-Age
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace CleverAge\ArchiveProcessBundle\Tests\Exception;

use CleverAge\ArchiveProcessBundle\Exception\RuntimeException;
use CleverAge\ArchiveProcessBundle\Exception\UnexpectedValueException;
use CleverAge\ProcessBundle\Exception\ProcessExceptionInterface;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

/**
* The exceptions thrown by the bundle can be caught as ProcessExceptionInterface, and still as the SPL exceptions they
* were before.
*/
#[CoversClass(UnexpectedValueException::class)]
#[CoversClass(RuntimeException::class)]
class SplExceptionsTest extends TestCase
{
/**
* @return iterable<string, array{class-string<\Throwable>, class-string<\Throwable>}>
*/
public static function provideExceptions(): iterable
{
yield 'UnexpectedValueException' => [UnexpectedValueException::class, \UnexpectedValueException::class];
yield 'RuntimeException' => [RuntimeException::class, \RuntimeException::class];
}

/**
* @param class-string<\Throwable> $class
* @param class-string<\Throwable> $splClass
*/
#[DataProvider('provideExceptions')]
public function testExtendsTheSplExceptionAndImplementsTheInterface(string $class, string $splClass): void
{
$exception = new $class('message', 12);

self::assertInstanceOf($splClass, $exception);
self::assertInstanceOf(ProcessExceptionInterface::class, $exception);
self::assertSame(['message', 12], [$exception->getMessage(), $exception->getCode()]);
}
}
Loading