diff --git a/core/core.services.yml b/core/core.services.yml index 14c665c..be77e6c 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -984,7 +984,7 @@ services: class: Drupal\Core\EventSubscriber\DefaultExceptionHtmlSubscriber tags: - { name: event_subscriber } - arguments: ['@http_kernel', '@logger.channel.php'] + arguments: ['@http_kernel', '@logger.channel.php', '@redirect.destination'] exception.default: class: Drupal\Core\EventSubscriber\DefaultExceptionSubscriber tags: @@ -1004,7 +1004,7 @@ services: class: Drupal\Core\EventSubscriber\CustomPageExceptionHtmlSubscriber tags: - { name: event_subscriber } - arguments: ['@config.factory', '@path.alias_manager', '@http_kernel', '@logger.channel.php'] + arguments: ['@config.factory', '@path.alias_manager', '@http_kernel', '@logger.channel.php', '@redirect.destination'] exception.fast_404_html: class: Drupal\Core\EventSubscriber\Fast404ExceptionHtmlSubscriber tags: diff --git a/core/lib/Drupal/Core/Controller/ControllerBase.php b/core/lib/Drupal/Core/Controller/ControllerBase.php index 1161da5..5255bc3 100644 --- a/core/lib/Drupal/Core/Controller/ControllerBase.php +++ b/core/lib/Drupal/Core/Controller/ControllerBase.php @@ -9,6 +9,7 @@ use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Routing\LinkGeneratorTrait; +use Drupal\Core\Routing\RedirectDestinationTrait; use Drupal\Core\Routing\UrlGeneratorTrait; use Drupal\Core\StringTranslation\StringTranslationTrait; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -35,8 +36,10 @@ * @ingroup menu */ abstract class ControllerBase implements ContainerInjectionInterface { - use StringTranslationTrait; + use LinkGeneratorTrait; + use RedirectDestinationTrait; + use StringTranslationTrait; use UrlGeneratorTrait; /** diff --git a/core/lib/Drupal/Core/EventSubscriber/CustomPageExceptionHtmlSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/CustomPageExceptionHtmlSubscriber.php index c393a34..377f26b 100644 --- a/core/lib/Drupal/Core/EventSubscriber/CustomPageExceptionHtmlSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/CustomPageExceptionHtmlSubscriber.php @@ -9,6 +9,7 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Path\AliasManagerInterface; +use Drupal\Core\Routing\RedirectDestinationInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; @@ -44,9 +45,11 @@ class CustomPageExceptionHtmlSubscriber extends DefaultExceptionHtmlSubscriber { * The HTTP Kernel service. * @param \Psr\Log\LoggerInterface $logger * The logger service. + * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination + * The redirect destination service. */ - public function __construct(ConfigFactoryInterface $config_factory, AliasManagerInterface $alias_manager, HttpKernelInterface $http_kernel, LoggerInterface $logger) { - parent::__construct($http_kernel, $logger); + public function __construct(ConfigFactoryInterface $config_factory, AliasManagerInterface $alias_manager, HttpKernelInterface $http_kernel, LoggerInterface $logger, RedirectDestinationInterface $redirect_destination) { + parent::__construct($http_kernel, $logger, $redirect_destination); $this->configFactory = $config_factory; $this->aliasManager = $alias_manager; } diff --git a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php index f5a4b79..fc5375c 100644 --- a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php @@ -8,6 +8,7 @@ namespace Drupal\Core\EventSubscriber; use Drupal\Core\Routing\AccessAwareRouterInterface; +use Drupal\Core\Routing\RedirectDestinationInterface; use Drupal\Core\Url; use Drupal\Core\Utility\Error; use Psr\Log\LoggerInterface; @@ -36,16 +37,26 @@ class DefaultExceptionHtmlSubscriber extends HttpExceptionSubscriberBase { protected $logger; /** + * The redirect destination service. + * + * @var \Drupal\Core\Routing\RedirectDestinationInterface + */ + protected $redirectDestination; + + /** * Constructs a new DefaultExceptionHtmlSubscriber. * * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel * The HTTP kernel. * @param \Psr\Log\LoggerInterface $logger * The logger service. + * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination + * The redirect destination service. */ - public function __construct(HttpKernelInterface $http_kernel, LoggerInterface $logger) { + public function __construct(HttpKernelInterface $http_kernel, LoggerInterface $logger, RedirectDestinationInterface $redirect_destination) { $this->httpKernel = $http_kernel; $this->logger = $logger; + $this->redirectDestination = $redirect_destination; } /** @@ -105,10 +116,10 @@ protected function makeSubrequest(GetResponseForExceptionEvent $event, $url, $st if ($url != $request->getBasePath() . '/' && $url != $current_url) { if ($request->getMethod() === 'POST') { - $sub_request = Request::create($url, 'POST', $this->drupalGetDestination() + ['_exception_statuscode' => $status_code] + $request->request->all(), $request->cookies->all(), [], $request->server->all()); + $sub_request = Request::create($url, 'POST', $this->redirectDestination->getAsArray() + ['_exception_statuscode' => $status_code] + $request->request->all(), $request->cookies->all(), [], $request->server->all()); } else { - $sub_request = Request::create($url, 'GET', $request->query->all() + $this->drupalGetDestination() + ['_exception_statuscode' => $status_code], $request->cookies->all(), [], $request->server->all()); + $sub_request = Request::create($url, 'GET', $request->query->all() + $this->redirectDestination->getAsArray() + ['_exception_statuscode' => $status_code], $request->cookies->all(), [], $request->server->all()); } try { @@ -137,11 +148,4 @@ protected function makeSubrequest(GetResponseForExceptionEvent $event, $url, $st } } - /** - * Wraps drupal_get_destination(). - */ - protected function drupalGetDestination() { - return drupal_get_destination(); - } - } diff --git a/core/lib/Drupal/Core/Form/FormBase.php b/core/lib/Drupal/Core/Form/FormBase.php index d7c2bfd..5c2d2af 100644 --- a/core/lib/Drupal/Core/Form/FormBase.php +++ b/core/lib/Drupal/Core/Form/FormBase.php @@ -11,6 +11,7 @@ use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\Routing\LinkGeneratorTrait; +use Drupal\Core\Routing\RedirectDestinationTrait; use Drupal\Core\Routing\UrlGeneratorTrait; use Drupal\Core\StringTranslation\StringTranslationTrait; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -22,9 +23,11 @@ * @ingroup form_api */ abstract class FormBase implements FormInterface, ContainerInjectionInterface { - use StringTranslationTrait; + use DependencySerializationTrait; use LinkGeneratorTrait; + use RedirectDestinationTrait; + use StringTranslationTrait; use UrlGeneratorTrait; /** diff --git a/core/lib/Drupal/Core/Render/Element/SystemCompactLink.php b/core/lib/Drupal/Core/Render/Element/SystemCompactLink.php index c561b38..fa701b0 100644 --- a/core/lib/Drupal/Core/Render/Element/SystemCompactLink.php +++ b/core/lib/Drupal/Core/Render/Element/SystemCompactLink.php @@ -63,7 +63,7 @@ public static function preRenderCompactLink($element) { $element['#url'] = BaseUrl::fromRoute('system.admin_compact_page', array('mode' => 'off')); $element['#options'] = array( 'attributes' => array('title' => t('Expand layout to include descriptions.')), - 'query' => drupal_get_destination(), + 'query' => \Drupal::destination()->getAsArray() ); } else { @@ -71,7 +71,7 @@ public static function preRenderCompactLink($element) { $element['#url'] = BaseUrl::fromRoute('system.admin_compact_page', array('mode' => 'on')); $element['#options'] = array( 'attributes' => array('title' => t('Compress layout by hiding descriptions.')), - 'query' => drupal_get_destination(), + 'query' => \Drupal::destination()->getAsArray(), ); } diff --git a/core/lib/Drupal/Core/Routing/RedirectDestinationTrait.php b/core/lib/Drupal/Core/Routing/RedirectDestinationTrait.php new file mode 100644 index 0000000..db4696e --- /dev/null +++ b/core/lib/Drupal/Core/Routing/RedirectDestinationTrait.php @@ -0,0 +1,72 @@ +getRedirectDestination()->getAsArray(); + } + + /** + * Returns the redirect destination service. + * + * @return \Drupal\Core\Routing\RedirectDestinationInterface + * The redirect destination helper. + */ + protected function getRedirectDestination() { + if (!isset($this->redirectDestination)) { + $this->redirectDestination = \Drupal::destination(); + } + + return $this->redirectDestination; + } + + /** + * Sets the redirect destination service. + * + * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination + * The redirect destination service. + * + * @return $this + */ + public function setRedirectDestination(RedirectDestinationInterface $redirect_destination) { + $this->redirectDestination = $redirect_destination; + + return $this; + } + +} diff --git a/core/modules/book/src/Form/BookAdminEditForm.php b/core/modules/book/src/Form/BookAdminEditForm.php index 29fad42..9df174d 100644 --- a/core/modules/book/src/Form/BookAdminEditForm.php +++ b/core/modules/book/src/Form/BookAdminEditForm.php @@ -206,7 +206,7 @@ protected function bookAdminTableTree(array $tree, array &$form) { $delta = ($count < 30) ? 15 : intval($count / 2) + 1; $access = \Drupal::currentUser()->hasPermission('administer nodes'); - $destination = drupal_get_destination(); + $destination = $this->getDestinationArray(); foreach ($tree as $data) { $nid = $data['link']['nid']; diff --git a/core/modules/comment/src/CommentManager.php b/core/modules/comment/src/CommentManager.php index 72b87a2..45705a2 100644 --- a/core/modules/comment/src/CommentManager.php +++ b/core/modules/comment/src/CommentManager.php @@ -159,7 +159,7 @@ public function forbiddenMessage(EntityInterface $entity, $field_name) { } if ($this->authenticatedCanPostComments) { - // We cannot use drupal_get_destination() because these links + // We cannot use the redirect.destination service here because these links // sometimes appear on /node and taxonomy listing pages. if ($entity->get($field_name)->getFieldDefinition()->getSetting('form_location') == CommentItemInterface::FORM_SEPARATE_PAGE) { $comment_reply_parameters = [ diff --git a/core/modules/comment/src/Form/CommentAdminOverview.php b/core/modules/comment/src/Form/CommentAdminOverview.php index 8db0ed3..c5108c7 100644 --- a/core/modules/comment/src/Form/CommentAdminOverview.php +++ b/core/modules/comment/src/Form/CommentAdminOverview.php @@ -167,7 +167,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $type = ' // Build a table listing the appropriate comments. $options = array(); - $destination = drupal_get_destination(); + $destination = $this->getDestinationArray(); $commented_entity_ids = array(); $commented_entities = array(); diff --git a/core/modules/comment/src/Plugin/views/field/Link.php b/core/modules/comment/src/Plugin/views/field/Link.php index 70c5c0e..c2fc23d 100644 --- a/core/modules/comment/src/Plugin/views/field/Link.php +++ b/core/modules/comment/src/Plugin/views/field/Link.php @@ -11,6 +11,7 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\Routing\RedirectDestinationTrait; use Drupal\Core\Url; use Drupal\views\ResultRow; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -24,6 +25,8 @@ */ class Link extends FieldPluginBase { + use RedirectDestinationTrait; + /** * Entity Manager service. * diff --git a/core/modules/comment/src/Plugin/views/field/LinkApprove.php b/core/modules/comment/src/Plugin/views/field/LinkApprove.php index b249a74..11e7812 100644 --- a/core/modules/comment/src/Plugin/views/field/LinkApprove.php +++ b/core/modules/comment/src/Plugin/views/field/LinkApprove.php @@ -53,7 +53,7 @@ protected function renderLink($data, ResultRow $values) { $this->options['alter']['make_link'] = TRUE; $this->options['alter']['url'] = Url::fromRoute('comment.approve', ['comment' => $comment->id()]); - $this->options['alter']['query'] = drupal_get_destination() + array('token' => \Drupal::csrfToken()->get($this->options['alter']['url']->toString())); + $this->options['alter']['query'] = $this->getDestinationArray() + array('token' => \Drupal::csrfToken()->get($this->options['alter']['url']->toString())); return $text; } diff --git a/core/modules/comment/src/Plugin/views/field/LinkDelete.php b/core/modules/comment/src/Plugin/views/field/LinkDelete.php index b36c223..5ede03f 100644 --- a/core/modules/comment/src/Plugin/views/field/LinkDelete.php +++ b/core/modules/comment/src/Plugin/views/field/LinkDelete.php @@ -44,7 +44,7 @@ protected function renderLink($data, ResultRow $values) { $this->options['alter']['make_link'] = TRUE; $this->options['alter']['url'] = $comment->urlInfo('delete-form'); - $this->options['alter']['query'] = drupal_get_destination(); + $this->options['alter']['query'] = $this->getDestinationArray(); return $text; } diff --git a/core/modules/comment/src/Plugin/views/field/LinkEdit.php b/core/modules/comment/src/Plugin/views/field/LinkEdit.php index 316c272..7ae0693 100644 --- a/core/modules/comment/src/Plugin/views/field/LinkEdit.php +++ b/core/modules/comment/src/Plugin/views/field/LinkEdit.php @@ -60,7 +60,7 @@ protected function renderLink($data, ResultRow $values) { unset($this->options['alter']['fragment']); if (!empty($this->options['destination'])) { - $this->options['alter']['query'] = drupal_get_destination(); + $this->options['alter']['query'] = $this->getDestinationArray(); } $this->options['alter']['url'] = $comment->urlInfo('edit-form'); diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module index 99c36ee..9ab0bfd 100644 --- a/core/modules/content_translation/content_translation.module +++ b/core/modules/content_translation/content_translation.module @@ -336,7 +336,7 @@ function content_translation_form_field_config_edit_form_alter(array &$form, For // Provide helpful pointers for administrators. if (\Drupal::currentUser()->hasPermission('administer content translation') && !$bundle_is_translatable) { $toggle_url = \Drupal::url('language.content_settings_page', array(), array( - 'query' => drupal_get_destination(), + 'query' => \Drupal::destination()->getAsArray(), )); $form['translatable']['#description'] = t('To configure translation for this field, enable language support for this type.', array( '@language-settings-url' => $toggle_url, diff --git a/core/modules/contextual/src/Plugin/views/field/ContextualLinks.php b/core/modules/contextual/src/Plugin/views/field/ContextualLinks.php index bb89a26..68929d1 100644 --- a/core/modules/contextual/src/Plugin/views/field/ContextualLinks.php +++ b/core/modules/contextual/src/Plugin/views/field/ContextualLinks.php @@ -11,6 +11,7 @@ use Drupal\Component\Utility\Html; use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Routing\RedirectDestinationTrait; use Drupal\Core\Url; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\views\ResultRow; @@ -24,6 +25,8 @@ */ class ContextualLinks extends FieldPluginBase { + use RedirectDestinationTrait; + /** * {@inheritdoc} */ @@ -119,7 +122,7 @@ public function render(ResultRow $values) { 'title' => $title, ); if (!empty($this->options['destination'])) { - $links[$field]['query'] = drupal_get_destination(); + $links[$field]['query'] = $this->getDestinationArray(); } } } diff --git a/core/modules/field_ui/src/Form/FieldStorageAddForm.php b/core/modules/field_ui/src/Form/FieldStorageAddForm.php index 0c07e7f..b26c225 100644 --- a/core/modules/field_ui/src/Form/FieldStorageAddForm.php +++ b/core/modules/field_ui/src/Form/FieldStorageAddForm.php @@ -417,7 +417,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { } if ($destinations) { - $destination = drupal_get_destination(); + $destination = $this->getDestinationArray(); $destinations[] = $destination['destination']; $form_state->setRedirectUrl(FieldUI::getNextDestination($destinations, $form_state)); } diff --git a/core/modules/forum/src/Controller/ForumController.php b/core/modules/forum/src/Controller/ForumController.php index 82165ff..17c0454 100644 --- a/core/modules/forum/src/Controller/ForumController.php +++ b/core/modules/forum/src/Controller/ForumController.php @@ -290,7 +290,7 @@ protected function buildActionLinks($vid, TermInterface $forum_term = NULL) { '#theme' => 'menu_local_action', '#link' => array( 'title' => $this->t('Log in to post new content in the forum.'), - 'url' => Url::fromRoute('user.login', [], ['query' => $this->getDestination()]), + 'url' => Url::fromRoute('user.login', [], ['query' => $this->getDestinationArray()]), ), ]; } @@ -298,11 +298,4 @@ protected function buildActionLinks($vid, TermInterface $forum_term = NULL) { return $links; } - /** - * Wraps drupal_get_destination(). - */ - protected function getDestination() { - return drupal_get_destination(); - } - } diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc index 06807b6..41ce0b8 100644 --- a/core/modules/locale/locale.pages.inc +++ b/core/modules/locale/locale.pages.inc @@ -120,5 +120,5 @@ function template_preprocess_locale_translation_last_check(array &$variables) { $last = $variables['last']; $variables['last_checked'] = ($last != NULL); $variables['time'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $last); - $variables['link'] = \Drupal::l(t('Check manually'), new Url('locale.check_translation', array(), array('query' => drupal_get_destination()))); + $variables['link'] = \Drupal::l(t('Check manually'), new Url('locale.check_translation', array(), array('query' => \Drupal::destination()->getAsArray()))); } diff --git a/core/modules/menu_ui/src/MenuForm.php b/core/modules/menu_ui/src/MenuForm.php index fd38c02..09f529a 100644 --- a/core/modules/menu_ui/src/MenuForm.php +++ b/core/modules/menu_ui/src/MenuForm.php @@ -383,7 +383,7 @@ protected function buildOverviewTreeForm($tree, $delta) { if ($edit_route) { $operations['edit']['url'] = $edit_route; // Bring the user back to the menu overview. - $operations['edit']['query'] = drupal_get_destination(); + $operations['edit']['query'] = $this->getDestinationArray(); } else { // Fall back to the standard edit link. @@ -400,7 +400,7 @@ protected function buildOverviewTreeForm($tree, $delta) { } elseif ($delete_link = $link->getDeleteRoute()) { $operations['delete']['url'] = $delete_link; - $operations['delete']['query'] = drupal_get_destination(); + $operations['delete']['query'] = $this->getDestinationArray(); $operations['delete']['title'] = $this->t('Delete'); } if ($link->isTranslatable()) { diff --git a/core/modules/node/src/NodeListBuilder.php b/core/modules/node/src/NodeListBuilder.php index 8d36dee..7acbfc9 100644 --- a/core/modules/node/src/NodeListBuilder.php +++ b/core/modules/node/src/NodeListBuilder.php @@ -14,6 +14,7 @@ use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Language\LanguageInterface; +use Drupal\Core\Routing\RedirectDestinationInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -31,6 +32,13 @@ class NodeListBuilder extends EntityListBuilder { protected $dateFormatter; /** + * The redirect destination service. + * + * @var \Drupal\Core\Routing\RedirectDestinationInterface + */ + protected $redirectDestination; + + /** * Constructs a new NodeListBuilder object. * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type @@ -39,11 +47,14 @@ class NodeListBuilder extends EntityListBuilder { * The entity storage class. * @param \Drupal\Core\Datetime\DateFormatter $date_formatter * The date formatter service. + * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination + * The redirect destination service. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatter $date_formatter) { + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatter $date_formatter, RedirectDestinationInterface $redirect_destination) { parent::__construct($entity_type, $storage); $this->dateFormatter = $date_formatter; + $this->redirectDestination = $redirect_destination; } /** @@ -53,7 +64,8 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $container->get('entity.manager')->getStorage($entity_type->id()), - $container->get('date.formatter') + $container->get('date.formatter'), + $container->get('redirect.destination') ); } @@ -128,7 +140,7 @@ public function buildRow(EntityInterface $entity) { protected function getDefaultOperations(EntityInterface $entity) { $operations = parent::getDefaultOperations($entity); - $destination = drupal_get_destination(); + $destination = $this->redirectDestination->getAsArray(); foreach ($operations as $key => $operation) { $operations[$key]['query'] = $destination; } diff --git a/core/modules/node/src/Plugin/views/field/Link.php b/core/modules/node/src/Plugin/views/field/Link.php index 54b51ae..a0d7ba7 100644 --- a/core/modules/node/src/Plugin/views/field/Link.php +++ b/core/modules/node/src/Plugin/views/field/Link.php @@ -8,6 +8,7 @@ namespace Drupal\node\Plugin\views\field; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Routing\RedirectDestinationTrait; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\views\ResultRow; @@ -20,6 +21,8 @@ */ class Link extends FieldPluginBase { + use RedirectDestinationTrait; + /** * {@inheritdoc} */ diff --git a/core/modules/node/src/Plugin/views/field/LinkDelete.php b/core/modules/node/src/Plugin/views/field/LinkDelete.php index 6bc5156..6dad5e0 100644 --- a/core/modules/node/src/Plugin/views/field/LinkDelete.php +++ b/core/modules/node/src/Plugin/views/field/LinkDelete.php @@ -38,7 +38,7 @@ protected function renderLink($node, ResultRow $values) { $this->options['alter']['make_link'] = TRUE; $this->options['alter']['url'] = $node->urlInfo('delete-form'); - $this->options['alter']['query'] = drupal_get_destination(); + $this->options['alter']['query'] = $this->getDestinationArray(); $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('Delete'); return $text; diff --git a/core/modules/node/src/Plugin/views/field/LinkEdit.php b/core/modules/node/src/Plugin/views/field/LinkEdit.php index eb8b974..6d46642 100644 --- a/core/modules/node/src/Plugin/views/field/LinkEdit.php +++ b/core/modules/node/src/Plugin/views/field/LinkEdit.php @@ -39,7 +39,7 @@ protected function renderLink($node, ResultRow $values) { $this->options['alter']['make_link'] = TRUE; $this->options['alter']['url'] = $node->urlInfo('edit-form'); - $this->options['alter']['query'] = drupal_get_destination(); + $this->options['alter']['query'] = $this->getDestinationArray(); $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('Edit'); return $text; diff --git a/core/modules/node/src/Plugin/views/field/RevisionLink.php b/core/modules/node/src/Plugin/views/field/RevisionLink.php index b510e50..8370170 100644 --- a/core/modules/node/src/Plugin/views/field/RevisionLink.php +++ b/core/modules/node/src/Plugin/views/field/RevisionLink.php @@ -66,7 +66,7 @@ protected function renderLink($data, ResultRow $values) { $this->options['alter']['make_link'] = TRUE; $this->options['alter']['url'] = $url; - $this->options['alter']['query'] = drupal_get_destination(); + $this->options['alter']['query'] = $this->getDestinationArray(); return !empty($this->options['text']) ? $this->options['text'] : $this->t('View'); } diff --git a/core/modules/node/src/Plugin/views/field/RevisionLinkDelete.php b/core/modules/node/src/Plugin/views/field/RevisionLinkDelete.php index 1d5a14b..c7519d0 100644 --- a/core/modules/node/src/Plugin/views/field/RevisionLinkDelete.php +++ b/core/modules/node/src/Plugin/views/field/RevisionLinkDelete.php @@ -52,7 +52,7 @@ protected function renderLink($data, ResultRow $values) { $this->options['alter']['make_link'] = TRUE; $this->options['alter']['url'] = Url::fromRoute('node.revision_delete_confirm', ['node' => $node->id(), 'node_revision' => $vid]); - $this->options['alter']['query'] = drupal_get_destination(); + $this->options['alter']['query'] = $this->getDestinationArray(); return !empty($this->options['text']) ? $this->options['text'] : $this->t('Delete'); } diff --git a/core/modules/node/src/Plugin/views/field/RevisionLinkRevert.php b/core/modules/node/src/Plugin/views/field/RevisionLinkRevert.php index 17db8a8..a5d1c97 100644 --- a/core/modules/node/src/Plugin/views/field/RevisionLinkRevert.php +++ b/core/modules/node/src/Plugin/views/field/RevisionLinkRevert.php @@ -52,7 +52,7 @@ protected function renderLink($data, ResultRow $values) { $this->options['alter']['make_link'] = TRUE; $this->options['alter']['url'] = Url::fromRoute('node.revision_revert_confirm', ['node' => $node->id(), 'node_revision' => $vid]); - $this->options['alter']['query'] = drupal_get_destination(); + $this->options['alter']['query'] = $this->getDestinationArray(); return !empty($this->options['text']) ? $this->options['text'] : $this->t('Revert'); } diff --git a/core/modules/path/src/Controller/PathController.php b/core/modules/path/src/Controller/PathController.php index 8756270..cdb596d 100644 --- a/core/modules/path/src/Controller/PathController.php +++ b/core/modules/path/src/Controller/PathController.php @@ -83,7 +83,7 @@ public function adminOverview(Request $request) { $header[] = $this->t('Operations'); $rows = array(); - $destination = drupal_get_destination(); + $destination = $this->getDestinationArray(); foreach ($this->aliasStorage->getAliasesForAdminListing($header, $keys) as $data) { $row = array(); // @todo Should Path module store leading slashes? See diff --git a/core/modules/path/src/Form/EditForm.php b/core/modules/path/src/Form/EditForm.php index 18863d7..fc85a42 100644 --- a/core/modules/path/src/Form/EditForm.php +++ b/core/modules/path/src/Form/EditForm.php @@ -58,7 +58,7 @@ public function deleteSubmit(array &$form, FormStateInterface $form_state) { )); if ($this->getRequest()->query->has('destination')) { - $url->setOption('query', drupal_get_destination()); + $url->setOption('query', $this->getDestinationArray()); $this->getRequest()->query->remove('destination'); } diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index d57af75..459ea29 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -313,7 +313,7 @@ function shortcut_preprocess_page(&$variables) { 'link' => $link, 'name' => $variables['title'], ); - $query += drupal_get_destination(); + $query += \Drupal::destination()->getAsArray(); $shortcut_set = shortcut_current_displayed_set(); diff --git a/core/modules/system/src/Plugin/views/field/BulkForm.php b/core/modules/system/src/Plugin/views/field/BulkForm.php index f4a2545..b67bf8a 100644 --- a/core/modules/system/src/Plugin/views/field/BulkForm.php +++ b/core/modules/system/src/Plugin/views/field/BulkForm.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Routing\RedirectDestinationTrait; use Drupal\views\Plugin\views\display\DisplayPluginBase; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\views\Plugin\views\style\Table; @@ -24,6 +25,8 @@ */ class BulkForm extends FieldPluginBase { + use RedirectDestinationTrait; + /** * The action storage. * @@ -284,7 +287,7 @@ public function viewsFormSubmit(&$form, FormStateInterface $form_state) { $operation_definition = $action->getPluginDefinition(); if (!empty($operation_definition['confirm_form_route_name'])) { $options = array( - 'query' => drupal_get_destination(), + 'query' => $this->getDestinationArray(), ); $form_state->setRedirect($operation_definition['confirm_form_route_name'], array(), $options); } diff --git a/core/modules/system/system.module b/core/modules/system/system.module index d2bda7f..88f9023 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -729,7 +729,7 @@ function system_user_login(UserInterface $account) { $config = \Drupal::config('system.date'); // If the user has a NULL time zone, notify them to set a time zone. if (!$account->getTimezone() && $config->get('timezone.user.configurable') && $config->get('timezone.user.warn')) { - drupal_set_message(t('Configure your account time zone setting.', array('@user-edit' => $account->url('edit-form', array('query' => drupal_get_destination(), 'fragment' => 'edit-timezone'))))); + drupal_set_message(t('Configure your account time zone setting.', array('@user-edit' => $account->url('edit-form', array('query' => \Drupal::destination()->getAsArray(), 'fragment' => 'edit-timezone'))))); } } diff --git a/core/modules/system/tests/modules/common_test/src/Controller/CommonTestController.php b/core/modules/system/tests/modules/common_test/src/Controller/CommonTestController.php index 0b4c42a..8d89b6e 100644 --- a/core/modules/system/tests/modules/common_test/src/Controller/CommonTestController.php +++ b/core/modules/system/tests/modules/common_test/src/Controller/CommonTestController.php @@ -89,9 +89,8 @@ public function jsAndCssQuerystring() { * parameter. */ public function destination() { - $destination = drupal_get_destination(); + $destination = \Drupal::destination()->getAsArray(); $output = "The destination: " . SafeMarkup::checkPlain($destination['destination']); - return new Response($output); } diff --git a/core/modules/taxonomy/src/Form/OverviewTerms.php b/core/modules/taxonomy/src/Form/OverviewTerms.php index 9e7e391..eebbacc 100644 --- a/core/modules/taxonomy/src/Form/OverviewTerms.php +++ b/core/modules/taxonomy/src/Form/OverviewTerms.php @@ -200,7 +200,7 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular } $errors = $form_state->getErrors(); - $destination = drupal_get_destination(); + $destination = $this->getDestinationArray(); $row_position = 0; // Build the actual form. $form['terms'] = array( diff --git a/core/modules/taxonomy/src/Plugin/views/field/LinkEdit.php b/core/modules/taxonomy/src/Plugin/views/field/LinkEdit.php index 306c02c..10f0337 100644 --- a/core/modules/taxonomy/src/Plugin/views/field/LinkEdit.php +++ b/core/modules/taxonomy/src/Plugin/views/field/LinkEdit.php @@ -8,6 +8,7 @@ namespace Drupal\taxonomy\Plugin\views\field; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Routing\RedirectDestinationTrait; use Drupal\Core\Url; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\views\Plugin\views\display\DisplayPluginBase; @@ -23,6 +24,8 @@ */ class LinkEdit extends FieldPluginBase { + use RedirectDestinationTrait; + /** * {@inheritdoc} */ @@ -78,7 +81,7 @@ public function render(ResultRow $values) { )); if ($term->access('update')) { $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('Edit'); - return \Drupal::l($text, new Url('entity.taxonomy.edit_form', ['taxonomy_term' => $tid], array('query' => drupal_get_destination()))); + return \Drupal::l($text, new Url('entity.taxonomy.edit_form', ['taxonomy_term' => $tid], array('query' => $this->getDestinationArray()))); } } } diff --git a/core/modules/update/update.module b/core/modules/update/update.module index 6f4403d..b8cb1c8 100644 --- a/core/modules/update/update.module +++ b/core/modules/update/update.module @@ -290,7 +290,7 @@ function update_storage_clear_submit($form, FormStateInterface $form_state) { * Returns a warning message when there is no data about available updates. */ function _update_no_data() { - $destination = drupal_get_destination(); + $destination = \Drupal::destination()->getAsArray(); return t('No update information available. Run cron or check manually.', array( '@run_cron' => \Drupal::url('system.run_cron', [], ['query' => $destination]), '@check_manually' => \Drupal::url('update.manual_status', [], ['query' => $destination]), @@ -590,7 +590,7 @@ function _update_project_status_sort($a, $b) { */ function template_preprocess_update_last_check(&$variables) { $variables['time'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $variables['last']); - $variables['link'] = \Drupal::l(t('Check manually'), new Url('update.manual_status', array(), array('query' => drupal_get_destination()))); + $variables['link'] = \Drupal::l(t('Check manually'), new Url('update.manual_status', array(), array('query' => \Drupal::destination()->getAsArray()))); } /** diff --git a/core/modules/user/src/Plugin/Block/UserLoginBlock.php b/core/modules/user/src/Plugin/Block/UserLoginBlock.php index 64c4990..3f28d3c 100644 --- a/core/modules/user/src/Plugin/Block/UserLoginBlock.php +++ b/core/modules/user/src/Plugin/Block/UserLoginBlock.php @@ -8,6 +8,7 @@ namespace Drupal\user\Plugin\Block; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\Routing\RedirectDestinationTrait; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Routing\UrlGeneratorTrait; use Drupal\Core\Url; @@ -27,6 +28,7 @@ class UserLoginBlock extends BlockBase implements ContainerFactoryPluginInterface { use UrlGeneratorTrait; + use RedirectDestinationTrait; /** * The route match. @@ -87,7 +89,7 @@ public function build() { unset($form['pass']['#description']); $form['name']['#size'] = 15; $form['pass']['#size'] = 15; - $form['#action'] = $this->url('', [], ['query' => drupal_get_destination(), 'external' => FALSE]); + $form['#action'] = $this->url('', [], ['query' => $this->getDestinationArray(), 'external' => FALSE]); // Build action links. $items = array(); if (\Drupal::config('user.settings')->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY) { diff --git a/core/modules/user/src/Plugin/views/field/Link.php b/core/modules/user/src/Plugin/views/field/Link.php index 0bca949..78057cc 100644 --- a/core/modules/user/src/Plugin/views/field/Link.php +++ b/core/modules/user/src/Plugin/views/field/Link.php @@ -8,6 +8,7 @@ namespace Drupal\user\Plugin\views\field; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Routing\RedirectDestinationTrait; use Drupal\Core\Session\AccountInterface; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\views\Plugin\views\display\DisplayPluginBase; @@ -24,6 +25,8 @@ */ class Link extends FieldPluginBase { + use RedirectDestinationTrait; + /** * {@inheritdoc} */ diff --git a/core/modules/user/src/Plugin/views/field/LinkCancel.php b/core/modules/user/src/Plugin/views/field/LinkCancel.php index abdbec7..b29c426 100644 --- a/core/modules/user/src/Plugin/views/field/LinkCancel.php +++ b/core/modules/user/src/Plugin/views/field/LinkCancel.php @@ -29,7 +29,7 @@ protected function renderLink(EntityInterface $entity, ResultRow $values) { $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('Cancel account'); $this->options['alter']['url'] = $entity->urlInfo('cancel-form'); - $this->options['alter']['query'] = drupal_get_destination(); + $this->options['alter']['query'] = $this->getDestinationArray(); return $text; } diff --git a/core/modules/user/src/Plugin/views/field/LinkEdit.php b/core/modules/user/src/Plugin/views/field/LinkEdit.php index bb288631..23a4f5a 100644 --- a/core/modules/user/src/Plugin/views/field/LinkEdit.php +++ b/core/modules/user/src/Plugin/views/field/LinkEdit.php @@ -28,7 +28,7 @@ protected function renderLink(EntityInterface $entity, ResultRow $values) { $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('Edit'); - $this->options['alter']['url'] = $entity->urlInfo('edit-form', ['query' => ['destination' => drupal_get_destination()]]); + $this->options['alter']['url'] = $entity->urlInfo('edit-form', ['query' => ['destination' => $this->getDestinationArray()]]); return $text; } diff --git a/core/modules/user/src/UserListBuilder.php b/core/modules/user/src/UserListBuilder.php index c600016..e6ae82d 100644 --- a/core/modules/user/src/UserListBuilder.php +++ b/core/modules/user/src/UserListBuilder.php @@ -13,6 +13,7 @@ use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\Query\QueryFactory; +use Drupal\Core\Routing\RedirectDestinationInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -37,6 +38,13 @@ class UserListBuilder extends EntityListBuilder { protected $dateFormatter; /** + * The redirect destination service. + * + * @var \Drupal\Core\Routing\RedirectDestinationInterface + */ + protected $redirectDestination; + + /** * Constructs a new UserListBuilder object. * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type @@ -47,11 +55,14 @@ class UserListBuilder extends EntityListBuilder { * The entity query factory. * @param \Drupal\Core\Datetime\DateFormatter $date_formatter * The date formatter service. + * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination + * The redirect destination service. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, QueryFactory $query_factory, DateFormatter $date_formatter) { + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, QueryFactory $query_factory, DateFormatter $date_formatter, RedirectDestinationInterface $redirect_destination) { parent::__construct($entity_type, $storage); $this->queryFactory = $query_factory; $this->dateFormatter = $date_formatter; + $this->redirectDestination = $redirect_destination; } /** @@ -62,7 +73,8 @@ public static function createInstance(ContainerInterface $container, EntityTypeI $entity_type, $container->get('entity.manager')->getStorage($entity_type->id()), $container->get('entity.query'), - $container->get('date.formatter') + $container->get('date.formatter'), + $container->get('redirect.destination') ); } @@ -152,7 +164,7 @@ public function buildRow(EntityInterface $entity) { public function getOperations(EntityInterface $entity) { $operations = parent::getOperations($entity); if (isset($operations['edit'])) { - $destination = drupal_get_destination(); + $destination = $this->redirectDestination->getAsArray(); $operations['edit']['query'] = $destination; } return $operations; diff --git a/core/modules/user/user.api.php b/core/modules/user/user.api.php index 928a56a..74469f3 100644 --- a/core/modules/user/user.api.php +++ b/core/modules/user/user.api.php @@ -136,7 +136,7 @@ function hook_user_login($account) { $config = \Drupal::config('system.date'); // If the user has a NULL time zone, notify them to set a time zone. if (!$account->getTimezone() && $config->get('timezone.user.configurable') && $config->get('timezone.user.warn')) { - drupal_set_message(t('Configure your account time zone setting.', array('@user-edit' => $account->url('edit-form', array('query' => drupal_get_destination(), 'fragment' => 'edit-timezone'))))); + drupal_set_message(t('Configure your account time zone setting.', array('@user-edit' => $account->url('edit-form', array('query' => \Drupal::destination()->getAsArray(), 'fragment' => 'edit-timezone'))))); } } diff --git a/core/modules/views/src/Controller/ViewAjaxController.php b/core/modules/views/src/Controller/ViewAjaxController.php index 43e41e0..bd5f956 100644 --- a/core/modules/views/src/Controller/ViewAjaxController.php +++ b/core/modules/views/src/Controller/ViewAjaxController.php @@ -157,7 +157,7 @@ public function ajaxView(Request $request) { $request->query->replace($request_all + $query_all); // Overwrite the destination. - // @see drupal_get_destination() + // @see the redirect.destination service. $origin_destination = $path; $query = UrlHelper::buildQuery($request->query->all()); if ($query != '') { diff --git a/core/modules/views/src/Plugin/views/field/EntityOperations.php b/core/modules/views/src/Plugin/views/field/EntityOperations.php index 3b9128c..35fbfc3 100644 --- a/core/modules/views/src/Plugin/views/field/EntityOperations.php +++ b/core/modules/views/src/Plugin/views/field/EntityOperations.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Routing\RedirectDestinationTrait; use Drupal\views\ResultRow; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -21,6 +22,8 @@ */ class EntityOperations extends FieldPluginBase { + use RedirectDestinationTrait; + /** * The entity manager. * @@ -102,7 +105,7 @@ public function render(ResultRow $values) { if (!isset($operation['query'])) { $operation['query'] = array(); } - $operation['query'] += drupal_get_destination(); + $operation['query'] += $this->getDestinationArray(); } } $build = array( diff --git a/core/modules/views/src/Plugin/views/field/Links.php b/core/modules/views/src/Plugin/views/field/Links.php index 1953c56..93c2081 100644 --- a/core/modules/views/src/Plugin/views/field/Links.php +++ b/core/modules/views/src/Plugin/views/field/Links.php @@ -89,7 +89,7 @@ protected function getLinks() { 'title' => $title, ); if (!empty($this->options['destination'])) { - $links[$field]['query'] = drupal_get_destination(); + $links[$field]['query'] = \Drupal::destination()->getAsArray(); } } diff --git a/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php b/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php index 8f64a62..e3c6699 100644 --- a/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php +++ b/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php @@ -323,12 +323,3 @@ protected function assertViewResultCommand(ViewAjaxResponse $response, $position } -namespace { - // @todo Remove once drupal_get_destination is converted to autoloadable code. - if (!function_exists('drupal_static')) { - function &drupal_static($key) { - return $key; - } - } - -} diff --git a/core/modules/views/tests/src/Unit/Plugin/views/field/EntityOperationsUnitTest.php b/core/modules/views/tests/src/Unit/Plugin/views/field/EntityOperationsUnitTest.php index e8eee20..28bd2da 100644 --- a/core/modules/views/tests/src/Unit/Plugin/views/field/EntityOperationsUnitTest.php +++ b/core/modules/views/tests/src/Unit/Plugin/views/field/EntityOperationsUnitTest.php @@ -8,7 +8,6 @@ namespace Drupal\Tests\views\Unit\Plugin\views\field { use Drupal\Tests\UnitTestCase; -use Drupal\views\Plugin\views\field\EntityOperations; use Drupal\views\ResultRow; /** @@ -27,7 +26,7 @@ class EntityOperationsUnitTest extends UnitTestCase { /** * The plugin under test. * - * @var \Drupal\views\Plugin\views\field\EntityOperations + * @var \Drupal\views\Plugin\views\field\EntityOperations|\PHPUnit_Framework_MockObject_MockObject */ protected $plugin; @@ -44,7 +43,15 @@ public function setUp() { $plugin_definition = array( 'title' => $this->randomMachineName(), ); - $this->plugin = new EntityOperations($configuration, $plugin_id, $plugin_definition, $this->entityManager); + + $this->plugin = $this->getMockBuilder('Drupal\views\Plugin\views\field\EntityOperations') + ->setConstructorArgs([$configuration, $plugin_id, $plugin_definition, $this->entityManager]) + ->setMethods(array('getDestinationArray')) + ->getMock(); + $this->plugin->expects($this->any()) + ->method('getDestinationArray') + ->willReturn(['destination' => 'foobar']); + $view = $this->getMockBuilder('\Drupal\views\ViewExecutable') ->disableOriginalConstructor() ->getMock(); @@ -108,7 +115,7 @@ public function testRenderWithDestination() { '#type' => 'operations', '#links' => $operations ); - $expected_build['#links']['foo']['query'] = drupal_get_destination(); + $expected_build['#links']['foo']['query'] = ['destination' => 'foobar']; $build = $this->plugin->render($result); $this->assertSame($expected_build, $build); } @@ -156,15 +163,3 @@ public function testRenderWithoutDestination() { } } - -namespace { - -if (!function_exists('drupal_get_destination')) { - function drupal_get_destination() { - return array( - 'destination' => 'foobar', - ); - } -} - -} diff --git a/core/tests/Drupal/Tests/Core/EventSubscriber/CustomPageExceptionHtmlSubscriberTest.php b/core/tests/Drupal/Tests/Core/EventSubscriber/CustomPageExceptionHtmlSubscriberTest.php index 5b73c85..ffb2a21 100644 --- a/core/tests/Drupal/Tests/Core/EventSubscriber/CustomPageExceptionHtmlSubscriberTest.php +++ b/core/tests/Drupal/Tests/Core/EventSubscriber/CustomPageExceptionHtmlSubscriberTest.php @@ -65,6 +65,13 @@ class CustomPageExceptionHtmlSubscriberTest extends UnitTestCase { protected $customPageSubscriber; /** + * The mocked redirect.destination service. + * + * @var \Drupal\Core\Routing\RedirectDestinationInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $redirectDestination; + + /** * {@inheritdoc} */ protected function setUp() { @@ -73,7 +80,13 @@ protected function setUp() { $this->aliasManager = $this->getMock('Drupal\Core\Path\AliasManagerInterface'); $this->kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $this->logger = $this->getMock('Psr\Log\LoggerInterface'); - $this->customPageSubscriber = new TestCustomPageExceptionHtmlSubscriber($this->configFactory, $this->aliasManager, $this->kernel, $this->logger); + $this->redirectDestination = $this->getMock('\Drupal\Core\Routing\RedirectDestinationInterface'); + + $this->redirectDestination->expects($this->any()) + ->method('getAsArray') + ->willReturn(['destination' => 'test']); + + $this->customPageSubscriber = new CustomPageExceptionHtmlSubscriber($this->configFactory, $this->aliasManager, $this->kernel, $this->logger, $this->redirectDestination); // You can't create an exception in PHP without throwing it. Store the // current error_log, and disable it temporarily. @@ -139,13 +152,3 @@ public function testHandleWithGetRequest() { } -class TestCustomPageExceptionHtmlSubscriber extends CustomPageExceptionHtmlSubscriber { - - /** - * {@inheritdoc} - */ - protected function drupalGetDestination() { - return ['destination' => 'test']; - } - -}