PluginProbe
Elementor Website Builder – more than just a page builder / 3.29.0-dev4
Elementor Website Builder – more than just a page builder v3.29.0-dev4
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 / testimonial.php

testimonial.php in Elementor Website Builder – more than just a page builder 3.29.0-dev4, at includes/widgets/testimonial.php

653 lines 17.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 if ( ! defined( 'ABSPATH' ) ) {
5 exit; // Exit if accessed directly.
6 }
7
8 use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
9 use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
10 use Elementor\Modules\Promotions\Controls\Promotion_Control;
11
12 /**
13 * Elementor testimonial widget.
14 *
15 * Elementor widget that displays customer testimonials that show social proof.
16 *
17 * @since 1.0.0
18 */
19 class Widget_Testimonial extends Widget_Base {
20
21 /**
22 * Get widget name.
23 *
24 * Retrieve testimonial widget name.
25 *
26 * @since 1.0.0
27 * @access public
28 *
29 * @return string Widget name.
30 */
31 public function get_name() {
32 return 'testimonial';
33 }
34
35 /**
36 * Get widget title.
37 *
38 * Retrieve testimonial widget title.
39 *
40 * @since 1.0.0
41 * @access public
42 *
43 * @return string Widget title.
44 */
45 public function get_title() {
46 return esc_html__( 'Testimonial', 'elementor' );
47 }
48
49 /**
50 * Get widget icon.
51 *
52 * Retrieve testimonial widget icon.
53 *
54 * @since 1.0.0
55 * @access public
56 *
57 * @return string Widget icon.
58 */
59 public function get_icon() {
60 return 'eicon-testimonial';
61 }
62
63 /**
64 * Get widget keywords.
65 *
66 * Retrieve the list of keywords the widget belongs to.
67 *
68 * @since 2.1.0
69 * @access public
70 *
71 * @return array Widget keywords.
72 */
73 public function get_keywords() {
74 return [ 'testimonial', 'blockquote' ];
75 }
76
77 protected function is_dynamic_content(): bool {
78 return false;
79 }
80
81 /**
82 * Get style dependencies.
83 *
84 * Retrieve the list of style dependencies the widget requires.
85 *
86 * @since 3.24.0
87 * @access public
88 *
89 * @return array Widget style dependencies.
90 */
91 public function get_style_depends(): array {
92 return [ 'widget-testimonial' ];
93 }
94
95 public function has_widget_inner_wrapper(): bool {
96 return ! Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' );
97 }
98
99 /**
100 * Register testimonial widget controls.
101 *
102 * Adds different input fields to allow the user to change and customize the widget settings.
103 *
104 * @since 3.1.0
105 * @access protected
106 */
107 protected function register_controls() {
108 $this->start_controls_section(
109 'section_testimonial',
110 [
111 'label' => esc_html__( 'Testimonial', 'elementor' ),
112 ]
113 );
114
115 $this->add_control(
116 'testimonial_content',
117 [
118 'label' => esc_html__( 'Content', 'elementor' ),
119 'type' => Controls_Manager::TEXTAREA,
120 'dynamic' => [
121 'active' => true,
122 ],
123 'rows' => '10',
124 'default' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
125 ]
126 );
127
128 $this->add_control(
129 'testimonial_image',
130 [
131 'label' => esc_html__( 'Choose Image', 'elementor' ),
132 'type' => Controls_Manager::MEDIA,
133 'dynamic' => [
134 'active' => true,
135 ],
136 'default' => [
137 'url' => Utils::get_placeholder_image_src(),
138 ],
139 ]
140 );
141
142 $this->add_group_control(
143 Group_Control_Image_Size::get_type(),
144 [
145 'name' => 'testimonial_image', // Usage: `{name}_size` and `{name}_custom_dimension`, in this case `testimonial_image_size` and `testimonial_image_custom_dimension`.
146 'default' => 'full',
147 ]
148 );
149
150 $this->add_control(
151 'testimonial_name',
152 [
153 'label' => esc_html__( 'Name', 'elementor' ),
154 'type' => Controls_Manager::TEXT,
155 'dynamic' => [
156 'active' => true,
157 ],
158 'ai' => [
159 'active' => false,
160 ],
161 'default' => esc_html__( 'John Doe', 'elementor' ),
162 ]
163 );
164
165 $this->add_control(
166 'testimonial_job',
167 [
168 'label' => esc_html__( 'Title', 'elementor' ),
169 'type' => Controls_Manager::TEXT,
170 'dynamic' => [
171 'active' => true,
172 ],
173 'ai' => [
174 'active' => false,
175 ],
176 'default' => esc_html__( 'Designer', 'elementor' ),
177 ]
178 );
179
180 $this->add_control(
181 'link',
182 [
183 'label' => esc_html__( 'Link', 'elementor' ),
184 'type' => Controls_Manager::URL,
185 'dynamic' => [
186 'active' => true,
187 ],
188 ]
189 );
190
191 $aside = is_rtl() ? 'right' : 'left';
192
193 $this->add_control(
194 'testimonial_image_position',
195 [
196 'label' => esc_html__( 'Image Position', 'elementor' ),
197 'type' => Controls_Manager::CHOOSE,
198 'default' => 'aside',
199 'options' => [
200 'aside' => [
201 'title' => esc_html__( 'Aside', 'elementor' ),
202 'icon' => 'eicon-h-align-' . $aside,
203 ],
204 'top' => [
205 'title' => esc_html__( 'Top', 'elementor' ),
206 'icon' => 'eicon-v-align-top',
207 ],
208 ],
209 'toggle' => false,
210 'condition' => [
211 'testimonial_image[url]!' => '',
212 ],
213 'separator' => 'before',
214 'style_transfer' => true,
215 ]
216 );
217
218 $this->add_responsive_control(
219 'testimonial_alignment',
220 [
221 'label' => esc_html__( 'Alignment', 'elementor' ),
222 'type' => Controls_Manager::CHOOSE,
223 'default' => 'center',
224 'options' => [
225 'left' => [
226 'title' => esc_html__( 'Left', 'elementor' ),
227 'icon' => 'eicon-text-align-left',
228 ],
229 'center' => [
230 'title' => esc_html__( 'Center', 'elementor' ),
231 'icon' => 'eicon-text-align-center',
232 ],
233 'right' => [
234 'title' => esc_html__( 'Right', 'elementor' ),
235 'icon' => 'eicon-text-align-right',
236 ],
237 ],
238 'selectors' => [
239 '{{WRAPPER}} .elementor-testimonial-wrapper' => 'text-align: {{VALUE}}',
240 ],
241 'style_transfer' => true,
242 ]
243 );
244
245 if ( ! Utils::has_pro() ) {
246 $this->add_control(
247 Utils::TESTIMONIAL_WIDGET . '_promotion',
248 [
249 'label' => esc_html__( 'Loop Carousel widget', 'elementor' ),
250 'type' => Promotion_Control::TYPE,
251 ]
252 );
253 }
254
255 $this->end_controls_section();
256
257 // Content.
258 $this->start_controls_section(
259 'section_style_testimonial_content',
260 [
261 'label' => esc_html__( 'Content', 'elementor' ),
262 'tab' => Controls_Manager::TAB_STYLE,
263 ]
264 );
265
266 $this->add_control(
267 'content_content_color',
268 [
269 'label' => esc_html__( 'Text Color', 'elementor' ),
270 'type' => Controls_Manager::COLOR,
271 'global' => [
272 'default' => Global_Colors::COLOR_TEXT,
273 ],
274 'default' => '',
275 'selectors' => [
276 '{{WRAPPER}} .elementor-testimonial-content' => 'color: {{VALUE}};',
277 ],
278 ]
279 );
280
281 $this->add_group_control(
282 Group_Control_Typography::get_type(),
283 [
284 'name' => 'content_typography',
285 'global' => [
286 'default' => Global_Typography::TYPOGRAPHY_TEXT,
287 ],
288 'selector' => '{{WRAPPER}} .elementor-testimonial-content',
289 ]
290 );
291
292 $this->add_group_control(
293 Group_Control_Text_Shadow::get_type(),
294 [
295 'name' => 'content_shadow',
296 'selector' => '{{WRAPPER}} .elementor-testimonial-content',
297 ]
298 );
299
300 $this->end_controls_section();
301
302 // Image.
303 $this->start_controls_section(
304 'section_style_testimonial_image',
305 [
306 'label' => esc_html__( 'Image', 'elementor' ),
307 'tab' => Controls_Manager::TAB_STYLE,
308 'condition' => [
309 'testimonial_image[url]!' => '',
310 ],
311 ]
312 );
313
314 $this->add_responsive_control(
315 'image_size',
316 [
317 'label' => esc_html__( 'Image Resolution', 'elementor' ),
318 'type' => Controls_Manager::SLIDER,
319 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
320 'range' => [
321 'px' => [
322 'min' => 20,
323 'max' => 200,
324 ],
325 ],
326 'selectors' => [
327 '{{WRAPPER}} .elementor-testimonial-wrapper .elementor-testimonial-image img' => 'width: {{SIZE}}{{UNIT}};height: {{SIZE}}{{UNIT}};',
328 ],
329 ]
330 );
331
332 $this->add_group_control(
333 Group_Control_Border::get_type(),
334 [
335 'name' => 'image_border',
336 'selector' => '{{WRAPPER}} .elementor-testimonial-wrapper .elementor-testimonial-image img',
337 'separator' => 'before',
338 ]
339 );
340
341 $this->add_responsive_control(
342 'image_border_radius',
343 [
344 'label' => esc_html__( 'Border Radius', 'elementor' ),
345 'type' => Controls_Manager::DIMENSIONS,
346 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
347 'selectors' => [
348 '{{WRAPPER}} .elementor-testimonial-wrapper .elementor-testimonial-image img' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
349 ],
350 ]
351 );
352
353 $this->end_controls_section();
354
355 // Name.
356 $this->start_controls_section(
357 'section_style_testimonial_name',
358 [
359 'label' => esc_html__( 'Name', 'elementor' ),
360 'tab' => Controls_Manager::TAB_STYLE,
361 ]
362 );
363
364 $this->add_control(
365 'name_text_color',
366 [
367 'label' => esc_html__( 'Text Color', 'elementor' ),
368 'type' => Controls_Manager::COLOR,
369 'global' => [
370 'default' => Global_Colors::COLOR_PRIMARY,
371 ],
372 'default' => '',
373 'selectors' => [
374 '{{WRAPPER}} .elementor-testimonial-name' => 'color: {{VALUE}};',
375 ],
376 ]
377 );
378
379 $this->add_group_control(
380 Group_Control_Typography::get_type(),
381 [
382 'name' => 'name_typography',
383 'global' => [
384 'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
385 ],
386 'selector' => '{{WRAPPER}} .elementor-testimonial-name',
387 ]
388 );
389
390 $this->add_group_control(
391 Group_Control_Text_Shadow::get_type(),
392 [
393 'name' => 'name_shadow',
394 'selector' => '{{WRAPPER}} .elementor-testimonial-name',
395 ]
396 );
397
398 $this->end_controls_section();
399
400 // Job.
401 $this->start_controls_section(
402 'section_style_testimonial_job',
403 [
404 'label' => esc_html__( 'Title', 'elementor' ),
405 'tab' => Controls_Manager::TAB_STYLE,
406 ]
407 );
408
409 $this->add_control(
410 'job_text_color',
411 [
412 'label' => esc_html__( 'Text Color', 'elementor' ),
413 'type' => Controls_Manager::COLOR,
414 'global' => [
415 'default' => Global_Colors::COLOR_SECONDARY,
416 ],
417 'default' => '',
418 'selectors' => [
419 '{{WRAPPER}} .elementor-testimonial-job' => 'color: {{VALUE}};',
420 ],
421 ]
422 );
423
424 $this->add_group_control(
425 Group_Control_Typography::get_type(),
426 [
427 'name' => 'job_typography',
428 'global' => [
429 'default' => Global_Typography::TYPOGRAPHY_SECONDARY,
430 ],
431 'selector' => '{{WRAPPER}} .elementor-testimonial-job',
432 ]
433 );
434
435 $this->add_group_control(
436 Group_Control_Text_Shadow::get_type(),
437 [
438 'name' => 'job_shadow',
439 'selector' => '{{WRAPPER}} .elementor-testimonial-job',
440 ]
441 );
442
443 $this->end_controls_section();
444 }
445
446 /**
447 * Render testimonial widget output on the frontend.
448 *
449 * Written in PHP and used to generate the final HTML.
450 *
451 * @since 1.0.0
452 * @access protected
453 */
454 protected function render() {
455 $settings = $this->get_settings_for_display();
456
457 $has_content = ! empty( $settings['testimonial_content'] );
458 $has_image = ! empty( $settings['testimonial_image']['url'] );
459 $has_name = ! empty( $settings['testimonial_name'] );
460 $has_job = ! empty( $settings['testimonial_job'] );
461
462 if ( ! $has_content && ! $has_image && ! $has_name && ! $has_job ) {
463 return;
464 }
465
466 $this->add_render_attribute( 'wrapper', 'class', 'elementor-testimonial-wrapper' );
467
468 $this->add_render_attribute( 'meta', 'class', 'elementor-testimonial-meta' );
469
470 if ( $settings['testimonial_image']['url'] ) {
471 $this->add_render_attribute( 'meta', 'class', 'elementor-has-image' );
472 }
473
474 if ( $settings['testimonial_image_position'] ) {
475 $this->add_render_attribute( 'meta', 'class', 'elementor-testimonial-image-position-' . $settings['testimonial_image_position'] );
476 }
477
478 if ( ! empty( $settings['link']['url'] ) ) {
479 $this->add_link_attributes( 'link', $settings['link'] );
480 }
481 ?>
482 <div <?php $this->print_render_attribute_string( 'wrapper' ); ?>>
483 <?php
484 if ( $has_content ) :
485 $this->add_render_attribute( 'testimonial_content', 'class', 'elementor-testimonial-content' );
486 $this->add_inline_editing_attributes( 'testimonial_content' );
487 ?>
488 <div <?php $this->print_render_attribute_string( 'testimonial_content' ); ?>><?php $this->print_unescaped_setting( 'testimonial_content' ); ?></div>
489 <?php endif; ?>
490
491 <?php if ( $has_image || $has_name || $has_job ) : ?>
492 <div <?php $this->print_render_attribute_string( 'meta' ); ?>>
493 <div class="elementor-testimonial-meta-inner">
494 <?php if ( $has_image ) : ?>
495 <div class="elementor-testimonial-image">
496 <?php
497 $image_html = Group_Control_Image_Size::get_attachment_image_html( $settings, 'testimonial_image' );
498 if ( ! empty( $settings['link']['url'] ) ) :
499 $image_html = '<a ' . $this->get_render_attribute_string( 'link' ) . '>' . $image_html . '</a>';
500 endif;
501 echo wp_kses_post( $image_html );
502 ?>
503 </div>
504 <?php endif; ?>
505
506 <?php if ( $has_name || $has_job ) : ?>
507 <div class="elementor-testimonial-details">
508 <?php
509 if ( $has_name ) :
510 $this->add_render_attribute( 'testimonial_name', 'class', 'elementor-testimonial-name' );
511 $this->add_inline_editing_attributes( 'testimonial_name', 'none' );
512
513 if ( ! empty( $settings['link']['url'] ) ) :
514 ?>
515 <a <?php $this->print_render_attribute_string( 'testimonial_name' ); ?> <?php $this->print_render_attribute_string( 'link' ); ?>><?php $this->print_unescaped_setting( 'testimonial_name' ); ?></a>
516 <?php
517 else :
518 ?>
519 <div <?php $this->print_render_attribute_string( 'testimonial_name' ); ?>><?php $this->print_unescaped_setting( 'testimonial_name' ); ?></div>
520 <?php
521 endif;
522 endif; ?>
523 <?php
524 if ( $has_job ) :
525 $this->add_render_attribute( 'testimonial_job', 'class', 'elementor-testimonial-job' );
526
527 $this->add_inline_editing_attributes( 'testimonial_job', 'none' );
528
529 if ( ! empty( $settings['link']['url'] ) ) :
530 ?>
531 <a <?php $this->print_render_attribute_string( 'testimonial_job' ); ?> <?php $this->print_render_attribute_string( 'link' ); ?>><?php $this->print_unescaped_setting( 'testimonial_job' ); ?></a>
532 <?php
533 else :
534 ?>
535 <div <?php $this->print_render_attribute_string( 'testimonial_job' ); ?>><?php $this->print_unescaped_setting( 'testimonial_job' ); ?></div>
536 <?php
537 endif;
538 endif; ?>
539 </div>
540 <?php endif; ?>
541 </div>
542 </div>
543 <?php endif; ?>
544 </div>
545 <?php
546 }
547
548 /**
549 * Render testimonial widget output in the editor.
550 *
551 * Written as a Backbone JavaScript template and used to generate the live preview.
552 *
553 * @since 2.9.0
554 * @access protected
555 */
556 protected function content_template() {
557 ?>
558 <#
559 if ( '' === settings.testimonial_content && '' === settings.testimonial_image.url && '' === settings.testimonial_name && '' === settings.testimonial_job ) {
560 return;
561 }
562
563 var image = {
564 id: settings.testimonial_image.id,
565 url: settings.testimonial_image.url,
566 size: settings.testimonial_image_size,
567 dimension: settings.testimonial_image_custom_dimension,
568 model: view.getEditModel()
569 };
570 var imageUrl = false, hasImage = '';
571
572 if ( '' !== settings.testimonial_image.url ) {
573 imageUrl = elementor.imagesManager.getImageUrl( image );
574 hasImage = ' elementor-has-image';
575
576 var imageHtml = '<img src="' + _.escape( imageUrl ) + '" alt="testimonial" />';
577 if ( settings.link.url ) {
578 imageHtml = '<a href="' + elementor.helpers.sanitizeUrl( settings.link.url ) + '">' + imageHtml + '</a>';
579 }
580 }
581
582 var testimonial_image_position = settings.testimonial_image_position ? ' elementor-testimonial-image-position-' + settings.testimonial_image_position : '';
583 #>
584 <div class="elementor-testimonial-wrapper">
585 <# if ( '' !== settings.testimonial_content ) {
586 view.addRenderAttribute( 'testimonial_content', {
587 'data-binding-type': 'content',
588 'data-binding-setting': 'testimonial_content',
589 'data-binding-config': JSON.stringify({
590 'testimonial_content': {
591 editType: "text"
592 }
593 })
594 } );
595 view.addRenderAttribute( 'testimonial_content', 'class', 'elementor-testimonial-content' );
596
597 view.addInlineEditingAttributes( 'testimonial_content' );
598 #>
599 <div {{{ view.getRenderAttributeString( 'testimonial_content' ) }}}>{{{ settings.testimonial_content }}}</div>
600 <# } #>
601 <div class="elementor-testimonial-meta{{ hasImage }}{{ testimonial_image_position }}">
602 <div class="elementor-testimonial-meta-inner">
603 <# if ( imageUrl ) { #>
604 <div class="elementor-testimonial-image">{{{ imageHtml }}}</div>
605 <# } #>
606 <div class="elementor-testimonial-details">
607 <?php $this->render_testimonial_description(); ?>
608 </div>
609 </div>
610 </div>
611 </div>
612 <?php
613 }
614
615 protected function render_testimonial_description() {
616 ?>
617 <#
618 if ( '' !== settings.testimonial_name ) {
619 view.addRenderAttribute( 'testimonial_name', 'class', 'elementor-testimonial-name' );
620
621 view.addInlineEditingAttributes( 'testimonial_name', 'none' );
622
623 if ( settings.link.url ) {
624 #>
625 <a href="{{ elementor.helpers.sanitizeUrl( settings.link.url ) }}" {{{ view.getRenderAttributeString( 'testimonial_name' ) }}}>{{{ settings.testimonial_name }}}</a>
626 <#
627 } else {
628 #>
629 <div {{{ view.getRenderAttributeString( 'testimonial_name' ) }}}>{{{ settings.testimonial_name }}}</div>
630 <#
631 }
632 }
633
634 if ( '' !== settings.testimonial_job ) {
635 view.addRenderAttribute( 'testimonial_job', 'class', 'elementor-testimonial-job' );
636
637 view.addInlineEditingAttributes( 'testimonial_job', 'none' );
638
639 if ( settings.link.url ) {
640 #>
641 <a href="{{ elementor.helpers.sanitizeUrl( settings.link.url ) }}" {{{ view.getRenderAttributeString( 'testimonial_job' ) }}}>{{{ settings.testimonial_job }}}</a>
642 <#
643 } else {
644 #>
645 <div {{{ view.getRenderAttributeString( 'testimonial_job' ) }}}>{{{ settings.testimonial_job }}}</div>
646 <#
647 }
648 }
649 #>
650 <?php
651 }
652 }
653