Mercurial > hg > isophonics-drupal-site
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 } |