View source
<?php
namespace Drupal\tour_ui\Form;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\FormState;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\tour\TipPluginManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Url;
class TourForm extends EntityForm {
protected $entityTypeManager;
protected $tipPluginManager;
protected $languageManager;
protected $messenger;
public static function create(ContainerInterface $container) {
return new static($container
->get('entity_type.manager'), $container
->get('language_manager'), $container
->get('plugin.manager.tour.tip'), $container
->get('messenger'));
}
public function __construct(EntityTypeManagerInterface $entity_type_manager, LanguageManagerInterface $languageManager, TipPluginManager $tipPluginManager, MessengerInterface $messenger) {
$this->entityTypeManager = $entity_type_manager;
$this->languageManager = $languageManager;
$this->tipPluginManager = $tipPluginManager;
$this->messenger = $messenger;
}
public function form(array $form, FormStateInterface $form_state) {
$tour = $this->entity;
$form = parent::form($form, $form_state);
$form['label'] = [
'#type' => 'textfield',
'#title' => $this
->t('Tour name'),
'#required' => TRUE,
'#default_value' => $tour
->label(),
];
$form['id'] = [
'#type' => 'machine_name',
'#machine_name' => [
'exists' => '\\Drupal\\tour\\Entity\\Tour::load',
'replace_pattern' => '[^a-z0-9-]+',
'replace' => '-',
],
'#default_value' => $tour
->id(),
'#disabled' => !$tour
->isNew(),
];
$form['langcode'] = [
'#type' => 'language_select',
'#title' => $this
->t('Language'),
'#languages' => LanguageInterface::STATE_ALL,
'#default_value' => empty($tour
->language()) ? $this->languageManager
->getCurrentLanguage()
->getId() : $tour
->language()
->getId(),
];
$form['module'] = [
'#type' => 'textfield',
'#title' => $this
->t('Module name'),
'#description' => $this
->t('Each tour needs a module.'),
'#required' => TRUE,
'#autocomplete_route_name' => 'tour_ui.get_modules',
'#default_value' => $tour
->get('module'),
];
$default_routes = [];
if ($routes = $tour
->getRoutes()) {
foreach ($routes as $route) {
$default_routes[] = $route['route_name'];
if (isset($route['route_params'])) {
foreach ($route['route_params'] as $key => $value) {
$default_routes[] = '- ' . $key . ':' . $value;
}
}
}
}
$form['routes'] = [
'#type' => 'textarea',
'#title' => $this
->t('Routes'),
'#default_value' => implode("\n", $default_routes),
'#rows' => 5,
'#description' => $this
->t('Provide a list of routes that this tour will be displayed on. Add route_name first then optionally route parameters. For example <pre>entity.node.canonical<br/>- node:2</pre> will only show on the <em>node/2</em> page.<br/>NOTE: route parameters are <strong>not validated yet</strong>.'),
];
$form['find-routes'] = [
'#type' => 'textfield',
'#title' => $this
->t('Find route or path fragment'),
'#description' => $this
->t('You can type a route name or path fragment.'),
'#required' => FALSE,
'#autocomplete_route_name' => 'tour_ui.get_routes',
];
if ($tour
->isNew()) {
return $form;
}
$form['tips'] = [
'#type' => 'table',
'#header' => [
$this
->t('Label'),
$this
->t('Weight'),
$this
->t('Operations'),
],
'#caption' => [
[
'#markup' => $this
->t('Tips provided by this tour. By clicking on Operations buttons, every changes which are not saved will be lost.'),
],
],
'#tabledrag' => [
[
'action' => 'order',
'relationship' => 'sibling',
'group' => 'tip-order-weight',
],
],
'#weight' => 40,
];
$tips = $tour
->getTips();
if (!empty($tips)) {
foreach ($tips as $tip) {
$tip_id = $tip
->get('id');
try {
$form['#data'][$tip_id] = $tip
->getConfiguration();
} catch (\Error $e) {
$this->messenger
->addMessage($this
->t('Tip %tip is not configurable. You cannot save this tour.', [
'%tip' => $tip
->getLabel(),
]), 'warning');
}
$form['tips'][$tip_id]['#attributes']['class'][] = 'draggable';
$form['tips'][$tip_id]['label'] = [
'#plain_text' => $tip
->get('label'),
];
$form['tips'][$tip_id]['weight'] = [
'#type' => 'weight',
'#title' => $this
->t('Weight for @title', [
'@title' => $tip
->get('label'),
]),
'#delta' => 100,
'#title_display' => 'invisible',
'#default_value' => $tip
->get('weight'),
'#attributes' => [
'class' => [
'tip-order-weight',
],
],
];
$links = [];
if (method_exists($tip, 'buildConfigurationForm')) {
$links['edit'] = [
'title' => $this
->t('Edit'),
'url' => Url::fromRoute('tour_ui.tip.edit', [
'tour' => $tour
->id(),
'tip' => $tip_id,
]),
];
}
$links['delete'] = [
'title' => $this
->t('Delete'),
'url' => Url::fromRoute('tour_ui.tip.delete', [
'tour' => $tour
->id(),
'tip' => $tip_id,
]),
];
$form['tips'][$tip_id]['operations'] = [
'#type' => 'operations',
'#links' => $links,
];
}
}
$tip_definitions = $this->tipPluginManager
->getDefinitions();
$tip_definition_options = [];
foreach ($tip_definitions as $tip => $definition) {
if (method_exists($definition['class'], 'buildConfigurationForm')) {
$tip_definition_options[$tip] = $definition['title'];
}
}
$user_input = $form_state
->getUserInput();
$form['tips']['new'] = [
'#tree' => FALSE,
'#weight' => isset($user_input['weight']) ? $user_input['weight'] : 0,
'#attributes' => [
'class' => [
'draggable',
],
],
];
$form['tips']['new']['new'] = [
'#type' => 'select',
'#title' => $this
->t('Tip'),
'#title_display' => 'invisible',
'#options' => $tip_definition_options,
'#empty_option' => $this
->t('Select a new tip'),
];
$form['tips']['new']['weight'] = [
'#type' => 'weight',
'#title' => $this
->t('Weight for new tip'),
'#title_display' => 'invisible',
'#default_value' => count($form['tips']) - 1,
'#attributes' => [
'class' => [
'tip-order-weight',
],
],
];
$form['tips']['new']['add'] = [
'#type' => 'submit',
'#value' => $this
->t('Add'),
'#validate' => [
[
$this,
'tipValidate',
],
],
'#submit' => [
[
$this,
'tipAdd',
],
],
];
return $form;
}
public function tipValidate($form, FormStateInterface $form_state) {
if (!$form_state
->getValue('new')) {
$form_state
->setError($form['tips']['new']['new'], $this
->t('Select a new tip.'));
}
}
public function tipAdd($form, FormStateInterface $form_state) {
$tour = $this
->getEntity($form_state);
$this::submitForm($form, $form_state, FALSE);
$weight = 0;
if (!$form_state
->isValueEmpty('tips')) {
foreach ($form_state
->getValue('tips') as $tip) {
if ($tip['weight'] > $weight) {
$weight = $tip['weight'] + 1;
}
}
}
$stub = $this->tipPluginManager
->createInstance($form_state
->getValue('new'), []);
$stub_form = $stub
->buildConfigurationForm([], new FormState());
if (isset($stub_form)) {
$form_state
->setRedirect('tour_ui.tip.add', [
'tour' => $tour
->id(),
'type' => $form_state
->getValue('new'),
], [
'query' => [
'weight' => $weight,
],
]);
}
}
public function validateForm(array &$form, FormStateInterface $form_state, $redirect = TRUE) {
$routes = $this
->routesFromArray($form_state
->getValue('routes'));
if (!$form_state
->isValueEmpty('tips')) {
foreach ($form_state
->getValue('tips') as $key => $values) {
if (!isset($form['#data'][$key])) {
$form_state
->setError($form['tips'][$key], $this
->t('You cannot save the tour while %tip tip cannot be exported.', [
'%tip' => $this
->getEntity()
->getTip($key)
->getLabel(),
]));
}
}
}
}
protected function routesFromArray($routes_in) {
$routes_in = preg_replace("/(\r\n?|\n)/", "\n", $routes_in);
$routes_in = explode("\n", $routes_in);
$routes_in = array_map('trim', $routes_in);
$routes = [];
$route = null;
foreach ($routes_in as $line) {
if (empty($line)) {
continue;
}
if (strpos($line, '-') !== 0) {
$routes[] = [];
$route =& $routes[count($routes) - 1];
$route['route_name'] = $line;
}
else {
if (count($routes) === 0) {
break;
}
list($key, $value) = explode(':', $line, 2);
$key = trim(substr($key, 1));
$value = trim($value);
$route['route_params'][$key] = $value;
}
}
return $routes;
}
public function submitForm(array &$form, FormStateInterface $form_state, $redirect = TRUE) {
$routes = $this
->routesFromArray($form_state
->getValue('routes'));
$form_state
->setValue('routes', array_filter($routes));
if (!$form_state
->isValueEmpty('tips')) {
$tips = [];
foreach ($form_state
->getValue('tips') as $key => $values) {
$data = $form['#data'][$key];
$tips[$key] = array_merge($data, $values);
if (!is_array($tips[$key]['attributes'])) {
$tips[$key]['attributes'] = [];
}
}
$form_state
->setValue('tips', $tips);
}
else {
$form_state
->setValue('tips', []);
}
parent::submitForm($form, $form_state);
if ($redirect) {
$form_state
->setRedirect('entity.tour.edit_form', [
'tour' => $this->entity
->id(),
]);
}
}
public function delete(array $form, FormStateInterface $form_state) {
$entity = $this
->getEntity($form_state);
$form_state
->setRedirect('entity.tour.delete_form', [
'tour' => $entity
->id(),
]);
}
}