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 / NonLoggedInUsers / Wholesale / Settings / FormFields.php

FormFields.php in Tiered Pricing Table for WooCommerce 8.0.2, at src/Addons/NonLoggedInUsers/Wholesale/Settings/FormFields.php

151 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php namespace TierPricingTable\Addons\NonLoggedInUsers\Wholesale\Settings;
2
3 /**
4 * The application form's field definitions: what the store owner built in the settings, normalised.
5 *
6 * A field is [ 'key', 'label', 'type', 'required', 'options' ]. Keys are generated from the label once
7 * and then kept, so renaming a label does not change where the value goes. The keys company, phone,
8 * tax_id, website and message are recognised and copied to the customer record; every other key is a
9 * custom field stored on the application only.
10 */
11 class FormFields {
12
13 const KNOWN_KEYS = array( 'company', 'phone', 'tax_id', 'website', 'message' );
14
15 public static function getTypes(): array {
16 return array(
17 'text' => __( 'Text', 'tier-pricing-table' ),
18 'textarea' => __( 'Paragraph', 'tier-pricing-table' ),
19 'tel' => __( 'Phone', 'tier-pricing-table' ),
20 'email' => __( 'E-mail', 'tier-pricing-table' ),
21 'url' => __( 'Website', 'tier-pricing-table' ),
22 'number' => __( 'Number', 'tier-pricing-table' ),
23 'select' => __( 'Dropdown', 'tier-pricing-table' ),
24 'checkbox' => __( 'Checkbox', 'tier-pricing-table' ),
25 );
26 }
27
28 /**
29 * The fields a fresh install starts with.
30 */
31 public static function getDefaults(): array {
32 return array(
33 self::normalize( array( 'key' => 'company', 'label' => __( 'Company', 'tier-pricing-table' ), 'type' => 'text', 'required' => true ) ),
34 self::normalize( array( 'key' => 'phone', 'label' => __( 'Phone', 'tier-pricing-table' ), 'type' => 'tel' ) ),
35 );
36 }
37
38 /**
39 * Suggested rows for the "Add field" menu: the known keys with their labels and types.
40 */
41 public static function getPresets(): array {
42 return array(
43 'company' => array( 'label' => __( 'Company', 'tier-pricing-table' ), 'type' => 'text' ),
44 'phone' => array( 'label' => __( 'Phone', 'tier-pricing-table' ), 'type' => 'tel' ),
45 'tax_id' => array( 'label' => __( 'Tax / VAT ID', 'tier-pricing-table' ), 'type' => 'text' ),
46 'website' => array( 'label' => __( 'Website', 'tier-pricing-table' ), 'type' => 'url' ),
47 'message' => array( 'label' => __( 'Tell us about your business', 'tier-pricing-table' ), 'type' => 'textarea' ),
48 );
49 }
50
51 /**
52 * Decodes the stored JSON into a clean list of fields; falls back to the defaults.
53 */
54 public static function fromJson( $json ): array {
55 if ( is_array( $json ) ) {
56 $rows = $json;
57 } else {
58 $rows = json_decode( (string) $json, true );
59 }
60
61 if ( ! is_array( $rows ) ) {
62 return self::getDefaults();
63 }
64
65 return self::sanitizeList( $rows );
66 }
67
68 public static function toJson( array $fields ): string {
69 return (string) wp_json_encode( array_values( $fields ) );
70 }
71
72 /**
73 * Cleans a list of raw rows (from the settings form or stored JSON): drops rows without a label,
74 * generates missing keys from the label and keeps every key unique.
75 */
76 public static function sanitizeList( array $rows ): array {
77 $fields = array();
78 $used = array();
79
80 foreach ( $rows as $row ) {
81 if ( ! is_array( $row ) ) {
82 continue;
83 }
84
85 $field = self::normalize( $row );
86
87 if ( '' === $field['label'] ) {
88 continue;
89 }
90
91 $base = $field['key'] ?: self::keyFromLabel( $field['label'] );
92 $key = $base;
93 $n = 2;
94
95 while ( isset( $used[ $key ] ) ) {
96 $key = $base . '_' . $n ++;
97 }
98
99 $used[ $key ] = true;
100 $field['key'] = $key;
101 $fields[] = $field;
102 }
103
104 return $fields;
105 }
106
107 public static function normalize( array $row ): array {
108 $type = (string) ( $row['type'] ?? 'text' );
109 $type = array_key_exists( $type, self::getTypes() ) ? $type : 'text';
110 $label = self::cleanText( $row['label'] ?? '' );
111
112 $options = $row['options'] ?? array();
113
114 if ( ! is_array( $options ) ) {
115 $options = preg_split( '/\r\n|\r|\n|,/', (string) $options );
116 }
117
118 $options = array_values( array_filter( array_map( array( __CLASS__, 'cleanText' ), (array) $options ), 'strlen' ) );
119
120 return array(
121 'key' => self::cleanKey( $row['key'] ?? '' ),
122 'label' => mb_substr( $label, 0, 100 ),
123 'type' => $type,
124 'required' => ! empty( $row['required'] ) && 'no' !== $row['required'],
125 'options' => 'select' === $type ? $options : array(),
126 );
127 }
128
129 public static function keyFromLabel( string $label ): string {
130 $key = function_exists( 'remove_accents' ) ? remove_accents( $label ) : $label;
131 $key = strtolower( trim( (string) preg_replace( '/[^a-zA-Z0-9]+/', '_', $key ), '_' ) );
132 $key = mb_substr( $key, 0, 40 );
133
134 return $key ?: 'field';
135 }
136
137 public static function cleanKey( $key ): string {
138 return strtolower( (string) preg_replace( '/[^a-zA-Z0-9_]/', '', (string) $key ) );
139 }
140
141 public static function isKnownKey( string $key ): bool {
142 return in_array( $key, self::KNOWN_KEYS, true );
143 }
144
145 protected static function cleanText( $value ): string {
146 $value = is_scalar( $value ) ? (string) $value : '';
147
148 return function_exists( 'sanitize_text_field' ) ? sanitize_text_field( $value ) : trim( strip_tags( $value ) );
149 }
150 }
151