Commit 75b7b3e1 authored by borisson_'s avatar borisson_ Committed by borisson_
Browse files

Issue #2665400 by borisson_, Evaldas Užkuras, michiellucas:...

Issue #2665400 by borisson_, Evaldas Užkuras, michiellucas: InvalidArgumentException: The URI 'datasets' is invalid.
parent 17f65dbd
<?php
/**
* @file
* Contains \Drupal\facets\Form\CheckboxWidgetForm.
*/
namespace Drupal\facets\Form;
use Drupal\Core\Form\BaseFormIdInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\facets\FacetInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* The checkbox / radios widget form.
*/
class CheckboxWidgetForm implements BaseFormIdInterface {
/**
* The facet to build the checkbox 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_checkbox_widget';
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return $this->getBaseFormId() . '__' . $this->facet->id();
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
// Get the facet form the build info, see the remark in
// \Drupal\facets\Plugin\facets\widget\CheckboxWidget::build.
$build_info = $form_state->getBuildInfo();
/** @var \Drupal\facets\FacetInterface $facet */
$facet = $build_info['args'][0];
/** @var \Drupal\facets\Result\Result[] $results */
$results = $facet->getResults();
$configuration = $facet->getWidgetConfigs();
$show_numbers = (bool) isset($configuration['show_numbers']) ? $configuration['show_numbers'] : FALSE;
$form[$facet->getFieldAlias()] = [
'#type' => 'checkboxes',
'#title' => $facet->getName(),
];
$options = [];
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();
}
}
$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 we redirect to the page that has that facet
// selected. This should be an absolute link because RedirectResponse is a
// symfony class that requires a full URL.
if ($result_link instanceof Url) {
$result_link->setAbsolute();
$form_state->setResponse(new RedirectResponse($result_link->toString()));
return;
}
// The form was submitted but nothing was active in the form, we should
// still redirect, but the url for the new page can't come from a result.
// So we're redirecting to the facet source's page.
$path = $facet->getFacetSource()->getPath();
if (substr($path, 0, 1) !== '/') {
$path = '/' . $path;
}
$link = Url::fromUserInput($path);
$link->setAbsolute();
$form_state->setResponse(new RedirectResponse($link->toString()));
}
}
......@@ -7,13 +7,11 @@
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\Form\CheckboxWidgetForm;
use Drupal\facets\Widget\WidgetInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* The checkbox / radios widget.
......@@ -24,7 +22,7 @@ use Symfony\Component\HttpFoundation\RedirectResponse;
* description = @Translation("A configurable widget that shows a list of checkboxes"),
* )
*/
class CheckboxWidget implements WidgetInterface, FormInterface {
class CheckboxWidget implements WidgetInterface {
use StringTranslationTrait;
......@@ -34,11 +32,14 @@ class CheckboxWidget implements WidgetInterface, FormInterface {
public function build(FacetInterface $facet) {
$form_builder = \Drupal::getContainer()->get('form_builder');
$form_object = new CheckboxWidgetForm($facet);
// 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
// method. This way we can pass the facet to the
// \Drupal\facets\Form\CheckboxWidgetForm::buildForm method, it uses
// FormState::getBuildInfo to get the facet out.
$build = $form_builder->getForm(static::class, $facet);
$build = $form_builder->getForm($form_object, $facet);
return $build;
}
......@@ -70,103 +71,4 @@ class CheckboxWidget implements WidgetInterface, FormInterface {
return $query_types['string'];
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'facets_checkbox_widget';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
/** @var \Drupal\facets\FacetInterface $facet */
// Get the facet form the build info, see the remark in ::build to know
// where this comes from.
$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) (isset($configuration['show_numbers']) ? $configuration['show_numbers'] : FALSE);
$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();
}
}
$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 we redirect to the page that has that facet
// selected. This should be an absolute link because RedirectResponse is a
// symfony class that requires a full URL.
if ($result_link instanceof Url) {
$result_link->setAbsolute();
$form_state->setResponse(new RedirectResponse($result_link->toString()));
return;
}
// The form was submitted but nothing was active in the form, we should
// still redirect, but the url for the new page can't come from a result.
// So we're redirecting to the facet source's page.
$link = Url::fromUri($facet->getFacetSource()->getPath());
$link->setAbsolute();
$form_state->setResponse(new RedirectResponse($link->toString()));
}
}
......@@ -79,6 +79,80 @@ class WidgetIntegrationTest extends FacetWebTestBase {
$this->assertFieldChecked('edit-type-item');
}
/**
* Tests multiple checkbox widgets.
*/
public function testMultipleCheckboxWidget() {
$facet_add_page = 'admin/config/search/facets/add-facet';
$id = 'type';
$name = 'Northern hawk-owl | type';
$id_2 = 'keywords';
$name_2 = 'Papuan hawk-owl | keywords';
// Add a new facet.
$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->drupalGet($facet_add_page);
$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'));
// Add a new facet.
$form_values = [
'id' => $id_2,
'status' => 1,
'url_alias' => $id_2,
'name' => $name_2,
'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]' => 'keywords',
];
$this->drupalGet($facet_add_page);
$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'));
// Place facets as blocks.
$block_values = ['region' => 'footer', 'id' => str_replace('_', '-', $id)];
$this->drupalPlaceBlock('facet_block:' . $id, $block_values);
$block_values = ['region' => 'footer', 'id' => str_replace('_', '-', $id_2)];
$this->drupalPlaceBlock('facet_block:' . $id_2, $block_values);
// Go to the test view and test that both facets are shown on the page.
$this->drupalGet('search-api-test-fulltext');
$this->assertText($name);
$this->assertText($name_2);
$this->assertText('item');
$this->assertText('apple');
// Submit the facet form and check that the form is submitted and the
// checkbox is now checked.
$edit = array('type[item]' => 'item');
$this->drupalPostForm(NULL, $edit, $this->t('submit'));
$this->assertText($name);
$this->assertText($name_2);
$this->assertText('item');
$this->assertText('apple');
$this->assertFieldChecked('edit-type-item');
// Submit the second facet form and check that the form is submitted and the
// checkbox is now checked.
$edit = array('keywords[apple]' => 'apple');
$this->drupalPostForm(NULL, $edit, $this->t('submit'));
$this->assertText($name);
$this->assertText($name_2);
$this->assertText('item');
$this->assertText('apple');
$this->assertFieldChecked('edit-type-item');
$this->assertFieldChecked('edit-keywords-apple');
}
/**
* Tests links widget's basic functionality.
*/
......
<?php
/**
* @file
* Contains \Drupal\Tests\facets\Unit\Form\CheckboxWidgetFormTest.
*/
namespace Drupal\Tests\facets\Unit\Form;
use Drupal\Core\Form\FormState;
use Drupal\facets\Entity\Facet;
use Drupal\facets\Form\CheckboxWidgetForm;
use Drupal\facets\Result\Result;
use Drupal\Tests\UnitTestCase;
/**
* Unit test for the checkbox widget form.
*
* @group facets
*/
class CheckboxWidgetTest 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();
/** @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 \Drupal\Core\Url('test'));
}
$original_results[1]->setActiveState(TRUE);
$this->originalResults = $original_results;
}
/**
* 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 CheckboxWidgetForm($facet);
$built_form = $widget_form->buildForm($form, $form_state);
$this->assertInternalType('array', $built_form);
$this->assertCount(4, $built_form['zoo_animal']['#options']);
$this->assertEquals('checkboxes', $built_form['zoo_animal']['#type']);
$expected_links = [
'llama' => 'Llama',
'badger' => 'Badger',
'duck' => 'Duck',
'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 CheckboxWidgetForm($facet);
$built_form = $widget_form->buildForm($form, $form_state);
$this->assertInternalType('array', $built_form);
$this->assertCount(4, $built_form['zoo__animal']['#options']);
$expected_links = [
'llama' => 'Llama',
'badger' => 'Badger',
'duck' => 'Duck',
'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(4, $built_form['zoo__animal']['#options']);
$expected_links = [
'llama' => 'Llama (10)',
'badger' => 'Badger (20)',
'duck' => 'Duck (15)',
'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 CheckboxWidgetForm($facet);
$this->assertEquals('facets_checkbox_widget', $form->getBaseFormId());
$this->assertEquals('facets_checkbox_widget__donkey', $form->getFormId());
}
}
......@@ -7,7 +7,6 @@
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;
......@@ -57,6 +56,9 @@ class CheckboxWidgetTest extends UnitTestCase {
$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()
......@@ -78,73 +80,8 @@ class CheckboxWidgetTest extends UnitTestCase {
$facet->setResults($this->originalResults);
$facet->setFieldIdentifier('test_field');
$form_state = new FormState();
$form_state->addBuildInfo('args', [$facet]);
$form = [];
$built_form = $this->widget->buildForm($form, $form_state);
$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, $built_form['test_field']['#options'][$index]);
}
}
/**
* Tests widget, make sure hiding and showing numbers works.
*/
public function testHideNumbers() {
$original_results = $this->originalResults;
$original_results[1]->setActiveState(TRUE);
$facet = new Facet([], 'facet');
$facet->setResults($original_results);
$facet->setFieldIdentifier('test__field');
$facet->setWidgetConfigs(['show_numbers' => 0]);
$form_state = new FormState();
$form_state->addBuildInfo('args', [$facet]);
$form = [];
$built_form = $this->widget->buildForm($form, $form_state);
$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]);
$built_form = $this->widget->buildForm($form, $form_state);
$this->assertInternalType('array', $built_form);
$this->assertCount(4, $built_form['test__field']['#options']);
$expected_links = [
'llama' => 'Llama (10)',
'badger' => 'Badger (20)',
'duck' => 'Duck (15)',
'alpaca' => 'Alpaca (9)',
];
foreach ($expected_links as $index => $value) {
$this->assertEquals($value, $built_form['test__field']['#options'][$index]);
}
$built_form = $this->widget->build($facet);