wayfinding-2.1.x-dev/src/Form/Settings.php
src/Form/Settings.php
<?php
namespace Drupal\wayfinding\Form;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\Field\WidgetPluginManager;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\TypedData\DataDefinitionInterface;
use Drupal\wayfinding\EntityTypes;
use Drupal\wayfinding\Event\SettingsOptionEvent;
use Drupal\wayfinding\WayfindingEvents;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* Configure Way finding settings for this site.
*/
class Settings extends ConfigFormBase {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManager;
/**
* The entity type and bundle info service.
*
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
*/
protected EntityTypeBundleInfoInterface $entityTypeBundleInfo;
/**
* The entity field manager.
*
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/
protected EntityFieldManagerInterface $entityFieldManager;
/**
* The widget plugin manager.
*
* @var \Drupal\Core\Field\WidgetPluginManager
*/
protected WidgetPluginManager $pluginManagerFieldWidget;
/**
* The event dispatcher.
*
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
protected EventDispatcherInterface $eventDispatcher;
/**
* The entity types services.
*
* @var \Drupal\wayfinding\EntityTypes
*/
protected EntityTypes $entityTypesService;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container): Settings {
$instance = parent::create($container);
$instance->entityTypeManager = $container->get('entity_type.manager');
$instance->entityTypeBundleInfo = $container->get('entity_type.bundle.info');
$instance->entityFieldManager = $container->get('entity_field.manager');
$instance->pluginManagerFieldWidget = $container->get('plugin.manager.field.widget');
$instance->eventDispatcher = $container->get('event_dispatcher');
$instance->entityTypesService = $container->get('wayfinding.entity_types');
return $instance;
}
/**
* {@inheritdoc}
*/
public function getFormId(): string {
return 'wayfinding_settings';
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames(): array {
return ['wayfinding.settings'];
}
/**
* Build the form widget for a device.
*
* @param string $widget_id
* The widget ID.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param \Drupal\Core\StringTranslation\TranslatableMarkup $title
* The title.
* @param float $lat
* The latitude.
* @param float $lng
* The longitude.
*
* @return array
* The form widget.
*
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
protected function getWidgetForm(string $widget_id, FormStateInterface $form_state, TranslatableMarkup $title, float $lat, float $lng): array {
$widget_settings = [
'field_definition' => BaseFieldDefinition::create('geolocation')
->setName('geolocation')
->setLabel($title)
->setRequired(FALSE)
->setCardinality(1),
'form_mode' => 'default',
'prepare' => TRUE,
'configuration' => [
'type' => $widget_id,
'settings' => [],
'third_party_settings' => [],
],
];
$widget = $this->pluginManagerFieldWidget->getInstance($widget_settings);
if (!$widget) {
throw new PluginNotFoundException('geolocation', 'Plugin not found.');
}
$form['#parents'] = [];
$definition = $widget_settings['field_definition']->getFieldStorageDefinition();
if ($definition instanceof DataDefinitionInterface) {
$element = $widget->form(FieldItemList::createInstance($definition), $form, $form_state)['widget'][0];
$element['lat']['#default_value'] = $lat;
$element['lng']['#default_value'] = $lng;
return $element;
}
throw new PluginNotFoundException('geolocation', 'Plugin not found.');
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state): array {
$location = $this->config('wayfinding.settings')->get('location');
$form['#tree'] = TRUE;
$form['location'] = [
'#type' => 'fieldset',
'#title' => $this->t('Geo location'),
];
try {
$form['location']['topleft'] = $this->getWidgetForm('geolocation_latlng', $form_state, $this->t('Top left'), $location['topleft']['lat'], $location['topleft']['lng']);
$form['location']['bottomright'] = $this->getWidgetForm('geolocation_latlng', $form_state, $this->t('Bottom right'), $location['bottomright']['lat'], $location['bottomright']['lng']);
}
catch (PluginNotFoundException) {
// @todo handle exception.
}
$form['pin'] = [
'#type' => 'textfield',
'#title' => $this->t('URI to the pin svg'),
'#default_value' => $this->config('wayfinding.settings')->get('pin'),
];
$form['pindynamicposition'] = [
'#type' => 'checkbox',
'#title' => $this->t('Dynamically position the pin'),
'#default_value' => $this->config('wayfinding.settings')->get('pin dynamic position'),
];
$form['enableqrcode'] = [
'#type' => 'checkbox',
'#title' => $this->t('Support QR codes for route instructions'),
'#default_value' => $this->config('wayfinding.settings')->get('enable qr code'),
];
$form['enablepopups'] = [
'#type' => 'checkbox',
'#title' => $this->t('Support content popups'),
'#default_value' => $this->config('wayfinding.settings')->get('enable popups'),
];
$form['popupdestination'] = [
'#type' => 'select',
'#title' => $this->t('Destination for content popups'),
'#options' => [
'popup' => $this->t('Popup'),
'.legend-wrapper.before .content-container-before' => $this->t('Before early legends'),
'.legend-wrapper.before .content-container-after' => $this->t('After early legends'),
'.images-wrapper .content-container-before' => $this->t('Before image'),
'.images-wrapper .content-container-after' => $this->t('After image'),
'.legend-wrapper.after .content-container-before' => $this->t('Before late legends'),
'.legend-wrapper.after .content-container-after' => $this->t('After late legends'),
],
'#default_value' => $this->config('wayfinding.settings')->get('popup destination'),
];
$form['resettimeout'] = [
'#type' => 'textfield',
'#title' => $this->t('Reset timeout in seconds'),
'#default_value' => $this->config('wayfinding.settings')->get('reset timeout'),
];
$form['wrappertitle'] = [
'#type' => 'textfield',
'#title' => $this->t('Optional title for the wrapper'),
'#default_value' => $this->config('wayfinding.settings')->get('wrapper title'),
];
$bundles = $this->entityTypeBundleInfo->getAllBundleInfo();
$destinations = [];
$sources = [];
$entity_types = [];
foreach ($this->entityTypesService->allEnabled() as $definition) {
if (isset($bundles[$definition->id()])) {
$entity_types[$definition->id()] = $definition->getLabel()->render();
foreach ($bundles[$definition->id()] as $bundle => $def) {
if ($bundle === 'wayfinding' && $definition->id() === 'media') {
continue;
}
$id = $definition->id() . ' ' . $bundle;
$label = $definition->id() === $bundle ?
$definition->getLabel()->render() :
$definition->getLabel() . ' - ' . $def['label'];
$destinations[$id] = $label;
}
}
}
foreach ($destinations as $id => $label) {
[$entity_type, $bundle] = explode(' ', $id);
foreach ($this->entityFieldManager->getFieldDefinitions($entity_type, $bundle) as $field) {
if (
$field->getName() !== 'digital_signage' &&
($field->getType() === 'entity_reference' || $field->getType() === 'dynamic_entity_reference') &&
!str_starts_with($field->getName(), 'revision_')) {
$target_type = $field->getSetting('target_type');
if (isset($entity_types[$entity_type], $entity_types[$target_type]) && !isset($sources[$entity_type])) {
$sources[$entity_type] = $entity_types[$entity_type];
}
}
}
}
$event = new SettingsOptionEvent($sources, $destinations);
$this->eventDispatcher->dispatch($event, WayfindingEvents::SETTINGSOPTIONS);
$form['types'] = [
'#type' => 'fieldset',
'#title' => $this->t('Entity types'),
];
$form['types']['destinations'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Destinations'),
'#options' => $event->getDestinations(),
'#default_value' => $this->config('wayfinding.settings')->get('types.destinations'),
'#description' => $this->t('Destination entities will be displayed in the map if you enable the "published" checkbox in the wayfinding tab of the entity edit form.'),
];
$form['types']['sources'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Sources'),
'#options' => $event->getSources(),
'#default_value' => $this->config('wayfinding.settings')->get('types.sources'),
'#description' => $this->t('Source entity types are limited to those that have an entity reference to one of the available destination entity types. Select those types that you want to include in the wayfinding legend and enable the "published" checkbox in the wayfinding tab of the entity edit form for the individual entities.'),
];
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state): void {
$pin = $form_state->getValue('pin');
if (!file_exists($pin)) {
$form_state->setError($form['pin'], 'Pin file does not exist.');
}
parent::validateForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state): void {
$this->config('wayfinding.settings')
->set('location', $form_state->getValue('location'))
->set('pin', $form_state->getValue('pin'))
->set('pin dynamic position', $form_state->getValue('pindynamicposition'))
->set('enable qr code', $form_state->getValue('enableqrcode'))
->set('enable popups', $form_state->getValue('enablepopups'))
->set('popup destination', $form_state->getValue('popupdestination'))
->set('reset timeout', $form_state->getValue('resettimeout'))
->set('wrapper title', $form_state->getValue('wrappertitle'))
->set('types', $form_state->getValue('types'))
->save();
parent::submitForm($form, $form_state);
}
}
