Skip to content

Instantly share code, notes, and snippets.

@schnippy
Created August 10, 2018 22:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save schnippy/11b996bd11c751913e9f04278c7be544 to your computer and use it in GitHub Desktop.
Save schnippy/11b996bd11c751913e9f04278c7be544 to your computer and use it in GitHub Desktop.
Drupal 8.x Search API processor plugin for boosting search items by term reference field
<?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