PluginProbe
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant / 2.2.7
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant v2.2.7
2.3.2 2.3.1 2.3.0 2.2.8 2.2.7 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.11.0 1.11.1 1.11.2 1.6 1.7 1.8 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 1.9.10 1.9.11 All 60 releases
merchant / admin / classes / admin-options / class-merchant-field-registry.php

class-merchant-field-registry.php in Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant 2.2.7, at admin/classes/admin-options/class-merchant-field-registry.php

370 lines 11.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Merchant Field Registry.
4 *
5 * Singleton registry that maps field type strings to their corresponding
6 * field classes. Uses an explicit array for field registration.
7 *
8 * @package Merchant
9 * @since 2.2.5
10 */
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit; // Exit if accessed directly
14 }
15
16 /**
17 * Merchant_Field_Registry
18 *
19 * @since 2.2.5
20 */
21 class Merchant_Field_Registry {
22
23 /**
24 * The single class instance.
25 *
26 * @since 2.2.5
27 * @var Merchant_Field_Registry|null
28 */
29 private static $instance = null;
30
31 /**
32 * Registered field types.
33 * Maps type string => class name.
34 *
35 * @since 2.2.5
36 * @var array<string, string>
37 */
38 private $types = array();
39
40 /**
41 * Get the singleton instance.
42 *
43 * @since 2.2.5
44 *
45 * @return Merchant_Field_Registry
46 */
47 public static function instance() {
48 if ( is_null( self::$instance ) ) {
49 self::$instance = new self();
50 }
51
52 return self::$instance;
53 }
54
55 /**
56 * Reset the singleton instance.
57 *
58 * Clears the cached instance so a fresh one is created
59 * on the next {@see instance()} call. Intended for unit tests.
60 *
61 * @since 2.2.5
62 *
63 * @return void
64 */
65 public static function reset(): void {
66 self::$instance = null;
67 }
68
69 /**
70 * Constructor.
71 *
72 * Loads field classes from an explicit registry array and builds the type map.
73 *
74 * @since 2.2.5
75 */
76 private function __construct() {
77 $base_path = MERCHANT_DIR . 'admin/classes/admin-options/fields';
78
79 /**
80 * Core field type definitions.
81 *
82 * Each entry maps a type key to its class name and file path.
83 * Format: type_key => [ 'class' => ClassName, 'file' => absolute_path ]
84 *
85 * @since 2.2.5
86 */
87 $field_types = array(
88 'text' => array(
89 'class' => 'Merchant_Field_Text',
90 'file' => $base_path . '/text/class-merchant-field-text.php',
91 ),
92 'number' => array(
93 'class' => 'Merchant_Field_Number',
94 'file' => $base_path . '/number/class-merchant-field-number.php',
95 ),
96 'url' => array(
97 'class' => 'Merchant_Field_Url',
98 'file' => $base_path . '/url/class-merchant-field-url.php',
99 ),
100 'textarea' => array(
101 'class' => 'Merchant_Field_Textarea',
102 'file' => $base_path . '/textarea/class-merchant-field-textarea.php',
103 ),
104 'textarea_multiline' => array(
105 'class' => 'Merchant_Field_Textarea_Multiline',
106 'file' => $base_path . '/textarea-multiline/class-merchant-field-textarea-multiline.php',
107 ),
108 'textarea_code' => array(
109 'class' => 'Merchant_Field_Textarea_Code',
110 'file' => $base_path . '/textarea-code/class-merchant-field-textarea-code.php',
111 ),
112 'text_readonly' => array(
113 'class' => 'Merchant_Field_Text_Readonly',
114 'file' => $base_path . '/text-readonly/class-merchant-field-text-readonly.php',
115 ),
116 'color' => array(
117 'class' => 'Merchant_Field_Color',
118 'file' => $base_path . '/color/class-merchant-field-color.php',
119 ),
120 'range' => array(
121 'class' => 'Merchant_Field_Range',
122 'file' => $base_path . '/range/class-merchant-field-range.php',
123 ),
124 'date_time' => array(
125 'class' => 'Merchant_Field_Date_Time',
126 'file' => $base_path . '/date-time/class-merchant-field-date-time.php',
127 ),
128 'select' => array(
129 'class' => 'Merchant_Field_Select',
130 'file' => $base_path . '/select/class-merchant-field-select.php',
131 ),
132 'select_ajax' => array(
133 'class' => 'Merchant_Field_Select_Ajax',
134 'file' => $base_path . '/select-ajax/class-merchant-field-select-ajax.php',
135 ),
136 'select_size_chart' => array(
137 'class' => 'Merchant_Field_Select_Size_Chart',
138 'file' => $base_path . '/select-size-chart/class-merchant-field-select-size-chart.php',
139 ),
140 'radio' => array(
141 'class' => 'Merchant_Field_Radio',
142 'file' => $base_path . '/radio/class-merchant-field-radio.php',
143 ),
144 'radio_alt' => array(
145 'class' => 'Merchant_Field_Radio_Alt',
146 'file' => $base_path . '/radio-alt/class-merchant-field-radio-alt.php',
147 ),
148 'buttons' => array(
149 'class' => 'Merchant_Field_Buttons',
150 'file' => $base_path . '/buttons/class-merchant-field-buttons.php',
151 ),
152 'buttons_alt' => array(
153 'class' => 'Merchant_Field_Buttons_Alt',
154 'file' => $base_path . '/buttons-alt/class-merchant-field-buttons-alt.php',
155 ),
156 'buttons_content' => array(
157 'class' => 'Merchant_Field_Buttons_Content',
158 'file' => $base_path . '/buttons-content/class-merchant-field-buttons-content.php',
159 ),
160 'image_picker' => array(
161 'class' => 'Merchant_Field_Image_Picker',
162 'file' => $base_path . '/image-picker/class-merchant-field-image-picker.php',
163 ),
164 'choices' => array(
165 'class' => 'Merchant_Field_Choices',
166 'file' => $base_path . '/choices/class-merchant-field-choices.php',
167 ),
168 'switcher' => array(
169 'class' => 'Merchant_Field_Switcher',
170 'file' => $base_path . '/switcher/class-merchant-field-switcher.php',
171 ),
172 'checkbox' => array(
173 'class' => 'Merchant_Field_Checkbox',
174 'file' => $base_path . '/checkbox/class-merchant-field-checkbox.php',
175 ),
176 'checkbox_multiple' => array(
177 'class' => 'Merchant_Field_Checkbox_Multiple',
178 'file' => $base_path . '/checkbox-multiple/class-merchant-field-checkbox-multiple.php',
179 ),
180 'dimensions' => array(
181 'class' => 'Merchant_Field_Dimensions',
182 'file' => $base_path . '/dimensions/class-merchant-field-dimensions.php',
183 ),
184 'responsive_dimensions' => array(
185 'class' => 'Merchant_Field_Responsive_Dimensions',
186 'file' => $base_path . '/responsive-dimensions/class-merchant-field-responsive-dimensions.php',
187 ),
188 'sortable' => array(
189 'class' => 'Merchant_Field_Sortable',
190 'file' => $base_path . '/sortable/class-merchant-field-sortable.php',
191 ),
192 'sortable_repeater' => array(
193 'class' => 'Merchant_Field_Sortable_Repeater',
194 'file' => $base_path . '/sortable-repeater/class-merchant-field-sortable-repeater.php',
195 ),
196 'upload' => array(
197 'class' => 'Merchant_Field_Upload',
198 'file' => $base_path . '/upload/class-merchant-field-upload.php',
199 ),
200 'gallery' => array(
201 'class' => 'Merchant_Field_Gallery',
202 'file' => $base_path . '/gallery/class-merchant-field-gallery.php',
203 ),
204 'hook_select' => array(
205 'class' => 'Merchant_Field_Hook_Select',
206 'file' => $base_path . '/hook-select/class-merchant-field-hook-select.php',
207 ),
208 'create_page' => array(
209 'class' => 'Merchant_Field_Create_Page',
210 'file' => $base_path . '/create-page/class-merchant-field-create-page.php',
211 ),
212 'products_selector' => array(
213 'class' => 'Merchant_Field_Products_Selector',
214 'file' => $base_path . '/products-selector/class-merchant-field-products-selector.php',
215 ),
216 'reviews_selector' => array(
217 'class' => 'Merchant_Field_Reviews_Selector',
218 'file' => $base_path . '/reviews-selector/class-merchant-field-reviews-selector.php',
219 ),
220 'wc_coupons' => array(
221 'class' => 'Merchant_Field_Wc_Coupons',
222 'file' => $base_path . '/wc-coupons/class-merchant-field-wc-coupons.php',
223 ),
224 'flexible_content' => array(
225 'class' => 'Merchant_Field_Flexible_Content',
226 'file' => $base_path . '/flexible-content/class-merchant-field-flexible-content.php',
227 ),
228 'fields_group' => array(
229 'class' => 'Merchant_Field_Fields_Group',
230 'file' => $base_path . '/fields-group/class-merchant-field-fields-group.php',
231 ),
232 'content' => array(
233 'class' => 'Merchant_Field_Content',
234 'file' => $base_path . '/content/class-merchant-field-content.php',
235 ),
236 'divider' => array(
237 'class' => 'Merchant_Field_Divider',
238 'file' => $base_path . '/divider/class-merchant-field-divider.php',
239 ),
240 'info' => array(
241 'class' => 'Merchant_Field_Info',
242 'file' => $base_path . '/info/class-merchant-field-info.php',
243 ),
244 'info_block' => array(
245 'class' => 'Merchant_Field_Info_Block',
246 'file' => $base_path . '/info-block/class-merchant-field-info-block.php',
247 ),
248 'warning' => array(
249 'class' => 'Merchant_Field_Warning',
250 'file' => $base_path . '/warning/class-merchant-field-warning.php',
251 ),
252 'custom_callback' => array(
253 'class' => 'Merchant_Field_Custom_Callback',
254 'file' => $base_path . '/custom-callback/class-merchant-field-custom-callback.php',
255 ),
256 );
257
258 /**
259 * Filter: register, override, or remove field types.
260 *
261 * Allows 3rd-party plugins and Merchant Pro to register custom field types
262 * or override existing ones.
263 *
264 * Expected format: array( 'type_key' => array( 'class' => 'ClassName', 'file' => '/path/to/file.php' ) )
265 *
266 * @since 2.2.5
267 *
268 * @param array<string, array<string, string>> $field_types Map of type key => config array.
269 */
270 $field_types = apply_filters( 'merchant_field_types', $field_types );
271
272 // Load and register each field type.
273 foreach ( $field_types as $type_key => $config ) {
274 if ( ! empty( $config['file'] ) && file_exists( $config['file'] ) ) {
275 require_once $config['file'];
276 }
277
278 if ( ! empty( $config['class'] ) && class_exists( $config['class'] ) ) {
279 $this->register( $type_key, $config['class'] );
280 }
281 }
282 }
283
284 /**
285 * Check if a field type is registered.
286 *
287 * @since 2.2.5
288 *
289 * @param string $type The field type string.
290 *
291 * @return bool
292 */
293 public function has( $type ) {
294 return isset( $this->types[ $type ] );
295 }
296
297 /**
298 * Create a field instance for the given type.
299 *
300 * @since 2.2.5
301 *
302 * @param string $type The field type string.
303 * @param array<string, mixed> $field The field configuration array.
304 * @param mixed $value The current saved value.
305 * @param string $module_id The module ID.
306 *
307 * @return Merchant_Field_Interface|null The field instance, or null if type is unknown and text fallback unavailable.
308 */
309 public function create( $type, $field, $value = null, $module_id = '' ) {
310 if ( ! $this->has( $type ) ) {
311 _doing_it_wrong(
312 __METHOD__,
313 sprintf(
314 /* translators: %s: field type */
315 'Unknown field type "%s". Falling back to text field.',
316 esc_html( $type )
317 ),
318 '2.2.5'
319 );
320
321 // Fallback to text field if available, otherwise return a basic instance.
322 if ( $this->has( 'text' ) ) {
323 $class = $this->types['text'];
324
325 /** @var Merchant_Field_Interface $instance */
326 $instance = new $class( $field, $value, $module_id );
327
328 return $instance;
329 }
330
331 // If even text is not registered, this is an early bootstrap call.
332 return null;
333 }
334
335 $class = $this->types[ $type ];
336
337 /** @var Merchant_Field_Interface $instance */
338 $instance = new $class( $field, $value, $module_id );
339
340 return $instance;
341 }
342
343 /**
344 * Get all registered types.
345 *
346 * @since 2.2.5
347 *
348 * @return array<string, string> Map of type => class name.
349 */
350 public function get_types() {
351 return $this->types;
352 }
353
354 /**
355 * Register a field type manually.
356 *
357 * Used internally and by the merchant_field_types filter.
358 *
359 * @since 2.2.5
360 *
361 * @param string $type The field type string.
362 * @param string $class_name The fully qualified class name.
363 *
364 * @return void
365 */
366 public function register( $type, $class_name ) {
367 $this->types[ $type ] = $class_name;
368 }
369 }
370