Last active
January 27, 2021 20:58
-
-
Save daggerhart/63333cb47d9c8be7caf639b6dcb35bdb to your computer and use it in GitHub Desktop.
Drupal 8 views style plugin for a better rest serializer that leverages the Facets module.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Drupal\my_module\Plugin\views\style; | |
use Drupal\facets_rest\Plugin\views\style\FacetsSerializer; | |
/** | |
* The style plugin for serialized output formats. | |
* | |
* @ingroup views_style_plugins | |
* | |
* @ViewsStyle( | |
* id = "my_module_facets_serializer", | |
* title = @Translation("Better Facets Serializer"), | |
* help = @Translation("Extends existing serializer styles to provide additional view data."), | |
* display_types = {"data"} | |
* ) | |
*/ | |
class BetterRestFacetsSerializer extends FacetsSerializer { | |
/** | |
* {@inheritdoc} | |
*/ | |
public function render() { | |
$rows['search_results'] = $this->getSearchResults(); | |
$rows['facets'] = $this->options['show_facets'] ? $this->getFacets() : []; | |
$rows['active_facet_items'] = $this->getActiveFacetItems($rows['facets']); | |
$rows['pager'] = $this->getPagerDetails(); | |
$rows['exposed_filters'] = $this->getExposedHandlers('filter'); | |
$rows['exposed_sorts'] = $this->getExposedHandlers('sort'); | |
// Get the content type configured in the display or fallback to the | |
// default. | |
if ((empty($this->view->live_preview))) { | |
$content_type = $this->displayHandler->getContentType(); | |
} | |
else { | |
$content_type = !empty($this->options['formats']) ? \reset($this->options['formats']) : 'json'; | |
} | |
return $this->serializer->serialize($rows, $content_type, ['views_style_plugin' => $this]); | |
} | |
/** | |
* Get an array of active facet items. | |
* | |
* @param array $facets | |
* | |
* @return array | |
*/ | |
protected function getActiveFacetItems(array $facets): array { | |
$active_items = []; | |
foreach ($facets as $facet) { | |
if (!empty($facet['items'])) { | |
foreach ($facet['items'] as $item) { | |
if (!empty($item['values']['active'])) { | |
$item['facet_config'] = $facet['config']; | |
// We need to do some trickier to correctly set static values | |
// display item values. | |
if (!empty($item['facet_config']['static_values'])) { | |
// Break apart the config string in value pairs. | |
$static_values = \preg_split('/\R+/', $item['facet_config']['static_values']); | |
foreach ($static_values as $value) { | |
// Break apart key value pairs. | |
$key_values = \explode('|', $value); | |
// If value equates to the active item value, set display. | |
if ($key_values[0] === $item['values']['value']) { | |
$item['values']['display_value'] = $key_values[1]; | |
} | |
} | |
} | |
$active_items[] = $item; | |
} | |
} | |
} | |
} | |
return $active_items; | |
} | |
/** | |
* Get the search results and process facets. | |
* | |
* @see FacetsSerializer::render(); | |
* | |
* @return array | |
*/ | |
protected function getSearchResults() { | |
$rows = []; | |
// If the Data Entity row plugin is used, this will be an array of entities | |
// which will pass through Serializer to one of the registered Normalizers, | |
// which will transform it to arrays/scalars. If the Data field row plugin | |
// is used, $rows will not contain objects and will pass directly to the | |
// Encoder. | |
foreach ($this->view->result as $row_index => $row) { | |
// Keep track of the current rendered row, like every style plugin has to | |
// do. | |
// @see \Drupal\views\Plugin\views\style\StylePluginBase::renderFields | |
$this->view->row_index = $row_index; | |
$rows[] = $this->view->rowPlugin->render($row); | |
} | |
// Remove native row index which was throwing off something in the rendering | |
// and avoid confusion. This is not relevant as the actually rows are being | |
// stored and rendered elsewhere. Can ask Jonathan to help clarify if need | |
// be. | |
unset($this->view->row_index); | |
return $rows; | |
} | |
/** | |
* Process and return. | |
* | |
* @see FacetsSerializer::render(); | |
* | |
* @return array | |
* | |
* @throws \Drupal\facets\Exception\InvalidProcessorException | |
*/ | |
protected function getFacets() { | |
// Processing facets. | |
$facetsource_id = "search_api:views_rest__{$this->view->id()}__{$this->view->getDisplay()->display['id']}"; | |
$facets = $this->facetsManager->getFacetsByFacetSourceId($facetsource_id); | |
$this->facetsManager->updateResults($facetsource_id); | |
// Sort facets by weight. | |
\usort($facets, function ($a, $b) { | |
return $a->getWeight() > $b->getWeight(); | |
}); | |
$processed_facets = []; | |
foreach ($facets as $facet) { | |
$processed = $this->facetsManager->build($facet); | |
// Ensure facet is prepared and flatten it. | |
if (isset($processed[0], $processed[0]['config'])) { | |
$processed_facets[] = $processed[0]; | |
} | |
} | |
return $processed_facets; | |
} | |
/** | |
* Get pager and page details. | |
* | |
* @link https://www.drupal.org/project/drupal/issues/2982729 | |
* | |
* @return array | |
*/ | |
protected function getPagerDetails() { | |
$details = ['active' => FALSE]; | |
$pager = $this->view->pager; | |
if ($pager) { | |
$class = \get_class($pager); | |
$total_items = $pager->getTotalItems(); | |
$items_per_page = $pager->getItemsPerPage(); | |
$current_page = $pager->getCurrentPage(); | |
$total_pages = 0; | |
if (!in_array($class, ['Drupal\views\Plugin\views\pager\None', 'Drupal\views\Plugin\views\pager\Some'])) { | |
$total_pages = $pager->getPagerTotal(); | |
} | |
$details = [ | |
'active' => TRUE, | |
'current_page' => $current_page, | |
'total_items' => $total_items, | |
'total_pages' => $total_pages, | |
'items_per_page' => $items_per_page, | |
'options' => $pager->usesOptions() ? $pager->options : FALSE, | |
]; | |
} | |
return $details; | |
} | |
/** | |
* Get exposed handler information and option values. | |
* | |
* @param string $type | |
* ID for a handler type. | |
* | |
* @return array | |
*/ | |
protected function getExposedHandlers(string $type) { | |
$exposed = []; | |
$handlers = $this->view->getHandlers($type); | |
$exposed_input = $this->view->getExposedInput(); | |
foreach ($handlers as $id => $item) { | |
if ($item['exposed']) { | |
$info = ['id' => $id]; | |
if (isset($item['expose']['identifier'])) { | |
$info['submitted_values'] = $exposed_input[$item['expose']['identifier']] ?? []; | |
} | |
$info += $item['expose']; | |
$exposed[] = $info; | |
} | |
} | |
return $exposed; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment