PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.86
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.86
51.1.86 51.1.84 51.1.85 51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 All 40 releases
king-addons / includes / widgets / Ajax_Add_To_Cart / Ajax_Add_To_Cart.php

Ajax_Add_To_Cart.php in King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder 51.1.86, at includes/widgets/Ajax_Add_To_Cart/Ajax_Add_To_Cart.php

474 lines 13.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Ajax Add to Cart Widget (Free).
4 *
5 * @package King_Addons
6 */
7
8 namespace King_Addons;
9
10 use Elementor\Controls_Manager;
11 use Elementor\Group_Control_Border;
12 use Elementor\Group_Control_Typography;
13 use Elementor\Widget_Base;
14
15 if (!defined('ABSPATH')) {
16 exit;
17 }
18
19 /**
20 * Renders the Ajax Add to Cart widget.
21 */
22 class Ajax_Add_To_Cart extends Widget_Base
23 {
24 /**
25 * Detect whether the current request is running inside Elementor editor/preview.
26 *
27 * Elementor loads the page inside an iframe while editing, which is still a frontend request.
28 * Some interactive behaviors (like redirects) must be disabled there to avoid breaking editing.
29 *
30 * @return bool
31 */
32 protected function is_elementor_editor_context(): bool
33 {
34 // Fast path: common query arg used by Elementor preview iframe.
35 if (isset($_GET['elementor-preview'])) {
36 return true;
37 }
38
39 if (!defined('ELEMENTOR_VERSION') || !class_exists('\Elementor\Plugin')) {
40 return false;
41 }
42
43 // Be defensive: these properties/methods exist in Elementor but we guard to avoid fatals.
44 $plugin = \Elementor\Plugin::$instance;
45
46 if (isset($plugin->editor) && is_object($plugin->editor) && method_exists($plugin->editor, 'is_edit_mode')) {
47 if ($plugin->editor->is_edit_mode()) {
48 return true;
49 }
50 }
51
52 if (isset($plugin->preview) && is_object($plugin->preview) && method_exists($plugin->preview, 'is_preview_mode')) {
53 if ($plugin->preview->is_preview_mode()) {
54 return true;
55 }
56 }
57
58 return false;
59 }
60
61 /**
62 * Widget slug.
63 *
64 * @return string
65 */
66 public function get_name(): string
67 {
68 return 'king-addons-ajax-add-to-cart';
69 }
70
71 /**
72 * Widget title.
73 *
74 * @return string
75 */
76 public function get_title(): string
77 {
78 return esc_html__('Ajax Add to Cart', 'king-addons');
79 }
80
81 /**
82 * Widget icon.
83 *
84 * @return string
85 */
86 public function get_icon(): string
87 {
88 return 'king-addons-icon king-addons-ajax-add-to-cart';
89 }
90
91 /**
92 * Scripts.
93 *
94 * @return array<int, string>
95 */
96 public function get_script_depends(): array
97 {
98 return [
99 'jquery',
100 'wc-add-to-cart',
101 KING_ADDONS_ASSETS_UNIQUE_KEY . '-ajax-add-to-cart-script',
102 ];
103 }
104
105 /**
106 * Styles.
107 *
108 * @return array<int, string>
109 */
110 public function get_style_depends(): array
111 {
112 return [
113 KING_ADDONS_ASSETS_UNIQUE_KEY . '-ajax-add-to-cart-style',
114 ];
115 }
116
117 /**
118 * Categories.
119 *
120 * @return array<int, string>
121 */
122 public function get_categories(): array
123 {
124 return ['king-addons-woo'];
125 }
126
127 /**
128 * Keywords.
129 *
130 * @return array<int, string>
131 */
132 public function get_keywords(): array
133 {
134 return ['woocommerce', 'cart', 'ajax', 'button', 'add'];
135 }
136
137 public function get_custom_help_url()
138 {
139 return 'mailto:[email protected]?subject=Bug Report - King Addons&body=Please describe the issue';
140 }
141
142 /**
143 * Register controls.
144 *
145 * @return void
146 */
147 public function register_controls(): void
148 {
149 $this->register_content_controls();
150 $this->register_style_button_controls();
151 $this->register_style_notice_controls();
152 $this->register_pro_notice_controls();
153 }
154
155 /**
156 * Render widget output.
157 *
158 * @return void
159 */
160 public function render(): void
161 {
162 if (!class_exists('\WooCommerce')) {
163 Core::renderEditorHint(esc_html__('Ajax Add To Cart needs WooCommerce to be active.', 'king-addons'));
164 return;
165 }
166
167 $settings = $this->get_settings_for_display();
168 $product_id = $this->resolve_product_id($settings);
169
170 if (!$product_id) {
171 Core::renderEditorHint(esc_html__('Pick a product in the Content tab to show the Add to cart button.', 'king-addons'));
172 return;
173 }
174
175 $quantity = !empty($settings['kng_quantity']) ? max(1, (int) $settings['kng_quantity']) : 1;
176 $button_text = $settings['kng_button_text'] ?? esc_html__('Add to cart', 'king-addons');
177 $success_text = $settings['kng_success_text'] ?? esc_html__('Added to cart', 'king-addons');
178
179 $wrapper_classes = ['king-addons-ajax-atc'];
180 ?>
181 <div class="<?php echo esc_attr(implode(' ', $wrapper_classes)); ?>"
182 data-product-id="<?php echo esc_attr((string) $product_id); ?>"
183 data-quantity="<?php echo esc_attr((string) $quantity); ?>"
184 data-success-text="<?php echo esc_attr($success_text); ?>">
185 <button type="button" class="king-addons-ajax-atc__button">
186 <span class="king-addons-ajax-atc__label"><?php echo esc_html($button_text); ?></span>
187 </button>
188 <a class="added_to_cart wc-forward" href="<?php echo esc_url(wc_get_cart_url()); ?>">
189 <?php echo esc_html__('View cart', 'woocommerce'); ?>
190 </a>
191 <div class="king-addons-ajax-atc__notice" role="status" aria-live="polite"></div>
192 </div>
193 <?php
194 }
195
196 /**
197 * Register content controls.
198 *
199 * @return void
200 */
201 protected function register_content_controls(): void
202 {
203 $this->start_controls_section(
204 'kng_content_section',
205 [
206 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Settings', 'king-addons'),
207 'tab' => Controls_Manager::TAB_CONTENT,
208 ]
209 );
210
211 $this->add_control(
212 'kng_use_current_product',
213 [
214 'label' => esc_html__('Use Current Product (Single)', 'king-addons'),
215 'type' => Controls_Manager::SWITCHER,
216 'return_value' => 'yes',
217 'default' => 'yes',
218 'description' => esc_html__('On product pages, automatically use the current product.', 'king-addons'),
219 ]
220 );
221
222 $this->add_control(
223 'kng_product_id',
224 [
225 'label' => esc_html__('Product ID (fallback)', 'king-addons'),
226 'type' => Controls_Manager::NUMBER,
227 'min' => 1,
228 'step' => 1,
229 'description' => esc_html__('Used when not on a single product or when current product is unavailable.', 'king-addons'),
230 'condition' => [
231 'kng_use_current_product!' => 'yes',
232 ],
233 ]
234 );
235
236 $this->add_control(
237 'kng_quantity',
238 [
239 'label' => esc_html__('Quantity', 'king-addons'),
240 'type' => Controls_Manager::NUMBER,
241 'min' => 1,
242 'max' => 20,
243 'step' => 1,
244 'default' => 1,
245 ]
246 );
247
248 $this->add_control(
249 'kng_button_text',
250 [
251 'label' => esc_html__('Button Text', 'king-addons'),
252 'type' => Controls_Manager::TEXT,
253 'default' => esc_html__('Add to cart', 'king-addons'),
254 ]
255 );
256
257 $this->add_control(
258 'kng_success_text',
259 [
260 'label' => esc_html__('Success Message', 'king-addons'),
261 'type' => Controls_Manager::TEXT,
262 'default' => esc_html__('Added to cart', 'king-addons'),
263 ]
264 );
265
266 $this->end_controls_section();
267 }
268
269 /**
270 * Button styles.
271 *
272 * @return void
273 */
274 protected function register_style_button_controls(): void
275 {
276 $this->start_controls_section(
277 'kng_style_button_section',
278 [
279 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Button', 'king-addons'),
280 'tab' => Controls_Manager::TAB_STYLE,
281 ]
282 );
283
284 $this->add_control(
285 'kng_alignment',
286 [
287 'label' => esc_html__('Alignment', 'king-addons'),
288 'type' => Controls_Manager::CHOOSE,
289 'options' => [
290 'flex-start' => [
291 'title' => esc_html__('Left', 'king-addons'),
292 'icon' => 'eicon-h-align-left',
293 ],
294 'center' => [
295 'title' => esc_html__('Center', 'king-addons'),
296 'icon' => 'eicon-h-align-center',
297 ],
298 'flex-end' => [
299 'title' => esc_html__('Right', 'king-addons'),
300 'icon' => 'eicon-h-align-right',
301 ],
302 ],
303 'default' => 'flex-start',
304 'selectors' => [
305 '{{WRAPPER}} .king-addons-ajax-atc' => 'justify-content: {{VALUE}};',
306 ],
307 ]
308 );
309
310 $this->add_group_control(
311 Group_Control_Typography::get_type(),
312 [
313 'name' => 'kng_button_typography',
314 'selector' => '{{WRAPPER}} .king-addons-ajax-atc__button',
315 ]
316 );
317
318 $this->add_control(
319 'kng_button_color',
320 [
321 'label' => esc_html__('Text Color', 'king-addons'),
322 'type' => Controls_Manager::COLOR,
323 'selectors' => [
324 '{{WRAPPER}} .king-addons-ajax-atc__button' => 'color: {{VALUE}};',
325 ],
326 ]
327 );
328
329 $this->add_control(
330 'kng_button_bg',
331 [
332 'label' => esc_html__('Background', 'king-addons'),
333 'type' => Controls_Manager::COLOR,
334 'selectors' => [
335 '{{WRAPPER}} .king-addons-ajax-atc__button' => 'background-color: {{VALUE}};',
336 ],
337 ]
338 );
339
340 $this->add_control(
341 'kng_button_color_hover',
342 [
343 'label' => esc_html__('Hover Text Color', 'king-addons'),
344 'type' => Controls_Manager::COLOR,
345 'selectors' => [
346 '{{WRAPPER}} .king-addons-ajax-atc__button:hover' => 'color: {{VALUE}};',
347 ],
348 ]
349 );
350
351 $this->add_control(
352 'kng_button_bg_hover',
353 [
354 'label' => esc_html__('Hover Background', 'king-addons'),
355 'type' => Controls_Manager::COLOR,
356 'selectors' => [
357 '{{WRAPPER}} .king-addons-ajax-atc__button:hover' => 'background-color: {{VALUE}};',
358 ],
359 ]
360 );
361
362 $this->add_group_control(
363 Group_Control_Border::get_type(),
364 [
365 'name' => 'kng_button_border',
366 'selector' => '{{WRAPPER}} .king-addons-ajax-atc__button',
367 ]
368 );
369
370 $this->add_control(
371 'kng_button_radius',
372 [
373 'label' => esc_html__('Border Radius', 'king-addons'),
374 'type' => Controls_Manager::SLIDER,
375 'size_units' => ['px', '%'],
376 'range' => [
377 'px' => ['min' => 0, 'max' => 50],
378 '%' => ['min' => 0, 'max' => 100],
379 ],
380 'selectors' => [
381 '{{WRAPPER}} .king-addons-ajax-atc__button' => 'border-radius: {{SIZE}}{{UNIT}};',
382 ],
383 ]
384 );
385
386 $this->end_controls_section();
387 }
388
389 /**
390 * Notice styles.
391 *
392 * @return void
393 */
394 protected function register_style_notice_controls(): void
395 {
396 $this->start_controls_section(
397 'kng_style_notice_section',
398 [
399 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Notice', 'king-addons'),
400 'tab' => Controls_Manager::TAB_STYLE,
401 ]
402 );
403
404 $this->add_group_control(
405 Group_Control_Typography::get_type(),
406 [
407 'name' => 'kng_notice_typography',
408 'selector' => '{{WRAPPER}} .king-addons-ajax-atc__notice',
409 ]
410 );
411
412 $this->add_control(
413 'kng_notice_color',
414 [
415 'label' => esc_html__('Text Color', 'king-addons'),
416 'type' => Controls_Manager::COLOR,
417 'selectors' => [
418 '{{WRAPPER}} .king-addons-ajax-atc__notice' => 'color: {{VALUE}};',
419 ],
420 ]
421 );
422
423 $this->end_controls_section();
424 }
425
426 /**
427 * Resolve product ID based on settings.
428 *
429 * @param array<string, mixed> $settings Settings.
430 *
431 * @return int
432 */
433 protected function resolve_product_id(array $settings): int
434 {
435 $use_current = ($settings['kng_use_current_product'] ?? 'yes') === 'yes';
436 if ($use_current && is_singular('product')) {
437 $product_id = get_the_ID();
438 if ($product_id) {
439 return (int) $product_id;
440 }
441 }
442
443 if (!empty($settings['kng_product_id'])) {
444 return (int) $settings['kng_product_id'];
445 }
446
447 return 0;
448 }
449
450 /**
451 * Pro notice.
452 *
453 * @return void
454 */
455 public function register_pro_notice_controls(): void
456 {
457 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
458 Core::renderProFeaturesSection($this, '', Controls_Manager::RAW_HTML, 'ajax-add-to-cart', [
459 'Icons and badges on the button',
460 'Mini-cart fragment refresh toggle',
461 'Success/redirect behaviors and messages',
462 'Quantity selector and variable products',
463 ]);
464 }
465 }
466 }
467
468
469
470
471
472
473
474