/** * {@inheritdoc} */ public function getOptions(RouteMatchInterface $route_match) { $options = parent::getOptions($route_match); // Append the current path as destination to the query string. $options['query']['destination'] = $this->redirectDestination->get(); return $options; }
/** * Redirects on 403 Access Denied kernel exceptions. * * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event * The Event to process. */ public function onKernelException(GetResponseEvent $event) { $exception = $event->getException(); if (!$exception instanceof AccessDeniedHttpException) { return; } $config = $this->configFactory->get('r4032login.settings'); $options = array(); $options['query'] = $this->redirectDestination->getAsArray(); $options['absolute'] = TRUE; $code = $config->get('default_redirect_code'); if ($this->currentUser->isAnonymous()) { // Show custom access denied message if set. if ($config->get('display_denied_message')) { $message = $config->get('access_denied_message'); $message_type = $config->get('access_denied_message_type'); drupal_set_message(Xss::filterAdmin($message), $message_type); } // Handle redirection to the login form. $login_route = $config->get('user_login_route'); $url = Url::fromRoute($login_route, array(), $options)->toString(); $response = new RedirectResponse($url, $code); $event->setResponse($response); } else { // Check to see if we are to redirect the user. $redirect = $config->get('redirect_authenticated_users_to'); if ($redirect) { // Custom access denied page for logged in users. $url = Url::fromUserInput($redirect, $options)->toString(); $response = new RedirectResponse($url, $code); $event->setResponse($response); } } }
/** * {@inheritdoc} */ protected function setUp() { $this->configFactory = $this->getConfigFactoryStub(['system.site' => ['page.403' => 'access-denied-page', 'page.404' => 'not-found-page']]); $this->aliasManager = $this->getMock('Drupal\\Core\\Path\\AliasManagerInterface'); $this->kernel = $this->getMock('Symfony\\Component\\HttpKernel\\HttpKernelInterface'); $this->logger = $this->getMock('Psr\\Log\\LoggerInterface'); $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. $this->errorLog = ini_set('error_log', file_exists('/dev/null') ? '/dev/null' : 'nul'); }
/** * @covers ::getDefaultOperations */ public function testGetDefaultOperationsWithAccess() { $method = new \ReflectionMethod($this->sut, 'getDefaultOperations'); $method->setAccessible(TRUE); $url_canonical = new Url($this->randomMachineName()); $url_edit_form = new Url($this->randomMachineName()); $url_delete_form = new Url($this->randomMachineName()); $url_update_status_form = new Url($this->randomMachineName()); $url_capture_form = new Url($this->randomMachineName()); $url_refund_form = new Url($this->randomMachineName()); $url_complete = new Url($this->randomMachineName()); $payment = $this->getMock(PaymentInterface::class); $map = [['view', NULL, FALSE, TRUE], ['update', NULL, FALSE, TRUE], ['delete', NULL, FALSE, TRUE], ['update_status', NULL, FALSE, TRUE], ['capture', NULL, FALSE, TRUE], ['refund', NULL, FALSE, TRUE], ['complete', NULL, FALSE, TRUE]]; $payment->expects($this->atLeast(count($map)))->method('access')->willReturnMap($map); $payment->expects($this->any())->method('hasLinkTemplate')->willReturn(TRUE); $map = [['canonical', [], $url_canonical], ['edit-form', [], $url_edit_form], ['delete-form', [], $url_delete_form], ['update-status-form', [], $url_update_status_form], ['capture-form', [], $url_capture_form], ['refund-form', [], $url_refund_form], ['complete', [], $url_complete]]; $payment->expects($this->atLeast(count($map)))->method('urlInfo')->willReturnMap($map); $destination = $this->randomMachineName(); $this->redirectDestination->expects($this->atLeastOnce())->method('get')->willReturn($destination); $operations = $method->invoke($this->sut, $payment); ksort($operations); $expected_operations = ['view', 'edit', 'delete', 'update_status', 'capture', 'refund', 'complete']; sort($expected_operations); $this->assertSame($expected_operations, array_keys($operations)); foreach ($operations as $name => $operation) { $this->assertInstanceof(TranslatableMarkup::class, $operation['title']); $this->assertInstanceof(Url::class, $operation['url']); if (array_key_exists('weight', $operation)) { $this->assertInternalType('int', $operation['weight']); } } }
/** * Redirects login attempts on already-logged-in session to the destination. */ public function onRespond(FilterResponseEvent $event) { // Return early in most cases. if ($event->getRequest()->getMethod() !== 'POST') { return; } if (!$this->currentUser->isAuthenticated()) { return; } if (!$event->isMasterRequest()) { return; } if (!$event->getRequest()->query->has('destination')) { return; } if ($event->getResponse() instanceof RedirectResponse) { return; } // There has to be a better way to figure out if we landed on the 403/404 page. $page_403 = $this->configFactory->get('system.site')->get('page.403'); $page_404 = $this->configFactory->get('system.site')->get('page.404'); $path = $this->currentPath->getPath(); $route = $this->currentRouteMatch->getRouteName(); if ($route == 'system.403' || $page_403 && $path == $page_403 || $route == 'system.404' || $page_404 && $path == $page_404) { // RedirectResponseSubscriber will convert to absolute URL for us. $event->setResponse(new RedirectResponse($this->redirectDestination->get(), RedirectResponse::HTTP_SEE_OTHER)); } }
/** * {@inheritdoc} */ public function getOperations(EntityInterface $entity) { $operations = parent::getOperations($entity); if (isset($operations['edit'])) { $destination = $this->redirectDestination->getAsArray(); $operations['edit']['query'] = $destination; } return $operations; }
/** * {@inheritdoc} */ protected function getDefaultOperations(EntityInterface $entity) { $operations = parent::getDefaultOperations($entity); $destination = $this->redirectDestination->getAsArray(); foreach ($operations as $key => $operation) { $operations[$key]['query'] = $destination; } return $operations; }
/** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = NULL) { $this->data['version'] = Drupal::VERSION; $this->data['profile'] = drupal_get_profile(); $this->data['config_url'] = (new Drupal\Core\Url('webprofiler.settings', [], ['query' => $this->redirectDestination->getAsArray()]))->toString(); try { $process = new Process("git log -1 --pretty=format:'%H - %s (%ci)' --abbrev-commit"); $process->setTimeout(3600); $process->mustRun(); $this->data['git_commit'] = $process->getOutput(); $process = new Process("git log -1 --pretty=format:'%h' --abbrev-commit"); $process->setTimeout(3600); $process->mustRun(); $this->data['abbr_git_commit'] = $process->getOutput(); } catch (ProcessFailedException $e) { $this->data['git_commit'] = $this->data['git_commit_abbr'] = NULL; } }
/** * {@inheritdoc} */ public function build() { $build = parent::build(); $active_theme = $this->themeManager->getActiveTheme(); $theme_name = $active_theme->getName(); $destination = $this->redirectDestination->get(); $visible_regions = $this->getVisibleRegionNames($theme_name); // Build an array of the region names in the right order. $build += array_fill_keys(array_keys($visible_regions), []); foreach ($visible_regions as $region => $region_name) { $query = ['region' => $region]; if ($destination) { $query['destination'] = $destination; } $title = $this->t('<span class="visually-hidden">Place block in the %region region</span>', ['%region' => $region_name]); $operations['block_description'] = ['#type' => 'inline_template', '#template' => '<div class="block-place-region">{{ link }}</div>', '#context' => ['link' => Link::createFromRoute($title, 'block.admin_library', ['theme' => $theme_name], ['query' => $query, 'attributes' => ['title' => $title, 'class' => ['use-ajax', 'button', 'button--small'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 700])]])]]; $build[$region] = ['block_place_operations' => $operations] + $build[$region]; } $build['#attached']['library'][] = 'block_place/drupal.block_place'; return $build; }
/** * {@inheritdoc} */ protected function setUp() { $this->configFactory = $this->getConfigFactoryStub(['system.site' => ['page.403' => '/access-denied-page', 'page.404' => '/not-found-page']]); $this->kernel = $this->getMock('Symfony\\Component\\HttpKernel\\HttpKernelInterface'); $this->logger = $this->getMock('Psr\\Log\\LoggerInterface'); $this->redirectDestination = $this->getMock('\\Drupal\\Core\\Routing\\RedirectDestinationInterface'); $this->redirectDestination->expects($this->any())->method('getAsArray')->willReturn(['destination' => 'test']); $this->accessUnawareRouter = $this->getMock('Symfony\\Component\\Routing\\Matcher\\UrlMatcherInterface'); $this->accessUnawareRouter->expects($this->any())->method('match')->willReturn(['_controller' => 'mocked']); $this->accessManager = $this->getMock('Drupal\\Core\\Access\\AccessManagerInterface'); $this->accessManager->expects($this->any())->method('checkNamedRoute')->willReturn(AccessResult::allowed()->addCacheTags(['foo', 'bar'])); $this->customPageSubscriber = new CustomPageExceptionHtmlSubscriber($this->configFactory, $this->kernel, $this->logger, $this->redirectDestination, $this->accessUnawareRouter, $this->accessManager); $path_validator = $this->getMock('Drupal\\Core\\Path\\PathValidatorInterface'); $path_validator->expects($this->any())->method('getUrlIfValidWithoutAccessCheck')->willReturn(Url::fromRoute('foo', ['foo' => 'bar'])); $container = new ContainerBuilder(); $container->set('path.validator', $path_validator); \Drupal::setContainer($container); // You can't create an exception in PHP without throwing it. Store the // current error_log, and disable it temporarily. $this->errorLog = ini_set('error_log', file_exists('/dev/null') ? '/dev/null' : 'nul'); }
/** * {@inheritdoc} */ public function getOperations($plugin_id) { $payment_method_configuration_operations = $this->paymentMethodConfigurationListBuilder->getOperations($this->getPaymentMethodConfiguration($plugin_id)); $titles = array('edit' => $this->t('Edit configuration'), 'delete' => $this->t('Delete configuration'), 'enable' => $this->t('Enable configuration'), 'disable' => $this->t('Disable configuration')); $operations = []; foreach ($payment_method_configuration_operations as $name => $payment_method_configuration_operation) { if (array_key_exists($name, $titles)) { $operations[$name] = $payment_method_configuration_operation; $operations[$name]['title'] = $titles[$name]; $operations[$name]['query']['destination'] = $this->redirectDestination->get(); } } return $operations; }
/** * Gets operations for a rule. * * @param \Drupal\rng\RuleInterface $rule * The rule. * * @return array * An array of links suitable for an 'operations' element. */ protected function getOperations(RuleInterface $rule) { $links = []; $destination = $this->redirectDestination->getAsArray(); if ($component = $this->getDateCondition($rule)) { if ($component->access('edit')) { $links['edit-date'] = ['title' => $this->t('Edit date'), 'url' => $component->urlInfo('edit-form'), 'query' => $destination]; } } if ($rule->access('delete')) { $links['delete'] = ['title' => $this->t('Delete'), 'url' => $rule->urlInfo('delete-form'), 'query' => $destination]; } return $links; }
/** * {@inheritdoc} * * @param \Drupal\rng\RuleInterface $entity * A rule entity. */ public function buildRow(EntityInterface $entity) { $row['id'] = $entity->id(); $row['trigger'] = $entity->getTriggerID(); $row['conditions']['data'] = array('#theme' => 'links', '#links' => [], '#attributes' => ['class' => ['links', 'inline']]); foreach ($entity->getConditions() as $condition) { $row['conditions']['data']['#links'][] = array('title' => $this->t('Edit', ['@condition_id' => $condition->id(), '@condition' => $condition->getPluginId()]), 'url' => $condition->urlInfo('edit-form'), 'query' => $this->redirectDestination->getAsArray()); } $row['actions']['data'] = array('#theme' => 'links', '#links' => [], '#attributes' => ['class' => ['links', 'inline']]); foreach ($entity->getActions() as $action) { $row['actions']['data']['#links'][] = array('title' => $this->t('Edit', ['@action_id' => $action->id(), '@action' => $action->getPluginId()]), 'url' => $action->urlInfo('edit-form'), 'query' => $this->redirectDestination->getAsArray()); } $row['status'] = $entity->isActive() ? $this->t('Active') : $this->t('Inactive'); return $row + parent::buildRow($entity); }
/** * {@inheritdoc} */ protected function getDefaultOperations(EntityInterface $entity) { $operations = parent::getDefaultOperations($entity); $operations['edit']['weight'] = 0; if ($entity->access('import') && $entity->hasLinkTemplate('import-form')) { $operations['import'] = ['title' => $this->t('Import'), 'weight' => 2, 'url' => $entity->urlInfo('import-form')]; } if ($entity->access('clear') && $entity->hasLinkTemplate('clear-form')) { $operations['clear'] = ['title' => $this->t('Delete items'), 'weight' => 3, 'url' => $entity->urlInfo('clear-form')]; } $destination = $this->redirectDestination->getAsArray(); foreach ($operations as $key => $operation) { $operations[$key]['query'] = $destination; } return $operations; }
/** * Makes a subrequest to retrieve the default error page. * * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event * The event to process. * @param string $url * The path/url to which to make a subrequest for this error message. * @param int $status_code * The status code for the error being handled. */ protected function makeSubrequest(GetResponseForExceptionEvent $event, $url, $status_code) { $request = $event->getRequest(); $exception = $event->getException(); try { // Reuse the exact same request (so keep the same URL, keep the access // result, the exception, et cetera) but override the routing information. // This means that aside from routing, this is identical to the master // request. This allows us to generate a response that is executed on // behalf of the master request, i.e. for the original URL. This is what // allows us to e.g. generate a 404 response for the original URL; if we // would execute a subrequest with the 404 route's URL, then it'd be // generated for *that* URL, not the *original* URL. $sub_request = clone $request; // The routing to the 404 page should be done as GET request because it is // restricted to GET and POST requests only. Otherwise a DELETE request // would for example trigger a method not allowed exception. $request_context = clone $this->accessUnawareRouter->getContext(); $request_context->setMethod('GET'); $this->accessUnawareRouter->setContext($request_context); $sub_request->attributes->add($this->accessUnawareRouter->match($url)); // Add to query (GET) or request (POST) parameters: // - 'destination' (to ensure e.g. the login form in a 403 response // redirects to the original URL) // - '_exception_statuscode' $parameters = $sub_request->isMethod('GET') ? $sub_request->query : $sub_request->request; $parameters->add($this->redirectDestination->getAsArray() + ['_exception_statuscode' => $status_code]); $response = $this->httpKernel->handle($sub_request, HttpKernelInterface::SUB_REQUEST); // Only 2xx responses should have their status code overridden; any // other status code should be passed on: redirects (3xx), error (5xx)… // @see https://www.drupal.org/node/2603788#comment-10504916 if ($response->isSuccessful()) { $response->setStatusCode($status_code); } // Persist any special HTTP headers that were set on the exception. if ($exception instanceof HttpExceptionInterface) { $response->headers->add($exception->getHeaders()); } $event->setResponse($response); } catch (\Exception $e) { // If an error happened in the subrequest we can't do much else. Instead, // just log it. The DefaultExceptionSubscriber will catch the original // exception and handle it normally. $error = Error::decodeException($e); $this->logger->log($error['severity_level'], '%type: @message in %function (line %line of %file).', $error); } }
/** * @covers ::getOperations */ public function testGetOperations() { $list_builder_operations = ['edit' => ['title' => 'Edit configuration'], 'delete' => ['title' => 'Delete configuration'], 'enable' => ['title' => 'Enable configuration'], 'disable' => ['title' => 'Disable configuration'], 'foo' => []]; $destination = $this->randomMachineName(); $this->redirectDestination->expects($this->atLeastOnce())->method('get')->willReturn($destination); $plugin_id = $this->randomMachineName(); $payment_method_configuration = $this->getMock(PaymentMethodConfigurationInterface::class); $this->sut->expects($this->once())->method('getPaymentMethodConfiguration')->with($plugin_id)->willReturn($payment_method_configuration); $this->paymentMethodConfigurationListBuilder->expects($this->once())->method('getOperations')->with($payment_method_configuration)->willReturn($list_builder_operations); $expected_operations = $list_builder_operations; unset($expected_operations['foo']); foreach ($expected_operations as $name => $expected_operation) { $expected_operations[$name]['title'] = $list_builder_operations[$name]['title']; $expected_operations[$name]['query']['destination'] = $destination; } $this->assertEquals($expected_operations, $this->sut->getOperations($plugin_id)); }
/** * Makes a subrequest to retrieve the default error page. * * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event * The event to process * @param string $url * The path/url to which to make a subrequest for this error message. * @param int $status_code * The status code for the error being handled. */ protected function makeSubrequest(GetResponseForExceptionEvent $event, $url, $status_code) { $request = $event->getRequest(); $exception = $event->getException(); if (!($url && $url[0] == '/')) { $url = $request->getBasePath() . '/' . $url; } $current_url = $request->getBasePath() . $request->getPathInfo(); if ($url != $request->getBasePath() . '/' && $url != $current_url) { if ($request->getMethod() === 'POST') { $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->redirectDestination->getAsArray() + ['_exception_statuscode' => $status_code], $request->cookies->all(), [], $request->server->all()); } try { // Persist the 'exception' attribute to the subrequest. $sub_request->attributes->set('exception', $request->attributes->get('exception')); // Persist the access result attribute to the subrequest, so that the // error page inherits the access result of the master request. $sub_request->attributes->set(AccessAwareRouterInterface::ACCESS_RESULT, $request->attributes->get(AccessAwareRouterInterface::ACCESS_RESULT)); // Carry over the session to the subrequest. if ($session = $request->getSession()) { $sub_request->setSession($session); } $response = $this->httpKernel->handle($sub_request, HttpKernelInterface::SUB_REQUEST); // Only 2xx responses should have their status code overridden; any // other status code should be passed on: redirects (3xx), error (5xx)… // @see https://www.drupal.org/node/2603788#comment-10504916 if ($response->isSuccessful()) { $response->setStatusCode($status_code); } // Persist any special HTTP headers that were set on the exception. if ($exception instanceof HttpExceptionInterface) { $response->headers->add($exception->getHeaders()); } $event->setResponse($response); } catch (\Exception $e) { // If an error happened in the subrequest we can't do much else. Instead, // just log it. The DefaultExceptionSubscriber will catch the original // exception and handle it normally. $error = Error::decodeException($e); $this->logger->log($error['severity_level'], '%type: @message in %function (line %line of %file).', $error); } } }
/** * Tests a valid view without arguments pagers etc. */ public function testAjaxView() { $request = new Request(); $request->request->set('view_name', 'test_view'); $request->request->set('view_display_id', 'page_1'); $request->request->set('view_path', '/test-page'); $request->request->set('_wrapper_format', 'ajax'); $request->request->set('ajax_page_state', 'drupal.settings[]'); $request->request->set('type', 'article'); list($view, $executable) = $this->setupValidMocks(); $display_handler = $this->getMockBuilder('Drupal\\views\\Plugin\\views\\display\\DisplayPluginBase')->disableOriginalConstructor()->getMock(); // Ensure that the pager element is not set. $display_handler->expects($this->never())->method('setOption'); $display_collection = $this->getMockBuilder('Drupal\\views\\DisplayPluginCollection')->disableOriginalConstructor()->getMock(); $display_collection->expects($this->any())->method('get')->with('page_1')->will($this->returnValue($display_handler)); $executable->displayHandlers = $display_collection; $this->redirectDestination->expects($this->atLeastOnce())->method('set')->with('/test-page?type=article'); $response = $this->viewAjaxController->ajaxView($request); $this->assertTrue($response instanceof ViewAjaxResponse); $this->assertSame($response->getView(), $executable); $this->assertViewResultCommand($response); }
/** * Shows a list of blocks that can be added to a theme's layout. * * @param \Symfony\Component\HttpFoundation\Request $request * The current request. * @param string $theme * Theme key of the block list. * * @return array * A render array as expected by the renderer. */ public function listBlocks(Request $request, $theme) { // Since modals do not render any other part of the page, we need to render // them manually as part of this listing. if ($request->query->get(MainContentViewSubscriber::WRAPPER_FORMAT) === 'drupal_modal') { $build['local_actions'] = $this->buildLocalActions(); } $headers = [['data' => $this->t('Block')], ['data' => $this->t('Category')], ['data' => $this->t('Operations')]]; // Only add blocks which work without any available context. $definitions = $this->blockManager->getDefinitionsForContexts($this->contextRepository->getAvailableContexts()); // Order by category, and then by admin label. $definitions = $this->blockManager->getSortedDefinitions($definitions); $region = $request->query->get('region'); $weight = $request->query->get('weight'); $rows = []; foreach ($definitions as $plugin_id => $plugin_definition) { $row = []; $row['title']['data'] = ['#type' => 'inline_template', '#template' => '<div class="block-filter-text-source">{{ label }}</div>', '#context' => ['label' => $plugin_definition['admin_label']]]; $row['category']['data'] = $plugin_definition['category']; $links['add'] = ['title' => $this->t('Place block'), 'url' => Url::fromRoute('block.admin_add', ['plugin_id' => $plugin_id, 'theme' => $theme]), 'attributes' => ['class' => ['use-ajax'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 700])]]; if ($region) { $links['add']['query']['region'] = $region; } if (isset($weight)) { $links['add']['query']['weight'] = $weight; } $destination = $this->redirectDestination->get(); if ($destination) { $links['add']['query']['destination'] = $destination; } $row['operations']['data'] = ['#type' => 'operations', '#links' => $links]; $rows[] = $row; } $build['#attached']['library'][] = 'block/drupal.block.admin'; $build['filter'] = ['#type' => 'search', '#title' => $this->t('Filter'), '#title_display' => 'invisible', '#size' => 30, '#placeholder' => $this->t('Filter by block name'), '#attributes' => ['class' => ['block-filter-text'], 'data-element' => '.block-add-table', 'title' => $this->t('Enter a part of the block name to filter by.')]]; $build['blocks'] = ['#type' => 'table', '#header' => $headers, '#rows' => $rows, '#empty' => $this->t('No blocks available.'), '#attributes' => ['class' => ['block-add-table']]]; return $build; }
/** * {@inheritdoc} */ protected function getDefaultOperations(EntityInterface $entity) { $destination = $this->redirectDestination->get(); $operations = parent::getDefaultOperations($entity); foreach ($operations as &$operation) { $operation['query']['destination'] = $destination; } if ($entity->access('view')) { $operations['view'] = array('title' => $this->t('View'), 'weight' => -10, 'url' => $entity->urlInfo()); } if ($entity->access('update_status')) { $operations['update_status'] = array('title' => $this->t('Update status'), 'attributes' => array('class' => array('use-ajax'), 'data-accepts' => 'application/vnd.drupal-modal'), 'query' => array('destination' => $destination), 'url' => $entity->urlInfo('update-status-form')); } if ($entity->access('capture')) { $operations['capture'] = array('title' => $this->t('Capture'), 'attributes' => array('class' => array('use-ajax'), 'data-accepts' => 'application/vnd.drupal-modal'), 'query' => array('destination' => $destination), 'url' => $entity->urlInfo('capture-form')); } if ($entity->access('refund')) { $operations['refund'] = array('title' => $this->t('Refund'), 'attributes' => array('class' => array('use-ajax'), 'data-accepts' => 'application/vnd.drupal-modal'), 'query' => array('destination' => $destination), 'url' => $entity->urlInfo('refund-form')); } if ($entity->access('complete')) { $operations['complete'] = array('title' => $this->t('Complete'), 'url' => $entity->urlInfo('complete')); } return $operations; }
/** * Loads and renders a view via AJAX. * * @param \Symfony\Component\HttpFoundation\Request $request * The current request object. * * @return \Drupal\views\Ajax\ViewAjaxResponse * The view response as ajax response. * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException * Thrown when the view was not found. */ public function ajaxView(Request $request) { $name = $request->request->get('view_name'); $display_id = $request->request->get('view_display_id'); if (isset($name) && isset($display_id)) { $args = $request->request->get('view_args'); $args = isset($args) && $args !== '' ? explode('/', $args) : array(); // Arguments can be empty, make sure they are passed on as NULL so that // argument validation is not triggered. $args = array_map(function ($arg) { return $arg == '' ? NULL : $arg; }, $args); $path = $request->request->get('view_path'); $dom_id = $request->request->get('view_dom_id'); $dom_id = isset($dom_id) ? preg_replace('/[^a-zA-Z0-9_-]+/', '-', $dom_id) : NULL; $pager_element = $request->request->get('pager_element'); $pager_element = isset($pager_element) ? intval($pager_element) : NULL; $response = new ViewAjaxResponse(); // Remove all of this stuff from the query of the request so it doesn't // end up in pagers and tablesort URLs. foreach (array('view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER) as $key) { $request->query->remove($key); $request->request->remove($key); } // Load the view. if (!($entity = $this->storage->load($name))) { throw new NotFoundHttpException(); } $view = $this->executableFactory->get($entity); if ($view && $view->access($display_id)) { $response->setView($view); // Fix the current path for paging. if (!empty($path)) { $this->currentPath->setPath('/' . $path, $request); } // Add all POST data, because AJAX is always a post and many things, // such as tablesorts, exposed filters and paging assume GET. $request_all = $request->request->all(); $query_all = $request->query->all(); $request->query->replace($request_all + $query_all); // Overwrite the destination. // @see the redirect.destination service. $origin_destination = $path; // Remove some special parameters you never want to have part of the // destination query. $used_query_parameters = $request->query->all(); // @todo Remove this parsing once these are removed from the request in // https://www.drupal.org/node/2504709. unset($used_query_parameters[FormBuilderInterface::AJAX_FORM_REQUEST], $used_query_parameters[MainContentViewSubscriber::WRAPPER_FORMAT], $used_query_parameters['ajax_page_state']); $query = UrlHelper::buildQuery($used_query_parameters); if ($query != '') { $origin_destination .= '?' . $query; } $this->redirectDestination->set($origin_destination); // Override the display's pager_element with the one actually used. if (isset($pager_element)) { $response->addCommand(new ScrollTopCommand(".js-view-dom-id-{$dom_id}")); $view->displayHandlers->get($display_id)->setOption('pager_element', $pager_element); } // Reuse the same DOM id so it matches that in drupalSettings. $view->dom_id = $dom_id; $context = new RenderContext(); $preview = $this->renderer->executeInRenderContext($context, function () use($view, $display_id, $args) { return $view->preview($display_id, $args); }); if (!$context->isEmpty()) { $bubbleable_metadata = $context->pop(); BubbleableMetadata::createFromRenderArray($preview)->merge($bubbleable_metadata)->applyTo($preview); } $response->addCommand(new ReplaceCommand(".js-view-dom-id-{$dom_id}", $preview)); return $response; } else { throw new AccessDeniedHttpException(); } } else { throw new NotFoundHttpException(); } }
/** * {@inheritdoc} */ public function getOperations($plugin_id) { $operations['configure'] = array('title' => $this->t('Configure'), 'query' => $this->redirectDestination->getAsArray(), 'url' => new Url('currency.exchange_rate_provider.fixed_rates.overview')); return $operations; }
/** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = NULL) { $this->data['version'] = Drupal::VERSION; $this->data['profile'] = drupal_get_profile(); $this->data['config_url'] = $this->urlGenerator->generateFromRoute('webprofiler.settings', [], ['query' => $this->redirectDestination->getAsArray()]); }
/** * Loads and renders a view via AJAX. * * @param \Symfony\Component\HttpFoundation\Request $request * The current request object. * * @return \Drupal\views\Ajax\ViewAjaxResponse * The view response as ajax response. * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException * Thrown when the view was not found. */ public function ajaxView(Request $request) { $name = $request->request->get('view_name'); $display_id = $request->request->get('view_display_id'); if (isset($name) && isset($display_id)) { $args = $request->request->get('view_args'); $args = isset($args) && $args !== '' ? explode('/', $args) : array(); // Arguments can be empty, make sure they are passed on as NULL so that // argument validation is not triggered. $args = array_map(function ($arg) { return $arg == '' ? NULL : $arg; }, $args); $path = $request->request->get('view_path'); $dom_id = $request->request->get('view_dom_id'); $dom_id = isset($dom_id) ? preg_replace('/[^a-zA-Z0-9_-]+/', '-', $dom_id) : NULL; $pager_element = $request->request->get('pager_element'); $pager_element = isset($pager_element) ? intval($pager_element) : NULL; $response = new ViewAjaxResponse(); // Remove all of this stuff from the query of the request so it doesn't // end up in pagers and tablesort URLs. foreach (array('view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', 'ajax_html_ids') as $key) { $request->query->remove($key); $request->request->remove($key); } // Load the view. if (!($entity = $this->storage->load($name))) { throw new NotFoundHttpException(); } $view = $this->executableFactory->get($entity); if ($view && $view->access($display_id)) { $response->setView($view); // Fix the current path for paging. if (!empty($path)) { $this->currentPath->setPath('/' . $path, $request); } // Add all POST data, because AJAX is always a post and many things, // such as tablesorts, exposed filters and paging assume GET. $request_all = $request->request->all(); $query_all = $request->query->all(); $request->query->replace($request_all + $query_all); // Overwrite the destination. // @see the redirect.destination service. $origin_destination = $path; $query = UrlHelper::buildQuery($request->query->all()); if ($query != '') { $origin_destination .= '?' . $query; } $this->redirectDestination->set($origin_destination); // Override the display's pager_element with the one actually used. if (isset($pager_element)) { $response->addCommand(new ScrollTopCommand(".view-dom-id-{$dom_id}")); $view->displayHandlers->get($display_id)->setOption('pager_element', $pager_element); } // Reuse the same DOM id so it matches that in drupalSettings. $view->dom_id = $dom_id; if ($preview = $view->preview($display_id, $args)) { $response->addCommand(new ReplaceCommand(".view-dom-id-{$dom_id}", $this->renderer->render($preview))); $response->setAttachments($preview['#attached']); } return $response; } else { throw new AccessDeniedHttpException(); } } else { throw new NotFoundHttpException(); } }
/** * Displays a list of actions which are related to registration access on an * event. * * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The current route. * @param string $event * The parameter to find the event entity. * * @return array * A render array. */ public function listing_access(RouteMatchInterface $route_match, $event) { $event = $route_match->getParameter($event); $destination = $this->redirectDestination->getAsArray(); $event_meta = $this->eventManager->getMeta($event); $trigger = 'rng_event.register'; $build = []; $build['description'] = ['#prefix' => '<p>', '#markup' => $this->t('The following rules determine who is eligible to register or perform an operation on a registration.<br />Access is granted if all conditions for a rule evaluate as true.'), '#suffix' => '</p>']; $rows = []; // Header. $rows[0] = [['header' => TRUE, 'rowspan' => 2, 'data' => $this->t('Rule')], ['header' => TRUE, 'rowspan' => 2, 'data' => $this->t('Component')], ['header' => TRUE, 'rowspan' => 2, 'data' => $this->t('Scope')], ['header' => TRUE, 'rowspan' => 1, 'data' => $this->t('Operations'), 'colspan' => 4]]; if (!$event_meta->isDefaultRules($trigger)) { $rows[0][] = ['header' => TRUE, 'rowspan' => 2, 'data' => '']; } $operations = ['create' => $this->t('Create'), 'view' => $this->t('View'), 'update' => $this->t('Update'), 'delete' => $this->t('Delete')]; foreach ($operations as $operation) { $rows['operations'][] = ['header' => TRUE, 'data' => $operation]; } $i = 0; $rules = $event_meta->getRules($trigger, TRUE); foreach ($rules as $rule) { $i++; $scope_all = FALSE; $supports_create = 0; $condition_context = []; // Conditions. $k = 0; $row = []; $row['rule'] = ['header' => FALSE, 'data' => $this->t('@row.', ['@row' => $i]), 'rowspan' => count($rule->getConditions()) + 1]; foreach ($rule->getConditions() as $condition_storage) { $k++; $row[] = ['header' => TRUE, 'data' => $this->t('Condition #@condition', ['@condition' => $k])]; $condition = $condition_storage->createInstance(); $condition_context += array_keys($condition->getContextDefinitions()); $scope_all = !in_array('registration', $condition_context) || in_array('event', $condition_context); if (isset($row['rule']['rowspan']) && $scope_all) { $row['rule']['rowspan']++; } if ($condition instanceof RNGConditionInterface) { $supports_create++; } $row[] = ['colspan' => 5, 'data' => $condition->summary()]; if (!$event_meta->isDefaultRules($trigger)) { $row['condition_operations']['data'] = ['#type' => 'operations']; if ($condition_storage->access('edit')) { $row['condition_operations']['data']['#links']['edit'] = ['title' => t('Edit'), 'url' => $condition_storage->urlInfo('edit-form'), 'query' => $destination]; } } $rows[] = ['data' => $row, 'no_striping' => TRUE]; $row = []; } // Actions. foreach ($rule->getActions() as $action_storage) { $row = []; $row[] = ['header' => TRUE, 'data' => $this->t('Grants operations'), 'rowspan' => $scope_all ? 2 : 1]; // Scope: warn user actions apply to all registrations. $row[]['data'] = $scope_all ? $this->t('All registrations.') : $this->t('Single registration'); // Operations granted. $config = $action_storage->getConfiguration(); foreach ($operations as $op => $t) { $message = !empty($config['operations'][$op]) ? $t : '-'; $row['operation_' . $op] = ['data' => $op == 'create' && $supports_create != count($rule->getConditions()) ? $this->t('<em>N/A</em>') : $message]; } if (!$event_meta->isDefaultRules($trigger)) { $links = []; if ($action_storage->access('edit')) { $links['edit'] = ['title' => t('Edit'), 'url' => $action_storage->urlInfo('edit-form'), 'query' => $destination]; } $row[] = ['data' => ['#type' => 'operations', '#links' => $links], 'rowspan' => $scope_all ? 2 : 1]; } $rows[] = $row; if ($scope_all) { $rows[] = [['data' => $this->t('<strong>Warning:</strong> selecting view, update, or delete grants access to any registration on this event.'), 'colspan' => 5]]; } } } $build[] = ['#type' => 'table', '#header' => [], '#rows' => $rows, '#empty' => $this->t('No access rules.')]; return $build; }
/** * Provides the Switch user list. */ public function switchUserList() { $list_size = $this->configuration['list_size']; $include_anon = $this->configuration['include_anon']; $anon = new AnonymousUserSession(); $links = array(); if ($this->currentUser->hasPermission('switch users')) { if ($include_anon) { --$list_size; } $dest = $this->redirectDestination->getAsArray(); // Try to find at least $list_size users that can switch. // Inactive users are omitted from all of the following db selects. $roles = user_roles(TRUE, 'switch users'); $query = db_select('users', 'u'); $query->join('users_field_data', 'ufd'); $query->addField('u', 'uid'); $query->addField('ufd', 'access'); $query->distinct(); $query->condition('u.uid', 0, '>'); $query->condition('ufd.status', 0, '>'); $query->orderBy('ufd.access', 'DESC'); $query->range(0, $list_size); if (!isset($roles[DRUPAL_AUTHENTICATED_RID])) { $query->leftJoin('users_roles', 'r', 'u.uid = r.uid'); $or_condition = db_or(); $or_condition->condition('u.uid', 1); if (!empty($roles)) { $or_condition->condition('r.rid', array_keys($roles), 'IN'); } $query->condition($or_condition); } $uids = $query->execute()->fetchCol(); $accounts = user_load_multiple($uids); foreach ($accounts as $account) { $path = 'devel/switch/' . $account->name->value; $links[$account->id()] = array('title' => user_format_name($account), 'href' => $path, 'query' => $dest + array('token' => $this->csrfTokenGenerator->get($path)), 'attributes' => array('title' => t('This user can switch back.')), 'html' => TRUE, 'last_access' => $account->access->value); } $num_links = count($links); if ($num_links < $list_size) { // If we don't have enough, add distinct uids until we hit $list_size. $uids = db_query_range('SELECT u.uid FROM {users} u INNER JOIN {users_field_data} ufd WHERE u.uid > 0 AND u.uid NOT IN (:uids) AND ufd.status > 0 ORDER BY ufd.access DESC', 0, $list_size - $num_links, array(':uids' => array_keys($links)))->fetchCol(); $accounts = user_load_multiple($uids); foreach ($accounts as $account) { $path = 'devel/switch/' . $account->name->value; $links[$account->id()] = array('title' => user_format_name($account), 'href' => $path, 'query' => $dest + array('token' => $this->csrfTokenGenerator->get($path)), 'attributes' => array('title' => t('Caution: this user will be unable to switch back.')), 'last_access' => $account->access->value); } uasort($links, '_devel_switch_user_list_cmp'); } if ($include_anon) { $path = 'devel/switch'; $link = array('title' => $anon->getUsername(), 'href' => $path, 'query' => $dest + array('token' => $this->csrfTokenGenerator->get($path)), 'attributes' => array('title' => t('Caution: the anonymous user will be unable to switch back.'))); if ($this->currentUser->hasPermission('switch users')) { $link['title'] = SafeMarkup::placeholder($link['title']); $link['attributes'] = array('title' => t('This user can switch back.')); $link['html'] = TRUE; } $links[$anon->id()] = $link; } } if (array_key_exists($uid = $this->currentUser->id(), $links)) { $links[$uid]['title'] = '<strong>' . $links[$uid]['title'] . '</strong>'; } return $links; }