Skip to content

Commit

Permalink
Add the search_api_field_map module.
Browse files Browse the repository at this point in the history
  • Loading branch information
Kbentham committed Aug 14, 2018
0 parents commit 35403a6
Show file tree
Hide file tree
Showing 25 changed files with 852 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.

# dependencies
/node-modules
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Fields Search API Module

This module facilitates indexing data from multiple Drupal sites into a single Solr search index.

On each site included in the mapped field search, you will need to:

1. Install this module
2. Configure a Search API server to connect to the shared Solr index

## More information

* [How to use this module](docs/usage.md)
19 changes: 19 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "palantirnet/search_api_field_map",
"type": "drupal-module",
"description": "Allows indexing multiple Drupal sites into a single Solr search index by field.",
"keywords": ["Drupal"],
"license": "GPL-2.0+",
"minimum-stability": "dev",
"repositories": [
{
"type": "composer",
"url": "https://packages.drupal.org/8"
}
],
"require": {
"drupal/core": "^8.0",
"drupal/search_api_solr": "^1.2",
"drupal/token": "^1.1"
}
}
Binary file added docs/images/add_federated_field.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/add_federated_term_field_label.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/add_federated_term_to_term.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/add_federated_terms.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/edit_federated_field.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/save_index_field_config.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 46 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## About this module

This module provides new field options on Search API indexes:

1. The "Mapped field" field can be used to aggregate data from different entity types into the same field in the search index.

This is similar to the "Aggregated field" provided by Search API, but gives more direct, token-based control over the values for different entity types.

See [Using the "Mapped field"](#using-the-mapped-field).
1. The "Mapped terms" field can be used to assign "mapped term" values to any taxonomy term entities within a given site. See [Using the "Mapped terms" field](#using-the-mapped-terms-field).

## Using the "Mapped field"

1. Visit the fields list for your index at _Admin > Configuration > Search API > [your index] > Fields_ (path `/admin/config/search/search-api/index/YOUR_INDEX/fields`)
2. Click "Add fields"
3. Click the "Add" button for the "Mapped Field":

<img src="images/add_mapped_field.png" />

4. Configure field data for each entity type. This field allows token replacement; enter plain text directly or use the token browser to select tokens.

<img src="images/edit_mapped_field.png" />

5. Save your field.
6. Edit the field label, machine name, and type as necessary for your data

## Using the "Mapped terms" field

1. Visit the fields list for your index at _Admin > Configuration > Search API > [your index] > Fields_ (path `/admin/config/search/search-api/index/YOUR_INDEX/fields`)
1. Click "Add fields"
1. Click the "Add" button for the "Mapped terms":
<img src="images/add_mapped_terms.png" />
1. Once you have added the "Mapped terms" field to your search index configuration, you can read through the provided instructions and save the field:
<img src="images/confirmation_added_mapped_terms.png" />
1. Remember to save the index field configuration:
<img src="images/save_index_field_config.png" />
1. Configuration for mapped terms happens within the taxonomy term entity edit UI itself. Browse to a taxonomy vocabulary on your site and add an instance of the "Mapped terms" field type (If you plan on sharing this field among your vocabularies, use something like "Mapped terms" for the field label).
<img src="images/add_mapped_terms_to_vocabulary.png" />
<img src="images/add_mapped_term_field_label.png" />
1. Save the field settings
<img src="images/add_mapped_field_settings_save.png" />
<img src="images/add_mapped_field_save_settings_2.png" />
1. Edit any terms in the vocabularies to which you've just added a "Mapped terms" field instance. On the term edit form, you should now see a "Mapped terms" field instance where you can add one or many "mapped" terms.
<img src="images/add_mapped_term_to_term.png" />
1. Repeat for each term in each vocabulary which should have a mapped term value.
1. Once content which references these terms is indexed, all of their corresponding "mapped terms" will appear in the `mapped_terms` index property field.
9 changes: 9 additions & 0 deletions search_api_field_map.info.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name: Search API Field Map
type: module
description: Allows indexing multiple Drupal sites into a single Solr search index by field.
core: 8.x
package: Search
dependencies:
- search_api_solr
- token
- field
33 changes: 33 additions & 0 deletions search_api_field_map.module
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

/**
* @file search_api_field_map.module
* Contains hook implementations for the Field Map Search API Module.
*/


/**
* Implements hook_help().
*/
function search_api_field_map_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the search_api_field_map module.
case 'help.page.search_api_field_map':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('This module facilitates indexing data from multiple Drupal sites into a single Solr search index.') . '</p>';
$output .= '<h3>' . t('Usage') . '</h3>';
$output .= '<p>' . t('On each site included in the mapped field search, you will need to') . ':</p>';
$output .= '<ol>';
$output .= '<li>' . t('Install this module') . '</li>';
$output .= '<li>' . t('Configure a Search API server to connect to the shared Solr index') . '</li>';
$output .= '</ol>';
$output .= '<h3>' . t('More information') . '</h3>';
$output .= '<ul>';
$output .= '<li><a href="docs/usage.md">' . t('How to use this module') . '</a></li>';
$output .= '</ul>';
return $output;

default:
}
}
101 changes: 101 additions & 0 deletions src/Plugin/Field/FieldType/MappedTerms.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php
/**
* @file
* Contains \Drupal\search_api_field_map\Plugin\field\field_type\MappedTerms.
*/

