public function DefaultFacetManager::build in Facets 8
Builds a facet and returns it as a renderable array.
This method delegates to the relevant plugins to render a facet, it calls out to a widget plugin to do the actual rendering when results are found. When no results are found it calls out to the correct empty result plugin to build a render array.
Before doing any rendering, the processors that implement the BuildProcessorInterface enabled on this facet will run.
Parameters
\Drupal\facets\FacetInterface $facet: The facet we should build.
Return value
array Facet render arrays.
Throws
\Drupal\facets\Exception\InvalidProcessorException Throws an exception when an invalid processor is linked to the facet.
File
- src/
FacetManager/ DefaultFacetManager.php, line 249
Class
- DefaultFacetManager
- The facet manager.
Namespace
Drupal\facets\FacetManagerCode
public function build(FacetInterface $facet) {
// Immediately initialize the facets if they are not initiated yet.
$this
->initFacets();
// It might be that the facet received here, is not the same as the already
// loaded facets in the FacetManager.
// For that reason, get the facet from the already loaded facets in the
// static cache.
$facet = $this->facets[$facet
->id()];
if ($facet
->getOnlyVisibleWhenFacetSourceIsVisible()) {
// Block rendering and processing should be stopped when the facet source
// is not available on the page. Returning an empty array here is enough
// to halt all further processing.
$facet_source = $facet
->getFacetSource();
if (is_null($facet_source) || !$facet_source
->isRenderedInCurrentRequest()) {
return [];
}
}
// For clarity, process facets is called each build.
// The first facet therefor will trigger the processing. Note that
// processing is done only once, so repeatedly calling this method will not
// trigger the processing more than once.
$this
->processFacets($facet
->getFacetSourceId());
// Get the current results from the facets and let all processors that
// trigger on the build step do their build processing.
// @see \Drupal\facets\Processor\BuildProcessorInterface.
// @see \Drupal\facets\Processor\SortProcessorInterface.
$results = $facet
->getResults();
foreach ($facet
->getProcessorsByStage(ProcessorInterface::STAGE_BUILD) as $processor) {
if (!$processor instanceof BuildProcessorInterface) {
throw new InvalidProcessorException("The processor {$processor->getPluginDefinition()['id']} has a build definition but doesn't implement the required BuildProcessorInterface interface");
}
$results = $processor
->build($facet, $results);
}
// Handle hierarchy.
if ($results && $facet
->getUseHierarchy()) {
$keyed_results = [];
foreach ($results as $result) {
$keyed_results[$result
->getRawValue()] = $result;
}
$parent_groups = $facet
->getHierarchyInstance()
->getChildIds(array_keys($keyed_results));
$keyed_results = $this
->buildHierarchicalTree($keyed_results, $parent_groups);
// Remove children from primary level.
foreach (array_unique($this->childIds) as $child_id) {
unset($keyed_results[$child_id]);
}
$results = array_values($keyed_results);
}
// Trigger sort stage.
$active_sort_processors = [];
foreach ($facet
->getProcessorsByStage(ProcessorInterface::STAGE_SORT) as $processor) {
$active_sort_processors[] = $processor;
}
// Sort the actual results if we have enabled sort processors.
if (!empty($active_sort_processors)) {
$results = $this
->sortFacetResults($active_sort_processors, $results);
}
$facet
->setResults($results);
// We include this build even if empty, it may contain attached libraries.
/** @var \Drupal\facets\Widget\WidgetPluginInterface $widget */
$widget = $facet
->getWidgetInstance();
$build = $widget
->build($facet);
// No results behavior handling. Return a custom text or false depending on
// settings.
if (empty($facet
->getResults())) {
$empty_behavior = $facet
->getEmptyBehavior();
if ($empty_behavior && $empty_behavior['behavior'] === 'text') {
return [
[
$build,
'#type' => 'container',
'#attributes' => [
'data-drupal-facet-id' => $facet
->id(),
'class' => [
'facet-empty',
],
],
'empty_text' => [
// @codingStandardsIgnoreStart
'#markup' => $this
->t($empty_behavior['text']),
],
],
];
}
else {
// If the facet has no results, but it is being rendered trough ajax we
// should render a container (that is empty). This is because the
// javascript needs to be able to find a div to replace with the new
// content.
return [
[
$build,
'#type' => 'container',
'#attributes' => [
'data-drupal-facet-id' => $facet
->id(),
'class' => [
'facet-empty',
'facet-hidden',
],
],
],
];
}
}
return [
$build,
];
}