Initial Drupal 11 with DDEV setup
This commit is contained in:
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\shortcut\ShortcutSetInterface;
|
||||
use Drupal\shortcut\ShortcutInterface;
|
||||
|
||||
/**
|
||||
* Provides route responses for taxonomy.module.
|
||||
*/
|
||||
class ShortcutController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* Returns a form to add a new shortcut to a given set.
|
||||
*
|
||||
* @param \Drupal\shortcut\ShortcutSetInterface $shortcut_set
|
||||
* The shortcut set this shortcut will be added to.
|
||||
*
|
||||
* @return array
|
||||
* The shortcut add form.
|
||||
*/
|
||||
public function addForm(ShortcutSetInterface $shortcut_set) {
|
||||
$shortcut = $this->entityTypeManager()->getStorage('shortcut')->create(['shortcut_set' => $shortcut_set->id()]);
|
||||
return $this->entityFormBuilder()->getForm($shortcut, 'add');
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the selected shortcut.
|
||||
*
|
||||
* @param \Drupal\shortcut\ShortcutInterface $shortcut
|
||||
* The shortcut to delete.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
* A redirect to the previous location or the front page when destination
|
||||
* is not set.
|
||||
*/
|
||||
public function deleteShortcutLinkInline(ShortcutInterface $shortcut) {
|
||||
$label = $shortcut->label();
|
||||
|
||||
try {
|
||||
$shortcut->delete();
|
||||
$this->messenger()->addStatus($this->t('The shortcut %title has been deleted.', ['%title' => $label]));
|
||||
}
|
||||
catch (\Exception) {
|
||||
$this->messenger()->addStatus($this->t('Unable to delete the shortcut for %title.', ['%title' => $label]), 'error');
|
||||
}
|
||||
|
||||
return $this->redirect('<front>');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Path\PathValidatorInterface;
|
||||
use Drupal\shortcut\ShortcutSetInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
|
||||
/**
|
||||
* Builds the page for administering shortcut sets.
|
||||
*/
|
||||
class ShortcutSetController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* The path validator.
|
||||
*
|
||||
* @var \Drupal\Core\Path\PathValidatorInterface
|
||||
*/
|
||||
protected $pathValidator;
|
||||
|
||||
/**
|
||||
* Creates a new ShortcutSetController instance.
|
||||
*
|
||||
* @param \Drupal\Core\Path\PathValidatorInterface $path_validator
|
||||
* The path validator.
|
||||
*/
|
||||
public function __construct(PathValidatorInterface $path_validator) {
|
||||
$this->pathValidator = $path_validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new link in the provided shortcut set.
|
||||
*
|
||||
* @param \Drupal\shortcut\ShortcutSetInterface $shortcut_set
|
||||
* The shortcut set to add a link to.
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The request object.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
* A redirect response to the front page, or the previous location.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
*/
|
||||
public function addShortcutLinkInline(ShortcutSetInterface $shortcut_set, Request $request) {
|
||||
$link = $request->query->get('link');
|
||||
$name = $request->query->get('name');
|
||||
if (parse_url($link, PHP_URL_SCHEME) === NULL && $this->pathValidator->isValid($link)) {
|
||||
$shortcut = $this->entityTypeManager()->getStorage('shortcut')->create([
|
||||
'title' => $name,
|
||||
'shortcut_set' => $shortcut_set->id(),
|
||||
'link' => [
|
||||
'uri' => 'internal:/' . $link,
|
||||
],
|
||||
]);
|
||||
|
||||
try {
|
||||
$shortcut->save();
|
||||
$this->messenger()->addStatus($this->t('Added a shortcut for %title.', ['%title' => $shortcut->label()]));
|
||||
}
|
||||
catch (\Exception) {
|
||||
$this->messenger()->addError($this->t('Unable to add a shortcut for %title.', ['%title' => $shortcut->label()]));
|
||||
}
|
||||
|
||||
return $this->redirect('<front>');
|
||||
}
|
||||
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
}
|
||||
197
web/core/modules/shortcut/src/Entity/Shortcut.php
Normal file
197
web/core/modules/shortcut/src/Entity/Shortcut.php
Normal file
@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Entity;
|
||||
|
||||
use Drupal\Core\Entity\Attribute\ContentEntityType;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Entity\ContentEntityBase;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\link\LinkItemInterface;
|
||||
use Drupal\shortcut\Form\ShortcutDeleteForm;
|
||||
use Drupal\shortcut\ShortcutAccessControlHandler;
|
||||
use Drupal\shortcut\ShortcutForm;
|
||||
use Drupal\shortcut\ShortcutInterface;
|
||||
|
||||
/**
|
||||
* Defines the shortcut entity class.
|
||||
*
|
||||
* @property \Drupal\link\LinkItemInterface $link
|
||||
*/
|
||||
#[ContentEntityType(
|
||||
id: 'shortcut',
|
||||
label: new TranslatableMarkup('Shortcut link'),
|
||||
label_collection: new TranslatableMarkup('Shortcut links'),
|
||||
label_singular: new TranslatableMarkup('shortcut link'),
|
||||
label_plural: new TranslatableMarkup('shortcut links'),
|
||||
entity_keys: [
|
||||
'id' => 'id',
|
||||
'uuid' => 'uuid',
|
||||
'bundle' => 'shortcut_set',
|
||||
'label' => 'title',
|
||||
'langcode' => 'langcode',
|
||||
],
|
||||
handlers: [
|
||||
'access' => ShortcutAccessControlHandler::class,
|
||||
'form' => [
|
||||
'default' => ShortcutForm::class,
|
||||
'add' => ShortcutForm::class,
|
||||
'edit' => ShortcutForm::class,
|
||||
'delete' => ShortcutDeleteForm::class,
|
||||
],
|
||||
],
|
||||
links: [
|
||||
'canonical' => '/admin/config/user-interface/shortcut/link/{shortcut}',
|
||||
'delete-form' => '/admin/config/user-interface/shortcut/link/{shortcut}/delete',
|
||||
'edit-form' => '/admin/config/user-interface/shortcut/link/{shortcut}',
|
||||
],
|
||||
bundle_entity_type: 'shortcut_set',
|
||||
bundle_label: new TranslatableMarkup('Shortcut set'),
|
||||
base_table: 'shortcut',
|
||||
data_table: 'shortcut_field_data',
|
||||
translatable: TRUE,
|
||||
label_count: [
|
||||
'singular' => '@count shortcut link',
|
||||
'plural' => '@count shortcut links',
|
||||
],
|
||||
list_cache_tags: [
|
||||
'config:shortcut_set_list',
|
||||
],
|
||||
)]
|
||||
class Shortcut extends ContentEntityBase implements ShortcutInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTitle() {
|
||||
return $this->get('title')->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setTitle($link_title) {
|
||||
$this->set('title', $link_title);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getWeight() {
|
||||
return $this->get('weight')->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setWeight($weight) {
|
||||
$this->set('weight', $weight);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getUrl() {
|
||||
return $this->link->first()->getUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
|
||||
parent::postSave($storage, $update);
|
||||
|
||||
// EntityBase::postSave() calls EntityBase::invalidateTagsOnSave(), which
|
||||
// only handles the regular cases. The Shortcut entity has one special case:
|
||||
// a newly created shortcut is *also* added to a shortcut set, so we must
|
||||
// invalidate the associated shortcut set's cache tag.
|
||||
if (!$update) {
|
||||
Cache::invalidateTags($this->getCacheTagsToInvalidate());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
/** @var \Drupal\Core\Field\BaseFieldDefinition[] $fields */
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
|
||||
$fields['id']->setDescription(t('The ID of the shortcut.'));
|
||||
|
||||
$fields['uuid']->setDescription(t('The UUID of the shortcut.'));
|
||||
|
||||
$fields['shortcut_set']->setLabel(t('Shortcut set'))
|
||||
->setDescription(t('The bundle of the shortcut.'));
|
||||
|
||||
$fields['langcode']->setDescription(t('The language code of the shortcut.'));
|
||||
|
||||
$fields['title'] = BaseFieldDefinition::create('string')
|
||||
->setLabel(t('Name'))
|
||||
->setDescription(t('The name of the shortcut.'))
|
||||
->setRequired(TRUE)
|
||||
->setTranslatable(TRUE)
|
||||
->setSetting('max_length', 255)
|
||||
->setDisplayOptions('form', [
|
||||
'type' => 'string_textfield',
|
||||
'weight' => -10,
|
||||
'settings' => [
|
||||
'size' => 40,
|
||||
],
|
||||
]);
|
||||
|
||||
$fields['weight'] = BaseFieldDefinition::create('integer')
|
||||
->setLabel(t('Weight'))
|
||||
->setDescription(t('Weight among shortcuts in the same shortcut set.'));
|
||||
|
||||
$fields['link'] = BaseFieldDefinition::create('link')
|
||||
->setLabel(t('Path'))
|
||||
->setDescription(t('The location this shortcut points to.'))
|
||||
->setRequired(TRUE)
|
||||
->setSettings([
|
||||
'link_type' => LinkItemInterface::LINK_INTERNAL,
|
||||
'title' => DRUPAL_DISABLED,
|
||||
])
|
||||
->setDisplayOptions('form', [
|
||||
'type' => 'link_default',
|
||||
'weight' => 0,
|
||||
])
|
||||
->setDisplayConfigurable('form', TRUE);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheTagsToInvalidate() {
|
||||
return $this->shortcut_set->entity->getCacheTags();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort shortcut objects.
|
||||
*
|
||||
* Callback for uasort().
|
||||
*
|
||||
* @param \Drupal\shortcut\ShortcutInterface $a
|
||||
* First item for comparison.
|
||||
* @param \Drupal\shortcut\ShortcutInterface $b
|
||||
* Second item for comparison.
|
||||
*
|
||||
* @return int
|
||||
* The comparison result for uasort().
|
||||
*/
|
||||
public static function sort(ShortcutInterface $a, ShortcutInterface $b) {
|
||||
$a_weight = $a->getWeight();
|
||||
$b_weight = $b->getWeight();
|
||||
if ($a_weight == $b_weight) {
|
||||
return strnatcasecmp($a->getTitle(), $b->getTitle());
|
||||
}
|
||||
return $a_weight <=> $b_weight;
|
||||
}
|
||||
|
||||
}
|
||||
138
web/core/modules/shortcut/src/Entity/ShortcutSet.php
Normal file
138
web/core/modules/shortcut/src/Entity/ShortcutSet.php
Normal file
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Entity;
|
||||
|
||||
use Drupal\Core\Entity\Attribute\ConfigEntityType;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityBundleBase;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\shortcut\Form\SetCustomize;
|
||||
use Drupal\shortcut\Form\ShortcutSetDeleteForm;
|
||||
use Drupal\shortcut\ShortcutSetAccessControlHandler;
|
||||
use Drupal\shortcut\ShortcutSetForm;
|
||||
use Drupal\shortcut\ShortcutSetInterface;
|
||||
use Drupal\shortcut\ShortcutSetListBuilder;
|
||||
use Drupal\shortcut\ShortcutSetStorage;
|
||||
|
||||
/**
|
||||
* Defines the Shortcut set configuration entity.
|
||||
*/
|
||||
#[ConfigEntityType(
|
||||
id: 'shortcut_set',
|
||||
label: new TranslatableMarkup('Shortcut set'),
|
||||
label_collection: new TranslatableMarkup('Shortcut sets'),
|
||||
label_singular: new TranslatableMarkup('shortcut set'),
|
||||
label_plural: new TranslatableMarkup('shortcut sets'),
|
||||
config_prefix: 'set',
|
||||
entity_keys: [
|
||||
'id' => 'id',
|
||||
'label' => 'label',
|
||||
], handlers: [
|
||||
'storage' => ShortcutSetStorage::class,
|
||||
'access' => ShortcutSetAccessControlHandler::class,
|
||||
'list_builder' => ShortcutSetListBuilder::class,
|
||||
'form' => [
|
||||
'default' => ShortcutSetForm::class,
|
||||
'add' => ShortcutSetForm::class,
|
||||
'edit' => ShortcutSetForm::class,
|
||||
'customize' => SetCustomize::class,
|
||||
'delete' => ShortcutSetDeleteForm::class,
|
||||
],
|
||||
],
|
||||
links: [
|
||||
'customize-form' => '/admin/config/user-interface/shortcut/manage/{shortcut_set}/customize',
|
||||
'delete-form' => '/admin/config/user-interface/shortcut/manage/{shortcut_set}/delete',
|
||||
'edit-form' => '/admin/config/user-interface/shortcut/manage/{shortcut_set}',
|
||||
'collection' => '/admin/config/user-interface/shortcut',
|
||||
],
|
||||
bundle_of: 'shortcut',
|
||||
label_count: [
|
||||
'singular' => '@count shortcut set',
|
||||
'plural' => '@count shortcut sets',
|
||||
],
|
||||
config_export: [
|
||||
'id',
|
||||
'label',
|
||||
],
|
||||
)]
|
||||
class ShortcutSet extends ConfigEntityBundleBase implements ShortcutSetInterface {
|
||||
|
||||
/**
|
||||
* The machine name for the configuration entity.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* The human-readable name of the configuration entity.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $label;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
|
||||
parent::postSave($storage, $update);
|
||||
|
||||
if (!$update && !$this->isSyncing()) {
|
||||
// Save a new shortcut set with links copied from the user's default set.
|
||||
$default_set = $storage->getDefaultSet(\Drupal::currentUser());
|
||||
// This is the default set, do not copy shortcuts.
|
||||
if ($default_set->id() != $this->id()) {
|
||||
foreach ($default_set->getShortcuts() as $shortcut) {
|
||||
$shortcut = $shortcut->createDuplicate();
|
||||
$shortcut->enforceIsNew();
|
||||
$shortcut->shortcut_set->target_id = $this->id();
|
||||
$shortcut->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function preDelete(EntityStorageInterface $storage, array $entities) {
|
||||
parent::preDelete($storage, $entities);
|
||||
|
||||
foreach ($entities as $entity) {
|
||||
$storage->deleteAssignedShortcutSets($entity);
|
||||
|
||||
// Next, delete the shortcuts for this set.
|
||||
$shortcut_ids = \Drupal::entityQuery('shortcut')
|
||||
->accessCheck(FALSE)
|
||||
->condition('shortcut_set', $entity->id(), '=')
|
||||
->execute();
|
||||
|
||||
$controller = \Drupal::entityTypeManager()->getStorage('shortcut');
|
||||
$entities = $controller->loadMultiple($shortcut_ids);
|
||||
$controller->delete($entities);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resetLinkWeights() {
|
||||
$weight = -50;
|
||||
foreach ($this->getShortcuts() as $shortcut) {
|
||||
$shortcut->setWeight(++$weight);
|
||||
$shortcut->save();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getShortcuts() {
|
||||
$shortcuts = \Drupal::entityTypeManager()->getStorage('shortcut')->loadByProperties(['shortcut_set' => $this->id()]);
|
||||
uasort($shortcuts, ['\Drupal\shortcut\Entity\Shortcut', 'sort']);
|
||||
return $shortcuts;
|
||||
}
|
||||
|
||||
}
|
||||
114
web/core/modules/shortcut/src/Form/SetCustomize.php
Normal file
114
web/core/modules/shortcut/src/Form/SetCustomize.php
Normal file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Form;
|
||||
|
||||
use Drupal\Core\Entity\EntityForm;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Render\Element;
|
||||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
* Builds the shortcut set customize form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class SetCustomize extends EntityForm {
|
||||
|
||||
/**
|
||||
* The entity being used by this form.
|
||||
*
|
||||
* @var \Drupal\shortcut\ShortcutSetInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function form(array $form, FormStateInterface $form_state) {
|
||||
$form = parent::form($form, $form_state);
|
||||
$form['shortcuts'] = [
|
||||
'#tree' => TRUE,
|
||||
'#weight' => -20,
|
||||
];
|
||||
|
||||
$form['shortcuts']['links'] = [
|
||||
'#type' => 'table',
|
||||
'#header' => [$this->t('Name'), $this->t('Weight'), $this->t('Operations')],
|
||||
'#empty' => $this->t('No shortcuts available. <a href=":link">Add a shortcut</a>', [':link' => Url::fromRoute('shortcut.link_add', ['shortcut_set' => $this->entity->id()])->toString()]),
|
||||
'#attributes' => ['id' => 'shortcuts'],
|
||||
'#tabledrag' => [
|
||||
[
|
||||
'action' => 'order',
|
||||
'relationship' => 'sibling',
|
||||
'group' => 'shortcut-weight',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($this->entity->getShortcuts() as $shortcut) {
|
||||
$id = $shortcut->id();
|
||||
$url = $shortcut->getUrl();
|
||||
if (!$url->access()) {
|
||||
continue;
|
||||
}
|
||||
$form['shortcuts']['links'][$id]['#attributes']['class'][] = 'draggable';
|
||||
$form['shortcuts']['links'][$id]['name'] = [
|
||||
'#type' => 'link',
|
||||
'#title' => $shortcut->getTitle(),
|
||||
'#url' => $url,
|
||||
'#options' => $url->getOptions(),
|
||||
];
|
||||
$form['shortcuts']['links'][$id]['#weight'] = $shortcut->getWeight();
|
||||
$form['shortcuts']['links'][$id]['weight'] = [
|
||||
'#type' => 'weight',
|
||||
'#title' => $this->t('Weight for @title', ['@title' => $shortcut->getTitle()]),
|
||||
'#title_display' => 'invisible',
|
||||
'#default_value' => $shortcut->getWeight(),
|
||||
'#attributes' => ['class' => ['shortcut-weight']],
|
||||
];
|
||||
|
||||
$links['edit'] = [
|
||||
'title' => $this->t('Edit'),
|
||||
'url' => $shortcut->toUrl(),
|
||||
];
|
||||
$links['delete'] = [
|
||||
'title' => $this->t('Delete'),
|
||||
'url' => $shortcut->toUrl('delete-form'),
|
||||
];
|
||||
$form['shortcuts']['links'][$id]['operations'] = [
|
||||
'#type' => 'operations',
|
||||
'#links' => $links,
|
||||
'#access' => $url->access(),
|
||||
];
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function actions(array $form, FormStateInterface $form_state) {
|
||||
// Only includes a Save action for the entity, no direct Delete button.
|
||||
return [
|
||||
'submit' => [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Save'),
|
||||
'#access' => (bool) Element::getVisibleChildren($form['shortcuts']['links']),
|
||||
'#submit' => ['::submitForm', '::save'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function save(array $form, FormStateInterface $form_state) {
|
||||
foreach ($this->entity->getShortcuts() as $shortcut) {
|
||||
$weight = $form_state->getValue(['shortcuts', 'links', $shortcut->id(), 'weight']);
|
||||
$shortcut->setWeight($weight);
|
||||
$shortcut->save();
|
||||
}
|
||||
$this->messenger()->addStatus($this->t('The shortcut set has been updated.'));
|
||||
}
|
||||
|
||||
}
|
||||
38
web/core/modules/shortcut/src/Form/ShortcutDeleteForm.php
Normal file
38
web/core/modules/shortcut/src/Form/ShortcutDeleteForm.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Form;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityDeleteForm;
|
||||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
* Builds the shortcut link deletion form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ShortcutDeleteForm extends ContentEntityDeleteForm {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'shortcut_confirm_delete';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCancelUrl() {
|
||||
return new Url('entity.shortcut_set.customize_form', [
|
||||
'shortcut_set' => $this->entity->bundle(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getRedirectUrl() {
|
||||
return $this->getCancelUrl();
|
||||
}
|
||||
|
||||
}
|
||||
78
web/core/modules/shortcut/src/Form/ShortcutSetDeleteForm.php
Normal file
78
web/core/modules/shortcut/src/Form/ShortcutSetDeleteForm.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Form;
|
||||
|
||||
use Drupal\Core\Entity\EntityDeleteForm;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\shortcut\ShortcutSetStorageInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Drupal\Core\Database\Connection;
|
||||
|
||||
/**
|
||||
* Builds the shortcut set deletion form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ShortcutSetDeleteForm extends EntityDeleteForm {
|
||||
|
||||
/**
|
||||
* The database connection.
|
||||
*
|
||||
* @var \Drupal\Core\Database\Connection
|
||||
*/
|
||||
protected $database;
|
||||
|
||||
/**
|
||||
* The shortcut storage.
|
||||
*
|
||||
* @var \Drupal\shortcut\ShortcutSetStorageInterface
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
/**
|
||||
* Constructs a ShortcutSetDeleteForm object.
|
||||
*/
|
||||
public function __construct(Connection $database, ShortcutSetStorageInterface $storage) {
|
||||
$this->database = $database;
|
||||
$this->storage = $storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('database'),
|
||||
$container->get('entity_type.manager')->getStorage('shortcut_set')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
// Find out how many users are directly assigned to this shortcut set, and
|
||||
// make a message.
|
||||
$number = $this->storage->countAssignedUsers($this->entity);
|
||||
$info = '';
|
||||
if ($number) {
|
||||
$info .= '<p>' . $this->formatPlural($number,
|
||||
'1 user has chosen or been assigned to this shortcut set.',
|
||||
'@count users have chosen or been assigned to this shortcut set.') . '</p>';
|
||||
}
|
||||
|
||||
// Also, if a module implements hook_shortcut_default_set(), it's possible
|
||||
// that this set is being used as a default set. Add a message about that
|
||||
// too.
|
||||
if ($this->moduleHandler->hasImplementations('shortcut_default_set')) {
|
||||
$info .= '<p>' . $this->t('If you have chosen this shortcut set as the default for some or all users, they may also be affected by deleting it.') . '</p>';
|
||||
}
|
||||
|
||||
$form['info'] = [
|
||||
'#markup' => $info,
|
||||
];
|
||||
|
||||
return parent::buildForm($form, $form_state);
|
||||
}
|
||||
|
||||
}
|
||||
230
web/core/modules/shortcut/src/Form/SwitchShortcutSet.php
Normal file
230
web/core/modules/shortcut/src/Form/SwitchShortcutSet.php
Normal file
@ -0,0 +1,230 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\shortcut\Entity\ShortcutSet;
|
||||
use Drupal\shortcut\ShortcutSetStorageInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Builds the shortcut set switch form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class SwitchShortcutSet extends FormBase {
|
||||
|
||||
/**
|
||||
* The account the shortcut set is for.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* The shortcut set storage.
|
||||
*
|
||||
* @var \Drupal\shortcut\ShortcutSetStorageInterface
|
||||
*/
|
||||
protected $shortcutSetStorage;
|
||||
|
||||
/**
|
||||
* Constructs a SwitchShortcutSet object.
|
||||
*
|
||||
* @param \Drupal\shortcut\ShortcutSetStorageInterface $shortcut_set_storage
|
||||
* The shortcut set storage.
|
||||
*/
|
||||
public function __construct(ShortcutSetStorageInterface $shortcut_set_storage) {
|
||||
$this->shortcutSetStorage = $shortcut_set_storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity_type.manager')->getStorage('shortcut_set')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'shortcut_set_switch';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, ?UserInterface $user = NULL) {
|
||||
$account = $this->currentUser();
|
||||
|
||||
$this->user = $user;
|
||||
|
||||
// Prepare the list of shortcut sets.
|
||||
$options = array_map(function (ShortcutSet $set) {
|
||||
return $set->label();
|
||||
}, $this->shortcutSetStorage->loadMultiple());
|
||||
|
||||
$current_set = $this->shortcutSetStorage->getDisplayedToUser($this->user);
|
||||
|
||||
// Only administrators can add shortcut sets.
|
||||
$add_access = $account->hasPermission('administer shortcuts');
|
||||
if ($add_access) {
|
||||
$options['new'] = $this->t('New set');
|
||||
}
|
||||
|
||||
$account_is_user = $this->user->id() == $account->id();
|
||||
if (count($options) > 1) {
|
||||
$form['set'] = [
|
||||
'#type' => 'radios',
|
||||
'#title' => $account_is_user ? $this->t('Choose a set of shortcuts to use') : $this->t('Choose a set of shortcuts for this user'),
|
||||
'#options' => $options,
|
||||
'#default_value' => $current_set->id(),
|
||||
];
|
||||
|
||||
$form['label'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Label'),
|
||||
'#description' => $this->t('The new set is created by copying links from your default shortcut set.'),
|
||||
'#access' => $add_access,
|
||||
'#states' => [
|
||||
'visible' => [
|
||||
':input[name="set"]' => ['value' => 'new'],
|
||||
],
|
||||
'required' => [
|
||||
':input[name="set"]' => ['value' => 'new'],
|
||||
],
|
||||
],
|
||||
];
|
||||
$form['id'] = [
|
||||
'#type' => 'machine_name',
|
||||
'#machine_name' => [
|
||||
'exists' => [$this, 'exists'],
|
||||
'replace_pattern' => '[^a-z0-9-]+',
|
||||
'replace' => '-',
|
||||
],
|
||||
// This ID could be used for menu name.
|
||||
'#maxlength' => 23,
|
||||
'#states' => [
|
||||
'required' => [
|
||||
':input[name="set"]' => ['value' => 'new'],
|
||||
],
|
||||
],
|
||||
'#required' => FALSE,
|
||||
];
|
||||
|
||||
if (!$account_is_user) {
|
||||
$default_set = $this->shortcutSetStorage->getDefaultSet($this->user);
|
||||
$form['new']['#description'] = $this->t('The new set is created by copying links from the %default set.', ['%default' => $default_set->label()]);
|
||||
}
|
||||
|
||||
$form['actions'] = ['#type' => 'actions'];
|
||||
$form['actions']['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Change set'),
|
||||
];
|
||||
}
|
||||
else {
|
||||
// There is only 1 option, so output a message in the $form array.
|
||||
$form['info'] = [
|
||||
'#markup' => '<p>' . $this->t('You are currently using the %set-name shortcut set.', ['%set-name' => $current_set->label()]) . '</p>',
|
||||
];
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a shortcut set exists already.
|
||||
*
|
||||
* @param string $id
|
||||
* The set ID to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the shortcut set exists, FALSE otherwise.
|
||||
*/
|
||||
public function exists($id) {
|
||||
return (bool) $this->shortcutSetStorage->getQuery()
|
||||
->condition('id', $id)
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
if ($form_state->getValue('set') == 'new') {
|
||||
// Check to prevent creating a shortcut set with an empty title.
|
||||
if (trim($form_state->getValue('label')) == '') {
|
||||
$form_state->setErrorByName('label', $this->t('The new set label is required.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$account = $this->currentUser();
|
||||
|
||||
$account_is_user = $this->user->id() == $account->id();
|
||||
if ($form_state->getValue('set') == 'new') {
|
||||
// Save a new shortcut set with links copied from the user's default set.
|
||||
/** @var \Drupal\shortcut\Entity\ShortcutSet $set */
|
||||
$set = $this->shortcutSetStorage->create([
|
||||
'id' => $form_state->getValue('id'),
|
||||
'label' => $form_state->getValue('label'),
|
||||
]);
|
||||
$set->save();
|
||||
$replacements = [
|
||||
'%user' => $this->user->label(),
|
||||
'%set_name' => $set->label(),
|
||||
':switch-url' => Url::fromRoute('<current>')->toString(),
|
||||
];
|
||||
if ($account_is_user) {
|
||||
// Only administrators can create new shortcut sets, so we know they
|
||||
// have access to switch back.
|
||||
$this->messenger()->addStatus($this->t('You are now using the new %set_name shortcut set. You can edit it from this page or <a href=":switch-url">switch back to a different one.</a>', $replacements));
|
||||
}
|
||||
else {
|
||||
$this->messenger()->addStatus($this->t('%user is now using a new shortcut set called %set_name. You can edit it from this page.', $replacements));
|
||||
}
|
||||
$form_state->setRedirect(
|
||||
'entity.shortcut_set.customize_form',
|
||||
['shortcut_set' => $set->id()]
|
||||
);
|
||||
}
|
||||
else {
|
||||
// Switch to a different shortcut set.
|
||||
/** @var \Drupal\shortcut\Entity\ShortcutSet $set */
|
||||
$set = $this->shortcutSetStorage->load($form_state->getValue('set'));
|
||||
$replacements = [
|
||||
'%user' => $this->user->getDisplayName(),
|
||||
'%set_name' => $set->label(),
|
||||
];
|
||||
$this->messenger()->addStatus($account_is_user ? $this->t('You are now using the %set_name shortcut set.', $replacements) : $this->t('%user is now using the %set_name shortcut set.', $replacements));
|
||||
}
|
||||
|
||||
// Assign the shortcut set to the provided user account.
|
||||
$this->shortcutSetStorage->assignUser($set, $this->user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks access for the shortcut set switch form.
|
||||
*
|
||||
* @param \Drupal\user\UserInterface $user
|
||||
* (optional) The owner of the shortcut set.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The access result.
|
||||
*/
|
||||
public function checkAccess(?UserInterface $user = NULL) {
|
||||
return shortcut_set_switch_access($user);
|
||||
}
|
||||
|
||||
}
|
||||
140
web/core/modules/shortcut/src/Hook/ShortcutHooks.php
Normal file
140
web/core/modules/shortcut/src/Hook/ShortcutHooks.php
Normal file
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Hook;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Hook\Attribute\Hook;
|
||||
|
||||
/**
|
||||
* Hook implementations for shortcut.
|
||||
*/
|
||||
class ShortcutHooks {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
#[Hook('help')]
|
||||
public function help($route_name, RouteMatchInterface $route_match): ?string {
|
||||
switch ($route_name) {
|
||||
case 'help.page.shortcut':
|
||||
$output = '<h2>' . $this->t('About') . '</h2>';
|
||||
$output .= '<p>' . $this->t('The Shortcut module allows users to create sets of <em>shortcut</em> links to commonly-visited pages of the site. Shortcuts are contained within <em>sets</em>. Each user with <em>Select any shortcut set</em> permission can select a shortcut set created by anyone at the site. For more information, see the <a href=":shortcut">online documentation for the Shortcut module</a>.', [':shortcut' => 'https://www.drupal.org/docs/8/core/modules/shortcut']) . '</p>';
|
||||
$output .= '<h2>' . $this->t('Uses') . '</h2>';
|
||||
$output .= '<dl><dt>' . $this->t('Administering shortcuts') . '</dt>';
|
||||
$output .= '<dd>' . $this->t('Users with the <em>Administer shortcuts</em> permission can manage shortcut sets and edit the shortcuts within sets from the <a href=":shortcuts">Shortcuts administration page</a>.', [
|
||||
':shortcuts' => Url::fromRoute('entity.shortcut_set.collection')->toString(),
|
||||
]) . '</dd>';
|
||||
$output .= '<dt>' . $this->t('Choosing shortcut sets') . '</dt>';
|
||||
$output .= '<dd>' . $this->t('Users with permission to switch shortcut sets can choose a shortcut set to use from the Shortcuts tab of their user account page.') . '</dd>';
|
||||
$output .= '<dt>' . $this->t('Adding and removing shortcuts') . '</dt>';
|
||||
$output .= '<dd>' . $this->t('The Shortcut module creates an add/remove link for each page on your site; the link lets you add or remove the current page from the currently-enabled set of shortcuts (if your theme displays it and you have permission to edit your shortcut set). The core Claro administration theme displays this link next to the page title, as a gray or yellow star. If you click on the gray star, you will add that page to your preferred set of shortcuts. If the page is already part of your shortcut set, the link will be a yellow star, and will allow you to remove the current page from your shortcut set.') . '</dd>';
|
||||
$output .= '<dt>' . $this->t('Displaying shortcuts') . '</dt>';
|
||||
$output .= '<dd>' . $this->t('You can display your shortcuts by enabling the <em>Shortcuts</em> block on the <a href=":blocks">Blocks administration page</a>. Certain administrative modules also display your shortcuts; for example, the core <a href=":toolbar-help">Toolbar module</a> provides a corresponding menu link.', [
|
||||
':blocks' => \Drupal::moduleHandler()->moduleExists('block') ? Url::fromRoute('block.admin_display')->toString() : '#',
|
||||
':toolbar-help' => \Drupal::moduleHandler()->moduleExists('toolbar') ? Url::fromRoute('help.page', [
|
||||
'name' => 'toolbar',
|
||||
])->toString() : '#',
|
||||
]) . '</dd>';
|
||||
$output .= '</dl>';
|
||||
return $output;
|
||||
|
||||
case 'entity.shortcut_set.collection':
|
||||
case 'shortcut.set_add':
|
||||
case 'entity.shortcut_set.edit_form':
|
||||
$user = \Drupal::currentUser();
|
||||
if ($user->hasPermission('access shortcuts') && $user->hasPermission('switch shortcut sets')) {
|
||||
$output = '<p>' . $this->t('Define which shortcut set you are using on the <a href=":shortcut-link">Shortcuts tab</a> of your account page.', [
|
||||
':shortcut-link' => Url::fromRoute('shortcut.set_switch', [
|
||||
'user' => $user->id(),
|
||||
])->toString(),
|
||||
]) . '</p>';
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_toolbar().
|
||||
*/
|
||||
#[Hook('toolbar')]
|
||||
public function toolbar(): array {
|
||||
$user = \Drupal::currentUser();
|
||||
$items = [];
|
||||
$items['shortcuts'] = ['#cache' => ['contexts' => ['user.permissions']]];
|
||||
if ($user->hasPermission('access shortcuts')) {
|
||||
$shortcut_set = \Drupal::entityTypeManager()->getStorage('shortcut_set')->getDisplayedToUser($user);
|
||||
$items['shortcuts'] += [
|
||||
'#type' => 'toolbar_item',
|
||||
'tab' => [
|
||||
'#type' => 'link',
|
||||
'#title' => $this->t('Shortcuts'),
|
||||
'#url' => $shortcut_set->toUrl('collection'),
|
||||
'#attributes' => [
|
||||
'title' => $this->t('Shortcuts'),
|
||||
'class' => [
|
||||
'toolbar-icon',
|
||||
'toolbar-icon-shortcut',
|
||||
],
|
||||
],
|
||||
],
|
||||
'tray' => [
|
||||
'#heading' => $this->t('User-defined shortcuts'),
|
||||
'children' => [
|
||||
'#lazy_builder' => [
|
||||
'shortcut.lazy_builders:lazyLinks',
|
||||
[],
|
||||
],
|
||||
'#create_placeholder' => TRUE,
|
||||
'#cache' => [
|
||||
'keys' => [
|
||||
'shortcut_set_toolbar_links',
|
||||
],
|
||||
'contexts' => [
|
||||
'user',
|
||||
],
|
||||
],
|
||||
'#lazy_builder_preview' => [
|
||||
'#markup' => '<a href="#" class="toolbar-tray-lazy-placeholder-link"> </a>',
|
||||
],
|
||||
],
|
||||
],
|
||||
'#weight' => -10,
|
||||
'#attached' => [
|
||||
'library' => [
|
||||
'shortcut/drupal.shortcut',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_themes_installed().
|
||||
*/
|
||||
#[Hook('themes_installed')]
|
||||
public function themesInstalled($theme_list): void {
|
||||
// Theme settings are not configuration entities and cannot depend on
|
||||
// modules so to set a module-specific setting, we need to set it with
|
||||
// logic.
|
||||
if (in_array('claro', $theme_list, TRUE)) {
|
||||
\Drupal::configFactory()->getEditable("claro.settings")->set('third_party_settings.shortcut.module_link', TRUE)->save(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_delete().
|
||||
*/
|
||||
#[Hook('user_delete')]
|
||||
public function userDelete(EntityInterface $entity): void {
|
||||
// Clean up shortcut set mapping of removed user account.
|
||||
\Drupal::entityTypeManager()->getStorage('shortcut_set')->unassignUser($entity);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Block\Attribute\Block;
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
|
||||
/**
|
||||
* Provides a 'Shortcut' block.
|
||||
*/
|
||||
#[Block(
|
||||
id: "shortcuts",
|
||||
admin_label: new TranslatableMarkup("Shortcuts"),
|
||||
category: new TranslatableMarkup("Menus")
|
||||
)]
|
||||
class ShortcutsBlock extends BlockBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
return [
|
||||
'#lazy_builder' => ['shortcut.lazy_builders:lazyLinks', [FALSE]],
|
||||
'#create_placeholder' => TRUE,
|
||||
'#cache' => [
|
||||
'keys' => ['shortcut_set_block_links'],
|
||||
'contexts' => ['user'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function blockAccess(AccountInterface $account) {
|
||||
return AccessResult::allowedIfHasPermission($account, 'access shortcuts');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Plugin\migrate\destination;
|
||||
|
||||
use Drupal\migrate\Attribute\MigrateDestination;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate\Plugin\migrate\destination\EntityConfigBase;
|
||||
|
||||
/**
|
||||
* Migration destination for shortcut set entity.
|
||||
*/
|
||||
#[MigrateDestination('entity:shortcut_set')]
|
||||
class EntityShortcutSet extends EntityConfigBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getEntity(Row $row, array $old_destination_id_values) {
|
||||
$entity = parent::getEntity($row, $old_destination_id_values);
|
||||
// Set the "syncing" flag to TRUE, to avoid duplication of default
|
||||
// shortcut links
|
||||
$entity->setSyncing(TRUE);
|
||||
return $entity;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Plugin\migrate\destination;
|
||||
|
||||
use Drupal\migrate\Attribute\MigrateDestination;
|
||||
use Drupal\shortcut\ShortcutSetStorageInterface;
|
||||
use Drupal\user\Entity\User;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate\Plugin\migrate\destination\DestinationBase;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
|
||||
/**
|
||||
* Migration destination for shortcut_set_users.
|
||||
*/
|
||||
#[MigrateDestination('shortcut_set_users')]
|
||||
class ShortcutSetUsers extends DestinationBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The shortcut set storage handler.
|
||||
*
|
||||
* @var \Drupal\shortcut\ShortcutSetStorageInterface
|
||||
*/
|
||||
protected $shortcutSetStorage;
|
||||
|
||||
/**
|
||||
* Constructs an entity destination plugin.
|
||||
*
|
||||
* @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\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration.
|
||||
* @param \Drupal\shortcut\ShortcutSetStorageInterface $shortcut_set_storage
|
||||
* The shortcut_set entity storage handler.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, ShortcutSetStorageInterface $shortcut_set_storage) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
|
||||
$this->shortcutSetStorage = $shortcut_set_storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, ?MigrationInterface $migration = NULL) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$migration,
|
||||
$container->get('entity_type.manager')->getStorage('shortcut_set')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
return [
|
||||
'set_name' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
'uid' => [
|
||||
'type' => 'integer',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'uid' => 'The users.uid for this set.',
|
||||
'source' => 'The shortcut_set.set_name that will be displayed for this user.',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function import(Row $row, array $old_destination_id_values = []) {
|
||||
/** @var \Drupal\shortcut\ShortcutSetInterface $set */
|
||||
$set = $this->shortcutSetStorage->load($row->getDestinationProperty('set_name'));
|
||||
/** @var \Drupal\user\UserInterface $account */
|
||||
$account = User::load($row->getDestinationProperty('uid'));
|
||||
$this->shortcutSetStorage->assignUser($set, $account);
|
||||
|
||||
return [$set->id(), $account->id()];
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
// cspell:ignore mlid
|
||||
|
||||
/**
|
||||
* Drupal 7 shortcut links source from database.
|
||||
*
|
||||
* For available configuration keys, refer to the parent classes.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SqlBase
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBase
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_shortcut",
|
||||
* source_module = "shortcut"
|
||||
* )
|
||||
*/
|
||||
class Shortcut extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->select('menu_links', 'ml')
|
||||
->fields('ml', ['mlid', 'menu_name', 'link_path', 'link_title', 'weight'])
|
||||
->condition('hidden', '0')
|
||||
->condition('menu_name', 'shortcut-set-%', 'LIKE')
|
||||
->orderBy('ml.mlid');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'mlid' => $this->t("The menu.mlid primary key for this menu link (= shortcut link)."),
|
||||
'menu_name' => $this->t("The menu name (= set name) for this shortcut link."),
|
||||
'link_path' => $this->t("The link for this shortcut."),
|
||||
'link_title' => $this->t("The title for this shortcut."),
|
||||
'weight' => $this->t("The weight for this shortcut"),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['mlid']['type'] = 'integer';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal 7 shortcut_set source from database.
|
||||
*
|
||||
* For available configuration keys, refer to the parent classes.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SqlBase
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBase
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_shortcut_set",
|
||||
* source_module = "shortcut"
|
||||
* )
|
||||
*/
|
||||
class ShortcutSet extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->select('shortcut_set', 'ss')->fields('ss');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'set_name' => $this->t("The name under which the set's links are stored."),
|
||||
'title' => $this->t("The title of the set."),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['set_name']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal 7 shortcut_set_users source from database.
|
||||
*
|
||||
* For available configuration keys, refer to the parent classes.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SqlBase
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBase
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_shortcut_set_users",
|
||||
* source_module = "shortcut"
|
||||
* )
|
||||
*/
|
||||
class ShortcutSetUsers extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->select('shortcut_set_users', 'ssu')->fields('ssu');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'uid' => $this->t('The users.uid for this set.'),
|
||||
'set_name' => $this->t('The shortcut_set.set_name that will be displayed for this user.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
return [
|
||||
'set_name' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
'uid' => [
|
||||
'type' => 'integer',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Entity\EntityHandlerInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Defines the access control handler for the shortcut entity type.
|
||||
*
|
||||
* @see \Drupal\shortcut\Entity\Shortcut
|
||||
*/
|
||||
class ShortcutAccessControlHandler extends EntityAccessControlHandler implements EntityHandlerInterface {
|
||||
|
||||
/**
|
||||
* The shortcut_set storage.
|
||||
*
|
||||
* @var \Drupal\shortcut\ShortcutSetStorageInterface
|
||||
*/
|
||||
protected $shortcutSetStorage;
|
||||
|
||||
/**
|
||||
* Constructs a ShortcutAccessControlHandler object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type definition.
|
||||
* @param \Drupal\shortcut\ShortcutSetStorageInterface $shortcut_set_storage
|
||||
* The shortcut_set storage.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, ShortcutSetStorageInterface $shortcut_set_storage) {
|
||||
parent::__construct($entity_type);
|
||||
$this->shortcutSetStorage = $shortcut_set_storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
|
||||
return new static(
|
||||
$entity_type,
|
||||
$container->get('entity_type.manager')->getStorage('shortcut_set')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
if ($shortcut_set = $this->shortcutSetStorage->load($entity->bundle())) {
|
||||
return shortcut_set_edit_access($shortcut_set);
|
||||
}
|
||||
// @todo Fix this bizarre code: how can a shortcut exist without a shortcut
|
||||
// set? The above if-test is unnecessary. See
|
||||
// https://www.drupal.org/node/2339903.
|
||||
return AccessResult::neutral()->addCacheableDependency($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
|
||||
if ($shortcut_set = $this->shortcutSetStorage->load($entity_bundle)) {
|
||||
return shortcut_set_edit_access($shortcut_set);
|
||||
}
|
||||
// @todo Fix this bizarre code: how can a shortcut exist without a shortcut
|
||||
// set? The above if-test is unnecessary. See
|
||||
// https://www.drupal.org/node/2339903.
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
}
|
||||
64
web/core/modules/shortcut/src/ShortcutForm.php
Normal file
64
web/core/modules/shortcut/src/ShortcutForm.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityForm;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Link;
|
||||
|
||||
/**
|
||||
* Form handler for the shortcut entity forms.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ShortcutForm extends ContentEntityForm {
|
||||
|
||||
/**
|
||||
* The entity being used by this form.
|
||||
*
|
||||
* @var \Drupal\shortcut\ShortcutInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function form(array $form, FormStateInterface $form_state) {
|
||||
$form = parent::form($form, $form_state);
|
||||
$form['#attached']['library'][] = 'core/drupal.form';
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function save(array $form, FormStateInterface $form_state) {
|
||||
$entity = $this->entity;
|
||||
$status = $entity->save();
|
||||
$url = $entity->getUrl();
|
||||
// There's an edge case where a user can have permission to
|
||||
// 'link to any content', but has no right to access the linked page. So we
|
||||
// check the access before showing the link.
|
||||
if ($url->access()) {
|
||||
$view_link = Link::fromTextAndUrl($entity->getTitle(), $url)->toString();
|
||||
}
|
||||
else {
|
||||
$view_link = $entity->getTitle();
|
||||
}
|
||||
|
||||
if ($status == SAVED_UPDATED) {
|
||||
$message = $this->t('The shortcut %link has been updated.', ['%link' => $view_link]);
|
||||
}
|
||||
else {
|
||||
$message = $this->t('Added a shortcut for %title.', ['%title' => $view_link]);
|
||||
}
|
||||
$this->messenger()->addStatus($message);
|
||||
|
||||
$form_state->setRedirect(
|
||||
'entity.shortcut_set.customize_form',
|
||||
['shortcut_set' => $entity->bundle()]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
58
web/core/modules/shortcut/src/ShortcutInterface.php
Normal file
58
web/core/modules/shortcut/src/ShortcutInterface.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface defining a shortcut entity.
|
||||
*/
|
||||
interface ShortcutInterface extends ContentEntityInterface {
|
||||
|
||||
/**
|
||||
* Returns the title of this shortcut.
|
||||
*
|
||||
* @return string
|
||||
* The title of this shortcut.
|
||||
*/
|
||||
public function getTitle();
|
||||
|
||||
/**
|
||||
* Sets the title of this shortcut.
|
||||
*
|
||||
* @param string $title
|
||||
* The title of this shortcut.
|
||||
*
|
||||
* @return $this
|
||||
* The called shortcut entity.
|
||||
*/
|
||||
public function setTitle($title);
|
||||
|
||||
/**
|
||||
* Returns the weight among shortcuts with the same depth.
|
||||
*
|
||||
* @return int
|
||||
* The shortcut weight.
|
||||
*/
|
||||
public function getWeight();
|
||||
|
||||
/**
|
||||
* Sets the weight among shortcuts with the same depth.
|
||||
*
|
||||
* @param int $weight
|
||||
* The shortcut weight.
|
||||
*
|
||||
* @return $this
|
||||
* The called shortcut entity.
|
||||
*/
|
||||
public function setWeight($weight);
|
||||
|
||||
/**
|
||||
* Returns the URL object pointing to the configured route.
|
||||
*
|
||||
* @return \Drupal\Core\Url
|
||||
* The URL object.
|
||||
*/
|
||||
public function getUrl();
|
||||
|
||||
}
|
||||
84
web/core/modules/shortcut/src/ShortcutLazyBuilders.php
Normal file
84
web/core/modules/shortcut/src/ShortcutLazyBuilders.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Render\RendererInterface;
|
||||
use Drupal\Core\Security\TrustedCallbackInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
* Lazy builders for the shortcut module.
|
||||
*/
|
||||
class ShortcutLazyBuilders implements TrustedCallbackInterface {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* The renderer service.
|
||||
*
|
||||
* @var \Drupal\Core\Render\RendererInterface
|
||||
*/
|
||||
protected $renderer;
|
||||
|
||||
/**
|
||||
* Constructs a new ShortcutLazyBuilders object.
|
||||
*
|
||||
* @param \Drupal\Core\Render\RendererInterface $renderer
|
||||
* The renderer service.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
|
||||
* The entity type manager.
|
||||
* @param \Drupal\Core\Session\AccountInterface $currentUser
|
||||
* The current user.
|
||||
*/
|
||||
public function __construct(RendererInterface $renderer, protected EntityTypeManagerInterface $entityTypeManager, protected AccountInterface $currentUser) {
|
||||
$this->renderer = $renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function trustedCallbacks() {
|
||||
return ['lazyLinks'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Render API callback: Builds shortcut toolbar links.
|
||||
*
|
||||
* This function is assigned as a #lazy_builder callback.
|
||||
*
|
||||
* @param bool $show_configure_link
|
||||
* Boolean to indicate whether to include the configure link or not.
|
||||
*
|
||||
* @return array
|
||||
* A renderable array of shortcut links.
|
||||
*/
|
||||
public function lazyLinks(bool $show_configure_link = TRUE) {
|
||||
$shortcut_set = $this->entityTypeManager->getStorage('shortcut_set')
|
||||
->getDisplayedToUser($this->currentUser);
|
||||
|
||||
$links = shortcut_renderable_links();
|
||||
|
||||
$configure_link = NULL;
|
||||
if ($show_configure_link && shortcut_set_edit_access($shortcut_set)->isAllowed()) {
|
||||
$configure_link = [
|
||||
'#type' => 'link',
|
||||
'#title' => $this->t('Edit shortcuts'),
|
||||
'#url' => Url::fromRoute('entity.shortcut_set.customize_form', ['shortcut_set' => $shortcut_set->id()]),
|
||||
'#options' => ['attributes' => ['class' => ['edit-shortcuts']]],
|
||||
];
|
||||
}
|
||||
|
||||
$build = [
|
||||
'shortcuts' => $links,
|
||||
'configure' => $configure_link,
|
||||
];
|
||||
|
||||
$this->renderer->addCacheableDependency($build, $shortcut_set);
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityHandlerInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Defines the access control handler for the shortcut set entity type.
|
||||
*
|
||||
* @see \Drupal\shortcut\Entity\ShortcutSet
|
||||
*/
|
||||
class ShortcutSetAccessControlHandler extends EntityAccessControlHandler implements EntityHandlerInterface {
|
||||
|
||||
/**
|
||||
* Constructs a ShortcutSetAccessControlHandler object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type definition.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
|
||||
* The entity type manager.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, protected EntityTypeManagerInterface $entityTypeManager) {
|
||||
parent::__construct($entity_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
|
||||
return new static(
|
||||
$entity_type,
|
||||
$container->get('entity_type.manager'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
switch ($operation) {
|
||||
case 'view':
|
||||
return AccessResult::allowedIfHasPermission($account, 'access shortcuts');
|
||||
|
||||
case 'update':
|
||||
if ($account->hasPermission('administer shortcuts')) {
|
||||
return AccessResult::allowed()->cachePerPermissions();
|
||||
}
|
||||
if (!$account->hasPermission('access shortcuts')) {
|
||||
return AccessResult::neutral()->cachePerPermissions();
|
||||
}
|
||||
|
||||
$shortcut_set_storage = $this->entityTypeManager->getStorage('shortcut_set');
|
||||
return AccessResult::allowedIf($account->hasPermission('customize shortcut links') && $entity == $shortcut_set_storage->getDisplayedToUser($account))->cachePerPermissions()->addCacheableDependency($entity);
|
||||
|
||||
case 'delete':
|
||||
return AccessResult::allowedIf($account->hasPermission('administer shortcuts') && $entity->id() != 'default')->cachePerPermissions();
|
||||
|
||||
default:
|
||||
// No opinion.
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
|
||||
return AccessResult::allowedIfHasPermission($account, 'administer shortcuts')->orIf(AccessResult::allowedIfHasPermissions($account, ['access shortcuts', 'customize shortcut links'], 'AND'));
|
||||
}
|
||||
|
||||
}
|
||||
65
web/core/modules/shortcut/src/ShortcutSetForm.php
Normal file
65
web/core/modules/shortcut/src/ShortcutSetForm.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut;
|
||||
|
||||
use Drupal\Core\Entity\BundleEntityFormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Form handler for the shortcut set entity edit forms.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ShortcutSetForm extends BundleEntityFormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function form(array $form, FormStateInterface $form_state) {
|
||||
$form = parent::form($form, $form_state);
|
||||
|
||||
$entity = $this->entity;
|
||||
$form['label'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Set name'),
|
||||
'#description' => $this->t('The new set is created by copying links from your default shortcut set.'),
|
||||
'#required' => TRUE,
|
||||
'#default_value' => $entity->label(),
|
||||
];
|
||||
$form['id'] = [
|
||||
'#type' => 'machine_name',
|
||||
'#description' => $this->t('A unique machine-readable name. Can only contain lowercase letters, numbers, and hyphens.'),
|
||||
'#machine_name' => [
|
||||
'exists' => '\Drupal\shortcut\Entity\ShortcutSet::load',
|
||||
'source' => ['label'],
|
||||
'replace_pattern' => '[^a-z0-9-]+',
|
||||
'replace' => '-',
|
||||
],
|
||||
'#default_value' => $entity->id(),
|
||||
// This id could be used for menu name.
|
||||
'#maxlength' => 23,
|
||||
];
|
||||
|
||||
$form['actions']['submit']['#value'] = $this->t('Create new set');
|
||||
|
||||
return $this->protectBundleIdElement($form);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function save(array $form, FormStateInterface $form_state) {
|
||||
$entity = $this->entity;
|
||||
$is_new = !$entity->getOriginalId();
|
||||
$entity->save();
|
||||
|
||||
if ($is_new) {
|
||||
$this->messenger()->addStatus($this->t('The %set_name shortcut set has been created. You can edit it from this page.', ['%set_name' => $entity->label()]));
|
||||
}
|
||||
else {
|
||||
$this->messenger()->addStatus($this->t('Updated set name to %set-name.', ['%set-name' => $entity->label()]));
|
||||
}
|
||||
$form_state->setRedirectUrl($this->entity->toUrl('customize-form'));
|
||||
}
|
||||
|
||||
}
|
||||
32
web/core/modules/shortcut/src/ShortcutSetInterface.php
Normal file
32
web/core/modules/shortcut/src/ShortcutSetInterface.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface defining a shortcut set entity.
|
||||
*/
|
||||
interface ShortcutSetInterface extends ConfigEntityInterface {
|
||||
|
||||
/**
|
||||
* Resets the link weights in a shortcut set to match their current order.
|
||||
*
|
||||
* This function can be used, for example, when a new shortcut link is added
|
||||
* to the set. If the link is added to the end of the array and this function
|
||||
* is called, it will force that link to display at the end of the list.
|
||||
*
|
||||
* @return $this
|
||||
* The shortcut set.
|
||||
*/
|
||||
public function resetLinkWeights();
|
||||
|
||||
/**
|
||||
* Returns all the shortcuts from a shortcut set sorted correctly.
|
||||
*
|
||||
* @return \Drupal\shortcut\ShortcutInterface[]
|
||||
* An array of shortcut entities.
|
||||
*/
|
||||
public function getShortcuts();
|
||||
|
||||
}
|
||||
48
web/core/modules/shortcut/src/ShortcutSetListBuilder.php
Normal file
48
web/core/modules/shortcut/src/ShortcutSetListBuilder.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
|
||||
/**
|
||||
* Defines a class to build a listing of shortcut set entities.
|
||||
*
|
||||
* @see \Drupal\shortcut\Entity\ShortcutSet
|
||||
*/
|
||||
class ShortcutSetListBuilder extends ConfigEntityListBuilder {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildHeader() {
|
||||
$header['name'] = $this->t('Name');
|
||||
return $header + parent::buildHeader();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefaultOperations(EntityInterface $entity) {
|
||||
$operations = parent::getDefaultOperations($entity);
|
||||
|
||||
if (isset($operations['edit'])) {
|
||||
$operations['edit']['title'] = $this->t('Edit shortcut set');
|
||||
}
|
||||
|
||||
$operations['list'] = [
|
||||
'title' => $this->t('List links'),
|
||||
'url' => $entity->toUrl('customize-form'),
|
||||
];
|
||||
return $operations;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildRow(EntityInterface $entity) {
|
||||
$row['name'] = $entity->label();
|
||||
return $row + parent::buildRow($entity);
|
||||
}
|
||||
|
||||
}
|
||||
168
web/core/modules/shortcut/src/ShortcutSetStorage.php
Normal file
168
web/core/modules/shortcut/src/ShortcutSetStorage.php
Normal file
@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut;
|
||||
|
||||
use Drupal\Component\Uuid\UuidInterface;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\MemoryCache\MemoryCacheInterface;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityStorage;
|
||||
use Drupal\Core\Database\Connection;
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Defines a storage for shortcut_set entities.
|
||||
*/
|
||||
class ShortcutSetStorage extends ConfigEntityStorage implements ShortcutSetStorageInterface {
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The database connection.
|
||||
*
|
||||
* @var \Drupal\Core\Database\Connection
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* Constructs a ShortcutSetStorageController object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_info
|
||||
* The entity info for the entity type.
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The config factory service.
|
||||
* @param \Drupal\Component\Uuid\UuidInterface $uuid_service
|
||||
* The UUID service.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\Core\Cache\MemoryCache\MemoryCacheInterface $memory_cache
|
||||
* The memory cache.
|
||||
* @param \Drupal\Core\Database\Connection $connection
|
||||
* The database connection.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_info, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, ModuleHandlerInterface $module_handler, LanguageManagerInterface $language_manager, MemoryCacheInterface $memory_cache, Connection $connection) {
|
||||
parent::__construct($entity_info, $config_factory, $uuid_service, $language_manager, $memory_cache);
|
||||
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_info) {
|
||||
return new static(
|
||||
$entity_info,
|
||||
$container->get('config.factory'),
|
||||
$container->get('uuid'),
|
||||
$container->get('module_handler'),
|
||||
$container->get('language_manager'),
|
||||
$container->get('entity.memory_cache'),
|
||||
$container->get('database')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function deleteAssignedShortcutSets(ShortcutSetInterface $entity) {
|
||||
// First, delete any user assignments for this set, so that each of these
|
||||
// users will go back to using whatever default set applies.
|
||||
$this->connection->delete('shortcut_set_users')
|
||||
->condition('set_name', $entity->id())
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function assignUser(ShortcutSetInterface $shortcut_set, $account) {
|
||||
$current_shortcut_set = $this->getDisplayedToUser($account);
|
||||
$this->connection->merge('shortcut_set_users')
|
||||
->key('uid', $account->id())
|
||||
->fields(['set_name' => $shortcut_set->id()])
|
||||
->execute();
|
||||
if ($current_shortcut_set instanceof ShortcutSetInterface) {
|
||||
Cache::invalidateTags($current_shortcut_set->getCacheTagsToInvalidate());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function unassignUser($account) {
|
||||
$current_shortcut_set = $this->getDisplayedToUser($account);
|
||||
$deleted = $this->connection->delete('shortcut_set_users')
|
||||
->condition('uid', $account->id())
|
||||
->execute();
|
||||
if ($current_shortcut_set instanceof ShortcutSetInterface) {
|
||||
Cache::invalidateTags($current_shortcut_set->getCacheTagsToInvalidate());
|
||||
}
|
||||
return (bool) $deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAssignedToUser($account) {
|
||||
$query = $this->connection->select('shortcut_set_users', 'ssu');
|
||||
$query->fields('ssu', ['set_name']);
|
||||
$query->condition('ssu.uid', $account->id());
|
||||
return $query->execute()->fetchField();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDisplayedToUser(AccountInterface $account): ShortcutSetInterface {
|
||||
if ($set_name = $this->getAssignedToUser($account)) {
|
||||
return $this->load($set_name);
|
||||
}
|
||||
|
||||
return $this->getDefaultSet($account);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function countAssignedUsers(ShortcutSetInterface $shortcut_set) {
|
||||
return Database::getConnection()->select('shortcut_set_users')
|
||||
->condition('set_name', $shortcut_set->id())
|
||||
->countQuery()
|
||||
->execute()
|
||||
->fetchField();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefaultSet(AccountInterface $account) {
|
||||
// Allow modules to return a default shortcut set name. Since we can only
|
||||
// have one, we allow the last module which returns a valid result to take
|
||||
// precedence. If no module returns a valid set, fall back on the site-wide
|
||||
// default, which is the lowest-numbered shortcut set.
|
||||
$suggestions = array_reverse($this->moduleHandler->invokeAll('shortcut_default_set', [$account]));
|
||||
$suggestions[] = 'default';
|
||||
$shortcut_set = NULL;
|
||||
foreach ($suggestions as $name) {
|
||||
if ($shortcut_set = $this->load($name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $shortcut_set;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\shortcut;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Defines an interface for shortcut_set entity storage classes.
|
||||
*/
|
||||
interface ShortcutSetStorageInterface extends ConfigEntityStorageInterface {
|
||||
|
||||
/**
|
||||
* Assigns a user to a particular shortcut set.
|
||||
*
|
||||
* @param \Drupal\shortcut\ShortcutSetInterface $shortcut_set
|
||||
* An object representing the shortcut set.
|
||||
* @param \Drupal\user\UserInterface $account
|
||||
* A user account that will be assigned to use the set.
|
||||
*/
|
||||
public function assignUser(ShortcutSetInterface $shortcut_set, $account);
|
||||
|
||||
/**
|
||||
* Un-assigns a user from any shortcut set they may have been assigned to.
|
||||
*
|
||||
* The user will go back to using whatever default set applies.
|
||||
*
|
||||
* @param \Drupal\user\UserInterface $account
|
||||
* A user account that will be removed from the shortcut set assignment.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the user was previously assigned to a shortcut set and has been
|
||||
* successfully removed from it. FALSE if the user was already not assigned
|
||||
* to any set.
|
||||
*/
|
||||
public function unassignUser($account);
|
||||
|
||||
/**
|
||||
* Delete shortcut sets assigned to users.
|
||||
*
|
||||
* @param \Drupal\shortcut\ShortcutSetInterface $entity
|
||||
* Delete the user assigned sets belonging to this shortcut.
|
||||
*/
|
||||
public function deleteAssignedShortcutSets(ShortcutSetInterface $entity);
|
||||
|
||||
/**
|
||||
* Get the name of the set assigned to this user.
|
||||
*
|
||||
* @param \Drupal\user\Entity\User $account
|
||||
* The user account.
|
||||
*
|
||||
* @return string
|
||||
* The name of the shortcut set assigned to this user.
|
||||
*/
|
||||
public function getAssignedToUser($account);
|
||||
|
||||
/**
|
||||
* Gets the shortcut set to be displayed for a given user account.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The user account whose default shortcut set will be returned.
|
||||
*
|
||||
* @return \Drupal\shortcut\ShortcutSetInterface
|
||||
* An object representing the default shortcut set.
|
||||
*/
|
||||
public function getDisplayedToUser(AccountInterface $account): ShortcutSetInterface;
|
||||
|
||||
/**
|
||||
* Get the number of users who have this set assigned to them.
|
||||
*
|
||||
* @param \Drupal\shortcut\ShortcutSetInterface $shortcut_set
|
||||
* The shortcut to count the users assigned to.
|
||||
*
|
||||
* @return int
|
||||
* The number of users who have this set assigned to them.
|
||||
*/
|
||||
public function countAssignedUsers(ShortcutSetInterface $shortcut_set);
|
||||
|
||||
/**
|
||||
* Gets the default shortcut set for a given user account.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The user account whose default shortcut set will be returned.
|
||||
*
|
||||
* @return \Drupal\shortcut\ShortcutSetInterface
|
||||
* An object representing the default shortcut set.
|
||||
*/
|
||||
public function getDefaultSet(AccountInterface $account);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user