namespace Drupal\search_api_field_map\Plugin\Field\FieldType;

use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;

/**
* Plugin implementation of the 'mapped_terms' field type.
*
* @FieldType(
* id = "mapped_terms",
* label = @Translation("Mapped terms"),
* description = @Translation("Stores the solr search api mapped term destination value for taxonomy terms."),
* default_widget = "mapped_terms_textfield",
* default_formatter = "string",
* cardinality = -1,
* )
*/
class MappedTerms extends FieldItemBase {
const MAPPED_TERMS_MAXLENGTH = 255;


/**
* {@inheritdoc}
*/
public static function defaultStorageSettings() {
return [
'max_length' => static::MAPPED_TERMS_MAXLENGTH,
'is_ascii' => FALSE,
] + parent::defaultStorageSettings();
}

/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return [
'columns' => [
'value' => [
'type' => $field_definition->getSetting('is_ascii') === TRUE ? 'varchar_ascii' : 'varchar',
'length' => static::MAPPED_TERMS_MAXLENGTH,
'not null' => FALSE,
],
],
];
}

/**
* {@inheritdoc}
*/
public function getConstraints() {
$constraints = parent::getConstraints();

if ($max_length = $this->getSetting('max_length')) {
$constraint_manager = \Drupal::typedDataManager()->getValidationConstraintManager();
$constraints[] = $constraint_manager->create('ComplexData', [
'value' => [
'Length' => [
'max' => static::MAPPED_TERMS_MAXLENGTH,
'maxMessage' => t('%name: may not be longer than @max characters.', ['%name' => $this->getFieldDefinition()->getLabel(), '@max' => static::MAPPED_TERMS_MAXLENGTH]),
],
],
]);
}
return $constraints;
}

/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties['value'] = DataDefinition::create('string')->setLabel(t('Mapped terms destination value'));
return $properties;
}

/**
* {@inheritdoc}
*/
public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {
$element = [];

$element['max_length'] = [
'#type' => 'number',
'#title' => t('Maximum length'),
'#default_value' => $this->getSetting('max_length'),
'#required' => TRUE,
'#description' => t('The maximum length of the field in characters.'),
'#min' => 1,
'#disabled' => $has_data,
];

return $element;
}
}
83 changes: 83 additions & 0 deletions src/Plugin/Field/FieldWidget/MappedTermsTextfieldWidget.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

namespace Drupal\search_api_field_map\Plugin\Field\FieldWidget;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;

/**
* Plugin implementation of the 'mapped_terms_textfield' widget.
*
* @FieldWidget(
* id = "mapped_terms_textfield",
* label = @Translation("Mapped Terms Textfield"),
* field_types = {
* "mapped_terms"
* }
* )
*/
class MappedTermsTextfieldWidget extends WidgetBase {

/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
'size' => 75,
'placeholder' => '',
] + parent::defaultSettings();
}

/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$element['size'] = [
'#type' => 'number',
'#title' => t('Size of textfield'),
'#default_value' => $this->getSetting('size'),
'#required' => TRUE,
'#min' => 1,
];
$element['placeholder'] = [
'#type' => 'textfield',
'#title' => t('Placeholder'),
'#default_value' => $this->getSetting('placeholder'),
'#description' => t('Text that will be shown inside the field until a value is entered. This hint is usually a sample value or a brief description of the expected format.'),
];
return $element;
}

/**
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = [];

$summary[] = t('Textfield size: @size', ['@size' => $this->getSetting('size')]);
$placeholder = $this->getSetting('placeholder');
if (!empty($placeholder)) {
$summary[] = t('Placeholder: @placeholder', ['@placeholder' => $placeholder]);
}

return $summary;
}

/**
* {@inheritdoc}
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$element['value'] = [
'#type' => 'textfield',
'#default_value' => isset($items[$delta]->value) ? $items[$delta]->value : NULL,
'#description' => $this->t('This mapped term is used as a facet value in your search application. It should consist of a hierarchy made up of a type (i.e. "Condition") and term (i.e. "Diabetes"), separated by ">". For example: Condition>Diabetes.'),
'#size' => $this->getSetting('size'),
'#placeholder' => $this->getSetting('placeholder'),
'#maxlength' => $this->getFieldSetting('max_length'),
'#attributes' => ['class' => ['js-text-full', 'text-full']],
];

return $element;
}
}
Loading

0 comments on commit 35403a6

Please sign in to comment.