PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 2.4.0
Subscriptions for WooCommerce with Stripe Recurring Payments v2.4.0
2.4.0 2.3.0 2.2.0 2.1.0 2.0.0 1.11.2 1.11.1 1.11.0 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.6 1.9.5 trunk 1.3.0 1.3.1 1.3.2 1.4.0 All 65 releases
subscription / includes / Admin / views / plans / modal-bulk-price.php

modal-bulk-price.php in Subscriptions for WooCommerce with Stripe Recurring Payments 2.4.0, at includes/Admin/views/plans/modal-bulk-price.php

235 lines 13.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Bulk price modal. Sets one regular (and optional sale) price on the chosen
4 * connected products across the chosen durations in one write. Only products
5 * already on the plan are listed - bulk pricing never attaches new products.
6 *
7 * @var array $plan Plan (PlanPresenter shape: products[], terms[]).
8 *
9 * @package SpringDevs\Subscription\Admin
10 */
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit;
14 }
15
16 $subscrpt_bp_currency = function_exists( 'get_woocommerce_currency_symbol' )
17 ? html_entity_decode( get_woocommerce_currency_symbol(), ENT_QUOTES, 'UTF-8' )
18 : '';
19
20 /**
21 * Current price of a product/variation shown next to its name: a single price
22 * when every duration matches, a min-max range otherwise, a dash when unset.
23 *
24 * @param array $rows Price rows (each may carry regular_raw).
25 *
26 * @return string Escaped HTML.
27 */
28 $subscrpt_bp_price = function ( $rows ) {
29 $vals = array();
30 foreach ( (array) $rows as $subscrpt_bp_r ) {
31 $subscrpt_bp_raw = $subscrpt_bp_r['regular_raw'] ?? '';
32 if ( '' !== $subscrpt_bp_raw ) {
33 $vals[] = (float) $subscrpt_bp_raw;
34 }
35 }
36
37 if ( empty( $vals ) ) {
38 return '<span class="subscrpt-bp-price subscrpt-bp-price--empty">&mdash;</span>';
39 }
40
41 $min = min( $vals );
42 $max = max( $vals );
43
44 if ( $min === $max ) {
45 return '<span class="subscrpt-bp-price">' . esc_html( \SpringDevs\Subscription\Admin\PlanPresenter::money( $min ) ) . '</span>';
46 }
47
48 return '<span class="subscrpt-bp-price">' . esc_html( \SpringDevs\Subscription\Admin\PlanPresenter::money( $min ) ) . ' &ndash; ' . esc_html( \SpringDevs\Subscription\Admin\PlanPresenter::money( $max ) ) . '</span>';
49 };
50
51 /**
52 * Product / variation thumbnail cell.
53 *
54 * @param string $image Image URL, or '' for the placeholder icon.
55 * @param string $icon Dashicon class used when there is no image.
56 *
57 * @return string Escaped HTML.
58 */
59 $subscrpt_bp_thumb = function ( $image, $icon = 'dashicons-format-image' ) {
60 if ( $image ) {
61 return '<span class="subscrpt-bp-thumb"><img src="' . esc_url( $image ) . '" alt="" /></span>';
62 }
63 return '<span class="subscrpt-bp-thumb"><span class="dashicons ' . esc_attr( $icon ) . '"></span></span>';
64 };
65 ?>
66 <div class="wpsubs-modal" id="subscrpt-bulk-price" hidden data-subscrpt-bulk-price>
67 <style>
68 #subscrpt-bulk-price .subscrpt-bp-section { margin-bottom: 18px; }
69 #subscrpt-bulk-price .subscrpt-bp-section:last-child { margin-bottom: 0; }
70 #subscrpt-bulk-price .subscrpt-bp-legend { display: block; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--wpsubs-text-subtle); margin-bottom: 8px; }
71 #subscrpt-bulk-price .subscrpt-bp-pricecard { display: flex; gap: 12px; padding: 14px; background: var(--wpsubs-surface-muted, #f9fafb); border: 1px solid var(--wpsubs-border); border-radius: 8px; }
72 #subscrpt-bulk-price .subscrpt-bp-field { flex: 1; min-width: 0; font-size: 13px; color: var(--wpsubs-text); }
73 #subscrpt-bulk-price .subscrpt-bp-field__label { display: block; margin-bottom: 5px; font-weight: 600; }
74 #subscrpt-bulk-price .subscrpt-bp-field__hint { color: var(--wpsubs-text-subtle); font-weight: 400; }
75 #subscrpt-bulk-price .subscrpt-bp-money { position: relative; }
76 #subscrpt-bulk-price .subscrpt-bp-money__sym { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); font-size: 13px; color: var(--wpsubs-text-subtle); pointer-events: none; }
77 #subscrpt-bulk-price .subscrpt-bp-money .wpsubs-input { width: 100%; padding-left: 24px !important; }
78 #subscrpt-bulk-price .subscrpt-bp-cols { display: grid; grid-template-columns: 1fr 1.25fr; gap: 18px; }
79 #subscrpt-bulk-price .subscrpt-bp-colhead { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
80 #subscrpt-bulk-price .subscrpt-bp-colhead strong { font-size: 13px; color: var(--wpsubs-text); }
81 #subscrpt-bulk-price .subscrpt-bp-count { font-size: 11px; color: var(--wpsubs-text-muted); }
82 #subscrpt-bulk-price .subscrpt-bp-all { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--wpsubs-text-muted); cursor: pointer; }
83 #subscrpt-bulk-price .subscrpt-bp-list { list-style: none; margin: 0; padding: 5px; min-height: 160px; max-height: min(340px, 44vh); overflow-y: auto; display: flex; flex-direction: column; gap: 1px; border: 1px solid var(--wpsubs-border); border-radius: 8px; background: var(--wpsubs-surface, #fff); }
84 #subscrpt-bulk-price .subscrpt-bp-list ul { list-style: none; margin: 0; padding: 0; }
85 #subscrpt-bulk-price .subscrpt-bp-row { display: flex; align-items: center; gap: 10px; min-width: 0; padding: 7px 8px; border-radius: 6px; cursor: pointer; font-size: 13px; }
86 #subscrpt-bulk-price .subscrpt-bp-row:hover { background: var(--wpsubs-surface-muted, #f4f5f7); }
87 #subscrpt-bulk-price .subscrpt-bp-row--child { padding-left: 38px; }
88 #subscrpt-bulk-price .subscrpt-bp-thumb { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 5px; background: var(--wpsubs-surface, #fff); border: 1px solid var(--wpsubs-border); overflow: hidden; display: flex; align-items: center; justify-content: center; }
89 #subscrpt-bulk-price .subscrpt-bp-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
90 #subscrpt-bulk-price .subscrpt-bp-thumb .dashicons { font-size: 16px; width: 16px; height: 16px; color: var(--wpsubs-text-subtle); }
91 #subscrpt-bulk-price .subscrpt-bp-body { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.3; }
92 #subscrpt-bulk-price .subscrpt-bp-name { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
93 #subscrpt-bulk-price .subscrpt-bp-name--strong { font-weight: 600; }
94 #subscrpt-bulk-price .subscrpt-bp-sub { font-size: 11px; color: var(--wpsubs-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
95 #subscrpt-bulk-price .subscrpt-bp-price { flex: 0 0 auto; color: var(--wpsubs-text-muted); font-size: 12px; white-space: nowrap; }
96 #subscrpt-bulk-price .subscrpt-bp-price--empty { color: var(--wpsubs-text-subtle); }
97 #subscrpt-bulk-price .subscrpt-bp-draft { flex: 0 0 auto; font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; color: var(--wpsubs-text-subtle); background: var(--wpsubs-surface-muted, #f1f2f4); border: 1px solid var(--wpsubs-border); border-radius: 4px; padding: 1px 6px; }
98 @media (max-width: 560px) {
99 #subscrpt-bulk-price .subscrpt-bp-cols { grid-template-columns: 1fr; }
100 }
101 </style>
102 <div class="wpsubs-modal__backdrop" data-wpsubs-modal-close></div>
103 <div class="wpsubs-modal__dialog" style="width:min(760px, calc(100vw - 40px));">
104 <div class="wpsubs-modal__head" style="align-items:flex-start;">
105 <div>
106 <h2 class="wpsubs-modal__title"><?php esc_html_e( 'Quick price update', 'subscription' ); ?></h2>
107 <p style="margin:5px 0 0;color:var(--wpsubs-text-muted);font-size:13px;line-height:1.5;font-weight:400;">
108 <?php esc_html_e( 'Set one price on the selected products across the selected durations. This overwrites their current prices.', 'subscription' ); ?>
109 </p>
110 </div>
111 <button type="button" class="wpsubs-modal__close" data-wpsubs-modal-close aria-label="<?php esc_attr_e( 'Close', 'subscription' ); ?>">&times;</button>
112 </div>
113 <div class="wpsubs-modal__body">
114
115 <div class="subscrpt-bp-section">
116 <span class="subscrpt-bp-legend"><?php esc_html_e( 'New price', 'subscription' ); ?></span>
117 <div class="subscrpt-bp-pricecard">
118 <label class="subscrpt-bp-field">
119 <span class="subscrpt-bp-field__label"><?php esc_html_e( 'Regular price', 'subscription' ); ?></span>
120 <span class="subscrpt-bp-money">
121 <?php if ( '' !== $subscrpt_bp_currency ) : ?>
122 <span class="subscrpt-bp-money__sym"><?php echo esc_html( $subscrpt_bp_currency ); ?></span>
123 <?php endif; ?>
124 <input type="number" min="0" step="0.01" class="wpsubs-input" data-subscrpt-bulk-regular placeholder="0.00" />
125 </span>
126 </label>
127 <label class="subscrpt-bp-field">
128 <span class="subscrpt-bp-field__label"><?php esc_html_e( 'Sale price', 'subscription' ); ?> <span class="subscrpt-bp-field__hint">(<?php esc_html_e( 'optional', 'subscription' ); ?>)</span></span>
129 <span class="subscrpt-bp-money">
130 <?php if ( '' !== $subscrpt_bp_currency ) : ?>
131 <span class="subscrpt-bp-money__sym"><?php echo esc_html( $subscrpt_bp_currency ); ?></span>
132 <?php endif; ?>
133 <input type="number" min="0" step="0.01" class="wpsubs-input" data-subscrpt-bulk-sale placeholder="<?php esc_attr_e( 'No sale', 'subscription' ); ?>" />
134 </span>
135 </label>
136 </div>
137 </div>
138
139 <div class="subscrpt-bp-section">
140 <span class="subscrpt-bp-legend"><?php esc_html_e( 'Apply to', 'subscription' ); ?></span>
141 <div class="subscrpt-bp-cols">
142
143 <div>
144 <div class="subscrpt-bp-colhead">
145 <strong><?php esc_html_e( 'Durations', 'subscription' ); ?></strong>
146 <span class="subscrpt-bp-count" data-subscrpt-bulk-count="term"></span>
147 <label class="subscrpt-bp-all">
148 <input type="checkbox" class="wpsubs-checkbox" data-subscrpt-bulk-toggle-all="term" />
149 <?php esc_html_e( 'Select all', 'subscription' ); ?>
150 </label>
151 </div>
152 <ul class="subscrpt-bp-list">
153 <?php foreach ( $plan['terms'] as $subscrpt_bp_term ) : ?>
154 <li>
155 <label class="subscrpt-bp-row">
156 <input type="checkbox" class="wpsubs-checkbox" data-subscrpt-bulk-term value="<?php echo esc_attr( $subscrpt_bp_term['id'] ); ?>" />
157 <span class="subscrpt-bp-body">
158 <span class="subscrpt-bp-name"><?php echo esc_html( $subscrpt_bp_term['name'] ); ?></span>
159 <?php if ( ! empty( $subscrpt_bp_term['breakdown'] ) ) : ?>
160 <span class="subscrpt-bp-sub"><?php echo esc_html( $subscrpt_bp_term['breakdown'] ); ?></span>
161 <?php endif; ?>
162 </span>
163 <?php if ( ! empty( $subscrpt_bp_term['status'] ) && 'active' !== $subscrpt_bp_term['status'] ) : ?>
164 <span class="subscrpt-bp-draft"><?php esc_html_e( 'Draft', 'subscription' ); ?></span>
165 <?php endif; ?>
166 </label>
167 </li>
168 <?php endforeach; ?>
169 </ul>
170 </div>
171
172 <div>
173 <div class="subscrpt-bp-colhead">
174 <strong><?php esc_html_e( 'Products', 'subscription' ); ?></strong>
175 <span class="subscrpt-bp-count" data-subscrpt-bulk-count="product"></span>
176 <label class="subscrpt-bp-all">
177 <input type="checkbox" class="wpsubs-checkbox" data-subscrpt-bulk-toggle-all="product" />
178 <?php esc_html_e( 'Select all', 'subscription' ); ?>
179 </label>
180 </div>
181 <ul class="subscrpt-bp-list">
182 <?php foreach ( $plan['products'] as $subscrpt_bp_product ) : ?>
183 <?php if ( ! empty( $subscrpt_bp_product['is_variable'] ) ) : ?>
184 <?php
185 // Whole-product price range, from every variation's rows.
186 $subscrpt_bp_all_rows = array();
187 foreach ( $subscrpt_bp_product['variations'] as $subscrpt_bp_v ) {
188 foreach ( (array) ( $subscrpt_bp_v['rows'] ?? array() ) as $subscrpt_bp_vr ) {
189 $subscrpt_bp_all_rows[] = $subscrpt_bp_vr;
190 }
191 }
192 ?>
193 <li data-subscrpt-bulk-group>
194 <label class="subscrpt-bp-row">
195 <input type="checkbox" class="wpsubs-checkbox" data-subscrpt-bulk-parent />
196 <?php echo wp_kses_post( $subscrpt_bp_thumb( $subscrpt_bp_product['image'] ?? '' ) ); ?>
197 <span class="subscrpt-bp-name subscrpt-bp-name--strong" style="flex:1;"><?php echo esc_html( $subscrpt_bp_product['name'] ); ?></span>
198 <?php echo wp_kses_post( $subscrpt_bp_price( $subscrpt_bp_all_rows ) ); ?>
199 </label>
200 <ul>
201 <?php foreach ( $subscrpt_bp_product['variations'] as $subscrpt_bp_var ) : ?>
202 <li>
203 <label class="subscrpt-bp-row subscrpt-bp-row--child">
204 <input type="checkbox" class="wpsubs-checkbox" data-subscrpt-bulk-product data-oid="<?php echo esc_attr( $subscrpt_bp_product['id'] ); ?>" data-vid="<?php echo esc_attr( $subscrpt_bp_var['vid'] ); ?>" />
205 <span class="subscrpt-bp-name" style="flex:1;"><?php echo esc_html( $subscrpt_bp_var['name'] ); ?></span>
206 <?php echo wp_kses_post( $subscrpt_bp_price( $subscrpt_bp_var['rows'] ?? array() ) ); ?>
207 </label>
208 </li>
209 <?php endforeach; ?>
210 </ul>
211 </li>
212 <?php else : ?>
213 <li>
214 <label class="subscrpt-bp-row">
215 <input type="checkbox" class="wpsubs-checkbox" data-subscrpt-bulk-product data-oid="<?php echo esc_attr( $subscrpt_bp_product['id'] ); ?>" data-vid="0" />
216 <?php echo wp_kses_post( $subscrpt_bp_thumb( $subscrpt_bp_product['image'] ?? '' ) ); ?>
217 <span class="subscrpt-bp-name" style="flex:1;"><?php echo esc_html( $subscrpt_bp_product['name'] ); ?></span>
218 <?php echo wp_kses_post( $subscrpt_bp_price( $subscrpt_bp_product['rows'] ?? array() ) ); ?>
219 </label>
220 </li>
221 <?php endif; ?>
222 <?php endforeach; ?>
223 </ul>
224 </div>
225
226 </div>
227 </div>
228 </div>
229 <div class="wpsubs-modal__footer">
230 <button type="button" class="wpsubs-btn wpsubs-btn--outline" data-wpsubs-modal-close><?php esc_html_e( 'Cancel', 'subscription' ); ?></button>
231 <button type="button" class="wpsubs-btn wpsubs-btn--primary" data-subscrpt-bulk-apply><?php esc_html_e( 'Apply price', 'subscription' ); ?></button>
232 </div>
233 </div>
234 </div>
235