2
2
/**
3
3
* EarthAsylum Consulting {eac}Doojigger derivative
4
4
*
5
+ * Provides examples of input types, parameters, and processing callbacks & filters.
6
+ *
5
7
* @category WordPress Plugin
6
8
* @package myOptionsTest, {eac}Doojigger derivative
7
9
* @author Kevin Burkholder <KBurkholder@EarthAsylum.com>
8
- * @copyright Copyright (c) 2023 EarthAsylum Consulting <www.earthasylum.com>
9
- * @version 1.x
10
+ * @copyright Copyright (c) 2024 EarthAsylum Consulting <www.earthasylum.com>
11
+ * @version 24.0426.1
10
12
*/
11
13
12
14
namespace EarthAsylumConsulting \Plugin ;
@@ -94,78 +96,108 @@ public function admin_options_settings()
94
96
foreach (self ::INPUT_TYPES as $ type )
95
97
{
96
98
$ typeId = str_replace ('- ' ,'_ ' ,$ type );
97
- /* define the input meta-data array */
98
- $ options [ "input_ {$ typeId }" ] = array (
99
- 'type ' => $ type ,
100
- 'title ' => "HTML input type: {$ type }" ,
101
- 'label ' => ucwords (str_replace ('- ' ,' ' ,$ type )),
102
- 'before ' => '<span class="dashicons dashicons-arrow-left-alt2"></span> ' ,
103
- 'options ' => [$ type =>$ type , 'option2 ' =>'2 ' , 'option3 ' =>'3 ' ],
104
- 'default ' => $ type ,
105
- 'after ' => '<span class="dashicons dashicons-arrow-right-alt2"></span> ' ,
106
- 'info ' => "Saved option name: ' " .$ this ->prefixOptionName ("input_ {$ typeId }" )."' " ,
107
- // 'class' => "{$type}_class",
108
- // 'style' => "max-width: 50em;",
109
- /* attributes as a string */
110
- 'attributes ' => "placeholder=' {$ type }' alt=' {$ type } input' title='input type: {$ type }' " ,
111
- /* attributes as array of strings */
112
- // 'attributes' => [ "placeholder='{$type}'", "alt='{$type} input'", "title='input type: {$type}'" ],
113
- /* attributes as associative array */
114
- // 'attributes' => [ 'placeholder'=>$type, 'alt'=>"{$type} input", 'title'=>"input type: {$type}" ],
115
- /* attributes as array of [strings] */
116
- // 'attributes' => [ ["data-1"], ["data-2"], ["data-3"=>"data-3"] ],
117
- 'sanitize ' => [ $ this ,'sanitize_callback ' ],
118
- 'filter ' => [ FILTER_CALLBACK , ['options ' =>[$ this ,'filter_callback ' ]] ],
119
- 'validate ' => [ $ this ,'validate_callback ' ],
120
- // contextual help using meta ([title],[type],[info]) macros
121
- 'help ' => "<details><summary>[title]</summary>This field is an HTML input type '[type]'<br>[info]</details> " ,
99
+ /*
100
+ define the input meta-data array.
101
+ normally fields are defineed individually with appropriate parameters for each.
102
+ here we use a foreach loop for all input types where some parameters may not be applicable.
103
+ */
104
+ $ options [ "input_ {$ typeId }" ] = array
105
+ (
106
+ 'type ' => $ type ,
107
+ 'title ' => "HTML input type: {$ type }" ,
108
+ 'label ' => ucwords (str_replace ('- ' ,' ' ,$ type )),
109
+ 'before ' => '<span class="dashicons dashicons-arrow-left-alt2"></span> ' ,
110
+ 'options ' => [$ type =>$ type , 'option2 ' =>'2 ' , 'option3 ' =>'3 ' ],
111
+ 'default ' => $ type ,
112
+ 'after ' => '<span class="dashicons dashicons-arrow-right-alt2"></span> ' ,
113
+ 'info ' => "Saved option name: ' " .$ this ->prefixOptionName ("input_ {$ typeId }" )."' " ,
114
+ // info is converted to tooltip if tooltip isn't set, here we do both.
115
+ 'tooltip ' => "This field is an HTML input type '[type]' " ,
116
+ // 'class' => "{$type}_class",
117
+ // 'style' => "max-width: 50em;",
118
+ /* attributes as a string */
119
+ 'attributes ' => "placeholder=' {$ type }' alt=' {$ type } input' title='input type: {$ type }' " ,
120
+ /* attributes as array of strings */
121
+ // 'attributes' => [ "placeholder='{$type}'", "alt='{$type} input'", "title='input type: {$type}'" ],
122
+ /* attributes as associative array */
123
+ // 'attributes' => [ 'placeholder'=>$type, 'alt'=>"{$type} input", 'title'=>"input type: {$type}" ],
124
+ /* attributes as array of [strings] */
125
+ // 'attributes' => [ ["data-1"], ["data-2"], ["data-3"=>"data-3"] ],
126
+ 'sanitize ' => [ $ this ,'sanitize_callback ' ],
127
+ 'filter ' => [ FILTER_CALLBACK , ['options ' =>[$ this ,'filter_callback ' ]] ],
128
+ 'validate ' => [ $ this ,'validate_callback ' ],
129
+ // contextual help using meta ([title],[tooltip],[info]) macros
130
+ 'help ' => "<details><summary>[title]</summary>[tooltip]<br>[info]</details> " ,
122
131
);
123
132
124
- /* display values when changed */
133
+ /* display values when changed for these fields */
125
134
if (in_array ($ type ,['color ' ,'date ' ,'datetime-local ' ,'month ' ,'time ' ,'week ' ]))
126
135
{
127
- $ options ["input_ {$ typeId }" ]['attributes ' ] = ['oninput ' =>"input_ {$ typeId }_show.value = this.value " ];
128
- $ options ["input_ {$ typeId }" ]['after ' ] .= "<output name='input_ {$ typeId }_show' for='input_ {$ typeId }' style='padding:2em;color:blue;'>...</output> " ;
136
+ $ options ["input_ {$ typeId }" ]
137
+ ['attributes ' ] = ['oninput ' =>"input_ {$ typeId }_show.value = this.value " ];
138
+ $ options ["input_ {$ typeId }" ]
139
+ ['after ' ] .= "<output name='input_ {$ typeId }_show' for='input_ {$ typeId }' style='padding:2em;color:blue;'>...</output> " ;
140
+ }
141
+
142
+ /* don't use generic callbacks for file upload, see my_form_post_file() */
143
+ if ($ type == 'file ' )
144
+ {
145
+ unset( $ options ["input_ {$ typeId }" ]['sanitize ' ],
146
+ $ options ["input_ {$ typeId }" ]['filter ' ],
147
+ $ options ["input_ {$ typeId }" ]['validate ' ]
148
+ );
129
149
}
130
150
131
151
/* add output display and formatted data-points to our range input */
132
152
if ($ type == 'range ' )
133
153
{
134
- $ options ["input_ {$ typeId }" ]['attributes ' ] = ['min="0" ' , 'max="10" ' ,'step="1" ' , "list='input_ {$ typeId }_ticks' " ,
135
- 'oninput ' =>"input_ {$ typeId }_show.value = this.value " ];
136
- $ options ["input_ {$ typeId }" ]['default ' ] = 5 ;
137
- $ options ["input_ {$ typeId }" ]['after ' ] .= "<output name='input_ {$ typeId }_show' for='input_ {$ typeId }' style='padding:2em;color:blue;'></output> " .
138
- "<datalist id='input_ {$ typeId }_ticks'> " .
139
- '<option value="0" label="0"></option> ' .
140
- '<option value="1"></option> ' .
141
- '<option value="2" label="2"></option> ' .
142
- '<option value="3"></option> ' .
143
- '<option value="4" label="4"></option> ' .
144
- '<option value="5"></option> ' .
145
- '<option value="6" label="6"></option> ' .
146
- '<option value="7"></option> ' .
147
- '<option value="8" label="8"></option> ' .
148
- '<option value="9"></option> ' .
149
- '<option value="10" label="10"></option> ' .
150
- '</datalist> ' ;
154
+ unset($ options ["input_ {$ typeId }" ]['before ' ]);
155
+ $ options ["input_ {$ typeId }" ]
156
+ ['attributes ' ] = ['min="0" ' , 'max="10" ' ,'step=".5" ' , "list='input_ {$ typeId }_ticks' " ,
157
+ 'oninput ' =>"input_ {$ typeId }_show.value = this.value " ];
158
+ $ options ["input_ {$ typeId }" ]
159
+ ['default ' ] = 5 ;
160
+ $ options ["input_ {$ typeId }" ]
161
+ ['after ' ] =
162
+ "<datalist id='input_ {$ typeId }_ticks'> " .
163
+ '<option value="0" label="0"></option> ' .
164
+ '<option value="1"></option> ' .
165
+ '<option value="2" label="2"></option> ' .
166
+ '<option value="3"></option> ' .
167
+ '<option value="4" label="4"></option> ' .
168
+ '<option value="5"></option> ' .
169
+ '<option value="6" label="6"></option> ' .
170
+ '<option value="7"></option> ' .
171
+ '<option value="8" label="8"></option> ' .
172
+ '<option value="9"></option> ' .
173
+ '<option value="10" label="10"></option> ' .
174
+ '</datalist> ' .
175
+ "Range input: <code> " .
176
+ "<output name='input_ {$ typeId }_show' for='input_ {$ typeId }' " .
177
+ "style='padding:1em;color:blue;'>[value]</output> " .
178
+ "</code> " ;
151
179
}
152
180
}
153
181
154
182
/* register this plugin with options */
155
183
$ this ->registerPluginOptions ('plugin_settings ' ,$ options );
156
184
157
- /* filters to handle 'custom' input field ('input_custom is field name)*/
158
- $ this ->add_filter ( 'options_form_input_input_custom ' , array ($ this , 'options_form_input_custom ' ), 10 , 4 );
159
- $ this ->add_filter ( 'options_form_post_input_custom ' , array ($ this , 'options_form_post_custom ' ), 10 , 4 );
160
185
161
- /* filter to handle 'file' input field ('input_file is field name)*/
162
- $ this ->add_filter ( 'options_form_post_input_file ' , array ($ this , 'options_form_post_file ' ), 10 , 4 );
186
+ /* filters to handle 'custom' input field ('input_custom' is field name)*/
187
+ $ this ->add_filter ( 'options_form_input_input_custom ' , array ($ this , 'my_form_input_custom ' ), 10 , 4 );
188
+ $ this ->add_filter ( 'options_form_post_input_custom ' , array ($ this , 'my_form_post_custom ' ), 10 , 4 );
189
+
190
+
191
+ /* filter to handle 'file' input field ('input_file' is field name)*/
192
+ $ this ->add_filter ( 'options_form_post_input_file ' , array ($ this , 'my_form_post_file ' ), 10 , 4 );
193
+
194
+
195
+ /* filter to sanitize all fields individually (redundant when using above 'sanitize' callback) */
196
+ $ this ->add_filter ( 'sanitize_option ' , array ($ this , 'my_option_sanitize ' ), 10 , 4 );
163
197
164
- /* filter to sanitize all fields */
165
- $ this ->add_filter ( 'sanitize_option ' , array ($ this , 'sanitize_options ' ), 10 , 4 );
166
198
167
199
/* action after form posted and fields updated */
168
- // $this->add_action( 'options_form_post', array($this, 'my_options_form_post') );
200
+ $ this ->add_action ( 'options_form_post ' , array ($ this , 'my_options_form_post ' ) );
169
201
}
170
202
171
203
@@ -210,7 +242,10 @@ public function addActionsAndFilters(): void
210
242
{
211
243
parent ::addActionsAndFilters ();
212
244
213
- /* custom stylesheet action - add formatting for our input_range data-points */
245
+ /*
246
+ custom stylesheet action - called when stylesheet is enqueued
247
+ add formatting for our input_range data-points
248
+ */
214
249
$ this ->add_action ('admin_enqueue_styles ' , function ($ styleId )
215
250
{
216
251
$ style =
@@ -219,24 +254,24 @@ public function addActionsAndFilters(): void
219
254
"display: flex; width: 80%; max-width: 38em; " .
220
255
"justify-content: space-between; " .
221
256
"font-size: 0.85em; color:blue; " .
222
- "padding-left: 2em; " .
223
- "} \n " ;
257
+ "padding-left: . 2em; " .
258
+ "} " ;
224
259
225
260
wp_add_inline_style ( $ styleId , $ style );
226
261
});
227
262
}
228
263
229
264
230
265
/**
231
- * options_form_input_{$fieldName} filter
266
+ * options_form_input_{$fieldName} filter - input_custom field
232
267
*
233
268
* @param string $html current html for field
234
269
* @param string $fieldName option name
235
270
* @param array $metaData option meta data
236
271
* @param mixed $value current option value
237
272
* @return string new html for field
238
273
*/
239
- public function options_form_input_custom ($ html , $ fieldName , $ metaData , $ value )
274
+ public function my_form_input_custom ($ html , $ fieldName , $ metaData , $ value )
240
275
{
241
276
// The default for custom is:
242
277
// <blockquote>[title]</blockquote>
@@ -248,7 +283,7 @@ public function options_form_input_custom($html, $fieldName, $metaData, $value)
248
283
"<mark>Custom input field</mark> " .
249
284
"<input type=' {$ metaData ['type ' ]}' name=' {$ fieldName }' id=' {$ fieldName }' " .
250
285
"value=' {$ value }' size=' {$ metaData ['width ' ]}' {$ metaData ['attributes ' ]} /> " ,
251
- $ html );
286
+ $ html );
252
287
// return the updated input html wrapped in a styled <div>
253
288
return "<div class='custom-example' style='border: solid 1px yellow; padding: .5em; background: #ddd;'> " .
254
289
$ html .
@@ -257,66 +292,77 @@ public function options_form_input_custom($html, $fieldName, $metaData, $value)
257
292
258
293
259
294
/**
260
- * options_form_post_{$fieldName} filter
295
+ * options_form_post_{$fieldName} filter - input_custom field
261
296
*
262
297
* @param mixed $value posted option value(s)
263
298
* @param string $fieldName option name
264
299
* @param array $metaData option meta data
265
300
* @param mixed $priorValue prior option value
266
301
* @return mixed new option value(s)
267
302
*/
268
- public function options_form_post_custom ($ value , $ fieldName , $ metaData , $ priorValue )
303
+ public function my_form_post_custom ($ value , $ fieldName , $ metaData , $ priorValue )
269
304
{
270
305
// if no change, just return the value
271
306
if ($ value == $ priorValue ) return $ value ;
272
307
273
308
// sanitize/validate (or otherwise process) the value before it is saved to the database
309
+
274
310
return $ value ;
275
311
}
276
312
277
313
278
314
/**
279
- * options_form_post_{$fieldName} filter
315
+ * options_form_post_{$fieldName} filter - input_file field
280
316
*
281
317
* @param mixed $value posted option value(s)
282
318
* @param string $fieldName option name
283
319
* @param array $metaData option meta data
284
320
* @param mixed $priorValue prior option value
285
321
* @return mixed new option value(s)
286
322
*/
287
- public function options_form_post_file ($ value , $ fieldName , $ metaData , $ priorValue )
323
+ public function my_form_post_file ($ value , $ fieldName , $ metaData , $ priorValue )
288
324
{
289
- if (! isset ($ value ['error ' ]) && $ value ['type ' ] == 'application/json ' )
325
+ // for 'file' type, $value is the array returned by wp_handle_upload()
326
+ if (! isset ($ value ['error ' ]))
290
327
{
291
- // valid upload with expected file type, $values['file'] is pathname
292
- if ($ data = wp_json_file_decode ($ values ['file ' ],['associative ' =>true ]))
328
+ if ($ value ['type ' ] == 'application/json ' )
293
329
{
294
- // do something here...
330
+ // valid upload with expected file type, $values['file'] is pathname
331
+ if ($ data = wp_json_file_decode ($ values ['file ' ],['associative ' =>true ]))
332
+ {
333
+ // do something here...
334
+ }
335
+ unlink ($ value ['file ' ]);
336
+ return $ value ;
337
+ }
338
+ else
339
+ {
340
+ $ this ->add_option_error (
341
+ $ fieldName ,
342
+ sprintf ("%s : Input file of type '%s' could not be processed. " ,$ metaData ['label ' ],$ value ['type ' ])
343
+ );
295
344
}
296
- unlink ($ value ['file ' ]);
297
- return $ value ;
298
345
}
299
346
300
- $ this ->add_option_error (
301
- $ aOptionKey ,
302
- sprintf ('%s : Input file could not be processed. ' ,$ aOptionMeta ['label ' ])
303
- );
304
347
unlink ($ values ['file ' ]);
305
348
return $ value ;
306
349
}
307
350
308
351
309
352
/**
310
- * sanitize_option filter
353
+ * sanitize_option filter called for each option POSTed
311
354
*
312
355
* @param mixed $value posted option value(s)
313
356
* @param string $fieldName option name
314
357
* @param array $metaData option meta data
315
358
* @param mixed $priorValue prior option value
316
359
* @return mixed new option value(s)
317
360
*/
318
- public function sanitize_options ($ value , $ fieldName , $ metaData , $ priorValue )
361
+ public function my_option_sanitize ($ value , $ fieldName , $ metaData , $ priorValue )
319
362
{
363
+ // if no change, just return the value
364
+ if ($ value == $ priorValue ) return $ value ;
365
+
320
366
switch ($ fieldName )
321
367
{
322
368
case 'input_number ' :
@@ -355,6 +401,7 @@ public function sanitize_options($value, $fieldName, $metaData, $priorValue)
355
401
*/
356
402
public function sanitize_callback ($ value , $ fieldName , $ metaData , $ priorValue )
357
403
{
404
+ // sanitize value
358
405
return $ value ;
359
406
}
360
407
@@ -370,10 +417,13 @@ public function sanitize_callback($value, $fieldName, $metaData, $priorValue)
370
417
*/
371
418
public function filter_callback ($ value , $ fieldName , $ metaData , $ priorValue )
372
419
{
420
+ // if no change, just return the value
421
+ if ($ value == $ priorValue ) return $ value ;
422
+
373
423
// validate the value and display a notification
374
424
if (is_numeric ($ value ))
375
425
{
376
- // add admin notice using helper method (does not use transient)
426
+ // add admin notice using helper method
377
427
$ this ->add_admin_notice (
378
428
$ fieldName .": {$ value } May be the Answer to the Ultimate Question of Life, the Universe, and Everything. " ,
379
429
'notice ' ,
0 commit comments