Skip to content

Commit

Permalink
Merge pull request #41 from systopia/translate-validation-errors
Browse files Browse the repository at this point in the history
Translate JSON schema validation errors
  • Loading branch information
dontub authored Nov 6, 2023
2 parents bfbc1d2 + e1147ce commit bf12a3e
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 23 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"require": {
"php": "^7.4 || ^8",
"systopia/expression-language-ext": "~0.1",
"systopia/opis-json-schema-ext": "~0.1"
"systopia/opis-json-schema-ext": "~0.2"
},
"require-dev": {
"drupal/core": "^9.1.6",
Expand Down
2 changes: 1 addition & 1 deletion json_forms.info.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ name: JSONForms
type: module
description: Create a Drupal form from a JSONForms definition.
package: JSONForms
core_version_requirement: ^9.1.6 || ^10
core_version_requirement: ^9.5 || ^10
php: 7.4
hidden: true
16 changes: 12 additions & 4 deletions json_forms.services.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
# We cannot use things like autowiring or "!tagged_iterator":
# https://www.drupal.org/project/drupal/issues/3111008

services:
_defaults:
autowire: true
public: false # Controller classes and services directly fetched from container need to be public

Drupal\json_forms\Form\FormArrayFactoryInterface:
class: Drupal\json_forms\Form\FormArrayFactory
public: true

Drupal\json_forms\Form\Validation\FormValidationMapperInterface:
class: Drupal\json_forms\Form\Validation\FormValidationMapper
public: true

Systopia\JsonSchema\Translation\TranslatorInterface:
class: Drupal\json_forms\Form\Validation\Translation\DrupalJsonSchemaValidationTranslator
arguments:
- '@language_manager'

Opis\JsonSchema\Validator:
class: Opis\JsonSchema\Validator
factory: [Drupal\json_forms\Form\Validation\OpisValidatorFactory, getValidator]

Drupal\json_forms\Form\Validation\FormValidatorInterface:
class: Drupal\json_forms\Form\Validation\FormValidator
arguments: ['@Opis\JsonSchema\Validator']
public: true

Drupal\json_forms\Form\Control\Rule\StatesArrayFactoryInterface:
class: Drupal\json_forms\Form\Control\Rule\StatesArrayFactory
2 changes: 1 addition & 1 deletion modules/json_forms_example/json_forms_example.info.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: JSONForms example
type: module
description: Demonstrates how to use JSONForms.
package: JSONForms
core_version_requirement: ^9.1.6 || ^10
core_version_requirement: ^9.5 || ^10
php: 7.4
dependencies:
- json_forms:json_forms
8 changes: 6 additions & 2 deletions src/Form/Validation/FormValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@
use Drupal\json_forms\Form\Util\JsonConverter;
use Opis\JsonSchema\Validator as OpisValidator;
use Systopia\JsonSchema\Errors\ErrorCollector;
use Systopia\JsonSchema\Translation\TranslatorInterface;

final class FormValidator implements FormValidatorInterface {

private TranslatorInterface $translator;

private OpisValidator $validator;

public function __construct(OpisValidator $validator) {
public function __construct(TranslatorInterface $translator, OpisValidator $validator) {
$this->translator = $translator;
$this->validator = $validator;
}

Expand All @@ -40,7 +44,7 @@ public function validate(\stdClass $jsonSchema, array $data): ValidationResult {
$errorCollector = new ErrorCollector();
$this->validator->validate($data, $jsonSchema, ['errorCollector' => $errorCollector]);

return new ValidationResult(JsonConverter::toArray($data), $errorCollector);
return new ValidationResult(JsonConverter::toArray($data), $errorCollector, $this->translator);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

/*
* Copyright (C) 2023 SYSTOPIA GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

declare(strict_types=1);

namespace Drupal\json_forms\Form\Validation\Translation;

use Drupal\Core\Language\LanguageManagerInterface;
use Opis\JsonSchema\Errors\ValidationError;
use Systopia\JsonSchema\Translation\TranslatorFactory;
use Systopia\JsonSchema\Translation\TranslatorInterface;

/**
* @codeCoverageIgnore
*/
final class DrupalJsonSchemaValidationTranslator implements TranslatorInterface {

private LanguageManagerInterface $languageManager;

private string $lastLanguageId = '';


/**
* @phpstan-ignore-next-line Not initialized in constructor.
*/
private TranslatorInterface $translator;

public function __construct(LanguageManagerInterface $languageManager) {
$this->languageManager = $languageManager;
}

/**
* {@inheritDoc}
*/
public function trans(string $id, array $parameters, ValidationError $error): string {
return $this->getTranslator()->trans($id, $parameters, $error);
}

private function getTranslator(): TranslatorInterface {
if ($this->languageManager->getCurrentLanguage()->getId() !== $this->lastLanguageId) {
$this->lastLanguageId = $this->languageManager->getCurrentLanguage()->getId();
$this->translator = TranslatorFactory::createTranslator($this->lastLanguageId);
}

return $this->translator;
}

}
25 changes: 11 additions & 14 deletions src/Form/Validation/ValidationResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@

namespace Drupal\json_forms\Form\Validation;

use Opis\JsonSchema\Errors\ErrorFormatter;
use Opis\JsonSchema\Errors\ValidationError;
use Systopia\JsonSchema\Errors\ErrorCollector;
use Systopia\JsonSchema\Translation\ErrorTranslator;
use Systopia\JsonSchema\Translation\NullTranslator;
use Systopia\JsonSchema\Translation\TranslatorInterface;

final class ValidationResult {

Expand All @@ -33,13 +35,16 @@ final class ValidationResult {

private ErrorCollector $errorCollector;

private ErrorTranslator $errorTranslator;

/**
* @param array<int|string, mixed> $data
* @param \Systopia\JsonSchema\Errors\ErrorCollector $errorCollector
*/
public function __construct(array $data, ErrorCollector $errorCollector) {
public function __construct(array $data, ErrorCollector $errorCollector, ?TranslatorInterface $translator = NULL) {
$this->data = $data;
$this->errorCollector = $errorCollector;
$this->errorTranslator = new ErrorTranslator($translator ?? new NullTranslator());
}

/**
Expand All @@ -53,14 +58,14 @@ public function getData(): array {
* @return array<string, non-empty-array<string>>
*/
public function getErrorMessages(): array {
return static::mapErrorsToMessages($this->errorCollector->getErrors());
return $this->mapErrorsToMessages($this->errorCollector->getErrors());
}

/**
* @return array<string, non-empty-array<string>>
*/
public function getLeafErrorMessages(): array {
return static::mapErrorsToMessages($this->errorCollector->getLeafErrors());
return $this->mapErrorsToMessages($this->errorCollector->getLeafErrors());
}

public function hasErrors(): bool {
Expand All @@ -76,21 +81,13 @@ public function isValid(): bool {
*
* @return array<string, non-empty-array<string>>
*/
private static function mapErrorsToMessages(array $errors): array {
$errorFormatter = static::getErrorFormatter();
private function mapErrorsToMessages(array $errors): array {
return array_map(
fn (array $errors): array => array_map(
fn (ValidationError $error): string => $errorFormatter->formatErrorMessage($error),
fn (ValidationError $error): string => $this->errorTranslator->trans($error),
$errors
), $errors
);
}

private static function getErrorFormatter(): ErrorFormatter {
static $errorFormatter;
$errorFormatter ??= new ErrorFormatter();

return $errorFormatter;
}

}

0 comments on commit bf12a3e

Please sign in to comment.