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

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