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,170 changes: 0 additions & 1,170 deletions phpstan-baseline.neon

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,15 @@
*/
final class ConstraintViolationAdapter implements ValidationErrorInterface
{
/** @var \Symfony\Component\Validator\ConstraintViolationInterface */
private $violation;
private ConstraintViolationInterface $violation;

/**
* Element on which the error occurred
* e.g. property name or property path compatible with Symfony PropertyAccess component.
*
* Example: StringLengthValidator[minStringLength]
*
* @var string
*/
private $target;
private string $target;

public function __construct(ConstraintViolationInterface $violation)
{
Expand All @@ -48,7 +45,7 @@ public function getTranslatableMessage(): Translation
);
}

public function setTarget($target): void
public function setTarget(string $target): void
{
$this->target = $target;
}
Expand Down
10 changes: 3 additions & 7 deletions src/contracts/FieldType/ValidationError.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,13 @@ interface ValidationError extends Translatable
* Can be a property path compatible with Symfony PropertyAccess component.
*
* Examples:
* - "[StringLengthValidator][minStringLength]" => Target is "minStringLength" key under "StringLengthValidator" key (fieldtype validator configuration)
* - "[StringLengthValidator][minStringLength]" => Target is the "minStringLength" key under "StringLengthValidator" key (field type validator configuration)
* - "my_field_definition_identifier"
*
* @param string $target
*/
public function setTarget($target);
public function setTarget(string $target): void;

