PluginProbe ʕ •ᴥ•ʔ
Presto Player / 2.3.3
Presto Player v2.3.3
4.3.0 4.2.4 4.2.3 4.2.2 4.2.0 4.2.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.12.0 1.13.0 1.14.0 1.14.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.13 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3-beta1 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.0-beta1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1.0 3.1.1 3.1.2 3.1.3 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4
presto-player / inc / Services / Shortcodes.php
presto-player / inc / Services Last commit date
API 2 years ago Blocks 5 years ago License 5 years ago AdminNotice.php 5 years ago AdminNotices.php 4 years ago AjaxActions.php 2 years ago Blocks.php 4 years ago Compatibility.php 4 years ago Menu.php 2 years ago Migrations.php 5 years ago Player.php 2 years ago ProCompatibility.php 2 years ago ReusableVideos.php 2 years ago Scripts.php 2 years ago Settings.php 4 years ago Shortcodes.php 2 years ago Streamer.php 4 years ago Translation.php 2 years ago VideoPostType.php 2 years ago
Shortcodes.php
444 lines
1 <?php
2
3 namespace PrestoPlayer\Services;
4
5 use PrestoPlayer\Blocks\AudioBlock;
6 use PrestoPlayer\Pro\Blocks\PlaylistBlock;
7 use PrestoPlayer\Playlist;
8 use PrestoPlayer\Models\Video;
9 use PrestoPlayer\Blocks\VimeoBlock;
10 use PrestoPlayer\Blocks\YouTubeBlock;
11 use PrestoPlayer\Blocks\SelfHostedBlock;
12 use PrestoPlayer\Services\ReusableVideos;
13 use PrestoPlayer\Pro\Blocks\BunnyCDNBlock;
14
15 class Shortcodes
16 {
17 public function register()
18 {
19 add_shortcode('presto_player_chapter', '__return_false');
20 add_shortcode('presto_playlist_item', '__return_false');
21 add_shortcode('presto_player_overlay', '__return_false');
22 add_shortcode('presto_player_track', '__return_false');
23 add_shortcode('presto_player', [$this, 'playerShortcode'], 10, 2);
24 add_shortcode('presto_timestamp', [$this, 'timestampShortcode'], 10, 2);
25 add_shortcode('pptime', [$this, 'timestampShortcode'], 10, 2);
26 add_shortcode('presto_playlist', [$this, 'playlistShortcode'], 10, 2);
27 }
28
29 /**
30 * Do the shortcode
31 *
32 * @param array $atts Array of shortcode attributes
33 * @param string $content String of content.
34 * @return void
35 */
36 public function playerShortcode($atts, $content)
37 {
38 if (!is_admin()) {
39 // global is the most reliable between page builders
40 global $load_presto_js;
41 $load_presto_js = true;
42 (new Scripts())->blockAssets(); // enqueue block assets
43 }
44
45 $atts = shortcode_atts(
46 [
47 'id' => '',
48 'src' => '',
49 'title' => '',
50 'provider' => '',
51 'class' => '',
52 'custom_field' => '',
53 'poster' => '',
54 'preload' => 'auto',
55 'preset' => 0,
56 'autoplay' => false,
57 'plays_inline' => false,
58 'chapters' => [],
59 'overlays' => [],
60 'muted_autoplay_preview' => false,
61 'muted_autoplay_caption_preview' => false,
62 ],
63 $atts
64 );
65
66 // could not find source but ID is present.
67 if (!$atts['src'] && !$atts['custom_field'] && $atts['id']) {
68 return ReusableVideos::getBlock($atts['id']);
69 }
70
71 $atts = $this->parseAttributes($atts, $content);
72 return $this->renderBlock($atts);
73 }
74
75 /**
76 * Do the shortcode
77 *
78 * @param array $atts Array of shortcode attributes
79 * @param string $content String of content.
80 * @return void
81 */
82 public function playlistShortcode($atts, $content)
83 {
84 if (!is_admin()) {
85 // global is the most reliable between page builders
86 global $load_presto_js;
87 $load_presto_js = true;
88 (new Scripts())->blockAssets(); // enqueue block assets
89 }
90
91 $atts = $this->parsePlaylistAttributes($atts, $content);
92
93 return (new PlaylistBlock())->html($atts);
94 }
95
96 /**
97 * Timestamp shortcode
98 *
99 * @param array $atts Shortcode attributes.
100 * @param string $content Content inside shortcode.
101 * @return string
102 */
103 public function timestampShortcode($atts, $content)
104 {
105 $atts = shortcode_atts(
106 [
107 'time' => '',
108 ],
109 $atts
110 );
111 return '<presto-timestamp time="' . esc_attr($atts['time']) . '">' . $content . '</presto-timestamp>';
112 }
113
114 public function parsePlaylistAttributes($atts, $content = '')
115 {
116
117 // backwards compat.
118 $atts['listTextPlural'] = $atts['listtextplural'] ?? null;
119 $atts['listTextSingular'] = $atts['listtextplural'] ?? null;
120 $atts['transitionDuration'] = $atts['transitionduration'] ?? null;
121
122 $atts = shortcode_atts(
123 [
124 'heading' => __('Playlist', 'presto-player'),
125 'listTextPlural' => __('Videos', 'presto-player'),
126 'listTextSingular' => __('Video', 'presto-player'),
127 'transitionDuration' => 5,
128 'styles' => ''
129 ],
130 $atts
131 );
132
133 $atts['items'] = $this->getPlaylistItems($content);
134
135 return $atts;
136 }
137
138 public function parseAttributes($atts, $content = '')
139 {
140 $atts = shortcode_atts(
141 [
142 'id' => '',
143 'src' => '',
144 'title' => '',
145 'provider' => '',
146 'class' => '',
147 'custom_field' => '',
148 'poster' => '',
149 'preload' => 'auto',
150 'preset' => 0,
151 'autoplay' => false,
152 'plays_inline' => false,
153 'chapters' => [],
154 'overlays' => [],
155 'muted_autoplay_preview' => false,
156 'muted_autoplay_caption_preview' => false,
157 ],
158 $atts
159 );
160
161 if (!$atts['id'] && !$atts['src'] && !$atts['custom_field']) {
162 return [];
163 }
164
165 // custom field as a src
166 if ($atts['custom_field']) {
167 $atts['src'] = get_post_meta(get_the_ID(), $atts['custom_field'], true);
168
169 // Compatibility for file input field type from Advanced custom field plugin.
170 if (function_exists('get_field') && $custom_field = get_field($atts['custom_field'])) {
171 switch (gettype($custom_field ?? null)) {
172 case 'array':
173 $atts['src'] = $custom_field['url'] ?? '';
174 break;
175 case 'integer':
176 $atts['src'] = wp_get_attachment_url($custom_field) ?? '';
177 break;
178 case 'string':
179 $atts['src'] = $custom_field;
180 break;
181 }
182 }
183 }
184
185 // get provider based on src, if not provided
186 $atts['provider'] = !$atts['provider'] ? $this->getProvider($atts['src']) : 'self-hosted';
187
188 $atts['id'] = $this->getOrCreateVideoId($atts);
189 $atts['chapters'] = $this->getChapters($content);
190 $atts['overlays'] = $this->getOverlays($content);
191 $atts['tracks'] = $this->getTracks($content);
192 $atts['playsInline'] = (bool) $atts['plays_inline'];
193 $atts['mutedPreview'] = [
194 'enabled' => (bool) $atts['muted_autoplay_preview'],
195 'captions' => (bool) $atts['muted_autoplay_caption_preview'],
196 ];
197 $atts['className'] = sanitize_html_class($atts['class']);
198
199 unset($atts['plays_inline']);
200 unset($atts['muted_autoplay_preview']);
201 unset($atts['muted_autoplay_caption_preview']);
202 unset($atts['class']);
203
204 return $atts;
205 }
206
207 /**
208 * Renders the block with attributes.
209 *
210 * @param array $atts Block attributes.
211 * @return void
212 */
213 public function renderBlock($atts)
214 {
215 switch ($atts['provider'] ?? '') {
216 case 'self-hosted':
217 return (new SelfHostedBlock())->html($atts, '');
218
219 case 'youtube':
220 return (new YouTubeBlock())->html($atts, '');
221
222 case 'vimeo':
223 return (new VimeoBlock())->html($atts, '');
224
225 case 'bunny':
226 return (new BunnyCDNBlock())->html($atts, '');
227
228 case 'audio':
229 return (new AudioBlock())->html($atts, '');
230 }
231 }
232
233 /**
234 * Get or create video id for analytics
235 *
236 * @param array $atts
237 * @return int
238 */
239 public function getOrCreateVideoId($atts)
240 {
241 $create = [
242 'src' => $atts['src'],
243 'type' => $atts['provider']
244 ];
245 if (!empty($atts['title'])) {
246 $create['title'] = $atts['title'];
247 }
248
249 $video = new Video();
250 $model = $video->getOrCreate(
251 ['src' => $atts['src']],
252 $create
253 );
254
255 $model = $model->toObject();
256 return !empty($model->id) ? $model->id : 0;
257 }
258
259 /**
260 * Get chapters from shortcodes
261 *
262 * @param string $content
263 * @return array
264 */
265 public function getChapters($content)
266 {
267 $chapters = $this->getShortcodesAtts(
268 'presto_player_chapter',
269 $content,
270 [
271 'time' => '00:00',
272 'title' => ''
273 ]
274 );
275 foreach ((array) $chapters as $key => $chapter) {
276 if (!strpos($chapter['time'], ':')) {
277 $chapters[$key]['time'] = '00:' . $chapter['time'];
278 }
279 }
280
281 return $chapters;
282 }
283
284 public function getPlaylistItems($content)
285 {
286 $items = $this->getShortcodesAtts(
287 'presto_playlist_item',
288 $content,
289 [
290 'duration' => '00:00',
291 'title' => '',
292 'id' => 0
293 ]
294 );
295 foreach ($items as $key => $item) {
296 $video_id = $item['id'];
297 $block = parse_blocks(ReusableVideos::get((int)$video_id));
298 if (!isset($block[0]['innerBlocks'][0]['attrs'])) {
299 unset($items[$key]);
300 continue;
301 }
302 $inner_block = $block[0]['innerBlocks'][0];
303 $attributes = $inner_block['attrs'];
304 $video_details = (new Playlist())->parsed_attributes($inner_block['blockName'], $attributes);
305 $items[$key] = [
306 'id' => $items[$key]['id'],
307 'config' => $video_details,
308 'duration' => $items[$key]['duration'],
309 'title' => $items[$key]['title']
310 ];
311 }
312 return $items;
313 }
314
315 /**
316 * Get overlays from shortcodes
317 *
318 * @param string $content
319 * @return array
320 */
321 public function getOverlays($content)
322 {
323
324 $overlays = $this->getShortcodesAtts(
325 'presto_player_overlay',
326 $content,
327 [
328 'start_time' => '00:00',
329 'end_time' => '',
330 'text' => '',
331 'link' => [],
332 'position' => '',
333 ]
334 );
335 foreach ((array) $overlays as $key => $overlay) {
336 if (!strpos($overlay['start_time'], ':')) {
337 $overlays[$key]['startTime'] = '00:' . $overlay['start_time'];
338 } else {
339 $overlays[$key]['startTime'] = $overlay['start_time'];
340 }
341
342 if (!strpos($overlay['end_time'], ':')) {
343 $overlays[$key]['endTime'] = '00:' . $overlay['end_time'];
344 } else {
345 $overlays[$key]['endTime'] = $overlay['end_time'];
346 }
347
348 $overlays[$key]['link']['url'] = $overlay['link_url'];
349 $overlays[$key]['link']['opensInNewTab'] = (bool) $overlay['link_new_tab'];
350
351 unset($overlays[$key]['link_url']);
352 unset($overlays[$key]['link_new_tab']);
353 unset($overlays[$key]['start_time']);
354 unset($overlays[$key]['end_time']);
355 }
356 return $overlays;
357 }
358
359 /**
360 * Get tracks from shortcodes
361 *
362 * @param string $content
363 * @return array
364 */
365 public function getTracks($content)
366 {
367 return $this->getShortcodesAtts(
368 'presto_player_track',
369 $content,
370 [
371 'label' => '',
372 'src' => '',
373 'srclang' => ''
374 ]
375 );
376 }
377
378 /**
379 * Get specific shortcode atts from content
380 *
381 * @param string $name Name of shortcode
382 * @param string $content Page content
383 * @param array $defaults Defaults for each
384 * @return array
385 */
386 public function getShortcodesAtts($name, $content, $defaults = [])
387 {
388 $items = [];
389
390 // if shortcode exists
391 if (
392 preg_match_all('/' . get_shortcode_regex() . '/s', $content, $matches)
393 && array_key_exists(2, $matches)
394 && in_array($name, $matches[2])
395 ) {
396 foreach ((array) $matches[0] as $key => $value) {
397 if (strpos($value, $name) !== false) {
398 $items[] = wp_parse_args(
399 shortcode_parse_atts($matches[3][$key]),
400 $defaults
401 );
402 }
403 }
404 }
405
406 return $items;
407 }
408
409 /**
410 * Maybe switch provider if the url is overridden
411 */
412 protected function getProvider($src)
413 {
414 $provider = 'self-hosted';
415
416 if (!empty($src)) {
417 $filetype = wp_check_filetype($src);
418 if (isset($filetype['type']) && false !== strpos($filetype['type'], 'audio')) {
419 return 'audio';
420 }
421
422 $yt_rx = '/^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w\-]+\?v=|embed\/|v\/)?)([\w\-]+)(\S+)?$/';
423 $has_match_youtube = preg_match($yt_rx, $src, $yt_matches);
424
425 if ($has_match_youtube) {
426 return 'youtube';
427 }
428
429 $vm_rx = '/(https?:\/\/)?(www\.)?(player\.)?vimeo\.com\/([a-z]*\/)*([‌​0-9]{6,11})[?]?.*/';
430 $has_match_vimeo = preg_match($vm_rx, $src, $vm_matches);
431
432 if ($has_match_vimeo) {
433 return 'vimeo';
434 }
435
436 if (strpos($src, 'https://vz-') !== false && strpos($src, 'b-cdn.net') !== false) {
437 return 'bunny';
438 }
439 }
440
441 return $provider;
442 }
443 }
444