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

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