-
-
Save dstorozhuk/2136b7fae016944a1d1851a9db1b1940 to your computer and use it in GitHub Desktop.
Drupal 8.x Search API processor plugin for boosting search items by term reference field
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 | |
// This plugin allows the administrator to boost items in an index based on a taxonomy term. | |
// | |
// Drop into an existing plugin module or create a new one, ex. create an info.yml file as | |
// modules/custom/search_api_boost_term_reference/search_api_boost_term_reference.info.yml | |
// | |
// name: 'Search API Boost by Term Reference' | |
// description: 'Define custom boost priority in Search API index by term reference field' | |
// core: 8.x | |
// package: Search | |
// type: module | |
// dependencies: | |
// - search_api:search_api | |
// version: '8.x-1.0' | |
// core: '8.x' | |
// project: 'search_api_boost_term_reference' | |
// | |
// and then save in your module folder as: | |
// | |
// modules/custom/search_api_boost_term_reference/src/Plugin/search_api/processor/TermReferenceBoost.php | |
// | |
// Enable the module and configure | |
namespace Drupal\search_api_boost_term_reference\Plugin\search_api\processor; | |
use Drupal\comment\CommentInterface; | |
use Drupal\Component\Utility\Html; | |
use Drupal\Core\Form\FormStateInterface; | |
use Drupal\Core\Plugin\PluginFormInterface; | |
use Drupal\Core\TypedData\ComplexDataInterface; | |
use Drupal\node\NodeInterface; | |
use Drupal\search_api\Plugin\PluginFormTrait; | |
use Drupal\search_api\Processor\ProcessorPluginBase; | |
/** | |
* Adds a boost to indexed items based on a taxonomy term | |
* | |
* @SearchApiProcessor( | |
* id = "search_api_boost_term_reference", | |
* label = @Translation("Add boost processor based on term reference field"), | |
* description = @Translation("Adds search_api processor to allow weighted boosting for a term reference field."), | |
* stages = { | |
* "preprocess_index" = 0, | |
* } | |
* ) | |
*/ | |
class TermReferenceBoost extends ProcessorPluginBase implements PluginFormInterface { | |
use PluginFormTrait; | |
/** | |
* The available boost factors. | |
* | |
* @var string[] | |
*/ | |
protected static $boostFactors = [ | |
'0.0' => '0.0', | |
'0.1' => '0.1', | |
'0.2' => '0.2', | |
'0.3' => '0.3', | |
'0.5' => '0.5', | |
'0.8' => '0.8', | |
'1.0' => '1.0', | |
'2.0' => '2.0', | |
'3.0' => '3.0', | |
'5.0' => '5.0', | |
'8.0' => '8.0', | |
'13.0' => '13.0', | |
'21.0' => '21.0', | |
]; | |
/** | |
* {@inheritdoc} | |
*/ | |
public function defaultConfiguration() { | |
return [ | |
'boost_table' => [ | |
'weight' => '0.0', | |
], | |
]; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function buildConfigurationForm(array $form, FormStateInterface $formState) { | |
$form['boost_table'] = [ | |
'#type' => 'table', | |
'#header' => [ | |
$this->t('## FIELD LABEL ##'), | |
$this->t('Boost'), | |
], | |
]; | |
// add the name of the vocabulary I am trying to load | |
$vid = '## VOCABULARY MACHINE NAME ##'; | |
$terms =\Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($vid); | |
foreach ($terms as $term) { | |
// load values from existing configuration if they exist | |
if (isset($this->configuration['boost_table'][$term->tid]['weight'])) { | |
$weight = $this->configuration['boost_table'][$term->tid]['weight']; | |
} else { | |
$key =array_rand(static::$boostFactors); | |
//$weight = static::$boostFactors[$key]; | |
$weight = 0; | |
} | |
$term_data[] = array( | |
'tid' => $term->tid, | |
'name' => $term->name, | |
'weight' => $weight | |
); | |
} | |
// Sort weights, with heaviest items dropping down in the list. | |
uasort($term_data, ['Drupal\Component\Utility\SortArray', 'sortByWeightElement']); | |
// Create our configuration table | |
foreach ($term_data as $term) { | |
$form['boost_table'][$term["tid"]]['label']['#plain_text'] = $term["name"]; | |
// Weight column element. | |
$form['boost_table'][$term["tid"]]['weight'] = [ | |
'#type' => 'select', | |
'#title' => t('Weight for @title', ['@title' => $term["name"]]), | |
'#title_display' => 'invisible', | |
'#default_value' => $term["weight"], | |
'#options' => static::$boostFactors, | |
]; | |
} | |
return $form; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { | |
$values = $form_state->getValues(); | |
// add the name of the vocabulary I am trying to load | |
$vid = '## VOCABULARY MACHINE NAME ##'; | |
$terms =\Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($vid); | |
foreach ($terms as $term) { | |
if (!empty($values['boost_table'][$term->tid]['weight'])) { | |
$weight = $values['boost_table'][$term->tid]['weight']; | |
if ($weight === '') { | |
unset($values['boost_table'][$term->tid]); | |
} | |
} | |
} | |
$form_state->setValues($values); | |
$this->setConfiguration($values); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function preprocessIndexItems(array $items) { | |
foreach ($items as $item) { | |
$entityTypeId = $item->getDatasource()->getEntityTypeId(); | |
switch ($entityTypeId) { | |
case 'node': | |
// Get the node object. | |
$node = $this->getNode($item->getOriginalObject()); | |
$boost = $this->getBoostFromNode($node); | |
break; | |
// pass on all other entity types | |
default: | |
$boost = 0; | |
break; | |
} | |
$item->setBoost($boost); | |
} | |
} | |
/** | |
* Retrieves the node related to an indexed search object. | |
* | |
* Will be either the node itself, or the node the comment is attached to. | |
* | |
* @param \Drupal\Core\TypedData\ComplexDataInterface $item | |
* A search object that is being indexed. | |
* | |
* @return \Drupal\node\NodeInterface|null | |
* The node related to that search object. | |
*/ | |
protected function getNode(ComplexDataInterface $item) { | |
$item = $item->getValue(); | |
if ($item instanceof CommentInterface) { | |
$item = $item->getCommentedEntity(); | |
} | |
if ($item instanceof NodeInterface) { | |
return $item; | |
} | |
return NULL; | |
} | |
/** | |
* Retrieves the boost related to a node. | |
* | |
* @return float | |
* Boost Value. | |
*/ | |
protected function getBoostFromNode($node) { | |
$node_type = $node->getType(); | |
switch($node_type) { | |
case "professional": | |
$tid = $node->get('## NODE TERM REFERENCE FIELD')->target_id; | |
$boost = $this->configuration['boost_table'][$tid]['weight']; | |
break; | |
default: | |
$boost = 1.0; | |
} | |
return $boost; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment