From 4106cd761bef3f3ab2239ff924c77ebd2ab16051 Mon Sep 17 00:00:00 2001 From: Lukasz Ostafin Date: Tue, 19 Aug 2025 16:27:18 +0200 Subject: [PATCH 1/6] IBX-10362: No validation of matrix field without columns when creating content type --- dependencies.json | 11 ++++++++++ .../js/scripts/admin.contenttype.matrix.js | 17 ++++++++++++++ .../public/scss/_matrix-settings.scss | 4 ++++ .../matrix_fieldtype/field_types.html.twig | 22 +++++++++++++++++-- src/lib/FieldType/Mapper/MatrixFormMapper.php | 4 ++-- src/lib/Form/Type/ColumnType.php | 2 ++ 6 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 dependencies.json diff --git a/dependencies.json b/dependencies.json new file mode 100644 index 0000000..c58bfc4 --- /dev/null +++ b/dependencies.json @@ -0,0 +1,11 @@ +{ + "recipesEndpoint": "", + "packages": [ + { + "requirement": "dev-IBX-10362 as 4.6.x-dev", + "repositoryUrl": "https://github.com/ibexa/admin-ui", + "package": "ibexa/admin-ui", + "shouldBeAddedAsVCS": false + } + ] +} \ No newline at end of file diff --git a/src/bundle/Resources/public/js/scripts/admin.contenttype.matrix.js b/src/bundle/Resources/public/js/scripts/admin.contenttype.matrix.js index e035e80..02448d4 100644 --- a/src/bundle/Resources/public/js/scripts/admin.contenttype.matrix.js +++ b/src/bundle/Resources/public/js/scripts/admin.contenttype.matrix.js @@ -6,6 +6,7 @@ const SELECTOR_ADD_COLUMN = '.ibexa-btn--add-column'; const SELECTOR_REMOVE_COLUMN = '.ibexa-btn--remove-column'; const SELECTOR_TEMPLATE = '.ibexa-matrix-settings__column-template'; + const ERROR_NODE_SELECTOR = '.ibexa-form-error'; const NUMBER_PLACEHOLDER = /__number__/g; const getNextIndex = (parentNode) => { return parentNode.dataset.nextIndex++; @@ -36,9 +37,18 @@ node.insertAdjacentHTML('beforeend', template.replace(NUMBER_PLACEHOLDER, getNextIndex(node))); initColumns(settingsNode); + validateColumnsNumber(settingsNode); node.closest('.ibexa-table').dispatchEvent(new CustomEvent('ibexa-refresh-main-table-checkbox')); + doc.body.dispatchEvent(new CustomEvent('ibexa-inputs:added')); + doc.body.dispatchEvent( + new CustomEvent('ibexa-fieldtype-matrix:added-column', { + detail: { + columnNode: node.querySelector(`${SELECTOR_COLUMN}:last-of-type`), + }, + }), + ); }; const removeItems = (event) => { const settingsNode = event.target.closest(SELECTOR_SETTINGS_COLUMNS); @@ -66,6 +76,7 @@ }); node.closest('.ibexa-table').dispatchEvent(new CustomEvent('ibexa-refresh-main-table-checkbox')); + validateColumnsNumber(settingsNode); }, 0); initColumns(settingsNode); @@ -91,6 +102,12 @@ initColumns(container); }; + const validateColumnsNumber = (settingsNode) => { + const columns = settingsNode.querySelectorAll(SELECTOR_COLUMN); + const errorNode = settingsNode.querySelector(ERROR_NODE_SELECTOR); + + errorNode.toggleAttribute('hidden', columns.length > 0); + }; doc.querySelectorAll(SELECTOR_SETTINGS_COLUMNS).forEach((container) => { initComponent(container); diff --git a/src/bundle/Resources/public/scss/_matrix-settings.scss b/src/bundle/Resources/public/scss/_matrix-settings.scss index 28c794a..24771da 100644 --- a/src/bundle/Resources/public/scss/_matrix-settings.scss +++ b/src/bundle/Resources/public/scss/_matrix-settings.scss @@ -1,4 +1,8 @@ .ibexa-matrix-settings { + &__columns { + margin-top: calculateRem(16px) + } + &__column { .form-check { padding-left: 0; diff --git a/src/bundle/Resources/views/themes/admin/matrix_fieldtype/field_types.html.twig b/src/bundle/Resources/views/themes/admin/matrix_fieldtype/field_types.html.twig index 314d608..e0ac931 100644 --- a/src/bundle/Resources/views/themes/admin/matrix_fieldtype/field_types.html.twig +++ b/src/bundle/Resources/views/themes/admin/matrix_fieldtype/field_types.html.twig @@ -21,11 +21,16 @@ body_row_cols: [ { has_checkbox: true, content: col_checkbox, raw: true }, { content: form_widget(form.columns.vars.prototype.name), raw: true }, - { content: form_widget(form.columns.vars.prototype.identifier), raw: true }, + { content: form_widget(form.columns.vars.prototype.identifier, { + attr: { + class: 'ibexa-input--matrix-column-identifier' + } + }), raw: true }, ], class: 'ibexa-matrix-settings__column', } %} + {{ form_label(form.columns, null, { 'label_attr': { 'class': 'ibexa-label' } }) }} {{ form_errors(form.columns) }} {% set body_rows = [] %} @@ -40,7 +45,11 @@ cols: [ { has_checkbox: true, content: col_checkbox, raw: true }, { content: form_widget(column.name), raw: true }, - { content: form_widget(column.identifier), raw: true }, + { content: form_widget(column.identifier, { + attr: { + class: 'ibexa-input--matrix-column-identifier' + } + }), raw: true }, ], class: 'ibexa-matrix-settings__column', }]) %} @@ -82,5 +91,14 @@ {% endembed %} {% endblock %} {% endembed %} + + {% endblock %} diff --git a/src/lib/FieldType/Mapper/MatrixFormMapper.php b/src/lib/FieldType/Mapper/MatrixFormMapper.php index c7ddfae..3bbdda0 100644 --- a/src/lib/FieldType/Mapper/MatrixFormMapper.php +++ b/src/lib/FieldType/Mapper/MatrixFormMapper.php @@ -43,13 +43,13 @@ public function mapFieldDefinitionForm(FormInterface $fieldDefinitionForm, Field ]) ->add('columns', CollectionType::class, [ 'entry_type' => ColumnType::class, - 'entry_options' => ['required' => false], + 'entry_options' => ['required' => true], 'allow_add' => true, 'allow_delete' => true, 'delete_empty' => false, 'prototype' => true, 'prototype_name' => '__number__', - 'required' => false, + 'required' => true, 'property_path' => 'fieldSettings[columns]', 'label' => false, 'translation_domain' => 'ibexa_matrix_fieldtype', diff --git a/src/lib/Form/Type/ColumnType.php b/src/lib/Form/Type/ColumnType.php index 22a831e..a6113d5 100644 --- a/src/lib/Form/Type/ColumnType.php +++ b/src/lib/Form/Type/ColumnType.php @@ -20,9 +20,11 @@ public function buildForm(FormBuilderInterface $builder, array $options): void $builder ->add('name', TextType::class, [ 'label' => /** @Desc("Name") */ 'fieldtype.column.name', + 'required' => false, ]) ->add('identifier', TextType::class, [ 'label' => /** @Desc("Identifier") */ 'fieldtype.column.identifier', + 'required' => true, ]); } From 9f352d67166ddf3ab04a1cc993f207800a88daa5 Mon Sep 17 00:00:00 2001 From: Lukasz Ostafin Date: Fri, 22 Aug 2025 10:35:14 +0200 Subject: [PATCH 2/6] Added translations --- .../Resources/translations/ibexa_matrix_fieldtype.en.xliff | 5 +++++ .../themes/admin/matrix_fieldtype/field_types.html.twig | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/bundle/Resources/translations/ibexa_matrix_fieldtype.en.xliff b/src/bundle/Resources/translations/ibexa_matrix_fieldtype.en.xliff index 03e79b9..4dc9c10 100644 --- a/src/bundle/Resources/translations/ibexa_matrix_fieldtype.en.xliff +++ b/src/bundle/Resources/translations/ibexa_matrix_fieldtype.en.xliff @@ -26,6 +26,11 @@ Delete key: field.column.delete + + At least one column is required for matrix field. + At least one column is required for matrix field. + key: field.column.error.quantity + Identifier Identifier diff --git a/src/bundle/Resources/views/themes/admin/matrix_fieldtype/field_types.html.twig b/src/bundle/Resources/views/themes/admin/matrix_fieldtype/field_types.html.twig index e0ac931..787193b 100644 --- a/src/bundle/Resources/views/themes/admin/matrix_fieldtype/field_types.html.twig +++ b/src/bundle/Resources/views/themes/admin/matrix_fieldtype/field_types.html.twig @@ -33,7 +33,9 @@ {{ form_label(form.columns, null, { 'label_attr': { 'class': 'ibexa-label' } }) }} {{ form_errors(form.columns) }} + {% set body_rows = [] %} + {% for column in form.columns %} {% set col_checkbox %}
@@ -97,7 +99,7 @@ - At least one column is required for matrix field. + {{ 'field.column.error.quantity'|trans|desc('At least one column is required for matrix field.') }}
From a09f34d1d6960a9fe4c10348e411f5f77f50c20f Mon Sep 17 00:00:00 2001 From: Lukasz Ostafin Date: Fri, 22 Aug 2025 10:38:59 +0200 Subject: [PATCH 3/6] Fixed frontend build --- src/bundle/Resources/public/scss/_matrix-settings.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bundle/Resources/public/scss/_matrix-settings.scss b/src/bundle/Resources/public/scss/_matrix-settings.scss index 24771da..9fab852 100644 --- a/src/bundle/Resources/public/scss/_matrix-settings.scss +++ b/src/bundle/Resources/public/scss/_matrix-settings.scss @@ -1,6 +1,6 @@ .ibexa-matrix-settings { &__columns { - margin-top: calculateRem(16px) + margin-top: calculateRem(16px); } &__column { From 50000c95aa3a6451d87f30b3407c286628db1492 Mon Sep 17 00:00:00 2001 From: Lukasz Ostafin Date: Fri, 22 Aug 2025 11:07:49 +0200 Subject: [PATCH 4/6] Regenerated baseline --- phpstan-baseline.neon | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 5a65ec6..8b5dac8 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,5 +1,11 @@ parameters: ignoreErrors: + - + message: '#^Argument of an invalid type array\\|null supplied for foreach, only iterables are supported\.$#' + identifier: foreach.nonIterable + count: 1 + path: src/bundle/Command/MigrateLegacyMatrixCommand.php + - message: '#^Cannot access offset ''entries'' on array\|bool\|float\|int\|string\|null\.$#' identifier: offsetAccess.nonOffsetAccessible @@ -54,6 +60,12 @@ parameters: count: 1 path: src/bundle/Command/MigrateLegacyMatrixCommand.php + - + message: '#^Parameter \#1 \$cells of method Ibexa\\Bundle\\FieldTypeMatrix\\Command\\MigrateLegacyMatrixCommand\:\:convertCellsToRows\(\) expects array, array\\|null given\.$#' + identifier: argument.type + count: 1 + path: src/bundle/Command/MigrateLegacyMatrixCommand.php + - message: '#^Variable \$xml might not be defined\.$#' identifier: variable.undefined From d7f6cf8b12234899740dca204b69343b98b351b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Bia=C5=82czak?= Date: Fri, 22 Aug 2025 11:46:25 +0200 Subject: [PATCH 5/6] Added ibexa/twig-components dependency and registered TwigComponentsBundle in the kernel --- composer.json | 1 + tests/integration/Kernel.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/composer.json b/composer.json index 13df9ca..8be8310 100644 --- a/composer.json +++ b/composer.json @@ -48,6 +48,7 @@ "ibexa/http-cache": "~4.6.0@dev", "ibexa/design-engine": "~4.6.0@dev", "ibexa/code-style": "^1.0", + "ibexa/twig-components": "~4.6.x-dev", "friendsofphp/php-cs-fixer": "^3.0", "phpunit/phpunit": "^9.5", "phpstan/phpstan": "^2.0", diff --git a/tests/integration/Kernel.php b/tests/integration/Kernel.php index 4eaec91..6e9d1bf 100644 --- a/tests/integration/Kernel.php +++ b/tests/integration/Kernel.php @@ -17,6 +17,7 @@ use Ibexa\Bundle\Notifications\IbexaNotificationsBundle; use Ibexa\Bundle\Rest\IbexaRestBundle; use Ibexa\Bundle\Search\IbexaSearchBundle; +use Ibexa\Bundle\TwigComponents\IbexaTwigComponentsBundle; use Ibexa\Bundle\User\IbexaUserBundle; use Ibexa\Contracts\Test\Core\IbexaTestKernel; use Knp\Bundle\MenuBundle\KnpMenuBundle; @@ -47,6 +48,7 @@ public function registerBundles(): iterable yield new IbexaAdminUiBundle(); yield new IbexaNotificationsBundle(); yield new IbexaGraphQLBundle(); + yield new IbexaTwigComponentsBundle(); yield new IbexaFieldTypeMatrixBundle(); } From f7ac4cb25f117f368aca035ed4884c8ba82cd25f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Bia=C5=82czak?= Date: Fri, 22 Aug 2025 11:56:13 +0200 Subject: [PATCH 6/6] Fixed handling of empty column and cell lists in MigrateLegacyMatrixCommand --- phpstan-baseline.neon | 12 ------------ src/bundle/Command/MigrateLegacyMatrixCommand.php | 5 +++-- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 8b5dac8..5a65ec6 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,11 +1,5 @@ parameters: ignoreErrors: - - - message: '#^Argument of an invalid type array\\|null supplied for foreach, only iterables are supported\.$#' - identifier: foreach.nonIterable - count: 1 - path: src/bundle/Command/MigrateLegacyMatrixCommand.php - - message: '#^Cannot access offset ''entries'' on array\|bool\|float\|int\|string\|null\.$#' identifier: offsetAccess.nonOffsetAccessible @@ -60,12 +54,6 @@ parameters: count: 1 path: src/bundle/Command/MigrateLegacyMatrixCommand.php - - - message: '#^Parameter \#1 \$cells of method Ibexa\\Bundle\\FieldTypeMatrix\\Command\\MigrateLegacyMatrixCommand\:\:convertCellsToRows\(\) expects array, array\\|null given\.$#' - identifier: argument.type - count: 1 - path: src/bundle/Command/MigrateLegacyMatrixCommand.php - - message: '#^Variable \$xml might not be defined\.$#' identifier: variable.undefined diff --git a/src/bundle/Command/MigrateLegacyMatrixCommand.php b/src/bundle/Command/MigrateLegacyMatrixCommand.php index 377682b..62d6177 100644 --- a/src/bundle/Command/MigrateLegacyMatrixCommand.php +++ b/src/bundle/Command/MigrateLegacyMatrixCommand.php @@ -107,7 +107,7 @@ public function execute(InputInterface $input, OutputInterface $output) } if ($isValidXml) { - $columnList = $xml->xpath('//column-name'); + $columnList = $xml->xpath('//column-name') ?: []; $columns = []; @@ -180,7 +180,8 @@ public function execute(InputInterface $input, OutputInterface $output) ], ]); - $rows = $this->convertCellsToRows($xml->xpath('c'), $columns); + $cells = $xml->xpath('c') ?: []; + $rows = $this->convertCellsToRows($cells, $columns); $fieldValue->data['entries'] = $rows;