PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.1
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.1
1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 1.9.14 All 163 releases
woocommerce-pos / includes / Services / Settings / General_Section.php

General_Section.php in WCPOS – Point of Sale (POS) plugin for WooCommerce 1.10.1, at includes/Services/Settings/General_Section.php

282 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * General Settings Section.
4 *
5 * @package WCPOS\WooCommercePOS
6 */
7
8 namespace WCPOS\WooCommercePOS\Services\Settings;
9
10 use WCPOS\WooCommercePOS\Services\Store_Defaults;
11
12 /**
13 * The General Settings Section: store identity, POS behaviour toggles, and
14 * structured store tax IDs.
15 */
16 class General_Section extends Abstract_Section {
17 /**
18 * Section id.
19 */
20 public function id(): string {
21 return 'general';
22 }
23
24 /**
25 * Section defaults.
26 */
27 public function defaults(): array {
28 return array(
29 'pos_only_products' => false,
30 'decimal_qty' => false,
31 'force_ssl' => true,
32 'default_customer' => 0,
33 'default_customer_is_cashier' => false,
34 'barcode_field' => '_global_unique_id',
35 'generate_username' => true,
36 'restore_stock_on_delete' => true,
37 'storefront_receipt_enabled' => false,
38 'storefront_receipt_template' => '',
39 'tracking_consent' => 'undecided',
40 'store_name' => '',
41 'store_phone' => '',
42 'store_email' => '',
43 'policies_and_conditions' => '',
44 'store_tax_ids' => array(),
45 );
46 }
47
48 /**
49 * Migrate tracking_consent from the legacy `tools` option if it was set
50 * there before being moved to `general`. In-memory only — an explicit
51 * general-level choice always wins, and the database is never written
52 * from a read path.
53 *
54 * @param array $raw Raw option value.
55 */
56 protected function migrate( array $raw ): array {
57 if ( ! \array_key_exists( 'tracking_consent', $raw ) ) {
58 $legacy_tools = get_option( self::DB_PREFIX . 'tools', array() );
59 if ( \is_array( $legacy_tools ) && \array_key_exists( 'tracking_consent', $legacy_tools ) ) {
60 $raw['tracking_consent'] = $legacy_tools['tracking_consent'];
61 }
62 }
63
64 return $raw;
65 }
66
67 /**
68 * Normalize store_tax_ids and expose resolved fallbacks so the React UI
69 * can render placeholders for store_name / store_phone / store_email /
70 * policies_and_conditions when the user has not entered a value.
71 *
72 * @param array $settings Merged settings.
73 */
74 protected function compose( array $settings ): array {
75 $settings['store_tax_ids'] = self::sanitize_store_tax_ids( $settings['store_tax_ids'] );
76 $settings['store_defaults'] = Store_Defaults::fallbacks();
77
78 return $settings;
79 }
80
81 /**
82 * Sanitize general settings before persisting.
83 *
84 * @param array $settings General settings.
85 */
86 protected function sanitize( array $settings ): array {
87 if ( \array_key_exists( 'store_tax_ids', $settings ) ) {
88 $settings['store_tax_ids'] = self::sanitize_store_tax_ids( $settings['store_tax_ids'] );
89 }
90
91 foreach ( array( 'store_name', 'store_phone' ) as $key ) {
92 if ( \array_key_exists( $key, $settings ) ) {
93 $settings[ $key ] = \is_string( $settings[ $key ] )
94 ? sanitize_text_field( $settings[ $key ] )
95 : '';
96 }
97 }
98
99 if ( \array_key_exists( 'store_email', $settings ) ) {
100 $email = \is_string( $settings['store_email'] ) ? trim( $settings['store_email'] ) : '';
101 $settings['store_email'] = ( '' !== $email && is_email( $email ) ) ? sanitize_email( $email ) : '';
102 }
103
104 if ( \array_key_exists( 'policies_and_conditions', $settings ) ) {
105 $settings['policies_and_conditions'] = \is_string( $settings['policies_and_conditions'] )
106 ? sanitize_textarea_field( $settings['policies_and_conditions'] )
107 : '';
108 }
109
110 if ( \array_key_exists( 'storefront_receipt_enabled', $settings ) ) {
111 $settings['storefront_receipt_enabled'] = wp_validate_boolean( $settings['storefront_receipt_enabled'] );
112 }
113
114 // Template IDs are numeric (database) or slug strings (virtual/gallery); an empty
115 // string means "use the active receipt template". Store as a sanitized string and
116 // let Storefront_Receipts pass it through the already-validated ?template= path.
117 if ( \array_key_exists( 'storefront_receipt_template', $settings ) ) {
118 $settings['storefront_receipt_template'] = \is_scalar( $settings['storefront_receipt_template'] )
119 ? sanitize_text_field( (string) $settings['storefront_receipt_template'] )
120 : '';
121 }
122
123 // store_defaults is a read-only computed field for the UI; never persist it.
124 unset( $settings['store_defaults'] );
125
126 return $settings;
127 }
128
129 /**
130 * Store_tax_ids is a full replacement on PATCH so users can remove rows
131 * by sending the trimmed list.
132 *
133 * @param array $existing Existing settings view.
134 * @param array $patch Incoming partial payload.
135 */
136 public function merge( array $existing, array $patch ): array {
137 $settings = array_replace_recursive( $existing, $patch );
138 if ( isset( $patch['store_tax_ids'] ) && \is_array( $patch['store_tax_ids'] ) ) {
139 $settings['store_tax_ids'] = $patch['store_tax_ids'];
140 }
141
142 return $settings;
143 }
144
145 /**
146 * REST endpoint args for the general update route (formerly the legacy
147 * API\Settings controller's get_general_endpoint_args(), removed in 1.10).
148 */
149 public function endpoint_args(): array {
150 return array(
151 'pos_only_products' => array(
152 'validate_callback' => function ( $param, $request, $key ) {
153 return \is_bool( $param );
154 },
155 ),
156 'decimal_qty' => array(
157 'validate_callback' => function ( $param, $request, $key ) {
158 return \is_bool( $param );
159 },
160 ),
161 'force_ssl' => array(
162 'validate_callback' => function ( $param, $request, $key ) {
163 return \is_bool( $param );
164 },
165 ),
166 'default_customer' => array(
167 'validate_callback' => function ( $param, $request, $key ) {
168 return \is_integer( $param );
169 },
170 ),
171 'default_customer_is_cashier' => array(
172 'validate_callback' => function ( $param, $request, $key ) {
173 return \is_bool( $param );
174 },
175 ),
176 'barcode_field' => array(
177 'validate_callback' => function ( $param, $request, $key ) {
178 return \is_string( $param );
179 },
180 ),
181 'generate_username' => array(
182 'validate_callback' => function ( $param, $request, $key ) {
183 return \is_bool( $param );
184 },
185 ),
186 'restore_stock_on_delete' => array(
187 'validate_callback' => function ( $param, $request, $key ) {
188 return \is_bool( $param );
189 },
190 ),
191 'tracking_consent' => array(
192 'validate_callback' => function ( $param, $request, $key ) {
193 return \is_string( $param ) && \in_array( $param, array( 'allowed', 'denied', 'undecided' ), true );
194 },
195 ),
196 'store_tax_ids' => array(
197 'validate_callback' => function ( $param, $request, $key ) {
198 return \is_array( $param );
199 },
200 ),
201 'store_name' => array(
202 'validate_callback' => function ( $param, $request, $key ) {
203 return \is_string( $param );
204 },
205 ),
206 'store_phone' => array(
207 'validate_callback' => function ( $param, $request, $key ) {
208 return \is_string( $param );
209 },
210 ),
211 'store_email' => array(
212 'validate_callback' => function ( $param, $request, $key ) {
213 return \is_string( $param );
214 },
215 ),
216 'policies_and_conditions' => array(
217 'validate_callback' => function ( $param, $request, $key ) {
218 return \is_string( $param );
219 },
220 ),
221 );
222 }
223
224 /**
225 * Sanitize the additional free-store tax IDs entered in General settings.
226 *
227 * Drops malformed rows and keeps optional country/label fields only when
228 * non-empty. Values are preserved verbatim apart from normal text-field
229 * sanitization and surrounding whitespace.
230 *
231 * @param mixed $tax_ids Raw tax IDs.
232 *
233 * @return array<int,array<string,string>>
234 */
235 public static function sanitize_store_tax_ids( $tax_ids ): array {
236 if ( ! \is_array( $tax_ids ) ) {
237 return array();
238 }
239
240 $sanitized = array();
241 foreach ( $tax_ids as $tax_id ) {
242 if ( ! \is_array( $tax_id ) ) {
243 continue;
244 }
245
246 $type = isset( $tax_id['type'] ) && \is_string( $tax_id['type'] )
247 ? sanitize_key( $tax_id['type'] )
248 : '';
249 $value = isset( $tax_id['value'] ) && \is_string( $tax_id['value'] )
250 ? trim( sanitize_text_field( $tax_id['value'] ) )
251 : '';
252
253 if ( '' === $type || '' === $value ) {
254 continue;
255 }
256
257 $entry = array(
258 'type' => $type,
259 'value' => $value,
260 );
261
262 $country = isset( $tax_id['country'] ) && \is_string( $tax_id['country'] )
263 ? strtoupper( trim( sanitize_text_field( $tax_id['country'] ) ) )
264 : '';
265 if ( '' !== $country ) {
266 $entry['country'] = $country;
267 }
268
269 $label = isset( $tax_id['label'] ) && \is_string( $tax_id['label'] )
270 ? trim( sanitize_text_field( $tax_id['label'] ) )
271 : '';
272 if ( '' !== $label ) {
273 $entry['label'] = $label;
274 }
275
276 $sanitized[] = $entry;
277 }
278
279 return $sanitized;
280 }
281 }
282