acquia_search-3.0.1/acquia_search.module
acquia_search.module
<?php
/**
* @file
* Integration between Drupal and Acquia's hosted Solr search service.
*/
use Drupal\acquia_search\Helper\Messages;
use Drupal\acquia_search\Helper\Runtime;
use Drupal\acquia_search\Plugin\search_api\backend\AcquiaSearchSolrBackend;
use Drupal\acquia_search\Plugin\SolrConnector\SearchApiSolrAcquiaConnector;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\search_api\Entity\Server;
use Drupal\search_api\Form\IndexProcessorsForm;
use Drupal\search_api\IndexInterface;
use Drupal\search_api\Query\QueryInterface;
use Drupal\search_api\SearchApiException;
use Drupal\search_api\ServerInterface;
use Laminas\Stdlib\ArrayUtils;
use Solarium\Core\Query\QueryInterface as SolariumQueryInterface;
/**
* Implements hook_modules_installed().
*/
/**
* Implements hook_modules_installed().
*/
function acquia_search_modules_installed($modules, $is_syncing) {
// During a config import, we shouldn't try to install additional modules.
if ($is_syncing) {
return;
}
// Install acquia search default server by default.
if (in_array('acquia_search', $modules)) {
\Drupal::service('module_installer')->install(['acquia_search_defaults']);
}
}
/**
* Implements hook_search_api_server_load().
*
* Flag when a certain server should be enforcing read-only mode.
*/
function acquia_search_search_api_server_load(array $entities) {
/** @var \Drupal\search_api\Entity\Server[] $entities */
$acquia_servers = array_filter($entities, function ($server) {
return Runtime::isAcquiaServer($server);
});
foreach ($acquia_servers as $server) {
// This is needed in case anyone didn't re-export their config after running
// the post_update hook to update Search API server configuration.
// @see acquia_search_post_update_acquia_search_solr_backend().
if ($server->getBackendId() !== 'acquia_search_solr') {
$server->set('backend', 'acquia_search_solr');
}
$backend = $server->getBackend();
if (!$backend instanceof AcquiaSearchSolrBackend) {
// This should never happen.
continue;
}
$backend_config = $backend->getConfiguration();
if (!$backend->isPreferredCoreAvailable() && $server->status()) {
$server->disable();
continue;
}
if ($backend->isReadOnly()) {
$backend_config['overridden_by_acquia_search'] = SearchApiSolrAcquiaConnector::READ_ONLY;
}
$server->setBackendConfig($backend_config);
}
}
/**
* Implements hook_search_api_index_load().
*
* This takes care of marking indexes as read-only mode under the right
* conditions (@see acquia_search_search_api_server_load()).
*/
function acquia_search_search_api_index_load($entities) {
// Loop through the Index entities.
/** @var \Drupal\search_api\Entity\Index $index */
foreach ($entities as $index) {
// Check for server-less indexes.
// An infinite loop will occur if this tries to load a server.
// @see https://www.drupal.org/project/acquia_connector/issues/2956737
$server = $index->getServerInstance();
if (!$server instanceof ServerInterface) {
continue;
}
if (!$server->status()) {
continue;
}
$backend = $server->getBackend();
if (!$backend instanceof AcquiaSearchSolrBackend) {
continue;
}
// Reset the overridden_by_acquia_search option.
$options = $index->getOptions();
if (!empty($options['overridden_by_acquia_search'])) {
unset($options['overridden_by_acquia_search']);
$index->setOptions($options);
}
if ($backend->isReadOnly()) {
// Set this index to read-only mode.
$index->set('read_only', TRUE);
// Flag this index as having been altered by this module.
$index->setOption('overridden_by_acquia_search', SearchApiSolrAcquiaConnector::READ_ONLY);
}
}
}
/**
* Implements hook_form_FORM_ID_alter().
*
* Alters the Search API server's status form and displays a warning.
*/
function acquia_search_form_search_api_server_status_alter(&$form) {
if (empty($form['#server'])) {
return;
}
$server = $form['#server'];
if (!$server instanceof ServerInterface) {
return;
}
$backend = $server->getBackend();
if (!$backend instanceof AcquiaSearchSolrBackend) {
return;
}
if ($backend->isReadOnly()) {
// Show read-only warning and disable the "Delete all indexed data on this
// server" action.
Messages::showReadOnlyModeWarning();
$form['actions']['clear']['#disabled'] = TRUE;
}
if (!$backend->isPreferredCoreAvailable()) {
Messages::showNoPreferredCoreError($backend);
}
}
/**
* Implements hook_form_FORM_ID_alter().
*
* Shows message if we are editing a Search API server's configuration.
*/
function acquia_search_form_search_api_index_edit_form_alter(&$form, FormState $form_state) {
/** @var \Drupal\search_api\Entity\Server $server */
$server = Server::load($form['server']['#default_value']);
if (!$server) {
return;
}
$backend = $server->getBackend();
if (!$backend instanceof AcquiaSearchSolrBackend) {
return;
}
if ($backend->isReadOnly()) {
Messages::showReadOnlyModeWarning();
$form['options']['read_only']['#disabled'] = TRUE;
}
if (!$backend->isPreferredCoreAvailable()) {
// Show "could not find preferred core" message.
Messages::showNoPreferredCoreError($backend);
}
$settings = [];
$default_settings = ['use_edismax' => FALSE];
/** @var \Drupal\search_api\IndexInterface $search_index */
$search_index = $form_state->getFormObject()->getEntity();
if (!$search_index->isNew()) {
$settings = $search_index->getThirdPartySettings('acquia_search');
}
$settings = ArrayUtils::merge($default_settings, $settings, TRUE);
$form['third_party_settings']['acquia_search'] = [
'#tree' => TRUE,
'#type' => 'details',
'#title' => t('Acquia Search Solr'),
'#open' => TRUE,
];
$form['third_party_settings']['acquia_search']['use_edismax'] = [
'#type' => 'checkbox',
'#title' => t('Enable eDisMax'),
'#description' => t('Using the eDisMax query parser prevents the <em>Type-specific boosting</em> from having any effect on queries. Read <a href="https://support-acquia.force.com/s/article/Should-I-enable-eDisMax-with-Acquia-Search">Should I enable eDisMax with Acquia Search?</a> to learn more.'),
'#default_value' => $settings['use_edismax'],
];
}
/**
* Implements hook_form_search_api_index_processors_alter().
*/
function acquia_search_form_search_api_index_processors_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$form_object = $form_state->getFormObject();
if (!$form_object instanceof IndexProcessorsForm) {
return;
}
$index = $form_object->getEntity();
if (!$index instanceof IndexInterface) {
return;
}
$use_edismax = $index->getThirdPartySetting(
'acquia_search',
'use_edismax',
FALSE
);
if ($use_edismax && $index->isValidProcessor('type_boost')) {
\Drupal::messenger()->addWarning(t('Using the eDisMax query parser prevents the <em>Type-specific boosting</em> from having any effect on queries.'));
}
if ($use_edismax && isset($form['status']['type_boost'])) {
$form['status']['type_boost']['#disabled'] = TRUE;
$form['status']['type_boost']['#description'] .= '<br /><strong>' . t('Using the eDisMax query parser prevents the <em>Type-specific boosting</em> from having any effect on queries.') . '</strong>';
}
}
/**
* Implements hook_theme_registry_alter().
*
* Helps us alter some Search API status pages.
*/
function acquia_search_theme_registry_alter(&$theme_registry) {
$module_handler = \Drupal::moduleHandler();
$module_path = $module_handler->getModule('acquia_search')->getPath();
$theme_registry['search_api_index']['variables']['acquia_search_info_box'] = NULL;
$theme_registry['search_api_index']['path'] = $module_path . '/templates';
$theme_registry['search_api_server']['variables']['acquia_search_info_box'] = NULL;
$theme_registry['search_api_server']['path'] = $module_path . '/templates';
}
/**
* Implements hook_preprocess_HOOK().
*
* Theme override for Search API index status page.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
* @throws \Drupal\search_api\SearchApiException
*/
function acquia_search_preprocess_search_api_index(array &$variables) {
/** @var \Drupal\search_api\IndexInterface $index */
$index = $variables['index'];
/** @var \Drupal\search_api\Entity\Server $server */
$server = $index->getServerInstance();
if ($server === NULL) {
return;
}
$backend = $server->getBackend();
if (!$backend instanceof AcquiaSearchSolrBackend) {
return;
}
if ($backend->isReadOnly()) {
Messages::showReadOnlyModeWarning();
}
if (!$backend->isPreferredCoreAvailable()) {
// Show "could not find preferred core" message.
Messages::showNoPreferredCoreError($backend);
}
$variables['acquia_search_info_box'] = [
'#type' => 'fieldset',
'#title' => t('Acquia Search status for this connection'),
'#markup' => Messages::getSearchStatusMessage($backend),
];
}
/**
* Theme override function for Search API server status page.
*
* @param array $variables
* Variables.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
* @throws \Drupal\search_api\SearchApiException
*/
function acquia_search_preprocess_search_api_server(array &$variables) {
/** @var \Drupal\search_api\Entity\Server $server */
$server = $variables['server'];
if (!Runtime::isAcquiaServer($server)) {
return;
}
$backend = $server->getBackend();
if (!$backend instanceof AcquiaSearchSolrBackend) {
// This should never happen.
return;
}
if ($backend->isReadOnly()) {
Messages::showReadOnlyModeWarning();
}
$variables['acquia_search_info_box'] = [
'#type' => 'fieldset',
'#title' => t('Acquia Search status for this connection'),
'#markup' => Messages::getSearchStatusMessage($server->getBackend()),
];
}
/**
* Implements hook_search_api_solr_query_alter().
*
* @todo Remove when support for Solr 4.2.1 is no longer supported.
*/
function acquia_search_search_api_solr_query_alter(SolariumQueryInterface $solarium_query, QueryInterface $query) {
if (class_exists('Drupal\search_api_solr\Event\SearchApiSolrEvents')) {
return;
}
$handler = $solarium_query->getHandler();
$search_index = $query->getIndex();
try {
$server = $search_index->getServerInstance();
}
catch (SearchApiException $exception) {
return;
}
if (empty($server)) {
return;
}
$backend_config = $server->getBackendConfig();
if (!(!empty($backend_config['connector']) && $backend_config['connector'] === 'solr_acquia_connector')) {
return;
}
if ('select' === $handler) {
$use_edismax = $search_index->getThirdPartySetting(
'acquia_search',
'use_edismax',
FALSE
);
if ($use_edismax) {
$solarium_query->addParam('defType', 'edismax');
}
}
}
