PluginProbe
Tiered Pricing Table for WooCommerce / 8.0.2
Tiered Pricing Table for WooCommerce v8.0.2
8.0.2 7.1.7 7.1.5 7.1.4 7.1.1 6.5.0 6.4.0 6.1.0 trunk 1.0 1.1 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.3.0 2.3.1 2.3.2 2.3.3 All 91 releases
tier-pricing-table / src / Addons / GlobalTieredPricing / CPT / Form / Form.php

Form.php in Tiered Pricing Table for WooCommerce 8.0.2, at src/Addons/GlobalTieredPricing/CPT/Form/Form.php

566 lines 15.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php namespace TierPricingTable\Addons\GlobalTieredPricing\CPT\Form;
2
3 use TierPricingTable\Addons\GlobalTieredPricing\CPT\Form\Tabs\ProductAndCategories;
4 use TierPricingTable\Addons\GlobalTieredPricing\CPT\Form\Tabs\Quantity;
5 use TierPricingTable\Addons\GlobalTieredPricing\CPT\Form\Tabs\Pricing;
6 use TierPricingTable\Addons\GlobalTieredPricing\CPT\Form\Tabs\Settings;
7 use TierPricingTable\Addons\GlobalTieredPricing\CPT\Form\Tabs\UsersAndRoles;
8 use TierPricingTable\Addons\GlobalTieredPricing\CPT\GlobalTieredPricingCPT;
9 use TierPricingTable\Addons\GlobalTieredPricing\GlobalPricingRule;
10 use TierPricingTable\Core\ServiceContainerTrait;
11 use WP_Post;
12
13 class Form {
14
15 use ServiceContainerTrait;
16
17 /**
18 * Tabs
19 *
20 * @var FormTab[]
21 */
22 protected $tabs;
23
24 protected $defaultTab = 'pricing';
25
26 protected $pricingRuleInstance = null;
27
28 public function __construct() {
29
30 add_action( 'init', function () {
31 $tabs = array(
32 new Pricing( $this ),
33 new ProductAndCategories( $this ),
34 new UsersAndRoles( $this ),
35 new Quantity( $this ),
36 );
37
38 $tabs[] = new Settings( $this );
39
40 $this->tabs = apply_filters( 'tiered_pricing_table/global_pricing/form_tabs', $tabs, $this );
41 } );
42
43 add_action( 'edit_form_after_title', function ( WP_Post $post ) {
44 if ( GlobalTieredPricingCPT::SLUG !== $post->post_type ) {
45 return;
46 }
47
48 $this->render( $post );
49 } );
50
51 new UpgradeTip();
52 }
53
54 protected function includeAssets() {
55 ?>
56 <style>
57 /**
58 * Externals
59 */
60 /* do not display any notices on rule creation */
61 .wrap .notice:not(.notice-success, .tpt__admin__feedback-discount-banner) {
62 display: none
63 }
64
65 .tpt-global-pricing-rule-form .woocommerce-help-tip {
66 margin-left: 5px;
67 }
68
69 .tpt-global-pricing-rule-hint {
70 display: flex;
71 align-items: center;
72 padding: 10px;
73 border-left: 3px solid var(--wp-admin-theme-color, #2271b1);
74 background: #f6f7f7;
75 color: var(--wp-admin-theme-color, #2271b1) !important;
76 margin-bottom: 20px;
77 }
78
79 .tpt-global-pricing-rule-hint--top-level {
80 margin-top: 10px;
81 border: 1px solid #888;
82 }
83
84 .tpt-global-pricing-rule-hint__icon {
85 margin-right: 10px;
86 }
87
88 .tpt-global-pricing-rule-form {
89 margin: 20px 0;
90 display: flex;
91 overflow: hidden;
92 border-radius: 3px;
93 flex-wrap: nowrap;
94 }
95
96 .tpt-global-pricing-rule-form__tabs {
97 width: 30%;
98 max-width: 300px;
99 min-width: 250px;
100 }
101
102 .tpt-global-pricing-rule-form-tab {
103 background: #fff;
104 border-bottom: 1px solid #e8e8e8;
105 border-left: 1px solid #e8e8e8;
106 overflow: hidden;
107 cursor: pointer;
108 display: flex;
109 align-items: center;
110 padding: 15px 10px;
111 }
112
113 .tpt-global-pricing-rule-form-tab:first-child {
114 border-top: 1px solid #e8e8e8;
115 }
116
117 .tpt-global-pricing-rule-form-tab:hover:not(.tpt-global-pricing-rule-form-tab--active) {
118 background: #fbfbfb;
119 }
120
121 .tpt-global-pricing-rule-form-tab--active {
122 cursor: default;
123 background: #f6f7f7;
124 }
125
126 .tpt-global-pricing-rule-form-tab__icon {
127 transition: all .1s;
128 margin-right: 10px;
129 height: 40px;
130 aspect-ratio: 1/1;
131 border-radius: 50%;
132 background: #f6f7f7;
133 text-align: center;
134 color: var(--wp-admin-theme-color, #2271b1);
135 font-size: 20px;
136 font-weight: bold;
137 display: flex;
138 justify-content: center;
139 align-items: center;
140 }
141
142 .tpt-global-pricing-rule-form-tab--active h3,
143 .tpt-global-pricing-rule-form-tab--active div {
144 color: var(--wp-admin-theme-color, #2271b1) !important;
145 }
146
147 .tpt-global-pricing-rule-form-tab--active .tpt-global-pricing-rule-form-tab__icon {
148 background: #fff;
149 }
150
151 .tpt-global-pricing-rule-form-tab__title h3 {
152 font-size: 1.1em;
153 margin: 0;
154 }
155
156 .tpt-global-pricing-rule-form-tab__title div {
157 margin-top: 5px;
158 color: #777;
159 }
160
161 .tpt-global-pricing-rule-form-tab-content {
162 display: none;
163 }
164
165 .tpt-global-pricing-rule-form-tab-content--active {
166 display: block;
167 }
168
169 .tpt-global-pricing-rule-form__content {
170 width: 70%;
171 background: #fff;
172 flex-grow: 1;
173 padding: 10px;
174 border: 1px solid #e8e8e8;
175 box-shadow: 0 0 8px rgba(0, 0, 0, .1);
176 }
177
178 .tpt-global-pricing-rule-form input[type="text"],
179 .tpt-global-pricing-rule-form input[type="number"],
180 .tpt-global-pricing-rule-form .tiered-pricing-pricing-rules-form-row__inputs {
181 width: 75% !important;
182 }
183
184 .tpt-global-pricing-rule-form #tiered_pricing_type {
185 max-width: 75%;
186 width: 75% !important;
187 }
188
189 @media screen and (max-width: 1248px) {
190
191 .tpt-global-pricing-rule-form input[type="text"],
192 .tpt-global-pricing-rule-form input[type="number"],
193 .tpt-global-pricing-rule-form .tiered-pricing-pricing-rules-form-row__inputs {
194 width: 100% !important;
195 }
196
197 .tpt-global-pricing-rule-form #tiered_pricing_type {
198 max-width: 100%;
199 width: 100% !important;
200 }
201
202
203 .tpt-global-pricing-rule-form {
204 flex-wrap: wrap;
205 }
206
207 .tpt-global-pricing-rule-form__tabs {
208 display: flex;
209 max-width: 100%;
210 width: 100%;
211 }
212
213 .tpt-global-pricing-rule-form-tab__icon {
214 display: none;
215 }
216
217 .tpt-global-pricing-rule-form-tab--active {
218 border-bottom: 3px solid var(--wp-admin-theme-color, #2271b1);
219 }
220 }
221
222 @media screen and (max-width: 500px) {
223 .tiered-pricing-form-block {
224 padding: 5px 20px !important;
225 }
226 }
227
228 /* Accordion styles */
229 .tpt-exclusions-accordion {
230 margin-top: 20px;
231 background: #fff;
232 }
233
234 .tpt-exclusions-accordion summary {
235 cursor: pointer;
236 list-style: none;
237 display: flex;
238 align-items: center;
239 justify-content: space-between;
240 padding: 12px 15px;
241 background: #f6f7f7;
242 border: 1px solid #e8e8e8;
243 font-size: 14px;
244 font-weight: 600;
245 color: #1d2327;
246 transition: background-color 0.2s ease;
247 }
248
249 .tpt-exclusions-accordion summary::-webkit-details-marker {
250 display: none;
251 }
252
253 .tpt-exclusions-accordion summary:hover {
254 background: #f0f0f1;
255 }
256
257 .tpt-exclusions-accordion[open] summary {
258 border-bottom-left-radius: 0;
259 border-bottom-right-radius: 0;
260 border-bottom: 1px solid #e8e8e8;
261 }
262
263 .tpt-exclusions-accordion[open] summary .tpt-accordion-icon {
264 transform: rotate(180deg);
265 }
266
267 .tpt-accordion-icon {
268 transition: transform 0.3s ease;
269 color: #787c82;
270 }
271
272 .tpt-exclusions-accordion-content {
273 padding: 15px 0;
274 border: 1px solid #e8e8e8;
275 border-top: none;
276 border-radius: 0 0 4px 4px;
277 }
278 </style>
279 <script>
280 jQuery(document).ready(function () {
281 let tabs = jQuery('.tpt-global-pricing-rule-form-tab');
282 let tabsContent = jQuery('.tpt-global-pricing-rule-form-tab-content');
283
284 tabs.click(function (e) {
285 e.preventDefault();
286
287 tabsContent.removeClass('tpt-global-pricing-rule-form-tab-content--active');
288 tabs.removeClass('tpt-global-pricing-rule-form-tab--active');
289
290 jQuery(this).addClass('tpt-global-pricing-rule-form-tab--active');
291
292 const target = jQuery(this).data('target');
293
294 jQuery('#' + target).addClass('tpt-global-pricing-rule-form-tab-content--active');
295 });
296 });
297 </script>
298 <?php
299 }
300
301 protected function render( WP_Post $post ) {
302
303 $this->includeAssets();
304
305 $rulesCount = (int) wp_count_posts( GlobalTieredPricingCPT::SLUG )->publish;
306
307 if ( $this->isNewRule() && $rulesCount < 1 ) {
308 $this->renderHelpingSteps();
309 }
310
311 if ( ! $this->isNewRule() && ! $this->getPricingRuleInstance( $post )->isValidPricing() ) {
312 $this->tabs[0]->renderHint( __( 'The pricing rule does not affect either prices or product quantity limits. The rule will be skipped.',
313 'tier-pricing-table' ), array( 'custom_class' => 'tpt-global-pricing-rule-hint--top-level' ) );
314 }
315
316 ?>
317 <div class="tpt-global-pricing-rule-form">
318
319 <nav class="tpt-global-pricing-rule-form__tabs">
320 <?php foreach ( $this->tabs as $tab ) : ?>
321 <div class="tpt-global-pricing-rule-form-tab <?php echo esc_attr( $tab->getId() === $this->defaultTab ? 'tpt-global-pricing-rule-form-tab--active' : '' ); ?>"
322 data-target="tpt-global-pricing-rule-form-tab-<?php echo esc_attr( $tab->getId() ); ?>">
323
324 <div class="tpt-global-pricing-rule-form-tab__icon" style="">
325 <?php if ( strpos( $tab->getIcon(), 'dashicons-' ) === 0 ) : ?>
326 <span class="dashicons <?php echo esc_attr( $tab->getIcon() ); ?>"></span>
327 <?php else : ?>
328 <span><?php echo esc_html( $tab->getIcon() ); ?></span>
329 <?php endif; ?>
330 </div>
331
332 <div class="tpt-global-pricing-rule-form-tab__title">
333 <h3>
334 <?php echo esc_html( $tab->getTitle() ); ?>
335 </h3>
336 <div><?php echo esc_html( $tab->getDescription() ); ?></div>
337 </div>
338 </div>
339 <?php endforeach; ?>
340 </nav>
341
342 <section class="tpt-global-pricing-rule-form__content woocommerce_options_panel">
343 <?php foreach ( $this->tabs as $tab ) : ?>
344 <div class="tpt-global-pricing-rule-form-tab-content <?php echo esc_attr( $tab->getId() === $this->defaultTab ? 'tpt-global-pricing-rule-form-tab-content--active' : '' ); ?>"
345 id="tpt-global-pricing-rule-form-tab-<?php echo esc_attr( $tab->getId() ); ?>">
346 <?php
347 $tab->render( $this->getPricingRuleInstance( $post ) );
348
349 do_action( 'tiered_pricing_table/global_pricing/form/tab_end', $tab,
350 $this->getPricingRuleInstance( $post ) );
351 ?>
352 </div>
353 <?php endforeach; ?>
354 </section>
355 </div>
356 <?php
357 }
358
359 /**
360 * Get pricing rule instance
361 *
362 * @param WP_Post $post
363 *
364 * @return GlobalPricingRule
365 */
366 public function getPricingRuleInstance( WP_Post $post ): GlobalPricingRule {
367 if ( empty( $this->pricingRuleInstance ) ) {
368 $this->pricingRuleInstance = GlobalPricingRule::build( $post->ID );
369 }
370
371 return $this->pricingRuleInstance;
372 }
373
374 public function renderHelpingSteps() {
375 ?>
376 <style>
377 .tpt-global-pricing-rule-helping {
378 background: #ffffff;
379 border: 1px solid #e2e4e7;
380 border-radius: 8px;
381 padding: 30px;
382 position: relative;
383 margin: 20px 0;
384 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
385 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
386 }
387
388 .tpt-global-pricing-rule-helping__close {
389 position: absolute;
390 top: 15px;
391 width: 32px;
392 height: 32px;
393 background: #f0f0f1;
394 color: #3c434a;
395 text-align: center;
396 line-height: 32px;
397 right: 15px;
398 font-weight: 600;
399 border-radius: 50%;
400 transition: all 0.2s ease;
401 }
402
403 .tpt-global-pricing-rule-helping__close:hover {
404 background: #dcdcdd;
405 cursor: pointer;
406 transform: scale(1.05);
407 }
408
409 .tpt-global-pricing-rule-helping__header {
410 text-align: center;
411 margin-bottom: 30px;
412 }
413
414 .tpt-global-pricing-rule-helping__title {
415 font-size: 22px;
416 font-weight: 600;
417 color: #1d2327;
418 margin-bottom: 20px;
419 }
420
421 .tpt-global-pricing-rule-helping__subtitle {
422 font-size: 14px;
423 color: #646970;
424 max-width: 650px;
425 margin: 0 auto;
426 line-height: 1.5;
427 }
428
429 .tpt-global-pricing-rule-helping__steps {
430 display: grid;
431 grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
432 gap: 20px;
433 }
434
435 .tpt-global-pricing-rule-helping-step {
436 background: #ffffff;
437 border: 1px solid #e0e0e0;
438 border-radius: 8px;
439 padding: 24px 20px;
440 text-align: center;
441 transition: transform 0.2s ease, box-shadow 0.2s ease;
442 position: relative;
443 }
444
445 .tpt-global-pricing-rule-helping-step:hover {
446 transform: translateY(-2px);
447 box-shadow: 0 6px 16px rgba(0, 0, 0, 0.06);
448 border-color: #c3c4c7;
449 }
450
451 .tpt-global-pricing-rule-helping-step__icon {
452 width: 52px;
453 height: 52px;
454 border-radius: 50%;
455 background: #e0f0fa;
456 color: #0070bc;
457 margin: 0 auto 16px;
458 display: flex;
459 align-items: center;
460 justify-content: center;
461 font-size: 24px;
462 font-weight: bold;
463 }
464
465 .tpt-global-pricing-rule-helping-step__title {
466 font-size: 15px;
467 font-weight: 600;
468 color: #1d2327;
469 margin-bottom: 8px;
470 }
471
472 .tpt-global-pricing-rule-helping-step__description {
473 font-size: 13px;
474 color: #50575e;
475 line-height: 1.5;
476 }
477
478 </style>
479 <script>
480 jQuery(document).ready(function () {
481 jQuery('.tpt-global-pricing-rule-helping__close').click(function () {
482 jQuery(this).closest('.tpt-global-pricing-rule-helping').slideUp(200);
483 })
484 })
485 </script>
486 <?php
487 $steps = array(
488 array(
489 'title' => __( 'Set Custom Pricing', 'tier-pricing-table' ),
490 'description' => __( 'Set custom regular and tiered pricing for matching products.',
491 'tier-pricing-table' ),
492 'icon' => '$',
493 ),
494 array(
495 'title' => __( 'Select Products', 'tier-pricing-table' ),
496 'description' => __( 'Target specific products, categories, tags, or brands. Leave empty to apply store-wide.',
497 'tier-pricing-table' ),
498 'icon' => '<span class="dashicons dashicons-archive"></span>',
499 ),
500 array(
501 'title' => __( 'Filter Users', 'tier-pricing-table' ),
502 'description' => 'Restrict this pricing to specific customers or user roles.',
503 'icon' => '<span class="dashicons dashicons-admin-users"></span>',
504 ),
505 array(
506 'title' => __( 'Quantity Limits', 'tier-pricing-table' ),
507 'description' => __( 'Enforce minimum, maximum, and step increments for purchasing.',
508 'tier-pricing-table' ),
509 'icon' => '<span class="dashicons dashicons-database"></span>',
510 ),
511 )
512 ?>
513 <div class="tpt-global-pricing-rule-helping">
514 <div class="tpt-global-pricing-rule-helping__close"
515 title="<?php esc_attr_e( 'Dismiss', 'tier-pricing-table' ); ?>">
516 &times;
517 </div>
518
519 <div class="tpt-global-pricing-rule-helping__header">
520 <div class="tpt-global-pricing-rule-helping__title">
521 <?php esc_html_e( 'How global pricing rules work', 'tier-pricing-table' ); ?>
522 </div>
523 <div class="tpt-global-pricing-rule-helping__subtitle">
524 <p style="margin: 0 0 6px;">
525 <?php
526 esc_html_e( 'Global rules enable you to bulk-apply dynamic pricing and quantity limits to selected groups of products and users simultaneously.',
527 'tier-pricing-table' );
528 ?>
529 </p>
530 <p style="margin: 0;">
531 <?php
532 echo sprintf( '<strong>%s</strong> %s', esc_html__( 'Note:', 'tier-pricing-table' ),
533 esc_html__( 'Depending on your priority settings, global rules may override product-level pricing configurations.',
534 'tier-pricing-table' ) );
535 ?>
536 </p>
537 </div>
538 </div>
539
540 <div class="tpt-global-pricing-rule-helping__steps">
541 <?php foreach ( $steps as $index => $step ) : ?>
542 <div class="tpt-global-pricing-rule-helping-step">
543 <div class="tpt-global-pricing-rule-helping-step__icon">
544 <?php echo wp_kses_post( $step['icon'] ); ?>
545 </div>
546
547 <div class="tpt-global-pricing-rule-helping-step__title">
548 <?php echo esc_html( $step['title'] ); ?>
549 </div>
550
551 <div class="tpt-global-pricing-rule-helping-step__description">
552 <?php echo esc_html( $step['description'] ); ?>
553 </div>
554 </div>
555 <?php endforeach; ?>
556 </div>
557 </div>
558 <?php
559 }
560
561 public function isNewRule(): bool {
562 global $pagenow;
563
564 return 'post-new.php' == $pagenow;
565 }
566 }