PluginProbe ʕ •ᴥ•ʔ
Presto Player / 2.0.13
Presto Player v2.0.13
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 / Support / Block.php
presto-player / inc / Support Last commit date
Block.php 2 years ago BlockFinder.php 5 years ago DynamicData.php 4 years ago HasOneRelationship.php 5 years ago Integration.php 5 years ago Utility.php 4 years ago
Block.php
614 lines
1 <?php
2
3 namespace PrestoPlayer\Support;
4
5
6 use PrestoPlayer\Plugin;
7 use PrestoPlayer\Models\Video;
8 use PrestoPlayer\Models\Player;
9 use PrestoPlayer\Models\Preset;
10 use PrestoPlayer\Models\AudioPreset;
11 use PrestoPlayer\Models\Setting;
12 use PrestoPlayer\WPackio\Enqueue;
13 use PrestoPlayer\Support\DynamicData;
14 use PrestoPlayer\Integrations\LearnDash\LearnDash;
15
16 use function cli\err;
17
18 class Block
19 {
20 protected $enqueue;
21 protected $assets;
22 protected $video_assets;
23 protected $name = '';
24 protected $template_name = 'video';
25 public $services;
26
27 /**
28 * Attributes
29 *
30 * @var array
31 */
32 protected $attributes = [
33 'color' => [
34 'type' => 'string',
35 'default' => '#00b3ff',
36 ],
37 'blockAlignment' => [
38 'type' => 'string',
39 ],
40 'autoplay' => [
41 'type' => 'boolean'
42 ],
43 'id' => [
44 'type' => 'number',
45 ],
46 'src' => [
47 'type' => 'string'
48 ],
49 'imageID' => [
50 'type' => 'number',
51 ],
52 'poster' => [
53 'type' => 'string',
54 ],
55 'content' => [
56 'type' => 'boolean',
57 ],
58 'pip' => [
59 'type' => 'boolean',
60 'default' => true
61 ],
62 'fullscreen' => [
63 'type' => 'boolean',
64 'default' => true
65 ],
66 'captions' => [
67 'type' => 'boolean',
68 'default' => false
69 ],
70 'hideControls' => [
71 'type' => 'boolean',
72 'default' => true
73 ],
74 'playLarge' => [
75 'type' => 'boolean',
76 'default' => true
77 ],
78 'chapters' => [
79 'type' => 'array',
80 'default' => []
81 ],
82 'overlays' => [
83 'type' => 'array',
84 'default' => []
85 ],
86 'speed' => [
87 'type' => 'boolean',
88 'default' => true
89 ],
90 ];
91
92 /**
93 * Attributes to pass to web component
94 */
95 protected $component_attributes = [
96 'preset',
97 'chapters',
98 'overlays',
99 'tracks',
100 'branding',
101 'blockAttributes',
102 'config',
103 'skin',
104 'analytics',
105 'automations',
106 'provider',
107 'video_id',
108 'videoAttributes',
109 'audioAttributes',
110 'provider_video_id',
111 'youtube'
112 ];
113
114
115 public function __construct(bool $isPremium = false, $version = 1)
116 {
117 do_action('presto_player_before_block_output', [$this, 'middleware']);
118 }
119
120 /**
121 * Register the block type
122 *
123 * @return void
124 */
125 public function register()
126 {
127 $this->registerBlockType();
128 }
129
130 public function additionalAttributes()
131 {
132 return [];
133 }
134
135 /**
136 * Register dynamic block type
137 *
138 * @return void
139 */
140 public function registerBlockType()
141 {
142 register_block_type(
143 "presto-player/$this->name",
144 [
145 'attributes' => wp_parse_args($this->additionalAttributes(), $this->attributes),
146 'render_callback' => [$this, 'html'],
147 ]
148 );
149 }
150
151 /**
152 * Middleware to run before outputting template
153 * Should the block load?
154 *
155 * @param array $attributes
156 * @param string $content
157 * @return boolean
158 */
159 public function middleware($attributes, $content)
160 {
161 return true;
162 }
163
164 /**
165 * Sanitize attributes function
166 * Let's a parent class sanitize attributes before displaying
167 *
168 * @param array $attributes
169 * @param array $default_config
170 * @return array
171 */
172 public function sanitizeAttributes($attributes, $default_config)
173 {
174 return [];
175 }
176
177 /**
178 * Allow overriding attributes
179 *
180 * @param array $attributes
181 * @return array
182 */
183 public function overrideAttributes($attributes)
184 {
185 return apply_filters("presto_video_block_attributes_override", $attributes, $this);
186 }
187
188 /**
189 * Must sanitize attributes
190 *
191 * @param array $attributes
192 * @return array
193 */
194 private function _sanitizeAttibutes($attributes)
195 {
196
197 // attribute overrides
198 $attributes = $this->overrideAttributes($attributes);
199
200 // video id
201 $id = !empty($attributes['id']) ? $attributes['id'] : 0;
202
203 if ('audio' === $this->name) {
204 $preset = $this->getAudioPreset(!empty($attributes['preset']) ? $attributes['preset'] : 0);
205 $preset->type = 'audio';
206 } else {
207 $preset = $this->getPreset(!empty($attributes['preset']) ? $attributes['preset'] : 0);
208 }
209 $branding = $this->getBranding($preset);
210 $class = $this->getClasses($attributes);
211 $playerClass = $this->getPlayerClasses($id, $preset);
212 $styles = $this->getPlayerStyles($preset, $branding);
213 $css = $this->getCSS($id);
214 $src = !empty($attributes['src']) ? $attributes['src'] : '';
215
216 // use title or source.
217 if (empty($attributes['title'])) {
218 $video = $id ? (new Video($id)) : false;
219 $attributes['title'] = $video ? $video->title : $src;
220 }
221
222 // Default config
223 $default_config = apply_filters('presto_player/block/default_attributes', [
224 'type' => $this->name,
225 'css' => wp_kses_post($css),
226 'class' => $class,
227 'is_hls' => $this->isHls($src),
228 'styles' => $styles,
229 'skin' => $preset->skin,
230 'playerClass' => $playerClass,
231 'id' => $id,
232 'src' => $src,
233 'autoplay' => !empty($attributes['autoplay']),
234 'playsInline' => !empty($attributes['playsInline']),
235 'poster' => !empty($attributes['poster']) ? $attributes['poster'] : '',
236 'branding' => $branding,
237 'youtube' => [
238 'noCookie' => (bool) Setting::get('youtube', 'nocookie'),
239 'channelId' => sanitize_text_field(Setting::get('youtube', 'channel_id')),
240 'show_count' => !empty($preset->action_bar['show_count'])
241 ],
242 'preload' => !empty($attributes['preload']) ? $attributes['preload'] : '',
243 'tracks' => !empty($attributes['tracks']) ? (array) $attributes['tracks'] : [],
244 'preset' => $preset ? $preset->toArray() : [],
245 'chapters' => !empty($attributes['chapters']) ? $attributes['chapters'] : [],
246 'overlays' => DynamicData::replaceItems(!empty($attributes['overlays']) ? $attributes['overlays'] : [], 'text'),
247 'blockAttributes' => $attributes,
248 'provider' => $this->name,
249 'analytics' => Setting::get('analytics', 'enable', false),
250 'automations' => Setting::get('performance', 'automations', true),
251 'title' => !empty($attributes['title']) ? html_entity_decode($attributes['title']) : '',
252 ], $attributes);
253
254 return wp_parse_args(
255 $this->sanitizeAttributes($attributes, $default_config),
256 $default_config
257 );
258 }
259
260 /**
261 * Get CSS from settings
262 * Is it an HLS playlist
263 *
264 * @param string $src
265 * @return boolean
266 */
267 public function isHls($src)
268 {
269 $src = !empty($src) ? $src : '';
270 return \strpos($src, '.m3u8') !== false;
271 }
272
273 /**
274 * Get CSS from settings
275 * Validates before output
276 *
277 * @param integer $id
278 * @return string
279 */
280 public function getCSS($id)
281 {
282 return apply_filters(
283 'presto_player/player/css',
284 Utility::sanitizeCSS(
285 Setting::get('branding', 'player_css'),
286 $id
287 )
288 );
289 }
290
291 /**
292 * Gets the preset
293 *
294 * @param integer $id Preset ID
295 * @return \PrestoPlayer\Models\Preset
296 */
297 public function getPreset($id)
298 {
299 $preset = new Preset(!empty($id) ? $id : 0);
300 $preset_id = $preset->id;
301
302 if (empty($preset_id)) {
303 $preset = $preset->findWhere(['slug' => 'default']);
304 }
305
306 // replace watermark text.
307 if (!empty($preset->watermark['enabled'])) {
308 $watermark_text = [
309 'text' => DynamicData::replaceText($preset->watermark['text'])
310 ];
311
312 $preset->watermark = wp_parse_args($watermark_text, $preset->watermark);
313 }
314
315 return apply_filters('presto_player/presto_player_presets/data', $preset, 'video');
316 }
317
318 /**
319 * Gets the audio preset
320 *
321 * @param integer $id Preset ID
322 * @return \PrestoPlayer\Models\AudioPreset
323 */
324 public function getAudioPreset($id)
325 {
326 $preset = new AudioPreset(!empty($id) ? $id : 0);
327 $preset_id = $preset->id;
328
329 if (empty($preset_id)) {
330 $preset = $preset->findWhere(['slug' => 'default']);
331 }
332
333 return apply_filters('presto_player/presto_player_presets/data', $preset, 'audio');
334 }
335
336 /**
337 * Get player branding
338 *
339 * @param \PrestoPlayer\Models\Preset $preset
340 * @return array
341 */
342 public function getBranding($preset)
343 {
344 $branding = Player::getBranding();
345
346 // sanitize with sensible defaults
347 $branding['color'] = !empty($branding['color']) ? sanitize_hex_color($branding['color']) : 'rgba(43,51,63,.7)';
348 $branding['logo_width'] = !empty($branding['logo_width']) ? $branding['logo_width'] : 150;
349 $branding['logo'] = !empty($branding['logo'] && !$preset->hide_logo) ? $branding['logo'] : '';
350
351 return $branding;
352 }
353
354 /**
355 * Get block classes
356 *
357 * @param array $attributes
358 * @return string
359 */
360 public function getClasses($attributes)
361 {
362 $block_alignment = isset($attributes['align']) ? sanitize_text_field($attributes['align']) : '';
363 return !empty($block_alignment) ? 'align' . $block_alignment : '';
364 }
365
366 /**
367 * Get player classes
368 *
369 * @param integer $id
370 * @param \PrestoPlayer\Models\Preset $preset
371 * @return string
372 */
373 public function getPlayerClasses($id, $preset)
374 {
375 $skin = $preset->skin;
376 $playerClass = 'presto-video-id-' . (int) $id;
377 $playerClass .= ' presto-preset-id-' . (int) $preset->id;
378
379 if (!empty($skin)) {
380 $playerClass .= ' skin-' . sanitize_text_field($skin);
381 }
382
383 $caption_style = $preset->caption_style;
384 if (!empty($caption_style)) {
385 $playerClass .= ' caption-style-' . sanitize_html_class($caption_style);
386 }
387
388 if (!empty($attributes['className'])) {
389 $playerClass .= ' ' . (string) $attributes['className'];
390 }
391
392 return $playerClass;
393 }
394
395 /**
396 * Get player styles
397 *
398 * @param \PrestoPlayer\Models\Preset $preset
399 * @param array $branding
400 * @return string
401 */
402 public function getPlayerStyles($preset, $branding)
403 {
404
405 // set brand color.
406 $styles = '--plyr-color-main: ' . sanitize_hex_color(!empty($preset->background_color) ? $preset->background_color : $branding['color']) . '; ';
407
408 // video
409 if ($preset->caption_background) {
410 $styles .= '--plyr-captions-background: ' . sanitize_hex_color($preset->caption_background) . '; ';
411 }
412 if ($preset->border_radius) {
413 $styles .= '--presto-player-border-radius: ' . (int) $preset->border_radius . 'px; ';
414 }
415
416 if ($branding['logo_width']) {
417 $styles .= '--presto-player-logo-width: ' . (int) $branding['logo_width'] . 'px; ';
418 }
419 if (!empty($preset->email_collection['border_radius'])) {
420 $styles .= '--presto-player-email-border-radius: ' . (int) $preset->email_collection['border_radius'] . 'px; ';
421 }
422
423 // audio
424 if ($preset->type === 'audio') {
425 if ($preset->background_color) {
426 $styles .= '--plyr-audio-controls-background: ' . sanitize_hex_color($preset->background_color) . ';';
427 } else {
428 $styles .= '--plyr-audio-controls-background: ' . sanitize_hex_color($branding['color']) . ';';
429 }
430
431 if ($preset->control_color) {
432 $styles .= '--plyr-audio-control-color: ' . sanitize_hex_color($preset->control_color) . ';';
433 $styles .= '--plyr-range-thumb-background: ' . sanitize_hex_color($preset->control_color) . ';';
434 $styles .= '--plyr-range-fill-background: ' . sanitize_hex_color($preset->control_color) . ';';
435 $styles .= '--plyr-audio-progress-buffered-background: ' . Utility::hex2rgba(sanitize_hex_color($preset->control_color), 0.35) . ';';
436 $styles .= '--plyr-range-thumb-shadow: 0 1px 1px ' . Utility::hex2rgba(sanitize_hex_color($preset->control_color), 0.15) . ', 0 0 0 1px ' . Utility::hex2rgba(sanitize_hex_color($preset->control_color), 0.2) . ';';
437 } else {
438 $styles .= '--plyr-audio-control-color: #ffffff;';
439 $styles .= '--plyr-range-thumb-background: #ffffff;';
440 $styles .= '--plyr-range-fill-background: #ffffff;';
441 $styles .= '--plyr-audio-progress-buffered-background: ' . Utility::hex2rgba(sanitize_hex_color(sanitize_hex_color('#dcdcdc')), 0.35) . ';';
442 }
443 }
444
445 return $styles;
446 }
447
448 /**
449 * Get block attributes
450 *
451 * @param array $attributes
452 * @return array
453 */
454 public function getAttributes($attributes)
455 {
456 return $this->_sanitizeAttibutes($attributes);
457 }
458
459 /**
460 * Dynamic block output
461 *
462 * @param array $attributes
463 * @param string $content
464 * @return void
465 */
466 public function html($attributes, $content)
467 {
468 global $presto_player_instance;
469 if ($presto_player_instance === null) {
470 $presto_player_instance = 0;
471 }
472 $presto_player_instance++;
473
474 // html middleware
475 $load = $this->middleware($attributes, $content);
476
477 if (is_feed()) {
478 return $this->getFeedHtml($attributes);
479 }
480
481 if (LearnDash::isEnabled()) {
482 if (!LearnDash::shouldVideoLoad()) {
483 return false;
484 }
485 }
486
487 // let integrations filter loading capabilities
488 if (!apply_filters('presto_player_load_video', $load, $attributes, $content, $this->name)) {
489 // allow a custom fallback
490 if ($fallback = apply_filters('presto_player_load_video_fallback', false, $attributes, $content, $this)) {
491 return wp_kses_post($fallback);
492 }
493 return $this->getFallbackHTMLForUnauthorizeAccess();
494 }
495
496 // get template data
497 $data = apply_filters('presto_player_block_data', $this->getAttributes($attributes), $this);
498
499 // need and id and src
500 if (empty($data['id']) && empty($data['src'])) {
501 return false;
502 }
503
504 // TODO: child template system
505 ob_start();
506
507 if (!empty($data['id'])) {
508 echo "<!--presto-player:video_id=" . (int) $data['id'] . "-->";
509 }
510
511 if (file_exists(PRESTO_PLAYER_PLUGIN_DIR . "templates/{$this->template_name}.php")) {
512 include PRESTO_PLAYER_PLUGIN_DIR . "templates/{$this->template_name}.php";
513 }
514
515 $this->initComponentScript($data['id'], $data, $presto_player_instance);
516 $this->iframeFallback($data);
517
518 $template = ob_get_contents();
519 ob_end_clean();
520
521 return $template;
522 }
523
524 /**
525 * Dynamically initialize component via script tag
526 * We have to do this because we cannot send arrays or object in plain html
527 */
528 public function initComponentScript($id = 0, $data = [], $instance = 1)
529 {
530 if (!$id) {
531 return;
532 }
533 ?>
534 <script>
535 var player = document.querySelector('presto-player#presto-player-<?php echo (int) $instance; ?>');
536 player.video_id = <?php echo (int) $id; ?>;
537 <?php
538 $attributes = apply_filters('presto_player/component/attributes', $this->component_attributes, $data);
539 foreach ($attributes as $attribute) { ?>
540 <?php if (isset($data[$attribute])) { ?>
541 player.<?php echo sanitize_text_field($attribute); ?> = <?php echo wp_json_encode($data[$attribute]); ?>;
542 <?php } ?>
543 <?php } ?>
544 </script>
545 <?php
546 }
547
548 /**
549 * Adds an iframe fallback script to the page in case js loading fails
550 *
551 * @return void
552 */
553 public function iframeFallback($data)
554 {
555 // must be vimeo or youtube
556 if (in_array($data['provider'], ['youtube', 'vimeo'])) {
557 add_filter('presto_player/scripts/load_iframe_fallback', '__return_true');
558 }
559 }
560
561 /**
562 * This function return HTML for unauthorized access or curtain.
563 *
564 * @return void
565 */
566 public function getFallbackHTMLForUnauthorizeAccess()
567 {
568 // Get the branding CSS variable.
569 $data = $this->getAttributes([]);
570 ob_start();
571 if (file_exists(PRESTO_PLAYER_PLUGIN_DIR . "templates/unauthorized.php")) {
572 include PRESTO_PLAYER_PLUGIN_DIR . "templates/unauthorized.php";
573 }
574 $template = ob_get_contents();
575 ob_end_clean();
576 return $template;
577 }
578
579 /**
580 * Return fallback html for feeds.
581 *
582 * @param array $atts array of attributes.
583 */
584 public function getFeedHtml($atts)
585 {
586 if (is_feed()) {
587 ob_start(); ?>
588
589 <?php if (in_array($this->name, array('self-hosted', 'bunny')) && !empty($atts['src'])) { ?>
590 <video controls preload="none">
591 <source src="<?php echo esc_url($atts['src']); ?>" />
592 </video>
593 <?php } ?>
594
595 <?php if ('audio' === $this->name && !empty($atts['src'])) { ?>
596 <audio controls preload="none">
597 <source src="<?php echo esc_url($atts['src']); ?>" />
598 </audio>
599 <?php } ?>
600
601 <?php if ('youtube' === $this->name && !empty($atts['video_id'])) { ?>
602 <?php echo wp_oembed_get('https://www.youtube.com/watch?v=' . $atts['video_id']); ?>
603 <?php } ?>
604
605 <?php if ('vimeo' === $this->name && !empty($atts['video_id'])) { ?>
606 <?php echo wp_oembed_get('https://vimeo.com/' . $atts['video_id']); ?>
607 <?php } ?>
608
609 <?php
610 return ob_get_clean();
611 }
612 }
613 }
614