updated contrib modules
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity\Access;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Routing\Access\AccessInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\TempStore\PrivateTempStoreFactory;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
/**
|
||||
* Checks if the current user has delete access to the items of the tempstore.
|
||||
*/
|
||||
class EntityDeleteMultipleAccessCheck implements AccessInterface {
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The tempstore service.
|
||||
*
|
||||
* @var \Drupal\Core\TempStore\PrivateTempStoreFactory
|
||||
*/
|
||||
protected $tempStore;
|
||||
|
||||
/**
|
||||
* Request stack service.
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\RequestStack
|
||||
*/
|
||||
protected $requestStack;
|
||||
|
||||
/**
|
||||
* Constructs a new EntityDeleteMultipleAccessCheck.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
|
||||
* The tempstore service.
|
||||
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
|
||||
* The request stack service.
|
||||
*/
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, PrivateTempStoreFactory $temp_store_factory, RequestStack $request_stack) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->tempStore = $temp_store_factory->get('entity_delete_multiple_confirm');
|
||||
$this->requestStack = $request_stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the user has delete access for at least one item of the store.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* Run access checks for this account.
|
||||
* @param string $entity_type_id
|
||||
* Entity type ID.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResult
|
||||
* Allowed or forbidden, neutral if tempstore is empty.
|
||||
*/
|
||||
public function access(AccountInterface $account, $entity_type_id) {
|
||||
if (!$this->requestStack->getCurrentRequest()->getSession()) {
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
$selection = $this->tempStore->get($account->id() . ':' . $entity_type_id);
|
||||
if (empty($selection) || !is_array($selection)) {
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
$entities = $this->entityTypeManager->getStorage($entity_type_id)->loadMultiple(array_keys($selection));
|
||||
foreach ($entities as $entity) {
|
||||
// As long as the user has access to delete one entity allow access to the
|
||||
// delete form. Access will be checked again in
|
||||
// Drupal\Core\Entity\Form\DeleteMultipleForm::submit() in case it has
|
||||
// changed in the meantime.
|
||||
if ($entity->access('delete', $account)) {
|
||||
return AccessResult::allowed();
|
||||
}
|
||||
}
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,7 +23,7 @@ trait RevisionControllerTrait {
|
||||
*
|
||||
* @return \Drupal\Core\Language\LanguageManagerInterface
|
||||
*/
|
||||
public abstract function languageManager();
|
||||
abstract public function languageManager();
|
||||
|
||||
/**
|
||||
* Determines if the user has permission to revert revisions.
|
||||
@@ -55,7 +55,6 @@ trait RevisionControllerTrait {
|
||||
*
|
||||
* @return array
|
||||
* A link render array.
|
||||
*
|
||||
*/
|
||||
abstract protected function buildRevertRevisionLink(EntityInterface $entity_revision);
|
||||
|
||||
@@ -117,24 +116,17 @@ trait RevisionControllerTrait {
|
||||
$langcode = $this->languageManager()
|
||||
->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
|
||||
->getId();
|
||||
$entity_storage = $this->entityTypeManager()
|
||||
->getStorage($entity->getEntityTypeId());
|
||||
/** @var \Drupal\Core\Entity\ContentEntityStorageInterface $entity_storage */
|
||||
$entity_storage = $this->entityTypeManager()->getStorage($entity->getEntityTypeId());
|
||||
$revision_ids = $this->revisionIds($entity);
|
||||
$entity_revisions = $entity_storage->loadMultipleRevisions($revision_ids);
|
||||
|
||||
$header = [$this->t('Revision'), $this->t('Operations')];
|
||||
$rows = [];
|
||||
|
||||
$revision_ids = $this->revisionIds($entity);
|
||||
// @todo Expand the entity storage to load multiple revisions.
|
||||
$entity_revisions = array_combine($revision_ids, array_map(function($vid) use ($entity_storage) {
|
||||
return $entity_storage->loadRevision($vid);
|
||||
}, $revision_ids));
|
||||
|
||||
foreach ($entity_revisions as $revision) {
|
||||
$row = [];
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $revision */
|
||||
if ($revision->hasTranslation($langcode) && $revision->getTranslation($langcode)
|
||||
->isRevisionTranslationAffected()
|
||||
) {
|
||||
if ($revision->hasTranslation($langcode) && $revision->getTranslation($langcode)->isRevisionTranslationAffected()) {
|
||||
$row[] = $this->getRevisionDescription($revision, $revision->isDefaultRevision());
|
||||
|
||||
if ($revision->isDefaultRevision()) {
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity\Entity;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
|
||||
interface RevisionableEntityBundleInterface extends ConfigEntityInterface {
|
||||
|
||||
/**
|
||||
* Returns whether a new revision should be created by default.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if a new revision should be created by default.
|
||||
*/
|
||||
public function shouldCreateNewRevision();
|
||||
|
||||
}
|
||||
@@ -2,13 +2,7 @@
|
||||
|
||||
namespace Drupal\entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityHandlerInterface;
|
||||
use Drupal\Core\Entity\EntityPublishedInterface;
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\user\EntityOwnerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides generic entity permissions which are still cacheable.
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityViewBuilder as CoreEntityViewBuilder;
|
||||
|
||||
/**
|
||||
* Provides a entity view builder with contextual links support
|
||||
*/
|
||||
class EntityViewBuilder extends CoreEntityViewBuilder {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function alterBuild(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
|
||||
$entity_type_id = $entity->getEntityTypeId();
|
||||
if (($entity instanceof ContentEntityInterface && $entity->isDefaultRevision()) || !$entity->getEntityType()->isRevisionable()) {
|
||||
$build['#contextual_links'][$entity_type_id] = [
|
||||
'route_parameters' => [
|
||||
$entity_type_id => $entity->id()
|
||||
],
|
||||
];
|
||||
}
|
||||
else {
|
||||
$build['#contextual_links'][$entity_type_id . '_revision'] = [
|
||||
'route_parameters' => [
|
||||
$entity_type_id => $entity->id(),
|
||||
$entity_type_id . '_revision' => $entity->getRevisionId(),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,226 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity\Form;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\user\PrivateTempStoreFactory;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides an entities deletion confirmation form.
|
||||
*/
|
||||
class DeleteMultiple extends ConfirmFormBase {
|
||||
|
||||
/**
|
||||
* The current user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The tempstore.
|
||||
*
|
||||
* @var \Drupal\user\SharedTempStore
|
||||
*/
|
||||
protected $tempStore;
|
||||
|
||||
/**
|
||||
* The entity type id.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $entityTypeId;
|
||||
|
||||
/**
|
||||
* The selection, in the entity_id => langcodes format.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $selection = [];
|
||||
|
||||
/**
|
||||
* Constructs a new DeleteMultiple object.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $current_user
|
||||
* The current user.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
* @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
|
||||
* The tempstore factory.
|
||||
*/
|
||||
public function __construct(AccountInterface $current_user, EntityTypeManagerInterface $entity_type_manager, PrivateTempStoreFactory $temp_store_factory) {
|
||||
$this->currentUser = $current_user;
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->tempStore = $temp_store_factory->get('entity_delete_multiple_confirm');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('current_user'),
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('user.private_tempstore')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'entity_delete_multiple_confirm';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getQuestion() {
|
||||
return $this->formatPlural(count($this->selection), 'Are you sure you want to delete this item?', 'Are you sure you want to delete these items?');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCancelUrl() {
|
||||
return new Url('entity.' . $this->entityTypeId . '.collection');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfirmText() {
|
||||
return $this->t('Delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param string $entity_type_id
|
||||
* The entity type id.
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, $entity_type_id = NULL) {
|
||||
$this->entityTypeId = $entity_type_id;
|
||||
$this->selection = $this->tempStore->get($this->currentUser->id());
|
||||
if (empty($this->entityTypeId) || empty($this->selection)) {
|
||||
return new RedirectResponse($this->getCancelUrl()->setAbsolute()->toString());
|
||||
}
|
||||
|
||||
$storage = $this->entityTypeManager->getStorage($this->entityTypeId);
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface[] $entities */
|
||||
$entities = $storage->loadMultiple(array_keys($this->selection));
|
||||
$items = [];
|
||||
foreach ($this->selection as $id => $langcodes) {
|
||||
foreach ($langcodes as $langcode) {
|
||||
$entity = $entities[$id]->getTranslation($langcode);
|
||||
$key = $id . ':' . $langcode;
|
||||
$default_key = $id . ':' . $entity->getUntranslated()->language()->getId();
|
||||
|
||||
// If we have a translated entity we build a nested list of translations
|
||||
// that will be deleted.
|
||||
$languages = $entity->getTranslationLanguages();
|
||||
if (count($languages) > 1 && $entity->isDefaultTranslation()) {
|
||||
$names = [];
|
||||
foreach ($languages as $translation_langcode => $language) {
|
||||
$names[] = $language->getName();
|
||||
unset($items[$id . ':' . $translation_langcode]);
|
||||
}
|
||||
$items[$default_key] = [
|
||||
'label' => [
|
||||
'#markup' => $this->t('@label (Original translation) - <em>The following translations will be deleted:</em>', ['@label' => $entity->label()]),
|
||||
],
|
||||
'deleted_translations' => [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $names,
|
||||
],
|
||||
];
|
||||
}
|
||||
elseif (!isset($items[$default_key])) {
|
||||
$items[$key] = $entity->label();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$form['entities'] = [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $items,
|
||||
];
|
||||
$form = parent::buildForm($form, $form_state);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$total_count = 0;
|
||||
$delete_entities = [];
|
||||
$delete_translations = [];
|
||||
$storage = $this->entityTypeManager->getStorage($this->entityTypeId);
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface[] $entities */
|
||||
$entities = $storage->loadMultiple(array_keys($this->selection));
|
||||
|
||||
foreach ($this->selection as $id => $langcodes) {
|
||||
foreach ($langcodes as $langcode) {
|
||||
$entity = $entities[$id]->getTranslation($langcode);
|
||||
if ($entity->isDefaultTranslation()) {
|
||||
$delete_entities[$id] = $entity;
|
||||
unset($delete_translations[$id]);
|
||||
$total_count += count($entity->getTranslationLanguages());
|
||||
}
|
||||
elseif (!isset($delete_entities[$id])) {
|
||||
$delete_translations[$id][] = $entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($delete_entities) {
|
||||
$storage->delete($delete_entities);
|
||||
$this->logger('content')->notice('Deleted @count @entity_type items.', [
|
||||
'@count' => count($delete_entities),
|
||||
'@entity_type' => $this->entityTypeId,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($delete_translations) {
|
||||
$count = 0;
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface[][] $delete_translations */
|
||||
foreach ($delete_translations as $id => $translations) {
|
||||
$entity = $entities[$id]->getUntranslated();
|
||||
foreach ($translations as $translation) {
|
||||
$entity->removeTranslation($translation->language()->getId());
|
||||
}
|
||||
$entity->save();
|
||||
$count += count($translations);
|
||||
}
|
||||
if ($count) {
|
||||
$total_count += $count;
|
||||
$this->logger('content')->notice('Deleted @count @entity_type translations.', [
|
||||
'@count' => $count,
|
||||
'@entity_type' => $this->entityTypeId,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($total_count) {
|
||||
drupal_set_message($this->formatPlural($total_count, 'Deleted 1 item.', 'Deleted @count items.'));
|
||||
}
|
||||
$this->tempStore->delete($this->currentUser->id());
|
||||
$form_state->setRedirectUrl($this->getCancelUrl());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity\Form;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Form\BaseFormIdInterface;
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
use Drupal\Core\Messenger\MessengerInterface;
|
||||
use Drupal\Core\TypedData\TranslatableInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\TempStore\PrivateTempStoreFactory;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides an entities deletion confirmation form.
|
||||
*/
|
||||
class DeleteMultipleForm extends ConfirmFormBase implements BaseFormIdInterface {
|
||||
|
||||
/**
|
||||
* The current user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The tempstore.
|
||||
*
|
||||
* @var \Drupal\Core\TempStore\SharedTempStore
|
||||
*/
|
||||
protected $tempStore;
|
||||
|
||||
/**
|
||||
* The messenger service.
|
||||
*
|
||||
* @var \Drupal\Core\Messenger\MessengerInterface
|
||||
*/
|
||||
protected $messenger;
|
||||
|
||||
/**
|
||||
* The entity type ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $entityTypeId;
|
||||
|
||||
/**
|
||||
* The selection, in the entity_id => langcodes format.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $selection = [];
|
||||
|
||||
/**
|
||||
* The entity type definition.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeInterface
|
||||
*/
|
||||
protected $entityType;
|
||||
|
||||
/**
|
||||
* Constructs a new DeleteMultiple object.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $current_user
|
||||
* The current user.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
|
||||
* The tempstore factory.
|
||||
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
|
||||
* The messenger service.
|
||||
*/
|
||||
public function __construct(AccountInterface $current_user, EntityTypeManagerInterface $entity_type_manager, PrivateTempStoreFactory $temp_store_factory, MessengerInterface $messenger) {
|
||||
$this->currentUser = $current_user;
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->tempStore = $temp_store_factory->get('entity_delete_multiple_confirm');
|
||||
$this->messenger = $messenger;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('current_user'),
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('tempstore.private'),
|
||||
$container->get('messenger')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getBaseFormId() {
|
||||
return 'entity_delete_multiple_confirm_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
// Get entity type ID from the route because ::buildForm has not yet been
|
||||
// called.
|
||||
$entity_type_id = $this->getRouteMatch()->getParameter('entity_type_id');
|
||||
return $entity_type_id . '_delete_multiple_confirm_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getQuestion() {
|
||||
return $this->formatPlural(count($this->selection), 'Are you sure you want to delete this @item?', 'Are you sure you want to delete these @items?', [
|
||||
'@item' => $this->entityType->getSingularLabel(),
|
||||
'@items' => $this->entityType->getPluralLabel(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCancelUrl() {
|
||||
if ($this->entityType->hasLinkTemplate('collection')) {
|
||||
return new Url('entity.' . $this->entityTypeId . '.collection');
|
||||
}
|
||||
else {
|
||||
return new Url('<front>');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfirmText() {
|
||||
return $this->t('Delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, $entity_type_id = NULL) {
|
||||
$this->entityTypeId = $entity_type_id;
|
||||
$this->entityType = $this->entityTypeManager->getDefinition($this->entityTypeId);
|
||||
$this->selection = $this->tempStore->get($this->currentUser->id() . ':' . $entity_type_id);
|
||||
if (empty($this->entityTypeId) || empty($this->selection)) {
|
||||
return new RedirectResponse($this->getCancelUrl()
|
||||
->setAbsolute()
|
||||
->toString());
|
||||
}
|
||||
|
||||
$items = [];
|
||||
$entities = $this->entityTypeManager->getStorage($entity_type_id)->loadMultiple(array_keys($this->selection));
|
||||
foreach ($this->selection as $id => $selected_langcodes) {
|
||||
$entity = $entities[$id];
|
||||
foreach ($selected_langcodes as $langcode) {
|
||||
$key = $id . ':' . $langcode;
|
||||
if ($entity instanceof TranslatableInterface) {
|
||||
$entity = $entity->getTranslation($langcode);
|
||||
$default_key = $id . ':' . $entity->getUntranslated()->language()->getId();
|
||||
|
||||
// Build a nested list of translations that will be deleted if the
|
||||
// entity has multiple translations.
|
||||
$entity_languages = $entity->getTranslationLanguages();
|
||||
if (count($entity_languages) > 1 && $entity->isDefaultTranslation()) {
|
||||
$names = [];
|
||||
foreach ($entity_languages as $translation_langcode => $language) {
|
||||
$names[] = $language->getName();
|
||||
unset($items[$id . ':' . $translation_langcode]);
|
||||
}
|
||||
$items[$default_key] = [
|
||||
'label' => [
|
||||
'#markup' => $this->t('@label (Original translation) - <em>The following @entity_type translations will be deleted:</em>',
|
||||
[
|
||||
'@label' => $entity->label(),
|
||||
'@entity_type' => $this->entityType->getSingularLabel(),
|
||||
]),
|
||||
],
|
||||
'deleted_translations' => [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $names,
|
||||
],
|
||||
];
|
||||
}
|
||||
elseif (!isset($items[$default_key])) {
|
||||
$items[$key] = $entity->label();
|
||||
}
|
||||
}
|
||||
elseif (!isset($items[$key])) {
|
||||
$items[$key] = $entity->label();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$form['entities'] = [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $items,
|
||||
];
|
||||
$form = parent::buildForm($form, $form_state);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$total_count = 0;
|
||||
$delete_entities = [];
|
||||
$delete_translations = [];
|
||||
$inaccessible_entities = [];
|
||||
$storage = $this->entityTypeManager->getStorage($this->entityTypeId);
|
||||
|
||||
$entities = $storage->loadMultiple(array_keys($this->selection));
|
||||
foreach ($this->selection as $id => $selected_langcodes) {
|
||||
$entity = $entities[$id];
|
||||
if (!$entity->access('delete', $this->currentUser)) {
|
||||
$inaccessible_entities[] = $entity;
|
||||
continue;
|
||||
}
|
||||
foreach ($selected_langcodes as $langcode) {
|
||||
if ($entity instanceof TranslatableInterface) {
|
||||
$entity = $entity->getTranslation($langcode);
|
||||
// If the entity is the default translation then deleting it will
|
||||
// delete all the translations.
|
||||
if ($entity->isDefaultTranslation()) {
|
||||
$delete_entities[$id] = $entity;
|
||||
// If there are translations already marked for deletion then remove
|
||||
// them as they will be deleted anyway.
|
||||
unset($delete_translations[$id]);
|
||||
// Update the total count. Since a single delete will delete all
|
||||
// translations, we need to add the number of translations to the
|
||||
// count.
|
||||
$total_count += count($entity->getTranslationLanguages());
|
||||
}
|
||||
// Add the translation to the list of translations to be deleted
|
||||
// unless the default translation is being deleted.
|
||||
elseif (!isset($delete_entities[$id])) {
|
||||
$delete_translations[$id][] = $entity;
|
||||
}
|
||||
}
|
||||
elseif (!isset($delete_entities[$id])) {
|
||||
$delete_entities[$id] = $entity;
|
||||
$total_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($delete_entities) {
|
||||
$storage->delete($delete_entities);
|
||||
foreach ($delete_entities as $entity) {
|
||||
$this->logger($entity->getEntityType()->getProvider())->notice('The @entity-type %label has been deleted.', [
|
||||
'@entity-type' => $entity->getEntityType()->getLowercaseLabel(),
|
||||
'%label' => $entity->label(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($delete_translations) {
|
||||
/** @var \Drupal\Core\Entity\TranslatableInterface[][] $delete_translations */
|
||||
foreach ($delete_translations as $id => $translations) {
|
||||
$entity = $entities[$id]->getUntranslated();
|
||||
foreach ($translations as $translation) {
|
||||
$entity->removeTranslation($translation->language()->getId());
|
||||
}
|
||||
$entity->save();
|
||||
foreach ($translations as $translation) {
|
||||
$this->logger($entity->getEntityType()->getProvider())->notice('The @entity-type %label @language translation has been deleted.', [
|
||||
'@entity-type' => $entity->getEntityType()->getLowercaseLabel(),
|
||||
'%label' => $entity->label(),
|
||||
'@language' => $translation->language()->getName(),
|
||||
]);
|
||||
}
|
||||
$total_count += count($translations);
|
||||
}
|
||||
}
|
||||
|
||||
if ($total_count) {
|
||||
$this->messenger->addStatus($this->getDeletedMessage($total_count));
|
||||
}
|
||||
if ($inaccessible_entities) {
|
||||
$this->messenger->addWarning($this->getInaccessibleMessage(count($inaccessible_entities)));
|
||||
}
|
||||
$this->tempStore->delete($this->currentUser->id());
|
||||
$form_state->setRedirectUrl($this->getCancelUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message to show the user after an item was deleted.
|
||||
*
|
||||
* @param int $count
|
||||
* Count of deleted translations.
|
||||
*
|
||||
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
* The item deleted message.
|
||||
*/
|
||||
protected function getDeletedMessage($count) {
|
||||
return $this->formatPlural($count, 'Deleted @count item.', 'Deleted @count items.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message to show the user when an item has not been deleted.
|
||||
*
|
||||
* @param int $count
|
||||
* Count of deleted translations.
|
||||
*
|
||||
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
* The item inaccessible message.
|
||||
*/
|
||||
protected function getInaccessibleMessage($count) {
|
||||
return $this->formatPlural($count, "@count item has not been deleted because you do not have the necessary permissions.", "@count items have not been deleted because you do not have the necessary permissions.");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity\Form;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityForm;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\entity\Entity\RevisionableEntityBundleInterface;
|
||||
|
||||
/**
|
||||
* Extends the base entity form with revision support in the UI.
|
||||
*/
|
||||
class RevisionableContentEntityForm extends ContentEntityForm {
|
||||
|
||||
/**
|
||||
* The entity being used by this form.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityInterface|\Drupal\Core\Entity\RevisionableInterface|\Drupal\entity\Revision\EntityRevisionLogInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function prepareEntity() {
|
||||
parent::prepareEntity();
|
||||
|
||||
$bundle_entity = $this->getBundleEntity();
|
||||
|
||||
// Set up default values, if required.
|
||||
if (!$this->entity->isNew()) {
|
||||
$this->entity->setRevisionLogMessage(NULL);
|
||||
}
|
||||
|
||||
if ($bundle_entity instanceof RevisionableEntityBundleInterface) {
|
||||
// Always use the default revision setting.
|
||||
$this->entity->setNewRevision($bundle_entity && $bundle_entity->shouldCreateNewRevision());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bundle entity of the entity, or NULL if there is none.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface|null
|
||||
*/
|
||||
protected function getBundleEntity() {
|
||||
if ($bundle_key = $this->entity->getEntityType()->getKey('bundle')) {
|
||||
return $this->entity->{$bundle_key}->referencedEntities()[0];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function form(array $form, FormStateInterface $form_state) {
|
||||
$entity_type = $this->entity->getEntityType();
|
||||
$bundle_entity = $this->getBundleEntity();
|
||||
$account = $this->currentUser();
|
||||
|
||||
if ($this->operation == 'edit') {
|
||||
$form['#title'] = $this->t('Edit %bundle_label @label', [
|
||||
'%bundle_label' => $bundle_entity ? $bundle_entity->label() : '',
|
||||
'@label' => $this->entity->label(),
|
||||
]);
|
||||
}
|
||||
|
||||
$form['advanced'] = [
|
||||
'#type' => 'vertical_tabs',
|
||||
'#weight' => 99,
|
||||
];
|
||||
|
||||
// Add a log field if the "Create new revision" option is checked, or if the
|
||||
// current user has the ability to check that option.
|
||||
// @todo Could we autogenerate this form by using some widget on the
|
||||
// revision info field.
|
||||
$form['revision_information'] = [
|
||||
'#type' => 'details',
|
||||
'#title' => $this->t('Revision information'),
|
||||
// Open by default when "Create new revision" is checked.
|
||||
'#open' => $this->entity->isNewRevision(),
|
||||
'#group' => 'advanced',
|
||||
'#weight' => 20,
|
||||
'#access' => $this->entity->isNewRevision() || $account->hasPermission($entity_type->get('admin_permission')),
|
||||
];
|
||||
|
||||
$form['revision_information']['revision'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Create new revision'),
|
||||
'#default_value' => $this->entity->isNewRevision(),
|
||||
'#access' => $account->hasPermission($entity_type->get('admin_permission')),
|
||||
];
|
||||
|
||||
// Check the revision log checkbox when the log textarea is filled in.
|
||||
// This must not happen if "Create new revision" is enabled by default,
|
||||
// since the state would auto-disable the checkbox otherwise.
|
||||
if (!$this->entity->isNewRevision()) {
|
||||
$form['revision_information']['revision']['#states'] = [
|
||||
'checked' => [
|
||||
'textarea[name="revision_log"]' => ['empty' => FALSE],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$form['revision_information']['revision_log'] = [
|
||||
'#type' => 'textarea',
|
||||
'#title' => $this->t('Revision log message'),
|
||||
'#rows' => 4,
|
||||
'#default_value' => $this->entity->getRevisionLogMessage(),
|
||||
'#description' => $this->t('Briefly describe the changes you have made.'),
|
||||
];
|
||||
|
||||
return parent::form($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function save(array $form, FormStateInterface $form_state) {
|
||||
// Save as a new revision if requested to do so.
|
||||
if (!$form_state->isValueEmpty('revision')) {
|
||||
$this->entity->setNewRevision();
|
||||
}
|
||||
|
||||
$insert = $this->entity->isNew();
|
||||
$this->entity->save();
|
||||
$context = ['@type' => $this->entity->bundle(), '%info' => $this->entity->label()];
|
||||
$logger = $this->logger('content');
|
||||
$bundle_entity = $this->getBundleEntity();
|
||||
$t_args = ['@type' => $bundle_entity ? $bundle_entity->label() : 'None', '%info' => $this->entity->label()];
|
||||
|
||||
if ($insert) {
|
||||
$logger->notice('@type: added %info.', $context);
|
||||
drupal_set_message($this->t('@type %info has been created.', $t_args));
|
||||
}
|
||||
else {
|
||||
$logger->notice('@type: updated %info.', $context);
|
||||
drupal_set_message($this->t('@type %info has been updated.', $t_args));
|
||||
}
|
||||
|
||||
if ($this->entity->id()) {
|
||||
$form_state->setValue('id', $this->entity->id());
|
||||
$form_state->set('id', $this->entity->id());
|
||||
|
||||
if ($this->entity->getEntityType()->hasLinkTemplate('collection')) {
|
||||
$form_state->setRedirectUrl($this->entity->toUrl('collection'));
|
||||
}
|
||||
else {
|
||||
$form_state->setRedirectUrl($this->entity->toUrl('canonical'));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// In the unlikely case something went wrong on save, the entity will be
|
||||
// rebuilt and entity form redisplayed.
|
||||
drupal_set_message($this->t('The entity could not be saved.'), 'error');
|
||||
$form_state->setRebuild();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity\Menu;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Menu\LocalActionDefault;
|
||||
use Drupal\Core\Routing\RouteProviderInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Provides a local action to add an entity.
|
||||
*/
|
||||
class EntityAddLocalAction extends LocalActionDefault {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* The entity type.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeInterface
|
||||
*/
|
||||
protected $entityType;
|
||||
|
||||
/**
|
||||
* Constructs a EntityAddLocalAction object.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
* @param string $plugin_id
|
||||
* The plugin_id for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
|
||||
* The route provider to load routes by name.
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type.
|
||||
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
|
||||
* The string translation service.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteProviderInterface $route_provider, EntityTypeInterface $entity_type, TranslationInterface $string_translation) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $route_provider);
|
||||
|
||||
$this->entityType = $entity_type;
|
||||
$this->setStringTranslation($string_translation);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
/* @var \Drupal\Core\Entity\EntityTypeManagerInterface */
|
||||
$entity_type_manager = $container->get('entity_type.manager');
|
||||
// The plugin ID is of the form
|
||||
// "entity.entity_actions:entity.$entity_type_id.collection".
|
||||
// @see entity.links.action.yml
|
||||
// @see \Drupal\entity\Menu\EntityCollectionLocalActionProvider::buildLocalActions()
|
||||
list(, $derivate_id) = explode(':', $plugin_id);
|
||||
list(, $entity_type_id, ) = explode('.', $derivate_id);
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('router.route_provider'),
|
||||
$entity_type_manager->getDefinition($entity_type_id),
|
||||
$container->get('string_translation')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTitle(Request $request = NULL) {
|
||||
return (string) $this->t('Add @entity', [
|
||||
'@entity' => (string) $this->entityType->getSingularLabel(),
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity\Menu;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
|
||||
/**
|
||||
* Provides a action link to the add page or add form on the collection.
|
||||
*/
|
||||
class EntityCollectionLocalActionProvider implements EntityLocalActionProviderInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildLocalActions(EntityTypeInterface $entity_type) {
|
||||
$actions = [];
|
||||
if ($entity_type->hasLinkTemplate('collection')) {
|
||||
$entity_type_id = $entity_type->id();
|
||||
|
||||
if ($entity_type->hasLinkTemplate('add-page')) {
|
||||
$route_name = "entity.$entity_type_id.add_page";
|
||||
}
|
||||
elseif ($entity_type->hasLinkTemplate('add-form')) {
|
||||
$route_name = "entity.$entity_type_id.add_form";
|
||||
}
|
||||
|
||||
if (isset($route_name)) {
|
||||
$actions[$route_name] = [
|
||||
// The title is translated at runtime by EntityAddLocalAction.
|
||||
/* @see \Drupal\entity\Menu\EntityAddLocalAction::getTitle() */
|
||||
'title' => 'Add ' . $entity_type->getSingularLabel(),
|
||||
'route_name' => $route_name,
|
||||
'appears_on' => ["entity.$entity_type_id.collection"],
|
||||
'class' => EntityAddLocalAction::class,
|
||||
];
|
||||
}
|
||||
}
|
||||
return $actions;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity\Menu;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface for entity local action providers.
|
||||
*/
|
||||
interface EntityLocalActionProviderInterface {
|
||||
|
||||
/**
|
||||
* Builds local actions for the given entity type.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type.
|
||||
*
|
||||
* @return array[]
|
||||
* An array of local action definitions.
|
||||
*/
|
||||
public function buildLocalActions(EntityTypeInterface $entity_type);
|
||||
|
||||
}
|
||||
@@ -5,7 +5,7 @@ namespace Drupal\entity\Plugin\Action;
|
||||
use Drupal\Core\Action\ActionBase;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\user\PrivateTempStoreFactory;
|
||||
use Drupal\Core\TempStore\PrivateTempStoreFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
@@ -22,7 +22,7 @@ class DeleteAction extends ActionBase implements ContainerFactoryPluginInterface
|
||||
/**
|
||||
* The tempstore object.
|
||||
*
|
||||
* @var \Drupal\user\SharedTempStore
|
||||
* @var \Drupal\Core\TempStore\SharedTempStore
|
||||
*/
|
||||
protected $tempStore;
|
||||
|
||||
@@ -42,7 +42,7 @@ class DeleteAction extends ActionBase implements ContainerFactoryPluginInterface
|
||||
* The plugin ID for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
|
||||
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
|
||||
* The tempstore factory.
|
||||
* @param AccountInterface $current_user
|
||||
* Current user.
|
||||
@@ -62,7 +62,7 @@ class DeleteAction extends ActionBase implements ContainerFactoryPluginInterface
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('user.private_tempstore'),
|
||||
$container->get('tempstore.private'),
|
||||
$container->get('current_user')
|
||||
);
|
||||
}
|
||||
@@ -71,13 +71,13 @@ class DeleteAction extends ActionBase implements ContainerFactoryPluginInterface
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function executeMultiple(array $entities) {
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface[] $entities */
|
||||
/** @var \Drupal\Core\Entity\EntityInterface[] $entities */
|
||||
$selection = [];
|
||||
foreach ($entities as $entity) {
|
||||
$langcode = $entity->language()->getId();
|
||||
$selection[$entity->id()][$langcode] = $langcode;
|
||||
}
|
||||
$this->tempStore->set($this->currentUser->id(), $selection);
|
||||
$this->tempStore->set($this->currentUser->id() . ':' . $this->getPluginDefinition()['type'], $selection);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ class DeleteActionDeriver extends DeriverBase implements ContainerDeriverInterfa
|
||||
$definitions = [];
|
||||
foreach ($this->getParticipatingEntityTypes() as $entity_type_id => $entity_type) {
|
||||
$definition = $base_plugin_definition;
|
||||
$definition['label'] = t('Delete @entity_type', ['@entity_type' => $entity_type->getLowercaseLabel()]);
|
||||
$definition['label'] = t('Delete @entity_type', ['@entity_type' => $entity_type->getSingularLabel()]);
|
||||
$definition['type'] = $entity_type_id;
|
||||
$definition['confirm_form_route_name'] = 'entity.' . $entity_type_id . '.delete_multiple_form';
|
||||
$definitions[$entity_type_id] = $definition;
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity\Plugin\Derivative;
|
||||
|
||||
use Drupal\Component\Plugin\Derivative\DeriverBase;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Derives local actions for entity types.
|
||||
*/
|
||||
class EntityActionsDeriver extends DeriverBase implements ContainerDeriverInterface {
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Constructs an entity local actions deriver.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
*/
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, $base_plugin_id) {
|
||||
return new static($container->get('entity_type.manager'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
if (!$this->derivatives) {
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
|
||||
$handlers = $entity_type->getHandlerClasses();
|
||||
if (isset($handlers['local_action_provider'])) {
|
||||
foreach ($handlers['local_action_provider'] as $class) {
|
||||
/** @var \Drupal\entity\Menu\EntityLocalActionProviderInterface $handler */
|
||||
$handler = $this->entityTypeManager->createHandlerInstance($class, $entity_type);
|
||||
$this->derivatives += $handler->buildLocalActions($entity_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->derivatives;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,12 +13,8 @@ abstract class RevisionableContentEntityBase extends BaseRevisionableContentEnti
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function urlRouteParameters($rel) {
|
||||
$uri_route_parameters = [];
|
||||
$uri_route_parameters = parent::urlRouteParameters($rel);
|
||||
|
||||
if ($rel != 'collection') {
|
||||
// The entity ID is needed as a route parameter.
|
||||
$uri_route_parameters[$this->getEntityTypeId()] = $this->id();
|
||||
}
|
||||
if (strpos($this->getEntityType()->getLinkTemplate($rel), $this->getEntityTypeId() . '_revision') !== FALSE) {
|
||||
$uri_route_parameters[$this->getEntityTypeId() . '_revision'] = $this->getRevisionId();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity\Routing;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\Routing\AdminHtmlRouteProvider as CoreAdminHtmlRouteProvider;
|
||||
|
||||
/**
|
||||
* Provides HTML routes for entities with administrative add/edit/delete pages.
|
||||
*/
|
||||
class AdminHtmlRouteProvider extends CoreAdminHtmlRouteProvider {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getCollectionRoute(EntityTypeInterface $entity_type) {
|
||||
$route = parent::getCollectionRoute($entity_type);
|
||||
if ($route && $entity_type->hasHandlerClass('permission_provider')) {
|
||||
$admin_permission = $entity_type->getAdminPermission();
|
||||
$overview_permission = "access {$entity_type->id()} overview";
|
||||
$route->setRequirement('_permission', "$admin_permission+$overview_permission");
|
||||
}
|
||||
return $route;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity\Routing;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider as CoreDefaultHtmlRouteProvider;
|
||||
|
||||
/**
|
||||
* Provides HTML routes for entities.
|
||||
*/
|
||||
class DefaultHtmlRouteProvider extends CoreDefaultHtmlRouteProvider {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getCollectionRoute(EntityTypeInterface $entity_type) {
|
||||
$route = parent::getCollectionRoute($entity_type);
|
||||
if ($route && $entity_type->hasHandlerClass('permission_provider')) {
|
||||
$admin_permission = $entity_type->getAdminPermission();
|
||||
$overview_permission = "access {$entity_type->id()} overview";
|
||||
$route->setRequirement('_permission', "$admin_permission+$overview_permission");
|
||||
}
|
||||
return $route;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,9 +36,9 @@ class DeleteMultipleRouteProvider implements EntityRouteProviderInterface {
|
||||
protected function deleteMultipleFormRoute(EntityTypeInterface $entity_type) {
|
||||
if ($entity_type->hasLinkTemplate('delete-multiple-form')) {
|
||||
$route = new Route($entity_type->getLinkTemplate('delete-multiple-form'));
|
||||
$route->setDefault('_form', '\Drupal\entity\Form\DeleteMultiple');
|
||||
$route->setDefault('_form', '\Drupal\entity\Form\DeleteMultipleForm');
|
||||
$route->setDefault('entity_type_id', $entity_type->id());
|
||||
$route->setRequirement('_permission', $entity_type->getAdminPermission());
|
||||
$route->setRequirement('_entity_delete_multiple_access', $entity_type->id());
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
@@ -2,13 +2,8 @@
|
||||
|
||||
namespace Drupal\entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityHandlerInterface;
|
||||
use Drupal\Core\Entity\EntityPublishedInterface;
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\user\EntityOwnerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides generic entity permissions which are cached per user.
|
||||
@@ -25,7 +20,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
* - create $bundle $entity_type
|
||||
*
|
||||
* As this class supports "view own ($bundle) $entity_type" it is just cacheable
|
||||
* per user, which might harm performance of sites. Given that please use
|
||||
* per user, which might harm performance of sites. Given that please use
|
||||
* \Drupal\entity\EntityPermissionProvider unless you need the feature, or your
|
||||
* entity type is not really user facing (commerce orders for example).
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user