comparison core/modules/views/src/Controller/ViewAjaxController.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children c2387f117808
comparison
equal deleted inserted replaced
-1:000000000000 0:4c8ae668cc8c
1 <?php
2
3 namespace Drupal\views\Controller;
4
5 use Drupal\Component\Utility\UrlHelper;
6 use Drupal\Core\Ajax\ReplaceCommand;
7 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
8 use Drupal\Core\Entity\EntityStorageInterface;
9 use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
10 use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
11 use Drupal\Core\Form\FormBuilderInterface;
12 use Drupal\Core\Path\CurrentPathStack;
13 use Drupal\Core\Render\BubbleableMetadata;
14 use Drupal\Core\Render\RenderContext;
15 use Drupal\Core\Render\RendererInterface;
16 use Drupal\Core\Routing\RedirectDestinationInterface;
17 use Drupal\views\Ajax\ScrollTopCommand;
18 use Drupal\views\Ajax\ViewAjaxResponse;
19 use Drupal\views\ViewExecutableFactory;
20 use Symfony\Component\DependencyInjection\ContainerInterface;
21 use Symfony\Component\HttpFoundation\Request;
22 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
23 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
24
25 /**
26 * Defines a controller to load a view via AJAX.
27 */
28 class ViewAjaxController implements ContainerInjectionInterface {
29
30 /**
31 * The entity storage for views.
32 *
33 * @var \Drupal\Core\Entity\EntityStorageInterface
34 */
35 protected $storage;
36
37 /**
38 * The factory to load a view executable with.
39 *
40 * @var \Drupal\views\ViewExecutableFactory
41 */
42 protected $executableFactory;
43
44 /**
45 * The renderer.
46 *
47 * @var \Drupal\Core\Render\RendererInterface
48 */
49 protected $renderer;
50
51 /**
52 * The current path.
53 *
54 * @var \Drupal\Core\Path\CurrentPathStack
55 */
56 protected $currentPath;
57
58 /**
59 * The redirect destination.
60 *
61 * @var \Drupal\Core\Routing\RedirectDestinationInterface
62 */
63 protected $redirectDestination;
64
65 /**
66 * Constructs a ViewAjaxController object.
67 *
68 * @param \Drupal\Core\Entity\EntityStorageInterface $storage
69 * The entity storage for views.
70 * @param \Drupal\views\ViewExecutableFactory $executable_factory
71 * The factory to load a view executable with.
72 * @param \Drupal\Core\Render\RendererInterface $renderer
73 * The renderer.
74 * @param \Drupal\Core\Path\CurrentPathStack $current_path
75 * The current path.
76 * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination
77 * The redirect destination.
78 */
79 public function __construct(EntityStorageInterface $storage, ViewExecutableFactory $executable_factory, RendererInterface $renderer, CurrentPathStack $current_path, RedirectDestinationInterface $redirect_destination) {
80 $this->storage = $storage;
81 $this->executableFactory = $executable_factory;
82 $this->renderer = $renderer;
83 $this->currentPath = $current_path;
84 $this->redirectDestination = $redirect_destination;
85 }
86
87 /**
88 * {@inheritdoc}
89 */
90 public static function create(ContainerInterface $container) {
91 return new static(
92 $container->get('entity.manager')->getStorage('view'),
93 $container->get('views.executable'),
94 $container->get('renderer'),
95 $container->get('path.current'),
96 $container->get('redirect.destination')
97 );
98 }
99
100 /**
101 * Loads and renders a view via AJAX.
102 *
103 * @param \Symfony\Component\HttpFoundation\Request $request
104 * The current request object.
105 *
106 * @return \Drupal\views\Ajax\ViewAjaxResponse
107 * The view response as ajax response.
108 *
109 * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
110 * Thrown when the view was not found.
111 */
112 public function ajaxView(Request $request) {
113 $name = $request->request->get('view_name');
114 $display_id = $request->request->get('view_display_id');
115 if (isset($name) && isset($display_id)) {
116 $args = $request->request->get('view_args');
117 $args = isset($args) && $args !== '' ? explode('/', $args) : [];
118
119 // Arguments can be empty, make sure they are passed on as NULL so that
120 // argument validation is not triggered.
121 $args = array_map(function ($arg) {
122 return ($arg == '' ? NULL : $arg);
123 }, $args);
124
125 $path = $request->request->get('view_path');
126 $dom_id = $request->request->get('view_dom_id');
127 $dom_id = isset($dom_id) ? preg_replace('/[^a-zA-Z0-9_-]+/', '-', $dom_id) : NULL;
128 $pager_element = $request->request->get('pager_element');
129 $pager_element = isset($pager_element) ? intval($pager_element) : NULL;
130
131 $response = new ViewAjaxResponse();
132
133 // Remove all of this stuff from the query of the request so it doesn't
134 // end up in pagers and tablesort URLs.
135 foreach (['view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER] as $key) {
136 $request->query->remove($key);
137 $request->request->remove($key);
138 }
139
140 // Load the view.
141 if (!$entity = $this->storage->load($name)) {
142 throw new NotFoundHttpException();
143 }
144 $view = $this->executableFactory->get($entity);
145 if ($view && $view->access($display_id) && $view->setDisplay($display_id) && $view->display_handler->ajaxEnabled()) {
146 $response->setView($view);
147 // Fix the current path for paging.
148 if (!empty($path)) {
149 $this->currentPath->setPath('/' . $path, $request);
150 }
151
152 // Add all POST data, because AJAX is always a post and many things,
153 // such as tablesorts, exposed filters and paging assume GET.
154 $request_all = $request->request->all();
155 $query_all = $request->query->all();
156 $request->query->replace($request_all + $query_all);
157
158 // Overwrite the destination.
159 // @see the redirect.destination service.
160 $origin_destination = $path;
161
162 // Remove some special parameters you never want to have part of the
163 // destination query.
164 $used_query_parameters = $request->query->all();
165 // @todo Remove this parsing once these are removed from the request in
166 // https://www.drupal.org/node/2504709.
167 unset($used_query_parameters[FormBuilderInterface::AJAX_FORM_REQUEST], $used_query_parameters[MainContentViewSubscriber::WRAPPER_FORMAT], $used_query_parameters['ajax_page_state']);
168
169 $query = UrlHelper::buildQuery($used_query_parameters);
170 if ($query != '') {
171 $origin_destination .= '?' . $query;
172 }
173 $this->redirectDestination->set($origin_destination);
174
175 // Override the display's pager_element with the one actually used.
176 if (isset($pager_element)) {
177 $response->addCommand(new ScrollTopCommand(".js-view-dom-id-$dom_id"));
178 $view->displayHandlers->get($display_id)->setOption('pager_element', $pager_element);
179 }
180 // Reuse the same DOM id so it matches that in drupalSettings.
181 $view->dom_id = $dom_id;
182
183 $context = new RenderContext();
184 $preview = $this->renderer->executeInRenderContext($context, function () use ($view, $display_id, $args) {
185 return $view->preview($display_id, $args);
186 });
187 if (!$context->isEmpty()) {
188 $bubbleable_metadata = $context->pop();
189 BubbleableMetadata::createFromRenderArray($preview)
190 ->merge($bubbleable_metadata)
191 ->applyTo($preview);
192 }
193 $response->addCommand(new ReplaceCommand(".js-view-dom-id-$dom_id", $preview));
194
195 return $response;
196 }
197 else {
198 throw new AccessDeniedHttpException();
199 }
200 }
201 else {
202 throw new NotFoundHttpException();
203 }
204 }
205
206 }