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

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