video.php 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022
  1. <?php
  2. namespace Elementor;
  3. use Elementor\Modules\DynamicTags\Module as TagsModule;
  4. if ( ! defined( 'ABSPATH' ) ) {
  5. exit; // Exit if accessed directly.
  6. }
  7. /**
  8. * Elementor video widget.
  9. *
  10. * Elementor widget that displays a video player.
  11. *
  12. * @since 1.0.0
  13. */
  14. class Widget_Video extends Widget_Base {
  15. /**
  16. * Get widget name.
  17. *
  18. * Retrieve video widget name.
  19. *
  20. * @since 1.0.0
  21. * @access public
  22. *
  23. * @return string Widget name.
  24. */
  25. public function get_name() {
  26. return 'video';
  27. }
  28. /**
  29. * Get widget title.
  30. *
  31. * Retrieve video widget title.
  32. *
  33. * @since 1.0.0
  34. * @access public
  35. *
  36. * @return string Widget title.
  37. */
  38. public function get_title() {
  39. return __( 'Video', 'elementor' );
  40. }
  41. /**
  42. * Get widget icon.
  43. *
  44. * Retrieve video widget icon.
  45. *
  46. * @since 1.0.0
  47. * @access public
  48. *
  49. * @return string Widget icon.
  50. */
  51. public function get_icon() {
  52. return 'eicon-youtube';
  53. }
  54. /**
  55. * Get widget categories.
  56. *
  57. * Retrieve the list of categories the video widget belongs to.
  58. *
  59. * Used to determine where to display the widget in the editor.
  60. *
  61. * @since 2.0.0
  62. * @access public
  63. *
  64. * @return array Widget categories.
  65. */
  66. public function get_categories() {
  67. return [ 'basic' ];
  68. }
  69. /**
  70. * Get widget keywords.
  71. *
  72. * Retrieve the list of keywords the widget belongs to.
  73. *
  74. * @since 2.1.0
  75. * @access public
  76. *
  77. * @return array Widget keywords.
  78. */
  79. public function get_keywords() {
  80. return [ 'video', 'player', 'embed', 'youtube', 'vimeo', 'dailymotion' ];
  81. }
  82. /**
  83. * Register video widget controls.
  84. *
  85. * Adds different input fields to allow the user to change and customize the widget settings.
  86. *
  87. * @since 1.0.0
  88. * @access protected
  89. */
  90. protected function _register_controls() {
  91. $this->start_controls_section(
  92. 'section_video',
  93. [
  94. 'label' => __( 'Video', 'elementor' ),
  95. ]
  96. );
  97. $this->add_control(
  98. 'video_type',
  99. [
  100. 'label' => __( 'Source', 'elementor' ),
  101. 'type' => Controls_Manager::SELECT,
  102. 'default' => 'youtube',
  103. 'options' => [
  104. 'youtube' => __( 'YouTube', 'elementor' ),
  105. 'vimeo' => __( 'Vimeo', 'elementor' ),
  106. 'dailymotion' => __( 'Dailymotion', 'elementor' ),
  107. 'hosted' => __( 'Self Hosted', 'elementor' ),
  108. ],
  109. ]
  110. );
  111. $this->add_control(
  112. 'youtube_url',
  113. [
  114. 'label' => __( 'URL', 'elementor' ),
  115. 'type' => Controls_Manager::TEXT,
  116. 'dynamic' => [
  117. 'active' => true,
  118. 'categories' => [
  119. TagsModule::POST_META_CATEGORY,
  120. TagsModule::URL_CATEGORY,
  121. ],
  122. ],
  123. 'placeholder' => __( 'Enter your URL', 'elementor' ) . ' (YouTube)',
  124. 'default' => 'https://www.youtube.com/watch?v=9uOETcuFjbE',
  125. 'label_block' => true,
  126. 'condition' => [
  127. 'video_type' => 'youtube',
  128. ],
  129. ]
  130. );
  131. $this->add_control(
  132. 'vimeo_url',
  133. [
  134. 'label' => __( 'URL', 'elementor' ),
  135. 'type' => Controls_Manager::TEXT,
  136. 'dynamic' => [
  137. 'active' => true,
  138. 'categories' => [
  139. TagsModule::POST_META_CATEGORY,
  140. TagsModule::URL_CATEGORY,
  141. ],
  142. ],
  143. 'placeholder' => __( 'Enter your URL', 'elementor' ) . ' (Vimeo)',
  144. 'default' => 'https://vimeo.com/235215203',
  145. 'label_block' => true,
  146. 'condition' => [
  147. 'video_type' => 'vimeo',
  148. ],
  149. ]
  150. );
  151. $this->add_control(
  152. 'dailymotion_url',
  153. [
  154. 'label' => __( 'URL', 'elementor' ),
  155. 'type' => Controls_Manager::TEXT,
  156. 'dynamic' => [
  157. 'active' => true,
  158. 'categories' => [
  159. TagsModule::POST_META_CATEGORY,
  160. TagsModule::URL_CATEGORY,
  161. ],
  162. ],
  163. 'placeholder' => __( 'Enter your URL', 'elementor' ) . ' (Dailymotion)',
  164. 'default' => 'https://www.dailymotion.com/video/x6tqhqb',
  165. 'label_block' => true,
  166. 'condition' => [
  167. 'video_type' => 'dailymotion',
  168. ],
  169. ]
  170. );
  171. $this->add_control(
  172. 'hosted_url',
  173. [
  174. 'label' => __( 'URL', 'elementor' ),
  175. 'type' => Controls_Manager::MEDIA,
  176. 'dynamic' => [
  177. 'active' => true,
  178. 'categories' => [
  179. TagsModule::POST_META_CATEGORY,
  180. TagsModule::MEDIA_CATEGORY,
  181. ],
  182. ],
  183. 'media_type' => 'video',
  184. 'condition' => [
  185. 'video_type' => 'hosted',
  186. ],
  187. ]
  188. );
  189. $this->add_control(
  190. 'start',
  191. [
  192. 'label' => __( 'Start Time', 'elementor' ),
  193. 'type' => Controls_Manager::NUMBER,
  194. 'description' => __( 'Specify a start time (in seconds)', 'elementor' ),
  195. 'condition' => [
  196. 'loop' => '',
  197. ],
  198. ]
  199. );
  200. $this->add_control(
  201. 'end',
  202. [
  203. 'label' => __( 'End Time', 'elementor' ),
  204. 'type' => Controls_Manager::NUMBER,
  205. 'description' => __( 'Specify an end time (in seconds)', 'elementor' ),
  206. 'condition' => [
  207. 'loop' => '',
  208. 'video_type' => [ 'youtube', 'hosted' ],
  209. ],
  210. ]
  211. );
  212. $this->add_control(
  213. 'video_options',
  214. [
  215. 'label' => __( 'Video Options', 'elementor' ),
  216. 'type' => Controls_Manager::HEADING,
  217. 'separator' => 'before',
  218. ]
  219. );
  220. $this->add_control(
  221. 'autoplay',
  222. [
  223. 'label' => __( 'Autoplay', 'elementor' ),
  224. 'type' => Controls_Manager::SWITCHER,
  225. ]
  226. );
  227. $this->add_control(
  228. 'mute',
  229. [
  230. 'label' => __( 'Mute', 'elementor' ),
  231. 'type' => Controls_Manager::SWITCHER,
  232. ]
  233. );
  234. $this->add_control(
  235. 'loop',
  236. [
  237. 'label' => __( 'Loop', 'elementor' ),
  238. 'type' => Controls_Manager::SWITCHER,
  239. 'condition' => [
  240. 'video_type!' => 'dailymotion',
  241. ],
  242. ]
  243. );
  244. $this->add_control(
  245. 'controls',
  246. [
  247. 'label' => __( 'Player Controls', 'elementor' ),
  248. 'type' => Controls_Manager::SWITCHER,
  249. 'label_off' => __( 'Hide', 'elementor' ),
  250. 'label_on' => __( 'Show', 'elementor' ),
  251. 'default' => 'yes',
  252. 'condition' => [
  253. 'video_type!' => 'vimeo',
  254. ],
  255. ]
  256. );
  257. $this->add_control(
  258. 'showinfo',
  259. [
  260. 'label' => __( 'Video Info', 'elementor' ),
  261. 'type' => Controls_Manager::SWITCHER,
  262. 'label_off' => __( 'Hide', 'elementor' ),
  263. 'label_on' => __( 'Show', 'elementor' ),
  264. 'default' => 'yes',
  265. 'condition' => [
  266. 'video_type' => [ 'youtube', 'dailymotion' ],
  267. ],
  268. ]
  269. );
  270. $this->add_control(
  271. 'modestbranding',
  272. [
  273. 'label' => __( 'Modest Branding', 'elementor' ),
  274. 'type' => Controls_Manager::SWITCHER,
  275. 'condition' => [
  276. 'video_type' => [ 'youtube' ],
  277. 'controls' => 'yes',
  278. ],
  279. ]
  280. );
  281. $this->add_control(
  282. 'logo',
  283. [
  284. 'label' => __( 'Logo', 'elementor' ),
  285. 'type' => Controls_Manager::SWITCHER,
  286. 'label_off' => __( 'Hide', 'elementor' ),
  287. 'label_on' => __( 'Show', 'elementor' ),
  288. 'default' => 'yes',
  289. 'condition' => [
  290. 'video_type' => [ 'dailymotion' ],
  291. ],
  292. ]
  293. );
  294. $this->add_control(
  295. 'color',
  296. [
  297. 'label' => __( 'Controls Color', 'elementor' ),
  298. 'type' => Controls_Manager::COLOR,
  299. 'default' => '',
  300. 'condition' => [
  301. 'video_type' => [ 'vimeo', 'dailymotion' ],
  302. ],
  303. ]
  304. );
  305. // YouTube.
  306. $this->add_control(
  307. 'rel',
  308. [
  309. 'label' => __( 'Suggested Videos', 'elementor' ),
  310. 'type' => Controls_Manager::SWITCHER,
  311. 'label_off' => __( 'Hide', 'elementor' ),
  312. 'label_on' => __( 'Show', 'elementor' ),
  313. 'condition' => [
  314. 'video_type' => 'youtube',
  315. ],
  316. ]
  317. );
  318. $this->add_control(
  319. 'yt_privacy',
  320. [
  321. 'label' => __( 'Privacy Mode', 'elementor' ),
  322. 'type' => Controls_Manager::SWITCHER,
  323. 'description' => __( 'When you turn on privacy mode, YouTube won\'t store information about visitors on your website unless they play the video.', 'elementor' ),
  324. 'condition' => [
  325. 'video_type' => 'youtube',
  326. ],
  327. ]
  328. );
  329. // Vimeo.
  330. $this->add_control(
  331. 'vimeo_title',
  332. [
  333. 'label' => __( 'Intro Title', 'elementor' ),
  334. 'type' => Controls_Manager::SWITCHER,
  335. 'label_off' => __( 'Hide', 'elementor' ),
  336. 'label_on' => __( 'Show', 'elementor' ),
  337. 'default' => 'yes',
  338. 'condition' => [
  339. 'video_type' => 'vimeo',
  340. ],
  341. ]
  342. );
  343. $this->add_control(
  344. 'vimeo_portrait',
  345. [
  346. 'label' => __( 'Intro Portrait', 'elementor' ),
  347. 'type' => Controls_Manager::SWITCHER,
  348. 'label_off' => __( 'Hide', 'elementor' ),
  349. 'label_on' => __( 'Show', 'elementor' ),
  350. 'default' => 'yes',
  351. 'condition' => [
  352. 'video_type' => 'vimeo',
  353. ],
  354. ]
  355. );
  356. $this->add_control(
  357. 'vimeo_byline',
  358. [
  359. 'label' => __( 'Intro Byline', 'elementor' ),
  360. 'type' => Controls_Manager::SWITCHER,
  361. 'label_off' => __( 'Hide', 'elementor' ),
  362. 'label_on' => __( 'Show', 'elementor' ),
  363. 'default' => 'yes',
  364. 'condition' => [
  365. 'video_type' => 'vimeo',
  366. ],
  367. ]
  368. );
  369. $this->add_control(
  370. 'download_button',
  371. [
  372. 'label' => __( 'Download Button', 'elementor' ),
  373. 'type' => Controls_Manager::SWITCHER,
  374. 'label_off' => __( 'Hide', 'elementor' ),
  375. 'label_on' => __( 'Show', 'elementor' ),
  376. 'condition' => [
  377. 'video_type' => 'hosted',
  378. ],
  379. ]
  380. );
  381. $this->add_control(
  382. 'poster',
  383. [
  384. 'label' => __( 'Poster', 'elementor' ),
  385. 'type' => Controls_Manager::MEDIA,
  386. 'condition' => [
  387. 'video_type' => 'hosted',
  388. ],
  389. ]
  390. );
  391. $this->add_control(
  392. 'view',
  393. [
  394. 'label' => __( 'View', 'elementor' ),
  395. 'type' => Controls_Manager::HIDDEN,
  396. 'default' => 'youtube',
  397. ]
  398. );
  399. $this->end_controls_section();
  400. $this->start_controls_section(
  401. 'section_image_overlay',
  402. [
  403. 'label' => __( 'Image Overlay', 'elementor' ),
  404. ]
  405. );
  406. $this->add_control(
  407. 'show_image_overlay',
  408. [
  409. 'label' => __( 'Image Overlay', 'elementor' ),
  410. 'type' => Controls_Manager::SWITCHER,
  411. 'label_off' => __( 'Hide', 'elementor' ),
  412. 'label_on' => __( 'Show', 'elementor' ),
  413. ]
  414. );
  415. $this->add_control(
  416. 'image_overlay',
  417. [
  418. 'label' => __( 'Image', 'elementor' ),
  419. 'type' => Controls_Manager::MEDIA,
  420. 'default' => [
  421. 'url' => Utils::get_placeholder_image_src(),
  422. ],
  423. 'dynamic' => [
  424. 'active' => true,
  425. ],
  426. 'condition' => [
  427. 'show_image_overlay' => 'yes',
  428. ],
  429. ]
  430. );
  431. $this->add_control(
  432. 'lazy_load',
  433. [
  434. 'label' => __( 'Lazy Load', 'elementor' ),
  435. 'type' => Controls_Manager::SWITCHER,
  436. 'condition' => [
  437. 'show_image_overlay' => 'yes',
  438. 'video_type!' => 'hosted',
  439. ],
  440. ]
  441. );
  442. $this->add_group_control(
  443. Group_Control_Image_Size::get_type(),
  444. [
  445. 'name' => 'image_overlay', // Usage: `{name}_size` and `{name}_custom_dimension`, in this case `image_overlay_size` and `image_overlay_custom_dimension`.
  446. 'default' => 'full',
  447. 'separator' => 'none',
  448. 'condition' => [
  449. 'show_image_overlay' => 'yes',
  450. ],
  451. ]
  452. );
  453. $this->add_control(
  454. 'show_play_icon',
  455. [
  456. 'label' => __( 'Play Icon', 'elementor' ),
  457. 'type' => Controls_Manager::SWITCHER,
  458. 'default' => 'yes',
  459. 'condition' => [
  460. 'show_image_overlay' => 'yes',
  461. 'image_overlay[url]!' => '',
  462. ],
  463. ]
  464. );
  465. $this->add_control(
  466. 'lightbox',
  467. [
  468. 'label' => __( 'Lightbox', 'elementor' ),
  469. 'type' => Controls_Manager::SWITCHER,
  470. 'frontend_available' => true,
  471. 'label_off' => __( 'Off', 'elementor' ),
  472. 'label_on' => __( 'On', 'elementor' ),
  473. 'condition' => [
  474. 'show_image_overlay' => 'yes',
  475. 'image_overlay[url]!' => '',
  476. ],
  477. 'separator' => 'before',
  478. ]
  479. );
  480. $this->end_controls_section();
  481. $this->start_controls_section(
  482. 'section_video_style',
  483. [
  484. 'label' => __( 'Video', 'elementor' ),
  485. 'tab' => Controls_Manager::TAB_STYLE,
  486. ]
  487. );
  488. $this->add_control(
  489. 'aspect_ratio',
  490. [
  491. 'label' => __( 'Aspect Ratio', 'elementor' ),
  492. 'type' => Controls_Manager::SELECT,
  493. 'options' => [
  494. '169' => '16:9',
  495. '219' => '21:9',
  496. '43' => '4:3',
  497. '32' => '3:2',
  498. ],
  499. 'default' => '169',
  500. 'prefix_class' => 'elementor-aspect-ratio-',
  501. 'frontend_available' => true,
  502. ]
  503. );
  504. $this->add_group_control(
  505. Group_Control_Css_Filter::get_type(),
  506. [
  507. 'name' => 'css_filters',
  508. 'selector' => '{{WRAPPER}} .elementor-wrapper',
  509. ]
  510. );
  511. $this->add_control(
  512. 'play_icon_title',
  513. [
  514. 'label' => __( 'Play Icon', 'elementor' ),
  515. 'type' => Controls_Manager::HEADING,
  516. 'condition' => [
  517. 'show_image_overlay' => 'yes',
  518. 'show_play_icon' => 'yes',
  519. ],
  520. 'separator' => 'before',
  521. ]
  522. );
  523. $this->add_control(
  524. 'play_icon_color',
  525. [
  526. 'label' => __( 'Color', 'elementor' ),
  527. 'type' => Controls_Manager::COLOR,
  528. 'selectors' => [
  529. '{{WRAPPER}} .elementor-custom-embed-play i' => 'color: {{VALUE}}',
  530. ],
  531. 'condition' => [
  532. 'show_image_overlay' => 'yes',
  533. 'show_play_icon' => 'yes',
  534. ],
  535. ]
  536. );
  537. $this->add_responsive_control(
  538. 'play_icon_size',
  539. [
  540. 'label' => __( 'Size', 'elementor' ),
  541. 'type' => Controls_Manager::SLIDER,
  542. 'range' => [
  543. 'px' => [
  544. 'min' => 10,
  545. 'max' => 300,
  546. ],
  547. ],
  548. 'selectors' => [
  549. '{{WRAPPER}} .elementor-custom-embed-play i' => 'font-size: {{SIZE}}{{UNIT}}',
  550. ],
  551. 'condition' => [
  552. 'show_image_overlay' => 'yes',
  553. 'show_play_icon' => 'yes',
  554. ],
  555. ]
  556. );
  557. $this->add_group_control(
  558. Group_Control_Text_Shadow::get_type(),
  559. [
  560. 'name' => 'play_icon_text_shadow',
  561. 'selector' => '{{WRAPPER}} .elementor-custom-embed-play i',
  562. 'fields_options' => [
  563. 'text_shadow_type' => [
  564. 'label' => _x( 'Shadow', 'Text Shadow Control', 'elementor' ),
  565. ],
  566. ],
  567. 'condition' => [
  568. 'show_image_overlay' => 'yes',
  569. 'show_play_icon' => 'yes',
  570. ],
  571. ]
  572. );
  573. $this->end_controls_section();
  574. $this->start_controls_section(
  575. 'section_lightbox_style',
  576. [
  577. 'label' => __( 'Lightbox', 'elementor' ),
  578. 'tab' => Controls_Manager::TAB_STYLE,
  579. 'condition' => [
  580. 'show_image_overlay' => 'yes',
  581. 'image_overlay[url]!' => '',
  582. 'lightbox' => 'yes',
  583. ],
  584. ]
  585. );
  586. $this->add_control(
  587. 'lightbox_color',
  588. [
  589. 'label' => __( 'Background Color', 'elementor' ),
  590. 'type' => Controls_Manager::COLOR,
  591. 'selectors' => [
  592. '#elementor-lightbox-{{ID}}' => 'background-color: {{VALUE}};',
  593. ],
  594. ]
  595. );
  596. $this->add_control(
  597. 'lightbox_ui_color',
  598. [
  599. 'label' => __( 'UI Color', 'elementor' ),
  600. 'type' => Controls_Manager::COLOR,
  601. 'selectors' => [
  602. '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button' => 'color: {{VALUE}}',
  603. ],
  604. ]
  605. );
  606. $this->add_control(
  607. 'lightbox_ui_color_hover',
  608. [
  609. 'label' => __( 'UI Hover Color', 'elementor' ),
  610. 'type' => Controls_Manager::COLOR,
  611. 'selectors' => [
  612. '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button:hover' => 'color: {{VALUE}}',
  613. ],
  614. 'separator' => 'after',
  615. ]
  616. );
  617. $this->add_control(
  618. 'lightbox_video_width',
  619. [
  620. 'label' => __( 'Content Width', 'elementor' ),
  621. 'type' => Controls_Manager::SLIDER,
  622. 'default' => [
  623. 'unit' => '%',
  624. ],
  625. 'range' => [
  626. '%' => [
  627. 'min' => 50,
  628. ],
  629. ],
  630. 'selectors' => [
  631. '(desktop+)#elementor-lightbox-{{ID}} .elementor-video-container' => 'width: {{SIZE}}{{UNIT}};',
  632. ],
  633. ]
  634. );
  635. $this->add_control(
  636. 'lightbox_content_position',
  637. [
  638. 'label' => __( 'Content Position', 'elementor' ),
  639. 'type' => Controls_Manager::SELECT,
  640. 'frontend_available' => true,
  641. 'options' => [
  642. '' => __( 'Center', 'elementor' ),
  643. 'top' => __( 'Top', 'elementor' ),
  644. ],
  645. 'selectors' => [
  646. '#elementor-lightbox-{{ID}} .elementor-video-container' => '{{VALUE}}; transform: translateX(-50%);',
  647. ],
  648. 'selectors_dictionary' => [
  649. 'top' => 'top: 60px',
  650. ],
  651. ]
  652. );
  653. $this->add_control(
  654. 'lightbox_content_animation',
  655. [
  656. 'label' => __( 'Entrance Animation', 'elementor' ),
  657. 'type' => Controls_Manager::ANIMATION,
  658. 'default' => '',
  659. 'frontend_available' => true,
  660. 'label_block' => true,
  661. ]
  662. );
  663. $this->end_controls_section();
  664. }
  665. /**
  666. * Render video widget output on the frontend.
  667. *
  668. * Written in PHP and used to generate the final HTML.
  669. *
  670. * @since 1.0.0
  671. * @access protected
  672. */
  673. protected function render() {
  674. $settings = $this->get_settings_for_display();
  675. $video_url = $settings[ $settings['video_type'] . '_url' ];
  676. if ( 'hosted' === $settings['video_type'] ) {
  677. $video_url = $this->get_hosted_video_url();
  678. }
  679. if ( empty( $video_url ) ) {
  680. return;
  681. }
  682. if ( 'hosted' === $settings['video_type'] ) {
  683. ob_start();
  684. $this->render_hosted_video();
  685. $video_html = ob_get_clean();
  686. } else {
  687. $embed_params = $this->get_embed_params();
  688. $embed_options = $this->get_embed_options();
  689. $video_html = Embed::get_embed_html( $video_url, $embed_params, $embed_options );
  690. }
  691. if ( empty( $video_html ) ) {
  692. echo esc_url( $video_url );
  693. return;
  694. }
  695. $this->add_render_attribute( 'video-wrapper', 'class', 'elementor-wrapper' );
  696. if ( ! $settings['lightbox'] ) {
  697. $this->add_render_attribute( 'video-wrapper', 'class', 'elementor-fit-aspect-ratio' );
  698. }
  699. $this->add_render_attribute( 'video-wrapper', 'class', 'elementor-open-' . ( $settings['lightbox'] ? 'lightbox' : 'inline' ) );
  700. ?>
  701. <div <?php echo $this->get_render_attribute_string( 'video-wrapper' ); ?>>
  702. <?php
  703. if ( ! $settings['lightbox'] ) {
  704. echo $video_html; // XSS ok.
  705. }
  706. if ( $this->has_image_overlay() ) {
  707. $this->add_render_attribute( 'image-overlay', 'class', 'elementor-custom-embed-image-overlay' );
  708. if ( $settings['lightbox'] ) {
  709. if ( 'hosted' === $settings['video_type'] ) {
  710. $lightbox_url = $video_url;
  711. } else {
  712. $lightbox_url = Embed::get_embed_url( $video_url, $embed_params, $embed_options );
  713. }
  714. $lightbox_options = [
  715. 'type' => 'video',
  716. 'videoType' => $settings['video_type'],
  717. 'url' => $lightbox_url,
  718. 'modalOptions' => [
  719. 'id' => 'elementor-lightbox-' . $this->get_id(),
  720. 'entranceAnimation' => $settings['lightbox_content_animation'],
  721. 'videoAspectRatio' => $settings['aspect_ratio'],
  722. ],
  723. ];
  724. if ( 'hosted' === $settings['video_type'] ) {
  725. $lightbox_options['videoParams'] = $this->get_hosted_params();
  726. }
  727. $this->add_render_attribute( 'image-overlay', [
  728. 'data-elementor-open-lightbox' => 'yes',
  729. 'data-elementor-lightbox' => wp_json_encode( $lightbox_options ),
  730. ] );
  731. if ( Plugin::$instance->editor->is_edit_mode() ) {
  732. $this->add_render_attribute( 'image-overlay', [
  733. 'class' => 'elementor-clickable',
  734. ] );
  735. }
  736. } else {
  737. $this->add_render_attribute( 'image-overlay', 'style', 'background-image: url(' . Group_Control_Image_Size::get_attachment_image_src( $settings['image_overlay']['id'], 'image_overlay', $settings ) . ');' );
  738. }
  739. ?>
  740. <div <?php echo $this->get_render_attribute_string( 'image-overlay' ); ?>>
  741. <?php if ( $settings['lightbox'] ) : ?>
  742. <?php echo Group_Control_Image_Size::get_attachment_image_html( $settings, 'image_overlay' ); ?>
  743. <?php endif; ?>
  744. <?php if ( 'yes' === $settings['show_play_icon'] ) : ?>
  745. <div class="elementor-custom-embed-play" role="button">
  746. <i class="eicon-play" aria-hidden="true"></i>
  747. <span class="elementor-screen-only"><?php echo __( 'Play Video', 'elementor' ); ?></span>
  748. </div>
  749. <?php endif; ?>
  750. </div>
  751. <?php } ?>
  752. </div>
  753. <?php
  754. }
  755. /**
  756. * Render video widget as plain content.
  757. *
  758. * Override the default behavior, by printing the video URL insted of rendering it.
  759. *
  760. * @since 1.4.5
  761. * @access public
  762. */
  763. public function render_plain_content() {
  764. $settings = $this->get_settings_for_display();
  765. $url = $settings[ $settings['video_type'] . '_url' ];
  766. echo esc_url( $url );
  767. }
  768. /**
  769. * Get embed params.
  770. *
  771. * Retrieve video widget embed parameters.
  772. *
  773. * @since 1.5.0
  774. * @access public
  775. *
  776. * @return array Video embed parameters.
  777. */
  778. public function get_embed_params() {
  779. $settings = $this->get_settings_for_display();
  780. $params = [];
  781. if ( $settings['autoplay'] && ! $this->has_image_overlay() ) {
  782. $params['autoplay'] = '1';
  783. }
  784. $params_dictionary = [];
  785. if ( 'youtube' === $settings['video_type'] ) {
  786. $params_dictionary = [
  787. 'loop',
  788. 'controls',
  789. 'mute',
  790. 'showinfo',
  791. 'rel',
  792. 'modestbranding',
  793. ];
  794. if ( $settings['loop'] ) {
  795. $video_properties = Embed::get_video_properties( $settings['youtube_url'] );
  796. $params['playlist'] = $video_properties['video_id'];
  797. }
  798. $params['start'] = $settings['start'];
  799. $params['end'] = $settings['end'];
  800. $params['wmode'] = 'opaque';
  801. } elseif ( 'vimeo' === $settings['video_type'] ) {
  802. $params_dictionary = [
  803. 'loop',
  804. 'mute' => 'muted',
  805. 'vimeo_title' => 'title',
  806. 'vimeo_portrait' => 'portrait',
  807. 'vimeo_byline' => 'byline',
  808. ];
  809. $params['color'] = str_replace( '#', '', $settings['color'] );
  810. $params['autopause'] = '0';
  811. } elseif ( 'dailymotion' === $settings['video_type'] ) {
  812. $params_dictionary = [
  813. 'controls',
  814. 'mute',
  815. 'showinfo' => 'ui-start-screen-info',
  816. 'logo' => 'ui-logo',
  817. ];
  818. $params['ui-highlight'] = str_replace( '#', '', $settings['color'] );
  819. $params['start'] = $settings['start'];
  820. $params['endscreen-enable'] = '0';
  821. }
  822. foreach ( $params_dictionary as $key => $param_name ) {
  823. $setting_name = $param_name;
  824. if ( is_string( $key ) ) {
  825. $setting_name = $key;
  826. }
  827. $setting_value = $settings[ $setting_name ] ? '1' : '0';
  828. $params[ $param_name ] = $setting_value;
  829. }
  830. return $params;
  831. }
  832. /**
  833. * Whether the video widget has an overlay image or not.
  834. *
  835. * Used to determine whether an overlay image was set for the video.
  836. *
  837. * @since 1.0.0
  838. * @access protected
  839. *
  840. * @return bool Whether an image overlay was set for the video.
  841. */
  842. protected function has_image_overlay() {
  843. $settings = $this->get_settings_for_display();
  844. return ! empty( $settings['image_overlay']['url'] ) && 'yes' === $settings['show_image_overlay'];
  845. }
  846. private function get_embed_options() {
  847. $settings = $this->get_settings_for_display();
  848. $embed_options = [];
  849. if ( 'youtube' === $settings['video_type'] ) {
  850. $embed_options['privacy'] = $settings['yt_privacy'];
  851. } elseif ( 'vimeo' === $settings['video_type'] ) {
  852. $embed_options['start'] = $settings['start'];
  853. }
  854. $embed_options['lazy_load'] = ! empty( $settings['lazy_load'] );
  855. return $embed_options;
  856. }
  857. private function get_hosted_params() {
  858. $settings = $this->get_settings_for_display();
  859. $video_params = [];
  860. foreach ( [ 'autoplay', 'loop', 'controls' ] as $option_name ) {
  861. if ( $settings[ $option_name ] ) {
  862. $video_params[] = $option_name;
  863. }
  864. }
  865. if ( $settings['mute'] ) {
  866. $video_params[] = 'muted';
  867. }
  868. if ( ! $settings['download_button'] ) {
  869. $video_params[] = 'controlsList="nodownload"';
  870. }
  871. if ( $settings['poster']['url'] ) {
  872. $video_params[] = 'poster="' . $settings['poster']['url'] . '"';
  873. }
  874. return $video_params;
  875. }
  876. private function get_hosted_video_url() {
  877. $settings = $this->get_settings_for_display();
  878. $video_url = $settings['hosted_url']['url'];
  879. if ( ! $video_url ) {
  880. return '';
  881. }
  882. $video_url .= '#t=';
  883. if ( $settings['start'] ) {
  884. $video_url .= $settings['start'];
  885. }
  886. if ( $settings['end'] ) {
  887. $video_url .= ',' . $settings['end'];
  888. }
  889. return $video_url;
  890. }
  891. private function render_hosted_video() {
  892. $video_params = $this->get_hosted_params();
  893. $video_url = $this->get_hosted_video_url();
  894. ?>
  895. <video class="elementor-video" src="<?php echo esc_url( $video_url ); ?>" <?php echo implode( ' ', $video_params ); ?>></video>
  896. <?php
  897. }
  898. }