Mercurial > hg > cmmr2012-drupal-site
comparison core/modules/media_library/src/MediaLibraryUiBuilder.php @ 5:12f9dff5fda9 tip
Update to Drupal core 8.7.1
author | Chris Cannam |
---|---|
date | Thu, 09 May 2019 15:34:47 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
4:a9cd425dd02b | 5:12f9dff5fda9 |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\media_library; | |
4 | |
5 use Drupal\Core\Access\AccessResult; | |
6 use Drupal\Core\Form\FormBuilderInterface; | |
7 use Drupal\Core\Form\FormState; | |
8 use Drupal\Core\Entity\EntityTypeManagerInterface; | |
9 use Drupal\Core\Session\AccountInterface; | |
10 use Drupal\Core\StringTranslation\StringTranslationTrait; | |
11 use Drupal\Core\Url; | |
12 use Drupal\views\ViewExecutableFactory; | |
13 use Symfony\Component\HttpFoundation\RequestStack; | |
14 use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; | |
15 | |
16 /** | |
17 * Service which builds the media library. | |
18 * | |
19 * @internal | |
20 * Media Library is an experimental module and its internal code may be | |
21 * subject to change in minor releases. External code should not instantiate | |
22 * or extend this class. | |
23 */ | |
24 class MediaLibraryUiBuilder { | |
25 | |
26 use StringTranslationTrait; | |
27 | |
28 /** | |
29 * The form builder. | |
30 * | |
31 * @var \Drupal\Core\Form\FormBuilderInterface | |
32 */ | |
33 protected $formBuilder; | |
34 | |
35 /** | |
36 * The entity type manager. | |
37 * | |
38 * @var \Drupal\Core\Entity\EntityTypeManagerInterface | |
39 */ | |
40 protected $entityTypeManager; | |
41 | |
42 /** | |
43 * The currently active request object. | |
44 * | |
45 * @var \Symfony\Component\HttpFoundation\Request | |
46 */ | |
47 protected $request; | |
48 | |
49 /** | |
50 * The views executable factory. | |
51 * | |
52 * @var \Drupal\views\ViewExecutableFactory | |
53 */ | |
54 protected $viewsExecutableFactory; | |
55 | |
56 /** | |
57 * Constructs a MediaLibraryUiBuilder instance. | |
58 * | |
59 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager | |
60 * The entity type manager. | |
61 * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack | |
62 * The request stack. | |
63 * @param \Drupal\views\ViewExecutableFactory $views_executable_factory | |
64 * The views executable factory. | |
65 * @param \Drupal\Core\Form\FormBuilderInterface $form_builder | |
66 * The currently active request object. | |
67 */ | |
68 public function __construct(EntityTypeManagerInterface $entity_type_manager, RequestStack $request_stack, ViewExecutableFactory $views_executable_factory, FormBuilderInterface $form_builder) { | |
69 $this->entityTypeManager = $entity_type_manager; | |
70 $this->request = $request_stack->getCurrentRequest(); | |
71 $this->viewsExecutableFactory = $views_executable_factory; | |
72 $this->formBuilder = $form_builder; | |
73 } | |
74 | |
75 /** | |
76 * Get media library dialog options. | |
77 * | |
78 * @return array | |
79 * The media library dialog options. | |
80 */ | |
81 public static function dialogOptions() { | |
82 return [ | |
83 'dialogClass' => 'media-library-widget-modal', | |
84 'title' => t('Add or select media'), | |
85 'height' => '75%', | |
86 'width' => '75%', | |
87 ]; | |
88 } | |
89 | |
90 /** | |
91 * Build the media library UI. | |
92 * | |
93 * @param \Drupal\media_library\MediaLibraryState $state | |
94 * (optional) The current state of the media library, derived from the | |
95 * current request. | |
96 * | |
97 * @return array | |
98 * The render array for the media library. | |
99 */ | |
100 public function buildUi(MediaLibraryState $state = NULL) { | |
101 if (!$state) { | |
102 $state = MediaLibraryState::fromRequest($this->request); | |
103 } | |
104 // When navigating to a media type through the vertical tabs, we only want | |
105 // to load the changed library content. This is not only more efficient, but | |
106 // also provides a more accessible user experience for screen readers. | |
107 if ($state->get('media_library_content') === '1') { | |
108 return $this->buildLibraryContent($state); | |
109 } | |
110 else { | |
111 return [ | |
112 '#type' => 'html_tag', | |
113 '#tag' => 'div', | |
114 '#attributes' => [ | |
115 'id' => 'media-library-wrapper', | |
116 'class' => ['media-library-wrapper'], | |
117 ], | |
118 'menu' => $this->buildMediaTypeMenu($state), | |
119 'content' => $this->buildLibraryContent($state), | |
120 // Attach the JavaScript for the media library UI. The number of | |
121 // available slots needs to be added to make sure users can't select | |
122 // more items than allowed. | |
123 '#attached' => [ | |
124 'library' => ['media_library/ui'], | |
125 'drupalSettings' => [ | |
126 'media_library' => [ | |
127 'selection_remaining' => $state->getAvailableSlots(), | |
128 ], | |
129 ], | |
130 ], | |
131 ]; | |
132 } | |
133 } | |
134 | |
135 /** | |
136 * Build the media library content area. | |
137 * | |
138 * @param \Drupal\media_library\MediaLibraryState $state | |
139 * The current state of the media library, derived from the current request. | |
140 * | |
141 * @return array | |
142 * The render array for the media library. | |
143 */ | |
144 protected function buildLibraryContent(MediaLibraryState $state) { | |
145 return [ | |
146 '#type' => 'html_tag', | |
147 '#tag' => 'div', | |
148 '#attributes' => [ | |
149 'id' => 'media-library-content', | |
150 'class' => ['media-library-content'], | |
151 'tabindex' => -1, | |
152 ], | |
153 'form' => $this->buildMediaTypeAddForm($state), | |
154 'view' => $this->buildMediaLibraryView($state), | |
155 ]; | |
156 } | |
157 | |
158 /** | |
159 * Check access to the media library. | |
160 * | |
161 * @param \Drupal\Core\Session\AccountInterface $account | |
162 * (optional) Run access checks for this account. | |
163 * @param \Drupal\media_library\MediaLibraryState $state | |
164 * (optional) The current state of the media library, derived from the | |
165 * current request. | |
166 * | |
167 * @return \Drupal\Core\Access\AccessResult | |
168 * The access result. | |
169 */ | |
170 public function checkAccess(AccountInterface $account = NULL, MediaLibraryState $state = NULL) { | |
171 if (!$state) { | |
172 try { | |
173 MediaLibraryState::fromRequest($this->request); | |
174 } | |
175 catch (BadRequestHttpException $e) { | |
176 return AccessResult::forbidden($e->getMessage()); | |
177 } | |
178 catch (\InvalidArgumentException $e) { | |
179 return AccessResult::forbidden($e->getMessage()); | |
180 } | |
181 } | |
182 // Deny access if the view or display are removed. | |
183 $view = $this->entityTypeManager->getStorage('view')->load('media_library'); | |
184 if (!$view) { | |
185 return AccessResult::forbidden('The media library view does not exist.') | |
186 ->setCacheMaxAge(0); | |
187 } | |
188 if (!$view->getDisplay('widget')) { | |
189 return AccessResult::forbidden('The media library widget display does not exist.') | |
190 ->addCacheableDependency($view); | |
191 } | |
192 return AccessResult::allowedIfHasPermission($account, 'view media') | |
193 ->addCacheableDependency($view); | |
194 } | |
195 | |
196 /** | |
197 * Get the media type menu for the media library. | |
198 * | |
199 * @param \Drupal\media_library\MediaLibraryState $state | |
200 * The current state of the media library, derived from the current request. | |
201 * | |
202 * @return array | |
203 * The render array for the media type menu. | |
204 */ | |
205 protected function buildMediaTypeMenu(MediaLibraryState $state) { | |
206 // Add the menu for each type if we have more than 1 media type enabled for | |
207 // the field. | |
208 $allowed_type_ids = $state->getAllowedTypeIds(); | |
209 if (count($allowed_type_ids) <= 1) { | |
210 return []; | |
211 } | |
212 | |
213 // @todo: Add a class to the li element. | |
214 // https://www.drupal.org/project/drupal/issues/3029227 | |
215 $menu = [ | |
216 '#theme' => 'links', | |
217 '#links' => [], | |
218 '#attributes' => [ | |
219 'class' => ['media-library-menu', 'js-media-library-menu'], | |
220 ], | |
221 ]; | |
222 | |
223 $allowed_types = $this->entityTypeManager->getStorage('media_type')->loadMultiple($allowed_type_ids); | |
224 | |
225 $selected_type_id = $state->getSelectedTypeId(); | |
226 foreach ($allowed_types as $allowed_type_id => $allowed_type) { | |
227 $link_state = MediaLibraryState::create($state->getOpenerId(), $state->getAllowedTypeIds(), $allowed_type_id, $state->getAvailableSlots()); | |
228 // Add the 'media_library_content' parameter so the response will contain | |
229 // only the updated content for the tab. | |
230 // @see self::buildUi() | |
231 $link_state->set('media_library_content', 1); | |
232 | |
233 $title = $allowed_type->label(); | |
234 if ($allowed_type_id === $selected_type_id) { | |
235 $title = [ | |
236 '#markup' => $this->t('@title<span class="active-tab visually-hidden"> (active tab)</span>', ['@title' => $title]), | |
237 ]; | |
238 } | |
239 | |
240 $menu['#links']['media-library-menu-' . $allowed_type_id] = [ | |
241 'title' => $title, | |
242 'url' => Url::fromRoute('media_library.ui', [], [ | |
243 'query' => $link_state->all(), | |
244 ]), | |
245 'attributes' => [ | |
246 'class' => ['media-library-menu__link'], | |
247 ], | |
248 ]; | |
249 } | |
250 | |
251 // Set the active menu item. | |
252 $menu['#links']['media-library-menu-' . $selected_type_id]['attributes']['class'][] = 'active'; | |
253 | |
254 return $menu; | |
255 } | |
256 | |
257 /** | |
258 * Get the add form for the selected media type. | |
259 * | |
260 * @param \Drupal\media_library\MediaLibraryState $state | |
261 * The current state of the media library, derived from the current request. | |
262 * | |
263 * @return array | |
264 * The render array for the media type add form. | |
265 */ | |
266 protected function buildMediaTypeAddForm(MediaLibraryState $state) { | |
267 $selected_type_id = $state->getSelectedTypeId(); | |
268 | |
269 if (!$this->entityTypeManager->getAccessControlHandler('media')->createAccess($selected_type_id)) { | |
270 return []; | |
271 } | |
272 | |
273 $selected_type = $this->entityTypeManager->getStorage('media_type')->load($selected_type_id); | |
274 $plugin_definition = $selected_type->getSource()->getPluginDefinition(); | |
275 | |
276 if (empty($plugin_definition['forms']['media_library_add'])) { | |
277 return []; | |
278 } | |
279 | |
280 // After the form to add new media is submitted, we need to rebuild the | |
281 // media library with a new instance of the media add form. The form API | |
282 // allows us to do that by forcing empty user input. | |
283 // @see \Drupal\Core\Form\FormBuilder::doBuildForm() | |
284 $form_state = new FormState(); | |
285 if ($state->get('_media_library_form_rebuild')) { | |
286 $form_state->setUserInput([]); | |
287 $state->remove('_media_library_form_rebuild'); | |
288 } | |
289 $form_state->set('media_library_state', $state); | |
290 return $this->formBuilder->buildForm($plugin_definition['forms']['media_library_add'], $form_state); | |
291 } | |
292 | |
293 /** | |
294 * Get the media library view. | |
295 * | |
296 * @param \Drupal\media_library\MediaLibraryState $state | |
297 * The current state of the media library, derived from the current request. | |
298 * | |
299 * @return array | |
300 * The render array for the media library view. | |
301 */ | |
302 protected function buildMediaLibraryView(MediaLibraryState $state) { | |
303 // @todo Make the view configurable in | |
304 // https://www.drupal.org/project/drupal/issues/2971209 | |
305 $view = $this->entityTypeManager->getStorage('view')->load('media_library'); | |
306 $view_executable = $this->viewsExecutableFactory->get($view); | |
307 $display_id = 'widget'; | |
308 | |
309 // Make sure the state parameters are set in the request so the view can | |
310 // pass the parameters along in the pager, filters etc. | |
311 $view_request = $view_executable->getRequest(); | |
312 $view_request->query->add($state->all()); | |
313 $view_executable->setRequest($view_request); | |
314 | |
315 $args = [$state->getSelectedTypeId()]; | |
316 | |
317 // Make sure the state parameters are set in the request so the view can | |
318 // pass the parameters along in the pager, filters etc. | |
319 $request = $view_executable->getRequest(); | |
320 $request->query->add($state->all()); | |
321 $view_executable->setRequest($request); | |
322 | |
323 $view_executable->setDisplay($display_id); | |
324 $view_executable->preExecute($args); | |
325 $view_executable->execute($display_id); | |
326 | |
327 return $view_executable->buildRenderable($display_id, $args, FALSE); | |
328 } | |
329 | |
330 } |