Skip to content

Commit d2e7dcd

Browse files
authored
Merge pull request #89 from rosiel/search-plugin
Replace "Linked Agent By Role" - new Plugin for filtering Typed Relations in search API
2 parents 50bba0d + 2a8b7e8 commit d2e7dcd

File tree

2 files changed

+224
-0
lines changed

2 files changed

+224
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
namespace Drupal\controlled_access_terms\Plugin\search_api\processor\Property;
4+
5+
use Drupal\Core\Form\FormStateInterface;
6+
use Drupal\Core\StringTranslation\StringTranslationTrait;
7+
use Drupal\search_api\Item\FieldInterface;
8+
use Drupal\search_api\Processor\ConfigurablePropertyBase;
9+
10+
/**
11+
* Defines a "Typed relation by type" property.
12+
*
13+
* @see \Drupal\controlled_access_terms\Plugin\search_api\processor\TypedRelationFiltered
14+
*/
15+
class TypedRelationFilteredProperty extends ConfigurablePropertyBase {
16+
17+
use StringTranslationTrait;
18+
19+
/**
20+
* {@inheritdoc}
21+
*/
22+
public function defaultConfiguration() {
23+
return [
24+
'rel_types' => [],
25+
'bundle' => '',
26+
'base_field' => '',
27+
];
28+
}
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
public function buildConfigurationForm(FieldInterface $field, array $form, FormStateInterface $form_state) {
34+
$configuration = $field->getConfiguration();
35+
$form['rel_types'] = [
36+
'#type' => 'select',
37+
'#title' => $this->t('Relations to include'),
38+
'#options' => $field->getDataDefinition()->getSetting('options'),
39+
'#multiple' => TRUE,
40+
'#default_value' => $configuration['rel_types'],
41+
'#required' => TRUE,
42+
'#size' => 16,
43+
];
44+
$form['bundle'] = [
45+
'#type' => 'hidden',
46+
'#value' => $field->getDataDefinition()->getSetting('bundle'),
47+
];
48+
$form['base_field'] = [
49+
'#type' => 'hidden',
50+
'#value' => $field->getDataDefinition()->getSetting('base_field'),
51+
];
52+
return $form;
53+
}
54+
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
<?php
2+
3+
namespace Drupal\controlled_access_terms\Plugin\search_api\processor;
4+
5+
use Drupal\controlled_access_terms\Plugin\search_api\processor\Property\TypedRelationFilteredProperty;
6+
use Drupal\Core\Entity\EntityTypeManager;
7+
use Drupal\search_api\Datasource\DatasourceInterface;
8+
use Drupal\search_api\Item\ItemInterface;
9+
use Drupal\search_api\Processor\ProcessorPluginBase;
10+
use Symfony\Component\DependencyInjection\ContainerInterface;
11+
12+
/**
13+
* Adds filterable fields for each Typed Relation field.
14+
*
15+
* @SearchApiProcessor(
16+
* id = "typed_relation_filtered",
17+
* label = @Translation("Typed Relation, filtered by type"),
18+
* description = @Translation("Filter Typed Relation fields by type"),
19+
* stages = {
20+
* "add_properties" = 0,
21+
* },
22+
* locked = false,
23+
* hidden = false,
24+
* )
25+
*/
26+
class TypedRelationFiltered extends ProcessorPluginBase {
27+
28+
/**
29+
* Entity Type Manager.
30+
*
31+
* @var \Drupal\Core\Entity\EntityTypeManager
32+
*/
33+
protected EntityTypeManager $entityTypeManager;
34+
35+
/**
36+
* Constructor.
37+
*
38+
* @param array $configuration
39+
* The plugin configuration, i.e. an array with configuration values keyed
40+
* by configuration option name. The special key 'context' may be used to
41+
* initialize the defined contexts by setting it to an array of context
42+
* values keyed by context names.
43+
* @param string $plugin_id
44+
* The plugin_id for the plugin instance.
45+
* @param mixed $plugin_definition
46+
* The plugin implementation definition.
47+
* @param \Drupal\Core\Entity\EntityTypeManager $entityTypeManager
48+
* The Entity Type Manager.
49+
*/
50+
public function __construct(
51+
array $configuration,
52+
$plugin_id,
53+
$plugin_definition,
54+
EntityTypeManager $entityTypeManager
55+
) {
56+
parent::__construct($configuration, $plugin_id, $plugin_definition);
57+
$this->entityTypeManager = $entityTypeManager;
58+
}
59+
60+
/**
61+
* {@inheritdoc}
62+
*/
63+
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
64+
return new static(
65+
$configuration,
66+
$plugin_id,
67+
$plugin_definition,
68+
$container->get('entity_type.manager'),
69+
);
70+
}
71+
72+
/**
73+
* {@inheritdoc}
74+
*/
75+
public function getPropertyDefinitions(DatasourceInterface $datasource = NULL): array {
76+
$properties = [];
77+
78+
if (!$datasource || !$datasource->getEntityTypeId()) {
79+
return $properties;
80+
}
81+
82+
$entity_type = $datasource->getEntityTypeId();
83+
84+
// Get all configured typed relation fields.
85+
$fields = $this->entityTypeManager->getStorage('field_config')->loadByProperties([
86+
'entity_type' => $entity_type,
87+
'field_type' => 'typed_relation',
88+
]);
89+
90+
foreach ($fields as $field) {
91+
// Create a "filtered" option.
92+
$definition = [
93+
'label' => $this->t('@label (filtered by type) [@bundle]', [
94+
'@label' => $field->label(),
95+
'@bundle' => $field->getTargetBundle(),
96+
]),
97+
'description' => $this->t('Typed relation field, filtered by type'),
98+
'type' => 'string',
99+
'processor_id' => $this->getPluginId(),
100+
'is_list' => TRUE,
101+
'settings' => [
102+
'options' => $field->getSetting('rel_types'),
103+
'bundle' => $field->getTargetBundle(),
104+
'base_field' => $field->getName(),
105+
],
106+
];
107+
$fieldname = 'typed_relation_filter__' . str_replace('.', '__', $field->id());
108+
$property = new TypedRelationFilteredProperty($definition);
109+
$property->setSetting('options', $field->getSetting('rel_types'));
110+
$properties[$fieldname] = $property;
111+
}
112+
return $properties;
113+
}
114+
115+
/**
116+
* {@inheritdoc}
117+
*/
118+
public function addFieldValues(ItemInterface $item) {
119+
// Skip if no Typed Relation Filtered search_api_fields are configured.
120+
$relevant_search_api_fields = [];
121+
$search_api_fields = $item->getFields(FALSE);
122+
foreach ($search_api_fields as $search_api_field) {
123+
if (substr($search_api_field->getPropertyPath(), 0, 23) == 'typed_relation_filter__') {
124+
$relevant_search_api_fields[] = $search_api_field;
125+
}
126+
}
127+
if (empty($search_api_fields)) {
128+
return;
129+
}
130+
// Cycle over any typed relation fields on the original item.
131+
$content_entity = $item->getOriginalObject()->getValue();
132+
133+
foreach ($relevant_search_api_fields as $search_api_field) {
134+
$field_config = $search_api_field->getConfiguration();
135+
136+
// Exit if we're on the wrong bundle or the field isn't set.
137+
if (($content_entity->bundle() != $field_config['bundle'])
138+
|| !$content_entity->hasField($field_config['base_field'])) {
139+
return;
140+
}
141+
142+
$vals = $content_entity->get($field_config['base_field'])->getValue();
143+
foreach ($vals as $element) {
144+
$rel_type = $element['rel_type'];
145+
if (in_array($rel_type, $field_config['rel_types'])) {
146+
$tid = $element['target_id'];
147+
$taxo_term = $this->entityTypeManager
148+
->getStorage('taxonomy_term')
149+
->load($tid);
150+
if ($taxo_term) {
151+
$taxo_name = $taxo_term->name->value;
152+
$search_api_field->addValue($taxo_name);
153+
}
154+
}
155+
}
156+
}
157+
}
158+
159+
/**
160+
* {@inheritdoc}
161+
*/
162+
public function requiresReindexing(array $old_settings = NULL, array $new_settings = NULL) {
163+
if ($new_settings != $old_settings) {
164+
return TRUE;
165+
}
166+
return FALSE;
167+
}
168+
169+
}

0 commit comments

Comments
 (0)