PluginProbe ʕ •ᴥ•ʔ
Presto Player / 2.0.2
Presto Player v2.0.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 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 if (LearnDash::isEnabled()) {
162 if (!LearnDash::shouldVideoLoad()) {
163 return false;
164 }
165 }
166
167 return true;
168 }
169
170 /**
171 * Sanitize attributes function
172 * Let's a parent class sanitize attributes before displaying
173 *
174 * @param array $attributes
175 * @param array $default_config
176 * @return array
177 */
178 public function sanitizeAttributes($attributes, $default_config)
179 {
180 return [];
181 }
182
183 /**
184 * Allow overriding attributes
185 *
186 * @param array $attributes
187 * @return array
188 */
189 public function overrideAttributes($attributes)
190 {
191 return apply_filters("presto_video_block_attributes_override", $attributes, $this);
192 }
193
194 /**
195 * Must sanitize attributes
196 *
197 * @param array $attributes
198 * @return array
199 */
200 private function _sanitizeAttibutes($attributes)
201 {
202
203 // attribute overrides
204 $attributes = $this->overrideAttributes($attributes);
205
206 // video id
207 $id = !empty($attributes['id']) ? $attributes['id'] : 0;
208
209 if ('audio' === $this->name) {
210 $preset = $this->getAudioPreset(!empty($attributes['preset']) ? $attributes['preset'] : 0);
211 $preset->type = 'audio';
212 } else {
213 $preset = $this->getPreset(!empty($attributes['preset']) ? $attributes['preset'] : 0);
214 }
215 $branding = $this->getBranding($preset);
216 $class = $this->getClasses($attributes);
217 $playerClass = $this->getPlayerClasses($id, $preset);
218 $styles = $this->getPlayerStyles($preset, $branding);
219 $css = $this->getCSS($id);
220 $src = !empty($attributes['src']) ? $attributes['src'] : '';
221
222 // use title or source.
223 if (empty($attributes['title'])) {
224 $video = $id ? (new Video($id)) : false;
225 $attributes['title'] = $video ? $video->title : $src;
226 }
227
228 // Default config
229 $default_config = apply_filters('presto_player/block/default_attributes', [
230 'type' => $this->name,
231 'css' => wp_kses_post($css),
232 'class' => $class,
233 'is_hls' => $this->isHls($src),
234 'styles' => $styles,
235 'skin' => $preset->skin,
236 'playerClass' => $playerClass,
237 'id' => $id,
238 'src' => $src,
239 'autoplay' => !empty($attributes['autoplay']),
240 'playsInline' => !empty($attributes['playsInline']),
241 'poster' => !empty($attributes['poster']) ? $attributes['poster'] : '',
242 'branding' => $branding,
243 'youtube' => [
244 'noCookie' => (bool) Setting::get('youtube', 'nocookie'),
245 'channelId' => sanitize_text_field(Setting::get('youtube', 'channel_id')),
246 'show_count' => !empty($preset->action_bar['show_count'])
247 ],
248 'preload' => !empty($attributes['preload']) ? $attributes['preload'] : '',
249 'tracks' => !empty($attributes['tracks']) ? (array) $attributes['tracks'] : [],
250 'preset' => $preset ? $preset->toArray() : [],
251 'chapters' => !empty($attributes['chapters']) ? $attributes['chapters'] : [],
252 'overlays' => DynamicData::replaceItems(!empty($attributes['overlays']) ? $attributes['overlays'] : [], 'text'),
253 'blockAttributes' => $attributes,
254 'provider' => $this->name,
255 'analytics' => Setting::get('analytics', 'enable', false),
256 'automations' => Setting::get('performance', 'automations', true),
257 'title' => !empty($attributes['title']) ? html_entity_decode($attributes['title']) : '',
258 ], $attributes);
259
260 return wp_parse_args(
261 $this->sanitizeAttributes($attributes, $default_config),
262 $default_config
263 );
264 }
265
266 /**
267 * Get CSS from settings
268 * Is it an HLS playlist
269 *
270 * @param string $src
271 * @return boolean
272 */
273 public function isHls($src)
274 {
275 $src = !empty($src) ? $src : '';
276 return \strpos($src, '.m3u8') !== false;
277 }
278
279 /**
280 * Get CSS from settings
281 * Validates before output
282 *
283 * @param integer $id
284 * @return string
285 */
286 public function getCSS($id)
287 {
288 return apply_filters(
289 'presto_player/player/css',
290 Utility::sanitizeCSS(
291 Setting::get('branding', 'player_css'),
292 $id
293 )
294 );
295 }
296
297 /**
298 * Gets the preset
299 *
300 * @param integer $id Preset ID
301 * @return \PrestoPlayer\Models\Preset
302 */
303 public function getPreset($id)
304 {
305 $preset = new Preset(!empty($id) ? $id : 0);
306 $preset_id = $preset->id;
307
308 if (empty($preset_id)) {
309 $preset = $preset->findWhere(['slug' => 'default']);
310 }
311
312 // replace watermark text.
313 if (!empty($preset->watermark['enabled'])) {
314 $watermark_text = [
315 'text' => DynamicData::replaceText($preset->watermark['text'])
316 ];
317
318 $preset->watermark = wp_parse_args($watermark_text, $preset->watermark);
319 }
320
321 return apply_filters('presto_player/presto_player_presets/data', $preset, 'video');
322 }
323
324 /**
325 * Gets the audio preset
326 *
327 * @param integer $id Preset ID
328 * @return \PrestoPlayer\Models\AudioPreset
329 */
330 public function getAudioPreset($id)
331 {
332 $preset = new AudioPreset(!empty($id) ? $id : 0);
333 $preset_id = $preset->id;
334
335 if (empty($preset_id)) {
336 $preset = $preset->findWhere(['slug' => 'default']);
337 }
338
339 return apply_filters('presto_player/presto_player_presets/data', $preset, 'audio');
340 }
341
342 /**
343 * Get player branding
344 *
345 * @param \PrestoPlayer\Models\Preset $preset
346 * @return array
347 */
348 public function getBranding($preset)
349 {
350 $branding = Player::getBranding();
351
352 // sanitize with sensible defaults
353 $branding['color'] = !empty($branding['color']) ? sanitize_hex_color($branding['color']) : 'rgba(43,51,63,.7)';
354 $branding['logo_width'] = !empty($branding['logo_width']) ? $branding['logo_width'] : 150;
355 $branding['logo'] = !empty($branding['logo'] && !$preset->hide_logo) ? $branding['logo'] : '';
356
357 return $branding;
358 }
359
360 /**
361 * Get block classes
362 *
363 * @param array $attributes
364 * @return string
365 */
366 public function getClasses($attributes)
367 {
368 $block_alignment = isset($attributes['align']) ? sanitize_text_field($attributes['align']) : '';
369 return !empty($block_alignment) ? 'align' . $block_alignment : '';
370 }
371
372 /**
373 * Get player classes
374 *
375 * @param integer $id
376 * @param \PrestoPlayer\Models\Preset $preset
377 * @return string
378 */
379 public function getPlayerClasses($id, $preset)
380 {
381 $skin = $preset->skin;
382 $playerClass = 'presto-video-id-' . (int) $id;
383 $playerClass .= ' presto-preset-id-' . (int) $preset->id;
384
385 if (!empty($skin)) {
386 $playerClass .= ' skin-' . sanitize_text_field($skin);
387 }
388
389 $caption_style = $preset->caption_style;
390 if (!empty($caption_style)) {
391 $playerClass .= ' caption-style-' . sanitize_html_class($caption_style);
392 }
393
394 if (!empty($attributes['className'])) {
395 $playerClass .= ' ' . (string) $attributes['className'];
396 }
397
398 return $playerClass;
399 }
400
401 /**
402 * Get player styles
403 *
404 * @param \PrestoPlayer\Models\Preset $preset
405 * @param array $branding
406 * @return string
407 */
408 public function getPlayerStyles($preset, $branding)
409 {
410
411 // set brand color.
412 $styles = '--plyr-color-main: ' . sanitize_hex_color(!empty($preset->background_color) ? $preset->background_color : $branding['color']) . '; ';
413
414 // video
415 if ($preset->caption_background) {
416 $styles .= '--plyr-captions-background: ' . sanitize_hex_color($preset->caption_background) . '; ';
417 }
418 if ($preset->border_radius) {
419 $styles .= '--presto-player-border-radius: ' . (int) $preset->border_radius . 'px; ';
420 }
421
422 if ($branding['logo_width']) {
423 $styles .= '--presto-player-logo-width: ' . (int) $branding['logo_width'] . 'px; ';
424 }
425 if (!empty($preset->email_collection['border_radius'])) {
426 $styles .= '--presto-player-email-border-radius: ' . (int) $preset->email_collection['border_radius'] . 'px; ';
427 }
428
429 // audio
430 if ($preset->type === 'audio') {
431 if ($preset->background_color) {
432 $styles .= '--plyr-audio-controls-background: ' . sanitize_hex_color($preset->background_color) . ';';
433 } else {
434 $styles .= '--plyr-audio-controls-background: ' . sanitize_hex_color($branding['color']) . ';';
435 }
436
437 if ($preset->control_color) {
438 $styles .= '--plyr-audio-control-color: ' . sanitize_hex_color($preset->control_color) . ';';
439 $styles .= '--plyr-range-thumb-background: ' . sanitize_hex_color($preset->control_color) . ';';
440 $styles .= '--plyr-range-fill-background: ' . sanitize_hex_color($preset->control_color) . ';';
441 $styles .= '--plyr-audio-progress-buffered-background: ' . Utility::hex2rgba(sanitize_hex_color($preset->control_color), 0.35) . ';';
442 $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) . ';';
443 } else {
444 $styles .= '--plyr-audio-control-color: #ffffff;';
445 $styles .= '--plyr-range-thumb-background: #ffffff;';
446 $styles .= '--plyr-range-fill-background: #ffffff;';
447 $styles .= '--plyr-audio-progress-buffered-background: ' . Utility::hex2rgba(sanitize_hex_color(sanitize_hex_color('#dcdcdc')), 0.35) . ';';
448 }
449 }
450
451 return $styles;
452 }
453
454 /**
455 * Get block attributes
456 *
457 * @param array $attributes
458 * @return array
459 */
460 public function getAttributes($attributes)
461 {
462 return $this->_sanitizeAttibutes($attributes);
463 }
464
465 /**
466 * Dynamic block output
467 *
468 * @param array $attributes
469 * @param string $content
470 * @return void
471 */
472 public function html($attributes, $content)
473 {
474 global $presto_player_instance;
475 if ($presto_player_instance === null) {
476 $presto_player_instance = 0;
477 }
478 $presto_player_instance++;
479
480 // html middleware
481 $load = $this->middleware($attributes, $content);
482
483 if (is_feed()) {
484 return $this->getFeedHtml($attributes);
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