summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorborisson_2016-05-13 10:41:19 +0200
committerJoris Vercammen2016-05-13 10:41:19 +0200
commit77ea6758f873a6facca800747df9acbc995890ac (patch)
tree66d74ec8e8a639e729414ddb99d0fb10da0bd873
parent30146cf0d629a8c9fc4253f64e2924054ecf839d (diff)
Issue #2713875 by borisson_, StryKaizer, stijn26: Use GET request for dropdown widget
-rw-r--r--facets.libraries.yml10
-rw-r--r--js/dropdown-widget.js66
-rw-r--r--src/Form/DropdownWidgetForm.php111
-rw-r--r--src/Plugin/facets/widget/DropdownWidget.php67
-rw-r--r--src/Tests/WidgetIntegrationTest.php12
-rw-r--r--tests/src/Unit/Form/SelectWidgetFormTest.php159
-rw-r--r--tests/src/Unit/Plugin/widget/DropdownWidgetTest.php111
-rw-r--r--tests/src/Unit/Plugin/widget/SelectWidgetTest.php83
8 files changed, 242 insertions, 377 deletions
diff --git a/facets.libraries.yml b/facets.libraries.yml
index 62daaf3..23cbc63 100644
--- a/facets.libraries.yml
+++ b/facets.libraries.yml
@@ -28,3 +28,13 @@ drupal.facets.checkbox-widget:
dependencies:
- core/jquery
- core/drupal
+ - core/jquery.once
+
+drupal.facets.dropdown-widget:
+ version: VERSION
+ js:
+ js/dropdown-widget.js: {}
+ dependencies:
+ - core/jquery
+ - core/drupal
+ - core/jquery.once \ No newline at end of file
diff --git a/js/dropdown-widget.js b/js/dropdown-widget.js
new file mode 100644
index 0000000..8b4e71b
--- /dev/null
+++ b/js/dropdown-widget.js
@@ -0,0 +1,66 @@
+/**
+ * @file
+ * Transforms links into a dropdown list.
+ */
+
+(function ($) {
+
+ 'use strict';
+
+ Drupal.facets = {};
+ Drupal.behaviors.facetsDropdownWidget = {
+ attach: function (context, settings) {
+ Drupal.facets.makeDropdown();
+ }
+ };
+
+ /**
+ * Turns all facet links into a dropdown with options for every link.
+ */
+ Drupal.facets.makeDropdown = function () {
+ // Find all dropdown facet links and turn them into an option.
+ $('.js-facets-dropdown-links').once('facets-dropdown-transform').each(function () {
+ var $links = $(this).find('.facet-item a');
+ var $dropdown = $('<select class="facets-dropdown" />');
+
+ // Add empty text option first.
+ var default_option_label = $(this).data('facet-default-option-label');
+ var $default_option = $('<option />')
+ .attr('value', '')
+ .text(default_option_label);
+
+ var has_active = false;
+ $links.each(function () {
+ var $link = $(this);
+ var active = $link.hasClass('is-active');
+ var $option = $('<option />')
+ .attr('value', $link.attr('href'));
+ if (active) {
+ has_active = true;
+ // Set empty text value to this link to unselect facet.
+ $default_option.attr('value', $link.attr('href'));
+
+ $option.attr('selected', 'selected');
+ $link.find('.facet-deactivate').remove();
+ }
+ $option.html($link.html());
+ $dropdown.append($option);
+ });
+
+ // Go to the selected option when it's clicked.
+ $dropdown.on('change', function () {
+ window.location.href = $(this).val();
+ });
+
+ // Append empty text option.
+ if (!has_active) {
+ $default_option.attr('selected', 'selected');
+ }
+ $dropdown.prepend($default_option);
+
+ // Append dropdown.
+ $(this).find('.content').html($dropdown);
+ });
+ };
+
+})(jQuery);
diff --git a/src/Form/DropdownWidgetForm.php b/src/Form/DropdownWidgetForm.php
deleted file mode 100644
index afd09d9..0000000
--- a/src/Form/DropdownWidgetForm.php
+++ /dev/null
@@ -1,111 +0,0 @@
-<?php
-
-namespace Drupal\facets\Form;
-
-use Drupal\Core\Form\BaseFormIdInterface;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Drupal\facets\FacetInterface;
-use Symfony\Component\HttpFoundation\RedirectResponse;
-
-/**
- * The dropdown widget form.
- */
-class DropdownWidgetForm implements BaseFormIdInterface {
-
- use StringTranslationTrait;
-
- /**
- * The facet to build the form for.
- *
- * @var FacetInterface $facet
- */
- protected $facet;
-
- /**
- * Class constructor.
- *
- * @param \Drupal\facets\FacetInterface $facet
- * The facet to build the form for.
- */
- public function __construct(FacetInterface $facet) {
- $this->facet = $facet;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getBaseFormId() {
- return 'facets_dropdown_widget';
- }
-
- /**
- * {@inheritdoc}
- */
- public function getFormId() {
- return $this->getBaseFormId() . '__' . $this->facet->id();
- }
-
- /**
- * {@inheritdoc}
- */
- public function buildForm(array $form, FormStateInterface $form_state) {
- $results = $this->facet->getResults();
-
- $configuration = $this->facet->getWidgetConfigs();
- $form[$this->facet->getFieldAlias()] = [
- '#type' => 'select',
- '#title' => $this->facet->getName(),
- '#default_value' => '_none',
- ];
-
- $options = [];
- $active_result_url = '_none';
- foreach ($results as $result) {
- $result_url = $result->getUrl()->setAbsolute()->toString();
-
- $text = $result->getDisplayValue();
- if (!empty($configuration['show_numbers'])) {
- $text .= ' (' . $result->getCount() . ')';
- }
-
- if ($result->isActive()) {
- $options['_none'] = $text;
- $active_result_url = $result_url;
- }
- else {
- $options[$result_url] = $text;
- }
- }
-
- $options = [$active_result_url => $this->t('- All -')] + $options;
-
- $form[$this->facet->getFieldAlias()]['#options'] = $options;
-
- $form[$this->facet->getFieldAlias() . '_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) {
- $field_alias = $this->facet->getFieldAlias();
- $form_value = $form_state->getValue($field_alias);
- if ($form_value != '_none') {
- $form_state->setResponse(new RedirectResponse($form_value));
- }
- }
-
-}
diff --git a/src/Plugin/facets/widget/DropdownWidget.php b/src/Plugin/facets/widget/DropdownWidget.php
index 5a90347..3062225 100644
--- a/src/Plugin/facets/widget/DropdownWidget.php
+++ b/src/Plugin/facets/widget/DropdownWidget.php
@@ -3,10 +3,7 @@
namespace Drupal\facets\Plugin\facets\widget;
use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\facets\FacetInterface;
-use Drupal\facets\Form\DropdownWidgetForm;
-use Drupal\facets\Widget\WidgetInterface;
/**
* The dropdown widget.
@@ -17,41 +14,83 @@ use Drupal\facets\Widget\WidgetInterface;
* description = @Translation("A configurable widget that shows a dropdown."),
* )
*/
-class DropdownWidget implements WidgetInterface {
-
- use StringTranslationTrait;
+class DropdownWidget extends LinksWidget {
/**
- * {@inheritdoc}
+ * The facet the widget is being built for.
+ *
+ * @var \Drupal\facets\FacetInterface
*/
- public function build(FacetInterface $facet) {
- $form_builder = \Drupal::getContainer()->get('form_builder');
- $form_object = new DropdownWidgetForm($facet);
- return $form_builder->getForm($form_object);
- }
+ protected $facet;
/**
* {@inheritdoc}
*/
- public function getQueryType($query_types) {
- return $query_types['string'];
+ public function build(FacetInterface $facet) {
+
+ $this->facet = $facet;
+
+ /** @var \Drupal\facets\Result\Result[] $results */
+ $results = $facet->getResults();
+ $items = [];
+
+ $configuration = $facet->getWidgetConfigs();
+ $this->showNumbers = empty($configuration['show_numbers']) ? FALSE : (bool) $configuration['show_numbers'];
+ $this->defaultOptionLabel = isset($configuration['default_option_label']) ? $configuration['default_option_label'] : '';
+
+ foreach ($results as $result) {
+ if (is_null($result->getUrl())) {
+ $text = $this->extractText($result);
+ $items[] = ['#markup' => $text];
+ }
+ else {
+ $items[] = $this->buildListItems($result);
+ }
+ }
+
+ $build = [
+ '#theme' => 'item_list',
+ '#items' => $items,
+ '#attributes' => ['class' => ['js-facets-dropdown-links'], 'data-facet-default-option-label' => $this->defaultOptionLabel],
+ '#cache' => [
+ 'contexts' => [
+ 'url.path',
+ 'url.query_args',
+ ],
+ ],
+ ];
+ $build['#attached']['library'][] = 'facets/drupal.facets.dropdown-widget';
+
+ return $build;
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state, $config) {
+ $message = $this->t('This widget requires "Make sure only one result can be shown." to be enabled to behave as a standard dropdown.');
+ $form['warning'] = [
+ '#markup' => '<div class="messages messages--warning">' . $message . '</div>',
+ ];
$form['show_numbers'] = [
'#type' => 'checkbox',
'#title' => $this->t('Show the amount of results'),
];
+ $form['default_option_label'] = [
+ '#type' => 'textfield',
+ '#title' => $this->t('Default option label'),
+ ];
+
if (!is_null($config)) {
$widget_configs = $config->get('widget_configs');
if (isset($widget_configs['show_numbers'])) {
$form['show_numbers']['#default_value'] = $widget_configs['show_numbers'];
}
+ if (isset($widget_configs['default_option_label'])) {
+ $form['default_option_label']['#default_value'] = $widget_configs['default_option_label'];
+ }
}
return $form;
diff --git a/src/Tests/WidgetIntegrationTest.php b/src/Tests/WidgetIntegrationTest.php
index 5a49f1a..b7a8fa7 100644
--- a/src/Tests/WidgetIntegrationTest.php
+++ b/src/Tests/WidgetIntegrationTest.php
@@ -2,8 +2,6 @@
namespace Drupal\facets\Tests;
-use Drupal\Core\Url;
-
/**
* Tests the overall functionality of the Facets admin UI.
*
@@ -82,15 +80,9 @@ class WidgetIntegrationTest extends WebTestBase {
$this->drupalPostForm(NULL, ['widget' => 'select'], $this->t('Save'));
$this->drupalGet('search-api-test-fulltext');
- $this->assertField('edit-type', 'Dropdown is visible.');
$this->assertText('Displaying 5 search results');
-
- $url = Url::fromUserInput('/search-api-test-fulltext', ['query' => ['f[0]' => 'select_widget:item']]);
- $url->setAbsolute();
-
- $this->drupalPostForm(NULL, ['type' => $url->toString()], $this->t('submit'));
- $this->assertResponse(200);
- $this->assertText('Displaying 3 search results');
+ $this->assertLink('item');
+ $this->assertLink('article');
}
/**
diff --git a/tests/src/Unit/Form/SelectWidgetFormTest.php b/tests/src/Unit/Form/SelectWidgetFormTest.php
deleted file mode 100644
index d237cbf..0000000
--- a/tests/src/Unit/Form/SelectWidgetFormTest.php
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php
-
-namespace Drupal\Tests\facets\Unit\Form;
-
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Drupal\Core\Form\FormState;
-use Drupal\Core\Routing\UrlGeneratorInterface;
-use Drupal\Core\StringTranslation\TranslationManager;
-use Drupal\Core\Url;
-use Drupal\facets\Entity\Facet;
-use Drupal\facets\Form\DropdownWidgetForm;
-use Drupal\facets\Result\Result;
-use Drupal\Tests\UnitTestCase;
-
-/**
- * Unit test for the select widget form.
- *
- * @group facets
- */
-class SelectWidgetFormTest extends UnitTestCase {
-
- /**
- * An array containing the results before the processor has ran.
- *
- * @var \Drupal\facets\Result\Result[]
- */
- protected $originalResults;
-
- /**
- * Creates a new processor object for use in the tests.
- */
- protected function setUp() {
- parent::setUp();
-
- $result = new Result('llama', 'Llama', 10);
- $result->setUrl(new Url('llama'));
- $result2 = new Result('badger', 'Badger', 20);
- $result2->setUrl(new Url('badger'));
- $result3 = new Result('duck', 'Duck', 15);
- $result3->setUrl(new Url('duck'));
- $result4 = new Result('alpaca', 'Alpaca', 9);
- $result4->setUrl(new Url('alpaca'));
-
- $this->originalResults = [
- $result,
- $result2,
- $result3,
- $result4,
- ];
-
- $url_generator = $this->getMock(UrlGeneratorInterface::class);
- $url_generator->expects($this->any())
- ->method('generateFromRoute')
- ->willReturnCallback(function ($param) {
- return 'http://test/' . $param;
- });
- $string_translation = $this->getMockBuilder(TranslationManager::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $container_builder = new ContainerBuilder();
- $container_builder->set('url_generator', $url_generator);
- $container_builder->set('string_translation', $string_translation);
- \Drupal::setContainer($container_builder);
- }
-
- /**
- * Tests widget form with default settings.
- */
- public function testDefaultSettings() {
- $facet = new Facet(['id' => 'zoo_animal'], 'facet');
- $facet->setResults($this->originalResults);
- $facet->setFieldIdentifier('zoo_animal');
-
- $form_state = new FormState();
- $form_state->addBuildInfo('args', [$facet]);
- $form = [];
-
- $widget_form = new DropdownWidgetForm($facet);
- $built_form = $widget_form->buildForm($form, $form_state);
-
- $this->assertInternalType('array', $built_form);
- $this->assertCount(5, $built_form['zoo_animal']['#options']);
- $this->assertEquals('select', $built_form['zoo_animal']['#type']);
-
- $expected_links = [
- 'http://test/llama' => 'Llama',
- 'http://test/badger' => 'Badger',
- 'http://test/duck' => 'Duck',
- 'http://test/alpaca' => 'Alpaca',
- ];
- foreach ($expected_links as $index => $value) {
- $this->assertEquals($value, $built_form['zoo_animal']['#options'][$index]);
- }
- $this->assertEquals(array('zoo_animal', 'zoo_animal_submit'), array_keys($built_form));
- }
-
- /**
- * Tests widget form, make sure hiding and showing numbers works.
- */
- public function testHideNumbers() {
- $facet = new Facet([], 'facet');
- $facet->setResults($this->originalResults);
- $facet->setFieldIdentifier('zoo__animal');
- $facet->setWidgetConfigs(['show_numbers' => 0]);
-
- $form_state = new FormState();
- $form_state->addBuildInfo('args', [$facet]);
- $form = [];
-
- $widget_form = new DropdownWidgetForm($facet);
- $built_form = $widget_form->buildForm($form, $form_state);
-
- $this->assertInternalType('array', $built_form);
- $this->assertCount(5, $built_form['zoo__animal']['#options']);
- $expected_links = [
- 'http://test/llama' => 'Llama',
- 'http://test/badger' => 'Badger',
- 'http://test/duck' => 'Duck',
- 'http://test/alpaca' => 'Alpaca',
- ];
- foreach ($expected_links as $index => $value) {
- $this->assertEquals($value, $built_form['zoo__animal']['#options'][$index]);
- }
-
- // Enable the 'show_numbers' setting again to make sure that the switch
- // between those settings works.
- $facet->setWidgetConfigs(['show_numbers' => 1]);
-
- $built_form = $widget_form->buildForm($form, $form_state);
- $this->assertInternalType('array', $built_form);
- $this->assertCount(5, $built_form['zoo__animal']['#options']);
-
- $expected_links = [
- 'http://test/llama' => 'Llama (10)',
- 'http://test/badger' => 'Badger (20)',
- 'http://test/duck' => 'Duck (15)',
- 'http://test/alpaca' => 'Alpaca (9)',
- ];
- foreach ($expected_links as $index => $value) {
- $this->assertEquals($value, $built_form['zoo__animal']['#options'][$index]);
- }
- }
-
- /**
- * Tests form default methods.
- */
- public function testForm() {
- $facet = new Facet(['id' => 'donkey'], 'facet');
- $facet->setResults($this->originalResults);
- $facet->setFieldIdentifier('donkey');
-
- $form = new DropdownWidgetForm($facet);
-
- $this->assertEquals('facets_dropdown_widget', $form->getBaseFormId());
- $this->assertEquals('facets_dropdown_widget__donkey', $form->getFormId());
- }
-
-}
diff --git a/tests/src/Unit/Plugin/widget/DropdownWidgetTest.php b/tests/src/Unit/Plugin/widget/DropdownWidgetTest.php
new file mode 100644
index 0000000..4eef01f
--- /dev/null
+++ b/tests/src/Unit/Plugin/widget/DropdownWidgetTest.php
@@ -0,0 +1,111 @@
+<?php
+
+namespace Drupal\Tests\facets\Unit\Plugin\widget;
+
+use Drupal\Component\Render\FormattableMarkup;
+use Drupal\Core\Url;
+use Drupal\facets\Entity\Facet;
+use Drupal\facets\Plugin\facets\widget\DropdownWidget;
+use Drupal\facets\Result\Result;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Unit test for widget.
+ *
+ * @group facets
+ */
+class DropdownWidgetTest extends UnitTestCase {
+
+ /**
+ * The processor to be tested.
+ *
+ * @var \Drupal\facets\Plugin\facets\widget\DropdownWidget
+ */
+ protected $widget;
+
+ /**
+ * An array containing the results before the processor has ran.
+ *
+ * @var \Drupal\facets\Result\Result[]
+ */
+ protected $originalResults;
+
+ /**
+ * Creates a new processor object for use in the tests.
+ */
+ protected function setUp() {
+ parent::setUp();
+
+ /** @var \Drupal\facets\Result\Result[] $original_results */
+ $original_results = [
+ new Result('llama', 'Llama', 10),
+ new Result('badger', 'Badger', 20),
+ new Result('duck', 'Duck', 15),
+ new Result('alpaca', 'Alpaca', 9),
+ ];
+
+ foreach ($original_results as $original_result) {
+ $original_result->setUrl(new Url('test'));
+ }
+ $this->originalResults = $original_results;
+
+ $this->widget = new DropdownWidget();
+ }
+
+ /**
+ * Tests widget without filters.
+ */
+ public function testNoFilterResults() {
+ $facet = new Facet([], 'facet');
+ $facet->setResults($this->originalResults);
+ $facet->setWidgetConfigs(['show_numbers' => 1]);
+
+ $output = $this->widget->build($facet);
+
+ $this->assertInternalType('array', $output);
+ $this->assertCount(4, $output['#items']);
+
+ $this->assertEquals(['js-facets-dropdown-links'], $output['#attributes']['class']);
+
+ $expected_links = [
+ $this->buildLinkAssertion('Llama', 10),
+ $this->buildLinkAssertion('Badger', 20),
+ $this->buildLinkAssertion('Duck', 15),
+ $this->buildLinkAssertion('Alpaca', 9),
+ ];
+ foreach ($expected_links as $index => $value) {
+ $this->assertInternalType('array', $output['#items'][$index]);
+ $this->assertEquals($value, $output['#items'][$index]['#title']);
+ $this->assertInstanceOf(FormattableMarkup::class, $output['#items'][$index]['#title']);
+ $this->assertEquals('link', $output['#items'][$index]['#type']);
+ $this->assertEquals(['facet-item'], $output['#items'][$index]['#wrapper_attributes']['class']);
+ }
+ }
+
+ /**
+ * Build a formattable markup object to use in the other tests.
+ *
+ * @param string $text
+ * Text to display.
+ * @param int $count
+ * Number of results.
+ * @param bool $active
+ * Link is active.
+ * @param bool $show_numbers
+ * Numbers are displayed.
+ *
+ * @return \Drupal\Component\Render\FormattableMarkup
+ * Formattable markup object for link.
+ */
+ private function buildLinkAssertion($text, $count = 0, $active = FALSE, $show_numbers = TRUE) {
+ $text = new FormattableMarkup('@text', ['@text' => $text, '@count' => $count]);
+ if ($show_numbers !== FALSE) {
+ $text->string .= ' <span class="facet-count">(@count)</span>';
+ }
+ if ($active) {
+ $text->string = '<span class="facet-deactivate">(-)</span> ' . $text->string;
+ }
+ return $text;
+ }
+
+}
diff --git a/tests/src/Unit/Plugin/widget/SelectWidgetTest.php b/tests/src/Unit/Plugin/widget/SelectWidgetTest.php
deleted file mode 100644
index 8f1bf73..0000000
--- a/tests/src/Unit/Plugin/widget/SelectWidgetTest.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-
-namespace Drupal\Tests\facets\Unit\Plugin\widget;
-
-use Drupal\Core\Url;
-use Drupal\facets\Entity\Facet;
-use Drupal\facets\Plugin\facets\widget\DropdownWidget;
-use Drupal\facets\Result\Result;
-use Drupal\Tests\UnitTestCase;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-
-/**
- * Unit test for widget.
- *
- * @group facets
- */
-class SelectWidgetTest extends UnitTestCase {
-
- /**
- * The processor to be tested.
- *
- * @var \Drupal\facets\Plugin\facets\widget\DropdownWidget
- */
- protected $widget;
-
- /**
- * An array containing the results before the processor has ran.
- *
- * @var \Drupal\facets\Result\Result[]
- */
- protected $originalResults;
-
- /**
- * Creates a new processor object for use in the tests.
- */
- protected function setUp() {
- parent::setUp();
-
- /** @var \Drupal\facets\Result\Result[] $original_results */
- $original_results = [
- new Result('llama', 'Llama', 10),
- new Result('badger', 'Badger', 20),
- new Result('duck', 'Duck', 15),
- new Result('alpaca', 'Alpaca', 9),
- ];
-
- foreach ($original_results as $original_result) {
- $original_result->setUrl(new Url('test'));
- }
- $this->originalResults = $original_results;
-
- $form_builder = $this->getMockBuilder('\Drupal\Core\Form\FormBuilder')
- ->disableOriginalConstructor()
- ->getMock();
- $form_builder->expects($this->once())
- ->method('getForm')
- ->willReturn('build');
-
- $string_translation = $this->getMockBuilder('\Drupal\Core\StringTranslation\TranslationManager')
- ->disableOriginalConstructor()
- ->getMock();
-
- $container_builder = new ContainerBuilder();
- $container_builder->set('form_builder', $form_builder);
- $container_builder->set('string_translation', $string_translation);
- \Drupal::setContainer($container_builder);
-
- $this->widget = new DropdownWidget();
- }
-
- /**
- * Tests widget with default settings.
- */
- public function testDefaultSettings() {
- $facet = new Facet([], 'facet');
- $facet->setResults($this->originalResults);
- $facet->setFieldIdentifier('test_field');
-
- $built_form = $this->widget->build($facet);
- $this->assertEquals('build', $built_form);
- }
-
-}