diff --git a/.ddev/config.yaml b/.ddev/config.yaml index 8347238cc..f0b5e171f 100644 --- a/.ddev/config.yaml +++ b/.ddev/config.yaml @@ -40,7 +40,7 @@ web_environment: - PANTHER_CHROME_ARGUMENTS='--disable-dev-shm-usage --ignore-certificate-errors' - PANTHER_NO_SANDBOX=1 - PANTHER_NO_HEADLESS=0 -nodejs_version: "16" +nodejs_version: "18" webimage_extra_packages: - pngquant - jpegoptim diff --git a/README.md b/README.md index eed0941a0..36f88fd4b 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ Please comply with `make codeclean` and `make tests` before to push, your PR won | [SolrSearchExtraBundle](https://github.com/Novactive/NovaeZSolrSearchExtraBundle): Solr search handler additions. It adds many things, binary file plain text content indexation, fullText criterion, custom field configuration, exact matches boosting configuration, etc. | ![eZ-Platform-2.x-OK] ![eZ-Platform-3.x-UNSURE] ![Ibexa-3.3.x-UNSURE] | ![MIT] | | [StaticTemplatesBundle](https://github.com/Novactive/NovaeZStaticTemplatesBundle): Render twig templates via their paths through the design engine mechanism. Simple and perfect tiny bundle to build your Front-end first using Twig. | ![eZ-Platform-2.x-OK] ![eZ-Platform-3.x-OK] ![Ibexa-3.3.x-OK] ![Ibexa-4.x-OK] | ![MIT] | | [TranslationUiBundle](https://github.com/Novactive/AlmaviaCXIbexaTranslationUiBundle): This bundle allows to import translation files content into the database and provide a GUI to edit translations. | ![Ibexa-4.x-OK] | ![MIT] | +| [SélectionFieldType](https://github.com/Novactive/Ibexa-FieldTypes): Enhanced Ibexa sélection type for Ibexa: possibility to add configure selection option by yaml. | ![Ibexa-4.x-OK] | ![MIT] | ## For Maintainers diff --git a/components/IbexaFieldTypes/README.md b/components/IbexaFieldTypes/README.md new file mode 100644 index 000000000..4bd80cc9d --- /dev/null +++ b/components/IbexaFieldTypes/README.md @@ -0,0 +1,50 @@ +## AlmaviaCX Ibexa FieldTypes +This bundle add some field types to ibexa + +## Installation +```bash +composer require almaviacx/ibexa-field-types +``` + +update `config/bundles.php` file by adding this: + +```php + AlmaviaCX\Ibexa\Bundle\FieldTypes\AlmaviaCXFieldTypesBundle::class => ['all' => true],, +``` + +## Configuration + +### ACX selection fieldType + +#### selection choices configuration +create a configuration `config/packages/acx_field_types.yaml` with the following +```yaml +acx_field_types: + system: + default: # or global or siteaccess GROUP + acx_selection: + my_selection_choices: # value of choices_entry in fiedltypes settings + # Label: value + "atlicon-grid": atlicon-grid + atlicon-industry: atlicon-industry + atlicon-people-simple: atlicon-people-simple + atlicon-gears: atlicon-gears +``` +#### template to render `my_selection_choices` field value +create a template accessible throught: `@ibexadesign/fields/acxselection/my_custom_choices.html.twig` +#### edit (or create) the content_type + - add a field of type almaviacx selection + - fieldSettings: + - Choices entry: `my_selection_choices` + - template: `my_custom_choices` + - check single / multiple selection + +update the template to your needs: +example for atlicon to diplay icon +`@ibexadesign/fields/acxselection/my_custom_choices.html.twig` content can be: +```twig +{% set selected_value = field.value.getSelection() %} +{% if selected_value is not empty %} + load('default_settings.yaml'); + $processor = new ConfigurationProcessor($container, Configuration::CONFIG_RESOLVER_NAMESPACE); + $processor->mapConfigArray('acx_selection', $config, ContextualizerInterface::MERGE_FROM_SECOND_LEVEL); + + $loader->load('services.yaml'); + } + + public function prepend(ContainerBuilder $container): void + { + $configFile = __DIR__.'/../Resources/config/field_types_templates.yaml'; + $container->prependExtensionConfig('ibexa', Yaml::parse(file_get_contents($configFile))); + $container->addResource(new FileResource($configFile)); + } +} diff --git a/components/IbexaFieldTypes/bundle/DependencyInjection/Configuration.php b/components/IbexaFieldTypes/bundle/DependencyInjection/Configuration.php new file mode 100644 index 000000000..8ecd66fac --- /dev/null +++ b/components/IbexaFieldTypes/bundle/DependencyInjection/Configuration.php @@ -0,0 +1,29 @@ +getRootNode(); + + $this->generateScopeBaseNode($rootNode) + ->arrayNode('acx_selection')->info('Choices entries') + ->prototype('array') + ->useAttributeAsKey('name') + ->prototype('variable')->end() + ->end() + ->end() + ; + + return $treeBuilder; + } +} diff --git a/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Form/AcxSelectionSettingsType.php b/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Form/AcxSelectionSettingsType.php new file mode 100644 index 000000000..175a060c2 --- /dev/null +++ b/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Form/AcxSelectionSettingsType.php @@ -0,0 +1,25 @@ +add( + 'isMultiple', + CheckboxType::class, + [ + 'required' => false, + 'label' => 'Multiple', + ] + ); + $builder->add('choices_entry', TextType::class); + $builder->add('template', TextType::class); + } +} diff --git a/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Form/AcxSelectionType.php b/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Form/AcxSelectionType.php new file mode 100644 index 000000000..b080907e0 --- /dev/null +++ b/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Form/AcxSelectionType.php @@ -0,0 +1,41 @@ +getBlockPrefix(); + } + + public function getParent(): string + { + return ChoiceType::class; + } + + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder->addModelTransformer(new FieldValueTransformer($options['multiple'])); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'expanded' => false, + 'required' => true, + 'multiple' => false, + 'choices' => [], + ]); + } +} diff --git a/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Form/FieldValueTransformer.php b/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Form/FieldValueTransformer.php new file mode 100644 index 000000000..02dd1e90c --- /dev/null +++ b/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Form/FieldValueTransformer.php @@ -0,0 +1,32 @@ +selection ?? []); + + return true === $this->isMultiple ? $selection : ($selection[0] ?? null); + } + + public function reverseTransform($value): ?Value + { + $value = (array) $value; + + return new Value(false === $this->isMultiple ? [reset($value)] : $value); + } +} diff --git a/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Type.php b/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Type.php new file mode 100644 index 000000000..27fa0ade3 --- /dev/null +++ b/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Type.php @@ -0,0 +1,159 @@ + [ + 'type' => 'string', + 'default' => 'default', + ], + 'template' => [ + 'type' => 'string', + 'default' => 'default', + ], + 'isMultiple' => [ + 'type' => 'bool', + 'default' => false, + ], + ]; + } + + public function fromHash($hash): Value + { + return new Value((array) $hash); + } + + public function toHash(SPIValue $value): ?array + { + if (!($value instanceof Value)) { + return []; + } + + return (array) $value->selection; + } + + public function getName(SPIValue $value, FieldDefinition $fieldDefinition, string $languageCode): string + { + if (empty($value->selection)) { + return ''; + } + + $names = []; + $fieldSettings = $fieldDefinition->getFieldSettings(); + + $choices = array_flip($this->selectionService->getChoices((string) $fieldSettings['choices_entry'])); + foreach ($value->selection as $selectedName) { + $name = $choices[$selectedName] ?? null; + if (null === $name) { + continue; + } + $names[] = $name; + } + + return implode(' ', array_filter($names)); + } + + public function mapFieldValueForm(FormInterface $fieldForm, FieldData $data): void + { + $definition = $data->fieldDefinition; + $fieldSettings = $definition->getFieldSettings(); + $fieldForm->add('value', AcxSelectionType::class, [ + 'required' => $definition->isRequired, + 'label' => $definition->getName(), + 'multiple' => $fieldSettings['isMultiple'] ?? true, + 'choices' => $this->selectionService->getChoices((string) $fieldSettings['choices_entry']), + ]); + } + + public function mapFieldDefinitionForm(FormInterface $fieldDefinitionForm, FieldDefinitionData $data): void + { + $fieldDefinitionForm->add('fieldSettings', AcxSelectionSettingsType::class, [ + 'label' => false, + ]); + } + + public function isSearchable(): bool + { + return true; + } + + public function getIndexData(Field $field, SPIFieldDefinition $fieldDefinition): array + { + $fieldValue = $field->value->data ?? []; + $fieldValue = (string) reset($fieldValue); + $values = (array) $field->value->data; + + return [ + new Search\Field( + 'value', + $fieldValue, + new Search\FieldType\StringField() + ), + new Search\Field( + 'values', + $values, + new Search\FieldType\MultipleStringField() + ), + new Search\Field( + 'fulltext', + $values, + new Search\FieldType\FullTextField() + ), + ]; + } + + public function getIndexDefinition(): array + { + return [ + 'value' => new Search\FieldType\StringField(), + 'values' => new Search\FieldType\MultipleStringField(), + ]; + } + + public function getDefaultMatchField(): string + { + return 'value'; + } + + public function getDefaultSortField(): string + { + return $this->getDefaultMatchField(); + } +} diff --git a/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Value.php b/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Value.php new file mode 100644 index 000000000..a2ce9dee2 --- /dev/null +++ b/components/IbexaFieldTypes/bundle/FieldType/AcxSelection/Value.php @@ -0,0 +1,25 @@ +selection = $selection; + } + + public function getSelection(): string + { + return $this->selection[0] ?? ''; + } + + public function __toString() + { + return implode(',', $this->selection); + } +} diff --git a/components/IbexaFieldTypes/bundle/Resources/config/default_settings.yaml b/components/IbexaFieldTypes/bundle/Resources/config/default_settings.yaml new file mode 100644 index 000000000..5f2cc8573 --- /dev/null +++ b/components/IbexaFieldTypes/bundle/Resources/config/default_settings.yaml @@ -0,0 +1,7 @@ +parameters: + acx_field_types.default.acx_selection: + default: + 'Document': 'docs' + 'Logiciel': 'log' + 'Outil': 'tool' + 'Youtube': 'youtube' \ No newline at end of file diff --git a/components/IbexaFieldTypes/bundle/Resources/config/field_types_templates.yaml b/components/IbexaFieldTypes/bundle/Resources/config/field_types_templates.yaml new file mode 100644 index 000000000..4f6c6aac0 --- /dev/null +++ b/components/IbexaFieldTypes/bundle/Resources/config/field_types_templates.yaml @@ -0,0 +1,6 @@ +system: + default: + field_templates: + - {template: '@ibexadesign/fields/acxselection.html.twig', priority: 0} + fielddefinition_edit_templates: + - { template: '@ibexadesign/fields/definition/acxselection.html.twig', priority: 0 } \ No newline at end of file diff --git a/components/IbexaFieldTypes/bundle/Resources/config/services.yaml b/components/IbexaFieldTypes/bundle/Resources/config/services.yaml new file mode 100644 index 000000000..829a7347d --- /dev/null +++ b/components/IbexaFieldTypes/bundle/Resources/config/services.yaml @@ -0,0 +1,19 @@ +services: + _defaults: + autoconfigure: true + autowire: true + public: false + + AlmaviaCX\Ibexa\Bundle\FieldTypes\Service\: + resource: '../../Service' + + AlmaviaCX\Ibexa\Bundle\FieldTypes\FieldType\AcxSelection\Form\AcxSelectionType: ~ + + AlmaviaCX\Ibexa\Bundle\FieldTypes\FieldType\AcxSelection\Form\AcxSelectionSettingsType: ~ + + AlmaviaCX\Ibexa\Bundle\FieldTypes\FieldType\AcxSelection\Type: + tags: + - { name: ibexa.field_type, alias: acxselection } + - { name: ibexa.admin_ui.field_type.form.mapper.value, fieldType: acxselection } + - { name: ibexa.admin_ui.field_type.form.mapper.definition, fieldType: acxselection } + - { name: ibexa.field_type.indexable, alias: acxselection } \ No newline at end of file diff --git a/components/IbexaFieldTypes/bundle/Resources/translations/fieldtypes.en.yaml b/components/IbexaFieldTypes/bundle/Resources/translations/fieldtypes.en.yaml new file mode 100644 index 000000000..b9a2fbb8a --- /dev/null +++ b/components/IbexaFieldTypes/bundle/Resources/translations/fieldtypes.en.yaml @@ -0,0 +1 @@ +acxselection.name: 'ALmaviacx Selection' \ No newline at end of file diff --git a/components/IbexaFieldTypes/bundle/Resources/views/themes/standard/fields/acxselection.html.twig b/components/IbexaFieldTypes/bundle/Resources/views/themes/standard/fields/acxselection.html.twig new file mode 100644 index 000000000..1555fdc82 --- /dev/null +++ b/components/IbexaFieldTypes/bundle/Resources/views/themes/standard/fields/acxselection.html.twig @@ -0,0 +1,5 @@ +{% block acxselection_field %} + {% set option_template = fieldSettings.template|default('default')|trim %} + {% set option_template = option_template == '' ? 'default':option_template %} + {% include '@ibexadesign/fields/acxselection/'~option_template~'.html.twig' %} +{% endblock %} \ No newline at end of file diff --git a/components/IbexaFieldTypes/bundle/Resources/views/themes/standard/fields/acxselection/default.html.twig b/components/IbexaFieldTypes/bundle/Resources/views/themes/standard/fields/acxselection/default.html.twig new file mode 100644 index 000000000..d6db4c83b --- /dev/null +++ b/components/IbexaFieldTypes/bundle/Resources/views/themes/standard/fields/acxselection/default.html.twig @@ -0,0 +1,9 @@ +{% if fieldSettings.isMultiple|default(false) %} + +{% else %} + {{ field.value.getSelection() }} +{% endif %} \ No newline at end of file diff --git a/components/IbexaFieldTypes/bundle/Resources/views/themes/standard/fields/definition/acxselection.html.twig b/components/IbexaFieldTypes/bundle/Resources/views/themes/standard/fields/definition/acxselection.html.twig new file mode 100644 index 000000000..28f330d20 --- /dev/null +++ b/components/IbexaFieldTypes/bundle/Resources/views/themes/standard/fields/definition/acxselection.html.twig @@ -0,0 +1,12 @@ +{% block acxselection_definition_edit %} +
+ {{- form_label(form.fieldSettings.choices_entry) -}} + {{- form_errors(form.fieldSettings.choices_entry) -}} + {{- form_widget(form.fieldSettings.choices_entry) -}} +
+
+ {{- form_label(form.fieldSettings.template) -}} + {{- form_errors(form.fieldSettings.template) -}} + {{- form_widget(form.fieldSettings.template) -}} +
+{% endblock %} \ No newline at end of file diff --git a/components/IbexaFieldTypes/bundle/Service/SelectionInterface.php b/components/IbexaFieldTypes/bundle/Service/SelectionInterface.php new file mode 100644 index 000000000..5d6cb2680 --- /dev/null +++ b/components/IbexaFieldTypes/bundle/Service/SelectionInterface.php @@ -0,0 +1,8 @@ +configResolver->getParameter('acx_selection', 'acx_field_types')[$choiceEntry] ?? []); + } +} diff --git a/components/IbexaFieldTypes/ci-config.yaml b/components/IbexaFieldTypes/ci-config.yaml new file mode 100644 index 000000000..fb3cee709 --- /dev/null +++ b/components/IbexaFieldTypes/ci-config.yaml @@ -0,0 +1,3 @@ +install: true +test: false +repo: Novactive/Ibexa-FieldTypes diff --git a/components/IbexaFieldTypes/composer.json b/components/IbexaFieldTypes/composer.json new file mode 100644 index 000000000..1d4eea120 --- /dev/null +++ b/components/IbexaFieldTypes/composer.json @@ -0,0 +1,20 @@ +{ + "name": "almaviacx/ibexa-field-types", + "description": "Ibexa Bundle that add some ibexa fieldtypes", + "type": "ibexa-bundle", + "require": { + "php": ">=8.1" + }, + "license": "MIT", + "autoload": { + "psr-4": { + "AlmaviaCX\\Ibexa\\Bundle\\FieldTypes\\": "bundle/" + } + }, + "authors": [ + { + "name": "Ousmane KANTE", + "email": "ousmane.kante@almaviacx.com" + } + ] +}