diff --git a/src/Plugin/facets/widget/CheckboxWidget.php b/src/Plugin/facets/widget/CheckboxWidget.php index 685ffea..bb71fed 100644 --- a/src/Plugin/facets/widget/CheckboxWidget.php +++ b/src/Plugin/facets/widget/CheckboxWidget.php @@ -7,10 +7,13 @@ namespace Drupal\facets\Plugin\facets\widget; +use Drupal\Core\Form\FormInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Core\Url; use Drupal\facets\FacetInterface; use Drupal\facets\Widget\WidgetInterface; +use Symfony\Component\HttpFoundation\RedirectResponse; /** * The checkbox / radios widget. @@ -21,19 +24,11 @@ use Drupal\facets\Widget\WidgetInterface; * description = @Translation("A configurable widget that shows a list of checkboxes"), * ) */ -class CheckboxWidget implements WidgetInterface { +class CheckboxWidget implements WidgetInterface, FormInterface { use StringTranslationTrait; /** - * The link generator. - * - * @var \Drupal\Core\Utility\LinkGeneratorInterface $linkGenerator - * The link generator. - */ - protected $linkGenerator; - - /** * {@inheritdoc} */ public function execute() { @@ -44,33 +39,14 @@ class CheckboxWidget implements WidgetInterface { * {@inheritdoc} */ public function build(FacetInterface $facet) { - /** @var \Drupal\facets\Result\Result[] $results */ - $results = $facet->getResults(); - $items = []; - - $configuration = $facet->getWidgetConfigs(); - $show_numbers = (bool) $configuration['show_numbers']; + $form_builder = \Drupal::getContainer()->get('form_builder'); - foreach ($results as $result) { - if ($result->getCount()) { - // Get the link. - $text = $result->getDisplayValue(); - if ($show_numbers) { - $text .= ' (' . $result->getCount() . ')'; - } - if ($result->isActive()) { - $text = '(-) ' . $text; - } - $link = $this->linkGenerator()->generate($text, $result->getUrl()); - $items[] = $link; - } - } - $build = [ - '#theme' => 'item_list', - '#items' => $items, - ]; + // The form builder's getForm method accepts 1 argument in the interface, + // the form ID. Extra arguments get passed into the form states addBuildInfo + // method. This way we can pass the facet to the ::buildForm method, it uses + // FormState::getBuildInfo to get the facet out. + $build = $form_builder->getForm(static::class, $facet); - $build['#prefix'] = $this->t('Checkboxes'); return $build; } @@ -102,16 +78,94 @@ class CheckboxWidget implements WidgetInterface { } /** - * Gets the link generator. - * - * @return \Drupal\Core\Utility\LinkGeneratorInterface - * The link generator. + * {@inheritdoc} + */ + public function getFormId() { + return 'facets_checkbox_widget'; + } + + /** + * {@inheritdoc} */ - protected function linkGenerator() { - if (!isset($this->linkGenerator)) { - $this->linkGenerator = \Drupal::linkGenerator(); + public function buildForm(array $form, FormStateInterface $form_state) { + + /** @var \Drupal\facets\FacetInterface $facet */ + $build_info = $form_state->getBuildInfo(); + $facet = $build_info['args'][0]; + + /** @var \Drupal\facets\Result\Result[] $results */ + $results = $facet->getResults(); + + $configuration = $facet->getWidgetConfigs(); + $show_numbers = (bool) $configuration['show_numbers']; + $form[$facet->getFieldAlias()] = [ + '#type' => 'checkboxes', + '#title' => $facet->getName(), + ]; + + $options = array(); + foreach ($results as $result) { + $text = $result->getDisplayValue(); + if ($show_numbers) { + $text .= ' (' . $result->getCount() . ')'; + } + + $options[$result->getRawValue()] = $text; + + if ($result->isActive()) { + $form[$facet->getFieldAlias()]['#default_value'][] = $result->getRawValue(); + } } - return $this->linkGenerator; + + $form[$facet->getFieldAlias()]['#options'] = $options; + + $form[$facet->id() . '_submit'] = [ + '#type' => 'submit', + '#value' => 'submit', + ]; + + return $form; } + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) {} + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $values = $form_state->getValues(); + + /** @var \Drupal\facets\FacetInterface $facet */ + $build_info = $form_state->getBuildInfo(); + $facet = $build_info['args'][0]; + + $result_link = FALSE; + $active_items = []; + + foreach ($values[$facet->getFieldAlias()] as $key => $value) { + if ($value !== 0) { + $active_items[] = $value; + } + } + + foreach ($facet->getResults() as $result) { + if (in_array($result->getRawValue(), $active_items)) { + $result_link = $result->getUrl(); + } + } + + // We have an active item, so redirecting to that page. + if ($result_link instanceof Url) { + $result_link->setAbsolute(); + $form_state->setResponse(new RedirectResponse($result_link->toString())); + return; + } + + // Form was submitted, but nothing was selected, so we should submit to the + // facet. + $form_state->setResponse(new RedirectResponse('/' . $facet->getFacetSource()->getPath())); + } } diff --git a/src/Tests/WidgetIntegrationTest.php b/src/Tests/WidgetIntegrationTest.php new file mode 100644 index 0000000..5f91902 --- /dev/null +++ b/src/Tests/WidgetIntegrationTest.php @@ -0,0 +1,83 @@ +drupalLogin($this->adminUser); + + $this->setUpExampleStructure(); + $this->insertExampleContent(); + $this->assertEqual($this->indexItems($this->indexId), 5, '5 items were indexed.'); + } + + /** + * Tests various url integration things. + */ + public function testCheckboxWidget() { + $id = 't'; + $name = 'Facet & checkbox~'; + $facet_add_page = 'admin/config/search/facets/add-facet'; + + $this->drupalGet($facet_add_page); + + $form_values = [ + 'id' => $id, + 'status' => 1, + 'url_alias' => $id, + 'name' => $name, + 'facet_source_id' => 'search_api_views:search_api_test_view:page_1', + 'facet_source_configs[search_api_views:search_api_test_view:page_1][field_identifier]' => 'type', + ]; + $this->drupalPostForm(NULL, ['facet_source_id' => 'search_api_views:search_api_test_view:page_1'], $this->t('Configure facet source')); + $this->drupalPostForm(NULL, $form_values, $this->t('Save')); + $this->drupalPostForm(NULL, ['widget' => 'checkbox'], $this->t('Save')); + + $block_values = [ + 'plugin_id' => 'facet_block:' . $id, + 'settings' => [ + 'region' => 'footer', + 'id' => str_replace('_', '-', $id), + ] + ]; + $this->drupalPlaceBlock($block_values['plugin_id'], $block_values['settings']); + + $this->drupalGet('search-api-test-fulltext'); + $this->drupalPostForm(NULL, array('type[item]' => 'item'), $this->t('submit')); + $this->assertFieldChecked('edit-type-item'); + } + +} diff --git a/tests/src/Unit/Plugin/widget/CheckboxWidgetTest.php b/tests/src/Unit/Plugin/widget/CheckboxWidgetTest.php index f24ee45..187dddd 100644 --- a/tests/src/Unit/Plugin/widget/CheckboxWidgetTest.php +++ b/tests/src/Unit/Plugin/widget/CheckboxWidgetTest.php @@ -7,6 +7,7 @@ namespace Drupal\Tests\facets\Unit\Plugin\widget; +use Drupal\Core\Form\FormState; use Drupal\facets\Entity\Facet; use Drupal\facets\Plugin\facets\widget\CheckboxWidget; use Drupal\facets\Result\Result; @@ -23,7 +24,7 @@ class CheckboxWidgetTest extends UnitTestCase { /** * The processor to be tested. * - * @var \drupal\facets\Widget\WidgetInterface + * @var \Drupal\facets\Plugin\facets\widget\CheckboxWidget */ protected $widget; @@ -53,19 +54,16 @@ class CheckboxWidgetTest extends UnitTestCase { } $this->originalResults = $original_results; - $link_generator = $this->getMockBuilder('\Drupal\Core\Utility\LinkGenerator') + $form_builder = $this->getMockBuilder('\Drupal\Core\Form\FormBuilder') ->disableOriginalConstructor() ->getMock(); - $link_generator->expects($this->atLeastOnce()) - ->method('generate') - ->will($this->returnArgument(0)); $string_translation = $this->getMockBuilder('\Drupal\Core\StringTranslation\TranslationManager') ->disableOriginalConstructor() ->getMock(); $container_builder = new ContainerBuilder(); - $container_builder->set('link_generator', $link_generator); + $container_builder->set('form_builder', $form_builder); $container_builder->set('string_translation', $string_translation); \Drupal::setContainer($container_builder); @@ -78,34 +76,74 @@ class CheckboxWidgetTest extends UnitTestCase { public function testDefaultSettings() { $facet = new Facet([], 'facet'); $facet->setResults($this->originalResults); - - $output = $this->widget->build($facet); - - $this->assertInternalType('array', $output); - $this->assertCount(4, $output['#items']); - - $expected_links = ['Llama', 'Badger', 'Duck', 'Alpaca']; + $facet->setFieldIdentifier('test_field'); + + $formState = new FormState(); + $formState->addBuildInfo('args', [$facet]); + $form = []; + $built_form = $this->widget->buildForm($form, $formState); + + $this->assertInternalType('array', $built_form); + $this->assertCount(4, $built_form['test_field']['#options']); + $this->assertEquals('checkboxes', $built_form['test_field']['#type']); + + $expected_links = [ + 'llama' => 'Llama', + 'badger' => 'Badger', + 'duck' => 'Duck', + 'alpaca' => 'Alpaca' + ]; foreach ($expected_links as $index => $value) { - $this->assertEquals($value, $output['#items'][$index]); + $this->assertEquals($value, $built_form['test_field']['#options'][$index]); } } /** - * Test widget with show numbers enabled. + * Test widget, make sure hiding and showing numbers works. */ - public function testShowAmount() { + public function testHideNumbers() { + $original_results = $this->originalResults; + $original_results[1]->setActiveState(TRUE); + $facet = new Facet([], 'facet'); - $facet->setResults($this->originalResults); + $facet->setResults($original_results); + $facet->setFieldIdentifier('test__field'); + $facet->setWidgetConfigs(['show_numbers' => 0]); + + $formState = new FormState(); + $formState->addBuildInfo('args', [$facet]); + $form = []; + $built_form = $this->widget->buildForm($form, $formState); + + $this->assertInternalType('array', $built_form); + $this->assertCount(4, $built_form['test__field']['#options']); + $expected_links = [ + 'llama' => 'Llama', + 'badger' => 'Badger', + 'duck' => 'Duck', + 'alpaca' => 'Alpaca' + ]; + foreach ($expected_links as $index => $value) { + $this->assertEquals($value, $built_form['test__field']['#options'][$index]); + } + + // Enable the 'show_numbers' setting again to make sure that the switch + // between those settings works. $facet->setWidgetConfigs(['show_numbers' => 1]); - $output = $this->widget->build($facet); + $built_form = $this->widget->buildForm($form, $formState); - $this->assertInternalType('array', $output); - $this->assertCount(4, $output['#items']); + $this->assertInternalType('array', $built_form); + $this->assertCount(4, $built_form['test__field']['#options']); - $expected_links = ['Llama (10)', 'Badger (20)', 'Duck (15)', 'Alpaca (9)']; + $expected_links = [ + 'llama' => 'Llama (10)', + 'badger' => 'Badger (20)', + 'duck' => 'Duck (15)', + 'alpaca' => 'Alpaca (9)', + ]; foreach ($expected_links as $index => $value) { - $this->assertEquals($value, $output['#items'][$index]); + $this->assertEquals($value, $built_form['test__field']['#options'][$index]); } }