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

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