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 }