Newer
Older
Joris Vercammen
committed
* Contains facets.module.
Joris Vercammen
committed
use Drupal\Component\Utility\Html;
use Drupal\Core\Routing\RouteMatchInterface;
Joris Vercammen
committed
use Drupal\facets\Entity\Facet;
use Drupal\facets\Entity\FacetSource;
use Drupal\views\Entity\View;
use Drupal\Core\Entity\EntityInterface;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
Joris Vercammen
committed
use Drupal\Core\Logger\RfcLogLevel;
/**
* Implements hook_help().
*/
function facets_help($route_name, RouteMatchInterface $route_match) {
// Main module help for the facets module.
case 'help.page.facets':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Facets test') . '</p>';
Joris Vercammen
committed
case 'facets.overview':
Girish G
committed
return t('Below is a list of facets grouped by facetsources they are associated with. A facetsource is the instance where the facet does the actual filtering, for example a View on a Search API index.');
Joris Vercammen
committed
/**
* Implements hook_theme().
*/
function facets_theme($existing, $type, $theme, $path) {
return [
Andrew Zahura
committed
'facets_result_item' => [
'variables' => [
'value' => '',
'show_count' => FALSE,
'count' => NULL,
'is_active' => FALSE,
],
],
'facets_item_list' => [
'variables' => [
'items' => [],
'title' => '',
'list_type' => 'ul',
'wrapper_attributes' => [],
'attributes' => [],
'empty' => NULL,
'context' => [],
],
],
];
}
Joris Vercammen
committed
* Implements hook_search_api_query_alter().
*
* @param \Drupal\search_api\Query\QueryInterface $query
Joris Vercammen
committed
* Generates query for facet search.
function facets_search_api_query_alter(QueryInterface &$query) {
Joris Vercammen
committed
if ($query->getIndex()->getServerInstance()->supportsFeature('search_api_facets')) {
/** @var \Drupal\facets\FacetManager\DefaultFacetManager $facet_manager */
$facet_manager = \Drupal::service('facets.manager');
Joris Vercammen
committed
// It's safe to hardcode this to the search api scheme because this is in a
// search_api_query_alter method. If this generated source is not correct,
// implementing the same alter and directly calling
// $manager->alterQuery($query, $your_facetsource_id); will fix that.
$facet_source = 'search_api:' . str_replace(':', '__', $query->getSearchId());
Joris Vercammen
committed
// Add the active filters.
Joris Vercammen
committed
$facet_manager->alterQuery($query, $facet_source);
Joris Vercammen
committed
}
/**
* Implements hook_entity_presave().
*
* We implement this to make sure that a facet gets removed on view updates, so
* we don't get broken facet blocks.
*/
function facets_entity_presave(EntityInterface $entity) {
// Make sure that we only react on view entities with changed displays.
if ($entity instanceof View && !empty($entity->original)) {
if ($entity->original->get('display') != $entity->get('display')) {
/** @var \Drupal\facets\FacetSource\FacetSourcePluginManager $facet_source_plugin_manager */
$facet_source_plugin_manager = \Drupal::getContainer()
->get('plugin.manager.facets.facet_source');
$definitions = $facet_source_plugin_manager->getDefinitions();
// Setup an array of sources that are deleted.
$sources = [];
foreach ($entity->original->get('display') as $k => $display) {
// Check if the current display is also a facet source plugin and that
// is removed from the view. We use the double underscore here to make
// sure that we use core convention of "plugin:derived_plugin".
Joris Vercammen
committed
$facets_source_plugin_id = 'search_api:views_' . $display['display_plugin'] . '__' . $entity->id() . '__' . $display['id'];
Joris Vercammen
committed
if (array_key_exists($facets_source_plugin_id, $definitions) && !array_key_exists($k, $entity->get('display'))) {
$entity_id = str_replace(':', '__', $facets_source_plugin_id);
$source_entity = FacetSource::load($entity_id);
Joris Vercammen
committed
$sources[] = $facets_source_plugin_id;
if (!is_null($source_entity)) {
$source_entity->delete();
}
}
}
// Loop over all deleted sources and delete the facets that were linked to
// that source.
if (count($sources) > 0) {
/** @var \Drupal\facets\FacetManager\DefaultFacetManager $fm */
$fm = \Drupal::getContainer()->get('facets.manager');
foreach ($sources as $source) {
$facets = $fm->getFacetsByFacetSourceId($source);
foreach ($facets as $facet) {
$facet->delete();
}
}
}
$facet_source_plugin_manager->clearCachedDefinitions();
}
}
}
Joris Vercammen
committed
/**
* Implements hook_preprocess_block().
*
* Adds a class for the widget to the facet block to allow for more specific
* styling.
*/
function facets_preprocess_block(&$variables) {
if ($variables['configuration']['provider'] == 'facets') {
Jeff Geerling
committed
if (!empty($variables['derivative_plugin_id'])) {
$facet = Facet::load($variables['derivative_plugin_id']);
$variables['attributes']['class'][] = 'block-facet--' . Html::cleanCssIdentifier($facet->getWidget()['type']);
}
Joris Vercammen
committed
}
}
/**
* Implements hook_entity_predelete().
*
* We implement this hook to make sure that facet source plugins are cleared
* when a view is deleted. It also deletes facets that are created on those
* plugins.
*/
Joris Vercammen
committed
function facets_entity_predelete(EntityInterface $entity) {
if ($entity instanceof View) {
$facet_source_plugin_manager = \Drupal::getContainer()
->get('plugin.manager.facets.facet_source');
$definitions = $facet_source_plugin_manager->getDefinitions();
Joris Vercammen
committed
if (!is_array($definitions)) {
return;
}
Joris Vercammen
committed
foreach ($definitions as $plugin_id => $definition) {
Joris Vercammen
committed
if (strpos($plugin_id, 'search_api:' . $entity->id() . '__') !== FALSE) {
try {
$facetManager = \Drupal::getContainer()->get('facets.manager');
}
catch (ServiceNotFoundException $e) {
Joris Vercammen
committed
\Drupal::logger('facets')->log(RfcLogLevel::DEBUG, 'Facet manager not found on trying to delete a view.');
return;
}
Joris Vercammen
committed
$facets = $facetManager->getFacetsByFacetSourceId($plugin_id);
foreach ($facets as $facet) {
$facet->delete();
}
}
}
// Clear cached plugin definitions for facet source to make sure we don't
// show stale data.
$facet_source_plugin_manager->clearCachedDefinitions();
}
}
Andrew Zahura
committed
/**
* Prepares variables for facets item list templates.
*
* Default template: facets-item-list.html.twig.
*
* @param array $variables
* An associative array containing:
* - items: An array of items to be displayed in the list. Each item can be
* either a string or a render array. If #type, #theme, or #markup
* properties are not specified for child render arrays, they will be
* inherited from the parent list, allowing callers to specify larger
* nested lists without having to explicitly specify and repeat the
* render properties for all nested child lists.
* - title: A title to be prepended to the list.
* - list_type: The type of list to return (e.g. "ul", "ol").
* - wrapper_attributes: HTML attributes to be applied to the list wrapper.
*
* @see https://www.drupal.org/node/1842756
*/
function facets_preprocess_facets_item_list(&$variables) {
template_preprocess_item_list($variables);
}