eca-1.0.x-dev/modules/content/src/Plugin/Action/NewEntity.php
modules/content/src/Plugin/Action/NewEntity.php
<?php
namespace Drupal\eca_content\Plugin\Action;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Action\Attribute\Action;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\eca\Attribute\EcaAction;
use Drupal\eca\Plugin\Action\ConfigurableActionBase;
use Drupal\eca\Plugin\ECA\PluginFormTrait;
use Drupal\eca\Service\ContentEntityTypes;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Create a new content entity without saving it.
*/
#[Action(
id: 'eca_new_entity',
label: new TranslatableMarkup('Entity: create new'),
)]
#[EcaAction(
description: new TranslatableMarkup('Create a new content entity without saving it.'),
version_introduced: '1.0.0',
)]
class NewEntity extends ConfigurableActionBase {
use PluginFormTrait;
/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected LanguageManagerInterface $languageManager;
/**
* The entity type service.
*
* @var \Drupal\eca\Service\ContentEntityTypes
*/
protected ContentEntityTypes $entityTypes;
/**
* The instantiated entity.
*
* @var \Drupal\Core\Entity\EntityInterface|null
*/
protected ?EntityInterface $entity;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
$plugin = parent::create($container, $configuration, $plugin_id, $plugin_definition);
$plugin->entityTypes = $container->get('eca.service.content_entity_types');
$plugin->languageManager = $container->get('language_manager');
return $plugin;
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration(): array {
return [
'token_name' => '',
'type' => '',
'langcode' => '',
'label' => '',
'published' => FALSE,
'owner' => '',
] + parent::defaultConfiguration();
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
$form['token_name'] = [
'#type' => 'textfield',
'#title' => $this->t('Name of token'),
'#default_value' => $this->configuration['token_name'],
'#description' => $this->t('Provide the name of a token that holds the new entity.'),
'#weight' => -60,
'#eca_token_reference' => TRUE,
];
$options = $this->entityTypes->getTypesAndBundles(FALSE, FALSE);
unset($options['user user']);
$form['type'] = [
'#type' => 'select',
'#title' => $this->t('Type'),
'#options' => $options,
'#default_value' => $this->configuration['type'],
'#description' => $this->t('The type of the new entity.<br/>Note: to create a new user entity, enable the eca_user module and use the "User: create new" action from there.'),
'#weight' => -50,
'#eca_token_select_option' => TRUE,
];
$langcodes = [];
foreach ($this->languageManager->getLanguages() as $langcode => $language) {
$langcodes[$langcode] = $language->getName();
}
$langcodes['_interface'] = $this->t('Interface language');
$form['langcode'] = [
'#type' => 'select',
'#title' => $this->t('Language'),
'#options' => $langcodes,
'#default_value' => $this->configuration['langcode'],
'#description' => $this->t('The language code of the new entity.'),
'#weight' => -40,
'#eca_token_select_option' => TRUE,
];
$form['label'] = [
'#type' => 'textfield',
'#title' => $this->t('Entity label'),
'#default_value' => $this->configuration['label'],
'#description' => $this->t('The label of the new entity.'),
'#weight' => -30,
];
$form['published'] = [
'#type' => 'checkbox',
'#title' => $this->t('Published'),
'#default_value' => $this->shouldPublish(),
'#description' => $this->t('Whether the entity should be published or not.'),
'#weight' => -20,
];
$form['owner'] = [
'#type' => 'textfield',
'#title' => $this->t('Owner UID'),
'#default_value' => $this->configuration['owner'],
'#description' => $this->t('The owner UID of the new entity.'),
'#weight' => -10,
];
return parent::buildConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void {
$this->configuration['token_name'] = $form_state->getValue('token_name');
$this->configuration['type'] = $form_state->getValue('type');
$this->configuration['langcode'] = $form_state->getValue('langcode');
$this->configuration['label'] = $form_state->getValue('label');
$this->configuration['published'] = !empty($form_state->getValue('published'));
$this->configuration['owner'] = $form_state->getValue('owner');
parent::submitConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function access($object, ?AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\Core\Access\AccessResultInterface $access_result */
$access_result = parent::access($object, $account, TRUE);
if ($this->configuration['type'] === '_eca_token') {
$type = $this->getTokenValue('type', '');
}
else {
$type = $this->configuration['type'];
}
if (empty($type)) {
$access_result = AccessResult::forbidden('No entity type provided.');
}
elseif ($access_result->isAllowed()) {
$account = $account ?? $this->currentUser;
[$entity_type_id, $bundle] = array_pad(explode(' ', $type, 2), 2, NULL);
if ($bundle === NULL || $bundle === '' || $bundle === ContentEntityTypes::ALL) {
$access_result = AccessResult::forbidden('Cannot determine access without a specified bundle.');
}
elseif (!$this->entityTypeManager->hasDefinition($entity_type_id)) {
$access_result = AccessResult::forbidden(sprintf('Cannot determine access when "%s" is not a valid entity type ID.', $entity_type_id));
}
elseif (!$this->entityTypeManager->hasHandler($entity_type_id, 'access')) {
$admin_permission = $this->entityTypeManager->getStorage($entity_type_id)->getEntityType()->getAdminPermission();
$access_result = $admin_permission ?
AccessResult::allowedIfHasPermission($account, $admin_permission) :
AccessResult::forbidden('Cannot determine access without an access handler.');
}
else {
/**
* @var \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_handler
*/
$access_handler = $this->entityTypeManager->getHandler($entity_type_id, 'access');
$access_result = $access_handler->createAccess($bundle, $account, [], TRUE);
}
}
return $return_as_object ? $access_result : $access_result->isAllowed();
}
/**
* {@inheritdoc}
*/
public function execute(): void {
$config = &$this->configuration;
if ($config['type'] === '_eca_token') {
$type = $this->getTokenValue('type', '');
}
else {
$type = $config['type'];
}
[$entity_type_id, $bundle] = explode(' ', $type);
$values = [];
$definition = $this->entityTypeManager->getDefinition($entity_type_id);
$entity_keys = $definition->get('entity_keys');
if (isset($entity_keys['bundle'])) {
$values[$entity_keys['bundle']] = $bundle;
}
if (isset($entity_keys['langcode'])) {
$langcode = trim($config['langcode']);
if (in_array($langcode, ['_interface', ''], TRUE)) {
$langcode = $this->languageManager->getCurrentLanguage()->getId();
}
elseif ($langcode === '_eca_token') {
$langcode = $this->getTokenValue('langcode', $this->languageManager->getCurrentLanguage()->getId());
}
$values[$entity_keys['langcode']] = $langcode;
}
if (isset($entity_keys['label']) && isset($config['label'])) {
$values[$entity_keys['label']] = trim((string) $this->tokenService->replace($config['label'], [], ['clear' => TRUE]));
}
if (isset($entity_keys['published'])) {
$values[$entity_keys['published']] = (int) $this->shouldPublish();
}
if (isset($entity_keys['owner'])) {
if (!empty($config['owner'])) {
$owner_id = trim((string) $this->tokenService->replace($config['owner'], [], ['clear' => TRUE]));
}
if (!isset($owner_id) || $owner_id === '') {
$owner_id = $this->currentUser->id();
}
$values[$entity_keys['owner']] = $owner_id;
}
$entity = $this->entityTypeManager->getStorage($entity_type_id)->create($values);
$this->entity = $entity;
$this->tokenService->addTokenData($config['token_name'], $entity);
}
/**
* Whether the new entity should be set as published or not.
*
* @return bool
* Returns TRUE in case to set as published, FALSE otherwise.
*/
protected function shouldPublish(): bool {
return $this->configuration['published'];
}
}
