PluginProbe
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant / 2.3.2
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant v2.3.2
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 / fields / fields-group / class-merchant-field-fields-group.php

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

175 lines 5.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Merchant Field: Fields Group
4 *
5 * A container field that groups multiple sub-fields together, with optional
6 * accordion display, status flag, and support for nesting inside flexible_content.
7 *
8 * @package Merchant
9 * @since 2.2.5
10 */
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit;
14 }
15
16 /**
17 * Merchant_Field_Fields_Group
18 *
19 * Renders a collapsible group of nested sub-fields.
20 *
21 * @since 2.2.5
22 */
23 class Merchant_Field_Fields_Group extends Merchant_Abstract_Field {
24
25 /**
26 * Whether this group renders a status (active/inactive) control.
27 *
28 * @since 2.3.0
29 * @param array<string, mixed> $settings The group field definition.
30 * @return bool
31 */
32 public static function has_status_field( $settings ) {
33 return ! empty( $settings['display_status'] ) && $settings['display_status'] === true;
34 }
35
36 /**
37 * Build the virtual status sub-field definition for a group.
38 *
39 * Injected at render time, not declared in `fields`. ID is `<group_id>_status`;
40 * defaults to the group's `default` (else 'active'). A malformed filter return
41 * (non-array or missing `id`/`options`) falls back to the unfiltered definition.
42 *
43 * @since 2.3.0
44 * @param array<string, mixed> $settings The group field definition.
45 * @param mixed $value Current group value (passed to the filter).
46 * @param string $module_id Module ID (passed to the filter).
47 * @return array<string, mixed>
48 */
49 public static function get_status_field_definition( $settings, $value = null, $module_id = '' ) {
50 $default_def = array(
51 'id' => $settings['id'] . '_status',
52 'type' => 'select',
53 'title' => esc_html__( 'Status', 'merchant' ),
54 'options' => array(
55 'inactive' => esc_html__( 'Inactive', 'merchant' ),
56 'active' => esc_html__( 'Active', 'merchant' ),
57 ),
58 'default' => isset( $settings['default'] ) ? $settings['default'] : 'active',
59 );
60
61 /**
62 * Filter the status field configuration for a group.
63 *
64 * A malformed return (non-array or missing 'id'/'options') is silently
65 * ignored and the default definition is used instead.
66 *
67 * @since 1.9.12
68 *
69 * @param mixed $default_def The default status field definition.
70 * @param array<string, mixed> $settings The parent group field settings.
71 * @param mixed $value Current group value.
72 * @param string $module_id Module ID.
73 */
74 $filtered = apply_filters( 'merchant_group_status_field', $default_def, $settings, $value, $module_id );
75
76 return ( is_array( $filtered ) && isset( $filtered['id'], $filtered['options'] ) ) ? $filtered : $default_def;
77 }
78
79 /**
80 * Render the fields group (standard usage, not inside flexible_content).
81 *
82 * @since 2.2.5
83 *
84 * @return void
85 */
86 public function render() {
87 $control_field_status = self::has_status_field( $this->field );
88 $accordion = ! empty( $this->field['accordion'] ) && $this->field['accordion'] === true;
89 $state = ! empty( $this->field['state'] ) && $this->field['state'] === 'open';
90
91 $this->get_template_part( 'template', array(
92 'accordion' => $accordion,
93 'control_field_status' => $control_field_status,
94 'state' => $state,
95 'inside_flexible' => false,
96 'args' => array(),
97 ) );
98 }
99
100 /**
101 * Render the fields group.
102 *
103 * Public static so flexible_content can call it with extra parameters
104 * for nested usage inside layouts.
105 *
106 * @since 2.2.5
107 *
108 * @param array<string, mixed> $settings Field settings.
109 * @param mixed $value Field value.
110 * @param string $module_id Module ID.
111 * @param bool $inside_flexible Whether this group is inside a flexible_content layout.
112 * @param array<string, mixed> $args Extra arguments when inside flexible_content.
113 *
114 * @return void
115 */
116 public static function render_group( $settings, $value, $module_id = '', $inside_flexible = false, $args = array() ) {
117 $control_field_status = self::has_status_field( $settings );
118 $accordion = ! empty( $settings['accordion'] ) && $settings['accordion'] === true;
119 $state = ! empty( $settings['state'] ) && $settings['state'] === 'open';
120
121 include __DIR__ . '/template.php';
122 }
123
124 /**
125 * Type-specific sanitization for the fields group.
126 *
127 * Fields group values are sanitized per-sub-field during save_options,
128 * so this method returns the value as-is.
129 *
130 * @since 2.2.5
131 *
132 * @param mixed $value The raw submitted value.
133 *
134 * @return mixed The sanitized value.
135 */
136 protected function sanitize_value( $value ) {
137 if ( ! is_array( $value ) || empty( $this->field['fields'] ) ) {
138 return $value;
139 }
140
141 $registry = Merchant_Field_Registry::instance();
142 $sanitized = array();
143
144 foreach ( $this->field['fields'] as $sub_field ) {
145 if ( ! isset( $sub_field['id'] ) ) {
146 continue;
147 }
148
149 $sub_id = $sub_field['id'];
150 $sub_value = $value[ $sub_id ] ?? ( $sub_field['default'] ?? null );
151 $sub_type = $sub_field['type'] ?? 'text';
152
153 if ( $registry->has( $sub_type ) ) {
154 $instance = $registry->create( $sub_type, $sub_field, $sub_value );
155 if ( $instance !== null ) {
156 $sub_value = $instance->preprocess( $sub_value );
157 $sub_value = $instance->sanitize( $sub_value );
158 }
159 } else {
160 $sub_value = sanitize_text_field( $sub_value );
161 }
162
163 $sanitized[ $sub_id ] = $sub_value;
164 }
165
166 // Preserve the status sub-field if present (injected by render_group).
167 $status_id = $this->field['id'] . '_status';
168 if ( isset( $value[ $status_id ] ) ) {
169 $sanitized[ $status_id ] = sanitize_text_field( $value[ $status_id ] );
170 }
171
172 return $sanitized;
173 }
174 }
175