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