Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Injected previous exception into field validation exception #393

Closed
Closed
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
12 changes: 7 additions & 5 deletions src/contracts/Repository/ContentService.php
Original file line number Diff line number Diff line change
Expand Up @@ -340,11 +340,6 @@ public function updateContent(VersionInfo $versionInfo, ContentUpdateStruct $con
* Publishes a content version and deletes archive versions if they overflow max archive versions.
* Max archive versions are currently a configuration for default max limit, by default set to 5.
*
* @todo Introduce null|int ContentType->versionArchiveLimit to be able to let admins override this per type.
*
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to publish this version
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the version is not a draft
*
* @param \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo $versionInfo
* @param string[] $translations List of language codes of translations which will be included
* in a published version.
Expand All @@ -354,6 +349,13 @@ public function updateContent(VersionInfo $versionInfo, ContentUpdateStruct $con
* overriding those in the current version.
*
* @return \Ibexa\Contracts\Core\Repository\Values\Content\Content
*
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to publish this version
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the version is not a draft
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentValidationException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException
*/
public function publishVersion(VersionInfo $versionInfo, array $translations = Language::ALL): Content;

Expand Down
11 changes: 6 additions & 5 deletions src/lib/Base/Exceptions/ContentFieldValidationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException as APIContentFieldValidationException;
use Ibexa\Core\Base\Translatable;
use Ibexa\Core\Base\TranslatableBase;
use Throwable;

/**
* This Exception is thrown on create or update content one or more given fields are not valid.
Expand Down Expand Up @@ -42,27 +43,27 @@ class ContentFieldValidationException extends APIContentFieldValidationException
*
* @param array<int, array<string, \Ibexa\Contracts\Core\FieldType\ValidationError|\Ibexa\Contracts\Core\FieldType\ValidationError[]>> $errors
*/
public function __construct(array $errors)
public function __construct(array $errors, ?Throwable $previous = null)
{
$this->errors = $errors;
$this->setMessageTemplate('Content fields did not validate');
parent::__construct($this->getBaseTranslation());
parent::__construct($this->getBaseTranslation(), 0, $previous);
}

/**
* Generates: Content fields did not validate exception with additional information on affected fields.
*
* @param array<int, array<string, \Ibexa\Contracts\Core\FieldType\ValidationError|\Ibexa\Contracts\Core\FieldType\ValidationError[]>> $errors
*/
public static function createNewWithMultiline(array $errors, ?string $contentName = null): self
public static function createNewWithMultiline(array $errors, ?string $contentName = null, ?Throwable $previous = null): self
{
$exception = new self($errors);
$exception = new self($errors, $previous);
$exception->contentName = $contentName;

$exception->setMessageTemplate('Content "%contentName%" fields did not validate: %errors%');
$exception->setParameters([
'%errors%' => $exception->generateValidationErrorsMessages(),
'%contentName%' => $exception->contentName !== null ? $exception->contentName : '',
'%contentName%' => $exception->contentName ?? '',
]);
$exception->message = $exception->getBaseTranslation();

Expand Down
23 changes: 5 additions & 18 deletions src/lib/Repository/ContentService.php
Original file line number Diff line number Diff line change
Expand Up @@ -1449,22 +1449,6 @@ protected function internalUpdateContent(
);
}

/**
* Publishes a content version.
*
* Publishes a content version and deletes archive versions if they overflow max archive versions.
* Max archive versions are currently a configuration, but might be moved to be a param of ContentType in the future.
*
* @param \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo $versionInfo
* @param string[] $translations
*
* @return \Ibexa\Contracts\Core\Repository\Values\Content\Content
*
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the version is not a draft
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
*/
public function publishVersion(APIVersionInfo $versionInfo, array $translations = Language::ALL): APIContent
{
$content = $this->internalLoadContentById(
Expand Down Expand Up @@ -1721,13 +1705,16 @@ protected function fieldValuesAreEqual(FieldType $fieldType, Value $value1, Valu
* Publishes a content version and deletes archive versions if they overflow max archive versions.
* Max archive versions are currently a configuration, but might be moved to be a param of ContentType in the future.
*
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the version is not a draft
*
* @param \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo $versionInfo
* @param int|null $publicationDate If null existing date is kept if there is one, otherwise current time is used.
* @param string[] $translations
*
* @return \Ibexa\Contracts\Core\Repository\Values\Content\Content
*
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the version is not a draft
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException
*/
protected function internalPublishVersion(APIVersionInfo $versionInfo, $publicationDate = null, array $translations = Language::ALL)
{
Expand Down
72 changes: 72 additions & 0 deletions tests/lib/Base/Exception/ContentFieldValidationExceptionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Tests\Core\Base\Exception;

use Ibexa\Core\Base\Exceptions\ContentFieldValidationException;
use Ibexa\Core\FieldType\ValidationError;
use PHPUnit\Framework\TestCase;

/**
* @covers \Ibexa\Core\Base\Exceptions\ContentFieldValidationException
*/
final class ContentFieldValidationExceptionTest extends TestCase
{
public function testGetFieldErrors(): ContentFieldValidationException
{
$errors = [
123 => [
'eng-GB' => [
new ValidationError('error 1'), new ValidationError('error 2'),
],
'pol-PL' => [
new ValidationError('error 1'), new ValidationError('error 2'),
],
],
456 => [
'pol-PL' => [
new ValidationError('error 3'), new ValidationError('error 4'),
],
'eng-GB' => [
new ValidationError('error 3'), new ValidationError('error 4'),
],
],
];

$exception = new ContentFieldValidationException($errors);

self::assertSame($errors, $exception->getFieldErrors());

return $exception;
}

/**
* @depends testGetFieldErrors
*/
public function testCreateNewWithMultiline(ContentFieldValidationException $exception): void
{
$newException = ContentFieldValidationException::createNewWithMultiline(
$exception->getFieldErrors(),
'My Content'
);

$expectedExceptionMessage = <<<MSG
Content "My Content" fields did not validate:
- error 1
- error 2
- error 1
- error 2
- error 3
- error 4
- error 3
- error 4
MSG;

self::assertSame($expectedExceptionMessage, $newException->getMessage());
}
}
Loading