diff --git a/config/schema/facets.facet.schema.yml b/config/schema/facets.facet.schema.yml index 52a6813..3f3fff4 100644 --- a/config/schema/facets.facet.schema.yml +++ b/config/schema/facets.facet.schema.yml @@ -95,7 +95,18 @@ facets.facet.*: condition.plugin.other_facet: type: condition.plugin mapping: - facet_value: - type: string facets: - type: string + type: sequence + sequence: + type: mapping + label: 'Facet Conditions' + mapping: + condition: + type: string + label: 'Condition type' + values: + type: string + label: 'Comma separated values' + negate: + type: integer + label: 'Negate condition' diff --git a/src/Plugin/Condition/OtherFacet.php b/src/Plugin/Condition/OtherFacet.php index 3b0b099..647635f 100644 --- a/src/Plugin/Condition/OtherFacet.php +++ b/src/Plugin/Condition/OtherFacet.php @@ -101,30 +101,75 @@ class OtherFacet extends ConditionPluginBase implements ContainerFactoryPluginIn /** * {@inheritdoc} */ - public function buildConfigurationForm(array $form, FormStateInterface $form_state) { - $options = []; + public function defaultConfiguration() { + $config = [ + 'facets' => [], + 'facet_value' => '', + ]; + return $config + parent::defaultConfiguration(); + } + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { // Loop over all defined blocks and filter them by provider, this builds an // array of blocks that are provided by the facets module. foreach ($this->blockManager->getDefinitions() as $definition) { if ($definition['provider'] == 'facets') { - $options[$definition['id']] = $definition['label']; + $form[$definition['id'] . '_label'] = [ + '#title' => $definition['label'], + '#type' => 'label', + ]; + + $form[$definition['id'] . '_enable'] = [ + '#title' => t('Enable condition'), + '#type' => 'checkbox', + '#default_value' => !empty($this->configuration['facets'][$definition['id']]), + ]; + + $form[$definition['id'] . '_condition'] = [ + '#title' => t('Condition mode'), + '#type' => 'radios', + '#options' => [ + 'presence' => t('Check for facet being present'), + 'not_empty' => t('Check for facet being selected / not empty'), + 'values' => t('Check for facet being set to specific values'), + ], + '#default_value' => empty($this->configuration['facets'][$definition['id']]['condition']) ? NULL : $this->configuration['facets'][$definition['id']]['condition'], + '#states' => [ + 'visible' => [ + ':input[name="visibility[other_facet][' . $definition['id'] . '_enable]"]' => ['checked' => TRUE], + ], + ], + ]; + + $form[$definition['id'] . '_values'] = [ + '#title' => t('Values'), + '#type' => 'textfield', + '#default_value' => empty($this->configuration['facets'][$definition['id']]['values']) ? '' : $this->configuration['facets'][$definition['id']]['values'], + '#description' => $this->t('Enter a comma separated list of values.'), + '#states' => [ + 'visible' => [ + ':input[name="visibility[other_facet][' . $definition['id'] . '_enable]"]' => ['checked' => TRUE], + ':input[name="visibility[other_facet][' . $definition['id'] . '_condition]"]' => ['value' => 'values'], + ], + ], + ]; + + $form[$definition['id'] . '_negate'] = [ + '#title' => t('Negate condition'), + '#type' => 'checkbox', + '#default_value' => !empty($this->configuration['facets'][$definition['id']]['negate']), + '#states' => [ + 'visible' => [ + ':input[name="visibility[other_facet][' . $definition['id'] . '_enable]"]' => ['checked' => TRUE], + ], + ], + ]; } } - $form['facets'] = [ - '#title' => $this->t('Other facet blocks'), - '#type' => 'radios', - '#options' => $options, - '#default_value' => $this->configuration['facets'], - ]; - $form['facet_value'] = [ - '#title' => $this->t('Facet value'), - '#description' => $this->t('Only applies when a facet is already selected.'), - '#type' => 'textfield', - '#default_value' => $this->configuration['facet_value'], - ]; - return parent::buildConfigurationForm($form, $form_state); } @@ -132,8 +177,21 @@ class OtherFacet extends ConditionPluginBase implements ContainerFactoryPluginIn * {@inheritdoc} */ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { - $this->configuration['facets'] = $form_state->getValue('facets'); - $this->configuration['facet_value'] = $form_state->getValue('facet_value'); + $this->configuration['facets'] = []; + foreach ($this->blockManager->getDefinitions() as $definition) { + if ($definition['provider'] == 'facets') { + if ($form_state->getValue($definition['id'] . '_enable')) { + $this->configuration['facets'][$definition['id']] = [ + 'condition' => $form_state->getValue($definition['id'] . '_condition'), + 'negate' => $form_state->getValue($definition['id'] . '_negate'), + ]; + + if ($this->configuration['facets'][$definition['id']]['condition'] == 'values') { + $this->configuration['facets'][$definition['id']]['values'] = $form_state->getValue($definition['id'] . '_values'); + } + } + } + } parent::submitConfigurationForm($form, $form_state); } @@ -142,8 +200,7 @@ class OtherFacet extends ConditionPluginBase implements ContainerFactoryPluginIn */ public function summary() { return $this->t( - 'The facet is @facet also rendered on the same page.', - ['@facet' => $this->configuration['facets']] + 'This block depends on @facet facet conditions being met.', ['@facet' => count($this->configuration['facets'])] ); } @@ -151,54 +208,65 @@ class OtherFacet extends ConditionPluginBase implements ContainerFactoryPluginIn * {@inheritdoc} */ public function evaluate() { - $allowed_facet_value = $this->configuration['facet_value']; - $allowed_facets = $this->configuration['facets']; + + $enabled_conditions = $this->configuration['facets']; // Return as early as possible when there are no settings for allowed // facets. - if (empty($allowed_facets)) { + if (!is_array($enabled_conditions) || empty($enabled_conditions)) { return TRUE; } - /** @var \Drupal\facets\Plugin\Block\FacetBlock $block_plugin */ - $block_plugin = $this->blockManager->createInstance($allowed_facets); + $return = FALSE; - // Allowed facet value is not set, so we only have to check if the block is - // shown here by running the access method on the block plugin with the - // currently logged in user. - if (empty($allowed_facet_value)) { - return $block_plugin->access($this->currentUser); - } + foreach ($enabled_conditions as $facet_block_id => $condition_settings) { - // The block plugin id is saved in the schema: BasePluginID:FacetID. This - // means we can explode the ID on ':' and the facet id is in the last part - // of that result. - $block_plugin_id = $block_plugin->getPluginId(); - $facet_id = explode(PluginBase::DERIVATIVE_SEPARATOR, $block_plugin_id)[1]; + /** @var \Drupal\facets\Plugin\Block\FacetBlock $block_plugin */ + $block_plugin = $this->blockManager->createInstance($facet_block_id); - /** @var \Drupal\facets\FacetInterface $facet */ - $facet = $this->facetStorage->load($facet_id); - $facet = $this->facetManager->returnProcessedFacet($facet); + // If loops allow to skip expensive code. A switch loop on 'condition' + // would work too, but would get complicated as well. + if ($condition_settings['condition'] == 'presence') { + $return = $block_plugin->access($this->currentUser); + } + else { + // The block plugin id is saved in the schema: BasePluginID:FacetID. + // This means we can explode the ID on ':' and the facet id is in the + // last part of that result. + $block_plugin_id = $block_plugin->getPluginId(); + $facet_id = explode(PluginBase::DERIVATIVE_SEPARATOR, $block_plugin_id)[1]; + + /** @var \Drupal\facets\FacetInterface $facet */ + $facet = $this->facetStorage->load($facet_id); + $facet = $this->facetManager->returnProcessedFacet($facet); - foreach ($facet->getResults() as $result) { - $is_value = $result->getRawValue() == $allowed_facet_value || $result->getDisplayValue() == $allowed_facet_value; - if ($is_value && $result->isActive()) { - return TRUE; + if ($condition_settings['condition'] == 'not_empty') { + $return = !empty($facet->getActiveItems()); + } + else { + if ($condition_settings['condition'] == 'values') { + $values = explode(',', $condition_settings['values']); + foreach ($facet->getResults() as $result) { + if ( + $result->isActive() + && ( + in_array($result->getRawValue(), $values) + || in_array($result->getDisplayValue(), $values) + ) + ) { + $return = TRUE; + } + } + } + } } - } - return FALSE; - } + if (!empty($condition_settings['negate'])) { + $return = !$return; + } + } - /** - * {@inheritdoc} - */ - public function defaultConfiguration() { - $config = [ - 'facets' => '', - 'facet_value' => '', - ]; - return $config + parent::defaultConfiguration(); + return $return; } } diff --git a/tests/src/Functional/IntegrationTest.php b/tests/src/Functional/IntegrationTest.php index 51554be..40ea091 100644 --- a/tests/src/Functional/IntegrationTest.php +++ b/tests/src/Functional/IntegrationTest.php @@ -243,8 +243,9 @@ class IntegrationTest extends FacetsTestBase { // Change the visiblity settings of the DependingFacet. $this->drupalGet('admin/structure/block/manage/dependingfacet'); $edit = [ - 'visibility[other_facet][facets]' => 'facet_block:dependablefacet', - 'visibility[other_facet][facet_value]' => 'item', + 'visibility[other_facet][facet_block:dependablefacet_enable]' => 1, + 'visibility[other_facet][facet_block:dependablefacet_condition]' => 'values', + 'visibility[other_facet][facet_block:dependablefacet_values]' => 'item', ]; $this->drupalPostForm(NULL, $edit, 'Save block'); $this->assertText('The block configuration has been saved.'); @@ -271,8 +272,9 @@ class IntegrationTest extends FacetsTestBase { // Change the visibility settings to negate the previous settings. $this->drupalGet('admin/structure/block/manage/dependingfacet'); $edit = [ - 'visibility[other_facet][facets]' => 'facet_block:dependablefacet', - 'visibility[other_facet][facet_value]' => 'item', + 'visibility[other_facet][facet_block:dependablefacet_enable]' => 1, + 'visibility[other_facet][facet_block:dependablefacet_condition]' => 'values', + 'visibility[other_facet][facet_block:dependablefacet_values]' => 'item', 'visibility[other_facet][negate]' => TRUE, ]; $this->drupalPostForm(NULL, $edit, 'Save block'); diff --git a/tests/src/Unit/Plugin/Condition/OtherFacetTest.php b/tests/src/Unit/Plugin/Condition/OtherFacetTest.php index 2241a5a..0273768 100644 --- a/tests/src/Unit/Plugin/Condition/OtherFacetTest.php +++ b/tests/src/Unit/Plugin/Condition/OtherFacetTest.php @@ -53,7 +53,15 @@ class OtherFacetTest extends UnitTestCase { $facet_manager = $this->getMockBuilder('\Drupal\facets\FacetManager\DefaultFacetManager') ->disableOriginalConstructor() ->getMock(); - $sut = new OtherFacet($storage, $manager, $user, $facet_manager, ['facets' => 'test'], 'other_facet', ''); + $configuration = [ + 'facets' => [ + 'facet_block:test' => [ + 'enable' => 1, + 'condition' => 'presence', + ], + ], + ]; + $sut = new OtherFacet($storage, $manager, $user, $facet_manager, $configuration, 'other_facet', ''); $evaluation = $sut->evaluate(); $this->assertTrue($evaluation); @@ -80,7 +88,15 @@ class OtherFacetTest extends UnitTestCase { $facet_manager = $this->getMockBuilder('\Drupal\facets\FacetManager\DefaultFacetManager') ->disableOriginalConstructor() ->getMock(); - $sut = new OtherFacet($storage, $manager, $user, $facet_manager, ['facets' => 'test'], 'other_facet', ''); + $configuration = [ + 'facets' => [ + 'facet_block:test' => [ + 'enable' => 1, + 'condition' => 'presence', + ], + ], + ]; + $sut = new OtherFacet($storage, $manager, $user, $facet_manager, $configuration, 'other_facet', ''); $evaluation = $sut->evaluate(); $this->assertFalse($evaluation); @@ -127,7 +143,15 @@ class OtherFacetTest extends UnitTestCase { ->with($facet) ->willReturn($facet); - $configuration = ['facets' => 'test', 'facet_value' => 'llama']; + $configuration = [ + 'facets' => [ + 'facet_block:test' => [ + 'enable' => 1, + 'condition' => 'values', + 'values' => 'llama', + ], + ], + ]; $sut = new OtherFacet($storage, $manager, $user, $facet_manager, $configuration, 'other_facet', ''); $evaluation = $sut->evaluate(); @@ -175,7 +199,15 @@ class OtherFacetTest extends UnitTestCase { ->with($facet) ->willReturn($facet); - $configuration = ['facets' => 'test', 'facet_value' => 'llama']; + $configuration = [ + 'facets' => [ + 'facet_block:test' => [ + 'enable' => 1, + 'condition' => 'values', + 'values' => 'llama', + ], + ], + ]; $sut = new OtherFacet($storage, $manager, $user, $facet_manager, $configuration, 'other_facet', ''); $evaluation = $sut->evaluate();