View source
<?php
namespace Drupal\tca;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeBundleInfo;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\tca\Plugin\TcaPluginManager;
class FormManglerService {
use StringTranslationTrait;
private $entityTypeManager = NULL;
private $bundleInfo = NULL;
private $tcaPluginManager = NULL;
public function __construct(EntityTypeManagerInterface $etm, EntityTypeBundleInfo $etbi, TcaPluginManager $tca_plugin_manager, TcaSettingsManager $tca_settings_manager, TranslationInterface $translation) {
$this->entityTypeManager = $etm;
$this->allBundleInfo = $etbi
->getAllBundleInfo();
$this->tcaPluginManager = $tca_plugin_manager;
$this->tcaSettingsManager = $tca_settings_manager;
$this->stringTranslation = $translation;
}
public function addTcaSettingsToEntityForm(array &$attach, EntityInterface $entity, FormStateInterface $form_state, $form_id) {
$this
->addTcaSettingsToForm($attach, $entity
->getEntityType()
->id(), $entity, $form_state, $form_id);
}
private function addTcaSettingsToForm(array &$attach, $entity_type_id, $entity, FormStateInterface $form_state, $form_id) {
$entity_type = $this->entityTypeManager
->getStorage($entity_type_id)
->getEntityType();
$is_entity_viewable = $this->entityTypeManager
->getDefinition($entity_type_id)
->hasViewBuilderClass();
$is_entity_bundle = $this
->isEntityBundle($entity);
$entity_id = $entity
->id();
$tca_bundle_settings = NULL;
$tca_settings = NULL;
$active = NULL;
$token = NULL;
if ($is_entity_bundle) {
$tca_settings = $this->tcaSettingsManager
->loadSettingsAsConfig($entity_type_id, $entity_id);
$active = $tca_settings
->get('active');
$forced = $tca_settings
->get('force') ?? FALSE;
}
else {
$bundle_entity_type_id = $entity_type
->getBundleEntityType() ?: $entity_type_id;
$bundle_entity_id = $entity
->getEntityType()
->getBundleEntityType() ? $entity
->bundle() : NULL;
$tca_bundle_settings = $this->tcaSettingsManager
->loadSettingsAsConfig($bundle_entity_type_id, $bundle_entity_id);
if (!$tca_bundle_settings
->get('active')) {
return;
}
$tca_settings = $this->tcaSettingsManager
->loadSettingsAsConfig($entity_type_id, $entity_id);
$active = $tca_settings
->get('active');
$forced = $tca_bundle_settings
->get('force') ?? FALSE;
$token = $tca_settings
->get('token');
}
$entity_plugin = $this->tcaPluginManager
->createInstanceByEntityType($is_entity_bundle && !empty($entity_type
->getBundleOf()) ? $entity_type
->getBundleOf() : $entity_type_id);
$form = [];
$form['tca'] = [
'#type' => 'details',
'#title' => $this
->t('Token Content Access settings'),
'#open' => $active ? TRUE : FALSE,
'#group' => $is_entity_bundle ? 'additional_settings' : 'advanced',
'#attributes' => [
'class' => [
'tca-settings-form',
],
],
'#tree' => FALSE,
];
$form['tca']['tca_is_entity_bundle'] = [
'#type' => 'value',
'#value' => $is_entity_bundle,
];
$form['tca']['tca_entity_type_id'] = [
'#type' => 'value',
'#value' => $entity_type_id,
];
$form['tca']['tca_entity_id'] = [
'#type' => 'value',
'#value' => $entity_id,
];
$form['tca']['tca_active'] = [
'#type' => 'checkbox',
'#title' => t('Enable Token Content Access protection'),
'#default_value' => $forced ?: $active,
'#description' => t('If this is checked, users with the Administer Token Content Access settings permission will be able to enable Token Content Access protection for individual entities.'),
];
if (!$is_entity_bundle && $is_entity_viewable) {
$entity_url = !$entity
->isNew() ? $entity
->toUrl('canonical', [
'query' => [
'tca' => $token,
],
'absolute' => TRUE,
])
->toString() : t('N/A');
$form['tca']['tca_active']['#description'] = t('Prevent users from viewing this content without providing an access token via the URL.');
$form['tca']['tca_active']['#disabled'] = $forced;
$states = [
'visible' => [
':input[name="tca_active"]' => [
'checked' => TRUE,
],
],
];
$form['tca']['tca_public'] = [
'#type' => 'checkbox',
'#title' => t('All users with access token can view this content'),
'#default_value' => $tca_settings
->get('public'),
'#description' => t('Allow all users to view this content bypassing any permissions restrictions.'),
'#states' => $states,
];
$form['tca']['tca_token'] = [
'#type' => 'textfield',
'#title' => t('Access Token'),
'#default_value' => $token,
'#description' => t('Append this access token to the URL as the value for the "tca" query parameter.'),
'#attributes' => [
'readonly' => 'readonly',
],
'#states' => $states,
];
$module_handler = \Drupal::service('module_handler');
if ($module_handler
->moduleExists('clipboardjs')) {
$form['tca']['#attached']['library'][] = 'clipboardjs/clipboardjs';
$form['tca']['tca_clipboardjs'] = [
'#type' => 'textfield',
'#theme' => 'clipboardjs',
'#text' => $entity_url,
'#alert_text' => NULL,
'#disabled' => TRUE,
'#access' => !empty($token),
'#states' => $states,
];
}
$form['tca']['tca_url_copy'] = [
'#type' => 'item',
'#title' => t('URL to copy'),
'#markup' => '<span>' . $entity_url . '</span>',
'#access' => !empty($token),
'#states' => $states,
];
$form['tca']['actions'] = [
'#type' => 'actions',
];
$form['tca']['actions']['tca_regenerate'] = [
'#type' => 'submit',
'#value' => t('Generate a new Access Token'),
'#access' => !empty($token),
'#ajax' => [
'callback' => [
'Drupal\\tca\\FormManglerService',
'staticHandleFormAjax',
],
],
'#submit' => [
[
'Drupal\\tca\\FormManglerService',
'staticHandleFormSubmit',
],
],
'#states' => $states,
];
}
if ($is_entity_bundle) {
$states = [
'visible' => [
':input[name="tca_active"]' => [
'checked' => TRUE,
],
],
];
$form['tca']['tca_force'] = [
'#type' => 'checkbox',
'#title' => t('Enforce Token usage'),
'#default_value' => $forced,
'#description' => t('Enforce usage of Tokens on this bundle.'),
'#states' => $states,
];
}
$attach += $form;
$submit_handler_locations = $is_entity_bundle ? $entity_plugin
->getBundleFormSubmitHandlerAttachLocations() : $entity_plugin
->getFormSubmitHandlerAttachLocations();
foreach ($submit_handler_locations as $location) {
$array_ref =& $attach;
if (is_array($location)) {
foreach ($location as $subkey) {
$array_ref =& $array_ref[$subkey];
}
}
else {
$array_ref =& $array_ref[$location];
}
if (isset($array_ref)) {
$array_ref[] = [
'Drupal\\tca\\FormManglerService',
'staticHandleFormSubmit',
];
}
}
}
public static function staticHandleFormSubmit(array $form, $form_state) {
\Drupal::service('tca.form_mangler')
->handleFormSubmit($form, $form_state);
}
public function handleFormSubmit(array $form, $form_state) {
$is_entity_bundle = $form_state
->getValue('tca_is_entity_bundle');
$entity_type_id = $form_state
->getValue('tca_entity_type_id');
$entity_id = $form_state
->getValue('tca_entity_id');
$active = $form_state
->getValue('tca_active');
$forced = !$active ? FALSE : (bool) $form_state
->getValue('tca_force');
$settings = [
'active' => $active,
'token' => NULL,
'public' => $form_state
->getValue('tca_public'),
'force' => $forced,
];
if (!$entity_id) {
$entity_id = $form_state
->getformObject()
->getEntity()
->id();
if (!$entity_id) {
return;
}
}
$triggered_element = $form_state
->getTriggeringElement();
$regenerate = in_array('tca', $triggered_element['#array_parents']);
$token = NULL;
$is_new = FALSE;
if (!$is_entity_bundle && $active) {
$tca_settings = $this->tcaSettingsManager
->loadSettingsAsConfig($entity_type_id, $entity_id);
$token = $tca_settings
->get('token');
$is_new = !$token;
if ($regenerate || $is_new) {
$token = $this->tcaSettingsManager
->generateToken($entity_type_id, $entity_id);
$form_state
->setValue('tca_token', $token);
}
$settings['token'] = $token;
}
if (!$regenerate) {
$this->tcaSettingsManager
->saveSettings($settings, $entity_type_id, $entity_id);
}
if ($is_new && $token) {
$entity = $this->entityTypeManager
->getStorage($entity_type_id)
->load($entity_id);
$entity_url = $entity
->toUrl('canonical', [
'query' => [
'tca' => $token,
],
'absolute' => TRUE,
])
->toString();
\Drupal::messenger()
->addMessage(t('URL to bypass Token Access Control for this entity: @url', [
'@url' => $entity_url,
]));
}
}
public static function staticHandleFormAjax(array $form, $form_state) {
$token = $form_state
->getValue('tca_token');
$entity_type_id = $form_state
->getValue('tca_entity_type_id');
$entity_id = $form_state
->getValue('tca_entity_id');
if ($entity_id) {
$entity = \Drupal::entityTypeManager()
->getStorage($entity_type_id)
->load($entity_id);
$entity_url = $entity
->toUrl('canonical', [
'query' => [
'tca' => $token,
],
'absolute' => TRUE,
])
->toString();
}
else {
$entity_url = t('N/A');
}
$response = new AjaxResponse();
$response
->addCommand(new InvokeCommand('[name="tca_token"]', 'val', [
$token,
]));
$response
->addCommand(new InvokeCommand('.form-item-tca-url-copy span', 'text', [
$entity_url,
]));
$response
->addCommand(new InvokeCommand('.js-form-item-tca-clipboardjs .clipboardjs', 'val', [
$entity_url,
]));
return $response;
}
protected function isEntityBundle($entity) {
return is_subclass_of($entity, 'Drupal\\Core\\Config\\Entity\\ConfigEntityBundleBase');
}
}