From 1ec34a2bb0b595d310711e266c364bd3a5b9f293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Sun, 9 Nov 2025 23:02:40 +0100 Subject: [PATCH] Modified form to work properly with new datastructure --- .../Type/DataSourceSynonymsCollectionType.php | 85 ++++++++++++------ .../Misc/DataSourceSynonymResolver.php | 4 +- .../DataSourceSynonymsSettings.php | 90 ------------------- .../DataSourceSynonymsSettings.php | 81 +++++++++++++++++ .../SystemSettings/SystemSettings.php | 1 - 5 files changed, 141 insertions(+), 120 deletions(-) delete mode 100644 src/Settings/BehaviorSettings/DataSourceSynonymsSettings.php create mode 100644 src/Settings/SystemSettings/DataSourceSynonymsSettings.php diff --git a/src/Form/Type/DataSourceSynonymsCollectionType.php b/src/Form/Type/DataSourceSynonymsCollectionType.php index 3853d56a..5507d507 100644 --- a/src/Form/Type/DataSourceSynonymsCollectionType.php +++ b/src/Form/Type/DataSourceSynonymsCollectionType.php @@ -27,38 +27,69 @@ class DataSourceSynonymsCollectionType extends AbstractType { } + private function flattenStructure(array $modelValue): array + { + //If the model is already flattened, return as is + if (array_is_list($modelValue)) { + return $modelValue; + } + + $out = []; + foreach ($modelValue as $dataSource => $locales) { + if (!is_array($locales)) { + continue; + } + foreach ($locales as $locale => $translations) { + if (!is_array($translations)) { + continue; + } + $out[] = [ + 'dataSource' => $dataSource, + 'locale' => $locale, + 'translation_singular' => $translations['singular'] ?? '', + 'translation_plural' => $translations['plural'] ?? '', + ]; + } + } + return $out; + } + public function buildForm(FormBuilderInterface $builder, array $options): void { + $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event): void { + //Flatten the structure + $data = $event->getData(); + $event->setData($this->flattenStructure($data)); + }); + $builder->addModelTransformer(new CallbackTransformer( - // Model -> View - function ($modelValue) { - if (!is_array($modelValue)) { - return [[ - 'dataSource' => null, - 'locale' => null, - 'translation_singular' => null, - 'translation_plural' => null, - ]]; + // Model -> View + $this->flattenStructure(...), + // View -> Model (keep list; let existing behavior unchanged) + function (array $viewValue) { + //Turn our flat list back into the structured array + + foreach ($viewValue as $row) { + if (!is_array($row)) { + continue; + } + $dataSource = $row['dataSource'] ?? null; + $locale = $row['locale'] ?? null; + $translation_singular = $row['translation_singular'] ?? null; + $translation_plural = $row['translation_plural'] ?? null; + + if (!is_string($dataSource) || $dataSource === '' + || !is_string($locale) || $locale === '' + ) { + continue; + } + + $out[$dataSource][$locale] = [ + 'singular' => is_string($translation_singular) ? $translation_singular : '', + 'plural' => is_string($translation_plural) ? $translation_plural : '', + ]; } - return $modelValue === [] ? [[ - 'dataSource' => null, - 'locale' => null, - 'translation_singular' => null, - 'translation_plural' => null, - ]] : $modelValue; - }, - // View -> Model (keep list; let existing behavior unchanged) - function ($viewValue) { - if (!is_array($viewValue)) { - return []; - } - $out = []; - foreach ($viewValue as $row) { - if (is_array($row)) { - $out[] = $row; - } - } return $out; } )); diff --git a/src/Services/Misc/DataSourceSynonymResolver.php b/src/Services/Misc/DataSourceSynonymResolver.php index 8e164670..57e3d642 100644 --- a/src/Services/Misc/DataSourceSynonymResolver.php +++ b/src/Services/Misc/DataSourceSynonymResolver.php @@ -23,7 +23,7 @@ declare(strict_types=1); namespace App\Services\Misc; -use App\Settings\BehaviorSettings\DataSourceSynonymsSettings; +use App\Settings\SystemSettings\DataSourceSynonymsSettings; use Symfony\Contracts\Translation\TranslatorInterface; readonly class DataSourceSynonymResolver @@ -60,7 +60,7 @@ readonly class DataSourceSynonymResolver private function synonyms(string $dataSource, string $locale): array { - $all = $this->synonymsSettings->getSynonymsAsArray(); + $all = []; $row = $all[$dataSource][$locale] ?? ['singular' => '', 'plural' => '']; return [ diff --git a/src/Settings/BehaviorSettings/DataSourceSynonymsSettings.php b/src/Settings/BehaviorSettings/DataSourceSynonymsSettings.php deleted file mode 100644 index c10792d6..00000000 --- a/src/Settings/BehaviorSettings/DataSourceSynonymsSettings.php +++ /dev/null @@ -1,90 +0,0 @@ - ArrayType::class, 'options' => ['type' => StringType::class]], - formType: DataSourceSynonymsCollectionType::class, - formOptions: [ - 'required' => false, - 'data_sources' => [ - 'category' => new TM("settings.behavior.data_source_synonyms.category"), - 'storagelocation' => new TM("settings.behavior.data_source_synonyms.storagelocation"), - 'footprint' => new TM("settings.behavior.data_source_synonyms.footprint"), - 'manufacturer' => new TM("settings.behavior.data_source_synonyms.manufacturer"), - 'supplier' => new TM("settings.behavior.data_source_synonyms.supplier"), - 'project' => new TM("settings.behavior.data_source_synonyms.project"), - ], - ], - )] - #[Assert\Type('array')] - #[Assert\All([new Assert\Type('array')])] - public array $dataSourceSynonyms = [ - // flat list of rows, e.g.: - // ['dataSource' => 'category', 'locale' => 'en', 'translation_singular' => 'Category', 'translation_plural' => 'Categories'], - ]; - - /** - * Normalize to map form: - * [dataSource => [locale => ['singular' => string, 'plural' => string]]] - * No preference/merging is applied; both values are returned as provided (missing ones as empty strings). - * - * @return array> - */ - public function getSynonymsAsArray(): array - { - $result = []; - - foreach ($this->dataSourceSynonyms as $row) { - if (!is_array($row)) { - continue; - } - - $ds = $row['dataSource'] ?? null; - $loc = $row['locale'] ?? null; - - if (!is_string($ds) || $ds === '' || !is_string($loc) || $loc === '') { - continue; - } - - // Read both fields independently; do not prefer one over the other. - $singular = isset($row['translation_singular']) && is_string($row['translation_singular']) - ? $row['translation_singular'] : ''; - $plural = isset($row['translation_plural']) && is_string($row['translation_plural']) - ? $row['translation_plural'] : ''; - - // For legacy data (optional): if only "text" exists and both fields are empty, keep it as given in both slots or leave empty? - // Requirement says: no preference, just return values. We therefore do NOT map legacy automatically. - // If you want to expose legacy "text" as well, handle it outside or migrate data beforehand. - - $result[$ds] ??= []; - $result[$ds][$loc] = [ - 'singular' => $singular, - 'plural' => $plural, - ]; - } - - return $result; - } -} diff --git a/src/Settings/SystemSettings/DataSourceSynonymsSettings.php b/src/Settings/SystemSettings/DataSourceSynonymsSettings.php new file mode 100644 index 00000000..ab0cb053 --- /dev/null +++ b/src/Settings/SystemSettings/DataSourceSynonymsSettings.php @@ -0,0 +1,81 @@ +. + */ + +declare(strict_types=1); + +namespace App\Settings\SystemSettings; + +use App\Form\Type\DataSourceSynonymsCollectionType; +use App\Services\ElementTypes; +use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\ParameterTypes\ArrayType; +use Jbtronics\SettingsBundle\ParameterTypes\SerializeType; +use Jbtronics\SettingsBundle\ParameterTypes\StringType; +use Jbtronics\SettingsBundle\Settings\Settings; +use Jbtronics\SettingsBundle\Settings\SettingsParameter; +use Jbtronics\SettingsBundle\Settings\SettingsTrait; +use Symfony\Component\Translation\TranslatableMessage as TM; +use Symfony\Component\Validator\Constraints as Assert; + +#[Settings(label: new TM("settings.system.data_source_synonyms"))] +#[SettingsIcon("fa-language")] +class DataSourceSynonymsSettings +{ + use SettingsTrait; + + #[SettingsParameter( + ArrayType::class, + label: new TM("settings.system.data_source_synonyms.configuration"), + description: new TM("settings.system.data_source_synonyms.configuration.help"), + options: ['type' => SerializeType::class], + formType: DataSourceSynonymsCollectionType::class, + formOptions: [ + 'required' => false, + 'data_sources' => [ + 'category' => new TM("settings.behavior.data_source_synonyms.category"), + 'storagelocation' => new TM("settings.behavior.data_source_synonyms.storagelocation"), + 'footprint' => new TM("settings.behavior.data_source_synonyms.footprint"), + 'manufacturer' => new TM("settings.behavior.data_source_synonyms.manufacturer"), + 'supplier' => new TM("settings.behavior.data_source_synonyms.supplier"), + 'project' => new TM("settings.behavior.data_source_synonyms.project"), + ], + ], + )] + #[Assert\Type('array')] + #[Assert\All([new Assert\Type('array')])] + /** + * @var array> $customTypeLabels + * An array of the form: [ + * 'category' => [ + * 'en' => ['singular' => 'Category', 'plural' => 'Categories'], + * 'de' => ['singular' => 'Kategorie', 'plural' => 'Kategorien'], + * ], + * 'manufacturer' => [ + * 'en' => ['singular' => 'Manufacturer', 'plural' =>'Manufacturers'], + * ], + * ] + */ + public array $customTypeLabels = []; + + public function isCustomLabelDefinedForType(ElementTypes $type): bool + { + return isset($this->customTypeLabels[$type->value]); + } +} diff --git a/src/Settings/SystemSettings/SystemSettings.php b/src/Settings/SystemSettings/SystemSettings.php index 3d6c4041..2e887116 100644 --- a/src/Settings/SystemSettings/SystemSettings.php +++ b/src/Settings/SystemSettings/SystemSettings.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace App\Settings\SystemSettings; use Jbtronics\SettingsBundle\Settings\EmbeddedSettings; -use App\Settings\BehaviorSettings\DataSourceSynonymsSettings; use Jbtronics\SettingsBundle\Settings\Settings; use Symfony\Component\Translation\TranslatableMessage as TM;