diff --git a/.cspell-project-words.txt b/.cspell-project-words.txt new file mode 100644 index 0000000000000000000000000000000000000000..a9bc196c505b1ba4c4ee9b4e15d1a93132240102 --- /dev/null +++ b/.cspell-project-words.txt @@ -0,0 +1,31 @@ +Addressfield +addressfield +afterbuild +Colan +colan +ergonlogic +Ferreira +Gervais +Hedding +heddn +hideme +itsekhmistro +Magini +mparker +olgarabodzei +oneline +organisation +peterpoe +plusplus +Rabodzei +Rutz +tesformat +Thalles +thalles +Tsekhmistro +UNTRIGGERED +untriggered +autocollapse +autocompleteselect +legendsspan +unrequired diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..2c4a217bb94fa54a2d5f241d4853d41856a39cd8 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,37 @@ +################ +# GitLabCI template for Drupal projects. +# +# This template is designed to give any Contrib maintainer everything they need to test, without requiring modification. +# It is also designed to keep up to date with Core Development automatically through the use of include files that can be centrally maintained. +# As long as you include the project, ref and three files below, any future updates added by the Drupal Association will be used in your +# pipelines automatically. However, you can modify this template if you have additional needs for your project. +# The full documentation is on https://project.pages.drupalcode.org/gitlab_templates/ +################ + +# For information on alternative values for 'ref' see https://project.pages.drupalcode.org/gitlab_templates/info/templates-version/ +# To test a Drupal 7 project, change the first include filename from .main.yml to .main-d7.yml +include: + - project: $_GITLAB_TEMPLATES_REPO + ref: $_GITLAB_TEMPLATES_REF + file: + - "/includes/include.drupalci.main.yml" + - "/includes/include.drupalci.variables.yml" + - "/includes/include.drupalci.workflows.yml" + +################ +# Pipeline configuration variables are defined with default values and descriptions in the file +# https://git.drupalcode.org/project/gitlab_templates/-/blob/main/includes/include.drupalci.variables.yml +# Uncomment the lines below if you want to override any of the variables. The following is just an example. +################ +variables: + _PHPUNIT_CONCURRENT: '1' + +# +# Start custom overrides. +# Based on https://git.drupalcode.org/project/keycdn/-/blob/8.x-1.x/.gitlab-ci.yml +# + +variables: + _SHOW_ENVIRONMENT_VARIABLES: 1 + # Broaden test coverage. + OPT_IN_TEST_PREVIOUS_MAJOR: 1 diff --git a/README.md b/README.md index 8aa3dd4dce2481573f8d5f4b340e6a7c1725bb64..103ebea67ec5b84914d65b5cb98b83d00246ddf3 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,13 @@ # Conditional Fields -Conditional Fields allows you to manage sets of dependencies between fields. When a field is “dependent”, it will only be available for editing and displayed if the state of the “dependee” field matches the right condition. -When editing a node (or any other entity type that supports fields, like users and categories), the dependent fields are dynamically modified with the States API. -A simple use case would be defining a custom “Article teaser" field that is shown only if a "Has teaser" checkbox is checked, but much more complex options are available. +Conditional Fields allows you to manage sets of dependencies between fields. +When a field is “dependent”, it will only be available for editing and displayed +if the state of the “dependee” field matches the right condition. +When editing a node (or any other entity type that supports fields, like users +and categories), the dependent fields are dynamically modified with the States +API. A simple use case would be defining a custom “Article teaser" field that is +shown only if a "Has teaser" checkbox is checked, but much more complex options +are available. For a full description of the module, visit the [project page](https://www.drupal.org/project/conditional_fields). @@ -33,7 +38,8 @@ information, see ## Configuration -After enable the module, you can create conditional fields on /admin/structure/conditional_fields. +After enable the module, you can create conditional fields on +/admin/structure/conditional_fields. ## Maintainers diff --git a/composer.json b/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..92da7e303c30e400f462ff4aae7f964eaf4d94d4 --- /dev/null +++ b/composer.json @@ -0,0 +1,16 @@ +{ + "name": "drupal/conditional_fields", + "description": "Enables conditional field behaviors.", + "type":"drupal-module", + "license": "GPL-2.0-or-later", + "minimum-stability": "dev", + "homepage": "https://www.drupal.org/project/conditional_fields", + "support": { + "issues": "https://www.drupal.org/project/issues/conditional_fields", + "source": "https://git.drupalcode.org/project/conditional_fields" + }, + "require-dev": { + "drupal/entity_reference_revisions": "1.x-dev", + "drupal/paragraphs": "^1" + } +} diff --git a/conditional_fields.info.yml b/conditional_fields.info.yml index bb41294377dc080e12caaa6c34f9b4ad47ad18c2..5dec4c8297171ea6462bcbc2225f1ec13273fae3 100644 --- a/conditional_fields.info.yml +++ b/conditional_fields.info.yml @@ -1,8 +1,7 @@ name: Conditional Fields type: module description: Define dependencies between fields based on their states and values. -core: 8.x -core_version_requirement: ^8 || ^9 || ^10 +core_version_requirement: ^9 || ^10 || ^11 configure: conditional_fields package: Fields dependencies: diff --git a/conditional_fields.install b/conditional_fields.install index 7852aa56ab52f9d5fa50a59944ada72906981437..fb48206b019d3a0bf10970ceb2d441a417a5f37f 100644 --- a/conditional_fields.install +++ b/conditional_fields.install @@ -16,13 +16,13 @@ function conditional_fields_update_8001() { $bundle_info = \Drupal::service('entity_type.bundle.info'); $entity_types = $cf_service->getEntityTypes(); foreach ($entity_types as $entity_type) { - $etid = $entity_type->id(); - $bundles = $bundle_info->getBundleInfo($etid); + $entity_id = $entity_type->id(); + $bundles = $bundle_info->getBundleInfo($entity_id); foreach ($bundles as $bundle_name => $bundle) { /** @var \Drupal\Core\Entity\Entity\EntityFormDisplay $entity */ $entity = \Drupal::entityTypeManager() ->getStorage('entity_form_display') - ->load("$etid.$bundle_name.default"); + ->load("$entity_id.$bundle_name.default"); // Replace keys. if ($entity instanceof EntityInterface) { _conditional_fields_update_conditional_fields_settings($entity); diff --git a/conditional_fields.libraries.yml b/conditional_fields.libraries.yml index a2eab25c8b74b9ff395f0b27731a5d35e338862e..4b83c2c42303aadd90d7c9bfc8858768e351da6e 100644 --- a/conditional_fields.libraries.yml +++ b/conditional_fields.libraries.yml @@ -1,5 +1,4 @@ conditional_fields: - version: "4.x" js: js/conditional_fields.js: {} dependencies: @@ -7,7 +6,6 @@ conditional_fields: - core/drupal.states admin: - version: "4.x" css: component: css/conditional_fields.admin.css: {} diff --git a/conditional_fields.links.menu.yml b/conditional_fields.links.menu.yml index 20f40eb4356a75f5a0a0c23d39e1d53ecc3b65c7..208468cf4a848da6a834bfba427ed2fbadc40241 100644 --- a/conditional_fields.links.menu.yml +++ b/conditional_fields.links.menu.yml @@ -5,5 +5,3 @@ config.conditional_field: description: 'List Conditional fields' parent: system.admin_structure weight: 100 - - diff --git a/conditional_fields.links.task.yml b/conditional_fields.links.task.yml index 0dfe1d8fa78f6fcede27cd80c636dbc1e8278ebd..7c763ac58a8d5172b53d5bad0b6bc402092cfe88 100644 --- a/conditional_fields.links.task.yml +++ b/conditional_fields.links.task.yml @@ -1,25 +1,30 @@ conditional_fields.conditional_fields.node: - title: Manage Dependencies + title: Manage dependencies route_name: conditional_fields.tab.node base_route: entity.node_type.edit_form weight: 10 conditional_fields.conditional_fields.media: - title: Manage Dependencies + title: Manage dependencies route_name: conditional_fields.tab.media base_route: entity.media_type.edit_form weight: 10 conditional_fields.conditional_fields.block: - title: Manage Dependencies + title: Manage dependencies route_name: conditional_fields.tab.block_content base_route: entity.block_content_type.edit_form weight: 10 conditional_fields.conditional_fields.comment: - title: Manage Dependencies + title: Manage dependencies route_name: conditional_fields.tab.comment base_route: entity.comment_type.edit_form weight: 10 conditional_fields.conditional_fields.user: - title: Manage Dependencies + title: Manage dependencies route_name: conditional_fields.tab.user base_route: entity.user.admin_form weight: 10 +conditional_fields.conditional_fields.paragraphs_type: + title: Manage dependencies + route_name: conditional_fields.tab.paragraph + base_route: entity.paragraphs_type.edit_form + weight: 10 diff --git a/conditional_fields.module b/conditional_fields.module index bd6b44437d7f1dc522bae9a57a58543485c96043..8513aa50faf50a5d6ebbede6d491a3e877da27cb 100644 --- a/conditional_fields.module +++ b/conditional_fields.module @@ -5,11 +5,11 @@ * Contains conditional_fields.module. */ -use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\WidgetInterface; +use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Url; /** @@ -51,10 +51,11 @@ function conditional_fields_theme() { */ function conditional_fields_entity_operation(EntityInterface $entity) { $operations = []; - if ($entity->getEntityTypeId() == 'node_type') { + $url = Url::fromRoute('conditional_fields.tab.node', [$entity->getEntityTypeId() => $entity->id()]); + if ($entity->getEntityTypeId() == 'node_type' && $url->access()) { $operations['dependencies'] = [ 'title' => t('Manage dependencies'), - 'url' => Url::fromRoute('conditional_fields.tab.node', [$entity->getEntityTypeId() => $entity->id()]), + 'url' => $url, 'weight' => 29, ]; } @@ -95,7 +96,7 @@ function conditional_fields_conditional_fields_alter(&$fields, $entity_type, $bu } /** - * After build function to process field depencies. + * After build function to process field dependencies. */ function conditional_fields_element_after_build($element, FormStateInterface &$form_state) { return \Drupal::service('conditional_fields.element_alter_helper')->afterBuild($element, $form_state); @@ -109,7 +110,7 @@ function conditional_fields_element_after_build($element, FormStateInterface &$f * @param array $field * The field form element. * - * @return string|FALSE + * @return string|false * A jQuery selector string. */ function conditional_fields_field_selector($field) { @@ -158,13 +159,6 @@ function conditional_fields_field_widget_third_party_settings_form(WidgetInterfa * Implements hook_form_alter(). * * Hook_form_alter() that attaches an 'afterbuild' function to the form. - * - * @param $form - * The form to attach the callback to. - * @param $form_state - * Not used, part of the hook interface. - * @param $form_id - * Not used, part of the hook interface. */ function conditional_fields_form_alter(&$form, &$form_state, $form_id) { $form['#after_build'][] = 'conditional_fields_form_after_build'; @@ -173,30 +167,44 @@ function conditional_fields_form_alter(&$form, &$form_state, $form_id) { /** * Implements hook_inline_entity_form_entity_form_alter(). * - * Hook_inline_entity_form_entity_form_alter() that attaches an 'afterbuild' function to the form. - * - * @param array $entity_form - * Nested array of form elements that comprise the entity form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The form state of the parent form. + * Hook_inline_entity_form_entity_form_alter() that attaches an 'afterbuild' + * function to the form. */ function conditional_fields_inline_entity_form_entity_form_alter(&$entity_form, &$form_state) { $entity_form['#after_build'][] = 'conditional_fields_form_after_build'; } /** - * Runs the 'afterbuild' validation of a form with dependencies. + * Implements hook_form_after_build(). * + * Runs the 'afterbuild' validation of a form with dependencies. * This function will run only once per form. - * - * @param $form - * The form to validate - * @param $form_state - * The form's state. - * - * @return mixed - * The form. */ function conditional_fields_form_after_build($form, &$form_state) { return \Drupal::service('conditional_fields.form_helper')->afterBuild($form, $form_state); } + +/** + * Allows identify dependents/dependees with predictable IDs. + */ +function conditional_fields_get_simpler_id($id) { + // Removes an appended identifier used for individual options. + // preg_match('/.*([-]{2,}[a-zA-Z0-9]+)$/', $id, $matches);. + preg_match('/.*(--[a-zA-Z0-9-_]+)$/', $id, $matches); + if ($matches[1] ?? FALSE) { + $id = str_replace($matches[1], '', $id); + } + + $strings_to_remove = [ + '-0-value', + '-value', + ]; + foreach ($strings_to_remove as $string_to_remove) { + $string_to_remove_strlen = strlen($string_to_remove); + if ((strrpos($id, $string_to_remove) + $string_to_remove_strlen) == strlen($id)) { + return substr($id, 0, -$string_to_remove_strlen); + } + } + + return $id; +} diff --git a/conditional_fields.permissions.yml b/conditional_fields.permissions.yml index 6eb4b3111433af3b8481b549becbbea7cc23dbd4..035e2a409489175a3ee8c334e2585c9769db7a57 100644 --- a/conditional_fields.permissions.yml +++ b/conditional_fields.permissions.yml @@ -6,4 +6,3 @@ edit conditional fields: delete conditional fields: title: 'Delete Conditional fields' - diff --git a/conditional_fields.routing.yml b/conditional_fields.routing.yml index 563cbc070b60f9d2dbee711546e0ea24fc5dff7d..9bab74045f845209bea2f5875084bb7ece9ab1e2 100644 --- a/conditional_fields.routing.yml +++ b/conditional_fields.routing.yml @@ -40,7 +40,7 @@ conditional_fields.delete_form: conditional_fields.tab.node: path: '/admin/structure/types/manage/{node_type}/conditionals' defaults: - _title: 'Manage Dependencies' + _title: 'Manage dependencies' _controller: 'conditional_fields.controller:provideArguments' requirements: _permission: 'view conditional fields' @@ -48,7 +48,7 @@ conditional_fields.tab.node: conditional_fields.tab.media: path: '/admin/structure/media/manage/{media_type}/conditionals' defaults: - _title: 'Manage Dependencies' + _title: 'Manage dependencies' _controller: 'conditional_fields.controller:getMediaEditFormTab' requirements: _permission: 'view conditional fields' @@ -56,7 +56,7 @@ conditional_fields.tab.media: conditional_fields.tab.block_content: path: '/admin/structure/block/manage/block-content/{block_content_type}/conditionals' defaults: - _title: 'Manage Dependencies' + _title: 'Manage dependencies' _controller: 'conditional_fields.controller:getBlockEditFormTab' requirements: _permission: 'view conditional fields' @@ -64,7 +64,7 @@ conditional_fields.tab.block_content: conditional_fields.tab.comment: path: '/admin/structure/comment/manage/{comment_type}/conditionals' defaults: - _title: 'Manage Dependencies' + _title: 'Manage dependencies' _controller: 'conditional_fields.controller:getCommentEditFormTab' requirements: _permission: 'view conditional fields' @@ -72,11 +72,19 @@ conditional_fields.tab.comment: conditional_fields.tab.user: path: '/admin/config/people/accounts/conditionals' defaults: - _title: 'Manage Dependencies' + _title: 'Manage dependencies' _controller: 'conditional_fields.controller:getUserEditFormTab' requirements: _permission: 'view conditional fields' +conditional_fields.tab.paragraph: + path: '/admin/structure/paragraphs_type/{paragraphs_type}/conditionals' + defaults: + _title: 'Manage dependencies' + _controller: 'conditional_fields.controller:getParagraphEditFormTab' + requirements: + _permission: 'view conditional fields' + conditional_fields.edit_form.tab: path: '/admin/structure/conditional_fields/{entity_type}/{bundle}/{field_name}/{uuid}/tab/edit' defaults: diff --git a/conditional_fields.services.yml b/conditional_fields.services.yml index c732cff2bab406bdcbc43986da4fe6fde4f52e8f..86fe65f5c78fbed13311c7189bcaf1703055b686 100644 --- a/conditional_fields.services.yml +++ b/conditional_fields.services.yml @@ -7,10 +7,20 @@ services: parent: default_plugin_manager conditional_fields.controller: class: Drupal\conditional_fields\Controller\ConditionalFieldController - arguments: ['@entity_type.manager', '@form_builder', '@entity_type.bundle.info', '@entity_field.manager'] + arguments: + - '@entity_type.manager' + - '@form_builder' + - '@entity_type.bundle.info' + - '@entity_field.manager' conditional_fields.form_helper: class: Drupal\conditional_fields\ConditionalFieldsFormHelper - arguments: ['@plugin.manager.element_info', '@plugin.manager.conditional_fields_handlers', '@entity_display.repository'] + arguments: + - '@plugin.manager.element_info' + - '@plugin.manager.conditional_fields_handlers' + - '@entity_display.repository' + - '@language_manager' conditional_fields.element_alter_helper: class: Drupal\conditional_fields\ConditionalFieldsElementAlterHelper - arguments: [] + arguments: + - '@module_handler' + - '@entity_type.manager' diff --git a/css/conditional_fields.admin.css b/css/conditional_fields.admin.css index 205894688dc20d174ee1639b9a52ed5aecc4a880..8e91903bc5cd0017cc8b2049c57b7ec61ff22be6 100644 --- a/css/conditional_fields.admin.css +++ b/css/conditional_fields.admin.css @@ -1,4 +1,4 @@ .conditional-fields-selector { - min-width: 150px; width: 50%; + min-width: 150px; } diff --git a/js/conditional_fields.js b/js/conditional_fields.js index a8bb10212ea3c9ec9560cf80f378204147716399..61e0bbde4c2c5571189b7df3551114b48eb21ed1 100644 --- a/js/conditional_fields.js +++ b/js/conditional_fields.js @@ -1,308 +1,353 @@ -(function ($, Drupal) { - -/** - * Enhancements to states.js. - */ -// Checking if autocomplete is plugged in. -if (Drupal.autocomplete) { +(($, Drupal) => { /** - * Handles an autocompleteselect event. - * - * Override the autocomplete method to add a custom event. - * - * @param {jQuery.Event} event - * The event triggered. - * @param {object} ui - * The jQuery UI settings object. - * - * @return {bool} - * Returns false to indicate the event status. + * Enhancements to states.js. */ - Drupal.autocomplete.options.select = function selectHandler(event, ui) { - var terms = Drupal.autocomplete.splitValues(event.target.value); - // Remove the current input. - terms.pop(); - // Add the selected item. - if (ui.item.value.search(',') > 0) { - terms.push('"' + ui.item.value + '"'); - } - else { - terms.push(ui.item.value); - } - event.target.value = terms.join(', '); - // Fire custom event that other controllers can listen to. - jQuery(event.target).trigger('autocomplete-select'); - // Return false to tell jQuery UI that we've filled in the value already. - return false; - }; -} + // Checking if autocomplete is plugged in. + if (Drupal.autocomplete) { + /** + * Handles an autocompleteselect event. + * + * Override the autocomplete method to add a custom event. + * + * @param {jQuery.Event} event + * The event triggered. + * @param {object} ui + * The jQuery UI settings object. + * + * @return {bool} + * Returns false to indicate the event status. + */ + Drupal.autocomplete.options.select = function selectHandler(event, ui) { + const terms = Drupal.autocomplete.splitValues(event.target.value); + // Remove the current input. + terms.pop(); + // Add the selected item. + if (ui.item.value.search(',') > 0) { + terms.push(`"${ui.item.value}"`); + } else { + terms.push(ui.item.value); + } + event.target.value = terms.join(', '); + // Fire custom event that other controllers can listen to. + jQuery(event.target).trigger('autocomplete-select'); + // Return false to tell jQuery UI that we've filled in the value already. + return false; + }; + } -/** - * New and existing states enhanced with configurable options. - * Event names of states with effects have the following structure: - * state:stateName-effectName. - */ + /** + * New and existing states enhanced with configurable options. + * Event names of states with effects have the following structure: + * state:stateName-effectName. + */ -//Visible/Invisible. -$(document).bind('state:visible-fade', function (e) { - if (e.trigger) { - $(e.target).closest('.form-item, .form-submit, .form-wrapper')[e.value ? 'fadeIn' : 'fadeOut'](e.effect.speed); - } -}) -.bind('state:visible-slide', function (e) { - if (e.trigger) { - $(e.target).closest('.form-item, .form-submit, .form-wrapper')[e.value ? 'slideDown' : 'slideUp'](e.effect.speed); - } -}) -// Empty/Filled. -.bind('state:empty', function (e) { - if (e.trigger) { - var fields = $(e.target).find('input, select, textarea'); - fields.each(function () { - if (typeof $(this).data('conditionalFieldsSavedValue') === 'undefined') { - $(this).data('conditionalFieldsSavedValue', $(this).val()); + // Visible/Invisible. + $(document) + .on('state:visible-fade', (e) => { + if (e.trigger) { + $(e.target) + .closest('.form-item, .form-submit, .form-wrapper') + [e.value ? 'fadeIn' : 'fadeOut'](e.effect.speed); } - if (e.effect) { - if (e.value) { - $(this).val(e.effect.value); - } - else if ($(this).data('conditionalFieldsSavedValue')) { - $(this).val($(this).data('conditionalFieldsSavedValue')); - } + }) + .on('state:visible-slide', (e) => { + if (e.trigger) { + $(e.target) + .closest('.form-item, .form-submit, .form-wrapper') + [e.value ? 'slideDown' : 'slideUp'](e.effect.speed); } }) - } -}) -// On invisible make empty and unrequired. -.bind('state:visible', function (e) { - if (e.trigger) { - const fields = $(e.target).find('input, select, textarea'); - fields.each(function () { - const $field = $(this); - // Save required property. - if (typeof $field.data('conditionalFieldsSavedRequired') === 'undefined') { - $field.data('conditionalFieldsSavedRequired', $field.attr('required')); + // Empty/Filled. + .on('state:empty', (e) => { + if (e.trigger) { + const fields = $(e.target).find('input, select, textarea'); + fields.each(function processControls() { + if ( + typeof $(this).data('conditionalFieldsSavedValue') === 'undefined' + ) { + $(this).data('conditionalFieldsSavedValue', this.value); + } + if (e.effect) { + if (e.value) { + this.value = e.effect.value; + } else if ($(this).data('conditionalFieldsSavedValue')) { + this.value = $(this).data('conditionalFieldsSavedValue'); + } + } + }); } - // Go invisible. - if (!e.value) { - // Remove required property. - $field.trigger({type: 'state:required', value: false, trigger: true}); + }) + // On invisible make empty and unrequired. + .on('state:visible', (e) => { + if (e.trigger) { + const fields = $(e.target).find('input, select, textarea'); + fields.each(function processControls() { + const $field = $(this); + // Save required property. + if ( + typeof $field.data('conditionalFieldsSavedRequired') === 'undefined' + ) { + $field.data( + 'conditionalFieldsSavedRequired', + $field.attr('required'), + ); + } + // Go invisible. + if (!e.value) { + // Remove required property. + $field.trigger({ + type: 'state:required', + value: false, + trigger: true, + }); + } + // Go visible. + else { + // Restore required if necessary. + // eslint-disable-next-line no-lonely-if + if ($field.data('conditionalFieldsSavedRequired')) { + $field.trigger({ + type: 'state:required', + value: true, + trigger: true, + }); + } + } + }); } - // Go visible. - else { - // Restore required if necessary. - if ($field.data('conditionalFieldsSavedRequired')) { - $field.trigger({type: 'state:required', value: true, trigger: true}); + }) + // Required/Not-Required. + .on('state:required', (e) => { + if (e.trigger) { + const fieldsSupportingRequired = $(e.target).find('input, textarea'); + const legends = $(e.target).find('legend'); + const legendsspan = $(e.target).find('legend span'); + const labels = $(e.target).find( + ':not(.form-item--editor-format, .form-type-radio)>label', + ); + const tabs = $('.vertical-tabs'); + let tab = ''; + if (tabs.length !== 0) { + const detail = $(legends).closest('details'); + const selector = `a[href='#${detail.attr('id')}']`; + tab = $(selector); } - } - }); - } -}) -// Required/Not-Required. -.bind('state:required', function (e) { - if (e.trigger) { - const fields_supporting_required = $(e.target).find('input, textarea'); - const legends = $(e.target).find('legend'); - const legendsspan = $(e.target).find('legend span'); - const labels = $(e.target).find(':not(.form-item--editor-format, .form-type-radio)>label'); - const tabs = $('.vertical-tabs'); - let tab = ''; - if (tabs.length !== 0) { - const detail = $(legends).closest('details'); - const selector = "a[href='#" + detail.attr('id') + "']"; - tab = $(selector); - } - if (e.value) { - if (legends.length !== 0) { - legends.addClass("form-required"); - legendsspan.addClass("js-form-required form-required"); - if (tabs.length !== 0) { - tab.find('strong').addClass("form-required"); + if (e.value) { + if (legends.length !== 0) { + legends.addClass('form-required'); + legendsspan.addClass('js-form-required form-required'); + if (tabs.length !== 0) { + tab.find('strong').addClass('form-required'); + } + } else { + labels.addClass('form-required'); } + fieldsSupportingRequired + .filter(`[name *= "[0]"]`) + .attr('required', 'required'); } else { - labels.addClass("form-required"); - } - fields_supporting_required.filter(`[name *= "[0]"]`).attr('required', 'required'); - } else { - if (legends.length !== 0) { - legends.removeClass("form-required"); - legendsspan.removeClass("js-form-required form-required"); - if (tabs.length !== 0) { - tab.find('strong').removeClass("form-required"); + if (legends.length !== 0) { + legends.removeClass('form-required'); + legendsspan.removeClass('js-form-required form-required'); + if (tabs.length !== 0) { + tab.find('strong').removeClass('form-required'); + } + } else { + labels.removeClass('form-required'); } - } else { - labels.removeClass("form-required"); + fieldsSupportingRequired.removeAttr('required'); } - fields_supporting_required.removeAttr('required'); } - } -}) -// Unchanged state. Do nothing. -.bind('state:unchanged', function () {}); + }) + // Unchanged state. Do nothing. + .on('state:unchanged', () => {}); -Drupal.behaviors.conditionalFields = { - attach: function (context, settings) { - // AJAX is not updating settings.conditionalFields correctly. - var conditionalFields = settings.conditionalFields || 'undefined'; - if (typeof conditionalFields === 'undefined' || typeof conditionalFields.effects === 'undefined') { - return; - } - // Override state change handlers for dependents with special effects. - var eventsData = $.hasOwnProperty('_data') ? $._data(document, 'events') : $(document).data('events'); - $.each(eventsData, function (i, events) { - if (i.substring(0, 6) === 'state:') { - var originalHandler = events[0].handler; - events[0].handler = function (e) { - var effect = conditionalFields.effects['#' + e.target.id]; - if (typeof effect !== 'undefined') { - var effectEvent = i + '-' + effect.effect; - if (typeof eventsData[effectEvent] !== 'undefined') { - $(e.target).trigger({ type : effectEvent, trigger : e.trigger, value : e.value, effect : effect.options }); - return; + Drupal.behaviors.conditionalFields = { + attach(context, settings) { + // AJAX is not updating settings.conditionalFields correctly. + const conditionalFields = settings.conditionalFields || 'undefined'; + if ( + typeof conditionalFields === 'undefined' || + typeof conditionalFields.effects === 'undefined' + ) { + return; + } + // Override state change handlers for dependents with special effects. + const eventsData = $.hasOwnProperty('_data') + ? $._data(document, 'events') + : $(document).data('events'); + $.each(eventsData, (i, events) => { + if (i.substring(0, 6) === 'state:') { + const originalHandler = events[0].handler; + events[0].handler = (e) => { + const effect = conditionalFields.effects[`#${e.target.id}`]; + if (typeof effect !== 'undefined') { + const effectEvent = `${i}-${effect.effect}`; + if (typeof eventsData[effectEvent] !== 'undefined') { + $(e.target).trigger({ + type: effectEvent, + trigger: e.trigger, + value: e.value, + effect: effect.options, + }); + return; + } } - } - e.effect = effect; - originalHandler(e); + e.effect = effect; + originalHandler(e); + }; } - } - }); - } -}; + }); + }, + }; -Drupal.behaviors.ckeditorTextareaFix = { - attach: function (context, settings) { - if (typeof CKEDITOR !== 'undefined') { - CKEDITOR.on('instanceReady', function () { - $(context).find('.form-textarea-wrapper textarea').each(function () { - var $textarea = jQuery(this); - if (CKEDITOR.instances[$textarea.attr('id')] != undefined) { - CKEDITOR.instances[$textarea.attr('id')].on('change', function () { - CKEDITOR.instances[$textarea.attr('id')].updateElement(); - $textarea.trigger('keyup'); - }); - } + Drupal.behaviors.ckeditorTextareaFix = { + attach(context) { + if (typeof CKEDITOR !== 'undefined') { + // eslint-disable-next-line no-undef + const ckEditor = CKEDITOR; + ckEditor.on('instanceReady', () => { + $(context) + .find('.form-textarea-wrapper textarea') + .each(function processTextarea() { + const $textarea = jQuery(this); + if (ckEditor.instances[$textarea.attr('id')] !== undefined) { + ckEditor.instances[$textarea.attr('id')].on('change', () => { + ckEditor.instances[$textarea.attr('id')].updateElement(); + $textarea.trigger('keyup'); }); + } }); - } - } -}; + }); + } + }, + }; -Drupal.behaviors.autocompleteChooseTrigger = { - attach: function (context, settings) { - $(context).find('.form-autocomplete').each(function () { - var $input = $(this); - $(this).on('autocomplete-select', function (event, node) { - setTimeout(function () { - $input.trigger("keyup"); - }, 1); - }); + Drupal.behaviors.autocompleteChooseTrigger = { + attach(context) { + $(context) + .find('.form-autocomplete') + .each(function processAutocomplete() { + const $input = $(this); + $(this).on('autocomplete-select', () => { + setTimeout(() => { + $input.trigger('keyup'); + }, 1); + }); }); + }, + }; + + /** + * The function for compare two strings + * @param a + * @param b + * @return {boolean|*} + * @private + */ + function _compare2(a, b) { + a = typeof a === 'string' ? a.replace(/(^[\n\r]+|[\n\r]+$)/g, '') : a; + b = typeof b === 'string' ? b.replace(/(^[\n\r]+|[\n\r]+$)/g, '') : b; + if (a === b) { + return typeof a === 'undefined' ? a : true; } -}; -Drupal.behaviors.statesModification = { - weight: -10, - attach: function (context, settings) { - if (Drupal.states) { - /** - * Handle array values. - * @see http://drupal.org/node/1149078 - */ - Drupal.states.Dependent.comparisons['Array'] = function (reference, value) { - // Make sure value is an array. - var compare = []; - if ( typeof value === "string" ) { - compare = value.split(/\r?\n\r?/); - } else if ( typeof(value) === "object" && value instanceof Array ) { - compare = value; - } + return typeof a === 'undefined' || typeof b === 'undefined'; + } - if (compare.length < 1 ) { - return false; - } - // We iterate through each value provided in the reference. If all of them - // exist in value array, we return true. Otherwise return false. - for (var key in reference) { - if (reference.hasOwnProperty(key) && $.inArray(String(reference[key]), compare) < 0) { - return false; + Drupal.behaviors.statesModification = { + weight: -10, + attach() { + if (Drupal.states) { + /** + * Handle array values. + * @see http://drupal.org/node/1149078 + */ + Drupal.states.Dependent.comparisons.Array = (reference, value) => { + // Make sure value is an array. + let compare = []; + if (typeof value === 'string') { + compare = value.split(/\r?\n\r?/); + } else if (typeof value === 'object' && value instanceof Array) { + compare = value; } - } - return true; - }; - /** - * Handle object values. - */ - Drupal.states.Dependent.comparisons.Object = function (reference, value) { + if (compare.length < 1) { + return false; + } + // We iterate through each value provided in the reference. If all of them + // exist in value array, we return true. Otherwise return false. + // eslint-disable-next-line no-restricted-syntax + for (const key in reference) { + if ( + reference.hasOwnProperty(key) && + $.inArray(String(reference[key]), compare) < 0 + ) { + return false; + } + } + return true; + }; /** - * Adds RegEx support - * https://www.drupal.org/node/1340616 + * Handle object values. */ - if ('regex' in reference) { - //The fix for regex when value is array - var regObj = new RegExp(reference.regex, reference.flags); - if ( value && value.constructor.name == 'Array' ) { - for (var index in value) { - if (regObj.test( value[index])) { - return true; + Drupal.states.Dependent.comparisons.Object = (reference, value) => { + /** + * Adds RegEx support + * https://www.drupal.org/node/1340616 + */ + if ('regex' in reference) { + // The fix for regex when value is array + const regObj = new RegExp(reference.regex, reference.flags); + if (value && value.constructor.name === 'Array') { + // eslint-disable-next-line no-restricted-syntax + for (const index in value) { + if (regObj.test(value[index])) { + return true; + } + } + return false; } - } - return false; - } else { return regObj.test(value); + + // Adds single XOR support } - //Adds single XOR support - }else if ('xor' in reference) { - var compare = []; - if ( typeof value === "string" ) { - compare = value.split(/\r?\n\r?/); - } else if ( typeof(value) === "object" && value instanceof Array ) { - compare = value; - } - var eq_count = 0; - for (var key in reference.xor) { - if (reference.xor.hasOwnProperty(key) && $.inArray( reference.xor[key], compare) >= 0) { - eq_count++; + if ('xor' in reference) { + let compare = []; + if (typeof value === 'string') { + compare = value.split(/\r?\n\r?/); + } else if (typeof value === 'object' && value instanceof Array) { + compare = value; + } + let eqCount = 0; + // eslint-disable-next-line no-restricted-syntax + for (const key in reference.xor) { + if ( + reference.xor.hasOwnProperty(key) && + $.inArray(reference.xor[key], compare) >= 0 + ) { + eqCount += 1; + } } + return eqCount % 2 === 1; } - return eq_count % 2 == 1; - } - else { return reference.indexOf(value) !== false; - } - } - //The fix for compare strings wrapped by control symbols - Drupal.states.Dependent.comparisons.String = function ( reference, value ) { - if ( value && value.constructor.name == 'Array' ) { - for (var index in value) { - if (_compare2(reference, value[index])) { - return true; - } - } - return false; - } else { + }; + // The fix for compare strings wrapped by control symbols + Drupal.states.Dependent.comparisons.String = (reference, value) => { + if (value && value.constructor.name === 'Array') { + // eslint-disable-next-line no-restricted-syntax + for (const index in value) { + if (_compare2(reference, value[index])) { + return true; + } + } + return false; + } return _compare2(reference, value); - } + }; } - } - } -}; - - /** - * The function for compare two strings - * @param a - * @param b - * @returns {boolean|*} - * @private - */ - function _compare2(a, b) { - a = typeof a == "string" ? a.replace(/(^[\n\r]+|[\n\r]+$)/g, '') : a; - b = typeof b == "string" ? b.replace(/(^[\n\r]+|[\n\r]+$)/g, '') : b; - if (a === b) { - return typeof a === 'undefined' ? a : true; - } - - return typeof a === 'undefined' || typeof b === 'undefined'; - } + }, + }; })(jQuery, Drupal); diff --git a/logo.png b/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e35fe915086bca6dce838519ce5ddb3e102992f1 Binary files /dev/null and b/logo.png differ diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000000000000000000000000000000000000..3818cb44bb9de64a1c416c1505cbdad6b9f442a4 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,17 @@ +parameters: + ignoreErrors: + + - + message: "#^Variable \\$selectors in empty\\(\\) is never defined\\.$#" + count: 1 + path: src/Plugin/conditional_fields/handler/TextAreaFormatted.php + + - + message: "#^Undefined variable\\: \\$selectors$#" + count: 1 + path: src/Plugin/conditional_fields/handler/TextAreaFormatted.php + + - + message: "#^Variable \\$regex in empty\\(\\) is never defined\\.$#" + count: 1 + path: src/Plugin/conditional_fields/handler/LanguageSelect.php diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000000000000000000000000000000000000..178523f2ba1b4546e04d5c027fbcd324e4f74177 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,5 @@ +includes: + - phpstan-baseline.neon + +parameters: + level: 1 diff --git a/src/ConditionalFieldsElementAlterHelper.php b/src/ConditionalFieldsElementAlterHelper.php index c6d86bd5e1b88f59f13927debc5c7e9b613dd6b0..3c5f0265ed59be688447d3337ae88397c44248dd 100644 --- a/src/ConditionalFieldsElementAlterHelper.php +++ b/src/ConditionalFieldsElementAlterHelper.php @@ -4,6 +4,8 @@ namespace Drupal\conditional_fields; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormStateInterface; /** @@ -11,10 +13,31 @@ use Drupal\Core\Form\FormStateInterface; */ class ConditionalFieldsElementAlterHelper { + /** + * The module handler. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface + */ + protected $moduleHandler; + + /** + * Provides an interface for entity type managers. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + /** * ConditionalFieldsElementAlterHelper constructor. + * + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The module handler. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. */ - public function __construct() { + public function __construct(ModuleHandlerInterface $module_handler, EntityTypeManagerInterface $entity_type_manager) { + $this->moduleHandler = $module_handler; + $this->entityTypeManager = $entity_type_manager; } /** @@ -43,6 +66,8 @@ class ConditionalFieldsElementAlterHelper { return $element; } + $is_related_to_paragraph = FALSE; + $full_form = &$form_state->getCompleteForm(); // Some fields do not have entity type and bundle properties. // In this case we try to use the properties from the form. @@ -69,13 +94,16 @@ class ConditionalFieldsElementAlterHelper { $bundle = $entity->bundle(); $entity_type = $entity->getEntityTypeId(); - /** - * @deprecated Not actual from Drupal 8.7.0. - * Media entity returns the actual bundle object, rather than id - */ + // Deprecated, not actual from Drupal 8.7.0. + // Media entity returns the actual bundle object, rather than id. if (is_object($bundle) && method_exists($bundle, 'getPluginId')) { $bundle = $bundle->getPluginId(); } + + $paragraph_bundle = $this->getParagraphBundle($field, $form); + $bundle = $paragraph_bundle ?: $bundle; + $is_related_to_paragraph = (bool) $paragraph_bundle; + $entity_type = $is_related_to_paragraph ? 'paragraph' : $entity_type; } } } @@ -123,19 +151,57 @@ class ConditionalFieldsElementAlterHelper { return $element; } $field_name = reset($field['#array_parents']); + + // We get the name of the field inside the the paragraph where the + // conditions are being applied, instead of the field name where the + // paragraph is. + if ($is_related_to_paragraph) { + foreach ($field['#array_parents'] as $parent) { + if (isset($dependencies['dependents'][$parent])) { + $field_name = $parent; + break; + } + + if (isset($dependencies['dependees'][$parent])) { + $field_name = $parent; + break; + } + } + + if ($parent != $field_name || $first_parent == $field_name || !isset($field['#type'])) { + return $element; + } + } + + $paragraph_info = []; + + if ($is_related_to_paragraph) { + $paragraph_info['entity_type'] = $entity_type; + $paragraph_info['bundle'] = $bundle; + $paragraph_info['paragraph_field'] = $first_parent; + $paragraph_info['array_parents'] = $element['#array_parents']; + } + // Attach dependent. if (isset($dependencies['dependents'][$field_name])) { foreach ($dependencies['dependents'][$field_name] as $id => $dependency) { if (!isset($form['#conditional_fields'][$field_name]['dependees'][$id]) || $this->isPriorityField($field)) { - $this->attachDependency($form, $form_state, ['#field_name' => $dependency['dependee']], $field, $dependency['options'], $id); + if ($is_related_to_paragraph) { + $paragraph_info['field'] = $field_name; + } + $this->attachDependency($form, $form_state, ['#field_name' => $dependency['dependee']], $field, $dependency['options'], $id, $paragraph_info); } } } + // Attach dependee. if (isset($dependencies['dependees'][$field_name])) { foreach ($dependencies['dependees'][$field_name] as $id => $dependency) { if (!isset($form['#conditional_fields'][$field_name]['dependents'][$id]) || $this->isPriorityField($field)) { - $this->attachDependency($form, $form_state, $field, ['#field_name' => $dependency['dependent']], $dependency['options'], $id); + if ($is_related_to_paragraph) { + $paragraph_info['field'] = $field_name; + } + $this->attachDependency($form, $form_state, $field, ['#field_name' => $dependency['dependent']], $dependency['options'], $id, $paragraph_info); } } } @@ -143,6 +209,32 @@ class ConditionalFieldsElementAlterHelper { return $element; } + /** + * Gets the paragraph's bundle from a form field. + */ + public function getParagraphBundle($field, $form) { + $closest_parent = []; + $last_subform = FALSE; + + // Finds closest subform position. + foreach ($field['#array_parents'] as $index => $parent) { + if ($parent === 'subform') { + $last_subform = $index; + } + } + + if (!$last_subform) { + return FALSE; + } + + // Gets the route to the closest subform. + $closest_parent = array_slice($field['#array_parents'], 0, $last_subform); + // Gets the paragraph's bundle if any... + $bundle = NestedArray::getValue($form, array_merge($closest_parent, ['#paragraph_type'])); + + return $bundle && !is_array($bundle) ? $bundle : FALSE; + } + /** * Loads all dependencies from the database for a given bundle. */ @@ -150,7 +242,8 @@ class ConditionalFieldsElementAlterHelper { static $dependency_helpers; $dependency_key = $entity_type . '.' . $bundle; if (!isset($dependency_helpers[$dependency_key])) { - $dependency_helpers[$dependency_key] = new DependencyHelper($entity_type, $bundle); + $dependency_helpers[$dependency_key] = + new DependencyHelper($entity_type, $bundle, $this->moduleHandler, $this->entityTypeManager); } return $dependency_helpers[$dependency_key]->getBundleDependencies(); } @@ -158,7 +251,8 @@ class ConditionalFieldsElementAlterHelper { /** * Checking if field is priority for rewrite the conditions. * - * If the field widget is datelist this function help to return correct object for this field. + * If the field widget is datelist this function help to return correct object + * for this field. * * @param array $field * The field form element. @@ -171,7 +265,7 @@ class ConditionalFieldsElementAlterHelper { 'datelist', ]; // For modules supports. - \Drupal::moduleHandler()->alter(['conditional_fields_priority_field'], $priority_fields); + $this->moduleHandler->alter(['conditional_fields_priority_field'], $priority_fields); if (isset($field['#type']) && in_array($field['#type'], $priority_fields)) { return TRUE; @@ -187,14 +281,16 @@ class ConditionalFieldsElementAlterHelper { * * @param array $form * The form where the dependency is attached. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. * @param string $dependee * The dependee field form element. Either a string identifying the element - * key in the form, or a fully built field array. Actually used properties of - * the array are #field_name and #parents. + * key in the form, or a fully built field array. Actually used properties + * of the array are #field_name and #parents. * @param string $dependent * The dependent field form element. Either a string identifying the element - * key in the form, or a fully built field array. Actually used properties of - * the array are #field_name and #field_parents. + * key in the form, or a fully built field array. Actually used properties + * of the array are #field_name and #field_parents. * @param array $options * An array of dependency options with the following key/value pairs: * - state: The state applied to the dependent when the dependency is @@ -202,42 +298,49 @@ class ConditionalFieldsElementAlterHelper { * - condition: The condition for the dependency to be triggered. See * conditionalFieldsConditions() for available conditions. * - values_set: One of the following constants: - * - ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_WIDGET: Dependency is - * triggered if the dependee has a certain value defined in 'value'. - * - ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_AND: Dependency is triggered if - * the dependee has all the values defined in 'values'. - * - ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_OR: Dependency is triggered if the - * dependee has any of the values defined in 'values'. - * - ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_XOR: Dependency is triggered if - * the dependee has only one of the values defined in 'values'. - * - ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_NOT: Dependency is triggered if - * the dependee does not have any of the values defined in 'values'. + * - ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_WIDGET: + * Dependency is triggered if the dependee has a certain value defined + * in 'value'. + * - ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_AND: + * Dependency is triggered if the dependee has all the values defined in + * 'values'. + * - ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_OR: + * Dependency is triggered if the dependee has any of the values defined + * in 'values'. + * - ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_XOR: + * Dependency is triggered if the dependee has only one of the values + * defined in 'values'. + * - ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_NOT: + * Dependency is triggered if the dependee does not have any of the + * values defined in 'values'. * - value: The value to be tested when 'values_set' is - * ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_WIDGET. An associative array with - * the same structure of the dependee field values as found in - * $form_states['values] when the form is submitted. You can use - * field_default_extract_form_values() to extract this array. + * ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_WIDGET. + * An associative array with the same structure of the dependee field + * values as found in $form_states['values] when the form is submitted. + * You can use field_default_extract_form_values() to extract this array. * - values: The array of values to be tested when 'values_set' is not * ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_WIDGET. - * - value_form: An associative array with the same structure of the dependee - * field values as found in $form_state['input']['value']['field'] when the - * form is submitted. + * - value_form: An associative array with the same structure of the + * dependee field values as found in + * $form_state['input']['value']['field'] when the form is submitted. * - effect: The jQuery effect associated to the state change. See * conditionalFieldsEffects() for available effects and options. * - effect_options: The options for the active effect. * - selector: (optional) Custom jQuery selector for the dependee. * @param int $id - * (internal use) The identifier for the dependency. Omit this parameter when - * attaching a custom dependency. + * (internal use) The identifier for the dependency. Omit this parameter + * when attaching a custom dependency. + * @param array $paragraph_info + * @todo Document parameter. * * Note that you don't need to manually set all these options, since default * settings are always provided. */ - public function attachDependency(array &$form, &$form_state, $dependee, $dependent, array $options, $id = 0) { + public function attachDependency(array &$form, &$form_state, $dependee, $dependent, array $options, $id = 0, $paragraph_info = []) { // The absence of the $id parameter identifies a custom dependency. if (!$id) { - // String values are accepted to simplify usage of this function with custom - // forms. + // String values are accepted to simplify usage of this function with + // custom forms. if (is_string($dependee) && is_string($dependent)) { $dependee = [ '#field_name' => $dependee, @@ -261,9 +364,19 @@ class ConditionalFieldsElementAlterHelper { // Attach dependee. // Use the #array_parents property of the dependee instead of #field_parents // since we will need access to the full structure of the widget. - if (isset($dependee['#parents'])) { - $form['#conditional_fields'][$dependee['#parents'][0]]['parents'] = $dependee['#array_parents']; - $form['#conditional_fields'][$dependee['#parents'][0]]['dependents'][$id] = [ + if (isset($dependee['#array_parents'])) { + + $dependee_index = $dependee['#parents'][0]; + if ($paragraph_info) { + $dependee_index = conditional_fields_get_simpler_id($dependee['#id']); + } + + $form['#conditional_fields'][$dependee_index]['index'] = $dependee_index; + $form['#conditional_fields'][$dependee_index]['base'] = $dependee_index; + + $form['#conditional_fields'][$dependee_index]['is_from_paragraph'] = (bool) $paragraph_info; + $form['#conditional_fields'][$dependee_index]['parents'] = $dependee['#array_parents']; + $form['#conditional_fields'][$dependee_index]['dependents'][$id] = [ 'dependent' => $dependent['#field_name'], 'options' => $options, ]; @@ -272,8 +385,8 @@ class ConditionalFieldsElementAlterHelper { // Attach dependent. if (!empty($dependent['#parents'])) { $dependent_parents = $dependent['#parents']; - // If the field type is Date, we need to remove the last "date" parent key, - // since it is not part of the $form_state value when we validate it. + // If the field type is Date, we need to remove the last "date" parent + // key, since it is not part of the $form_state value when we validate it. if (isset($dependent['#type']) && $dependent['#type'] === 'date') { array_pop($dependent_parents); } @@ -281,9 +394,21 @@ class ConditionalFieldsElementAlterHelper { elseif (isset($dependent['#field_parents'])) { $dependent_parents = $dependent['#field_parents']; } + if (isset($dependent_parents)) { - $form['#conditional_fields'][$dependent['#parents'][0]]['field_parents'] = $dependent_parents; - $form['#conditional_fields'][$dependent['#parents'][0]]['dependees'][$id] = [ + $dependent_index = $dependent['#parents'][0]; + + if ($paragraph_info) { + $dependent_index = conditional_fields_get_simpler_id($dependent['#id']); + } + + $form['#conditional_fields'][$dependent_index]['is_from_paragraph'] = (bool) $paragraph_info; + + $form['#conditional_fields'][$dependent_index]['index'] = $dependent_index; + + $form['#conditional_fields'][$dependent_index]['field_parents'] = $dependent_parents; + $form['#conditional_fields'][$dependent_index]['array_parents'] = $paragraph_info['array_parents'] ?? []; + $form['#conditional_fields'][$dependent_index]['dependees'][$id] = [ 'dependee' => $dependee['#field_name'], 'options' => $options, ]; diff --git a/src/ConditionalFieldsFormHelper.php b/src/ConditionalFieldsFormHelper.php index a6cab60e61a8769e612c81b9b2fb5cea292aeeae..e95a534cfa586815b05706d3438d7176c5d1bd28 100644 --- a/src/ConditionalFieldsFormHelper.php +++ b/src/ConditionalFieldsFormHelper.php @@ -3,13 +3,14 @@ namespace Drupal\conditional_fields; use Drupal\Component\Render\MarkupInterface; +use Drupal\Component\Utility\Html; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Entity\EntityDisplayRepositoryInterface; use Drupal\Core\Field\WidgetBase; use Drupal\Core\Form\FormStateInterface; -use Drupal\field\Entity\FieldStorageConfig; +use Drupal\Core\Language\LanguageManager; use Drupal\Core\Render\ElementInfoManager; -use Drupal\Core\Entity\EntityFormInterface; +use Drupal\field\Entity\FieldStorageConfig; /** * Helper to interact with forms. @@ -28,7 +29,7 @@ class ConditionalFieldsFormHelper { * * @var \Drupal\Core\Form\FormStateInterface */ - public $form_state; + public $formState; /** * Array of effects for being applied to the conditional fields in this form. @@ -58,6 +59,13 @@ class ConditionalFieldsFormHelper { */ protected $entityDisplayRepository; + /** + * The LanguageManager service. + * + * @var \Drupal\Core\Language\LanguageManager + */ + protected $languageManager; + /** * ConditionalFieldsFormHelper constructor. * @@ -67,11 +75,14 @@ class ConditionalFieldsFormHelper { * A manager for conditional fields handlers. * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository * The entity display repository. + * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager + * The language manager. */ - public function __construct(ElementInfoManager $element_info, ConditionalFieldsHandlersManager $type, EntityDisplayRepositoryInterface $entity_display_repository) { + public function __construct(ElementInfoManager $element_info, ConditionalFieldsHandlersManager $type, EntityDisplayRepositoryInterface $entity_display_repository, LanguageManager $language_manager) { $this->elementInfo = $element_info; $this->type = $type; $this->entityDisplayRepository = $entity_display_repository; + $this->languageManager = $language_manager; } /** @@ -91,7 +102,7 @@ class ConditionalFieldsFormHelper { */ public function afterBuild(array $form, FormStateInterface &$form_state) { $this->form = $form; - $this->form_state = $form_state; + $this->formState = $form_state; if ($this->hasConditionalFields()) { $this->processDependentFields() @@ -102,6 +113,16 @@ class ConditionalFieldsFormHelper { return $this->form; } + /** + * Returns the "base name" for a field id. + * + * Returns $name until the last subform appears to relate field ids + * from paragraphs on the #conditional_fields array. + */ + private static function getBaseName($name) { + return implode('subform', array_slice(explode('subform', $name), 0, -1)) . 'subform-'; + } + /** * Build and attach #states properties to dependent fields. */ @@ -117,10 +138,20 @@ class ConditionalFieldsFormHelper { } $dependees = $dependent_info['dependees']; - $dependent_location = array_merge([], [$dependent]); + $dependent_location = ($dependent_info['is_from_paragraph'] ?? FALSE) ? + $dependent_info['array_parents'] : + array_merge([], [$dependent]); + $dependent_form_field = NestedArray::getValue($this->form, $dependent_location); - $states = $this->processDependeeFields($dependees, $dependent_form_field, $dependent_location, $states); + if ($dependent_info['is_from_paragraph'] ?? FALSE) { + $base_name = $this->getBaseName($dependent); + } + else { + $base_name = ''; + } + + $states = $this->processDependeeFields($dependees, $dependent_form_field, $dependent_location, $states, $base_name ?? ''); if (empty($states)) { continue; @@ -131,20 +162,49 @@ class ConditionalFieldsFormHelper { // radio button), and there is a checkbox or radio button deeper in the // array, we actually need to use the (deeper) checkbox or radio button // because it is not possible to set a checked state on a container. - if (count(array_intersect(['checked', '!checked'], array_keys($states))) > 0 - && $dependent_form_field['#type'] === 'container' - && isset($dependent_form_field['widget']['value']['#type']) - && in_array($dependent_form_field['widget']['value']['#type'], ['checkbox', 'radio']) + if (count(array_intersect([ + 'checked', + '!checked', + ], array_keys($states))) > 0 + && $dependent_form_field['#type'] === 'container' + && isset($dependent_form_field['widget']['value']['#type']) + && in_array($dependent_form_field['widget']['value']['#type'], [ + 'checkbox', + 'radio', + ]) ) { - $dependent_location = array_merge($dependent_location, ['widget', 'value']); + $dependent_location = array_merge($dependent_location, [ + 'widget', + 'value', + ]); $dependent_form_field = $dependent_form_field['widget']['value']; } // Save the modified field back into the form. NestedArray::setValue($this->form, $dependent_location, $dependent_form_field); + $states_location = $dependent_location; + while ($states_location && end($states_location) != 'subform') { + $last_field = array_pop($states_location); + } + + if (end($states_location) == 'subform' && isset($last_field)) { + $states_location[] = $last_field; + } + else { + $states_location = $dependent_location; + } + + $states_location = array_merge($states_location, ['#states']); + + // Merge states in case there are previous states defined. + $new_states = array_merge( + NestedArray::getValue($this->form, $states_location) ?? [], + $this->mapStates($states) + ); + // Add the #states property to the dependent field. - NestedArray::setValue($this->form, array_merge($dependent_location, ['#states']), $this->mapStates($states)); + NestedArray::setValue($this->form, $states_location, $new_states); } return $this; @@ -153,11 +213,15 @@ class ConditionalFieldsFormHelper { /** * Determine and register dependee field effects. */ - public function processDependeeFields($dependees, &$dependent_form_field = [], $dependent_location = [], $states = []) { + public function processDependeeFields($dependees, &$dependent_form_field = [], $dependent_location = [], $states = [], $base_name = '') { // Cycle the dependant's dependees. foreach ($dependees as $dependency) { $dependee = $dependency['dependee']; + if ($base_name) { + $dependee = $base_name . HTML::getId($dependee); + } + if (empty($this->form['#conditional_fields'][$dependee])) { continue; } @@ -171,9 +235,9 @@ class ConditionalFieldsFormHelper { } if (isset($this->form[$dependee]['#attributes']) - && $this->form[$dependee]['#attributes']['class'][0] == 'field--type-list-string' - && isset($this->form[$dependee]['widget']['#type']) - && $this->form[$dependee]['widget']['#type'] == 'checkboxes') { + && $this->form[$dependee]['#attributes']['class'][0] == 'field--type-list-string' + && isset($this->form[$dependee]['widget']['#type']) + && $this->form[$dependee]['widget']['#type'] == 'checkboxes') { array_pop($dependee_info['parents']); } @@ -240,7 +304,7 @@ class ConditionalFieldsFormHelper { $this->form['#validate'][] = [self::class, 'formValidate']; // Initialize validation information every time the form is rendered to // avoid stale data after a failed submission. - $this->form_state->setValue('conditional_fields_untriggered_dependents', []); + $this->formState->setValue('conditional_fields_untriggered_dependents', []); return $this; } @@ -262,16 +326,19 @@ class ConditionalFieldsFormHelper { */ protected function getState($dependee, array $dependee_form_field, array $options) { // Get the build info from form_state. - $build_info = $this->form_state->getBuildInfo(); + $build_info = $this->formState->getBuildInfo(); // If this form is an entity_browser_form, the form display must be built // from the form attributes. EntityBrowserForm doesn't have a getFormDisplay // method to call. if (isset($build_info['base_form_id']) && $build_info['base_form_id'] === 'entity_browser_form') { - $form_display = $this->entityDisplayRepository->getFormDisplay($this->form['#entity_type'], $this->form['#bundle'], $this->form['#form_mode']); + $form_display = $this->entityDisplayRepository + ->getFormDisplay($this->form['#entity_type'], $this->form['#bundle'], $this->form['#form_mode']); } else { /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */ - $form_display = $this->form_state->getFormObject()->getFormDisplay($this->form_state); + $form_display = $this->formState + ->getFormObject() + ->getFormDisplay($this->formState); } $state = []; @@ -279,9 +346,38 @@ class ConditionalFieldsFormHelper { // Conditions different than "value" are always evaluated against TRUE. $state = [$options['state'] => [$options['selector'] => [$options['condition'] => TRUE]]]; } - else { + elseif (isset($dependee_form_field['#name'])) { $widget_id = ''; - $field_name = explode('[', $dependee_form_field['#name']); + + // If the name has a subform in it, we should get information on its + // parent element to find out if it is a paragraph. + if (strpos($dependee_form_field['#name'], '[subform]') !== FALSE) { + $subform_exploded = explode('[subform][', $dependee_form_field['#name']); + $first_field = \explode('[', $subform_exploded[0])[0]; + $field_name = explode('][', end($subform_exploded)); + $storage = \Drupal::service('entity_type.manager') + ->getStorage('entity_form_display'); + $parent_widget_parents = $dependee_form_field['#array_parents']; + + while ($parent_widget_parents && end($parent_widget_parents) !== 'subform') { + array_pop($parent_widget_parents); + } + array_pop($parent_widget_parents); + $parent_info = NestedArray::getValue($this->formState->getCompleteForm(), $parent_widget_parents); + } + + // For paragraphs we must change the form display. + if (isset($parent_info['#paragraph_type'])) { + $form_settings = $form_display->getComponent($first_field)['settings']; + $form_display_mode = $form_settings['form_display_mode']; + $paragraph_type = $parent_info['#paragraph_type']; + $form_display = $storage->load("paragraph.$paragraph_type.$form_display_mode"); + $dependee = $field_name[0]; + } + else { + $field_name = explode('[', $dependee_form_field['#name']); + } + $dependee_form_state = isset($dependee_form_field['#field_parents'], $field_name[0], $this->form_state) ? WidgetBase::getWidgetState($dependee_form_field['#field_parents'], $field_name[0], $this->form_state) : NULL; $dependee_form_field['#original_name'] = $field_name[0]; $dependee_display = $form_display->getComponent($dependee); @@ -291,10 +387,11 @@ class ConditionalFieldsFormHelper { // If inline entity form is used, pass the form mode for getFormDisplay // and get the widget ID from field. - if ($widget_id === '' && isset($dependee_form_field['#field_parents']) && in_array('inline_entity_form', $dependee_form_field['#field_parents'])){ + if ($widget_id === '' && isset($dependee_form_field['#field_parents']) && in_array('inline_entity_form', $dependee_form_field['#field_parents'])) { $ief = $form_display->getComponent($dependee_form_field['#field_parents'][0]); - // Inject type and bundle for ECK-based entities. This should probably be fixed in ECK itself. + // Inject type and bundle for ECK-based entities. This should probably + // be fixed in ECK itself. if (isset($this->form["#entity"])) { $entity = $this->form["#entity"]; $dependee_form_field['#entity_type'] = $entity->getEntityTypeId(); @@ -350,9 +447,9 @@ class ConditionalFieldsFormHelper { if (empty($this->form['#conditional_fields'])) { return FALSE; } - if (!method_exists($this->form_state->getFormObject(), 'getFormDisplay')) { + if (!method_exists($this->formState->getFormObject(), 'getFormDisplay')) { // Get the build info from form_state. - $build_info = $this->form_state->getBuildInfo(); + $build_info = $this->formState->getBuildInfo(); // If this is an entity_browser_form, we can process conditional fields. if (isset($build_info['base_form_id']) && $build_info['base_form_id'] === 'entity_browser_form') { return TRUE; @@ -373,8 +470,8 @@ class ConditionalFieldsFormHelper { } else { // Replace the language placeholder in the selector with current language. - $current_language = \Drupal::languageManager()->getCurrentLanguage()->getId(); - $language = isset($dependee_form_field['#language']) ? $dependee_form_field['#language'] : $current_language; + $current_language = $this->languageManager->getCurrentLanguage()->getId(); + $language = $dependee_form_field['#language'] ?? $current_language; $selector = str_replace('%lang', $language, $options_selector); } return $selector; @@ -453,6 +550,7 @@ class ConditionalFieldsFormHelper { $form = NestedArray::getValue($form, $inline_entity_form_parents['element_parents']); } + /** @var \Drupal\Core\Entity\ContentEntityFormInterface $entity_form */ // Get the build info from form_state. $build_info = $form_state->getBuildInfo(); // If this form is an entity_browser_form, the entity type will have to be @@ -463,7 +561,10 @@ class ConditionalFieldsFormHelper { $entity_type_id = $form['#entity_type']; } else { - $entity_type_id = $form_state->getFormObject()->getEntity()->getEntityTypeId(); + $entity_type_id = $form_state + ->getFormObject() + ->getEntity() + ->getEntityTypeId(); } if ($inline_entity_form_parents) { @@ -471,7 +572,15 @@ class ConditionalFieldsFormHelper { $dependent = $form['#conditional_fields'][reset($ief_element['#array_parents'])]; } else { - $dependent = $form['#conditional_fields'][reset($element['#array_parents'])]; + $dependent = $form['#conditional_fields'][reset($element['#array_parents'])] ?? FALSE; + $conditional_field_key = conditional_fields_get_simpler_id($element['#id']); + $element['#type'] !== 'container' && $dependent = $dependent ?: $form['#conditional_fields'][$conditional_field_key]; + + // @todo if there are not dependents, something might be wrong, + // however, this also avoids potential fatal errors. + if (!$dependent) { + return; + } } // Check if this field's dependencies were triggered. @@ -495,24 +604,57 @@ class ConditionalFieldsFormHelper { unset($input_state['add_more']); } $input_state = (is_null($input_state)) ? [] : $input_state; - if (isset($dependent['field_parents'][0])) { - $field = FieldStorageConfig::loadByName($entity_type_id, $dependent['field_parents'][0]); + // Get the containing subform in the parents array. + $subform_key = \array_search('subform', array_reverse($dependent['array_parents'], TRUE), TRUE); + $field = NULL; + if ($subform_key !== FALSE) { + $subform_array = NestedArray::getValue($form, array_slice($dependent['array_parents'], 0, $subform_key + 1)); + $entity_type = $subform_array['#entity_type']; + $field_name = $dependent['array_parents'][$subform_key + 1]; + $field = FieldStorageConfig::loadByName($entity_type, $field_name); } else { - $field = NULL; - } - if (empty($input_state)) { - if (isset($element['widget']['#title'])) { - $title = $element['widget']['#title']; + if (isset($dependent['field_parents'][0])) { + $field = FieldStorageConfig::loadByName($entity_type_id, $dependent['field_parents'][0]); } - elseif (isset($dependent['field_parents'][0])) { - $title = $dependent['field_parents'][0]; - } - elseif ($field) { - $title = $field->getName(); + else { + $field = NULL; } - $form_state->setError($element, t('%name is required.', ['%name' => $title])); + if (empty($input_state)) { + if (isset($element['widget']['#title'])) { + $title = $element['widget']['#title']; + } + elseif (isset($dependent['field_parents'][0])) { + $title = $subform_key === FALSE ? $dependent['field_parents'][0] : $field_name; + } + elseif ($field) { + $title = $field->getName(); + } + else { + $title = t('Missing title'); + } + + // Gets the deepest element to set the error. + $element_to_set_error = + $element['widget'][0]['value'] ?? + $element['widget'][0] ?? + $element['widget'] ?? + $element; + + if (isset($element_to_set_error['#title'])) { + $title = $element_to_set_error['#title']; + } + + if ($element_to_set_error['#access'] ?? TRUE) { + if ($element_to_set_error['#type'] == 'hidden') { + $element_to_set_error = NestedArray::getValue($form, array_slice($element_to_set_error['#array_parents'], 0, -1)); + $title = $element_to_set_error['#title']; + } + + $form_state->setError($element_to_set_error, t('%name is required.', ['%name' => $title])); + } + } } } } @@ -536,6 +678,10 @@ class ConditionalFieldsFormHelper { $form_state_addition['reset'] = FALSE; } + // Store dependent to remove validation errors previously set. + // See: ConditionalFieldsFormHelper::formValidate(). + $form_state_addition['dependent'] = $dependent; + // Tag validation errors previously set on this field for removal in // ConditionalFieldsFormHelper::formValidate(). $errors = $form_state->getErrors(); @@ -558,10 +704,10 @@ class ConditionalFieldsFormHelper { return; } - $fiel_state_values_count = count($form_state->getValue('conditional_fields_untriggered_dependents')); + $field_state_values_count = count($form_state->getValue('conditional_fields_untriggered_dependents')); $form_state->setValue([ 'conditional_fields_untriggered_dependents', - $fiel_state_values_count, + $field_state_values_count, ], $form_state_addition); } @@ -576,24 +722,38 @@ class ConditionalFieldsFormHelper { * The state of the form to evaluate dependencies on. * @param bool $grouping * TRUE to evaluate grouping; FALSE otherwise. + * @param array $inline_entity_form_parents + * Paths of the inline_entity_form, the result of the function + * findInlineEntityFormParentsForElement(). * * @return array|bool * Evaluated dependencies array. */ protected static function evaluateDependencies(array $dependent, array $form, FormStateInterface $form_state, $grouping = TRUE, $inline_entity_form_parents = NULL) { - $dependencies = $form['#conditional_fields'][reset($dependent['field_parents'])]['dependees']; + if ($dependent['is_from_paragraph']) { + $dependencies = $form['#conditional_fields'][$dependent['index']]['dependees']; + $base_name = self::getBaseName($dependent['index']); + } + else { + $dependencies = $form['#conditional_fields'][reset($dependent['field_parents'])]['dependees']; + } $evaluated_dependees = []; foreach ($dependencies as $dependency) { // Extract field values from submitted values. $dependee = $dependency['dependee']; + $dependee_key = $dependee; + + if (isset($base_name)) { + $dependee_key = $base_name . HTML::getId($dependee); + } // Skip any misconfigured conditions. - if (empty($form['#conditional_fields'][$dependee]['parents'])) { + if (empty($form['#conditional_fields'][$dependee_key]['parents'])) { continue; } - $dependee_parents = $form['#conditional_fields'][$dependee]['parents']; + $dependee_parents = $form['#conditional_fields'][$dependee_key]['parents']; // We have the parents of the field, but depending on the entity type and // the widget type, they may include additional elements that are actually @@ -601,10 +761,23 @@ class ConditionalFieldsFormHelper { // structure and use the parents only up to that depth. $dependee_parents_keys = array_flip($dependee_parents); $dependee_parent = NestedArray::getValue($form, array_slice($dependee_parents, 0, $dependee_parents_keys[$dependee])); - $values = self::formFieldGetValues($dependee_parent[$dependee], $form_state, $inline_entity_form_parents); - if (isset($values['value']) && is_numeric($values['value'])) { - $values = $values['value']; + + if ($inline_entity_form_parents) { + $values = self::formFieldGetValues($dependee_parent[$dependee], $form_state, $inline_entity_form_parents); + if (isset($values['value']) && is_numeric($values['value'])) { + $values = $values['value']; + } } + else { + $form_state_values = $form_state->getValues(); + $dependee_element = NestedArray::getValue($form, $dependee_parents); + $values = NestedArray::getValue($form_state_values, $dependee_element['#parents']); + + if (is_array($values) && isset($values[0]['value'])) { + $values = $values[0]['value']; + } + } + // Remove the language key. if (isset($dependee_parent[$dependee]['#language'], $values[$dependee_parent[$dependee]['#language']])) { $values = $values[$dependee_parent[$dependee]['#language']]; @@ -619,7 +792,7 @@ class ConditionalFieldsFormHelper { } if ($grouping) { - return self::evaluateGrouping($evaluated_dependees[reset($dependent['field_parents'])]); + return self::evaluateGrouping($evaluated_dependees[reset($dependent['field_parents'])] ?? FALSE); } return $evaluated_dependees; @@ -659,22 +832,45 @@ class ConditionalFieldsFormHelper { return; } - $entity = $form_state->getFormObject()->getEntity(); $untriggered_dependents_errors = []; + $form_state_errors = $form_state->getErrors(); + + // Tag errors from untriggered fields to remove them later. + $untriggered_dependents = $form_state->getValue('conditional_fields_untriggered_dependents'); + foreach ($untriggered_dependents as &$field) { + $error_key_arr = NestedArray::getValue($form, $field['parents'])['#parents'] ?? []; + $error_key = implode('][', $error_key_arr ?? []); + if ($error_key && isset($form_state_errors[$error_key])) { + $field['errors'][$error_key] = $form_state_errors[$error_key]; + } + } - foreach ($form_state->getValue('conditional_fields_untriggered_dependents') as $field) { - $parent = [$field['parents'][0]]; - $dependent = NestedArray::getValue($form, $parent); - if (!$dependent) { - continue; + foreach ($untriggered_dependents as $field) { + // When there is a subform, the parent location is different. + $subform_location = \array_search('subform', $field['dependent']['array_parents'], TRUE); + if ($subform_location !== FALSE) { + $dependent = NestedArray::getValue($form, $field['dependent']['array_parents']); + $parents = $dependent['#parents']; + $field_name = end($parents); + $route_to_parent = array_slice($dependent['#parents'], 0, -1); + $field_values_location = NestedArray::getValue($form_state->getValues(), $route_to_parent); + $dependent_parents = $dependent['#parents']; } - $field_values_location = self::formFieldGetValues($dependent, $form_state); + else { + $parent = [$field['parents'][0]]; + $dependent = NestedArray::getValue($form, $parent); + $field_values_location = self::formFieldGetValues($dependent, $form_state); + + $route_to_parent = array_slice($dependent['#parents'], 0, -1); + $field_values_location = NestedArray::getValue($form_state->getValues(), $route_to_parent); - $dependent_field_name = reset($dependent['#array_parents']); + $dependent_parents = $dependent['#parents']; + $field_name = reset($dependent['#array_parents']); + } // If we couldn't find a location for the field's submitted values, let // the validation errors pass through to avoid security holes. - if (empty($field_values_location)) { + if (!isset($field_values_location[$field_name])) { if (!empty($field['errors'])) { $untriggered_dependents_errors = array_merge($untriggered_dependents_errors, $field['errors']); } @@ -686,13 +882,8 @@ class ConditionalFieldsFormHelper { // that the values are located at // $form_state['values'][ ... $element['#parents'] ... ], while the // documentation of hook_field_widget_form() states that field values are - // // $form_state['values'][ ... $element['#field_parents'] ... ]. - // NestedArray::setValue($form_state['values'], $dependent['#field_parents'], $field_values_location); - if (!empty($field['reset'])) { - $default = $entity->getFieldDefinition($dependent_field_name)->getDefaultValue($entity); - // Save the changed array back in place. - $form_state->setValue($dependent_field_name, $default); - } + // $form_state['values'][ ... $element['#field_parents'] ... ]. + NestedArray::setValue($form_state->getValues(), $dependent_parents, $field_values_location[$field_name]); if (!empty($field['errors'])) { $untriggered_dependents_errors = array_merge($untriggered_dependents_errors, $field['errors']); @@ -766,7 +957,9 @@ class ConditionalFieldsFormHelper { $dependency_values = $context == 'view' ? $options['value'] : $options['value_form']; if ($options['condition'] === '!empty') { - $values = (isset($values[0]['value'])) ? $values[0]['value'] : $values; + if (is_array($values)) { + $values = (isset($values[0]['value'])) ? $values[0]['value'] : $values; + } $values = ($values === '_none') ? '' : $values; return (!empty($values)) ? TRUE : FALSE; } @@ -869,7 +1062,7 @@ class ConditionalFieldsFormHelper { // Regular expression method. if ($options['values_set'] == ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_REGEX) { foreach ($reference_values as $reference_value) { - if (!preg_match('/' . $options['regex'] . '/', $reference_value)) { + if (!preg_match('/' . $options['regex'] . '/', (string) $reference_value)) { return FALSE; } } @@ -1024,7 +1217,8 @@ class ConditionalFieldsFormHelper { return FALSE; } - // We need to find last embedded inline_entity_form, but array_search can search only first. + // We need to find last embedded inline_entity_form, but array_search can + // search only first. $inline_entity_form_level = count($element['#array_parents']) - 1 - array_search('inline_entity_form', array_reverse($element['#array_parents']), TRUE); $result['element_parents'] = array_slice($element['#array_parents'], 0, $inline_entity_form_level + 1); diff --git a/src/ConditionalFieldsHandlersManager.php b/src/ConditionalFieldsHandlersManager.php index 980caae7379135877b4eae35a327320608ddb305..12014588f526d7820616d2fb862f8d440e18077d 100644 --- a/src/ConditionalFieldsHandlersManager.php +++ b/src/ConditionalFieldsHandlersManager.php @@ -2,13 +2,13 @@ namespace Drupal\conditional_fields; -use Drupal\Component\Plugin\Factory\DefaultFactory; +use Drupal\Component\Plugin\Discovery\StaticDiscovery; +use Drupal\Component\Plugin\Discovery\StaticDiscoveryDecorator; use Drupal\Component\Plugin\FallbackPluginManagerInterface; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Plugin\DefaultPluginManager; -use Drupal\Component\Plugin\Discovery\StaticDiscovery; -use Drupal\Component\Plugin\Discovery\StaticDiscoveryDecorator; +use Drupal\Core\Plugin\Factory\ContainerFactory; use Drupal\Core\StringTranslation\TranslatableMarkup; /** @@ -32,7 +32,7 @@ class ConditionalFieldsHandlersManager extends DefaultPluginManager implements F $this->alterInfo('handler_info'); $this->setCacheBackend($cache_backend, 'handler_plugins'); - $this->factory = new DefaultFactory($this->getDiscovery()); + $this->factory = new ContainerFactory($this->getDiscovery()); } /** diff --git a/src/Conditions.php b/src/Conditions.php index cd9a347f6b4dc6110097ba4f37fa45486072720a..ae6cc8949e5be1e2b1ce3c04bebb936c2ff74f0e 100644 --- a/src/Conditions.php +++ b/src/Conditions.php @@ -2,8 +2,8 @@ namespace Drupal\conditional_fields; -use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Provide conditional field's lists. @@ -93,7 +93,7 @@ class Conditions { * Builds a list of supported effects. * * That may be applied to a dependent field - * when it changes from visible to invisible and viceversa. The effects may + * when it changes from visible to invisible and vice versa. The effects may * have options that will be passed as Javascript settings and used by * conditional_fields.js. * diff --git a/src/Controller/ConditionalFieldController.php b/src/Controller/ConditionalFieldController.php index 74ac7848bdc84204242df631dd2ef5b651859ddf..956e961923aef300210a076579dfff0a940ea559 100644 --- a/src/Controller/ConditionalFieldController.php +++ b/src/Controller/ConditionalFieldController.php @@ -2,7 +2,6 @@ namespace Drupal\conditional_fields\Controller; -use Drupal\conditional_fields\Form\ConditionalFieldFormTab; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Entity\ContentEntityType; use Drupal\Core\Entity\EntityFieldManagerInterface; @@ -10,6 +9,7 @@ use Drupal\Core\Entity\EntityTypeBundleInfoInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Url; +use Drupal\conditional_fields\Form\ConditionalFieldFormTab; /** * Returns responses for conditional_fields module routes. @@ -216,6 +216,19 @@ class ConditionalFieldController extends ControllerBase { return $this->formBuilder->getForm(ConditionalFieldFormTab::class, 'media', $media_type); } + /** + * Provide arguments for ConditionalFieldFormTab. + * + * @param string $paragraphs_type + * Paragraphs type. + * + * @return array + * Form array. + */ + public function getParagraphEditFormTab($paragraphs_type) { + return $this->formBuilder->getForm(ConditionalFieldFormTab::class, 'paragraph', $paragraphs_type); + } + /** * Provide arguments for ConditionalFieldFormTab. * diff --git a/src/DependencyHelper.php b/src/DependencyHelper.php index 8299d6848fb3e1f0dff5123d5af8deb40832a1ca..432164c9919bdf51b7598d8b4226ef39551b2dc2 100644 --- a/src/DependencyHelper.php +++ b/src/DependencyHelper.php @@ -2,6 +2,9 @@ namespace Drupal\conditional_fields; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; + /** * Resolve conditional field's dependencies. */ @@ -12,7 +15,7 @@ class DependencyHelper { * * @var string */ - protected $entity_type; + protected $entityType; /** * The current bundle name. @@ -33,7 +36,7 @@ class DependencyHelper { * * @var array */ - protected $dependent_field; + protected $dependentField; /** * Full list of dependencies. @@ -47,7 +50,7 @@ class DependencyHelper { * * @var array */ - protected $dependent_fields; + protected $dependentFields; /** * UUID of the current dependency. @@ -75,21 +78,28 @@ class DependencyHelper { * * @var array */ - protected $form_fields; + protected $formFields; /** * Fields that support inheritance. * * @var array */ - protected $inheriting_fields; + protected $inheritingFields; /** * The module handler service. * * @var \Drupal\Core\Extension\ModuleHandlerInterface */ - protected $module_handler; + protected $moduleHandler; + + /** + * Entity manager service. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; /** * Constructor method. @@ -98,11 +108,16 @@ class DependencyHelper { * An entity type name. * @param string $bundle * A bundle name. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The module handler. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. */ - public function __construct(string $entity_type, string $bundle) { - $this->entity_type = $entity_type; + public function __construct(string $entity_type, string $bundle, ModuleHandlerInterface $module_handler, EntityTypeManagerInterface $entity_type_manager) { + $this->entityType = $entity_type; $this->bundle = $bundle; - $this->module_handler = \Drupal::moduleHandler(); + $this->moduleHandler = $module_handler; + $this->entityTypeManager = $entity_type_manager; } /** @@ -110,10 +125,10 @@ class DependencyHelper { */ public function getAvailableConditionalFields() { $hook = 'conditional_fields'; - $fields = $this->module_handler - ->invokeAll($hook, [$this->entity_type, $this->bundle]); - $this->module_handler - ->alter($hook, $fields, $this->entity_type, $this->bundle); + $fields = $this->moduleHandler + ->invokeAll($hook, [$this->entityType, $this->bundle]); + $this->moduleHandler + ->alter($hook, $fields, $this->entityType, $this->bundle); return $fields; } @@ -121,10 +136,10 @@ class DependencyHelper { * Return dependencies for a given bundle. */ public function getBundleDependencies() { - if (!isset($this->dependencies[$this->entity_type][$this->bundle])) { + if (!isset($this->dependencies[$this->entityType][$this->bundle])) { $this->resolveBundleDependencies($this->getBundleDependentFields()); } - return $this->dependencies ? $this->dependencies[$this->entity_type][$this->bundle] : NULL; + return $this->dependencies ? $this->dependencies[$this->entityType][$this->bundle] : NULL; } /** @@ -140,7 +155,7 @@ class DependencyHelper { protected function resolveBundleDependencies($dependent_fields) { foreach ($dependent_fields as $dependent => $field) { $this->dependent = $dependent; - $this->dependent_field = $field; + $this->dependentField = $field; $this->resolveFieldDependencies(); } } @@ -149,7 +164,7 @@ class DependencyHelper { * Resolve a field's dependencies. */ protected function resolveFieldDependencies() { - foreach ($this->dependent_field['third_party_settings']['conditional_fields'] as $uuid => $conditional_field) { + foreach ($this->dependentField['third_party_settings']['conditional_fields'] as $uuid => $conditional_field) { $this->uuid = $uuid; $this->dependee = $conditional_field['dependee']; $this->settings = $conditional_field['settings']; @@ -198,11 +213,11 @@ class DependencyHelper { * Return fields with conditional settings to inherit. */ protected function getInheritingFields() { - if (empty($this->dependent_field['third_party_settings']['conditional_fields'][$this->uuid])) { + if (empty($this->dependentField['third_party_settings']['conditional_fields'][$this->uuid])) { return []; } - $propagating_settings = $this->dependent_field['third_party_settings']['conditional_fields'][$this->uuid]; + $propagating_settings = $this->dependentField['third_party_settings']['conditional_fields'][$this->uuid]; $inheriting_fields = []; foreach ($this->getInheritingFieldNames($this->dependent) as $field_name) { $inheriting_field = $this->getBundleFormField($field_name); @@ -220,24 +235,24 @@ class DependencyHelper { * Return a list of fields to inherit conditional settings. */ protected function getInheritingFieldNames($parent_field) { - if (!isset($this->inheriting_fields)) { - $this->inheriting_fields = $this->getInheritingChildren(); + if (!isset($this->inheritingFields)) { + $this->inheritingFields = $this->getInheritingChildren(); } - if (!isset($this->inheriting_fields[$parent_field])) { + if (!isset($this->inheritingFields[$parent_field])) { return []; } - return $this->inheriting_fields[$parent_field]; + return $this->inheritingFields[$parent_field]; } /** - * Determine all fields that support inheritence, and their children. + * Determine all fields that support inheritance, and their children. */ protected function getInheritingChildren() { $hook = 'conditional_fields_children'; - $inheriting_fields = $this->module_handler - ->invokeAll($hook, [$this->entity_type, $this->bundle]); - $this->module_handler - ->alter($hook, $inheriting_fields, $this->entity_type, $this->bundle); + $inheriting_fields = $this->moduleHandler + ->invokeAll($hook, [$this->entityType, $this->bundle]); + $this->moduleHandler + ->alter($hook, $inheriting_fields, $this->entityType, $this->bundle); return $inheriting_fields; } @@ -253,7 +268,7 @@ class DependencyHelper { * Add a dependent field to the list of dependencies. */ protected function registerDependent() { - $this->dependencies[$this->entity_type][$this->bundle]['dependents'][$this->dependent][$this->uuid] = [ + $this->dependencies[$this->entityType][$this->bundle]['dependents'][$this->dependent][$this->uuid] = [ 'dependee' => $this->dependee, 'options' => $this->settings, ]; @@ -263,7 +278,7 @@ class DependencyHelper { * Add a dependee field to the list of dependencies. */ protected function registerDependee() { - $this->dependencies[$this->entity_type][$this->bundle]['dependees'][$this->dependee][$this->uuid] = [ + $this->dependencies[$this->entityType][$this->bundle]['dependees'][$this->dependee][$this->uuid] = [ 'dependent' => $this->dependent, 'options' => $this->settings, ]; @@ -276,17 +291,17 @@ class DependencyHelper { if (!$this->bundleHasRegisteredDependentFields()) { $this->registerBundleDependentFields(); } - return $this->dependent_fields[$this->entity_type][$this->bundle]; + return $this->dependentFields[$this->entityType][$this->bundle]; } /** * Determine whether a bundle has registered any dependent fields. */ protected function bundleHasRegisteredDependentFields() { - if (!isset($this->dependent_fields[$this->entity_type][$this->bundle])) { + if (!isset($this->dependentFields[$this->entityType][$this->bundle])) { return FALSE; } - if (empty($this->dependent_fields[$this->entity_type][$this->bundle])) { + if (empty($this->dependentFields[$this->entityType][$this->bundle])) { return FALSE; } return TRUE; @@ -296,12 +311,12 @@ class DependencyHelper { * Register all dependent fields attached to a bundle. */ protected function registerBundleDependentFields() { - $this->dependent_fields[$this->entity_type][$this->bundle] = []; + $this->dependentFields[$this->entityType][$this->bundle] = []; foreach ($this->getBundleFormFields() as $name => $field) { if (!$this->hasConditionalFields($field)) { continue; } - $this->dependent_fields[$this->entity_type][$this->bundle][$name] = $field; + $this->dependentFields[$this->entityType][$this->bundle][$name] = $field; } } @@ -309,13 +324,13 @@ class DependencyHelper { * Return a field attached to a bundle. */ protected function getBundleFormField($field_name) { - if (!isset($this->form_fields)) { - $this->form_fields = $this->getBundleFormFields(); + if (!isset($this->formFields)) { + $this->formFields = $this->getBundleFormFields(); } - if (!isset($this->form_fields[$field_name])) { + if (!isset($this->formFields[$field_name])) { return []; } - return $this->form_fields[$field_name]; + return $this->formFields[$field_name]; } /** @@ -323,9 +338,9 @@ class DependencyHelper { */ protected function getBundleFormFields() { /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $entity */ - $entity = \Drupal::entityTypeManager() + $entity = $this->entityTypeManager ->getStorage('entity_form_display') - ->load($this->entity_type . '.' . $this->bundle . '.default'); + ->load($this->entityType . '.' . $this->bundle . '.default'); if (!$entity) { return []; diff --git a/src/Form/ConditionalFieldDeleteForm.php b/src/Form/ConditionalFieldDeleteForm.php index 8338da90004162425464c70deb8117a6aa8bf983..5d5eb996639d38e7575042c9e01ce04ac745c1e5 100644 --- a/src/Form/ConditionalFieldDeleteForm.php +++ b/src/Form/ConditionalFieldDeleteForm.php @@ -2,9 +2,11 @@ namespace Drupal\conditional_fields\Form; -use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\ConfirmFormBase; +use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * A form to delete a conditional field. @@ -41,6 +43,19 @@ class ConditionalFieldDeleteForm extends ConfirmFormBase { */ private $uuid; + public function __construct( + protected EntityTypeManagerInterface $entityTypeManager, + ) {} + + /** + * {@inheritDoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity_type.manager'), + ); + } + /** * {@inheritdoc} */ @@ -75,7 +90,7 @@ class ConditionalFieldDeleteForm extends ConfirmFormBase { return; } /** @var \Drupal\Core\Entity\Entity\EntityFormDisplay $entity */ - $entity = \Drupal::entityTypeManager() + $entity = $this->entityTypeManager ->getStorage('entity_form_display') ->load($this->entityType . '.' . $this->bundle . '.default'); if (!$entity) { diff --git a/src/Form/ConditionalFieldDeleteFormTab.php b/src/Form/ConditionalFieldDeleteFormTab.php index 0b31f80c506ecd21f4f5f97dba30e74c7d551ecc..614102ec6f9570a5ec3d0d1f3bd1e13cc60148b7 100644 --- a/src/Form/ConditionalFieldDeleteFormTab.php +++ b/src/Form/ConditionalFieldDeleteFormTab.php @@ -17,7 +17,7 @@ class ConditionalFieldDeleteFormTab extends ConditionalFieldDeleteForm { * * @var string */ - protected $entity_type; + protected $entityType; /** * The bundle type this conditional field is attached to. @@ -30,8 +30,14 @@ class ConditionalFieldDeleteFormTab extends ConditionalFieldDeleteForm { * {@inheritdoc} */ public function getCancelUrl() { - return Url::fromRoute('conditional_fields.tab' . "." . $this->entity_type, [ - "{$this->entity_type}_type" => $this->bundle, + if ($this->entityType == 'paragraph') { + return Url::fromRoute('conditional_fields.tab' . "." . $this->entityType, [ + "{$this->entityType}s_type" => $this->bundle, + ]); + } + + return Url::fromRoute('conditional_fields.tab' . "." . $this->entityType, [ + "{$this->entityType}_type" => $this->bundle, ]); } @@ -46,7 +52,7 @@ class ConditionalFieldDeleteFormTab extends ConditionalFieldDeleteForm { * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, $entity_type = NULL, $bundle = NULL, $field_name = NULL, $uuid = NULL) { - $this->entity_type = $entity_type; + $this->entityType = $entity_type; $this->bundle = $bundle; return parent::buildForm($form, $form_state, $entity_type, $bundle, $field_name, $uuid); } diff --git a/src/Form/ConditionalFieldEditForm.php b/src/Form/ConditionalFieldEditForm.php index 84f8c11a70211ee38d5211bf48dddbb58c718321..64d7210c99190e24e854c55eac445aabfaf4efbe 100644 --- a/src/Form/ConditionalFieldEditForm.php +++ b/src/Form/ConditionalFieldEditForm.php @@ -3,16 +3,19 @@ namespace Drupal\conditional_fields\Form; use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException; -use Drupal\conditional_fields\ConditionalFieldsInterface; -use Drupal\conditional_fields\Conditions; -use Drupal\conditional_fields\DependencyHelper; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Form\FormState; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Logger\LoggerChannelInterface; use Drupal\Core\Render\Element; +use Drupal\Core\Utility\Error; +use Drupal\conditional_fields\ConditionalFieldsInterface; +use Drupal\conditional_fields\Conditions; +use Drupal\conditional_fields\DependencyHelper; use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -30,45 +33,24 @@ class ConditionalFieldEditForm extends FormBase { */ protected $redirectPath = 'conditional_fields.conditions_list'; - /** - * CF lists builder. - * - * @var \Drupal\conditional_fields\Conditions - */ - protected $list; - - /** - * Provides an interface for entity type managers. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; - - /** - * Provides an interface for form building and processing. - * - * @var \Drupal\Core\Form\FormBuilderInterface - */ - protected $formBuilder; - - /** - * Class constructor. - */ - public function __construct(Conditions $list, EntityTypeManagerInterface $entity_type_manager, FormBuilderInterface $form_builder) { - $this->list = $list; - $this->entityTypeManager = $entity_type_manager; - $this->formBuilder = $form_builder; - } + public function __construct( + protected Conditions $list, + protected EntityTypeManagerInterface $entityTypeManager, + protected FormBuilderInterface $formBuilder, + protected ModuleHandlerInterface $moduleHandler, + protected LoggerChannelInterface $logger, + ) {} /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { - // Instantiates this form class. return new static( $container->get('conditional_fields.conditions'), $container->get('entity_type.manager'), - $container->get('form_builder') + $container->get('form_builder'), + $container->get('module_handler'), + $container->get('logger.factory')->get('conditional_fields'), ); } @@ -234,7 +216,7 @@ class ConditionalFieldEditForm extends FormBase { '#description' => $this->t('The dependency is triggered when all the values of the dependee %field match the regular expression. The expression should be valid both in PHP and in Javascript. Do not include delimiters.', ['%field' => $label]) . '<br>' . $this->t('Note: If the dependee has allowed values, these are actually the keys, not the labels, of those values.'), '#maxlength' => 2048, '#size' => 120, - '#default_value' => isset($settings['regex']) ? $settings['regex'] : '', + '#default_value' => $settings['regex'] ?? '', '#states' => [ 'visible' => [ ':input[name="values_set"]' => ['value' => (string) ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_REGEX], @@ -575,7 +557,16 @@ class ConditionalFieldEditForm extends FormBase { $form_object->setEntity($dummy_entity); } catch (InvalidPluginDefinitionException $e) { - watchdog_exception('conditional_fields', $e); + // @todo Backwards compatibility of error logging. See + // https://www.drupal.org/node/2932520. This can be removed when we no + // longer support Drupal < 10.2. + if (version_compare(\Drupal::VERSION, '10.1', '>=')) { + Error::logException($this->logger, $e); + } + else { + // @phpstan-ignore-next-line + watchdog_exception('conditional_fields', $e); + } // @todo May be it make sense to return markup? return NULL; } @@ -612,7 +603,7 @@ class ConditionalFieldEditForm extends FormBase { */ protected function setFieldProperty(&$field, $property, $value) { $elements = Element::children($field); - if (isset($elements) && count($elements) > 0) { + if (count($elements) > 0) { foreach ($elements as $element) { $field[$element][$property] = $value; $this->setFieldProperty($field[$element], $property, $value); @@ -624,7 +615,7 @@ class ConditionalFieldEditForm extends FormBase { * Determine whether a field supports inheritance. */ protected function fieldSupportsInheritance($entity_type, $bundle, $field_name) { - $dependency_helper = new DependencyHelper($entity_type, $bundle); + $dependency_helper = new DependencyHelper($entity_type, $bundle, $this->moduleHandler, $this->entityTypeManager); return $dependency_helper->fieldHasChildren($field_name); } diff --git a/src/Form/ConditionalFieldEditFormTab.php b/src/Form/ConditionalFieldEditFormTab.php index 9dfc561a23e425dc2830161db9f15d34d2cf2781..df1327259e098c5ebc40b3b4d7b4b5ce73cf50e8 100644 --- a/src/Form/ConditionalFieldEditFormTab.php +++ b/src/Form/ConditionalFieldEditFormTab.php @@ -31,7 +31,12 @@ class ConditionalFieldEditFormTab extends ConditionalFieldEditForm { public function submitForm(array &$form, FormStateInterface $form_state) { parent::submitForm($form, $form_state); $values = $form_state->cleanValues()->getValues(); - $parameters = ["{$values['entity_type']}_type" => $values['bundle']]; + if ($values['entity_type'] == 'paragraph') { + $parameters = ["{$values['entity_type']}s_type" => $values['bundle']]; + } + else { + $parameters = ["{$values['entity_type']}_type" => $values['bundle']]; + } $redirect = $this->redirectPath . "." . $values['entity_type']; $form_state->setRedirect($redirect, $parameters); diff --git a/src/Form/ConditionalFieldForm.php b/src/Form/ConditionalFieldForm.php index f5dec8411877d6abeabf6bb714dd5230ac8e7afe..84ff74d4a3a45965b4758ca5baa59e8284fd1ba3 100644 --- a/src/Form/ConditionalFieldForm.php +++ b/src/Form/ConditionalFieldForm.php @@ -3,14 +3,15 @@ namespace Drupal\conditional_fields\Form; use Drupal\Component\Uuid\UuidInterface; -use Drupal\conditional_fields\Conditions; -use Drupal\conditional_fields\DependencyHelper; use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; +use Drupal\conditional_fields\Conditions; +use Drupal\conditional_fields\DependencyHelper; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -34,34 +35,6 @@ class ConditionalFieldForm extends FormBase { */ protected $deletePath = 'conditional_fields.delete_form'; - /** - * Uuid generator. - * - * @var \Drupal\Component\Uuid\UuidInterface - */ - protected $uuidGenerator; - - /** - * Provides an interface for an entity field manager. - * - * @var \Drupal\Core\Entity\EntityFieldManagerInterface - */ - protected $entityFieldManager; - - /** - * Provides an interface for entity type managers. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; - - /** - * CF lists builder. - * - * @var \Drupal\conditional_fields\Conditions - */ - protected $list; - /** * Form array. * @@ -74,56 +47,40 @@ class ConditionalFieldForm extends FormBase { * * @var \Drupal\Core\Form\FormStateInterface */ - protected $form_state; + protected $formState; /** * Name of the entity type being configured. * * @var string */ - protected $entity_type; + protected $entityType; /** * Name of the entity bundle being configured. * * @var string */ - protected $bundle_name; + protected $bundleName; - /** - * Class constructor. - * - * @param \Drupal\conditional_fields\Conditions $list - * Conditions list provider. - * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager - * Provides an interface for an entity field manager. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager - * Provides an interface for entity type managers. - * @param \Drupal\Component\Uuid\UuidInterface $uuid - * Uuid generator. - */ public function __construct( - Conditions $list, - EntityFieldManagerInterface $entity_field_manager, - EntityTypeManagerInterface $entity_type_manager, - UuidInterface $uuid - ) { - $this->entityFieldManager = $entity_field_manager; - $this->entityTypeManager = $entity_type_manager; - $this->list = $list; - $this->uuidGenerator = $uuid; - } + protected EntityFieldManagerInterface $entityFieldManager, + protected EntityTypeManagerInterface $entityTypeManager, + protected Conditions $list, + protected UuidInterface $uuidGenerator, + protected ModuleHandlerInterface $moduleHandler, + ) {} /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { - // Instantiates this form class. return new static( - $container->get('conditional_fields.conditions'), $container->get('entity_field.manager'), $container->get('entity_type.manager'), - $container->get('uuid') + $container->get('conditional_fields.conditions'), + $container->get('uuid'), + $container->get('module_handler'), ); } @@ -139,18 +96,18 @@ class ConditionalFieldForm extends FormBase { */ public function buildForm(array $form, FormStateInterface $form_state, $entity_type = NULL, $bundle = NULL) { $this->form = $form; - $this->form_state = $form_state; - $this->entity_type = $entity_type; - $this->bundle_name = $bundle; + $this->formState = $form_state; + $this->entityType = $entity_type; + $this->bundleName = $bundle; $this->form['entity_type'] = [ '#type' => 'hidden', - '#value' => $this->entity_type, + '#value' => $this->entityType, ]; $this->form['bundle'] = [ '#type' => 'hidden', - '#value' => $this->bundle_name, + '#value' => $this->bundleName, ]; $this->buildTable(); @@ -163,16 +120,13 @@ class ConditionalFieldForm extends FormBase { */ public function validateForm(array &$form, FormStateInterface $form_state) { $table = $form_state->getValue('table'); - if (empty($table['add_new_dependency']) || !is_array($table['add_new_dependency'])) { - parent::validateForm($form, $form_state); - } $conditional_values = $table['add_new_dependency']; if (array_key_exists('dependee', $conditional_values) && array_key_exists('dependent', $conditional_values) ) { $dependent = $conditional_values['dependent']; - $state = isset($conditional_values['state']) ? $conditional_values['state'] : NULL; + $state = $conditional_values['state'] ?? NULL; $instances = $this->entityFieldManager ->getFieldDefinitions($form_state->getValue('entity_type'), $form_state->getValue('bundle')); @@ -191,7 +145,6 @@ class ConditionalFieldForm extends FormBase { } } } - parent::validateForm($form, $form_state); } /** @@ -219,10 +172,6 @@ class ConditionalFieldForm extends FormBase { */ public function submitForm(array &$form, FormStateInterface $form_state) { $table = $form_state->getValue('table'); - if (empty($table['add_new_dependency']) || !is_array($table['add_new_dependency'])) { - parent::submitForm($form, $form_state); - } - $field_names = []; $form_state->set('plugin_settings_edit', NULL); @@ -291,8 +240,8 @@ class ConditionalFieldForm extends FormBase { protected function buildTable() { $table = [ '#type' => 'table', - '#entity_type' => $this->entity_type, - '#bundle_name' => $this->bundle_name, + '#entity_type' => $this->entityType, + '#bundle_name' => $this->bundleName, '#header' => [ $this->t('Target field'), $this->t('Controlled by'), @@ -308,12 +257,12 @@ class ConditionalFieldForm extends FormBase { /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display_entity */ $form_display_entity = $this->entityTypeManager ->getStorage('entity_form_display') - ->load("$this->entity_type.$this->bundle_name.default"); + ->load("$this->entityType.$this->bundleName.default"); - if (empty($form_display_entity) && $this->entity_type == 'taxonomy_term') { + if (is_null($form_display_entity) && $this->entityType == 'taxonomy_term') { $form_display_entity = $this->entityTypeManager->getStorage('entity_form_display')->create([ 'targetEntityType' => 'taxonomy_term', - 'bundle' => $this->bundle_name, + 'bundle' => $this->bundleName, 'mode' => 'default', 'status' => TRUE, ]); @@ -431,7 +380,7 @@ class ConditionalFieldForm extends FormBase { * Build options list of available fields. */ protected function getFieldsList() { - $dependency_helper = new DependencyHelper($this->entity_type, $this->bundle_name); + $dependency_helper = new DependencyHelper($this->entityType, $this->bundleName, $this->moduleHandler, $this->entityTypeManager); $fields = []; foreach ($dependency_helper->getAvailableConditionalFields() as $name => $label) { $fields[$name] = $label . ' (' . $name . ')'; diff --git a/src/Plugin/conditional_fields/handler/Checkbox.php b/src/Plugin/conditional_fields/handler/Checkbox.php index 9f2f41ec71ed119b34fe8c58c14668c912e300a9..d7a59df05b927a9bc35a3a6089127884bbd8d3d1 100644 --- a/src/Plugin/conditional_fields/handler/Checkbox.php +++ b/src/Plugin/conditional_fields/handler/Checkbox.php @@ -60,7 +60,7 @@ class Checkbox extends ConditionalFieldsHandlerBase { * Values for triggering events. */ public function getWidgetValue(array $value_form) { - return isset($value_form[0]['value']) ? $value_form[0]['value'] : $value_form; + return $value_form[0]['value'] ?? $value_form; } } diff --git a/src/Plugin/conditional_fields/handler/DateDefault.php b/src/Plugin/conditional_fields/handler/DateDefault.php index c63a44f41bbd1c54e4c99b4a0308706b966cd0b1..18b3f31f4d7d83ebeb2434adecdd870d6c7a6f63 100644 --- a/src/Plugin/conditional_fields/handler/DateDefault.php +++ b/src/Plugin/conditional_fields/handler/DateDefault.php @@ -2,9 +2,9 @@ namespace Drupal\conditional_fields\Plugin\conditional_fields\handler; +use Drupal\Core\Datetime\DrupalDateTime; use Drupal\conditional_fields\ConditionalFieldsHandlerBase; use Drupal\conditional_fields\ConditionalFieldsInterface; -use Drupal\Core\Datetime\DrupalDateTime; use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface; /** diff --git a/src/Plugin/conditional_fields/handler/DateList.php b/src/Plugin/conditional_fields/handler/DateList.php index e7167084a31e4c49c626c3bfea2850a1bd76b41b..0d8c19166b3049191d0ebec18a4988cf02152e08 100644 --- a/src/Plugin/conditional_fields/handler/DateList.php +++ b/src/Plugin/conditional_fields/handler/DateList.php @@ -2,9 +2,9 @@ namespace Drupal\conditional_fields\Plugin\conditional_fields\handler; +use Drupal\Core\Datetime\DrupalDateTime; use Drupal\conditional_fields\ConditionalFieldsHandlerBase; use Drupal\conditional_fields\ConditionalFieldsInterface; -use Drupal\Core\Datetime\DrupalDateTime; /** * Provides states handler for date lists. @@ -42,12 +42,12 @@ class DateList extends ConditionalFieldsHandlerBase { $parts = preg_split($pattern, $options['regex']); if (is_array($parts)) { $date_patterns = [ - 'year' => isset($parts[0]) ? $parts[0] : '.*', - 'month' => isset($parts[1]) ? $parts[1] : '.*', - 'day' => isset($parts[2]) ? $parts[2] : '.*', - 'hour' => isset($parts[3]) ? $parts[3] : '.*', - 'minute' => isset($parts[4]) ? $parts[4] : '.*', - 'second' => isset($parts[5]) ? $parts[5] : '.*', + 'year' => $parts[0] ?? '.*', + 'month' => $parts[1] ?? '.*', + 'day' => $parts[2] ?? '.*', + 'hour' => $parts[3] ?? '.*', + 'minute' => $parts[4] ?? '.*', + 'second' => $parts[5] ?? '.*', ]; if (isset($field['#value']) && is_array($field['#value'])) { foreach ($field['#value'] as $key => $default_value) { diff --git a/src/Plugin/conditional_fields/handler/DefaultStateHandler.php b/src/Plugin/conditional_fields/handler/DefaultStateHandler.php index 39d2290db1ef2c5e6a7b7b10e2879ddaf52798b4..0dec4c8159481ce40c2e239a8966a16bf12f9b94 100644 --- a/src/Plugin/conditional_fields/handler/DefaultStateHandler.php +++ b/src/Plugin/conditional_fields/handler/DefaultStateHandler.php @@ -25,7 +25,7 @@ class DefaultStateHandler extends ConditionalFieldsHandlerBase { switch ($values_set) { case ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_WIDGET: - /** @todo This change fixes problem within inline_entity_form fields. + /* @todo This change fixes problem within inline_entity_form fields. * `[$options['condition']]` is removed because 'value_form' already * contain condition name as key. * But this need to be retested not to break any previous functionality. diff --git a/src/Plugin/conditional_fields/handler/EmailDefault.php b/src/Plugin/conditional_fields/handler/EmailDefault.php index 988aca2c03e38c06d86b78ae34c60cf5890deb6a..dd391047e8a4d8c96daa12fe643f7a033aecc47a 100644 --- a/src/Plugin/conditional_fields/handler/EmailDefault.php +++ b/src/Plugin/conditional_fields/handler/EmailDefault.php @@ -61,7 +61,9 @@ class EmailDefault extends ConditionalFieldsHandlerBase { ]; } - $state[$options['state']][] = $input_states; + if (isset($input_states)) { + $state[$options['state']][] = $input_states; + } break; default: diff --git a/src/Plugin/conditional_fields/handler/EntityReference.php b/src/Plugin/conditional_fields/handler/EntityReference.php index 85a0bec1ab966f0faafa65a90235c304ff8df22d..4a3ac07cc46204e08779ced37770192b377b98cc 100644 --- a/src/Plugin/conditional_fields/handler/EntityReference.php +++ b/src/Plugin/conditional_fields/handler/EntityReference.php @@ -2,9 +2,12 @@ namespace Drupal\conditional_fields\Plugin\conditional_fields\handler; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\conditional_fields\ConditionalFieldsHandlerBase; use Drupal\conditional_fields\ConditionalFieldsInterface; -use Drupal\Core\Entity\EntityInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides states handler for entity reference fields. @@ -13,7 +16,31 @@ use Drupal\Core\Entity\EntityInterface; * id = "states_handler_entity_reference_autocomplete", * ) */ -class EntityReference extends ConditionalFieldsHandlerBase { +class EntityReference extends ConditionalFieldsHandlerBase implements ContainerFactoryPluginInterface { + + /** + * Provides an interface for entity type managers. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * Constructs an entity reference states handler. + * + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager service. + */ + final public function __construct(EntityTypeManagerInterface $entity_type_manager) { + $this->entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritDoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static($container->get('entity_type.manager')); + } /** * {@inheritdoc} @@ -28,7 +55,7 @@ class EntityReference extends ConditionalFieldsHandlerBase { if (empty($value_form)) { break; } - $entity_type = \Drupal::entityTypeManager()->getStorage($field["#target_type"]); + $entity_type = $this->entityTypeManager->getStorage($field["#target_type"]); if ($options['field_cardinality'] == 1) { $entity = $entity_type->load($value_form[0]['target_id']); $state[$options['state']][$options['selector']] = $this->getAutocompleteSuggestions($entity); diff --git a/src/Plugin/conditional_fields/handler/LinkField.php b/src/Plugin/conditional_fields/handler/LinkField.php index 97759df4d6dc78a8920e335a8f443db3b8743bbc..a384d51af05a326d053275e781d07b64d78a0748 100644 --- a/src/Plugin/conditional_fields/handler/LinkField.php +++ b/src/Plugin/conditional_fields/handler/LinkField.php @@ -98,7 +98,7 @@ class LinkField extends ConditionalFieldsHandlerBase { $displayable_string = $uri_reference; } elseif ($scheme === 'entity') { - list($entity_type, $entity_id) = explode('/', substr($uri, 7), 2); + [$entity_type, $entity_id] = explode('/', substr($uri, 7), 2); // Show the 'entity:' URI as the entity autocomplete would. $entity_type_manager = \Drupal::entityTypeManager(); if ($entity_type_manager->getDefinition($entity_type, FALSE) && $entity = $entity_type_manager->getStorage($entity_type)->load($entity_id)) { diff --git a/src/Plugin/conditional_fields/handler/Select.php b/src/Plugin/conditional_fields/handler/Select.php index a45963df9f4f4be421312673efd419dbb4ef53ba..91a260f5ae137df3e594d1f6be84769f79b6e55d 100644 --- a/src/Plugin/conditional_fields/handler/Select.php +++ b/src/Plugin/conditional_fields/handler/Select.php @@ -33,12 +33,7 @@ class Select extends ConditionalFieldsHandlerBase { return $this->widgetCase($field, $options); case ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_AND: - if (isset($state[$options['state']][$options['selector']]['value'])) { - $state[$options['state']][$options['selector']]['value'] = (array) $state[$options['state']][$options['selector']]['value']; - } - else { - $state[$options['state']][$options['selector']]['value'] = $values_array; - } + $state[$options['state']][$options['selector']]['value'] = $values_array; break; case ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_XOR: diff --git a/src/Plugin/conditional_fields/handler/TextAreaFormated.php b/src/Plugin/conditional_fields/handler/TextAreaFormatted.php similarity index 97% rename from src/Plugin/conditional_fields/handler/TextAreaFormated.php rename to src/Plugin/conditional_fields/handler/TextAreaFormatted.php index 65671eb9b4accf9866a7d764e97e954875dc7e03..3eede57f1b70548f9cbe25e7db0d838914a38fcb 100644 --- a/src/Plugin/conditional_fields/handler/TextAreaFormated.php +++ b/src/Plugin/conditional_fields/handler/TextAreaFormatted.php @@ -12,7 +12,7 @@ use Drupal\conditional_fields\ConditionalFieldsInterface; * id = "states_handler_text_textarea_with_summary", * ) */ -class TextAreaFormated extends ConditionalFieldsHandlerBase { +class TextAreaFormatted extends ConditionalFieldsHandlerBase { /** * {@inheritdoc} diff --git a/src/Plugin/conditional_fields/handler/TextDefault.php b/src/Plugin/conditional_fields/handler/TextDefault.php index fe6c0bf32592c1f3250a7df7a39b796c1c505f2a..89d0a78f910b9c38bd624a8076cb0668c0b18d94 100644 --- a/src/Plugin/conditional_fields/handler/TextDefault.php +++ b/src/Plugin/conditional_fields/handler/TextDefault.php @@ -62,7 +62,9 @@ class TextDefault extends ConditionalFieldsHandlerBase { $options['condition'] => $values_array, ]; } - $state[$options['state']] = $input_states; + if (isset($input_states)) { + $state[$options['state']] = $input_states; + } break; default: diff --git a/src/Plugin/conditional_fields/handler/extra_contrib/Shs.php b/src/Plugin/conditional_fields/handler/extra_contrib/Shs.php index 824caaad3d234b158782ad131f4778e5e78729b9..d39dba1c7ee74e5839d5ceb07467ad88153f0978 100644 --- a/src/Plugin/conditional_fields/handler/extra_contrib/Shs.php +++ b/src/Plugin/conditional_fields/handler/extra_contrib/Shs.php @@ -2,8 +2,6 @@ namespace Drupal\conditional_fields\Plugin\conditional_fields\handler\extra_contrib; -use Drupal\conditional_fields\ConditionalFieldsHandlerBase; -use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\conditional_fields\Plugin\conditional_fields\handler\Select; /** diff --git a/tests/src/FunctionalJavascript/ConditionalFieldCheckboxesTest.php b/tests/src/FunctionalJavascript/ConditionalFieldCheckboxesTest.php index bdbbbb5d14884bfc30b736252b2db5141462f01b..b277d7006b078076f2584720da8f5a128a1fe4c6 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldCheckboxesTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldCheckboxesTest.php @@ -2,12 +2,12 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; -use Drupal\conditional_fields\ConditionalFieldsInterface; -use Drupal\Tests\field\Traits\EntityReferenceTestTrait; -use Drupal\taxonomy\Entity\Vocabulary; -use Drupal\taxonomy\Entity\Term; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; +use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait; +use Drupal\conditional_fields\ConditionalFieldsInterface; +use Drupal\taxonomy\Entity\Term; +use Drupal\taxonomy\Entity\Vocabulary; /** * Test Conditional Fields Checkboxes Plugin. @@ -16,7 +16,7 @@ use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFi */ class ConditionalFieldCheckboxesTest extends ConditionalFieldTestBase implements ConditionalFieldValueInterface { - use EntityReferenceTestTrait; + use EntityReferenceFieldCreationTrait; /** * {@inheritdoc} diff --git a/tests/src/FunctionalJavascript/ConditionalFieldDateListTest.php b/tests/src/FunctionalJavascript/ConditionalFieldDateListTest.php index 6361e9453f5924997d3a67b9d0d9c8755674a32b..cf74cf5625f16d7917d7e47a83fdbb4e4638ac23 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldDateListTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldDateListTest.php @@ -2,13 +2,13 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; +use Drupal\Core\Datetime\DrupalDateTime; +use Drupal\Core\Entity\Entity\EntityFormDisplay; +use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\Core\Entity\Entity\EntityFormDisplay; -use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; -use Drupal\Core\Datetime\DrupalDateTime; /** * Test Conditional Fields States. diff --git a/tests/src/FunctionalJavascript/ConditionalFieldDateTimeTest.php b/tests/src/FunctionalJavascript/ConditionalFieldDateTimeTest.php index 51610b85fe27e11100411735dd9265cbf52ff43b..e03d9ac22dd1ce4859fdbac281c7298c8ea3f12a 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldDateTimeTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldDateTimeTest.php @@ -2,15 +2,15 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; -use Drupal\conditional_fields\ConditionalFieldsInterface; +use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Entity\Display\EntityDisplayInterface; +use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Entity\Entity\EntityViewDisplay; +use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; +use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\Core\Entity\Entity\EntityFormDisplay; -use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; -use Drupal\Core\Datetime\DrupalDateTime; /** * Test Conditional Fields States. diff --git a/tests/src/FunctionalJavascript/ConditionalFieldEmailTest.php b/tests/src/FunctionalJavascript/ConditionalFieldEmailTest.php index ff36307c3549cdad1b37c96e10382113a0842bf2..498d525a06d3caf42bb9e794176fcd724512e964 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldEmailTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldEmailTest.php @@ -2,12 +2,12 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; -use Drupal\conditional_fields\ConditionalFieldsInterface; -use Drupal\field\Entity\FieldConfig; -use Drupal\field\Entity\FieldStorageConfig; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldFilledEmptyInterface; use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; +use Drupal\conditional_fields\ConditionalFieldsInterface; +use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; /** * Test Conditional Fields Text Handler. diff --git a/tests/src/FunctionalJavascript/ConditionalFieldEntityReferenceTagsTest.php b/tests/src/FunctionalJavascript/ConditionalFieldEntityReferenceTagsTest.php index f526654e3a6cd25ab5b42475ec6acf0f635ed40c..bd57b4b93aeb2ab673e7dd3cd1df77ed1fb19239 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldEntityReferenceTagsTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldEntityReferenceTagsTest.php @@ -2,11 +2,11 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; -use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\Core\Entity\Entity\EntityFormDisplay; -use Drupal\Tests\field\Traits\EntityReferenceTestTrait; -use Drupal\node\Entity\Node; use Drupal\Tests\RandomGeneratorTrait; +use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait; +use Drupal\conditional_fields\ConditionalFieldsInterface; +use Drupal\node\Entity\Node; /** * Test Conditional Fields Entity Reference Tags Plugin. @@ -15,7 +15,7 @@ use Drupal\Tests\RandomGeneratorTrait; */ class ConditionalFieldEntityReferenceTagsTest extends ConditionalFieldTestBase { - use EntityReferenceTestTrait; + use EntityReferenceFieldCreationTrait; use RandomGeneratorTrait; /** diff --git a/tests/src/FunctionalJavascript/ConditionalFieldEntityReferenceTest.php b/tests/src/FunctionalJavascript/ConditionalFieldEntityReferenceTest.php index 6e003693988445babd414e453e3fbd0ae2fdd3bb..8f7da9f026aa09df71e6fbf3b243bc9d07ae8dae 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldEntityReferenceTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldEntityReferenceTest.php @@ -2,13 +2,13 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; -use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\Core\Entity\Entity\EntityFormDisplay; -use Drupal\Tests\field\Traits\EntityReferenceTestTrait; -use Drupal\node\Entity\Node; +use Drupal\Tests\RandomGeneratorTrait; use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldFilledEmptyInterface; use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; -use Drupal\Tests\RandomGeneratorTrait; +use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait; +use Drupal\conditional_fields\ConditionalFieldsInterface; +use Drupal\node\Entity\Node; /** * Test Conditional Fields Entity Reference Plugin. @@ -17,7 +17,7 @@ use Drupal\Tests\RandomGeneratorTrait; */ class ConditionalFieldEntityReferenceTest extends ConditionalFieldTestBase implements ConditionalFieldValueInterface, ConditionalFieldFilledEmptyInterface { - use EntityReferenceTestTrait; + use EntityReferenceFieldCreationTrait; use RandomGeneratorTrait; /** @@ -105,7 +105,7 @@ class ConditionalFieldEntityReferenceTest extends ConditionalFieldTestBase imple $referenced_format_1 = sprintf("%s (%d)", $node->label(), $node->id()); $referenced_format_2 = sprintf("%s", $node->label()); - $referenced_format_wrong = sprintf("%s ", $node->label(), $node->id()); + $referenced_format_wrong = sprintf("%s ", $node->label()); // Visit a ConditionalFields configuration page for Content bundles. $this->createCondition('body', 'field_' . $this->fieldName, 'visible', 'value'); diff --git a/tests/src/FunctionalJavascript/ConditionalFieldLanguageSelectTest.php b/tests/src/FunctionalJavascript/ConditionalFieldLanguageSelectTest.php index 6de2de1fde96800d54e2d87520a7554bf184952f..b0ee5b826387704e9d2ffee97a7605331cee5cfe 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldLanguageSelectTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldLanguageSelectTest.php @@ -2,9 +2,9 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; +use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\language\Entity\ContentLanguageSettings; -use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; /** * Test Conditional Fields Language Select Plugin. diff --git a/tests/src/FunctionalJavascript/ConditionalFieldLinkFieldTest.php b/tests/src/FunctionalJavascript/ConditionalFieldLinkFieldTest.php index eea46e4e0ea9e212e8002c534031c3dcb8a0622a..c44ac896112c4740a1444ddadc308922d59e3bdd 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldLinkFieldTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldLinkFieldTest.php @@ -2,13 +2,13 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; -use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\Core\Entity\Entity\EntityFormDisplay; +use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldFilledEmptyInterface; +use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; +use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; use Drupal\link\LinkItemInterface; -use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldFilledEmptyInterface; -use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; /** * Test Conditional Fields Link field plugin. @@ -16,8 +16,8 @@ use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFi * @group conditional_fields */ class ConditionalFieldLinkFieldTest extends ConditionalFieldTestBase implements - ConditionalFieldValueInterface, - ConditionalFieldFilledEmptyInterface { + ConditionalFieldValueInterface, + ConditionalFieldFilledEmptyInterface { /** * {@inheritdoc} diff --git a/tests/src/FunctionalJavascript/ConditionalFieldNumberTest.php b/tests/src/FunctionalJavascript/ConditionalFieldNumberTest.php index ec3a23aadb7cf4baedc72a1758f695e8fc2f5ee4..a36fc082f4e66b93fae8c9313d3f0ba4d8c85298 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldNumberTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldNumberTest.php @@ -2,12 +2,12 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; -use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\Core\Entity\Entity\EntityFormDisplay; +use Drupal\Tests\RandomGeneratorTrait; +use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; +use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; -use Drupal\Tests\RandomGeneratorTrait; /** * Test Conditional Fields Number Plugin. diff --git a/tests/src/FunctionalJavascript/ConditionalFieldParagraphsTest.php b/tests/src/FunctionalJavascript/ConditionalFieldParagraphsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ec79c33521c84e0ebfc680d38eb8d062aa455133 --- /dev/null +++ b/tests/src/FunctionalJavascript/ConditionalFieldParagraphsTest.php @@ -0,0 +1,600 @@ +<?php + +namespace Drupal\Tests\conditional_fields\FunctionalJavascript; + +use Drupal\Core\Entity\Entity\EntityFormDisplay; +use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldFilledEmptyInterface; +use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; +use Drupal\conditional_fields\ConditionalFieldsInterface; +use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; +use Drupal\paragraphs\Entity\ParagraphsType; + +/** + * Test Conditional Fields Paragraphs Handler. + * + * @group conditional_fields + */ +class ConditionalFieldParagraphsTest extends ConditionalFieldTestBase implements + ConditionalFieldValueInterface, + ConditionalFieldFilledEmptyInterface { + + /** + * Modules to enable. + * + * @var array + */ + protected static $modules = [ + 'paragraphs', + 'entity_reference_revisions', + ]; + + /** + * {@inheritdoc} + */ + protected $screenshotPath = 'sites/simpletest/conditional_fields/paragraphs/'; + + /** + * The field name used in the test. + * + * @var string + */ + protected $fieldName = 'single_textfield'; + + /** + * The target field name. + * + * @var string + */ + protected $targetFieldName = 'field_body'; + + /** + * The target field wrapper selector. + * + * @var string + */ + protected $targetFieldWrap = ''; + + /** + * Jquery selector of field in a document. + * + * @var string + */ + protected $fieldSelector; + + /** + * Base steps for all javascript tests. + */ + protected function baseTestSteps() { + $admin_account = $this->createUser([ + 'view conditional fields', + 'edit conditional fields', + 'delete conditional fields', + 'administer nodes', + 'create article content', + 'administer content types', + ]); + + $this->drupalLogin($admin_account); + + // Visit a ConditionalFields configuration page for test_conditional CT. + $this->drupalGet('admin/structure/paragraphs_type/test_conditional/conditionals'); + $this->assertSession()->pageTextContains('Target field'); + } + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + + $this->fieldSelector = '[name="field_paragraph[0][subform][field_' . $this->fieldName . '][0][value]"]'; + $this->targetFieldWrap = '.field--name-' . str_replace('_', '-', $this->targetFieldName); + + $paragraphsType = ParagraphsType::create([ + 'label' => 'Test Conditional', + 'id' => 'test_conditional', + ]); + $paragraphsType->save(); + $this->addParagraphsField('test_conditional', 'field_single_textfield', 'string'); + $this->addParagraphsField('test_conditional', 'field_body', 'string'); + + $paragraphDisplay = EntityFormDisplay::create([ + 'targetEntityType' => 'paragraph', + 'bundle' => 'test_conditional', + 'mode' => 'default', + 'status' => TRUE, + ]); + + $paragraphDisplay->setComponent('field_single_textfield', [ + 'type' => 'text_textfield', + 'settings' => [], + ]); + + $paragraphDisplay->setComponent('field_body', [ + 'type' => 'text_textfield', + 'settings' => [], + ]); + $paragraphDisplay->save(); + + $handler_settings = [ + 'target_bundles' => [ + 'test_conditional' => 'test_conditional', + ], + ]; + $this->createEntityReferenceRevisionsField( + 'node', + 'article', + 'field_paragraph', + 'Paragraphs', + 'default:paragraph', + $handler_settings, + 1 + ); + + EntityFormDisplay::load('node.article.default') + ->setComponent('field_paragraph', [ + 'type' => 'paragraphs', + 'settings' => [ + 'title' => 'Paragraph', + 'title_plural' => 'Paragraphs', + 'closed_mode' => 'summary', + 'autocollapse' => 'none', + 'closed_mode_threshold' => 0, + 'add_mode' => 'button', + 'form_display_mode' => 'default', + 'edit_mode' => 'default', + 'default_paragraph_type' => 'test_conditional', + 'features' => [ + 'add_above' => '0', + 'collapse_edit_all' => 'collapse_edit_all', + 'convert' => '0', + 'duplicate' => 'duplicate', + ], + ], + ]) + ->save(); + } + + /** + * Creates a field of an entity reference field storage. + * + * Creates the field on the specified bundle. + * + * @param string $entity_type + * The type of entity the field will be attached to. + * @param string $bundle + * The bundle name of the entity the field will be attached to. + * @param string $field_name + * The name of the field; if it already exists, a new instance of the + * existing field will be created. + * @param string $field_label + * The label of the field. + * @param string $selection_handler + * The selection handler used by this field. + * @param array $selection_handler_settings + * An array of settings supported by the selection handler specified above. + * (e.g. 'target_bundles', 'sort', 'auto_create', etc). + * @param int $cardinality + * The cardinality of the field. + */ + protected function createEntityReferenceRevisionsField($entity_type, $bundle, $field_name, $field_label, $selection_handler = 'default:paragraph', $selection_handler_settings = [], $cardinality = 1) { + // Look for or add the specified field to the requested entity bundle. + if (!FieldStorageConfig::loadByName($entity_type, $field_name)) { + FieldStorageConfig::create([ + 'field_name' => $field_name, + 'type' => 'entity_reference_revisions', + 'entity_type' => $entity_type, + 'cardinality' => $cardinality, + 'settings' => [ + 'target_type' => 'paragraph', + ], + ])->save(); + } + if (!FieldConfig::loadByName($entity_type, $bundle, $field_name)) { + FieldConfig::create([ + 'field_name' => $field_name, + 'entity_type' => $entity_type, + 'bundle' => $bundle, + 'label' => $field_label, + 'settings' => [ + 'handler' => $selection_handler, + 'handler_settings' => $selection_handler_settings, + ], + ])->save(); + } + } + + /** + * Adds a field to a given paragraph type. + * + * @param string $paragraph_type_name + * Paragraph type name to be used. + * @param string $field_name + * Paragraphs field name to be used. + * @param string $field_type + * Type of the field. + * @param array $field_edit + * Edit settings for the field. + */ + protected function addParagraphsField($paragraph_type_name, $field_name, $field_type, $field_edit = []) { + // Add a paragraphs field. + $field_storage = FieldStorageConfig::create([ + 'field_name' => $field_name, + 'entity_type' => 'paragraph', + 'type' => $field_type, + 'cardinality' => '-1', + 'settings' => $field_edit, + ]); + $field_storage->save(); + $field = FieldConfig::create([ + 'field_storage' => $field_storage, + 'bundle' => $paragraph_type_name, + 'settings' => [ + 'handler' => 'default:paragraph', + 'handler_settings' => ['target_bundles' => NULL], + ], + ]); + $field->save(); + } + + /** + * {@inheritdoc} + */ + public function testVisibleValueWidget() { + + $this->baseTestSteps(); + + // Visit a ConditionalFields configuration page for Content bundles. + $this->createCondition($this->targetFieldName, 'field_' . $this->fieldName, 'visible', 'value'); + + // Set up conditions. + $text = $this->getRandomGenerator()->word(8); + $data = [ + 'condition' => 'value', + 'values_set' => ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_WIDGET, + 'field_' . $this->fieldName . '[0][value]' => $text, + 'grouping' => 'AND', + 'state' => 'visible', + 'effect' => 'show', + ]; + + $this->submitForm($data, 'Save settings'); + + // Check if that configuration is saved. + $this->drupalGet('admin/structure/paragraphs_type/test_conditional/conditionals'); + $this->assertSession() + ->pageTextContains($this->targetFieldName . ' ' . 'field_' . $this->fieldName . ' visible value'); + + $this->drupalGet('node/add/article'); + $this->assertSession()->elementExists('css', $this->targetFieldWrap); + + $this->waitUntilHidden($this->targetFieldWrap, 0, '01. Article Body field is hidden'); + + $this->changeField($this->fieldSelector, $text); + $this->waitUntilVisible($this->targetFieldWrap, 50, '02. Article Body field is visible'); + } + + /** + * {@inheritdoc} + */ + public function testVisibleValueRegExp() { + $this->baseTestSteps(); + $this->createCondition($this->targetFieldName, 'field_' . $this->fieldName, 'visible', 'value'); + + $data = [ + 'condition' => 'value', + 'values_set' => ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_REGEX, + 'regex' => '.*data\=[\d]+.*', + 'grouping' => 'AND', + 'state' => 'visible', + 'effect' => 'show', + ]; + + $text_without_expression = 'The field in not empty'; + $text_with_expression = 'The field has data=2 text'; + + $this->submitForm($data, 'Save settings'); + + // Check if that configuration is saved. + $this->drupalGet('admin/structure/paragraphs_type/test_conditional/conditionals'); + $this->assertSession() + ->pageTextContains($this->targetFieldName . ' ' . 'field_' . $this->fieldName . ' visible value'); + + $this->drupalGet('node/add/article'); + $this->assertSession()->elementExists('css', $this->targetFieldWrap); + + $this->waitUntilHidden($this->targetFieldWrap, 0, '01. Article Body field is visible'); + $this->changeField($this->fieldSelector, $text_without_expression); + $this->waitUntilHidden($this->targetFieldWrap, 50, '02. Article Body field is visible'); + $this->changeField($this->fieldSelector, $text_with_expression); + $this->waitUntilVisible($this->targetFieldWrap, 50, '03. Article Body field is not visible'); + + } + + /** + * {@inheritdoc} + */ + public function testVisibleValueAnd() { + $this->baseTestSteps(); + $this->createCondition($this->targetFieldName, 'field_' . $this->fieldName, 'visible', 'value'); + + $text_1 = $this->getRandomGenerator()->word(7); + $text_2 = $this->getRandomGenerator()->word(7); + + $data = [ + 'condition' => 'value', + 'values_set' => ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_AND, + 'values' => implode("\r\n", [ + $text_1, + $text_2, + ]), + 'grouping' => 'AND', + 'state' => 'visible', + 'effect' => 'show', + ]; + + $this->submitForm($data, 'Save settings'); + + $this->drupalGet('node/add/article'); + $this->assertSession()->elementExists('css', $this->targetFieldWrap); + + $text_false = implode(' ', [$text_1, $text_2]); + + $this->waitUntilHidden($this->targetFieldWrap, 0, '01. Article Body field is visible'); + + $this->changeField($this->fieldSelector, $text_false); + $this->waitUntilHidden($this->targetFieldWrap, 50, '02. Article Body field is visible'); + + $this->changeField($this->fieldSelector, $text_1); + $this->waitUntilHidden($this->targetFieldWrap, 50, '03. Article Body field is visible'); + + // Change a value to hide the body again. + $this->changeField($this->fieldSelector, ''); + $this->waitUntilHidden($this->targetFieldWrap, 50, '04. Article Body field is visible'); + + } + + /** + * {@inheritdoc} + */ + public function testVisibleValueOr() { + $this->baseTestSteps(); + + // Visit a ConditionalFields configuration page for Content bundles. + $this->createCondition($this->targetFieldName, 'field_' . $this->fieldName, 'visible', 'value'); + + // Random term id to check necessary value. + $text1 = $this->getRandomGenerator()->word(8); + $text2 = $this->getRandomGenerator()->word(7); + + // Set up conditions. + $values = implode("\r\n", [$text1, $text2]); + $data = [ + 'condition' => 'value', + 'values_set' => ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_OR, + 'values' => $values, + 'grouping' => 'AND', + 'state' => 'visible', + 'effect' => 'show', + ]; + $this->submitForm($data, 'Save settings'); + + // Check if that configuration is saved. + $this->drupalGet('admin/structure/paragraphs_type/test_conditional/conditionals'); + $this->assertSession() + ->pageTextContains($this->targetFieldName . ' ' . 'field_' . $this->fieldName . ' visible value'); + + // Visit Article Add form to check that conditions are applied. + $this->drupalGet('node/add/article'); + + // Check that the field Body is not visible. + $this->waitUntilHidden($this->targetFieldWrap, 0, '01. Article Body field is visible'); + + // Change value that should not show the body. + $this->changeField($this->fieldSelector, 'wrong'); + $this->waitUntilHidden($this->targetFieldWrap, 50, '02. Article Body field is visible'); + + // Change a value value to show the body. + $this->changeField($this->fieldSelector, $text1); + $this->waitUntilVisible($this->targetFieldWrap, 50, '03. Article Body field is not visible'); + + // Change a value value to show the body. + $this->changeField($this->fieldSelector, $text2); + $this->waitUntilVisible($this->targetFieldWrap, 50, '04. Article Body field is not visible'); + + // Change a value value to hide the body again. + $this->changeField($this->fieldSelector, ''); + $this->waitUntilHidden($this->targetFieldWrap, 50, '05. Article Body field is visible'); + } + + /** + * {@inheritdoc} + */ + public function testVisibleValueNot() { + $this->baseTestSteps(); + $this->createCondition($this->targetFieldName, 'field_' . $this->fieldName, 'visible', 'value'); + + $text_1 = $this->getRandomGenerator()->word(7); + $text_2 = $this->getRandomGenerator()->word(7); + + $data = [ + 'condition' => 'value', + 'values_set' => ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_NOT, + 'values' => implode("\r\n", [ + $text_1, + $text_2, + ]), + 'grouping' => 'AND', + 'state' => 'visible', + 'effect' => 'show', + ]; + + $this->submitForm($data, 'Save settings'); + + // Check if that configuration is saved. + $this->drupalGet('admin/structure/paragraphs_type/test_conditional/conditionals'); + $this->assertSession() + ->pageTextContains($this->targetFieldName . ' ' . 'field_' . $this->fieldName . ' visible value'); + + $this->drupalGet('node/add/article'); + + $this->waitUntilVisible($this->targetFieldWrap, 0, '01. Article Body field is not visible'); + + $this->changeField($this->fieldSelector, 'some-unique-text'); + $this->waitUntilVisible($this->targetFieldWrap, 50, '02. Article Body field is not visible'); + + $this->changeField($this->fieldSelector, $text_1); + $this->waitUntilHidden($this->targetFieldWrap, 50, '03. Article Body field is visible'); + + $this->changeField($this->fieldSelector, $text_2); + $this->waitUntilHidden($this->targetFieldWrap, 50, '04. Article Body field is visible'); + + $this->changeField($this->fieldSelector, ""); + $this->waitUntilVisible($this->targetFieldWrap, 50, '05. Article Body field is not visible'); + } + + /** + * {@inheritdoc} + */ + public function testVisibleValueXor() { + $this->baseTestSteps(); + $this->createCondition($this->targetFieldName, 'field_' . $this->fieldName, 'visible', 'value'); + + $text_1 = $this->getRandomGenerator()->word(7); + $text_2 = $this->getRandomGenerator()->word(7); + + $data = [ + 'condition' => 'value', + 'values_set' => ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_XOR, + 'values' => implode("\n", [ + $text_1, + $text_2, + ]), + 'grouping' => 'AND', + 'state' => 'visible', + 'effect' => 'show', + ]; + + $this->submitForm($data, 'Save settings'); + + // Check if that configuration is saved. + $this->drupalGet('admin/structure/paragraphs_type/test_conditional/conditionals'); + $this->assertSession() + ->pageTextContains($this->targetFieldName . ' ' . 'field_' . $this->fieldName . ' visible value'); + + $this->drupalGet('node/add/article'); + $this->assertSession()->elementExists('css', $this->targetFieldWrap); + + $text_false = 'same unique value'; + + $this->waitUntilHidden($this->targetFieldWrap, 0, '01. Article Body field is visible'); + + $this->changeField($this->fieldSelector, $text_false); + $this->waitUntilHidden($this->targetFieldWrap, 50, '02. Article Body field is visible'); + + $this->changeField($this->fieldSelector, $text_1); + $this->waitUntilVisible($this->targetFieldWrap, 50, '03. Article Body field is not visible'); + + $this->changeField($this->fieldSelector, ""); + $this->waitUntilHidden($this->targetFieldWrap, 50, '04. Article Body field is visible'); + } + + /** + * Tests creating Conditional Field: Visible if isFilled. + */ + public function testVisibleFilled() { + $this->baseTestSteps(); + + // Visit a ConditionalFields configuration page for `Article` Content type. + $this->createCondition($this->targetFieldName, 'field_' . $this->fieldName, 'visible', '!empty'); + + // Check that configuration is saved. + $this->drupalGet('admin/structure/paragraphs_type/test_conditional/conditionals'); + $this->assertSession() + ->pageTextContains($this->targetFieldName . ' ' . 'field_' . $this->fieldName . ' visible !empty'); + + // Visit Article Add form to check that conditions are applied. + $this->drupalGet('node/add/article'); + + // Check that the field Body is not visible. + $this->waitUntilHidden($this->targetFieldWrap, 0, '01. Article Body field is visible'); + + $this->changeField($this->fieldSelector, 'This field is not empty.'); + $this->waitUntilVisible($this->targetFieldWrap, 10, '02. Article Body field is not visible'); + + $this->changeField($this->fieldSelector, ''); + $this->waitUntilHidden($this->targetFieldWrap, 10, '03. Article Body field is visible'); + } + + /** + * {@inheritdoc} + */ + public function testVisibleEmpty() { + $this->baseTestSteps(); + $this->createCondition($this->targetFieldName, 'field_' . $this->fieldName, 'visible', 'empty'); + // Check that configuration is saved. + $this->drupalGet('admin/structure/paragraphs_type/test_conditional/conditionals'); + $this->assertSession() + ->pageTextContains($this->targetFieldName . ' ' . 'field_' . $this->fieldName . ' visible empty'); + + $this->drupalGet('node/add/article'); + + $this->waitUntilVisible($this->targetFieldWrap, 0, '01. Article Body field is not visible'); + + $this->changeField($this->fieldSelector, 'This field is not empty.'); + $this->waitUntilHidden($this->targetFieldWrap, 10, '02. Article Body field is visible'); + + $this->changeField($this->fieldSelector, ''); + $this->waitUntilVisible($this->targetFieldWrap, 10, '03. Article Body field is not visible'); + } + + /** + * {@inheritdoc} + */ + public function testInvisibleFilled() { + $this->baseTestSteps(); + $this->createCondition($this->targetFieldName, 'field_' . $this->fieldName, '!visible', '!empty'); + // Check that configuration is saved. + $this->drupalGet('admin/structure/paragraphs_type/test_conditional/conditionals'); + $this->assertSession() + ->pageTextContains($this->targetFieldName . ' ' . 'field_' . $this->fieldName . ' !visible !empty'); + + $this->drupalGet('node/add/article'); + + $this->waitUntilVisible($this->targetFieldWrap, 0, '01. Article Body field is not visible'); + + $this->changeField($this->fieldSelector, 'This field is not empty.'); + $this->waitUntilHidden($this->targetFieldWrap, 10, '02. Article Body field is visible'); + + $this->changeField($this->fieldSelector, ''); + $this->waitUntilVisible($this->targetFieldWrap, 10, '03. Article Body field is not visible'); + } + + /** + * {@inheritdoc} + */ + public function testInvisibleEmpty() { + $this->baseTestSteps(); + + // Visit a ConditionalFields configuration page for `Article` Content type. + $this->createCondition($this->targetFieldName, 'field_' . $this->fieldName, '!visible', 'empty'); + + // Check that configuration is saved. + $this->drupalGet('admin/structure/paragraphs_type/test_conditional/conditionals'); + $this->assertSession() + ->pageTextContains($this->targetFieldName . ' ' . 'field_' . $this->fieldName . ' !visible empty'); + + // Visit Article Add form to check that conditions are applied. + $this->drupalGet('node/add/article'); + + $this->waitUntilHidden($this->targetFieldWrap, 0, '01. Article Body field is visible'); + + $this->changeField($this->fieldSelector, 'This field is not empty.'); + $this->waitUntilVisible($this->targetFieldWrap, 10, '02. Article Body field is not visible'); + + $this->changeField($this->fieldSelector, ''); + $this->waitUntilHidden($this->targetFieldWrap, 10, '03. Article Body field is not visible'); + } + +} diff --git a/tests/src/FunctionalJavascript/ConditionalFieldRadiosTest.php b/tests/src/FunctionalJavascript/ConditionalFieldRadiosTest.php index 9c14f00cf3d9f3c079145e5d2109051d29ea38b0..4ec20099004e32fe073fa0873fc371341d5cbc9d 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldRadiosTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldRadiosTest.php @@ -2,13 +2,13 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; -use Drupal\conditional_fields\ConditionalFieldsInterface; -use Drupal\Tests\field\Traits\EntityReferenceTestTrait; -use Drupal\taxonomy\Entity\Vocabulary; -use Drupal\taxonomy\Entity\Term; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldCheckedUncheckedInterface; use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; +use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait; +use Drupal\conditional_fields\ConditionalFieldsInterface; +use Drupal\taxonomy\Entity\Term; +use Drupal\taxonomy\Entity\Vocabulary; /** * Test Conditional Fields States. @@ -16,10 +16,10 @@ use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFi * @group conditional_fields */ class ConditionalFieldRadiosTest extends ConditionalFieldTestBase implements - ConditionalFieldValueInterface, - ConditionalFieldCheckedUncheckedInterface { + ConditionalFieldValueInterface, + ConditionalFieldCheckedUncheckedInterface { - use EntityReferenceTestTrait; + use EntityReferenceFieldCreationTrait; /** * {@inheritdoc} diff --git a/tests/src/FunctionalJavascript/ConditionalFieldSelectMultipleTest.php b/tests/src/FunctionalJavascript/ConditionalFieldSelectMultipleTest.php index 4f80bb08f77994f0c151cc355749165be76e073a..717ef83f3196a596af354f34f8c9dc8c062c7949 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldSelectMultipleTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldSelectMultipleTest.php @@ -2,11 +2,11 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; +use Drupal\Core\Entity\Entity\EntityFormDisplay; +use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\Core\Entity\Entity\EntityFormDisplay; -use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; /** * Test Conditional Fields SelectMultiple Plugin. diff --git a/tests/src/FunctionalJavascript/ConditionalFieldSelectTest.php b/tests/src/FunctionalJavascript/ConditionalFieldSelectTest.php index 6e95a73183aac49eb3722fa26c9d8ed6df37a218..17fa606c3b946a06c19670182a3d675d50546c53 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldSelectTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldSelectTest.php @@ -2,11 +2,11 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; -use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\Core\Entity\Entity\EntityFormDisplay; +use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; +use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; /** * Test Conditional Fields Select Plugin. diff --git a/tests/src/FunctionalJavascript/ConditionalFieldTextTextareaTest.php b/tests/src/FunctionalJavascript/ConditionalFieldTextTextareaTest.php index 825918be60f576813223e988678a253d33cff866..e7b96156f8a358b4f4cac4526d64c1fd1a347ad4 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldTextTextareaTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldTextTextareaTest.php @@ -2,11 +2,11 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; +use Drupal\Core\Entity\Entity\EntityFormDisplay; +use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\Core\Entity\Entity\EntityFormDisplay; -use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; /** * Test Conditional Fields Text Handler. @@ -53,7 +53,7 @@ class ConditionalFieldTextTextareaTest extends ConditionalFieldTestBase implemen * * @var string */ - protected $targetFieldWrapp = ''; + protected $targetFieldWrap = ''; /** * The field storage definition used to created the field storage. @@ -83,7 +83,7 @@ class ConditionalFieldTextTextareaTest extends ConditionalFieldTestBase implemen parent::setUp(); $this->fieldSelector = '[name="field_' . $this->fieldName . '[0][value]"]'; - $this->targetFieldWrapp = '.field--name-' . str_replace('_', '-', $this->targetFieldName); + $this->targetFieldWrap = '.field--name-' . str_replace('_', '-', $this->targetFieldName); $this->fieldStorageDefinition = [ 'field_name' => 'field_' . $this->fieldName, @@ -138,17 +138,17 @@ class ConditionalFieldTextTextareaTest extends ConditionalFieldTestBase implemen // Change field that should not show the body. $this->createScreenshot($this->screenshotPath . '04-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); // Check that the field Body is visible. $this->changeField($this->fieldSelector, $text); $this->createScreenshot($this->screenshotPath . '05-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilVisible($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilVisible($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); // Change field that should not show the body again. $this->changeField($this->fieldSelector, ''); $this->createScreenshot($this->screenshotPath . '06-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); } /** @@ -184,27 +184,27 @@ class ConditionalFieldTextTextareaTest extends ConditionalFieldTestBase implemen // Check that the field Body is not visible. $this->createScreenshot($this->screenshotPath . '04-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); // Change field that should not show the body. $this->changeField($this->fieldSelector, 'https://drupal.org'); $this->createScreenshot($this->screenshotPath . '05-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); // Change field value to show the body. $this->changeField($this->fieldSelector, $text[0]); $this->createScreenshot($this->screenshotPath . '06-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); // Change field value to show the body. $this->changeField($this->fieldSelector, $text[1]); $this->createScreenshot($this->screenshotPath . '07-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); // Change field value to hide the body again. $this->changeField($this->fieldSelector, ''); $this->createScreenshot($this->screenshotPath . '08-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); } /** @@ -240,27 +240,27 @@ class ConditionalFieldTextTextareaTest extends ConditionalFieldTestBase implemen // Check that the field Body is not visible. $this->createScreenshot($this->screenshotPath . '04-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); // Change field that should not show the body. $this->changeField($this->fieldSelector, 'https://drupal.org'); $this->createScreenshot($this->screenshotPath . '05-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); // Change field value to show the body. $this->changeField($this->fieldSelector, $text[0]); $this->createScreenshot($this->screenshotPath . '06-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilVisible($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); // Change field value to show the body. $this->changeField($this->fieldSelector, $text[1]); $this->createScreenshot($this->screenshotPath . '07-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilVisible($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); // Change field value to hide the body again. $this->changeField($this->fieldSelector, ''); $this->createScreenshot($this->screenshotPath . '08-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); } /** @@ -283,8 +283,8 @@ class ConditionalFieldTextTextareaTest extends ConditionalFieldTestBase implemen 'effect' => 'show', ]; - $text_without_expresion = 'The field in not empty'; - $text_with_expresion = 'The field has data=2 text'; + $text_without_expression = 'The field in not empty'; + $text_with_expression = 'The field has data=2 text'; $this->submitForm($data, 'Save settings'); $this->createScreenshot($this->screenshotPath . '02-' . $this->testName . __FUNCTION__ . '.png'); @@ -299,22 +299,22 @@ class ConditionalFieldTextTextareaTest extends ConditionalFieldTestBase implemen // Change field that should not show the body. $this->createScreenshot($this->screenshotPath . '04-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); // Change field that should not show the body. - $this->changeField($this->fieldSelector, $text_without_expresion); + $this->changeField($this->fieldSelector, $text_without_expression); $this->createScreenshot($this->screenshotPath . '05-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); // Check that the field Body is visible. - $this->changeField($this->fieldSelector, $text_with_expresion); + $this->changeField($this->fieldSelector, $text_with_expression); $this->createScreenshot($this->screenshotPath . '06-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilVisible($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); // Change field that should not show the body again. $this->changeField($this->fieldSelector, ''); $this->createScreenshot($this->screenshotPath . '06-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); } /** @@ -349,22 +349,22 @@ class ConditionalFieldTextTextareaTest extends ConditionalFieldTestBase implemen // Check that the field Body is visible. $this->createScreenshot($this->screenshotPath . '04-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilVisible($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); // Change field that should not show the body. $this->changeField($this->fieldSelector, $text[0]); $this->createScreenshot($this->screenshotPath . '05-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); // Change field that should not show the body again. $this->changeField($this->fieldSelector, $text[1]); $this->createScreenshot($this->screenshotPath . '06-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); // Change field value to show the body. $this->changeField($this->fieldSelector, ''); $this->createScreenshot($this->screenshotPath . '07-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilVisible($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); } /** @@ -399,22 +399,22 @@ class ConditionalFieldTextTextareaTest extends ConditionalFieldTestBase implemen // Check that the field Body is invisible. $this->createScreenshot($this->screenshotPath . '04-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); // Change field that should not show the body. $this->changeField($this->fieldSelector, $text[0]); $this->createScreenshot($this->screenshotPath . '05-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilVisible($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); // Change field that should not show the body again. $this->changeField($this->fieldSelector, $text[1]); $this->createScreenshot($this->screenshotPath . '06-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilVisible($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is not visible'); // Change field value to show the body. $this->changeField($this->fieldSelector, ''); $this->createScreenshot($this->screenshotPath . '07-' . $this->testName . __FUNCTION__ . '.png'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, 'Article \'' . $this->targetFieldName . '\' field is visible'); } /** @@ -434,9 +434,9 @@ class ConditionalFieldTextTextareaTest extends ConditionalFieldTestBase implemen $this->drupalGet('node/add/article'); // Check that the field Body is not visible. - $this->waitUntilHidden($this->targetFieldWrapp, 0, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 0, 'Article \'' . $this->targetFieldName . '\' field is visible'); $this->changeField($this->fieldSelector, 'This field is not empty.'); - $this->waitUntilVisible($this->targetFieldWrapp, 10, 'Article \'' . $this->targetFieldName . '\' field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 10, 'Article \'' . $this->targetFieldName . '\' field is not visible'); } /** @@ -455,9 +455,9 @@ class ConditionalFieldTextTextareaTest extends ConditionalFieldTestBase implemen // Visit Article Add form to check that conditions are applied. $this->drupalGet('node/add/article'); - $this->waitUntilHidden($this->targetFieldWrapp, 0, 'Article \'' . $this->targetFieldName . '\' field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 0, 'Article \'' . $this->targetFieldName . '\' field is visible'); $this->changeField($this->fieldSelector, 'This field is not empty.'); - $this->waitUntilVisible($this->targetFieldWrapp, 10, 'Article \'' . $this->targetFieldName . '\' field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 10, 'Article \'' . $this->targetFieldName . '\' field is not visible'); } } diff --git a/tests/src/FunctionalJavascript/ConditionalFieldTextWithSummaryTest.php b/tests/src/FunctionalJavascript/ConditionalFieldTextWithSummaryTest.php index 6dc5292323657708f69b1d39e222820bec42f163..61731eef7bec8961a027f4c9d6079e0564507bd0 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldTextWithSummaryTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldTextWithSummaryTest.php @@ -2,11 +2,11 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; +use Drupal\Core\Entity\Entity\EntityFormDisplay; +use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; use Drupal\conditional_fields\ConditionalFieldsInterface; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\Core\Entity\Entity\EntityFormDisplay; -use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; /** * Test Conditional Fields Text Handler. diff --git a/tests/src/FunctionalJavascript/ConditionalFieldTextfieldTest.php b/tests/src/FunctionalJavascript/ConditionalFieldTextfieldTest.php index 9187cc03ae53bb0e827eee298b1487ee2b73b1f3..cde3796490d056470e94f70f91fdb0a63e90349d 100644 --- a/tests/src/FunctionalJavascript/ConditionalFieldTextfieldTest.php +++ b/tests/src/FunctionalJavascript/ConditionalFieldTextfieldTest.php @@ -2,12 +2,12 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript; -use Drupal\conditional_fields\ConditionalFieldsInterface; -use Drupal\field\Entity\FieldConfig; -use Drupal\field\Entity\FieldStorageConfig; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldFilledEmptyInterface; use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFieldValueInterface; +use Drupal\conditional_fields\ConditionalFieldsInterface; +use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; /** * Test Conditional Fields Text Handler. @@ -15,8 +15,8 @@ use Drupal\Tests\conditional_fields\FunctionalJavascript\TestCases\ConditionalFi * @group conditional_fields */ class ConditionalFieldTextfieldTest extends ConditionalFieldTestBase implements - ConditionalFieldValueInterface, - ConditionalFieldFilledEmptyInterface { + ConditionalFieldValueInterface, + ConditionalFieldFilledEmptyInterface { /** * {@inheritdoc} @@ -42,7 +42,7 @@ class ConditionalFieldTextfieldTest extends ConditionalFieldTestBase implements * * @var string */ - protected $targetFieldWrapp = ''; + protected $targetFieldWrap = ''; /** * Jquery selector of field in a document. @@ -58,7 +58,7 @@ class ConditionalFieldTextfieldTest extends ConditionalFieldTestBase implements parent::setUp(); $this->fieldSelector = '[name="field_' . $this->fieldName . '[0][value]"]'; - $this->targetFieldWrapp = '.field--name-' . str_replace('_', '-', $this->targetFieldName); + $this->targetFieldWrap = '.field--name-' . str_replace('_', '-', $this->targetFieldName); $fieldStorageDefinition = [ 'field_name' => 'field_' . $this->fieldName, @@ -112,12 +112,12 @@ class ConditionalFieldTextfieldTest extends ConditionalFieldTestBase implements $this->drupalGet('node/add/article'); // Check that the field Body is not visible. - $this->waitUntilHidden($this->targetFieldWrapp, 0, '01. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 0, '01. Article Body field is visible'); $this->changeField($this->fieldSelector, $text); - $this->waitUntilVisible($this->targetFieldWrapp, 50, '02. Article Body field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 50, '02. Article Body field is not visible'); // Change a select value set to hide the body again. $this->changeField($this->fieldSelector, $text . 'a'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, '03. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, '03. Article Body field is visible'); } /** @@ -136,8 +136,8 @@ class ConditionalFieldTextfieldTest extends ConditionalFieldTestBase implements 'effect' => 'show', ]; - $text_without_expresion = 'The field in not empty'; - $text_with_expresion = 'The field has data=2 text'; + $text_without_expression = 'The field in not empty'; + $text_with_expression = 'The field has data=2 text'; $this->submitForm($data, 'Save settings'); @@ -147,13 +147,13 @@ class ConditionalFieldTextfieldTest extends ConditionalFieldTestBase implements ->pageTextContains($this->targetFieldName . ' ' . 'field_' . $this->fieldName . ' visible value'); $this->drupalGet('node/add/article'); - $this->assertSession()->elementExists('css', $this->targetFieldWrapp); + $this->assertSession()->elementExists('css', $this->targetFieldWrap); - $this->waitUntilHidden($this->targetFieldWrapp, 0, '01. Article Body field is visible'); - $this->changeField($this->fieldSelector, $text_without_expresion); - $this->waitUntilHidden($this->targetFieldWrapp, 50, '02. Article Body field is visible'); - $this->changeField($this->fieldSelector, $text_with_expresion); - $this->waitUntilVisible($this->targetFieldWrapp, 50, '03. Article Body field is not visible'); + $this->waitUntilHidden($this->targetFieldWrap, 0, '01. Article Body field is visible'); + $this->changeField($this->fieldSelector, $text_without_expression); + $this->waitUntilHidden($this->targetFieldWrap, 50, '02. Article Body field is visible'); + $this->changeField($this->fieldSelector, $text_with_expression); + $this->waitUntilVisible($this->targetFieldWrap, 50, '03. Article Body field is not visible'); } @@ -182,21 +182,21 @@ class ConditionalFieldTextfieldTest extends ConditionalFieldTestBase implements $this->submitForm($data, 'Save settings'); $this->drupalGet('node/add/article'); - $this->assertSession()->elementExists('css', $this->targetFieldWrapp); + $this->assertSession()->elementExists('css', $this->targetFieldWrap); $text_false = implode(' ', [$text_1, $text_2]); - $this->waitUntilHidden($this->targetFieldWrapp, 0, '01. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 0, '01. Article Body field is visible'); $this->changeField($this->fieldSelector, $text_false); - $this->waitUntilHidden($this->targetFieldWrapp, 50, '02. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, '02. Article Body field is visible'); $this->changeField($this->fieldSelector, $text_1); - $this->waitUntilHidden($this->targetFieldWrapp, 50, '03. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, '03. Article Body field is visible'); // Change a value value to hide the body again. $this->changeField($this->fieldSelector, ''); - $this->waitUntilHidden($this->targetFieldWrapp, 50, '04. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, '04. Article Body field is visible'); } @@ -234,23 +234,23 @@ class ConditionalFieldTextfieldTest extends ConditionalFieldTestBase implements $this->drupalGet('node/add/article'); // Check that the field Body is not visible. - $this->waitUntilHidden($this->targetFieldWrapp, 0, '01. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 0, '01. Article Body field is visible'); // Change value that should not show the body. $this->changeField($this->fieldSelector, 'wrong'); - $this->waitUntilHidden($this->targetFieldWrapp, 50, '02. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, '02. Article Body field is visible'); // Change a value value to show the body. $this->changeField($this->fieldSelector, $text1); - $this->waitUntilVisible($this->targetFieldWrapp, 50, '03. Article Body field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 50, '03. Article Body field is not visible'); // Change a value value to show the body. $this->changeField($this->fieldSelector, $text2); - $this->waitUntilVisible($this->targetFieldWrapp, 50, '04. Article Body field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 50, '04. Article Body field is not visible'); // Change a value value to hide the body again. $this->changeField($this->fieldSelector, ''); - $this->waitUntilHidden($this->targetFieldWrapp, 50, '05. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, '05. Article Body field is visible'); } /** @@ -284,19 +284,19 @@ class ConditionalFieldTextfieldTest extends ConditionalFieldTestBase implements $this->drupalGet('node/add/article'); - $this->waitUntilVisible($this->targetFieldWrapp, 0, '01. Article Body field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 0, '01. Article Body field is not visible'); $this->changeField($this->fieldSelector, 'some-unique-text'); - $this->waitUntilVisible($this->targetFieldWrapp, 50, '02. Article Body field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 50, '02. Article Body field is not visible'); $this->changeField($this->fieldSelector, $text_1); - $this->waitUntilHidden($this->targetFieldWrapp, 50, '03. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, '03. Article Body field is visible'); $this->changeField($this->fieldSelector, $text_2); - $this->waitUntilHidden($this->targetFieldWrapp, 50, '04. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, '04. Article Body field is visible'); $this->changeField($this->fieldSelector, ""); - $this->waitUntilVisible($this->targetFieldWrapp, 50, '05. Article Body field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 50, '05. Article Body field is not visible'); } /** @@ -329,20 +329,20 @@ class ConditionalFieldTextfieldTest extends ConditionalFieldTestBase implements ->pageTextContains($this->targetFieldName . ' ' . 'field_' . $this->fieldName . ' visible value'); $this->drupalGet('node/add/article'); - $this->assertSession()->elementExists('css', $this->targetFieldWrapp); + $this->assertSession()->elementExists('css', $this->targetFieldWrap); $text_false = 'same unique value'; - $this->waitUntilHidden($this->targetFieldWrapp, 0, '01. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 0, '01. Article Body field is visible'); $this->changeField($this->fieldSelector, $text_false); - $this->waitUntilHidden($this->targetFieldWrapp, 50, '02. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, '02. Article Body field is visible'); $this->changeField($this->fieldSelector, $text_1); - $this->waitUntilVisible($this->targetFieldWrapp, 50, '03. Article Body field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 50, '03. Article Body field is not visible'); $this->changeField($this->fieldSelector, ""); - $this->waitUntilHidden($this->targetFieldWrapp, 50, '04. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 50, '04. Article Body field is visible'); } /** @@ -363,13 +363,13 @@ class ConditionalFieldTextfieldTest extends ConditionalFieldTestBase implements $this->drupalGet('node/add/article'); // Check that the field Body is not visible. - $this->waitUntilHidden($this->targetFieldWrapp, 0, '01. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 0, '01. Article Body field is visible'); $this->changeField($this->fieldSelector, 'This field is not empty.'); - $this->waitUntilVisible($this->targetFieldWrapp, 10, '02. Article Body field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 10, '02. Article Body field is not visible'); $this->changeField($this->fieldSelector, ''); - $this->waitUntilHidden($this->targetFieldWrapp, 10, '03. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 10, '03. Article Body field is visible'); } /** @@ -385,13 +385,13 @@ class ConditionalFieldTextfieldTest extends ConditionalFieldTestBase implements $this->drupalGet('node/add/article'); - $this->waitUntilVisible($this->targetFieldWrapp, 0, '01. Article Body field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 0, '01. Article Body field is not visible'); $this->changeField($this->fieldSelector, 'This field is not empty.'); - $this->waitUntilHidden($this->targetFieldWrapp, 10, '02. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 10, '02. Article Body field is visible'); $this->changeField($this->fieldSelector, ''); - $this->waitUntilVisible($this->targetFieldWrapp, 10, '03. Article Body field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 10, '03. Article Body field is not visible'); } /** @@ -407,13 +407,13 @@ class ConditionalFieldTextfieldTest extends ConditionalFieldTestBase implements $this->drupalGet('node/add/article'); - $this->waitUntilVisible($this->targetFieldWrapp, 0, '01. Article Body field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 0, '01. Article Body field is not visible'); $this->changeField($this->fieldSelector, 'This field is not empty.'); - $this->waitUntilHidden($this->targetFieldWrapp, 10, '02. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 10, '02. Article Body field is visible'); $this->changeField($this->fieldSelector, ''); - $this->waitUntilVisible($this->targetFieldWrapp, 10, '03. Article Body field is notvisible'); + $this->waitUntilVisible($this->targetFieldWrap, 10, '03. Article Body field is not visible'); } /** @@ -433,13 +433,13 @@ class ConditionalFieldTextfieldTest extends ConditionalFieldTestBase implements // Visit Article Add form to check that conditions are applied. $this->drupalGet('node/add/article'); - $this->waitUntilHidden($this->targetFieldWrapp, 0, '01. Article Body field is visible'); + $this->waitUntilHidden($this->targetFieldWrap, 0, '01. Article Body field is visible'); $this->changeField($this->fieldSelector, 'This field is not empty.'); - $this->waitUntilVisible($this->targetFieldWrapp, 10, '02. Article Body field is not visible'); + $this->waitUntilVisible($this->targetFieldWrap, 10, '02. Article Body field is not visible'); $this->changeField($this->fieldSelector, ''); - $this->waitUntilHidden($this->targetFieldWrapp, 10, '03. Article Body field is not visible'); + $this->waitUntilHidden($this->targetFieldWrap, 10, '03. Article Body field is not visible'); } } diff --git a/tests/src/FunctionalJavascript/Entity/ConditionalFieldsUserTest.php b/tests/src/FunctionalJavascript/Entity/ConditionalFieldsUserTest.php index dc2a2640ff13d0b866f70afedc36ae73ae186b31..e91425e17ad12f5f99d4aac2f605331d0224d904 100644 --- a/tests/src/FunctionalJavascript/Entity/ConditionalFieldsUserTest.php +++ b/tests/src/FunctionalJavascript/Entity/ConditionalFieldsUserTest.php @@ -3,10 +3,10 @@ namespace Drupal\Tests\conditional_fields\FunctionalJavascript\Entity; use Drupal\Core\Entity\Display\EntityDisplayInterface; +use Drupal\Core\Entity\Entity\EntityFormDisplay; +use Drupal\Tests\conditional_fields\FunctionalJavascript\ConditionalFieldTestBase; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\Tests\conditional_fields\FunctionalJavascript\ConditionalFieldTestBase; -use Drupal\Core\Entity\Entity\EntityFormDisplay; /** * Test Conditional Fields check User entity. diff --git a/tests/src/Unit/ConditionalFieldControllerTest.php b/tests/src/Unit/ConditionalFieldControllerTest.php index 6aafeb70d6eabdc2b836a3f8f0fe27b21c9959d7..61ffbbeb489278703e15755b0cdfc238fd126851 100644 --- a/tests/src/Unit/ConditionalFieldControllerTest.php +++ b/tests/src/Unit/ConditionalFieldControllerTest.php @@ -3,7 +3,6 @@ namespace Drupal\Tests\conditional_fields\Unit; use Drupal\Tests\UnitTestCase; - use Drupal\conditional_fields\Controller\ConditionalFieldController; /** @@ -40,19 +39,19 @@ class ConditionalFieldControllerTest extends UnitTestCase { ->getMock(); $entity_types['content_a']->expects($this->any()) ->method('getLabel') - ->will($this->returnValue("contentA")); + ->willReturn("contentA"); // `content_b` shouldn't appear in test results. $entity_types['content_b'] = $this->createMock('Drupal\Core\Config\Entity\ConfigEntityTypeInterface'); $entity_types['content_b']->expects($this->any()) ->method('getLabel') - ->will($this->returnValue("contentB")); + ->willReturn("contentB"); // Setup Drupal Container. $entity_type_manager = $this->createMock('Drupal\Core\Entity\EntityTypeManagerInterface'); $entity_type_manager->expects($this->any()) ->method('getDefinitions') - ->will($this->returnValue($entity_types)); + ->willReturn($entity_types); // For only one test case this classes not used, // change this after adding new test cases. diff --git a/tests/src/Unit/ConditionalFieldsFormHelperTest.php b/tests/src/Unit/ConditionalFieldsFormHelperTest.php index ff7d34ea68d1fd40c7abfa4b6ca035be1e356ab8..e54dbdf125cb54bd8588cd37a407a66ae371ff8e 100644 --- a/tests/src/Unit/ConditionalFieldsFormHelperTest.php +++ b/tests/src/Unit/ConditionalFieldsFormHelperTest.php @@ -2,13 +2,14 @@ namespace Drupal\Tests\conditional_fields\Unit; -use Drupal\conditional_fields\ConditionalFieldsFormHelper; -use Drupal\conditional_fields\ConditionalFieldsHandlersManager; use Drupal\Core\Entity\EntityDisplayRepositoryInterface; use Drupal\Core\Form\FormState; +use Drupal\Core\Language\LanguageManager; use Drupal\Core\Render\ElementInfoManager; -use Drupal\node\NodeForm; use Drupal\Tests\UnitTestCase; +use Drupal\conditional_fields\ConditionalFieldsFormHelper; +use Drupal\conditional_fields\ConditionalFieldsHandlersManager; +use Drupal\node\NodeForm; /** * Unit test the ConditionalFieldsFormHelper class. @@ -27,7 +28,8 @@ class ConditionalFieldsFormHelperTest extends UnitTestCase { $elementInfo = $this->createMock(ElementInfoManager::class); $cfHandlersManager = $this->createMock(ConditionalFieldsHandlersManager::class); $entityDisplayRepository = $this->createMock(EntityDisplayRepositoryInterface::class); - $sutClass = new ConditionalFieldsFormHelper($elementInfo, $cfHandlersManager, $entityDisplayRepository); + $languageManager = $this->createMock(LanguageManager::class); + $sutClass = new ConditionalFieldsFormHelper($elementInfo, $cfHandlersManager, $entityDisplayRepository, $languageManager); // Set up fixtures. $sutClass->effects = []; @@ -52,7 +54,8 @@ class ConditionalFieldsFormHelperTest extends UnitTestCase { $elementInfo = $this->createMock(ElementInfoManager::class); $cfHandlersManager = $this->createMock(ConditionalFieldsHandlersManager::class); $entityDisplayRepository = $this->createMock(EntityDisplayRepositoryInterface::class); - $sutClass = new ConditionalFieldsFormHelper($elementInfo, $cfHandlersManager, $entityDisplayRepository); + $languageManager = $this->createMock(LanguageManager::class); + $sutClass = new ConditionalFieldsFormHelper($elementInfo, $cfHandlersManager, $entityDisplayRepository, $languageManager); // Set up fixtures. $sutClass->effects = ['some_effect']; $sutClass->form = []; @@ -79,14 +82,15 @@ class ConditionalFieldsFormHelperTest extends UnitTestCase { $elementInfo = $this->createMock(ElementInfoManager::class); $cfHandlersManager = $this->createMock(ConditionalFieldsHandlersManager::class); $entityDisplayRepository = $this->createMock(EntityDisplayRepositoryInterface::class); - $sutClass = new ConditionalFieldsFormHelper($elementInfo, $cfHandlersManager, $entityDisplayRepository); + $languageManager = $this->createMock(LanguageManager::class); + $sutClass = new ConditionalFieldsFormHelper($elementInfo, $cfHandlersManager, $entityDisplayRepository, $languageManager); // Set up fixtures. $formState = $this->createMock(FormState::class); $formState->expects($this->exactly(1)) ->method('setValue') ->with('conditional_fields_untriggered_dependents', []); - $sutClass->form_state = $formState; + $sutClass->formState = $formState; $sutClass->form = []; // Run the method under test. @@ -172,14 +176,15 @@ class ConditionalFieldsFormHelperTest extends UnitTestCase { $elementInfo = $this->createMock(ElementInfoManager::class); $cfHandlersManager = $this->createMock(ConditionalFieldsHandlersManager::class); $entityDisplayRepository = $this->createMock(EntityDisplayRepositoryInterface::class); - $sutClass = new ConditionalFieldsFormHelper($elementInfo, $cfHandlersManager, $entityDisplayRepository); + $languageManager = $this->createMock(LanguageManager::class); + $sutClass = new ConditionalFieldsFormHelper($elementInfo, $cfHandlersManager, $entityDisplayRepository, $languageManager); // Set up fixtures. $sutClass->form = ['#conditional_fields' => []]; $formState = $this->createMock(FormState::class); $formState->expects($this->exactly(0)) ->method('getFormObject'); - $sutClass->form_state = $formState; + $sutClass->formState = $formState; // Run the method under test. $result = $sutClass->hasConditionalFields(); @@ -198,7 +203,8 @@ class ConditionalFieldsFormHelperTest extends UnitTestCase { $elementInfo = $this->createMock(ElementInfoManager::class); $cfHandlersManager = $this->createMock(ConditionalFieldsHandlersManager::class); $entityDisplayRepository = $this->createMock(EntityDisplayRepositoryInterface::class); - $sutClass = new ConditionalFieldsFormHelper($elementInfo, $cfHandlersManager, $entityDisplayRepository); + $languageManager = $this->createMock(LanguageManager::class); + $sutClass = new ConditionalFieldsFormHelper($elementInfo, $cfHandlersManager, $entityDisplayRepository, $languageManager); // Set up fixtures. $sutClass->form = ['#conditional_fields' => ['test' => 'test']]; @@ -206,7 +212,7 @@ class ConditionalFieldsFormHelperTest extends UnitTestCase { $formState->expects($this->exactly(1)) ->method('getFormObject') ->willReturnOnConsecutiveCalls(new \stdClass()); - $sutClass->form_state = $formState; + $sutClass->formState = $formState; // Run the method under test. $result = $sutClass->hasConditionalFields(); @@ -225,7 +231,8 @@ class ConditionalFieldsFormHelperTest extends UnitTestCase { $elementInfo = $this->createMock(ElementInfoManager::class); $cfHandlersManager = $this->createMock(ConditionalFieldsHandlersManager::class); $entityDisplayRepository = $this->createMock(EntityDisplayRepositoryInterface::class); - $sutClass = new ConditionalFieldsFormHelper($elementInfo, $cfHandlersManager, $entityDisplayRepository); + $languageManager = $this->createMock(LanguageManager::class); + $sutClass = new ConditionalFieldsFormHelper($elementInfo, $cfHandlersManager, $entityDisplayRepository, $languageManager); // Set up fixtures. $sutClass->form = ['#conditional_fields' => ['test' => 'test']]; @@ -234,7 +241,7 @@ class ConditionalFieldsFormHelperTest extends UnitTestCase { $formState->expects($this->exactly(1)) ->method('getFormObject') ->willReturnOnConsecutiveCalls($formObject); - $sutClass->form_state = $formState; + $sutClass->formState = $formState; // Run the method under test. $result = $sutClass->hasConditionalFields();