PluginProbe
Elementor Website Builder – more than just a page builder / 3.6.4
Elementor Website Builder – more than just a page builder v3.6.4
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.6.4, at includes/widgets/video.php

1,201 lines 28.4 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' ];
89 }
90
91 /**
92 * Register video widget controls.
93 *
94 * Adds different input fields to allow the user to change and customize the widget settings.
95 *
96 * @since 3.1.0
97 * @access protected
98 */
99 protected function register_controls() {
100 $this->start_controls_section(
101 'section_video',
102 [
103 'label' => esc_html__( 'Video', 'elementor' ),
104 ]
105 );
106
107 $this->add_control(
108 'video_type',
109 [
110 'label' => esc_html__( 'Source', 'elementor' ),
111 'type' => Controls_Manager::SELECT,
112 'default' => 'youtube',
113 'options' => [
114 'youtube' => esc_html__( 'YouTube', 'elementor' ),
115 'vimeo' => esc_html__( 'Vimeo', 'elementor' ),
116 'dailymotion' => esc_html__( 'Dailymotion', 'elementor' ),
117 'hosted' => esc_html__( 'Self Hosted', 'elementor' ),
118 ],
119 'frontend_available' => true,
120 ]
121 );
122
123 $this->add_control(
124 'youtube_url',
125 [
126 'label' => esc_html__( 'Link', 'elementor' ),
127 'type' => Controls_Manager::TEXT,
128 'dynamic' => [
129 'active' => true,
130 'categories' => [
131 TagsModule::POST_META_CATEGORY,
132 TagsModule::URL_CATEGORY,
133 ],
134 ],
135 'placeholder' => esc_html__( 'Enter your URL', 'elementor' ) . ' (YouTube)',
136 'default' => 'https://www.youtube.com/watch?v=XHOmBV4js_E',
137 'label_block' => true,
138 'condition' => [
139 'video_type' => 'youtube',
140 ],
141 'frontend_available' => true,
142 ]
143 );
144
145 $this->add_control(
146 'vimeo_url',
147 [
148 'label' => esc_html__( 'Link', 'elementor' ),
149 'type' => Controls_Manager::TEXT,
150 'dynamic' => [
151 'active' => true,
152 'categories' => [
153 TagsModule::POST_META_CATEGORY,
154 TagsModule::URL_CATEGORY,
155 ],
156 ],
157 'placeholder' => esc_html__( 'Enter your URL', 'elementor' ) . ' (Vimeo)',
158 'default' => 'https://vimeo.com/235215203',
159 'label_block' => true,
160 'condition' => [
161 'video_type' => 'vimeo',
162 ],
163 ]
164 );
165
166 $this->add_control(
167 'dailymotion_url',
168 [
169 'label' => esc_html__( 'Link', 'elementor' ),
170 'type' => Controls_Manager::TEXT,
171 'dynamic' => [
172 'active' => true,
173 'categories' => [
174 TagsModule::POST_META_CATEGORY,
175 TagsModule::URL_CATEGORY,
176 ],
177 ],
178 'placeholder' => esc_html__( 'Enter your URL', 'elementor' ) . ' (Dailymotion)',
179 'default' => 'https://www.dailymotion.com/video/x6tqhqb',
180 'label_block' => true,
181 'condition' => [
182 'video_type' => 'dailymotion',
183 ],
184 ]
185 );
186
187 $this->add_control(
188 'insert_url',
189 [
190 'label' => esc_html__( 'External URL', 'elementor' ),
191 'type' => Controls_Manager::SWITCHER,
192 'condition' => [
193 'video_type' => 'hosted',
194 ],
195 ]
196 );
197
198 $this->add_control(
199 'hosted_url',
200 [
201 'label' => esc_html__( 'Choose File', 'elementor' ),
202 'type' => Controls_Manager::MEDIA,
203 'dynamic' => [
204 'active' => true,
205 'categories' => [
206 TagsModule::MEDIA_CATEGORY,
207 ],
208 ],
209 'media_type' => 'video',
210 'condition' => [
211 'video_type' => 'hosted',
212 'insert_url' => '',
213 ],
214 ]
215 );
216
217 $this->add_control(
218 'external_url',
219 [
220 'label' => esc_html__( 'URL', 'elementor' ),
221 'type' => Controls_Manager::URL,
222 'autocomplete' => false,
223 'options' => false,
224 'label_block' => true,
225 'show_label' => false,
226 'dynamic' => [
227 'active' => true,
228 'categories' => [
229 TagsModule::POST_META_CATEGORY,
230 TagsModule::URL_CATEGORY,
231 ],
232 ],
233 'media_type' => 'video',
234 'placeholder' => esc_html__( 'Enter your URL', 'elementor' ),
235 'condition' => [
236 'video_type' => 'hosted',
237 'insert_url' => 'yes',
238 ],
239 ]
240 );
241
242 $this->add_control(
243 'start',
244 [
245 'label' => esc_html__( 'Start Time', 'elementor' ),
246 'type' => Controls_Manager::NUMBER,
247 'description' => esc_html__( 'Specify a start time (in seconds)', 'elementor' ),
248 'frontend_available' => true,
249 ]
250 );
251
252 $this->add_control(
253 'end',
254 [
255 'label' => esc_html__( 'End Time', 'elementor' ),
256 'type' => Controls_Manager::NUMBER,
257 'description' => esc_html__( 'Specify an end time (in seconds)', 'elementor' ),
258 'condition' => [
259 'video_type' => [ 'youtube', 'hosted' ],
260 ],
261 'frontend_available' => true,
262 ]
263 );
264
265 $this->add_control(
266 'video_options',
267 [
268 'label' => esc_html__( 'Video Options', 'elementor' ),
269 'type' => Controls_Manager::HEADING,
270 'separator' => 'before',
271 ]
272 );
273
274 $this->add_control(
275 'autoplay',
276 [
277 'label' => esc_html__( 'Autoplay', 'elementor' ),
278 'type' => Controls_Manager::SWITCHER,
279 'frontend_available' => true,
280 'conditions' => [
281 'relation' => 'or',
282 'terms' => [
283 [
284 'name' => 'show_image_overlay',
285 'value' => '',
286 ],
287 [
288 'name' => 'image_overlay[url]',
289 'value' => '',
290 ],
291 ],
292 ],
293 ]
294 );
295
296 $this->add_control(
297 'play_on_mobile',
298 [
299 'label' => esc_html__( 'Play On Mobile', 'elementor' ),
300 'type' => Controls_Manager::SWITCHER,
301 'condition' => [
302 'autoplay' => 'yes',
303 ],
304 'frontend_available' => true,
305 ]
306 );
307
308 $this->add_control(
309 'mute',
310 [
311 'label' => esc_html__( 'Mute', 'elementor' ),
312 'type' => Controls_Manager::SWITCHER,
313 'frontend_available' => true,
314 ]
315 );
316
317 $this->add_control(
318 'loop',
319 [
320 'label' => esc_html__( 'Loop', 'elementor' ),
321 'type' => Controls_Manager::SWITCHER,
322 'condition' => [
323 'video_type!' => 'dailymotion',
324 ],
325 'frontend_available' => true,
326 ]
327 );
328
329 $this->add_control(
330 'controls',
331 [
332 'label' => esc_html__( 'Player Controls', 'elementor' ),
333 'type' => Controls_Manager::SWITCHER,
334 'label_off' => esc_html__( 'Hide', 'elementor' ),
335 'label_on' => esc_html__( 'Show', 'elementor' ),
336 'default' => 'yes',
337 'condition' => [
338 'video_type!' => 'vimeo',
339 ],
340 'frontend_available' => true,
341 ]
342 );
343
344 $this->add_control(
345 'showinfo',
346 [
347 'label' => esc_html__( 'Video Info', 'elementor' ),
348 'type' => Controls_Manager::SWITCHER,
349 'label_off' => esc_html__( 'Hide', 'elementor' ),
350 'label_on' => esc_html__( 'Show', 'elementor' ),
351 'default' => 'yes',
352 'condition' => [
353 'video_type' => [ 'dailymotion' ],
354 ],
355 ]
356 );
357
358 $this->add_control(
359 'modestbranding',
360 [
361 'label' => esc_html__( 'Modest Branding', 'elementor' ),
362 'type' => Controls_Manager::SWITCHER,
363 'condition' => [
364 'video_type' => [ 'youtube' ],
365 'controls' => 'yes',
366 ],
367 'frontend_available' => true,
368 ]
369 );
370
371 $this->add_control(
372 'logo',
373 [
374 'label' => esc_html__( 'Logo', 'elementor' ),
375 'type' => Controls_Manager::SWITCHER,
376 'label_off' => esc_html__( 'Hide', 'elementor' ),
377 'label_on' => esc_html__( 'Show', 'elementor' ),
378 'default' => 'yes',
379 'condition' => [
380 'video_type' => [ 'dailymotion' ],
381 ],
382 ]
383 );
384
385 // YouTube.
386 $this->add_control(
387 'yt_privacy',
388 [
389 'label' => esc_html__( 'Privacy Mode', 'elementor' ),
390 'type' => Controls_Manager::SWITCHER,
391 'description' => esc_html__( 'When you turn on privacy mode, YouTube won\'t store information about visitors on your website unless they play the video.', 'elementor' ),
392 'condition' => [
393 'video_type' => 'youtube',
394 ],
395 'frontend_available' => true,
396 ]
397 );
398
399 $this->add_control(
400 'lazy_load',
401 [
402 'label' => esc_html__( 'Lazy Load', 'elementor' ),
403 'type' => Controls_Manager::SWITCHER,
404 'conditions' => [
405 'relation' => 'or',
406 'terms' => [
407 [
408 'name' => 'video_type',
409 'operator' => '===',
410 'value' => 'youtube',
411 ],
412 [
413 'relation' => 'and',
414 'terms' => [
415 [
416 'name' => 'show_image_overlay',
417 'operator' => '===',
418 'value' => 'yes',
419 ],
420 [
421 'name' => 'video_type',
422 'operator' => '!==',
423 'value' => 'hosted',
424 ],
425 ],
426 ],
427 ],
428 ],
429 'frontend_available' => true,
430 ]
431 );
432
433 $this->add_control(
434 'rel',
435 [
436 'label' => esc_html__( 'Suggested Videos', 'elementor' ),
437 'type' => Controls_Manager::SELECT,
438 'options' => [
439 '' => esc_html__( 'Current Video Channel', 'elementor' ),
440 'yes' => esc_html__( 'Any Video', 'elementor' ),
441 ],
442 'condition' => [
443 'video_type' => 'youtube',
444 ],
445 ]
446 );
447
448 // Vimeo.
449 $this->add_control(
450 'vimeo_title',
451 [
452 'label' => esc_html__( 'Intro Title', 'elementor' ),
453 'type' => Controls_Manager::SWITCHER,
454 'label_off' => esc_html__( 'Hide', 'elementor' ),
455 'label_on' => esc_html__( 'Show', 'elementor' ),
456 'default' => 'yes',
457 'condition' => [
458 'video_type' => 'vimeo',
459 ],
460 ]
461 );
462
463 $this->add_control(
464 'vimeo_portrait',
465 [
466 'label' => esc_html__( 'Intro Portrait', 'elementor' ),
467 'type' => Controls_Manager::SWITCHER,
468 'label_off' => esc_html__( 'Hide', 'elementor' ),
469 'label_on' => esc_html__( 'Show', 'elementor' ),
470 'default' => 'yes',
471 'condition' => [
472 'video_type' => 'vimeo',
473 ],
474 ]
475 );
476
477 $this->add_control(
478 'vimeo_byline',
479 [
480 'label' => esc_html__( 'Intro Byline', 'elementor' ),
481 'type' => Controls_Manager::SWITCHER,
482 'label_off' => esc_html__( 'Hide', 'elementor' ),
483 'label_on' => esc_html__( 'Show', 'elementor' ),
484 'default' => 'yes',
485 'condition' => [
486 'video_type' => 'vimeo',
487 ],
488 ]
489 );
490
491 $this->add_control(
492 'color',
493 [
494 'label' => esc_html__( 'Controls Color', 'elementor' ),
495 'type' => Controls_Manager::COLOR,
496 'default' => '',
497 'condition' => [
498 'video_type' => [ 'vimeo', 'dailymotion' ],
499 ],
500 ]
501 );
502
503 $this->add_control(
504 'download_button',
505 [
506 'label' => esc_html__( 'Download Button', 'elementor' ),
507 'type' => Controls_Manager::SWITCHER,
508 'label_off' => esc_html__( 'Hide', 'elementor' ),
509 'label_on' => esc_html__( 'Show', 'elementor' ),
510 'condition' => [
511 'video_type' => 'hosted',
512 ],
513 ]
514 );
515
516 $this->add_control(
517 'poster',
518 [
519 'label' => esc_html__( 'Poster', 'elementor' ),
520 'type' => Controls_Manager::MEDIA,
521 'dynamic' => [
522 'active' => true,
523 ],
524 'condition' => [
525 'video_type' => 'hosted',
526 ],
527 ]
528 );
529
530 $this->add_control(
531 'view',
532 [
533 'label' => esc_html__( 'View', 'elementor' ),
534 'type' => Controls_Manager::HIDDEN,
535 'default' => 'youtube',
536 ]
537 );
538
539 $this->end_controls_section();
540
541 $this->start_controls_section(
542 'section_image_overlay',
543 [
544 'label' => esc_html__( 'Image Overlay', 'elementor' ),
545 ]
546 );
547
548 $this->add_control(
549 'show_image_overlay',
550 [
551 'label' => esc_html__( 'Image Overlay', 'elementor' ),
552 'type' => Controls_Manager::SWITCHER,
553 'label_off' => esc_html__( 'Hide', 'elementor' ),
554 'label_on' => esc_html__( 'Show', 'elementor' ),
555 'frontend_available' => true,
556 ]
557 );
558
559 $this->add_control(
560 'image_overlay',
561 [
562 'label' => esc_html__( 'Choose Image', 'elementor' ),
563 'type' => Controls_Manager::MEDIA,
564 'default' => [
565 'url' => Utils::get_placeholder_image_src(),
566 ],
567 'dynamic' => [
568 'active' => true,
569 ],
570 'condition' => [
571 'show_image_overlay' => 'yes',
572 ],
573 'frontend_available' => true,
574 ]
575 );
576
577 $this->add_group_control(
578 Group_Control_Image_Size::get_type(),
579 [
580 'name' => 'image_overlay', // Usage: `{name}_size` and `{name}_custom_dimension`, in this case `image_overlay_size` and `image_overlay_custom_dimension`.
581 'default' => 'full',
582 'separator' => 'none',
583 'condition' => [
584 'show_image_overlay' => 'yes',
585 ],
586 ]
587 );
588
589 $this->add_control(
590 'show_play_icon',
591 [
592 'label' => esc_html__( 'Play Icon', 'elementor' ),
593 'type' => Controls_Manager::SWITCHER,
594 'default' => 'yes',
595 'condition' => [
596 'show_image_overlay' => 'yes',
597 'image_overlay[url]!' => '',
598 ],
599 ]
600 );
601
602 $this->add_control(
603 'lightbox',
604 [
605 'label' => esc_html__( 'Lightbox', 'elementor' ),
606 'type' => Controls_Manager::SWITCHER,
607 'frontend_available' => true,
608 'label_off' => esc_html__( 'Off', 'elementor' ),
609 'label_on' => esc_html__( 'On', 'elementor' ),
610 'condition' => [
611 'show_image_overlay' => 'yes',
612 'image_overlay[url]!' => '',
613 ],
614 'separator' => 'before',
615 ]
616 );
617
618 $this->end_controls_section();
619
620 $this->start_controls_section(
621 'section_video_style',
622 [
623 'label' => esc_html__( 'Video', 'elementor' ),
624 'tab' => Controls_Manager::TAB_STYLE,
625 ]
626 );
627
628 $this->add_control(
629 'aspect_ratio',
630 [
631 'label' => esc_html__( 'Aspect Ratio', 'elementor' ),
632 'type' => Controls_Manager::SELECT,
633 'options' => [
634 '169' => '16:9',
635 '219' => '21:9',
636 '43' => '4:3',
637 '32' => '3:2',
638 '11' => '1:1',
639 '916' => '9:16',
640 ],
641 'default' => '169',
642 'prefix_class' => 'elementor-aspect-ratio-',
643 'frontend_available' => true,
644 ]
645 );
646
647 $this->add_group_control(
648 Group_Control_Css_Filter::get_type(),
649 [
650 'name' => 'css_filters',
651 'selector' => '{{WRAPPER}} .elementor-wrapper',
652 ]
653 );
654
655 $this->add_control(
656 'play_icon_title',
657 [
658 'label' => esc_html__( 'Play Icon', 'elementor' ),
659 'type' => Controls_Manager::HEADING,
660 'condition' => [
661 'show_image_overlay' => 'yes',
662 'show_play_icon' => 'yes',
663 ],
664 'separator' => 'before',
665 ]
666 );
667
668 $this->add_control(
669 'play_icon_color',
670 [
671 'label' => esc_html__( 'Color', 'elementor' ),
672 'type' => Controls_Manager::COLOR,
673 'selectors' => [
674 '{{WRAPPER}} .elementor-custom-embed-play i' => 'color: {{VALUE}}',
675 '{{WRAPPER}} .elementor-custom-embed-play svg' => 'fill: {{VALUE}}',
676 ],
677 'condition' => [
678 'show_image_overlay' => 'yes',
679 'show_play_icon' => 'yes',
680 ],
681 ]
682 );
683
684 $this->add_responsive_control(
685 'play_icon_size',
686 [
687 'label' => esc_html__( 'Size', 'elementor' ),
688 'type' => Controls_Manager::SLIDER,
689 'range' => [
690 'px' => [
691 'min' => 10,
692 'max' => 300,
693 ],
694 ],
695 'selectors' => [
696 // Not using a CSS vars because the default size value is coming from a global scss file.
697 '{{WRAPPER}} .elementor-custom-embed-play i' => 'font-size: {{SIZE}}{{UNIT}}',
698 '{{WRAPPER}} .elementor-custom-embed-play svg' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}};',
699 ],
700 'condition' => [
701 'show_image_overlay' => 'yes',
702 'show_play_icon' => 'yes',
703 ],
704 ]
705 );
706
707 $this->add_group_control(
708 Group_Control_Text_Shadow::get_type(),
709 [
710 'name' => 'play_icon_text_shadow',
711 'selector' => '{{WRAPPER}} .elementor-custom-embed-play i',
712 'fields_options' => [
713 'text_shadow_type' => [
714 'label' => _x( 'Shadow', 'Text Shadow Control', 'elementor' ),
715 ],
716 ],
717 'condition' => [
718 'show_image_overlay' => 'yes',
719 'show_play_icon' => 'yes',
720 ],
721 ]
722 );
723
724 $this->end_controls_section();
725
726 $this->start_controls_section(
727 'section_lightbox_style',
728 [
729 'label' => esc_html__( 'Lightbox', 'elementor' ),
730 'tab' => Controls_Manager::TAB_STYLE,
731 'condition' => [
732 'show_image_overlay' => 'yes',
733 'image_overlay[url]!' => '',
734 'lightbox' => 'yes',
735 ],
736 ]
737 );
738
739 $this->add_control(
740 'lightbox_color',
741 [
742 'label' => esc_html__( 'Background Color', 'elementor' ),
743 'type' => Controls_Manager::COLOR,
744 'selectors' => [
745 '#elementor-lightbox-{{ID}}' => 'background-color: {{VALUE}};',
746 ],
747 ]
748 );
749
750 $this->add_control(
751 'lightbox_ui_color',
752 [
753 'label' => esc_html__( 'UI Color', 'elementor' ),
754 'type' => Controls_Manager::COLOR,
755 'selectors' => [
756 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button' => 'color: {{VALUE}}',
757 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button svg' => 'fill: {{VALUE}}',
758 ],
759 ]
760 );
761
762 $this->add_control(
763 'lightbox_ui_color_hover',
764 [
765 'label' => esc_html__( 'UI Hover Color', 'elementor' ),
766 'type' => Controls_Manager::COLOR,
767 'selectors' => [
768 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button:hover' => 'color: {{VALUE}}',
769 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button:hover svg' => 'fill: {{VALUE}}',
770 ],
771 'separator' => 'after',
772 ]
773 );
774
775 $this->add_control(
776 'lightbox_video_width',
777 [
778 'label' => esc_html__( 'Content Width', 'elementor' ),
779 'type' => Controls_Manager::SLIDER,
780 'default' => [
781 'unit' => '%',
782 ],
783 'range' => [
784 '%' => [
785 'min' => 30,
786 ],
787 ],
788 'selectors' => [
789 '(desktop+)#elementor-lightbox-{{ID}} .elementor-video-container' => 'width: {{SIZE}}{{UNIT}};',
790 ],
791 ]
792 );
793
794 $this->add_control(
795 'lightbox_content_position',
796 [
797 'label' => esc_html__( 'Content Position', 'elementor' ),
798 'type' => Controls_Manager::SELECT,
799 'frontend_available' => true,
800 'options' => [
801 '' => esc_html__( 'Center', 'elementor' ),
802 'top' => esc_html__( 'Top', 'elementor' ),
803 ],
804 'selectors' => [
805 '#elementor-lightbox-{{ID}} .elementor-video-container' => '{{VALUE}}; transform: translateX(-50%);',
806 ],
807 'selectors_dictionary' => [
808 'top' => 'top: 60px',
809 ],
810 ]
811 );
812
813 $this->add_responsive_control(
814 'lightbox_content_animation',
815 [
816 'label' => esc_html__( 'Entrance Animation', 'elementor' ),
817 'type' => Controls_Manager::ANIMATION,
818 'frontend_available' => true,
819 ]
820 );
821
822 $this->end_controls_section();
823 }
824
825 public function print_a11y_text( $image_overlay ) {
826 if ( empty( $image_overlay['alt'] ) ) {
827 echo esc_html__( 'Play Video', 'elementor' );
828 } else {
829 echo esc_html__( 'Play Video about', 'elementor' ) . ' ' . esc_attr( $image_overlay['alt'] );
830 }
831 }
832
833 /**
834 * Render video widget output on the frontend.
835 *
836 * Written in PHP and used to generate the final HTML.
837 *
838 * @since 1.0.0
839 * @access protected
840 */
841 protected function render() {
842 $settings = $this->get_settings_for_display();
843
844 $video_url = $settings[ $settings['video_type'] . '_url' ];
845
846 if ( 'hosted' === $settings['video_type'] ) {
847 $video_url = $this->get_hosted_video_url();
848 } else {
849 $embed_params = $this->get_embed_params();
850 $embed_options = $this->get_embed_options();
851 }
852
853 if ( empty( $video_url ) ) {
854 return;
855 }
856
857 if ( 'youtube' === $settings['video_type'] ) {
858 $video_html = '<div class="elementor-video"></div>';
859 }
860
861 if ( 'hosted' === $settings['video_type'] ) {
862 $this->add_render_attribute( 'video-wrapper', 'class', 'e-hosted-video' );
863
864 ob_start();
865
866 $this->render_hosted_video();
867
868 $video_html = ob_get_clean();
869 } else {
870 $is_static_render_mode = Plugin::$instance->frontend->is_static_render_mode();
871 $post_id = get_queried_object_id();
872
873 if ( $is_static_render_mode ) {
874 $video_html = Embed::get_embed_thumbnail_html( $video_url, $post_id );
875 // YouTube API requires a different markup which was set above.
876 } else if ( 'youtube' !== $settings['video_type'] ) {
877 $video_html = Embed::get_embed_html( $video_url, $embed_params, $embed_options );
878 }
879 }
880
881 if ( empty( $video_html ) ) {
882 echo esc_url( $video_url );
883
884 return;
885 }
886
887 $this->add_render_attribute( 'video-wrapper', 'class', 'elementor-wrapper' );
888
889 if ( ! $settings['lightbox'] ) {
890 $this->add_render_attribute( 'video-wrapper', 'class', 'elementor-fit-aspect-ratio' );
891 }
892
893 $this->add_render_attribute( 'video-wrapper', 'class', 'elementor-open-' . ( $settings['lightbox'] ? 'lightbox' : 'inline' ) );
894 ?>
895 <div <?php $this->print_render_attribute_string( 'video-wrapper' ); ?>>
896 <?php
897 if ( ! $settings['lightbox'] ) {
898 Utils::print_unescaped_internal_string( $video_html ); // XSS ok.
899 }
900
901 if ( $this->has_image_overlay() ) {
902 $this->add_render_attribute( 'image-overlay', 'class', 'elementor-custom-embed-image-overlay' );
903
904 if ( $settings['lightbox'] ) {
905 if ( 'hosted' === $settings['video_type'] ) {
906 $lightbox_url = $video_url;
907 } else {
908 $lightbox_url = Embed::get_embed_url( $video_url, $embed_params, $embed_options );
909 }
910
911 $lightbox_options = [
912 'type' => 'video',
913 'videoType' => $settings['video_type'],
914 'url' => $lightbox_url,
915 'modalOptions' => [
916 'id' => 'elementor-lightbox-' . $this->get_id(),
917 'entranceAnimation' => $settings['lightbox_content_animation'],
918 'entranceAnimation_tablet' => $settings['lightbox_content_animation_tablet'],
919 'entranceAnimation_mobile' => $settings['lightbox_content_animation_mobile'],
920 'videoAspectRatio' => $settings['aspect_ratio'],
921 ],
922 ];
923
924 if ( 'hosted' === $settings['video_type'] ) {
925 $lightbox_options['videoParams'] = $this->get_hosted_params();
926 }
927
928 $this->add_render_attribute( 'image-overlay', [
929 'data-elementor-open-lightbox' => 'yes',
930 'data-elementor-lightbox' => wp_json_encode( $lightbox_options ),
931 'e-action-hash' => Plugin::instance()->frontend->create_action_hash( 'lightbox', $lightbox_options ),
932 ] );
933
934 if ( Plugin::$instance->editor->is_edit_mode() ) {
935 $this->add_render_attribute( 'image-overlay', [
936 'class' => 'elementor-clickable',
937 ] );
938 }
939 } else {
940 // When there is an image URL but no ID, it means the overlay image is the placeholder. In this case, get the placeholder URL.
941 if ( empty( $settings['image_overlay']['id'] && ! empty( $settings['image_overlay']['url'] ) ) ) {
942 $image_url = $settings['image_overlay']['url'];
943 } else {
944 $image_url = Group_Control_Image_Size::get_attachment_image_src( $settings['image_overlay']['id'], 'image_overlay', $settings );
945 }
946
947 $this->add_render_attribute( 'image-overlay', 'style', 'background-image: url(' . $image_url . ');' );
948 }
949 ?>
950 <div <?php $this->print_render_attribute_string( 'image-overlay' ); ?>>
951 <?php if ( $settings['lightbox'] ) : ?>
952 <?php Group_Control_Image_Size::print_attachment_image_html( $settings, 'image_overlay' ); ?>
953 <?php endif; ?>
954 <?php if ( 'yes' === $settings['show_play_icon'] ) : ?>
955 <div class="elementor-custom-embed-play" role="button" aria-label="<?php $this->print_a11y_text( $settings['image_overlay'] ); ?>" tabindex="0">
956 <?php
957 Icons_Manager::render_icon( [
958 'library' => 'eicons',
959 'value' => 'eicon-play',
960 ], [ 'aria-hidden' => 'true' ] );
961 ?>
962 <span class="elementor-screen-only"><?php $this->print_a11y_text( $settings['image_overlay'] ); ?></span>
963 </div>
964 <?php endif; ?>
965 </div>
966 <?php } ?>
967 </div>
968 <?php
969 }
970
971 /**
972 * Render video widget as plain content.
973 *
974 * Override the default behavior, by printing the video URL insted of rendering it.
975 *
976 * @since 1.4.5
977 * @access public
978 */
979 public function render_plain_content() {
980 $settings = $this->get_settings_for_display();
981
982 if ( 'hosted' !== $settings['video_type'] ) {
983 $url = $settings[ $settings['video_type'] . '_url' ];
984 } else {
985 $url = $this->get_hosted_video_url();
986 }
987
988 echo esc_url( $url );
989 }
990
991 /**
992 * Get embed params.
993 *
994 * Retrieve video widget embed parameters.
995 *
996 * @since 1.5.0
997 * @access public
998 *
999 * @return array Video embed parameters.
1000 */
1001 public function get_embed_params() {
1002 $settings = $this->get_settings_for_display();
1003
1004 $params = [];
1005
1006 if ( $settings['autoplay'] && ! $this->has_image_overlay() ) {
1007 $params['autoplay'] = '1';
1008
1009 if ( $settings['play_on_mobile'] ) {
1010 $params['playsinline'] = '1';
1011 }
1012 }
1013
1014 $params_dictionary = [];
1015
1016 if ( 'youtube' === $settings['video_type'] ) {
1017 $params_dictionary = [
1018 'loop',
1019 'controls',
1020 'mute',
1021 'rel',
1022 'modestbranding',
1023 ];
1024
1025 if ( $settings['loop'] ) {
1026 $video_properties = Embed::get_video_properties( $settings['youtube_url'] );
1027
1028 $params['playlist'] = $video_properties['video_id'];
1029 }
1030
1031 $params['start'] = $settings['start'];
1032
1033 $params['end'] = $settings['end'];
1034
1035 $params['wmode'] = 'opaque';
1036 } elseif ( 'vimeo' === $settings['video_type'] ) {
1037 $params_dictionary = [
1038 'loop',
1039 'mute' => 'muted',
1040 'vimeo_title' => 'title',
1041 'vimeo_portrait' => 'portrait',
1042 'vimeo_byline' => 'byline',
1043 ];
1044
1045 $params['color'] = str_replace( '#', '', $settings['color'] );
1046
1047 $params['autopause'] = '0';
1048 } elseif ( 'dailymotion' === $settings['video_type'] ) {
1049 $params_dictionary = [
1050 'controls',
1051 'mute',
1052 'showinfo' => 'ui-start-screen-info',
1053 'logo' => 'ui-logo',
1054 ];
1055
1056 $params['ui-highlight'] = str_replace( '#', '', $settings['color'] );
1057
1058 $params['start'] = $settings['start'];
1059
1060 $params['endscreen-enable'] = '0';
1061 }
1062
1063 foreach ( $params_dictionary as $key => $param_name ) {
1064 $setting_name = $param_name;
1065
1066 if ( is_string( $key ) ) {
1067 $setting_name = $key;
1068 }
1069
1070 $setting_value = $settings[ $setting_name ] ? '1' : '0';
1071
1072 $params[ $param_name ] = $setting_value;
1073 }
1074
1075 return $params;
1076 }
1077
1078 /**
1079 * Whether the video widget has an overlay image or not.
1080 *
1081 * Used to determine whether an overlay image was set for the video.
1082 *
1083 * @since 1.0.0
1084 * @access protected
1085 *
1086 * @return bool Whether an image overlay was set for the video.
1087 */
1088 protected function has_image_overlay() {
1089 $settings = $this->get_settings_for_display();
1090
1091 return ! empty( $settings['image_overlay']['url'] ) && 'yes' === $settings['show_image_overlay'];
1092 }
1093
1094 /**
1095 * @since 2.1.0
1096 * @access private
1097 */
1098 private function get_embed_options() {
1099 $settings = $this->get_settings_for_display();
1100
1101 $embed_options = [];
1102
1103 if ( 'youtube' === $settings['video_type'] ) {
1104 $embed_options['privacy'] = $settings['yt_privacy'];
1105 } elseif ( 'vimeo' === $settings['video_type'] ) {
1106 $embed_options['start'] = $settings['start'];
1107 }
1108
1109 $embed_options['lazy_load'] = ! empty( $settings['lazy_load'] );
1110
1111 return $embed_options;
1112 }
1113
1114 /**
1115 * @since 2.1.0
1116 * @access private
1117 */
1118 private function get_hosted_params() {
1119 $settings = $this->get_settings_for_display();
1120
1121 $video_params = [];
1122
1123 foreach ( [ 'autoplay', 'loop', 'controls' ] as $option_name ) {
1124 if ( $settings[ $option_name ] ) {
1125 $video_params[ $option_name ] = '';
1126 }
1127 }
1128
1129 if ( $settings['mute'] ) {
1130 $video_params['muted'] = 'muted';
1131 }
1132
1133 if ( $settings['play_on_mobile'] ) {
1134 $video_params['playsinline'] = '';
1135 }
1136
1137 if ( ! $settings['download_button'] ) {
1138 $video_params['controlsList'] = 'nodownload';
1139 }
1140
1141 if ( $settings['poster']['url'] ) {
1142 $video_params['poster'] = $settings['poster']['url'];
1143 }
1144
1145 return $video_params;
1146 }
1147
1148 /**
1149 * @param bool $from_media
1150 *
1151 * @return string
1152 * @since 2.1.0
1153 * @access private
1154 */
1155 private function get_hosted_video_url() {
1156 $settings = $this->get_settings_for_display();
1157
1158 if ( ! empty( $settings['insert_url'] ) ) {
1159 $video_url = $settings['external_url']['url'];
1160 } else {
1161 $video_url = $settings['hosted_url']['url'];
1162 }
1163
1164 if ( empty( $video_url ) ) {
1165 return '';
1166 }
1167
1168 if ( $settings['start'] || $settings['end'] ) {
1169 $video_url .= '#t=';
1170 }
1171
1172 if ( $settings['start'] ) {
1173 $video_url .= $settings['start'];
1174 }
1175
1176 if ( $settings['end'] ) {
1177 $video_url .= ',' . $settings['end'];
1178 }
1179
1180 return $video_url;
1181 }
1182
1183 /**
1184 *
1185 * @since 2.1.0
1186 * @access private
1187 */
1188 private function render_hosted_video() {
1189 $video_url = $this->get_hosted_video_url();
1190 if ( empty( $video_url ) ) {
1191 return;
1192 }
1193
1194 $video_params = $this->get_hosted_params();
1195 /* Sometimes the video url is base64, therefore we use `esc_attr` in `src`. */
1196 ?>
1197 <video class="elementor-video" src="<?php echo esc_attr( $video_url ); ?>" <?php Utils::print_html_attributes( $video_params ); ?>></video>
1198 <?php
1199 }
1200 }
1201