View source
<?php
namespace Drupal\login_destination\Form;
use Drupal\Core\Entity\Element\EntityAutocomplete;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\login_destination\Entity\LoginDestination;
use Symfony\Component\DependencyInjection\ContainerInterface;
class LoginDestinationRuleForm extends EntityForm {
use StringTranslationTrait;
protected $loginDestinationStorage;
public function __construct(EntityStorageInterface $login_destination_storage) {
$this->loginDestinationStorage = $login_destination_storage;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('entity_type.manager')
->getStorage('login_destination'));
}
public function form(array $form, FormStateInterface $form_state) {
$login_destination = $this->entity;
$form['label'] = [
'#type' => 'textfield',
'#title' => $this
->t('Label'),
'#default_value' => $login_destination
->getLabel(),
'#description' => $this
->t('A short description of this login destination rule.'),
'#required' => TRUE,
];
$form['name'] = [
'#type' => 'machine_name',
'#machine_name' => [
'exists' => [
$this->loginDestinationStorage,
'load',
],
],
'#disabled' => !$login_destination
->isNew(),
'#default_value' => $login_destination
->id(),
'#required' => TRUE,
'#description' => $this
->t('A unique machine-readable name for this login destination rule.'),
];
$form['triggers'] = [
'#type' => 'checkboxes',
'#title' => $this
->t('Redirect upon triggers'),
'#options' => [
LoginDestination::TRIGGER_REGISTRATION => $this
->t('Registration'),
LoginDestination::TRIGGER_LOGIN => $this
->t('Login'),
LoginDestination::TRIGGER_ONE_TIME_LOGIN => $this
->t('One-time login link'),
LoginDestination::TRIGGER_LOGOUT => $this
->t('Logout'),
],
'#required' => TRUE,
'#default_value' => !empty($login_destination->triggers) ? $login_destination
->getTriggers() : [],
'#description' => $this
->t('Redirect only upon selected trigger(s).'),
];
$form['destination_path'] = [
'#type' => 'entity_autocomplete',
'#target_type' => 'node',
'#placeholder' => '',
'#attributes' => [
'data-autocomplete-first-character-blacklist' => '/#?[',
],
'#title' => $this
->t('Redirect destination'),
'#default_value' => $this
->getUriAsDisplayableString($login_destination
->getDestination()),
'#element_validate' => [
[
$this,
'validateUriElement',
],
],
'#maxlength' => 2048,
'#required' => TRUE,
'#process_default_value' => FALSE,
'#description' => $this
->t('Start typing the title of a piece of content to select it. You can also enter an internal path such as %add-node or an external URL such as %url. Enter %front to link to the front page. Enter %current to link to a current page.', [
'%front' => '<front>',
'%current' => '<current>',
'%add-node' => '/node/add',
'%url' => 'http://example.com',
]),
];
$form['token_tree'] = array(
'#theme' => 'token_tree_link',
'#token_types' => array(
'user',
),
'#show_restricted' => TRUE,
'#global_types' => TRUE,
);
$form['pages_type'] = [
'#type' => 'radios',
'#title' => $this
->t('Redirect from specific pages'),
'#default_value' => $login_destination
->getPagesType(),
'#options' => [
$login_destination::REDIRECT_NOT_LISTED => $this
->t('All pages except those listed'),
$login_destination::REDIRECT_LISTED => $this
->t('Only the listed pages'),
],
];
$form['pages'] = [
'#type' => 'textarea',
'#default_value' => $login_destination
->getPages(),
'#description' => $this
->t('Specify pages by using their paths. Enter one path per line. The \'*\' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page. %login is the login form. %register is the registration form. %reset is the one-time login (e-mail validation).', [
'%blog' => 'blog',
'%blog-wildcard' => '/blog/*',
'%front' => '<front>',
'%login' => '/user',
'%register' => '/user/register',
'%reset' => '/user/*/edit',
]),
];
$languages[''] = $this
->t('All languages');
foreach (\Drupal::languageManager()
->getLanguages() as $key => $value) {
$languages[$key] = $value
->getName();
}
$form['language'] = [
'#type' => 'select',
'#title' => $this
->t('Redirect for language'),
'#options' => $languages,
'#default_value' => $login_destination
->getLanguage(),
'#description' => $this
->t('Redirect only for the selected language.'),
];
$form['roles'] = [
'#type' => 'checkboxes',
'#title' => $this
->t('Redirect users with roles'),
'#options' => $login_destination
->getAllSystemRoles(),
'#default_value' => $login_destination
->getRoles(),
'#description' => $this
->t('Redirect only the selected role(s). If you select no roles, all users will be redirected.'),
];
$form['uuid'] = [
'#type' => 'value',
'#value' => $login_destination
->get('uuid'),
];
return parent::form($form, $form_state);
}
public function validateForm(array &$form, FormStateInterface $form_state) {
parent::validateForm($form, $form_state);
$roles = array_filter($form_state
->getValue('roles'));
$form_state
->setValue('roles', $roles);
$form_state
->setValue('triggers', array_filter($form_state
->getValue('triggers')));
}
public function save(array $form, FormStateInterface $form_state) {
$login_destination = $this->entity;
if ($login_destination
->save()) {
$this
->messenger()
->addMessage($this
->t('Saved the %label login destination.', [
'%label' => $login_destination
->getLabel(),
]));
}
else {
$this
->messenger()
->addMessage($this
->t('The %label login destination was not saved.', [
'%label' => $login_destination
->getLabel(),
]));
}
$form_state
->setRedirect('login_destination.list');
}
public function validateUriElement($element, FormStateInterface $form_state, $form) {
$uri = $this
->getUserEnteredStringAsUri($element['#value']);
$form_state
->setValueForElement($element, $uri);
if (parse_url($uri, PHP_URL_SCHEME) === 'internal' && !in_array($element['#value'][0], [
'/',
'?',
'#',
'[',
], TRUE) && substr($element['#value'], 0, 7) !== '<front>' && substr($element['#value'], 0, 9) !== '<current>') {
$form_state
->setError($element, $this
->t('Manually entered paths should start with /, [, ? or #.'));
return;
}
}
protected function getUriAsDisplayableString($uri) {
$scheme = parse_url($uri, PHP_URL_SCHEME);
$displayable_string = $uri;
if ($scheme === 'internal') {
$uri_reference = explode(':', $uri, 2)[1];
$path = parse_url($uri, PHP_URL_PATH);
if ($path === '/') {
$uri_reference = '<front>' . substr($uri_reference, 1);
}
$displayable_string = $uri_reference;
}
elseif ($scheme === 'entity') {
list($entity_type, $entity_id) = explode('/', substr($uri, 7), 2);
$entity_manager = \Drupal::entityTypeManager();
if ($entity_manager
->getDefinition($entity_type, FALSE) && ($entity = \Drupal::entityTypeManager()
->getStorage($entity_type)
->load($entity_id))) {
$displayable_string = EntityAutocomplete::getEntityLabels(array(
$entity,
));
}
}
return $displayable_string;
}
protected function getUserEnteredStringAsUri($string) {
$uri = $string;
$entity_id = EntityAutocomplete::extractEntityIdFromAutocompleteInput($string);
if ($entity_id !== NULL) {
$uri = 'entity:node/' . $entity_id;
}
elseif (!empty($string) && parse_url($string, PHP_URL_SCHEME) === NULL) {
if (strpos($string, '<front>') === 0) {
$string = '/' . substr($string, strlen('<front>'));
}
if (strpos($string, '[') === 0) {
$string = '/' . $string;
}
$uri = 'internal:' . $string;
}
return $uri;
}
}