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