Mercurial > hg > cmmr2012-drupal-site
comparison core/modules/media_library/media_library.module @ 5:12f9dff5fda9 tip
Update to Drupal core 8.7.1
author | Chris Cannam |
---|---|
date | Thu, 09 May 2019 15:34:47 +0100 |
parents | a9cd425dd02b |
children |
comparison
equal
deleted
inserted
replaced
4:a9cd425dd02b | 5:12f9dff5fda9 |
---|---|
4 * @file | 4 * @file |
5 * Contains hook implementations for the media_library module. | 5 * Contains hook implementations for the media_library module. |
6 */ | 6 */ |
7 | 7 |
8 use Drupal\Component\Utility\UrlHelper; | 8 use Drupal\Component\Utility\UrlHelper; |
9 use Drupal\Component\Serialization\Json; | 9 use Drupal\Core\Access\AccessResult; |
10 use Drupal\Core\Entity\EntityInterface; | |
11 use Drupal\Core\Entity\Entity\EntityFormDisplay; | |
12 use Drupal\Core\Entity\Entity\EntityViewDisplay; | |
10 use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; | 13 use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; |
11 use Drupal\Core\Form\FormStateInterface; | 14 use Drupal\Core\Form\FormStateInterface; |
12 use Drupal\Core\Render\Element; | 15 use Drupal\Core\Render\Element; |
13 use Drupal\Core\Routing\RouteMatchInterface; | 16 use Drupal\Core\Routing\RouteMatchInterface; |
17 use Drupal\Core\Session\AccountInterface; | |
14 use Drupal\Core\Template\Attribute; | 18 use Drupal\Core\Template\Attribute; |
15 use Drupal\Core\Url; | 19 use Drupal\image\Entity\ImageStyle; |
20 use Drupal\image\Plugin\Field\FieldType\ImageItem; | |
21 use Drupal\media\MediaTypeForm; | |
22 use Drupal\media\MediaTypeInterface; | |
23 use Drupal\media_library\Form\FileUploadForm; | |
24 use Drupal\media_library\Form\OEmbedForm; | |
25 use Drupal\media_library\MediaLibraryState; | |
16 use Drupal\views\Form\ViewsForm; | 26 use Drupal\views\Form\ViewsForm; |
17 use Drupal\views\Plugin\views\cache\CachePluginBase; | 27 use Drupal\views\Plugin\views\cache\CachePluginBase; |
18 use Drupal\views\Plugin\views\query\QueryPluginBase; | |
19 use Drupal\views\Plugin\views\query\Sql; | |
20 use Drupal\views\ViewExecutable; | 28 use Drupal\views\ViewExecutable; |
21 | 29 |
22 /** | 30 /** |
23 * Implements hook_help(). | 31 * Implements hook_help(). |
24 * | 32 * |
32 return $output; | 40 return $output; |
33 } | 41 } |
34 } | 42 } |
35 | 43 |
36 /** | 44 /** |
45 * Implements hook_media_source_info_alter(). | |
46 */ | |
47 function media_library_media_source_info_alter(array &$sources) { | |
48 $sources['audio_file']['forms']['media_library_add'] = FileUploadForm::class; | |
49 $sources['file']['forms']['media_library_add'] = FileUploadForm::class; | |
50 $sources['image']['forms']['media_library_add'] = FileUploadForm::class; | |
51 $sources['video_file']['forms']['media_library_add'] = FileUploadForm::class; | |
52 $sources['oembed:video']['forms']['media_library_add'] = OEmbedForm::class; | |
53 } | |
54 | |
55 /** | |
37 * Implements hook_theme(). | 56 * Implements hook_theme(). |
38 */ | 57 */ |
39 function media_library_theme() { | 58 function media_library_theme() { |
40 return [ | 59 return [ |
41 'media__media_library' => [ | 60 'media__media_library' => [ |
43 ], | 62 ], |
44 ]; | 63 ]; |
45 } | 64 } |
46 | 65 |
47 /** | 66 /** |
48 * Implements hook_preprocess_view(). | |
49 * | |
50 * Adds a link to add media above the view. | |
51 */ | |
52 function media_library_preprocess_views_view(&$variables) { | |
53 $view = $variables['view']; | |
54 if ($view->id() === 'media_library' && $view->current_display === 'widget') { | |
55 $url = Url::fromRoute('media_library.upload'); | |
56 if ($url->access()) { | |
57 $url->setOption('query', \Drupal::request()->query->all()); | |
58 $variables['header']['add_media'] = [ | |
59 '#type' => 'link', | |
60 '#title' => t('Add media'), | |
61 '#url' => $url, | |
62 '#attributes' => [ | |
63 'class' => ['button', 'button-action', 'button--primary', 'use-ajax'], | |
64 'data-dialog-type' => 'modal', | |
65 'data-dialog-options' => Json::encode([ | |
66 'dialogClass' => 'media-library-widget-modal', | |
67 'height' => '75%', | |
68 'width' => '75%', | |
69 'title' => t('Add media'), | |
70 ]), | |
71 ], | |
72 ]; | |
73 } | |
74 } | |
75 } | |
76 | |
77 /** | |
78 * Implements hook_views_post_render(). | 67 * Implements hook_views_post_render(). |
79 */ | 68 */ |
80 function media_library_views_post_render(ViewExecutable $view, &$output, CachePluginBase $cache) { | 69 function media_library_views_post_render(ViewExecutable $view, &$output, CachePluginBase $cache) { |
81 if ($view->id() === 'media_library') { | 70 if ($view->id() === 'media_library') { |
82 $output['#attached']['library'][] = 'media_library/view'; | 71 $output['#attached']['library'][] = 'media_library/view'; |
83 if ($view->current_display === 'widget') { | 72 if (strpos($view->current_display, 'widget') === 0) { |
84 $query = array_intersect_key(\Drupal::request()->query->all(), array_flip([ | 73 $query = MediaLibraryState::fromRequest($view->getRequest())->all(); |
85 'media_library_widget_id', | |
86 'media_library_allowed_types', | |
87 'media_library_remaining', | |
88 ])); | |
89 // If the current query contains any parameters we use to contextually | 74 // If the current query contains any parameters we use to contextually |
90 // filter the view, ensure they persist across AJAX rebuilds. | 75 // filter the view, ensure they persist across AJAX rebuilds. |
91 // The ajax_path is shared for all AJAX views on the page, but our query | 76 // The ajax_path is shared for all AJAX views on the page, but our query |
92 // parameters are prefixed and should not interfere with any other views. | 77 // parameters are prefixed and should not interfere with any other views. |
93 // @todo Rework or remove this in https://www.drupal.org/node/2983451 | 78 // @todo Rework or remove this in https://www.drupal.org/node/2983451 |
94 if (!empty($query)) { | 79 if (!empty($query)) { |
95 $ajax_path = &$output['#attached']['drupalSettings']['views']['ajax_path']; | 80 $ajax_path = &$output['#attached']['drupalSettings']['views']['ajax_path']; |
96 $parsed_url = UrlHelper::parse($ajax_path); | 81 $parsed_url = UrlHelper::parse($ajax_path); |
97 $query = array_merge($query, $parsed_url['query']); | 82 $query = array_merge($query, $parsed_url['query']); |
98 $ajax_path = $parsed_url['path'] . '?' . UrlHelper::buildQuery($query); | 83 $ajax_path = $parsed_url['path'] . '?' . UrlHelper::buildQuery($query); |
99 if (isset($query['media_library_remaining'])) { | |
100 $output['#attached']['drupalSettings']['media_library']['selection_remaining'] = (int) $query['media_library_remaining']; | |
101 } | |
102 } | 84 } |
103 } | 85 } |
104 } | 86 } |
105 } | 87 } |
106 | 88 |
161 $form['header']['media_bulk_form']['#attributes']['class'][] = 'media-library-views-form__bulk_form'; | 143 $form['header']['media_bulk_form']['#attributes']['class'][] = 'media-library-views-form__bulk_form'; |
162 } | 144 } |
163 } | 145 } |
164 | 146 |
165 // Add after build to fix media library views exposed filter's submit button. | 147 // Add after build to fix media library views exposed filter's submit button. |
166 if ($form_id === 'views_exposed_form' && $form['#id'] === 'views-exposed-form-media-library-widget') { | 148 if ($form_id === 'views_exposed_form' && strpos($form['#id'], 'views-exposed-form-media-library-widget') === 0) { |
167 $form['#after_build'][] = '_media_library_views_form_media_library_after_build'; | 149 $form['#after_build'][] = '_media_library_views_form_media_library_after_build'; |
150 } | |
151 | |
152 // Configures media_library displays when a type is submitted. | |
153 if ($form_object instanceof MediaTypeForm) { | |
154 $form['actions']['submit']['#submit'][] = '_media_library_media_type_form_submit'; | |
168 } | 155 } |
169 } | 156 } |
170 | 157 |
171 /** | 158 /** |
172 * After build callback for views form media library. | 159 * After build callback for views form media library. |
185 $form['actions']['#attributes']['class'][] = 'media-library-view--form-actions'; | 172 $form['actions']['#attributes']['class'][] = 'media-library-view--form-actions'; |
186 return $form; | 173 return $form; |
187 } | 174 } |
188 | 175 |
189 /** | 176 /** |
190 * Implements hook_views_query_alter(). | 177 * Submit callback for media type form. |
191 * | 178 */ |
192 * Alters the widget view's query to only show media that can be selected, | 179 function _media_library_media_type_form_submit(array &$form, FormStateInterface $form_state) { |
193 * based on what types are allowed in the field settings. | 180 $form_object = $form_state->getFormObject(); |
194 * | 181 if ($form_object->getOperation() === 'add') { |
195 * @todo Remove in https://www.drupal.org/node/2983454 | 182 $type = $form_object->getEntity(); |
196 */ | 183 $form_display_created = _media_library_configure_form_display($type); |
197 function media_library_views_query_alter(ViewExecutable $view, QueryPluginBase $query) { | 184 $view_display_created = _media_library_configure_view_display($type); |
198 if ($query instanceof Sql && $view->id() === 'media_library' && $view->current_display === 'widget') { | 185 if ($form_display_created || $view_display_created) { |
199 $types = _media_library_get_allowed_types(); | 186 \Drupal::messenger()->addStatus(t('Media Library form and view displays have been created for the %type media type.', [ |
200 if ($types) { | 187 '%type' => $type->label(), |
201 $entity_type = \Drupal::entityTypeManager()->getDefinition('media'); | 188 ])); |
202 $group = $query->setWhereGroup(); | |
203 $query->addWhere($group, $entity_type->getDataTable() . '.' . $entity_type->getKey('bundle'), $types, 'in'); | |
204 } | |
205 } | |
206 } | |
207 | |
208 /** | |
209 * Implements hook_form_FORM_ID_alter(). | |
210 * | |
211 * Limits the types available in the exposed filter to avoid users trying to | |
212 * filter by a type that is un-selectable. | |
213 * | |
214 * @see media_library_views_query_alter() | |
215 * | |
216 * @todo Remove in https://www.drupal.org/node/2983454 | |
217 */ | |
218 function media_library_form_views_exposed_form_alter(array &$form, FormStateInterface $form_state) { | |
219 if (isset($form['#id']) && $form['#id'] === 'views-exposed-form-media-library-widget') { | |
220 $types = _media_library_get_allowed_types(); | |
221 if ($types && isset($form['type']['#options'])) { | |
222 $keys = array_flip($types); | |
223 // Ensure that the default value (by default "All") persists. | |
224 if (isset($form['type']['#default_value'])) { | |
225 $keys[$form['type']['#default_value']] = TRUE; | |
226 } | |
227 $form['type']['#options'] = array_intersect_key($form['type']['#options'], $keys); | |
228 } | 189 } |
229 } | 190 } |
230 } | 191 } |
231 | 192 |
232 /** | 193 /** |
259 } | 220 } |
260 } | 221 } |
261 } | 222 } |
262 | 223 |
263 /** | 224 /** |
264 * Determines what types are allowed based on the current request. | 225 * Implements hook_ENTITY_TYPE_access(). |
265 * | 226 */ |
266 * @return array | 227 function media_library_image_style_access(EntityInterface $entity, $operation, AccountInterface $account) { |
267 * An array of allowed types. | 228 // Prevent the fallback 'media_library' image style from being deleted. |
268 */ | 229 // @todo: Lock the image style instead of preventing delete access. |
269 function _media_library_get_allowed_types() { | 230 // https://www.drupal.org/project/drupal/issues/2247293 |
270 $types = \Drupal::request()->query->get('media_library_allowed_types'); | 231 if ($operation === 'delete' && $entity->id() === 'media_library') { |
271 if ($types && is_array($types)) { | 232 return AccessResult::forbidden(); |
272 return array_filter($types, 'is_string'); | 233 } |
273 } | 234 } |
274 return []; | 235 |
275 } | 236 /** |
237 * Ensures that the given media type has a media_library form display. | |
238 * | |
239 * @param \Drupal\media\MediaTypeInterface $type | |
240 * The media type to configure. | |
241 * | |
242 * @return bool | |
243 * Whether a form display has been created or not. | |
244 * | |
245 * @throws \Drupal\Core\Entity\EntityStorageException | |
246 */ | |
247 function _media_library_configure_form_display(MediaTypeInterface $type) { | |
248 $display = EntityFormDisplay::load('media.' . $type->id() . '.media_library'); | |
249 | |
250 if ($display) { | |
251 return FALSE; | |
252 } | |
253 | |
254 $values = [ | |
255 'targetEntityType' => 'media', | |
256 'bundle' => $type->id(), | |
257 'mode' => 'media_library', | |
258 'status' => TRUE, | |
259 ]; | |
260 $display = EntityFormDisplay::create($values); | |
261 // Remove all default components. | |
262 foreach (array_keys($display->getComponents()) as $name) { | |
263 $display->removeComponent($name); | |
264 } | |
265 // Expose the name field when it is not mapped. | |
266 $field_map = $type->getFieldMap(); | |
267 if (empty($field_map['name'])) { | |
268 $display->setComponent('name', [ | |
269 'type' => 'string_textfield', | |
270 'settings' => [ | |
271 'size' => 60, | |
272 ], | |
273 ]); | |
274 } | |
275 // If the source field is an image field, expose it so that users can set alt | |
276 // and title text. | |
277 $source_field = $type->getSource()->getSourceFieldDefinition($type); | |
278 if ($source_field->isDisplayConfigurable('form') && is_a($source_field->getItemDefinition()->getClass(), ImageItem::class, TRUE)) { | |
279 $type->getSource()->prepareFormDisplay($type, $display); | |
280 } | |
281 return (bool) $display->save(); | |
282 } | |
283 | |
284 /** | |
285 * Ensures that the given media type has a media_library view display. | |
286 * | |
287 * @param \Drupal\media\MediaTypeInterface $type | |
288 * The media type to configure. | |
289 * | |
290 * @return bool | |
291 * Whether a view display has been created or not. | |
292 * | |
293 * @throws \Drupal\Core\Entity\EntityStorageException | |
294 */ | |
295 function _media_library_configure_view_display(MediaTypeInterface $type) { | |
296 $display = EntityViewDisplay::load('media.' . $type->id() . '.media_library'); | |
297 | |
298 if ($display) { | |
299 return FALSE; | |
300 } | |
301 | |
302 $values = [ | |
303 'targetEntityType' => 'media', | |
304 'bundle' => $type->id(), | |
305 'mode' => 'media_library', | |
306 'status' => TRUE, | |
307 ]; | |
308 $display = EntityViewDisplay::create($values); | |
309 // Remove all default components. | |
310 foreach (array_keys($display->getComponents()) as $name) { | |
311 $display->removeComponent($name); | |
312 } | |
313 | |
314 // @todo: Remove dependency on 'medium' and 'thumbnail' image styles from | |
315 // media and media library modules. | |
316 // https://www.drupal.org/project/drupal/issues/3030437 | |
317 $image_style = ImageStyle::load('medium'); | |
318 | |
319 // Expose the thumbnail component. If the medium image style doesn't exist, | |
320 // use the fallback 'media_library' image style. | |
321 $display->setComponent('thumbnail', [ | |
322 'type' => 'image', | |
323 'label' => 'hidden', | |
324 'settings' => [ | |
325 'image_style' => $image_style ? $image_style->id() : 'media_library', | |
326 'image_link' => '', | |
327 ], | |
328 ]); | |
329 return (bool) $display->save(); | |
330 } |