scanner-8.x-1.0-rc3/src/Form/ScannerAdminForm.php
src/Form/ScannerAdminForm.php
<?php
namespace Drupal\scanner\Form;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\scanner\Plugin\ScannerPluginManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Form for configuring the default scanner settings.
*/
class ScannerAdminForm extends ConfigFormBase {
/**
* Constructs a ScannerAdminForm object.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The factory for configuration objects.
* @param \Drupal\Core\Config\TypedConfigManagerInterface $typedConfigManager
* The typed config manager.
* @param \Drupal\scanner\Plugin\ScannerPluginManager $scannerPluginManager
* The scanner plugin manager.
* @param \Drupal\Core\Language\LanguageManagerInterface $languageManager
* The language manager.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager
* The entity field manager.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entityTypeBundleInfo
* The entity bundle info service.
*/
public function __construct(
ConfigFactoryInterface $config_factory,
TypedConfigManagerInterface $typedConfigManager,
protected ScannerPluginManager $scannerPluginManager,
protected LanguageManagerInterface $languageManager,
protected EntityTypeManagerInterface $entityTypeManager,
protected EntityFieldManagerInterface $entityFieldManager,
protected EntityTypeBundleInfoInterface $entityTypeBundleInfo,
) {
parent::__construct($config_factory, $typedConfigManager);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container): static {
return new static(
$container->get('config.factory'),
$container->get('config.typed'),
$container->get('plugin.manager.scanner'),
$container->get('language_manager'),
$container->get('entity_type.manager'),
$container->get('entity_field.manager'),
$container->get('entity_type.bundle.info')
);
}
/**
* {@inheritdoc}
*/
public function getFormId(): string {
return 'scanner_admin_settings';
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames(): array {
return ['scanner.admin_settings'];
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state): array {
$config = $this->config('scanner.admin_settings');
$form['word_boundaries'] = [
'#type' => 'radios',
'#title' => $this->t('Regex word boundaries'),
'#options' => [
'auto' => $this->t('Detect automatically; should work for most sites'),
'spencer' => $this->t('Henry Spencer mode - [[:<:]] and [[:>:]] - MySQL (8.0.3 and older), MariaDB (all versions)'),
'icu' => $this->t('ICU mode - \b - MySQL (8.0.4 and newer)'),
],
'#default_value' => $config->get('word_boundaries') ?? 'spencer',
'#description' => $this->t('MariaDB and all releases of MySQL prior to 8.0.4 used the first option, whereas MySQL 8.0.4 and newer use the second option.'),
'#required' => TRUE,
];
$form['settings'] = [
'#type' => 'fieldset',
'#title' => $this->t('Default options'),
];
$form['settings']['scanner_mode'] = [
'#type' => 'checkbox',
'#title' => $this->t('Default: Case sensitive search mode'),
'#default_value' => $config->get('scanner_mode'),
];
$form['settings']['scanner_wholeword'] = [
'#type' => 'checkbox',
'#title' => $this->t('Default: Match whole word'),
'#default_value' => $config->get('scanner_wholeword'),
];
$form['settings']['scanner_regex'] = [
'#type' => 'checkbox',
'#title' => $this->t('Default: Regular expression search'),
'#default_value' => $config->get('scanner_regex'),
];
$form['settings']['scanner_published'] = [
'#type' => 'checkbox',
'#title' => $this->t('Default: Search published nodes only'),
'#default_value' => $config->get('scanner_published'),
];
$form['settings']['scanner_pathauto'] = [
'#type' => 'checkbox',
'#title' => $this->t('Default: Maintain custom aliases'),
'#default_value' => $config->get('scanner_pathauto'),
];
$langs = $this->getLanguages();
$form['settings']['scanner_language'] = [
'#type' => 'select',
'#title' => $this->t('Default: Content language'),
'#options' => $langs,
'#default_value' => $config->get('scanner_language'),
];
$available_entity_types = $this->getAvailableEntityTypes();
$form['enabled_content_types'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Enabled entity types'),
'#options' => $available_entity_types,
'#default_value' => $config->get('enabled_content_types'),
'#description' => $this->t('Third party plugins can be written to add more options here.'),
'#attributes' => [
'data-scanner-select-all' => TRUE,
'data-scanner-select-all-screen-reader-label' => $this->t("Select all entity types"),
'data-scanner-select-none-screen-reader-label' => $this->t("Deselect all entity types"),
],
'#attached' => ['library' => ['scanner/select-all']],
'#ajax' => [
'callback' => [$this, 'getFieldsCallback'],
'event' => 'change',
'wrapper' => 'content-type-fields',
],
];
$enabled_entity_types = $form_state->getValue('enabled_content_types');
if ($enabled_entity_types === NULL) {
$enabled_entity_types = $this->config('scanner.admin_settings')->get('enabled_content_types');
}
$fields = $this->getEntityTypeFields($available_entity_types, $enabled_entity_types);
$form['fields_of_selected_content_type'] = [
'#title' => $this->t('Enabled fields'),
'#type' => 'checkboxes',
'#options' => $fields,
'#default_value' => $config->get('fields_of_selected_content_type'),
'#prefix' => '<div id="content-type-fields">',
'#suffix' => '</div>',
'#attributes' => [
'data-scanner-select-all' => TRUE,
'data-scanner-select-all-screen-reader-label' => $this->t("Select all fields"),
'data-scanner-select-none-screen-reader-label' => $this->t("Deselect all fields"),
],
'#attached' => ['library' => ['scanner/select-all']],
];
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state): void {
$this->config('scanner.admin_settings')
->set('scanner_mode', $form_state->getValue('scanner_mode'))
->set('scanner_regex', $form_state->getValue('scanner_regex'))
->set('scanner_wholeword', $form_state->getValue('scanner_wholeword'))
->set('scanner_published', $form_state->getValue('scanner_published'))
->set('scanner_pathauto', $form_state->getValue('scanner_pathauto'))
->set('scanner_language', $form_state->getValue('scanner_language'))
->set('word_boundaries', $form_state->getValue('word_boundaries'))
->set('enabled_content_types', array_filter($form_state->getValue('enabled_content_types')))
->set('fields_of_selected_content_type', array_filter($form_state->getValue('fields_of_selected_content_type')))
->save();
parent::submitForm($form, $form_state);
}
/**
* AJAX callback for fetching the entity type fields.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @return array
* List of entity type fields.
*/
public function getFieldsCallback(array $form, FormStateInterface $form_state): array {
return $form['fields_of_selected_content_type'];
}
/**
* Gets a list of available entity types as input options.
*
* @return array
* An array containing the entity type options.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
*/
protected function getAvailableEntityTypes(): array {
$options = [];
// Iterate over the available plugins to get their 'types'.
foreach ($this->scannerPluginManager->getDefinitions() as $definition) {
$entity_type_id = $definition['type'];
try {
$entity_type = $this->entityTypeManager->getStorage($entity_type_id)->getEntityType();
}
catch (PluginNotFoundException) {
// Non-existent entity was provided. Ignore it.
continue;
}
$bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id);
foreach ($bundles as $bundle_id => $bundle) {
$options["$entity_type_id:$bundle_id"] = $this->t('@entity_type » @bundle', [
'@entity_type' => $entity_type->getLabel(),
'@bundle' => $bundle['label'],
]);
}
}
return $options;
}
/**
* Gets a list of entity fields as input options.
*
* @param array $available_entity_types
* List of available entity types.
* @param array $entity_types
* The entity types, with their relevant bundles.
*
* @return array
* An array containing the fields of the entity types.
*/
protected function getEntityTypeFields(array $available_entity_types, array $entity_types): array {
$options = [];
// Iterate through each of the selected entity types and get their fields.
foreach ($entity_types as $key => $value) {
if (empty($value) || !isset($available_entity_types[$key])) {
// Ignore the entity type if it's unticked
// or the entity type no longer exists.
continue;
}
[$entity_type, $bundle] = explode(':', $key);
// Get the fields for the given entity type and bundle.
$field_definitions = $this->entityFieldManager->getFieldDefinitions($entity_type, $bundle);
foreach ($field_definitions as $field_name => $field_definition) {
// @todo Update in https://www.drupal.org/project/scanner/issues/3495498
// Ignore computed fields.
if ($field_definition->isComputed()) {
continue;
}
$allowed_field_type = [
// @todo Why no string_long?
'string', 'text_with_summary', 'text', 'text_long', 'link',
];
// We are only interested in certain field types.
if (in_array($field_definition->getType(), $allowed_field_type, TRUE)) {
// Skip fields starting with "parent_" (Paragraphs internal fields).
if (str_starts_with($field_name, 'parent_')) {
continue;
}
$name_with_type = "$entity_type:$bundle:$field_name";
$options[$name_with_type] = $this->t('@entity_bundle » @field_label <small><strong>(@field_name)</strong></small>', [
'@entity_bundle' => $available_entity_types[$key],
'@field_label' => $field_definition->getLabel(),
'@field_name' => $field_name,
]);
}
}
}
return $options;
}
/**
* Gets a list of languages as input options.
*
* @return array
* An array containing the list of enabled languages.
*/
protected function getLanguages(): array {
$languages = $this->languageManager->getLanguages();
$items = [
'all' => $this->t('All'),
];
foreach ($languages as $language) {
$items[$language->getId()] = $language->getName();
}
return $items;
}
}
