PluginProbe
Elementor Website Builder – more than just a page builder / 3.22.0-dev4
Elementor Website Builder – more than just a page builder v3.22.0-dev4
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / includes / widgets / video.php

video.php in Elementor Website Builder – more than just a page builder 3.22.0-dev4, at includes/widgets/video.php

1,406 lines 33.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor;
3
4 use Elementor\Modules\DynamicTags\Module as TagsModule;
5
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit; // Exit if accessed directly.
8 }
9
10 /**
11 * Elementor video widget.
12 *
13 * Elementor widget that displays a video player.
14 *
15 * @since 1.0.0
16 */
17 class Widget_Video extends Widget_Base {
18
19 /**
20 * Get widget name.
21 *
22 * Retrieve video widget name.
23 *
24 * @since 1.0.0
25 * @access public
26 *
27 * @return string Widget name.
28 */
29 public function get_name() {
30 return 'video';
31 }
32
33 /**
34 * Get widget title.
35 *
36 * Retrieve video widget title.
37 *
38 * @since 1.0.0
39 * @access public
40 *
41 * @return string Widget title.
42 */
43 public function get_title() {
44 return esc_html__( 'Video', 'elementor' );
45 }
46
47 /**
48 * Get widget icon.
49 *
50 * Retrieve video widget icon.
51 *
52 * @since 1.0.0
53 * @access public
54 *
55 * @return string Widget icon.
56 */
57 public function get_icon() {
58 return 'eicon-youtube';
59 }
60
61 /**
62 * Get widget categories.
63 *
64 * Retrieve the list of categories the video widget belongs to.
65 *
66 * Used to determine where to display the widget in the editor.
67 *
68 * @since 2.0.0
69 * @access public
70 *
71 * @return array Widget categories.
72 */
73 public function get_categories() {
74 return [ 'basic' ];
75 }
76
77 /**
78 * Get widget keywords.
79 *
80 * Retrieve the list of keywords the widget belongs to.
81 *
82 * @since 2.1.0
83 * @access public
84 *
85 * @return array Widget keywords.
86 */
87 public function get_keywords() {
88 return [ 'video', 'player', 'embed', 'youtube', 'vimeo', 'dailymotion', 'videopress' ];
89 }
90
91 protected function is_dynamic_content(): bool {
92 return false;
93 }
94
95 /**
96 * Register video widget controls.
97 *
98 * Adds different input fields to allow the user to change and customize the widget settings.
99 *
100 * @since 3.19.0
101 * @access protected
102 *
103 * @return array Widget promotion data.
104 */
105 protected function get_upsale_data() {
106 return [
107 'condition' => ! Utils::has_pro(),
108 'image' => esc_url( ELEMENTOR_ASSETS_URL . 'images/go-pro.svg' ),
109 'image_alt' => esc_attr__( 'Upgrade', 'elementor' ),
110 'title' => esc_html__( "Grab your visitors' attention", 'elementor' ),
111 'description' => esc_html__( 'Get the Video Playlist widget and grow your toolbox with Elementor Pro.', 'elementor' ),
112 'upgrade_url' => esc_url( 'https://go.elementor.com/go-pro-video-widget/' ),
113 'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ),
114 ];
115 }
116
117 /**
118 * Register video widget controls.
119 *
120 * Adds different input fields to allow the user to change and customize the widget settings.
121 *
122 * @since 3.1.0
123 * @access protected
124 */
125 protected function register_controls() {
126 $this->start_controls_section(
127 'section_video',
128 [
129 'label' => esc_html__( 'Video', 'elementor' ),
130 ]
131 );
132
133 $this->add_control(
134 'video_type',
135 [
136 'label' => esc_html__( 'Source', 'elementor' ),
137 'type' => Controls_Manager::SELECT,
138 'default' => 'youtube',
139 'options' => [
140 'youtube' => esc_html__( 'YouTube', 'elementor' ),
141 'vimeo' => esc_html__( 'Vimeo', 'elementor' ),
142 'dailymotion' => esc_html__( 'Dailymotion', 'elementor' ),
143 'videopress' => esc_html__( 'VideoPress', 'elementor' ),
144 'hosted' => esc_html__( 'Self Hosted', 'elementor' ),
145 ],
146 'frontend_available' => true,
147 ]
148 );
149
150 $this->add_control(
151 'youtube_url',
152 [
153 'label' => esc_html__( 'Link', 'elementor' ),
154 'type' => Controls_Manager::TEXT,
155 'dynamic' => [
156 'active' => true,
157 'categories' => [
158 TagsModule::POST_META_CATEGORY,
159 TagsModule::URL_CATEGORY,
160 ],
161 ],
162 'placeholder' => esc_html__( 'Enter your URL', 'elementor' ) . ' (YouTube)',
163 'default' => 'https://www.youtube.com/watch?v=XHOmBV4js_E',
164 'label_block' => true,
165 'condition' => [
166 'video_type' => 'youtube',
167 ],
168 'ai' => [
169 'active' => false,
170 ],
171 'frontend_available' => true,
172 ]
173 );
174
175 $this->add_control(
176 'vimeo_url',
177 [
178 'label' => esc_html__( 'Link', 'elementor' ),
179 'type' => Controls_Manager::TEXT,
180 'dynamic' => [
181 'active' => true,
182 'categories' => [
183 TagsModule::POST_META_CATEGORY,
184 TagsModule::URL_CATEGORY,
185 ],
186 ],
187 'placeholder' => esc_html__( 'Enter your URL', 'elementor' ) . ' (Vimeo)',
188 'default' => 'https://vimeo.com/235215203',
189 'label_block' => true,
190 'condition' => [
191 'video_type' => 'vimeo',
192 ],
193 'ai' => [
194 'active' => false,
195 ],
196 ]
197 );
198
199 $this->add_control(
200 'dailymotion_url',
201 [
202 'label' => esc_html__( 'Link', 'elementor' ),
203 'type' => Controls_Manager::TEXT,
204 'dynamic' => [
205 'active' => true,
206 'categories' => [
207 TagsModule::POST_META_CATEGORY,
208 TagsModule::URL_CATEGORY,
209 ],
210 ],
211 'placeholder' => esc_html__( 'Enter your URL', 'elementor' ) . ' (Dailymotion)',
212 'default' => 'https://www.dailymotion.com/video/x6tqhqb',
213 'label_block' => true,
214 'condition' => [
215 'video_type' => 'dailymotion',
216 ],
217 'ai' => [
218 'active' => false,
219 ],
220 ]
221 );
222
223 $this->add_control(
224 'insert_url',
225 [
226 'label' => esc_html__( 'External URL', 'elementor' ),
227 'type' => Controls_Manager::SWITCHER,
228 'condition' => [
229 'video_type' => [ 'hosted', 'videopress' ],
230 ],
231 ]
232 );
233
234 $this->add_control(
235 'hosted_url',
236 [
237 'label' => esc_html__( 'Choose Video File', 'elementor' ),
238 'type' => Controls_Manager::MEDIA,
239 'dynamic' => [
240 'active' => true,
241 'categories' => [
242 TagsModule::MEDIA_CATEGORY,
243 ],
244 ],
245 'media_types' => [
246 'video',
247 ],
248 'condition' => [
249 'video_type' => [ 'hosted', 'videopress' ],
250 'insert_url' => '',
251 ],
252 ]
253 );
254
255 $this->add_control(
256 'external_url',
257 [
258 'label' => esc_html__( 'URL', 'elementor' ),
259 'type' => Controls_Manager::URL,
260 'autocomplete' => false,
261 'options' => false,
262 'label_block' => true,
263 'show_label' => false,
264 'dynamic' => [
265 'active' => true,
266 'categories' => [
267 TagsModule::POST_META_CATEGORY,
268 TagsModule::URL_CATEGORY,
269 ],
270 ],
271 'placeholder' => esc_html__( 'Enter your URL', 'elementor' ),
272 'condition' => [
273 'video_type' => 'hosted',
274 'insert_url' => 'yes',
275 ],
276 ]
277 );
278
279 $this->add_control(
280 'videopress_url',
281 [
282 'label' => esc_html__( 'URL', 'elementor' ),
283 'type' => Controls_Manager::TEXT,
284 'label_block' => true,
285 'show_label' => false,
286 'default' => 'https://videopress.com/v/ZCAOzTNk',
287 'dynamic' => [
288 'active' => true,
289 'categories' => [
290 TagsModule::POST_META_CATEGORY,
291 TagsModule::URL_CATEGORY,
292 ],
293 ],
294 'placeholder' => esc_html__( 'VideoPress URL', 'elementor' ),
295 'ai' => [
296 'active' => false,
297 ],
298 'condition' => [
299 'video_type' => 'videopress',
300 'insert_url' => 'yes',
301 ],
302
303 ]
304 );
305
306 $this->add_control(
307 'start',
308 [
309 'label' => esc_html__( 'Start Time', 'elementor' ),
310 'type' => Controls_Manager::NUMBER,
311 'description' => esc_html__( 'Specify a start time (in seconds)', 'elementor' ),
312 'frontend_available' => true,
313 'separator' => 'before',
314 ]
315 );
316
317 $this->add_control(
318 'end',
319 [
320 'label' => esc_html__( 'End Time', 'elementor' ),
321 'type' => Controls_Manager::NUMBER,
322 'description' => esc_html__( 'Specify an end time (in seconds)', 'elementor' ),
323 'condition' => [
324 'video_type' => [ 'youtube', 'hosted' ],
325 ],
326 'frontend_available' => true,
327 ]
328 );
329
330 $this->add_control(
331 'video_options',
332 [
333 'label' => esc_html__( 'Video Options', 'elementor' ),
334 'type' => Controls_Manager::HEADING,
335 'separator' => 'before',
336 ]
337 );
338
339 $this->add_control(
340 'autoplay',
341 [
342 'label' => esc_html__( 'Autoplay', 'elementor' ),
343 'type' => Controls_Manager::SWITCHER,
344 'frontend_available' => true,
345 'conditions' => [
346 'relation' => 'or',
347 'terms' => [
348 [
349 'name' => 'show_image_overlay',
350 'value' => '',
351 ],
352 [
353 'name' => 'image_overlay[url]',
354 'value' => '',
355 ],
356 ],
357 ],
358 ]
359 );
360
361 $this->add_control(
362 'play_on_mobile',
363 [
364 'label' => esc_html__( 'Play On Mobile', 'elementor' ),
365 'type' => Controls_Manager::SWITCHER,
366 'condition' => [
367 'autoplay' => 'yes',
368 ],
369 'frontend_available' => true,
370 ]
371 );
372
373 $this->add_control(
374 'mute',
375 [
376 'label' => esc_html__( 'Mute', 'elementor' ),
377 'type' => Controls_Manager::SWITCHER,
378 'frontend_available' => true,
379 ]
380 );
381
382 $this->add_control(
383 'loop',
384 [
385 'label' => esc_html__( 'Loop', 'elementor' ),
386 'type' => Controls_Manager::SWITCHER,
387 'condition' => [
388 'video_type!' => 'dailymotion',
389 ],
390 'frontend_available' => true,
391 ]
392 );
393
394 $this->add_control(
395 'controls',
396 [
397 'label' => esc_html__( 'Player Controls', 'elementor' ),
398 'type' => Controls_Manager::SWITCHER,
399 'label_off' => esc_html__( 'Hide', 'elementor' ),
400 'label_on' => esc_html__( 'Show', 'elementor' ),
401 'default' => 'yes',
402 'condition' => [
403 'video_type!' => 'vimeo',
404 ],
405 'frontend_available' => true,
406 ]
407 );
408
409 $this->add_control(
410 'showinfo',
411 [
412 'label' => esc_html__( 'Video Info', 'elementor' ),
413 'type' => Controls_Manager::SWITCHER,
414 'label_off' => esc_html__( 'Hide', 'elementor' ),
415 'label_on' => esc_html__( 'Show', 'elementor' ),
416 'default' => 'yes',
417 'condition' => [
418 'video_type' => [ 'dailymotion' ],
419 ],
420 ]
421 );
422
423 $this->add_control(
424 'modestbranding',
425 [
426 'label' => esc_html__( 'Modest Branding', 'elementor' ),
427 'type' => Controls_Manager::SWITCHER,
428 'condition' => [
429 'video_type' => [ 'youtube' ],
430 'controls' => 'yes',
431 ],
432 'frontend_available' => true,
433 ]
434 );
435
436 $this->add_control(
437 'logo',
438 [
439 'label' => esc_html__( 'Logo', 'elementor' ),
440 'type' => Controls_Manager::SWITCHER,
441 'label_off' => esc_html__( 'Hide', 'elementor' ),
442 'label_on' => esc_html__( 'Show', 'elementor' ),
443 'default' => 'yes',
444 'condition' => [
445 'video_type' => [ 'dailymotion' ],
446 ],
447 ]
448 );
449
450 // YouTube.
451 $this->add_control(
452 'yt_privacy',
453 [
454 'label' => esc_html__( 'Privacy Mode', 'elementor' ),
455 'type' => Controls_Manager::SWITCHER,
456 'description' => esc_html__( 'When you turn on privacy mode, YouTube/Vimeo won\'t store information about visitors on your website unless they play the video.', 'elementor' ),
457 'condition' => [
458 'video_type' => [ 'youtube', 'vimeo' ],
459 ],
460 'frontend_available' => true,
461 ]
462 );
463
464 $this->add_control(
465 'lazy_load',
466 [
467 'label' => esc_html__( 'Lazy Load', 'elementor' ),
468 'type' => Controls_Manager::SWITCHER,
469 'conditions' => [
470 'relation' => 'or',
471 'terms' => [
472 [
473 'name' => 'video_type',
474 'operator' => '===',
475 'value' => 'youtube',
476 ],
477 [
478 'relation' => 'and',
479 'terms' => [
480 [
481 'name' => 'show_image_overlay',
482 'operator' => '===',
483 'value' => 'yes',
484 ],
485 [
486 'name' => 'video_type',
487 'operator' => '!==',
488 'value' => 'hosted',
489 ],
490 ],
491 ],
492 ],
493 ],
494 'frontend_available' => true,
495 ]
496 );
497
498 $this->add_control(
499 'rel',
500 [
501 'label' => esc_html__( 'Suggested Videos', 'elementor' ),
502 'type' => Controls_Manager::SELECT,
503 'options' => [
504 '' => esc_html__( 'Current Video Channel', 'elementor' ),
505 'yes' => esc_html__( 'Any Video', 'elementor' ),
506 ],
507 'condition' => [
508 'video_type' => 'youtube',
509 ],
510 ]
511 );
512
513 // Vimeo.
514 $this->add_control(
515 'vimeo_title',
516 [
517 'label' => esc_html__( 'Intro Title', 'elementor' ),
518 'type' => Controls_Manager::SWITCHER,
519 'label_off' => esc_html__( 'Hide', 'elementor' ),
520 'label_on' => esc_html__( 'Show', 'elementor' ),
521 'default' => 'yes',
522 'condition' => [
523 'video_type' => 'vimeo',
524 ],
525 ]
526 );
527
528 $this->add_control(
529 'vimeo_portrait',
530 [
531 'label' => esc_html__( 'Intro Portrait', 'elementor' ),
532 'type' => Controls_Manager::SWITCHER,
533 'label_off' => esc_html__( 'Hide', 'elementor' ),
534 'label_on' => esc_html__( 'Show', 'elementor' ),
535 'default' => 'yes',
536 'condition' => [
537 'video_type' => 'vimeo',
538 ],
539 ]
540 );
541
542 $this->add_control(
543 'vimeo_byline',
544 [
545 'label' => esc_html__( 'Intro Byline', 'elementor' ),
546 'type' => Controls_Manager::SWITCHER,
547 'label_off' => esc_html__( 'Hide', 'elementor' ),
548 'label_on' => esc_html__( 'Show', 'elementor' ),
549 'default' => 'yes',
550 'condition' => [
551 'video_type' => 'vimeo',
552 ],
553 ]
554 );
555
556 $this->add_control(
557 'color',
558 [
559 'label' => esc_html__( 'Controls Color', 'elementor' ),
560 'type' => Controls_Manager::COLOR,
561 'default' => '',
562 'condition' => [
563 'video_type' => [ 'vimeo', 'dailymotion' ],
564 ],
565 ]
566 );
567
568 $this->add_control(
569 'download_button',
570 [
571 'label' => esc_html__( 'Download Button', 'elementor' ),
572 'type' => Controls_Manager::SWITCHER,
573 'label_off' => esc_html__( 'Hide', 'elementor' ),
574 'label_on' => esc_html__( 'Show', 'elementor' ),
575 'condition' => [
576 'video_type' => 'hosted',
577 ],
578 ]
579 );
580
581 $this->add_control(
582 'preload',
583 [
584 'label' => esc_html__( 'Preload', 'elementor' ),
585 'type' => Controls_Manager::SELECT,
586 'options' => [
587 'metadata' => esc_html__( 'Metadata', 'elementor' ),
588 'auto' => esc_html__( 'Auto', 'elementor' ),
589 'none' => esc_html__( 'None', 'elementor' ),
590 ],
591 'description' => sprintf(
592 '%1$s <a target="_blank" href="https://go.elementor.com/preload-video/">%2$s</a>',
593 esc_html__( 'Preload attribute lets you specify how the video should be loaded when the page loads.', 'elementor' ),
594 esc_html__( 'Learn more', 'elementor' ),
595 ),
596 'default' => 'metadata',
597 'condition' => [
598 'video_type' => 'hosted',
599 'autoplay' => '',
600 ],
601 ]
602 );
603
604 $this->add_control(
605 'poster',
606 [
607 'label' => esc_html__( 'Poster', 'elementor' ),
608 'type' => Controls_Manager::MEDIA,
609 'dynamic' => [
610 'active' => true,
611 ],
612 'condition' => [
613 'video_type' => 'hosted',
614 ],
615 ]
616 );
617
618 $this->end_controls_section();
619
620 $this->start_controls_section(
621 'section_image_overlay',
622 [
623 'label' => esc_html__( 'Image Overlay', 'elementor' ),
624 ]
625 );
626
627 $this->add_control(
628 'show_image_overlay',
629 [
630 'label' => esc_html__( 'Image Overlay', 'elementor' ),
631 'type' => Controls_Manager::SWITCHER,
632 'label_off' => esc_html__( 'Hide', 'elementor' ),
633 'label_on' => esc_html__( 'Show', 'elementor' ),
634 'frontend_available' => true,
635 ]
636 );
637
638 $this->add_control(
639 'image_overlay',
640 [
641 'label' => esc_html__( 'Choose Image', 'elementor' ),
642 'type' => Controls_Manager::MEDIA,
643 'default' => [
644 'url' => Utils::get_placeholder_image_src(),
645 ],
646 'dynamic' => [
647 'active' => true,
648 ],
649 'condition' => [
650 'show_image_overlay' => 'yes',
651 ],
652 'frontend_available' => true,
653 ]
654 );
655
656 $this->add_group_control(
657 Group_Control_Image_Size::get_type(),
658 [
659 'name' => 'image_overlay', // Usage: `{name}_size` and `{name}_custom_dimension`, in this case `image_overlay_size` and `image_overlay_custom_dimension`.
660 'default' => 'full',
661 'condition' => [
662 'show_image_overlay' => 'yes',
663 ],
664 ]
665 );
666
667 $this->add_control(
668 'show_play_icon',
669 [
670 'label' => esc_html__( 'Play Icon', 'elementor' ),
671 'type' => Controls_Manager::SWITCHER,
672 'default' => 'yes',
673 'label_off' => esc_html__( 'Hide', 'elementor' ),
674 'label_on' => esc_html__( 'Show', 'elementor' ),
675 'separator' => 'before',
676 'condition' => [
677 'show_image_overlay' => 'yes',
678 'image_overlay[url]!' => '',
679 ],
680 ]
681 );
682
683 $this->add_control(
684 'play_icon',
685 [
686 'label' => esc_html__( 'Icon', 'elementor' ),
687 'type' => Controls_Manager::ICONS,
688 'fa4compatibility' => 'icon',
689 'skin' => 'inline',
690 'label_block' => false,
691 'skin_settings' => [
692 'inline' => [
693 'none' => [
694 'label' => 'Default',
695 'icon' => 'eicon-play',
696 ],
697 'icon' => [
698 'icon' => 'eicon-star',
699 ],
700 ],
701 ],
702 'recommended' => [
703 'fa-regular' => [
704 'play-circle',
705 ],
706 'fa-solid' => [
707 'play',
708 'play-circle',
709 ],
710 ],
711 'condition' => [
712 'show_image_overlay' => 'yes',
713 'show_play_icon!' => '',
714 ],
715 ]
716 );
717
718 $this->add_control(
719 'lightbox',
720 [
721 'label' => esc_html__( 'Lightbox', 'elementor' ),
722 'type' => Controls_Manager::SWITCHER,
723 'frontend_available' => true,
724 'label_off' => esc_html__( 'Off', 'elementor' ),
725 'label_on' => esc_html__( 'On', 'elementor' ),
726 'condition' => [
727 'show_image_overlay' => 'yes',
728 'image_overlay[url]!' => '',
729 ],
730 'separator' => 'before',
731 ]
732 );
733
734 $this->end_controls_section();
735
736 $this->start_controls_section(
737 'section_video_style',
738 [
739 'label' => esc_html__( 'Video', 'elementor' ),
740 'tab' => Controls_Manager::TAB_STYLE,
741 ]
742 );
743
744 $this->add_control(
745 'aspect_ratio',
746 [
747 'label' => esc_html__( 'Aspect Ratio', 'elementor' ),
748 'type' => Controls_Manager::SELECT,
749 'options' => [
750 '169' => '16:9',
751 '219' => '21:9',
752 '43' => '4:3',
753 '32' => '3:2',
754 '11' => '1:1',
755 '916' => '9:16',
756 ],
757 'selectors_dictionary' => [
758 '169' => '1.77777', // 16 / 9
759 '219' => '2.33333', // 21 / 9
760 '43' => '1.33333', // 4 / 3
761 '32' => '1.5', // 3 / 2
762 '11' => '1', // 1 / 1
763 '916' => '0.5625', // 9 / 16
764 ],
765 'default' => '169',
766 'selectors' => [
767 '{{WRAPPER}} .elementor-wrapper' => '--video-aspect-ratio: {{VALUE}}',
768 ],
769 ]
770 );
771
772 $this->add_group_control(
773 Group_Control_Css_Filter::get_type(),
774 [
775 'name' => 'css_filters',
776 'selector' => '{{WRAPPER}} .elementor-wrapper',
777 ]
778 );
779
780 $this->end_controls_section();
781
782 $this->start_controls_section(
783 'section_image_overlay_style',
784 [
785 'label' => esc_html__( 'Image Overlay', 'elementor' ),
786 'tab' => Controls_Manager::TAB_STYLE,
787 'condition' => [
788 'show_image_overlay' => 'yes',
789 'show_play_icon' => 'yes',
790 ],
791 ]
792 );
793
794 $this->add_control(
795 'play_icon_title',
796 [
797 'label' => esc_html__( 'Play Icon', 'elementor' ),
798 'type' => Controls_Manager::HEADING,
799 'condition' => [
800 'show_image_overlay' => 'yes',
801 'show_play_icon' => 'yes',
802 ],
803 ]
804 );
805
806 $this->add_control(
807 'play_icon_color',
808 [
809 'label' => esc_html__( 'Color', 'elementor' ),
810 'type' => Controls_Manager::COLOR,
811 'selectors' => [
812 '{{WRAPPER}} .elementor-custom-embed-play i' => 'color: {{VALUE}}',
813 '{{WRAPPER}} .elementor-custom-embed-play svg' => 'fill: {{VALUE}}',
814 ],
815 'condition' => [
816 'show_image_overlay' => 'yes',
817 'show_play_icon' => 'yes',
818 ],
819 ]
820 );
821
822 $this->add_responsive_control(
823 'play_icon_size',
824 [
825 'label' => esc_html__( 'Size', 'elementor' ),
826 'type' => Controls_Manager::SLIDER,
827 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
828 'range' => [
829 'px' => [
830 'min' => 10,
831 'max' => 300,
832 ],
833 ],
834 'selectors' => [
835 // Not using a CSS vars because the default size value is coming from a global scss file.
836 '{{WRAPPER}} .elementor-custom-embed-play i' => 'font-size: {{SIZE}}{{UNIT}}',
837 '{{WRAPPER}} .elementor-custom-embed-play svg' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}};',
838 ],
839 'condition' => [
840 'show_image_overlay' => 'yes',
841 'show_play_icon' => 'yes',
842 ],
843 ]
844 );
845
846 $this->add_group_control(
847 Group_Control_Text_Shadow::get_type(),
848 [
849 'name' => 'play_icon_text_shadow',
850 'selector' => '{{WRAPPER}} .elementor-custom-embed-play i',
851 'fields_options' => [
852 'text_shadow_type' => [
853 'label' => esc_html__( 'Shadow', 'elementor' ),
854 ],
855 ],
856 'condition' => [
857 'show_image_overlay' => 'yes',
858 'show_play_icon' => 'yes',
859 'play_icon[library]!' => 'svg',
860 ],
861 ]
862 );
863
864 $this->end_controls_section();
865
866 $this->start_controls_section(
867 'section_lightbox_style',
868 [
869 'label' => esc_html__( 'Lightbox', 'elementor' ),
870 'tab' => Controls_Manager::TAB_STYLE,
871 'condition' => [
872 'show_image_overlay' => 'yes',
873 'image_overlay[url]!' => '',
874 'lightbox' => 'yes',
875 ],
876 ]
877 );
878
879 $this->add_control(
880 'lightbox_color',
881 [
882 'label' => esc_html__( 'Background Color', 'elementor' ),
883 'type' => Controls_Manager::COLOR,
884 'selectors' => [
885 '#elementor-lightbox-{{ID}}' => 'background-color: {{VALUE}};',
886 ],
887 ]
888 );
889
890 $this->add_control(
891 'lightbox_ui_color',
892 [
893 'label' => esc_html__( 'UI Color', 'elementor' ),
894 'type' => Controls_Manager::COLOR,
895 'selectors' => [
896 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button' => 'color: {{VALUE}}',
897 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button svg' => 'fill: {{VALUE}}',
898 ],
899 ]
900 );
901
902 $this->add_control(
903 'lightbox_ui_color_hover',
904 [
905 'label' => esc_html__( 'UI Hover Color', 'elementor' ),
906 'type' => Controls_Manager::COLOR,
907 'selectors' => [
908 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button:hover' => 'color: {{VALUE}}',
909 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button:hover svg' => 'fill: {{VALUE}}',
910 ],
911 ]
912 );
913
914 $this->add_responsive_control(
915 'lightbox_content_animation',
916 [
917 'label' => esc_html__( 'Entrance Animation', 'elementor' ),
918 'type' => Controls_Manager::ANIMATION,
919 'frontend_available' => true,
920 'separator' => 'before',
921 ]
922 );
923
924 $this->add_control(
925 'deprecation_warning',
926 [
927 'type' => Controls_Manager::ALERT,
928 'alert_type' => 'danger',
929 'content' => esc_html__( 'Note: These controls have been deprecated and are only visible if they were previously in use. The video’s width and position are now set based on its aspect ratio.', 'elementor' ),
930 'separator' => 'before',
931 'condition' => [
932 'lightbox_video_width!' => '',
933 'lightbox_content_position!' => '',
934 ],
935 ]
936 );
937
938 // Deprecated control. Visible only if it was previously in use.
939 $this->add_control(
940 'lightbox_video_width',
941 [
942 'label' => esc_html__( 'Content Width', 'elementor' ),
943 'type' => Controls_Manager::SLIDER,
944 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
945 'default' => [
946 'unit' => '%',
947 ],
948 // 'selectors' => [
949 // '(desktop+)#elementor-lightbox-{{ID}} .elementor-video-container' => 'width: {{SIZE}}{{UNIT}};',
950 // ],
951 'condition' => [
952 'lightbox_video_width!' => '',
953 'lightbox_content_position!' => '',
954 ],
955 ]
956 );
957
958 // Deprecated control. Visible only if it was previously in use.
959 $this->add_control(
960 'lightbox_content_position',
961 [
962 'label' => esc_html__( 'Content Position', 'elementor' ),
963 'type' => Controls_Manager::SELECT,
964 'frontend_available' => true,
965 'options' => [
966 '' => esc_html__( 'Center', 'elementor' ),
967 'top' => esc_html__( 'Top', 'elementor' ),
968 ],
969 // 'selectors' => [
970 // '#elementor-lightbox-{{ID}} .elementor-video-container' => '{{VALUE}}; transform: translateX(-50%);',
971 // ],
972 'selectors_dictionary' => [
973 'top' => 'top: 60px',
974 ],
975 'condition' => [
976 'lightbox_video_width!' => '',
977 'lightbox_content_position!' => '',
978 ],
979 ]
980 );
981
982 $this->end_controls_section();
983 }
984
985 public function print_a11y_text( $image_overlay ) {
986 if ( empty( $image_overlay['alt'] ) ) {
987 echo esc_html__( 'Play Video', 'elementor' );
988 } else {
989 echo esc_html__( 'Play Video about', 'elementor' ) . ' ' . esc_attr( $image_overlay['alt'] );
990 }
991 }
992
993 /**
994 * Render video widget output on the frontend.
995 *
996 * Written in PHP and used to generate the final HTML.
997 *
998 * @since 1.0.0
999 * @access protected
1000 */
1001 protected function render() {
1002 $settings = $this->get_settings_for_display();
1003
1004 $video_url = $settings[ $settings['video_type'] . '_url' ];
1005
1006 if ( 'hosted' === $settings['video_type'] ) {
1007 $video_url = $this->get_hosted_video_url();
1008 } else {
1009 if ( 'videopress' === $settings['video_type'] ) {
1010 $video_url = $this->get_videopress_video_url();
1011 }
1012
1013 $embed_params = $this->get_embed_params();
1014 $embed_options = $this->get_embed_options();
1015 }
1016
1017 if ( empty( $video_url ) ) {
1018 return;
1019 }
1020
1021 if ( 'youtube' === $settings['video_type'] ) {
1022 $video_html = '<div class="elementor-video"></div>';
1023 }
1024
1025 if ( 'hosted' === $settings['video_type'] ) {
1026 $this->add_render_attribute( 'video-wrapper', 'class', 'e-hosted-video' );
1027
1028 ob_start();
1029
1030 $this->render_hosted_video();
1031
1032 $video_html = ob_get_clean();
1033 } else {
1034 $is_static_render_mode = Plugin::$instance->frontend->is_static_render_mode();
1035 $post_id = get_queried_object_id();
1036
1037 if ( $is_static_render_mode ) {
1038 $video_html = Embed::get_embed_thumbnail_html( $video_url, $post_id );
1039 // YouTube API requires a different markup which was set above.
1040 } else if ( 'youtube' !== $settings['video_type'] ) {
1041 $video_html = Embed::get_embed_html( $video_url, $embed_params, $embed_options );
1042 }
1043 }
1044
1045 if ( empty( $video_html ) ) {
1046 echo esc_url( $video_url );
1047
1048 return;
1049 }
1050
1051 $this->add_render_attribute( 'video-wrapper', 'class', 'elementor-wrapper' );
1052
1053 $this->add_render_attribute( 'video-wrapper', 'class', 'elementor-open-' . ( $settings['lightbox'] ? 'lightbox' : 'inline' ) );
1054 ?>
1055 <div <?php $this->print_render_attribute_string( 'video-wrapper' ); ?>>
1056 <?php
1057 if ( ! $settings['lightbox'] ) {
1058 Utils::print_unescaped_internal_string( $video_html ); // XSS ok.
1059 }
1060
1061 if ( $this->has_image_overlay() ) {
1062 $this->add_render_attribute( 'image-overlay', 'class', 'elementor-custom-embed-image-overlay' );
1063
1064 if ( $settings['lightbox'] ) {
1065 if ( 'hosted' === $settings['video_type'] ) {
1066 $lightbox_url = $video_url;
1067 } else {
1068 $lightbox_url = Embed::get_embed_url( $video_url, $embed_params, $embed_options );
1069 }
1070
1071 $lightbox_options = [
1072 'type' => 'video',
1073 'videoType' => $settings['video_type'],
1074 'url' => $lightbox_url,
1075 'modalOptions' => [
1076 'id' => 'elementor-lightbox-' . $this->get_id(),
1077 'entranceAnimation' => $settings['lightbox_content_animation'],
1078 'entranceAnimation_tablet' => $settings['lightbox_content_animation_tablet'],
1079 'entranceAnimation_mobile' => $settings['lightbox_content_animation_mobile'],
1080 'videoAspectRatio' => $settings['aspect_ratio'],
1081 ],
1082 ];
1083
1084 if ( 'hosted' === $settings['video_type'] ) {
1085 $lightbox_options['videoParams'] = $this->get_hosted_params();
1086 }
1087
1088 $this->add_render_attribute( 'image-overlay', [
1089 'data-elementor-open-lightbox' => 'yes',
1090 'data-elementor-lightbox' => wp_json_encode( $lightbox_options ),
1091 'data-e-action-hash' => Plugin::instance()->frontend->create_action_hash( 'lightbox', $lightbox_options ),
1092 ] );
1093
1094 if ( Plugin::$instance->editor->is_edit_mode() ) {
1095 $this->add_render_attribute( 'image-overlay', [
1096 'class' => 'elementor-clickable',
1097 ] );
1098 }
1099 } else {
1100 // When there is an image URL but no ID, it means the overlay image is the placeholder. In this case, get the placeholder URL.
1101 if ( empty( $settings['image_overlay']['id'] && ! empty( $settings['image_overlay']['url'] ) ) ) {
1102 $image_url = $settings['image_overlay']['url'];
1103 } else {
1104 $image_url = Group_Control_Image_Size::get_attachment_image_src( $settings['image_overlay']['id'], 'image_overlay', $settings );
1105 }
1106
1107 $this->add_render_attribute( 'image-overlay', 'style', 'background-image: url(' . $image_url . ');' );
1108 }
1109 ?>
1110 <div <?php $this->print_render_attribute_string( 'image-overlay' ); ?>>
1111 <?php if ( $settings['lightbox'] ) : ?>
1112 <?php Group_Control_Image_Size::print_attachment_image_html( $settings, 'image_overlay' ); ?>
1113 <?php endif; ?>
1114 <?php if ( 'yes' === $settings['show_play_icon'] ) : ?>
1115 <div class="elementor-custom-embed-play" role="button" aria-label="<?php $this->print_a11y_text( $settings['image_overlay'] ); ?>" tabindex="0">
1116 <?php
1117 if ( empty( $settings['play_icon']['value'] ) ) {
1118 $settings['play_icon'] = [
1119 'library' => 'eicons',
1120 'value' => 'eicon-play',
1121 ];
1122 }
1123 Icons_Manager::render_icon( $settings['play_icon'], [ 'aria-hidden' => 'true' ] );
1124 ?>
1125 <span class="elementor-screen-only"><?php $this->print_a11y_text( $settings['image_overlay'] ); ?></span>
1126 </div>
1127 <?php endif; ?>
1128 </div>
1129 <?php } ?>
1130 </div>
1131 <?php
1132 }
1133
1134 /**
1135 * Render video widget as plain content.
1136 *
1137 * Override the default behavior, by printing the video URL insted of rendering it.
1138 *
1139 * @since 1.4.5
1140 * @access public
1141 */
1142 public function render_plain_content() {
1143 $settings = $this->get_settings_for_display();
1144
1145 if ( 'hosted' !== $settings['video_type'] ) {
1146 $url = $settings[ $settings['video_type'] . '_url' ];
1147 } else {
1148 $url = $this->get_hosted_video_url();
1149 }
1150
1151 echo esc_url( $url );
1152 }
1153
1154 /**
1155 * Get embed params.
1156 *
1157 * Retrieve video widget embed parameters.
1158 *
1159 * @since 1.5.0
1160 * @access public
1161 *
1162 * @return array Video embed parameters.
1163 */
1164 public function get_embed_params() {
1165 $settings = $this->get_settings_for_display();
1166
1167 $params = [];
1168
1169 if ( $settings['autoplay'] && ! $this->has_image_overlay() ) {
1170 $params['autoplay'] = '1';
1171
1172 if ( $settings['play_on_mobile'] ) {
1173 $params['playsinline'] = '1';
1174 }
1175 }
1176
1177 $params_dictionary = [];
1178
1179 if ( 'youtube' === $settings['video_type'] ) {
1180 $params_dictionary = [
1181 'loop',
1182 'controls',
1183 'mute',
1184 'rel',
1185 'modestbranding',
1186 ];
1187
1188 if ( $settings['loop'] ) {
1189 $video_properties = Embed::get_video_properties( $settings['youtube_url'] );
1190
1191 $params['playlist'] = $video_properties['video_id'];
1192 }
1193
1194 $params['start'] = $settings['start'];
1195
1196 $params['end'] = $settings['end'];
1197
1198 $params['wmode'] = 'opaque';
1199 } elseif ( 'vimeo' === $settings['video_type'] ) {
1200 $params_dictionary = [
1201 'loop',
1202 'mute' => 'muted',
1203 'vimeo_title' => 'title',
1204 'vimeo_portrait' => 'portrait',
1205 'vimeo_byline' => 'byline',
1206 ];
1207
1208 $params['color'] = str_replace( '#', '', $settings['color'] );
1209
1210 $params['autopause'] = '0';
1211
1212 if ( ! empty( $settings['yt_privacy'] ) ) {
1213 $params['dnt'] = 'true';
1214 }
1215 } elseif ( 'dailymotion' === $settings['video_type'] ) {
1216 $params_dictionary = [
1217 'controls',
1218 'mute',
1219 'showinfo' => 'ui-start-screen-info',
1220 'logo' => 'ui-logo',
1221 ];
1222
1223 $params['ui-highlight'] = str_replace( '#', '', $settings['color'] );
1224
1225 $params['start'] = $settings['start'];
1226
1227 $params['endscreen-enable'] = '0';
1228 } elseif ( 'videopress' === $settings['video_type'] ) {
1229 $params_dictionary = $this->get_params_dictionary_for_videopress();
1230
1231 $params['at'] = $settings['start'];
1232 }
1233
1234 foreach ( $params_dictionary as $key => $param_name ) {
1235 $setting_name = $param_name;
1236
1237 if ( is_string( $key ) ) {
1238 $setting_name = $key;
1239 }
1240
1241 $setting_value = $settings[ $setting_name ] ? '1' : '0';
1242
1243 $params[ $param_name ] = $setting_value;
1244 }
1245
1246 return $params;
1247 }
1248
1249 /**
1250 * Whether the video widget has an overlay image or not.
1251 *
1252 * Used to determine whether an overlay image was set for the video.
1253 *
1254 * @since 1.0.0
1255 * @access protected
1256 *
1257 * @return bool Whether an image overlay was set for the video.
1258 */
1259 protected function has_image_overlay() {
1260 $settings = $this->get_settings_for_display();
1261
1262 return ! empty( $settings['image_overlay']['url'] ) && 'yes' === $settings['show_image_overlay'];
1263 }
1264
1265 /**
1266 * @since 2.1.0
1267 * @access private
1268 */
1269 private function get_embed_options() {
1270 $settings = $this->get_settings_for_display();
1271
1272 $embed_options = [];
1273
1274 if ( 'youtube' === $settings['video_type'] ) {
1275 $embed_options['privacy'] = $settings['yt_privacy'];
1276 } elseif ( 'vimeo' === $settings['video_type'] ) {
1277 $embed_options['start'] = $settings['start'];
1278 }
1279
1280 $embed_options['lazy_load'] = ! empty( $settings['lazy_load'] );
1281
1282 return $embed_options;
1283 }
1284
1285 /**
1286 * @since 2.1.0
1287 * @access private
1288 */
1289 private function get_hosted_params() {
1290 $settings = $this->get_settings_for_display();
1291
1292 $video_params = [];
1293
1294 foreach ( [ 'autoplay', 'loop', 'controls' ] as $option_name ) {
1295 if ( $settings[ $option_name ] ) {
1296 $video_params[ $option_name ] = '';
1297 }
1298 }
1299
1300 if ( $settings['preload'] ) {
1301 $video_params['preload'] = $settings['preload'];
1302 }
1303
1304 if ( $settings['mute'] ) {
1305 $video_params['muted'] = 'muted';
1306 }
1307
1308 if ( $settings['play_on_mobile'] ) {
1309 $video_params['playsinline'] = '';
1310 }
1311
1312 if ( ! $settings['download_button'] ) {
1313 $video_params['controlsList'] = 'nodownload';
1314 }
1315
1316 if ( $settings['poster']['url'] ) {
1317 $video_params['poster'] = $settings['poster']['url'];
1318 }
1319
1320 return $video_params;
1321 }
1322
1323 /**
1324 * @param bool $from_media
1325 *
1326 * @return string
1327 * @since 2.1.0
1328 * @access private
1329 */
1330 private function get_hosted_video_url() {
1331 $settings = $this->get_settings_for_display();
1332
1333 if ( ! empty( $settings['insert_url'] ) ) {
1334 $video_url = $settings['external_url']['url'];
1335 } else {
1336 $video_url = $settings['hosted_url']['url'];
1337 }
1338
1339 if ( empty( $video_url ) ) {
1340 return '';
1341 }
1342
1343 if ( $settings['start'] || $settings['end'] ) {
1344 $video_url .= '#t=';
1345 }
1346
1347 if ( $settings['start'] ) {
1348 $video_url .= $settings['start'];
1349 }
1350
1351 if ( $settings['end'] ) {
1352 $video_url .= ',' . $settings['end'];
1353 }
1354
1355 return $video_url;
1356 }
1357
1358 /**
1359 * Get the VideoPress video URL from the current selected settings.
1360 *
1361 * @return string
1362 */
1363 private function get_videopress_video_url() {
1364 $settings = $this->get_settings_for_display();
1365
1366 if ( ! empty( $settings['insert_url'] ) ) {
1367 return $settings['videopress_url'];
1368 }
1369
1370 return $settings['hosted_url']['url'];
1371 }
1372
1373 /**
1374 * Get the params dictionary for VideoPress videos.
1375 *
1376 * @return array
1377 */
1378 private function get_params_dictionary_for_videopress() {
1379 return [
1380 'controls',
1381 'autoplay' => 'autoPlay',
1382 'mute' => 'muted',
1383 'loop',
1384 'play_on_mobile' => 'playsinline',
1385 ];
1386 }
1387
1388 /**
1389 *
1390 * @since 2.1.0
1391 * @access private
1392 */
1393 private function render_hosted_video() {
1394 $video_url = $this->get_hosted_video_url();
1395 if ( empty( $video_url ) ) {
1396 return;
1397 }
1398
1399 $video_params = $this->get_hosted_params();
1400 /* Sometimes the video url is base64, therefore we use `esc_attr` in `src`. */
1401 ?>
1402 <video class="elementor-video" src="<?php echo esc_attr( $video_url ); ?>" <?php Utils::print_html_attributes( $video_params ); ?>></video>
1403 <?php
1404 }
1405 }
1406