Updated all the contrib modules to their latest versions.
[yaffs-website] / web / modules / contrib / blazy / src / Dejavu / BlazyVideoTrait.php
1 <?php
2
3 namespace Drupal\blazy\Dejavu;
4
5 use Drupal\Core\Url;
6 use Drupal\file\Entity\File;
7 use Drupal\blazy\BlazyMedia;
8
9 /**
10  * A Trait common for optional Media Entity and Video Embed Media integration.
11  *
12  * The basic idea is to display videos along with images even within core Image,
13  * and to re-associate VEF/ME video thumbnails beyond their own entity display.
14  * For editors, use Slick Browser, or Blazy Views field.
15  * For client-side, Blazy Views field, BlazyFileFormatter, SlickFileFormatter.
16  * Why bother? This addresses a mix of images/videos beyond field formatters
17  * or when ME and VEM integration is optional.
18  *
19  * For more robust VEM/ME integration, use Slick Media instead.
20  *
21  * @see Drupal\blazy\Plugin\views\field\BlazyViewsFieldPluginBase
22  * @see Drupal\slick_browser\SlickBrowser::widgetEntityBrowserFileFormAlter()
23  * @see Drupal\slick_browser\Plugin\EntityBrowser\FieldWidgetDisplay\...
24  */
25 trait BlazyVideoTrait {
26
27   /**
28    * Returns the image factory.
29    */
30   public function imageFactory() {
31     return \Drupal::service('image.factory');
32   }
33
34   /**
35    * Returns the optional VEF service to avoid dependency for optional plugins.
36    */
37   public static function videoEmbedMediaManager() {
38     if (function_exists('video_embed_field_theme')) {
39       return \Drupal::service('video_embed_field.provider_manager');
40     }
41     return FALSE;
42   }
43
44   /**
45    * Builds relevant video embed field settings based on the given media url.
46    *
47    * @param array $settings
48    *   An array of settings to be passed into theme_blazy().
49    * @param string $external_url
50    *   A video URL.
51    */
52   public function buildVideo(array &$settings = [], $external_url = '') {
53     /** @var \Drupal\video_embed_field\ProviderManagerInterface $video */
54     if (!($video = self::videoEmbedMediaManager())) {
55       return;
56     }
57
58     if (!($provider = $video->loadProviderFromInput($external_url))) {
59       return;
60     }
61
62     // Ensures thumbnail is available.
63     $provider->downloadThumbnail();
64
65     // @todo extract URL from the SRC of final rendered TWIG instead.
66     $render    = $provider->renderEmbedCode(640, 360, '0');
67     $old_url   = isset($render['#attributes']) && isset($render['#attributes']['src']) ? $render['#attributes']['src'] : '';
68     $embed_url = isset($render['#url']) ? $render['#url'] : $old_url;
69     $query     = isset($render['#query']) ? $render['#query'] : [];
70
71     // Prevents complication with multiple videos by now.
72     unset($query['autoplay'], $query['auto_play']);
73
74     $settings['video_id']  = $provider::getIdFromInput($external_url);
75     $settings['embed_url'] = Url::fromUri($embed_url, ['query' => $query])->toString();
76     $settings['scheme']    = $video->loadDefinitionFromInput($external_url)['id'];
77     $settings['uri']       = $provider->getLocalThumbnailUri();
78     $settings['type']      = 'video';
79
80     // Adds autoplay for media URL on lightboxes, saving another click.
81     $url = $settings['embed_url'];
82     if (strpos($url, 'autoplay') === FALSE || strpos($url, 'autoplay=0') !== FALSE) {
83       $settings['autoplay_url'] = strpos($url, '?') === FALSE ? $url . '?autoplay=1' : $url . '&autoplay=1';
84     }
85
86     // Only applies when Image style is empty, no file API, no $item,
87     // with unmanaged VEF image without image_style.
88     // Prevents 404 warning when video thumbnail missing for a reason.
89     if (empty($settings['image_style'])) {
90       if ($data = @getimagesize($settings['uri'])) {
91         list($settings['width'], $settings['height']) = $data;
92       }
93     }
94   }
95
96   /**
97    * Gets the faked image item out of file entity, or ER, if applicable.
98    *
99    * @param object $file
100    *   The expected file entity, or ER, to get image item from.
101    *
102    * @return array
103    *   The array of image item and settings if a file image, else empty.
104    */
105   public function getImageItem($file) {
106     $data = [];
107     $entity = $file;
108
109     /** @var Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem $file */
110     if (isset($file->entity) && !isset($file->alt)) {
111       $entity = $file->entity;
112     }
113
114     if (!$entity instanceof File) {
115       return $data;
116     }
117
118     /** @var \Drupal\file\Entity\File $entity */
119     list($type,) = explode('/', $entity->getMimeType(), 2);
120     $uri = $entity->getFileUri();
121
122     if ($type == 'image' && ($image = $this->imageFactory()->get($uri)) && $image->isValid()) {
123       $item            = new \stdClass();
124       $item->target_id = $entity->id();
125       $item->width     = $image->getWidth();
126       $item->height    = $image->getHeight();
127       $item->alt       = $entity->getFilename();
128       $item->title     = $entity->getFilename();
129       $item->uri       = $uri;
130       $settings        = (array) $item;
131       $item->entity    = $entity;
132
133       $settings['type'] = 'image';
134
135       // Build item and settings.
136       $data['item']     = $item;
137       $data['settings'] = $settings;
138       unset($item);
139     }
140
141     return $data;
142   }
143
144   /**
145    * Gets the Media item thumbnail, or re-associate the file entity to ME.
146    *
147    * @param array $data
148    *   An array of data containing settings, and potential video thumbnail item.
149    * @param object $entity
150    *   The media entity, else file entity to be associated to media, if any.
151    */
152   public function getMediaItem(array &$data = [], $entity = NULL) {
153     $settings = $data['settings'];
154
155     $media = $entity;
156     // Core File stores Media thumbnails, re-associate it to Media entity.
157     // @todo: If any proper method to get video URL from image URI, or FID.
158     if ($entity->getEntityTypeId() == 'file' && !empty($settings['uri']) && strpos($settings['uri'], 'video_thumbnails') !== FALSE) {
159       if ($media_id = \Drupal::entityQuery('media')->condition('thumbnail.target_id', $entity->id())->execute()) {
160         $media_id = reset($media_id);
161
162         /** @var \Drupal\media_entity\Entity\Media $entity */
163         $media = $this->blazyManager()->getEntityTypeManager()->getStorage('media')->load($media_id);
164       }
165     }
166
167     // Only proceed if we do have ME.
168     if ($media->getEntityTypeId() != 'media') {
169       return;
170     }
171
172     $bundle = $media->bundle();
173     $fields = $media->getFields();
174     $config = method_exists($media, 'getSource') ? $media->getSource()->getConfiguration() : $media->getType()->getConfiguration();
175     $source = isset($config['source_url_field']) ? $config['source_url_field'] : '';
176
177     $source_field[$bundle]    = isset($config['source_field']) ? $config['source_field'] : $source;
178     $settings['bundle']       = $bundle;
179     $settings['source_field'] = $source_field[$bundle];
180     $settings['media_url']    = $media->url();
181     $settings['media_id']     = $media->id();
182     $settings['view_mode']    = empty($settings['view_mode']) ? 'default' : $settings['view_mode'];
183
184     // If Media entity has a defined thumbnail, add it to data item.
185     if (isset($fields['thumbnail'])) {
186       $data['item'] = $fields['thumbnail']->get(0);
187       $settings['file_tags'] = ['file:' . $data['item']->target_id];
188
189       // Provides thumbnail URI for EB selection with various Media entities.
190       if (empty($settings['uri'])) {
191         $settings['uri'] = File::load($data['item']->target_id)->getFileUri();
192       }
193     }
194
195     $source = empty($settings['source_field']) ? '' : $settings['source_field'];
196     if ($source && isset($media->{$source})) {
197       $value     = $media->{$source}->getValue();
198       $input_url = isset($value[0]['uri']) ? $value[0]['uri'] : (isset($value[0]['value']) ? $value[0]['value'] : '');
199       $input_url = strip_tags($input_url);
200
201       if ($input_url) {
202         $settings['input_url'] = $input_url;
203
204         // Soundcloud has different source_field name: source_url_field.
205         if (strpos($input_url, 'soundcloud') === FALSE) {
206           $this->buildVideo($settings, $input_url);
207         }
208       }
209       elseif (isset($value[0]['alt'])) {
210         $settings['type'] = 'image';
211       }
212
213       // Do not proceed if it has type, already managed by theme_blazy().
214       // Supports other Media entities: Facebook, Instagram, Twitter, etc.
215       if (empty($settings['type'])) {
216         if ($build = BlazyMedia::build($media, $settings)) {
217           $data['content'][] = $build;
218         }
219       }
220     }
221
222     $data['settings'] = $settings;
223   }
224
225 }