/**
* Returns the target element on which the error occurred.
*
* @return string
*/
public function getTarget();
public function getTarget(): ?string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,24 @@
*/
abstract class AbstractValidationError implements ValidationError
{
/** @var string */
protected $message;
protected string $message;

/** @var array */
protected $parameters;
/** @var array<string, scalar> */
protected array $parameters;

/**
* Element on which the error occurred
* e.g. property name or property path compatible with Symfony PropertyAccess component.
* e.g., property name or property path compatible with Symfony PropertyAccess component.
*
* Example: StringLengthValidator[minStringLength]
*
* @var string
*/
protected $target;
protected string $target;

/**
* @param array<string, scalar> $parameters
*/
public function __construct(string $message, array $parameters, string $target)
{
$this->message = $message;
Expand All @@ -45,7 +47,7 @@ public function getTranslatableMessage(): Translation
return new Message($this->message, $this->parameters);
}

public function setTarget($target): void
public function setTarget(string $target): void
{
$this->target = $target;
}
Expand Down
9 changes: 5 additions & 4 deletions src/contracts/Repository/Translatable.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@
* @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\Contracts\Core\Repository;

use Ibexa\Contracts\Core\Repository\Values\Translation;

/**
* Interface implemented by everything which should be translatable. This
* should for example be implemented by any exception, which might bubble up to
* should, for example, be implemented by any exception, which might bubble up to
* a user, or validation errors.
*/
interface Translatable
{
/**
* Returns a translatable Message.
*
* @return \Ibexa\Contracts\Core\Repository\Values\Translation
*/
public function getTranslatableMessage();
public function getTranslatableMessage(): Translation;
}
2 changes: 1 addition & 1 deletion src/contracts/Repository/Values/Filter/Filter.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public function __construct(?FilteringCriterion $criterion = null, array $sortCl
sprintf(
'Expected an instance of "%s", got "%s" at position %d',
FilteringSortClause::class,
is_object($sortClause) ? get_class($sortClause) : gettype($sortClause),
get_debug_type($sortClause),
$idx
)
);
Expand Down
12 changes: 7 additions & 5 deletions src/contracts/Repository/Values/Translation/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,24 @@ class Message extends Translation
{
/**
* Message string. Might use replacements like %foo%, which are replaced by
* the values specified in the values array.
* the values specified in the `$values` array.
*/
protected string $message;

/**
* Translation value objects. May not contain any numbers, which might
* result in requiring plural forms. Use Plural for that.
* result in requiring plural forms. Use `Plural` class for that.
*
* @var array<string, scalar>
* @see \Ibexa\Contracts\Core\Repository\Values\Translation\Plural
*
* @var array<string, scalar|null>
*/
protected array $values;

/**
* Construct singular only message from string and optional value array.
* Construct a singular only message from string and optional value array.
*
* @param array<string, scalar> $values
* @param array<string, scalar|null> $values
*/
public function __construct(string $message, array $values = [])
{
Expand Down
24 changes: 12 additions & 12 deletions src/contracts/Repository/Values/Translation/Plural.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,44 +20,44 @@
* strings provided should be English and will be translated depending on the
* environment language.
*
* This interface follows the interfaces of XLIFF, gettext, Symfony Translations and Zend_Translate.
* For singular forms you just provide a plain string (with optional placeholders without effects on the plural forms).
* For potential plural forms you always provide a singular variant and an English simple plural variant.
* An instance of this class can be cast to a string. In such case whether to use singular or plural form is determined
* based on the value of first element of $values array (it needs to be 1 for singular, anything else for plural).
* If plurality cannot be inferred from $values, a plural form is assumed as default. To force singular form,
* This interface follows the interfaces of XLIFF, gettext, Symfony Translations, and Zend_Translate.
* For singular forms, you provide a plain string (with optional placeholders without effects on the plural forms).
* For potential plural forms, you always provide a singular variant and an English simple plural variant.
* An instance of this class can be cast to a string. In such a case, whether to use singular or plural form is determined
* based on the value of the first element of $values array (it needs to be 1 for singular, anything else for plural).
* If a plurality cannot be inferred from $values, a plural form is assumed as default. To force singular form,
* use {@see \Ibexa\Contracts\Core\Repository\Values\Translation\Message} instead.
*
* No implementation supports multiple different plural forms in one single message.
*
* The singular / plural string could, for Symfony, for example be converted
* to <code>"$singular|$plural"</code>, and you would call gettext like: <code>ngettext($singular, $plural, $count ).</code>
* The singular / plural string could, for Symfony, for example, be converted
* to ```"$singular|$plural"```, and you would call gettext like: ```ngettext($singular, $plural, $count ).```
*/
class Plural extends Translation
{
/**
* Singular string. Might use replacements like %foo%, which are replaced by
* the values specified in the values array.
* the values specified in the `$values` array.
*/
protected string $singular;

/**
* Message string. Might use replacements like %foo%, which are replaced by
* the values specified in the values array.
* the values specified in the `$values` array.
*/
protected string $plural;

/**
* Translation value objects.
*
* @var array<string, scalar>
* @var array<string, scalar|null>
*/
protected array $values;

/**
* Construct plural message from singular, plural and value array.
*
* @param array<string, scalar> $values
* @param array<string, scalar|null> $values
*/
public function __construct(string $singular, string $plural, array $values)
{
Expand Down
12 changes: 6 additions & 6 deletions src/lib/Base/Exceptions/BadStateException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* @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\Core\Base\Exceptions;

Expand All @@ -15,20 +16,19 @@
/**
* BadState Exception implementation.
*
* Usage: throw new BadState( 'nodes', 'array' );
* Usage:
* ```
* throw new BadStateException('nodes', 'array');
* ```
*/
class BadStateException extends APIBadStateException implements Translatable
{
use TranslatableBase;

/**
* Generates: "Argument '{$argumentName}' has a bad state: {$whatIsWrong}".
*
* @param string $argumentName
* @param string $whatIsWrong
* @param \Exception|null $previous
*/
public function __construct($argumentName, $whatIsWrong, Exception $previous = null)
public function __construct(string $argumentName, string $whatIsWrong, ?Exception $previous = null)
{
$this->setMessageTemplate("Argument '%argumentName%' has a bad state: %whatIsWrong%");
$this->setParameters(['%argumentName%' => $argumentName, '%whatIsWrong%' => $whatIsWrong]);
Expand Down
40 changes: 22 additions & 18 deletions src/lib/Base/Exceptions/ContentFieldValidationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
* @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\Core\Base\Exceptions;

use Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException as APIContentFieldValidationException;
use Ibexa\Contracts\Core\Repository\Values\Translation;
use Ibexa\Core\Base\Translatable;
use Ibexa\Core\Base\TranslatableBase;
use Ibexa\Core\FieldType\ValidationError;

/**
* This Exception is thrown on create or update content one or more given fields are not valid.
Expand All @@ -18,23 +21,22 @@ class ContentFieldValidationException extends APIContentFieldValidationException
{
use TranslatableBase;

private const MAX_MESSAGES_NUMBER = 32;
private const int MAX_MESSAGES_NUMBER = 32;

/**
* Contains an array of field ValidationError objects indexed with FieldDefinition id and language code.
*
* Example:
* <code>
* ```
* $fieldErrors = $exception->getFieldErrors();
* $fieldErrors[43]["eng-GB"]->getTranslatableMessage();
* </code>
* $fieldErrors[43]["eng-GB"][0]->getTranslatableMessage();
* ```
*
* @var array<int, array<string, \Ibexa\Contracts\Core\FieldType\ValidationError[]>>
*/
protected $errors;
protected array $errors;

/** @var string|null */
protected $contentName;
protected ?string $contentName;

/**
* Generates: Content fields did not validate.
Expand Down Expand Up @@ -63,7 +65,7 @@ public static function createNewWithMultiline(array $errors, ?string $contentNam
$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 All @@ -83,18 +85,20 @@ public function getFieldErrors(): array
private function generateValidationErrorsMessages(): string
{
$validationErrors = $this->collectValidationErrors();
$maxMessagesNumber = self::MAX_MESSAGES_NUMBER;

if (count($validationErrors) > $maxMessagesNumber) {
array_splice($validationErrors, $maxMessagesNumber);
$validationErrors[] = sprintf('Limit: %d of validation errors has been exceeded.', $maxMessagesNumber);
if (count($validationErrors) > self::MAX_MESSAGES_NUMBER) {
array_splice($validationErrors, self::MAX_MESSAGES_NUMBER);
$validationErrors[] = new Translation\Message(
'Limit of %max_message_number% validation errors has been exceeded.',
[
'%max_message_number%' => self::MAX_MESSAGES_NUMBER,
]
);
}

/** @var callable(string|\Ibexa\Contracts\Core\Repository\Values\Translation): string $convertToString */
$convertToString = static function ($error): string {
return (string)$error;
};
$validationErrors = array_map($convertToString, $validationErrors);
$validationErrors = array_map(
static fn (Translation $error): string => (string)$error,
$validationErrors
);

return "\n- " . implode("\n- ", $validationErrors);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* @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\Core\Base\Exceptions;

Expand Down Expand Up @@ -33,6 +34,9 @@ public function __construct(array $errors)
parent::__construct($this->getBaseTranslation());
}

/**
* @return array<string, \Ibexa\Contracts\Core\FieldType\ValidationError[]>
*/
public function getFieldErrors(): array
{
return $this->errors;
Expand Down
9 changes: 5 additions & 4 deletions src/lib/Base/Exceptions/ContentTypeValidationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* @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\Core\Base\Exceptions;

Expand All @@ -13,7 +14,7 @@
use JMS\TranslationBundle\Annotation\Ignore;

/**
* This Exception is thrown on create or update content type when content type is not valid.
* This Exception is thrown during content type creation or update when validation fails.
*/
class ContentTypeValidationException extends APIContentTypeValidationException implements Translatable
{
Expand All @@ -22,10 +23,10 @@ class ContentTypeValidationException extends APIContentTypeValidationException i
/**
* @param string $messageTemplate The message template, with placeholders for parameters.
* E.g. "Content with ID %contentId% could not be found".
* @param array $parameters Hash map with param placeholder as key and its corresponding value.
* E.g. array('%contentId%' => 123).
* @param array<string, mixed> $parameters Hash map with param placeholder as a key and its corresponding value.
* E.g., ['%contentId%' => 123].
*/
public function __construct($messageTemplate, array $parameters = [])
public function __construct(string $messageTemplate, array $parameters = [])
{
$this->setMessageTemplate(/** @Ignore */$messageTemplate);
$this->setParameters($parameters);
Expand Down
Loading
Loading