PluginProbe ʕ •ᴥ•ʔ
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments / 4.5.0
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments v4.5.0
4.5.1 4.5.0 4.4.2 4.4.1 4.4.0 4.3.3 4.3.2 4.3.1 4.3.0 4.2.3 4.2.2 4.2.1 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.11.0 1.11.1 1.11.2 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.9.0 1.9.1 1.9.2 1.9.3 1.9.4 1.9.5 2.0.0 2.0.1 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.10.0 2.10.1 2.11.0 2.11.1 2.11.2 2.11.3 2.11.4 2.12.0 2.13.0 2.14.0 2.14.1 2.15.0 2.15.1 2.16.0 2.16.1 2.16.2 2.16.3 2.17.0 2.17.1 2.17.2 2.18.0 2.19.0 2.19.2 2.19.3 2.19.4 2.2.0 2.2.1 2.20.0 2.20.1 2.20.2 2.20.3 2.20.4 2.20.5 2.20.6 2.21.0 2.22.0 2.22.1 2.23.0 2.24.0 2.25.0 2.25.1 2.25.2 2.26.0 2.27.0 2.27.1 2.28.0 2.29.0 2.29.1 2.29.2 2.29.3 2.29.4 2.3.0 2.3.1 2.30.0 2.31.0 2.31.1 2.31.2 2.31.3 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.40.0 2.40.1 2.5.0 2.5.1 2.5.2 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.9.0 3.0.0 3.0.0-RC1 3.0.0-RC2 3.0.0-beta1 3.0.0-beta2 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.10.0 3.10.1 3.11.0 3.12.0 3.13.0 3.13.1 3.13.2 3.13.3 3.13.4 3.14.0 3.15.0 3.15.1 3.15.2 3.15.3 3.15.4 3.15.5 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.16.6 3.16.7 3.16.8 3.17.0 3.17.1 3.17.2 3.17.3 3.17.4 3.17.5 3.17.6 3.18.0 3.19.0 3.19.1 3.19.2 3.2.0 3.2.1 3.2.2 3.20.0 3.20.1 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 3.6.2 3.7.0 3.7.1 3.7.2 3.7.3 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.9.0 4.0.0 4.0.1 4.0.2 4.0.3 trunk 4.1.0 0.2.19.1 4.1.1 1.0.0 4.2.0 1.0.1 1.0.2
surecart / app / src / Integrations / Elementor / Widgets / ProductReviewBreakdown.php
surecart / app / src / Integrations / Elementor / Widgets Last commit date
AddToCartButton.php 3 months ago CartMenuIcon.php 1 year ago CollectionTags.php 1 year ago Media.php 1 year ago PriceChooser.php 1 year ago Product.php 1 year ago ProductCard.php 1 year ago ProductContent.php 7 months ago ProductLineItemNote.php 10 months ago ProductPricing.php 1 year ago ProductQuickAddButton.php 7 months ago ProductReviewAverageRatingStars.php 4 months ago ProductReviewAverageRatingValue.php 4 months ago ProductReviewBreakdown.php 4 months ago ProductReviewContent.php 4 months ago ProductReviewList.php 2 months ago ProductReviewRating.php 4 months ago ProductReviewTotalRating.php 4 months ago ProductReviews.php 4 months ago Quantity.php 1 year ago ReusableFormWidget.php 1 year ago SaleBadge.php 1 year ago SelectedPriceAdHocAmount.php 1 year ago VariantPills.php 6 months ago
ProductReviewBreakdown.php
371 lines
1 <?php
2
3 namespace SureCart\Integrations\Elementor\Widgets;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit; // Exit if accessed directly.
7 }
8
9 /**
10 * Product Review Breakdown widget.
11 */
12 class ProductReviewBreakdown extends \Elementor\Widget_Base {
13 /**
14 * Get widget name.
15 *
16 * @return string
17 */
18 public function get_name() {
19 return 'surecart-product-review-breakdown';
20 }
21
22 /**
23 * Get widget title.
24 *
25 * @return string
26 */
27 public function get_title() {
28 return esc_html__( 'Review Breakdown', 'surecart' );
29 }
30
31 /**
32 * Get widget icon.
33 *
34 * @return string
35 */
36 public function get_icon() {
37 return 'eicon-slider-push';
38 }
39
40 /**
41 * Get the widget keywords.
42 *
43 * @return array
44 */
45 public function get_keywords() {
46 return array( 'surecart', 'review', 'breakdown', 'rating', 'stars', 'chart' );
47 }
48
49 /**
50 * Get the widget categories.
51 *
52 * @return array
53 */
54 public function get_categories() {
55 return array( 'surecart-elementor-elements' );
56 }
57
58 /**
59 * Register the widget content settings.
60 *
61 * @return void
62 */
63 private function register_content_settings() {
64 $this->start_controls_section(
65 'settings',
66 [
67 'label' => esc_html__( 'Settings', 'surecart' ),
68 ]
69 );
70
71 $this->add_control(
72 'star_size',
73 [
74 'label' => esc_html__( 'Star Size', 'surecart' ),
75 'type' => \Elementor\Controls_Manager::SLIDER,
76 'size_units' => [ 'px' ],
77 'range' => [
78 'px' => [
79 'min' => 8,
80 'max' => 64,
81 ],
82 ],
83 'default' => [
84 'size' => 20,
85 'unit' => 'px',
86 ],
87 ]
88 );
89
90 $this->end_controls_section();
91
92 $this->start_controls_section(
93 'column_spacing',
94 array(
95 'label' => esc_html__( 'Column & Spacing', 'surecart' ),
96 'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
97 )
98 );
99
100 $this->add_control(
101 'columns',
102 [
103 'label' => esc_html__( 'Columns', 'surecart' ),
104 'type' => \Elementor\Controls_Manager::SELECT,
105 'options' => [
106 '1' => esc_html__( '1 Column', 'surecart' ),
107 '2' => esc_html__( '2 Columns', 'surecart' ),
108 '3' => esc_html__( '3 Columns', 'surecart' ),
109 ],
110 'default' => '1',
111 'description' => esc_html__( 'Choose the number of columns to display the review breakdown. Keep in mind the number of columns may shrink if the width is too narrow.', 'surecart' ),
112 ]
113 );
114
115 $this->add_control(
116 'row_gap',
117 [
118 'label' => esc_html__( 'Row Gap', 'surecart' ),
119 'type' => \Elementor\Controls_Manager::SLIDER,
120 'size_units' => [ 'px' ],
121 'range' => [
122 'px' => [
123 'min' => 0,
124 'max' => 50,
125 ],
126 ],
127 'default' => [
128 'size' => 2,
129 'unit' => 'px',
130 ],
131 'selectors' => [
132 '{{WRAPPER}} .wp-block-surecart-product-review-breakdown .sc-star-bars' => 'row-gap: {{SIZE}}{{UNIT}};',
133 ],
134 ]
135 );
136
137 $this->add_control(
138 'column_gap',
139 [
140 'label' => esc_html__( 'Column Gap', 'surecart' ),
141 'type' => \Elementor\Controls_Manager::SLIDER,
142 'size_units' => [ 'px' ],
143 'range' => [
144 'px' => [
145 'min' => 0,
146 'max' => 100,
147 ],
148 ],
149 'default' => [
150 'size' => 20,
151 'unit' => 'px',
152 ],
153 'selectors' => [
154 '{{WRAPPER}} .wp-block-surecart-product-review-breakdown .sc-star-bars' => 'column-gap: {{SIZE}}{{UNIT}};',
155 ],
156 'condition' => [
157 'columns' => [ '2', '3' ],
158 ],
159 ]
160 );
161
162 $this->end_controls_section();
163 }
164
165 /**
166 * Register the widget style settings.
167 *
168 * @return void
169 */
170 private function register_style_settings() {
171 $selector = '{{WRAPPER}} .wp-block-surecart-product-review-breakdown';
172 $bar_selector = '{{WRAPPER}} .wp-block-surecart-product-review-breakdown .sc-star-bars .sc-star-row__bar';
173 $fill_selector = '{{WRAPPER}} .wp-block-surecart-product-review-breakdown .sc-star-bars .sc-star-row__bar .sc-star-row__bar-fill';
174
175 $this->start_controls_section(
176 'star_bar_style',
177 array(
178 'label' => esc_html__( 'Star & Bar Colors', 'surecart' ),
179 'tab' => \Elementor\Controls_Manager::TAB_STYLE,
180 )
181 );
182
183 $this->add_control(
184 'star_color',
185 array(
186 'label' => esc_html__( 'Star Color', 'surecart' ),
187 'type' => \Elementor\Controls_Manager::COLOR,
188 'global' => [
189 'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Colors::COLOR_PRIMARY,
190 ],
191 'selectors' => [
192 "{$selector} .sc-star-row svg" => 'fill: {{VALUE}}; stroke: {{VALUE}};',
193 "{$selector} .sc-star-row .sc-star-icon" => 'fill: {{VALUE}}; stroke: {{VALUE}};',
194 ],
195 )
196 );
197
198 $this->add_control(
199 'bar_color',
200 array(
201 'label' => esc_html__( 'Bar Active Color', 'surecart' ),
202 'type' => \Elementor\Controls_Manager::COLOR,
203 'global' => [
204 'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Colors::COLOR_PRIMARY,
205 ],
206 'selectors' => [
207 $fill_selector => 'background-color: {{VALUE}};',
208 ],
209 )
210 );
211
212 $this->add_control(
213 'bar_background_color',
214 array(
215 'label' => esc_html__( 'Bar Background Color', 'surecart' ),
216 'type' => \Elementor\Controls_Manager::COLOR,
217 'default' => '#e0e0e0',
218 'selectors' => [
219 $bar_selector => 'background-color: {{VALUE}};',
220 ],
221 )
222 );
223
224 $this->end_controls_section();
225
226 $this->start_controls_section(
227 'labels_style',
228 array(
229 'label' => esc_html__( 'Label & Count Text', 'surecart' ),
230 'tab' => \Elementor\Controls_Manager::TAB_STYLE,
231 )
232 );
233
234 $this->add_control(
235 'text_color',
236 array(
237 'label' => esc_html__( 'Text Color', 'surecart' ),
238 'type' => \Elementor\Controls_Manager::COLOR,
239 'selectors' => [
240 $selector => 'color: {{VALUE}};',
241 ],
242 )
243 );
244
245 $this->add_group_control(
246 \Elementor\Group_Control_Typography::get_type(),
247 [
248 'name' => 'typography',
249 'label' => esc_html__( 'Typography', 'surecart' ),
250 'selector' => $selector,
251 ]
252 );
253
254 $this->end_controls_section();
255 }
256
257 /**
258 * Register the widget controls.
259 *
260 * @return void
261 */
262 protected function register_controls() {
263 $this->register_content_settings();
264 $this->register_style_settings();
265 }
266
267 /**
268 * Render the widget output on the frontend.
269 *
270 * @return void
271 */
272 protected function render() {
273 $settings = $this->get_settings_for_display();
274 $star_size = $settings['star_size']['size'] ?? 20;
275 $columns = $settings['columns'] ?? 1;
276 $row_gap = $settings['row_gap']['size'] ?? 2;
277 $column_gap = $settings['column_gap']['size'] ?? 20;
278
279 if ( \Elementor\Plugin::$instance->editor->is_edit_mode() ) {
280 $this->render_preview( $star_size, $columns, $column_gap );
281 return;
282 }
283
284 $attributes = [
285 'size' => absint( $star_size ) . 'px',
286 'columns' => absint( $columns ),
287 'row_gap' => absint( $row_gap ) . 'px',
288 'column_gap' => absint( $column_gap ) . 'px',
289 ];
290
291 // The summary wrapper causes width issues in flex containers.
292 $block_content = '<!-- wp:surecart/product-review-breakdown ' . wp_json_encode( $attributes ) . ' /-->';
293
294 ?>
295 <div <?php $this->print_render_attribute_string( 'wrapper' ); ?>>
296 <?php echo sc_pre_render_blocks( $block_content ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
297 </div>
298 <?php
299 }
300
301 /**
302 * Render preview in editor.
303 *
304 * @param int $star_size Star size.
305 * @param int $columns Number of columns.
306 * @param int $column_gap Column gap in pixels.
307 *
308 * @return void
309 */
310 private function render_preview( $star_size, $columns = 1, $column_gap = 20 ) {
311 $breakdown_data = [
312 5 => 45,
313 4 => 25,
314 3 => 10,
315 2 => 5,
316 1 => 3,
317 ];
318 $total = array_sum( $breakdown_data );
319 $columns = absint( $columns );
320 $column_gap = absint( $column_gap );
321
322 // Use CSS Grid for proper column layout (matching the actual block).
323 $grid_style = 'display: grid; width: 100%; row-gap: 2px; column-gap: ' . esc_attr( $column_gap ) . 'px;';
324 if ( 2 === $columns ) {
325 $grid_style .= ' grid-template-columns: repeat(2, 1fr); grid-auto-flow: column; grid-template-rows: repeat(3, minmax(auto, 1fr));';
326 } elseif ( 3 === $columns ) {
327 $grid_style .= ' grid-template-columns: repeat(3, 1fr); grid-auto-flow: column; grid-template-rows: repeat(2, minmax(auto, 1fr));';
328 } else {
329 $grid_style .= ' grid-template-columns: 1fr;';
330 }
331 ?>
332 <div class="wp-block-surecart-product-review-breakdown">
333 <div class="sc-star-bars sc-star-bars__columns-<?php echo esc_attr( $columns ); ?>" style="<?php echo esc_attr( $grid_style ); ?>">
334 <?php
335 for ( $star = 5; $star >= 1; $star-- ) {
336 $count = $breakdown_data[ $star ];
337 $percentage = $total > 0 ? ( $count / $total ) * 100 : 0;
338 ?>
339 <a href="#" class="sc-star-row" onclick="event.preventDefault();" style="display: flex; align-items: center; gap: 8px; text-decoration: none; color: inherit; cursor: pointer; transition: opacity 0.2s ease;">
340 <div class="sc-star-row__label" style="display: flex; align-items: center; min-width: 35px; gap: 4px;">
341 <?php echo esc_html( $star ); ?>
342 <?php
343 echo wp_kses(
344 \SureCart::svg()->get(
345 'star',
346 [
347 'width' => esc_attr( $star_size ),
348 'height' => esc_attr( $star_size ),
349 'fill' => 'currentColor',
350 'stroke' => 'currentColor',
351 'stroke-width' => 2,
352 ]
353 ),
354 sc_allowed_svg_html()
355 )
356 ?>
357 </div>
358 <div class="sc-star-row__bar" style="flex: 1; height: 8px; border-radius: 4px; overflow: hidden; position: relative; min-width: 100px;">
359 <div class="sc-star-row__bar-fill" style="height: 100%; border-radius: 4px; width: <?php echo esc_attr( $percentage ); ?>%; transition: width 0.3s ease;"></div>
360 </div>
361 <div class="sc-star-row__count" style="text-align: right; min-width: 20px;"><?php echo esc_html( $count ); ?></div>
362 </a>
363 <?php
364 }
365 ?>
366 </div>
367 </div>
368 <?php
369 }
370 }
371