1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
/* |
6
|
|
|
* This file is part of the Sonata Project package. |
7
|
|
|
* |
8
|
|
|
* (c) Thomas Rabaix <[email protected]> |
9
|
|
|
* |
10
|
|
|
* For the full copyright and license information, please view the LICENSE |
11
|
|
|
* file that was distributed with this source code. |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
namespace Sonata\MediaBundle\Provider; |
15
|
|
|
|
16
|
|
|
use Buzz\Browser; |
17
|
|
|
use Gaufrette\Filesystem; |
18
|
|
|
use Sonata\MediaBundle\CDN\CDNInterface; |
19
|
|
|
use Sonata\MediaBundle\Generator\GeneratorInterface; |
20
|
|
|
use Sonata\MediaBundle\Metadata\MetadataBuilderInterface; |
21
|
|
|
use Sonata\MediaBundle\Model\MediaInterface; |
22
|
|
|
use Sonata\MediaBundle\Thumbnail\ThumbnailInterface; |
23
|
|
|
use Symfony\Component\HttpFoundation\RedirectResponse; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @final since sonata-project/media-bundle 3.21.0 |
27
|
|
|
*/ |
28
|
|
|
class YouTubeProvider extends BaseVideoProvider |
29
|
|
|
{ |
30
|
|
|
/** |
31
|
|
|
* @var bool |
32
|
|
|
*/ |
33
|
|
|
protected $html5; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @param string $name |
37
|
|
|
* @param MetadataBuilderInterface $metadata |
38
|
|
|
* @param bool $html5 |
39
|
|
|
*/ |
40
|
|
|
public function __construct($name, Filesystem $filesystem, CDNInterface $cdn, GeneratorInterface $pathGenerator, ThumbnailInterface $thumbnail, Browser $browser, ?MetadataBuilderInterface $metadata = null, $html5 = false) |
41
|
|
|
{ |
42
|
|
|
parent::__construct($name, $filesystem, $cdn, $pathGenerator, $thumbnail, $browser, $metadata); |
43
|
|
|
$this->html5 = $html5; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
public function getProviderMetadata() |
47
|
|
|
{ |
48
|
|
|
return new Metadata( |
49
|
|
|
$this->getName(), |
50
|
|
|
$this->getName().'.description', |
51
|
|
|
null, |
52
|
|
|
'SonataMediaBundle', |
53
|
|
|
['class' => 'fa fa-youtube'] |
54
|
|
|
); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
public function getHelperProperties(MediaInterface $media, $format, $options = []) |
58
|
|
|
{ |
59
|
|
|
// Override html5 value if $options['html5'] is a boolean |
60
|
|
|
if (!isset($options['html5'])) { |
61
|
|
|
$options['html5'] = $this->html5; |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
// documentation : http://code.google.com/apis/youtube/player_parameters.html |
65
|
|
|
|
66
|
|
|
$default_player_url_parameters = [ |
67
|
|
|
//Values: 0 or 1. Default is 1. Sets whether the player should load related |
68
|
|
|
// videos once playback of the initial video starts. Related videos are |
69
|
|
|
// displayed in the "genie menu" when the menu button is pressed. The player |
70
|
|
|
// search functionality will be disabled if rel is set to 0. |
71
|
|
|
'rel' => 0, |
72
|
|
|
|
73
|
|
|
// Values: 0 or 1. Default is 0. Sets whether or not the initial video will autoplay |
74
|
|
|
// when the player loads. |
75
|
|
|
'autoplay' => 0, |
76
|
|
|
|
77
|
|
|
// Values: 0 or 1. Default is 0. In the case of a single video player, a setting of 1 |
78
|
|
|
// will cause the player to play the initial video again and again. In the case of a |
79
|
|
|
// playlist player (or custom player), the player will play the entire playlist and |
80
|
|
|
// then start again at the first video. |
81
|
|
|
'loop' => 0, |
82
|
|
|
|
83
|
|
|
// Values: 0 or 1. Default is 0. Setting this to 1 will enable the Javascript API. |
84
|
|
|
// For more information on the Javascript API and how to use it, see the JavaScript |
85
|
|
|
// API documentation. |
86
|
|
|
'enablejsapi' => 0, |
87
|
|
|
|
88
|
|
|
// Value can be any alphanumeric string. This setting is used in conjunction with the |
89
|
|
|
// JavaScript API. See the JavaScript API documentation for details. |
90
|
|
|
'playerapiid' => null, |
91
|
|
|
|
92
|
|
|
// Values: 0 or 1. Default is 0. Setting to 1 will disable the player keyboard controls. |
93
|
|
|
// Keyboard controls are as follows: |
94
|
|
|
// Spacebar: Play / Pause |
95
|
|
|
// Arrow Left: Jump back 10% in the current video |
96
|
|
|
// Arrow Right: Jump ahead 10% in the current video |
97
|
|
|
// Arrow Up: Volume up |
98
|
|
|
// Arrow Down: Volume Down |
99
|
|
|
'disablekb' => 0, |
100
|
|
|
|
101
|
|
|
// Values: 0 or 1. Default is 0. Setting to 1 enables the "Enhanced Genie Menu". This |
102
|
|
|
// behavior causes the genie menu (if present) to appear when the user's mouse enters |
103
|
|
|
// the video display area, as opposed to only appearing when the menu button is pressed. |
104
|
|
|
'egm' => 0, |
105
|
|
|
|
106
|
|
|
// Values: 0 or 1. Default is 0. Setting to 1 enables a border around the entire video |
107
|
|
|
// player. The border's primary color can be set via the color1 parameter, and a |
108
|
|
|
// secondary color can be set by the color2 parameter. |
109
|
|
|
'border' => 0, |
110
|
|
|
|
111
|
|
|
// Values: Any RGB value in hexadecimal format. color1 is the primary border color, and |
112
|
|
|
// color2 is the video control bar background color and secondary border color. |
113
|
|
|
'color1' => null, |
114
|
|
|
'color2' => null, |
115
|
|
|
|
116
|
|
|
// Values: 0 or 1. Default is 0. Setting to 1 enables the fullscreen button. This has no |
117
|
|
|
// effect on the Chromeless Player. Note that you must include some extra arguments to |
118
|
|
|
// your embed code for this to work. |
119
|
|
|
'fs' => 1, |
120
|
|
|
|
121
|
|
|
// Values: A positive integer. This parameter causes the player to begin playing the video |
122
|
|
|
// at the given number of seconds from the start of the video. Note that similar to the |
123
|
|
|
// seekTo function, the player will look for the closest keyframe to the time you specify. |
124
|
|
|
// This means sometimes the play head may seek to just before the requested time, usually |
125
|
|
|
// no more than ~2 seconds |
126
|
|
|
'start' => 0, |
127
|
|
|
|
128
|
|
|
// Values: 0 or 1. Default is 0. Setting to 1 enables HD playback by default. This has no |
129
|
|
|
// effect on the Chromeless Player. This also has no effect if an HD version of the video |
130
|
|
|
// is not available. If you enable this option, keep in mind that users with a slower |
131
|
|
|
// connection may have an sub-optimal experience unless they turn off HD. You should ensure |
132
|
|
|
// your player is large enough to display the video in its native resolution. |
133
|
|
|
'hd' => 1, |
134
|
|
|
|
135
|
|
|
// Values: 0 or 1. Default is 1. Setting to 0 disables the search box from displaying when |
136
|
|
|
// the video is minimized. Note that if the rel parameter is set to 0 then the search box |
137
|
|
|
// will also be disabled, regardless of the value of showsearch. |
138
|
|
|
'showsearch' => 0, |
139
|
|
|
|
140
|
|
|
// Values: 0 or 1. Default is 1. Setting to 0 causes the player to not display information |
141
|
|
|
// like the video title and rating before the video starts playing. |
142
|
|
|
'showinfo' => 0, |
143
|
|
|
|
144
|
|
|
// Values: 1 or 3. Default is 1. Setting to 1 will cause video annotations to be shown by |
145
|
|
|
// default, whereas setting to 3 will cause video annotation to not be shown by default. |
146
|
|
|
'iv_load_policy' => 1, |
147
|
|
|
|
148
|
|
|
// Values: 1. Default is based on user preference. Setting to 1 will cause closed captions |
149
|
|
|
// to be shown by default, even if the user has turned captions off. |
150
|
|
|
'cc_load_policy' => 1, |
151
|
|
|
|
152
|
|
|
// Values: 'window' or 'opaque' or 'transparent'. |
153
|
|
|
// When wmode=window, the Flash movie is not rendered in the page. |
154
|
|
|
// When wmode=opaque, the Flash movie is rendered as part of the page. |
155
|
|
|
// When wmode=transparent, the Flash movie is rendered as part of the page. |
156
|
|
|
'wmode' => 'window', |
157
|
|
|
]; |
158
|
|
|
|
159
|
|
|
$default_player_parameters = [ |
160
|
|
|
// Values: 0 or 1. Default is 0. Setting to 1 enables a border around the entire video |
161
|
|
|
// player. The border's primary color can be set via the color1 parameter, and a |
162
|
|
|
// secondary color can be set by the color2 parameter. |
163
|
|
|
'border' => $default_player_url_parameters['border'], |
164
|
|
|
|
165
|
|
|
// Values: 'allowfullscreen' or empty. Default is 'allowfullscreen'. Setting to empty value disables |
166
|
|
|
// the fullscreen button. |
167
|
|
|
'allowFullScreen' => '1' === $default_player_url_parameters['fs'] ? true : false, |
|
|
|
|
168
|
|
|
|
169
|
|
|
// The allowScriptAccess parameter in the code is needed to allow the player SWF to call |
170
|
|
|
// functions on the containing HTML page, since the player is hosted on a different domain |
171
|
|
|
// from the HTML page. |
172
|
|
|
'allowScriptAccess' => $options['allowScriptAccess'] ?? 'always', |
173
|
|
|
|
174
|
|
|
// Values: 'window' or 'opaque' or 'transparent'. |
175
|
|
|
// When wmode=window, the Flash movie is not rendered in the page. |
176
|
|
|
// When wmode=opaque, the Flash movie is rendered as part of the page. |
177
|
|
|
// When wmode=transparent, the Flash movie is rendered as part of the page. |
178
|
|
|
'wmode' => $default_player_url_parameters['wmode'], |
179
|
|
|
]; |
180
|
|
|
|
181
|
|
|
$player_url_parameters = array_merge($default_player_url_parameters, $options['player_url_parameters'] ?? []); |
182
|
|
|
|
183
|
|
|
$box = $this->getBoxHelperProperties($media, $format, $options); |
184
|
|
|
|
185
|
|
|
$player_parameters = array_merge($default_player_parameters, $options['player_parameters'] ?? [], [ |
186
|
|
|
'width' => $box->getWidth(), |
187
|
|
|
'height' => $box->getHeight(), |
188
|
|
|
]); |
189
|
|
|
|
190
|
|
|
$params = [ |
191
|
|
|
'html5' => $options['html5'], |
192
|
|
|
'player_url_parameters' => http_build_query($player_url_parameters), |
193
|
|
|
'player_parameters' => $player_parameters, |
194
|
|
|
]; |
195
|
|
|
|
196
|
|
|
return $params; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
public function updateMetadata(MediaInterface $media, $force = false): void |
200
|
|
|
{ |
201
|
|
|
$url = sprintf('https://www.youtube.com/oembed?url=%s&format=json', $this->getReferenceUrl($media)); |
202
|
|
|
|
203
|
|
|
try { |
204
|
|
|
$metadata = $this->getMetadata($media, $url); |
205
|
|
|
} catch (\RuntimeException $e) { |
206
|
|
|
$media->setEnabled(false); |
207
|
|
|
$media->setProviderStatus(MediaInterface::STATUS_ERROR); |
208
|
|
|
|
209
|
|
|
return; |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
$media->setProviderMetadata($metadata); |
213
|
|
|
|
214
|
|
|
if ($force) { |
215
|
|
|
$media->setName($metadata['title']); |
216
|
|
|
$media->setAuthorName($metadata['author_name']); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
$media->setHeight($metadata['height']); |
220
|
|
|
$media->setWidth($metadata['width']); |
221
|
|
|
$media->setContentType('video/x-flv'); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
public function getDownloadResponse(MediaInterface $media, $format, $mode, array $headers = []) |
225
|
|
|
{ |
226
|
|
|
return new RedirectResponse($this->getReferenceUrl($media), 302, $headers); |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* Get provider reference url. |
231
|
|
|
* |
232
|
|
|
* @return string |
233
|
|
|
*/ |
234
|
|
|
public function getReferenceUrl(MediaInterface $media) |
235
|
|
|
{ |
236
|
|
|
return sprintf('https://www.youtube.com/watch?v=%s', $media->getProviderReference()); |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
protected function fixBinaryContent(MediaInterface $media): void |
240
|
|
|
{ |
241
|
|
|
if (!$media->getBinaryContent()) { |
242
|
|
|
return; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
if (11 === \strlen($media->getBinaryContent())) { |
246
|
|
|
return; |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
if (preg_match("/^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user)\/))([^\#\?&\"'>]+)/", $media->getBinaryContent(), $matches)) { |
250
|
|
|
$media->setBinaryContent($matches[1]); |
251
|
|
|
} |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
protected function doTransform(MediaInterface $media): void |
255
|
|
|
{ |
256
|
|
|
$this->fixBinaryContent($media); |
257
|
|
|
|
258
|
|
|
if (!$media->getBinaryContent()) { |
259
|
|
|
return; |
260
|
|
|
} |
261
|
|
|
|
262
|
|
|
$media->setProviderName($this->name); |
263
|
|
|
$media->setProviderStatus(MediaInterface::STATUS_OK); |
264
|
|
|
$media->setProviderReference($media->getBinaryContent()); |
265
|
|
|
|
266
|
|
|
$this->updateMetadata($media, true); |
267
|
|
|
} |
268
|
|
|
} |
269
|
|
|
|