Commit 746eb828 authored by borisson_'s avatar borisson_
Browse files

Start with implementing widgets.

parent 1da94407
......@@ -20,3 +20,6 @@ facetapi.facet.*:
field_identifier:
type: string
label: 'Field identifier'
widget:
type: string
label: 'Field identifier'
......@@ -8,6 +8,9 @@ services:
plugin.manager.facetapi.url_processor:
class: Drupal\facetapi\UrlProcessor\UrlProcessorPluginManager
parent: default_plugin_manager
plugin.manager.facetapi.widget:
class: Drupal\facetapi\Widget\WidgetPluginManager
parent: default_plugin_manager
search_api_facets.get_facets:
class: \Drupal\facetapi\GetFacets
arguments:
......
<?php
/**
* @file
* Contains \Drupal\facetapi\Annotation\FacetApiWidget.
*/
namespace Drupal\facetapi\Annotation;
use Drupal\Component\Annotation\Plugin;
/**
* Defines a Facet API Widget annotation object.
*
* @see \Drupal\facetapi\Widget\WidgetPluginManager
* @see plugin_api
*
* @ingroup plugin_api
*
* @Annotation
*/
class FacetApiWidget extends Plugin {
/**
* The widget plugin id
*
* @var string
*/
public $id;
/**
* The human-readable name of the widget plugin
*
* @ingroup plugin_translatable
*
* @var \Drupal\Core\Annotation\Translation
*/
public $label;
/**
* The widget description.
*
* @ingroup plugin_translatable
*
* @var \Drupal\Core\Annotation\Translation
*/
public $description;
/**
* The possible query types used by this widget.
*
* @var array
*/
public $queryType = [];
/**
* Class used to retrieve derivative definitions of the adapter.
*
* @var string
*/
public $derivative = '';
}
......@@ -40,6 +40,7 @@ use Drupal\facetapi\Result\ResultInterface;
* "name",
* "search_api_index",
* "field_identifier",
* "widget",
* },
* links = {
* "canonical" = "/admin/config/search/search-api/index/{search_api_index}/facets",
......@@ -72,6 +73,13 @@ class Facet extends ConfigEntityBase implements FacetInterface {
*/
protected $description;
/**
* A string describing the widget.
*
* @var string
*/
protected $widget;
/**
* An array of options configuring this index.
*
......@@ -146,6 +154,22 @@ class Facet extends ConfigEntityBase implements FacetInterface {
return $this->description;
}
/**
* @param string $widget
* @return $this
*/
public function setWidget($widget) {
$this->widget = $widget;
return $this;
}
/**
* @return string
*/
public function getWidget() {
return $this->widget;
}
/**
* Get the field alias used to identify the facet in the url.
*
......
......@@ -12,6 +12,8 @@ use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\facetapi\FacetInterface;
use Drupal\facetapi\FacetApiException;
use Drupal\facetapi\Widget\WidgetPluginManager;
use Drupal\search_api\Form\SubFormState;
use Drupal\search_api\IndexInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -27,14 +29,23 @@ class FacetForm extends EntityForm {
*/
protected $facetStorage;
/**
* The plugin manager for widgets.
* @var \Drupal\facetapi\Widget\WidgetPluginManager
*/
protected $widgetPluginManager;
/**
* Constructs a FacetForm object.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
* @param \Drupal\facetapi\Widget\WidgetPluginManager $widget_plugin_manager
* Plugin manager for widgets.
*/
public function __construct(EntityManagerInterface $entity_manager) {
public function __construct(EntityManagerInterface $entity_manager, WidgetPluginManager $widgetPluginManager) {
$this->facetStorage = $entity_manager->getStorage('facetapi_facet');
$this->widgetPluginManager = $widgetPluginManager;
}
/**
......@@ -43,7 +54,10 @@ class FacetForm extends EntityForm {
public static function create(ContainerInterface $container) {
/** @var \Drupal\Core\Entity\EntityManagerInterface $entity_manager */
$entity_manager = $container->get('entity.manager');
return new static($entity_manager);
/** @var \Drupal\facetapi\Widget\WidgetPluginManager $widget_plugin_manager */
$widget_plugin_manager = $container->get('plugin.manager.facetapi.widget');
return new static($entity_manager, $widget_plugin_manager);
}
/**
......@@ -56,6 +70,16 @@ class FacetForm extends EntityForm {
return $this->facetStorage ?: \Drupal::service('entity.manager')->getStorage('facetapi_facet');
}
/**
* Returns the widget plugin manager.
*
* @return \Drupal\facetapi\Widget\WidgetPluginManager
* The widget plugin manager.
*/
protected function getWidgetPluginManager() {
return $this->widgetPluginManager?: \Drupal::service('plugin.manager.facetapi.widget');
}
/**
* {@inheritdoc}
*/
......@@ -124,6 +148,46 @@ class FacetForm extends EntityForm {
'#default_value' => $facet->getFieldIdentifier()
];
$widget_options = [];
foreach ($this->getWidgetPluginManager()->getDefinitions() as $widget_id => $definition) {
$widget_options[$widget_id] = !empty($definition['label']) ? $definition['label'] : $widget_id;
}
$form['widget'] = [
'#type' => 'select',
'#title' => $this->t('Widget'),
'#description' => $this->t('Select the widget used for displaying this facet.'),
'#options' => $widget_options,
'#default_value' => $facet->getWidget(),
'#required' => TRUE,
'#ajax' => [
'trigger_as' => ['name' => 'widgets_configure'],
'callback' => '::buildAjaxWidgetConfigForm',
'wrapper' => 'facet-api-widget-config-form',
'method' => 'replace',
'effect' => 'fade',
],
];
$form['widget_configs'] = array(
'#type' => 'container',
'#attributes' => array(
'id' => 'facet-api-widget-config-form',
),
'#tree' => TRUE,
);
$form['widget_configure_button'] = [
'#type' => 'submit',
'#name' => 'widget_configure',
'#value' => $this->t('Configure'),
'#limit_validation_errors' => [['widget']],
'#submit' => ['::submitAjaxWidgetConfigForm'],
'#ajax' => [
'callback' => '::buildAjaxWidgetConfigForm',
'wrapper' => 'facet-api-widget-config-form',
],
'#attributes' => ['class' => ['js-hide']],
];
$this->buildWidgetConfigForm($form, $form_state, $facet);
$form['status'] = array(
'#type' => 'checkbox',
'#title' => $this->t('Enabled'),
......@@ -152,6 +216,45 @@ class FacetForm extends EntityForm {
return $indexed_fields;
}
/**
* Handles changes to the selected widgets.
*/
public function buildAjaxWidgetConfigForm(array $form, FormStateInterface $form_state) {
return $form['widget_configs'];
}
/**
* Builds the configuration forms for all selected widgets.
*
* @param \Drupal\search_api\IndexInterface $index
* The index begin created or edited.
*/
public function buildWidgetConfigForm(array &$form, FormStateInterface $form_state, FacetInterface $facet) {
$widget = $facet->getWidget();
if (!is_null($widget)) {
$widget_instance = $this->getWidgetPluginManager()->createInstance($widget);
// @todo Create, use and save SubFormState already here, not only in
// validate(). Also, use proper subset of $form for first parameter?
if ($config_form = $widget_instance->buildConfigurationForm([], $form_state)) {
$form['widget_config']['#type'] = 'details';
$form['widget_config']['#title'] = $this->t('Configure the %widget widget', ['%widget' => $this->getWidgetPluginManager()->getDefinition($widget)['label']]);
$form['widget_config']['#open'] = $facet->isNew();
$form['widget_config'] += $config_form;
}
}
}
/**
* Form submission handler for buildEntityForm().
*
* Takes care of changes in the selected datasources.
*/
public function submitAjaxWidgetConfigForm($form, FormStateInterface $form_state) {
$form_state->setRebuild();
}
/**
* {@inheritdoc}
*/
......
<?php
namespace Drupal\facetapi\Plugin\facetapi\Widget;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\facetapi\Widget\WidgetInterface;
/**
* @FacetApiWidget(
* id = "checkbox",
* label = @Translation("Checkbox widget"),
* description = @Translation("A widget that shows checkboxes"),
* )
*
* Class CheckboxWidget
*/
class CheckboxWidget implements WidgetInterface {
use StringTranslationTrait;
/**
* {@inheritdoc}
*/
public function execute() {
// Execute all the things.
}
/**
* {@inheritdoc}
*/
public function build() {
return ['#markup' => 'checkbox widget'];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
return $form;
}
}
<?php
namespace Drupal\facetapi\Plugin\facetapi\Widget;
use Drupal\Core\Form\FormStateInterface;
use Drupal\facetapi\Widget\WidgetInterface;
/**
* @FacetApiWidget(
* id = "links",
* label = @Translation("Links widget"),
* description = @Translation("A widget that shows links"),
* )
*
* Class LinksWidget
*/
class LinksWidget implements WidgetInterface {
/**
* {@inheritdoc}
*/
public function execute() {
// Execute all the things.
}
/**
* {@inheritdoc}
*/
public function build() {
return ['#markup' => 'links widget'];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
return $form;
}
}
<?php
/**
* @file
* Contains Drupal\facetapi\Widget\WidgetInterface
*/
namespace Drupal\facetapi\Widget;
interface WidgetInterface {
/**
* Add facet info to the query using the selected query type.
*
* @return mixed
*/
public function execute();
/**
* Builds the widget for rendering
*/
public function build();
}
<?php
/**
* Contains Drupal\facetapi\Widget\WidgetPluginManager
*/
namespace Drupal\facetapi\Widget;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
class WidgetPluginManager extends DefaultPluginManager {
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
parent::__construct('Plugin/facetapi/widget', $namespaces, $module_handler, 'Drupal\facetapi\Widget\WidgetInterface', 'Drupal\facetapi\Annotation\FacetApiWidget');
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment