PluginProbe
Code Snippets / trunk
Code Snippets vtrunk
4.0.0-beta.2 3.10.2 3.10.1 3.10.0 3.10.0-beta.2 3.10.0-beta.1 4.0.0-beta.1 3.9.6 trunk 2.10.0 2.10.1 2.12.0 2.12.1 2.13.0 2.13.1 2.13.2 2.13.3 2.14.0 2.14.1 2.14.2 2.14.3 2.14.4 2.14.5 2.14.6 3.0.0 All 65 releases
code-snippets / php / Settings / Setting_Field.php

Setting_Field.php in Code Snippets trunk, at php/Settings/Setting_Field.php

282 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Code_Snippets\Settings;
4
5 /**
6 * Represents a single setting field.
7 *
8 * @property-read string $desc Field description.
9 * @property-read string $label Field label.
10 * @property-read string $type Field type.
11 * @property-read string $name Setting name.
12 *
13 * @property-read int $min Minimum value (for numerical inputs).
14 * @property-read int $max Maximum value(for numerical inputs).
15 * @property-read array<string, string> $options List of options for a select or checkboxes field.
16 * @property-read callable $render_callback Custom function to use when rendering a callback field.
17 * @property-read callable $sanitize_callback Custom function to use when sanitize the setting value.
18 * @property-read mixed $default Default setting value.
19 *
20 * @property-read string $input_name Value of `name` HTML attribute on an input element.
21 * @property-read string $element_id
22 */
23 class Setting_Field {
24
25 /**
26 * Input field identifier.
27 *
28 * @var string
29 */
30 private string $field_id;
31
32 /**
33 * Settings section identifier.
34 *
35 * @var string
36 */
37 private string $section;
38
39 /**
40 * List of possible arguments.
41 *
42 * @var array<string, mixed>
43 */
44 private array $args = array(
45 'desc' => '',
46 'label' => '',
47 'min' => null,
48 'max' => null,
49 'options' => [],
50 );
51
52 /**
53 * Class constructor.
54 *
55 * @param string $section_id Settings section identifier.
56 * @param string $field_id Setting field identifier.
57 * @param array<string, mixed> $args The setting field attributes.
58 */
59 public function __construct( string $section_id, string $field_id, array $args ) {
60 $this->field_id = $field_id;
61 $this->section = $section_id;
62 $this->args = array_merge( $this->args, $args );
63 }
64
65 /**
66 * Retrieve a single setting attribute.
67 *
68 * @param string $argument Attribute name.
69 *
70 * @return mixed Attribute value.
71 */
72 public function __get( string $argument ) {
73
74 if ( 'input_name' === $argument ) {
75 return sprintf( '%s[%s][%s]', OPTION_NAME, $this->section, $this->field_id );
76 }
77
78 // Stable DOM id for the rendered control, so the settings-table heading
79 // can be associated with it via `label_for` (accessible name).
80 if ( 'element_id' === $argument ) {
81 return sanitize_key( sprintf( '%s_%s_%s', OPTION_NAME, $this->section, $this->field_id ) );
82 }
83
84 return $this->args[ $argument ];
85 }
86
87 /**
88 * Retrieve the saved value for this setting.
89 *
90 * @return mixed
91 */
92 private function get_saved_value() {
93 return get_setting( $this->section, $this->field_id );
94 }
95
96 /**
97 * Render the setting field
98 */
99 public function render() {
100 switch ( $this->type ) {
101 case 'callback':
102 if ( is_callable( $this->render_callback ) ) {
103 call_user_func( $this->render_callback, $this->args );
104 }
105 break;
106
107 case 'checkbox':
108 $this->render_checkbox( $this->input_name, $this->label, $this->get_saved_value() ?? false );
109 break;
110
111 case 'checkboxes':
112 $this->render_checkboxes_field();
113 break;
114
115 case 'text':
116 $this->render_text_field();
117 break;
118
119 case 'number':
120 $this->render_number_field();
121 break;
122
123 case 'select':
124 $this->render_select_field();
125 break;
126
127 case 'action':
128 $this->render_action_field();
129 break;
130
131 default:
132 // Error message, not necessary to translate.
133 printf( 'Cannot render a %s field.', esc_html( $this->type ) );
134 return;
135
136 }
137
138 if ( $this->desc ) {
139 echo '<p class="description">', wp_kses_post( $this->desc ), '</p>';
140 }
141 }
142
143 /**
144 * Render a single checkbox field.
145 *
146 * @param string $input_name Input name.
147 * @param string $label Input label.
148 * @param bool $checked Whether the checkbox should be checked.
149 */
150 private static function render_checkbox( string $input_name, string $label, bool $checked ) {
151 $checkbox = sprintf(
152 '<input type="checkbox" name="%s" %s>',
153 esc_attr( $input_name ),
154 checked( $checked, true, false )
155 );
156
157 $allowed_html = [
158 'input' => [
159 'type' => [],
160 'name' => [],
161 'checked' => [],
162 ],
163 ];
164
165 if ( $label ) {
166 printf(
167 '<label>%s %s</label>',
168 wp_kses( $checkbox, $allowed_html ),
169 wp_kses_post( $label )
170 );
171 } else {
172 echo wp_kses( $checkbox, $allowed_html );
173 }
174 }
175
176 /**
177 * Render a checkbox field for a setting
178 *
179 * @return void
180 * @since 2.0.0
181 */
182 public function render_checkboxes_field() {
183 $saved_value = $this->get_saved_value();
184 $saved_value = is_array( $saved_value ) ? $saved_value : [];
185
186 echo '<fieldset>';
187 printf( '<legend class="screen-reader-text"><span>%s</span></legend>', esc_html( $this->name ) );
188
189 foreach ( $this->options as $option => $label ) {
190 $this->render_checkbox( $this->input_name . "[$option]", $label, in_array( $option, $saved_value, true ) );
191 echo '<br>';
192 }
193
194 echo '</fieldset>';
195 }
196
197 /**
198 * Render a basic text field for an editor setting.
199 *
200 * @return void
201 */
202 private function render_text_field() {
203 printf(
204 '<input id="%s" type="text" name="%s" value="%s" class="regular-text %s">',
205 esc_attr( $this->element_id ),
206 esc_attr( $this->input_name ),
207 esc_attr( $this->get_saved_value() ),
208 esc_attr( $this->element_id )
209 );
210
211 if ( $this->label ) {
212 echo ' ' . wp_kses_post( $this->label );
213 }
214 }
215
216 /**
217 * Render a number select field for an editor setting
218 *
219 * @since 2.0.0
220 */
221 private function render_number_field() {
222 printf(
223 '<input id="%s" type="number" name="%s" value="%s"',
224 esc_attr( $this->element_id ),
225 esc_attr( $this->input_name ),
226 esc_attr( $this->get_saved_value() )
227 );
228
229 if ( is_numeric( $this->min ) ) {
230 printf( ' min="%d"', intval( $this->min ) );
231 }
232
233 if ( is_numeric( $this->max ) ) {
234 printf( ' max="%d"', intval( $this->max ) );
235 }
236
237 echo '>';
238
239 if ( $this->label ) {
240 echo ' ' . wp_kses_post( $this->label );
241 }
242 }
243
244 /**
245 * Render a number select field for an editor setting.
246 *
247 * @since 3.0.0
248 */
249 private function render_select_field() {
250 $saved_value = $this->get_saved_value();
251 printf(
252 '<select id="%s" name="%s">',
253 esc_attr( $this->element_id ),
254 esc_attr( $this->input_name )
255 );
256
257 foreach ( $this->options as $option => $option_label ) {
258 printf(
259 '<option value="%s" %s>%s</option>',
260 esc_attr( $option ),
261 selected( $option, $saved_value, false ),
262 esc_html( $option_label )
263 );
264 }
265
266 echo '</select>';
267 }
268
269 /**
270 * Render a button link.
271 *
272 * @since 3.5.1
273 */
274 private function render_action_field() {
275 printf(
276 '<button type="submit" name="%s" class="button">%s</button>',
277 esc_attr( $this->input_name ),
278 esc_html( $this->label ? $this->label : $this->name )
279 );
280 }
281 }
282