View source
<?php
namespace Drupal\search_api\Form;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Core\Form\SubformState;
use Drupal\Core\Url;
use Drupal\Core\Utility\Error;
use Drupal\search_api\Backend\BackendPluginManager;
use Drupal\search_api\ServerInterface;
use Drupal\search_api\Utility\Utility;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ServerForm extends EntityForm {
protected $backendPluginManager;
protected $messenger;
public function __construct(BackendPluginManager $backend_plugin_manager, MessengerInterface $messenger) {
$this->backendPluginManager = $backend_plugin_manager;
$this->messenger = $messenger;
}
public static function create(ContainerInterface $container) {
$backend_plugin_manager = $container
->get('plugin.manager.search_api.backend');
$messenger = $container
->get('messenger');
return new static($backend_plugin_manager, $messenger);
}
public function form(array $form, FormStateInterface $form_state) {
if ($form_state
->isRebuilding()) {
$this->entity = $this
->buildEntity($form, $form_state);
}
$form = parent::form($form, $form_state);
$server = $this
->getEntity();
if ($server
->isNew()) {
$form['#title'] = $this
->t('Add search server');
}
else {
$form['#title'] = $this
->t('Edit search server %label', [
'%label' => $server
->label(),
]);
}
$this
->buildEntityForm($form, $form_state, $server);
if ($form) {
$this
->buildBackendConfigForm($form, $form_state, $server);
}
return $form;
}
public function buildEntityForm(array &$form, FormStateInterface $form_state, ServerInterface $server) {
$form['#attached']['library'][] = 'search_api/drupal.search_api.admin_css';
$form['name'] = [
'#type' => 'textfield',
'#title' => $this
->t('Server name'),
'#description' => $this
->t('Enter the displayed name for the server.'),
'#default_value' => $server
->label(),
'#required' => TRUE,
];
$form['id'] = [
'#type' => 'machine_name',
'#default_value' => $server
->isNew() ? NULL : $server
->id(),
'#maxlength' => 50,
'#required' => TRUE,
'#machine_name' => [
'exists' => '\\Drupal\\search_api\\Entity\\Server::load',
'source' => [
'name',
],
],
'#disabled' => !$server
->isNew(),
];
$form['status'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Enabled'),
'#description' => $this
->t('Only enabled servers can index items or execute searches.'),
'#default_value' => $server
->status(),
];
$form['description'] = [
'#type' => 'textarea',
'#title' => $this
->t('Description'),
'#description' => $this
->t('Enter a description for the server.'),
'#default_value' => $server
->getDescription(),
];
$backends = $this->backendPluginManager
->getDefinitions();
$backend_options = [];
$descriptions = [];
foreach ($backends as $backend_id => $definition) {
$config = $backend_id === $server
->getBackendId() ? $server
->getBackendConfig() : [];
$config['#server'] = $server;
try {
$backend = $this->backendPluginManager
->createInstance($backend_id, $config);
} catch (PluginException $e) {
continue;
}
if ($backend
->isHidden()) {
continue;
}
$backend_options[$backend_id] = Utility::escapeHtml($backend
->label());
$descriptions[$backend_id]['#description'] = Utility::escapeHtml($backend
->getDescription());
}
asort($backend_options, SORT_NATURAL | SORT_FLAG_CASE);
if ($backend_options) {
if (count($backend_options) == 1) {
$server
->set('backend', key($backend_options));
}
$form['backend'] = [
'#type' => 'radios',
'#title' => $this
->t('Backend'),
'#description' => $this
->t('Choose a backend to use for this server.'),
'#options' => $backend_options,
'#default_value' => $server
->getBackendId(),
'#required' => TRUE,
'#disabled' => !$server
->isNew(),
'#ajax' => [
'callback' => [
get_class($this),
'buildAjaxBackendConfigForm',
],
'wrapper' => 'search-api-backend-config-form',
'method' => 'replace',
'effect' => 'fade',
],
];
$form['backend'] += $descriptions;
}
else {
$url = 'https://www.drupal.org/docs/8/modules/search-api/getting-started/server-backends-and-features';
$args[':url'] = Url::fromUri($url)
->toString();
$error = $this
->t('There are no backend plugins available for the Search API. Please install a <a href=":url">module that provides a backend plugin</a> to proceed.', $args);
$this->messenger
->addError($error);
$form = [];
}
}
protected function actions(array $form, FormStateInterface $form_state) {
if ($form === []) {
return [];
}
return parent::actions($form, $form_state);
}
public function buildBackendConfigForm(array &$form, FormStateInterface $form_state, ServerInterface $server) {
$form['backend_config'] = [];
if ($server
->hasValidBackend()) {
$backend = $server
->getBackend();
$form_state
->set('backend', $backend
->getPluginId());
if ($backend instanceof PluginFormInterface) {
if ($form_state
->isRebuilding()) {
$this->messenger
->addWarning($this
->t('Please configure the selected backend.'));
}
$backend_form_state = SubformState::createForSubform($form['backend_config'], $form, $form_state);
$form['backend_config'] = $backend
->buildConfigurationForm($form['backend_config'], $backend_form_state);
$form['backend_config']['#type'] = 'details';
$form['backend_config']['#title'] = $this
->t('Configure %plugin backend', [
'%plugin' => $backend
->label(),
]);
$form['backend_config']['#open'] = TRUE;
}
}
elseif (!$server
->isNew()) {
$this->messenger
->addError($this
->t('The backend plugin is missing or invalid.'));
return;
}
$form['backend_config'] += [
'#type' => 'container',
];
$form['backend_config']['#attributes']['id'] = 'search-api-backend-config-form';
$form['backend_config']['#tree'] = TRUE;
}
public static function buildAjaxBackendConfigForm(array $form, FormStateInterface $form_state) {
return $form['backend_config'];
}
public function validateForm(array &$form, FormStateInterface $form_state) {
parent::validateForm($form, $form_state);
$server = $this
->getEntity();
$backend_id = $server
->getBackendId();
if ($backend_id != $form_state
->get('backend')) {
$input =& $form_state
->getUserInput();
$input['backend_config'] = [];
$new_backend = $this->backendPluginManager
->createInstance($form_state
->getValue('backend'));
if ($new_backend instanceof PluginFormInterface) {
$form_state
->setRebuild();
}
}
elseif ($server
->hasValidBackend()) {
$backend = $server
->getBackend();
if ($backend instanceof PluginFormInterface) {
$backend_form_state = SubformState::createForSubform($form['backend_config'], $form, $form_state);
$backend
->validateConfigurationForm($form['backend_config'], $backend_form_state);
}
}
}
public function submitForm(array &$form, FormStateInterface $form_state) {
parent::submitForm($form, $form_state);
$server = $this
->getEntity();
if ($server
->hasValidBackend()) {
$backend = $server
->getBackend();
if ($backend instanceof PluginFormInterface) {
$backend_form_state = SubformState::createForSubform($form['backend_config'], $form, $form_state);
$backend
->submitConfigurationForm($form['backend_config'], $backend_form_state);
}
}
return $server;
}
public function save(array $form, FormStateInterface $form_state) {
if (!$form_state
->isRebuilding()) {
try {
$server = $this
->getEntity();
$server
->save();
$this->messenger
->addStatus($this
->t('The server was successfully saved.'));
$form_state
->setRedirect('entity.search_api_server.canonical', [
'search_api_server' => $server
->id(),
]);
} catch (EntityStorageException $e) {
$form_state
->setRebuild();
$message = '%type: @message in %function (line %line of %file).';
$variables = Error::decodeException($e);
$this
->getLogger('search_api')
->error($message, $variables);
$this->messenger
->addError($this
->t('The server could not be saved.'));
}
}
}
}