1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Admin Page Framework |
4
|
|
|
* |
5
|
|
|
* http://admin-page-framework.michaeluno.jp/ |
6
|
|
|
* Copyright (c) 2013-2022, Michael Uno; Licensed MIT |
7
|
|
|
* |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Provides public methods to add form elements. |
12
|
|
|
* |
13
|
|
|
* @abstract |
14
|
|
|
* @since 2.0.0 |
15
|
|
|
* @since 3.3.1 Changed the name from `AdminPageFramework_Setting`. |
16
|
|
|
* @since 3.6.3 Changed the name from `AdminPageFramework_Form_Controller`. |
17
|
|
|
* @extends AdminPageFramework_View_Form |
18
|
|
|
* @package AdminPageFramework/Factory/AdminPage |
19
|
|
|
*/ |
20
|
|
|
abstract class AdminPageFramework_Controller_Form extends AdminPageFramework_View_Form { |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* {@inheritdoc} |
24
|
|
|
* |
25
|
|
|
* {@inheritdoc} |
26
|
|
|
* |
27
|
|
|
* <h4>Example</h4> |
28
|
|
|
* <code>$this->addSettingSections( |
29
|
|
|
* array( |
30
|
|
|
* 'section_id' => 'text_fields', |
31
|
|
|
* 'page_slug' => 'first_page', |
32
|
|
|
* 'tab_slug' => 'textfields', |
33
|
|
|
* 'title' => 'Text Fields', |
34
|
|
|
* 'description' => 'These are text type fields.', |
35
|
|
|
* 'order' => 10, |
36
|
|
|
* ), |
37
|
|
|
* array( |
38
|
|
|
* 'section_id' => 'selectors', |
39
|
|
|
* 'page_slug' => 'first_page', |
40
|
|
|
* 'tab_slug' => 'selectors', |
41
|
|
|
* 'title' => 'Selectors', |
42
|
|
|
* 'description' => 'These are selector type options such as dropdown lists, radio buttons, and checkboxes', |
43
|
|
|
* ) |
44
|
|
|
* );</code> |
45
|
|
|
* |
46
|
|
|
* @since 2.0.0 |
47
|
|
|
* @since 3.0.0 Changed the scope to public from protected. |
48
|
|
|
* @since 3.5.3 Removed the parameter declarations as they are caught with the func_get_args(). |
49
|
|
|
* @access public |
50
|
|
|
* @remark Accepts variadic parameters; the number of accepted parameters are not limited to three. |
51
|
|
|
* @remark The actual registration will be performed in the <em>_replyToRegisterSettings()</em> method with the <em>admin_menu</em> hook. |
52
|
|
|
* @remark The target section tab slug and the target tab slug will be reset once the method returns. |
53
|
|
|
* @param array|string the section array or the target page slug. If the target page slug is set, the next section array can omit the page slug key. |
54
|
|
|
* <h4>Section Array</h4> |
55
|
|
|
* <ul> |
56
|
|
|
* <li>**section_id** - (required, string) the section ID. Avoid using non-alphabetic characters except underscore and numbers.</li> |
57
|
|
|
* <li>**page_slug** - (optional, string) the page slug that the section belongs to. If the target page slug is set, it can be omitted.</li> |
58
|
|
|
* <li>**tab_slug** - (optional, string) the tab slug that the section belongs to. The tab here refers to in-page tabs.</li> |
59
|
|
|
* <li>**section_tab_slug** - (optional, string) [3.0.0+] the section tab slug that the section are grouped into. The tab here refers to section tabs.</li> |
60
|
|
|
* <li>**title** - (optional, string) the title of the section.</li> |
61
|
|
|
* <li>**capability** - (optional, string) the <a href="http://codex.wordpress.org/Roles_and_Capabilities">access level</a> of the section. If the page visitor does not have sufficient capability, the section will be invisible to them.</li> |
62
|
|
|
* <li>**if** - (optional, boolean) if the passed value is false, the section will not be registered.</li> |
63
|
|
|
* <li>**order** - (optional, integer) the order number of the section. The higher the number is, the lower the position it gets.</li> |
64
|
|
|
* <li>**help** - (optional, string) the help description added to the contextual help tab.</li> |
65
|
|
|
* <li>**help_aside** - (optional, string) the additional help description for the side bar of the contextual help tab.</li> |
66
|
|
|
* <li>**repeatable** - (optional, boolean|array) [3.0.0+] Indicates whether or not the section is repeatable. To set a minimum/maximum number of sections, pass an array with the key, `min`, and `max`. e.g. `array( 'min' => 3, 'max' => 10 )` |
67
|
|
|
* <ul> |
68
|
|
|
* <li>**max** - (optional, integer) The maximum number of repeated fields.</li> |
69
|
|
|
* <li>**min** - (optional, integer) The minimum number of repeated fields.</li> |
70
|
|
|
* <li>**disabled** - (optional, boolean|array) [3.8.13+] |
71
|
|
|
* <ul> |
72
|
|
|
* <li>**message** - (optional, string) the message to show when the user clicks on the `Add` repeatable button.</li> |
73
|
|
|
* <li>**caption** - (optional, string) the title of the modal window that displays the message. Default: Warning</li> |
74
|
|
|
* <li>**box_width** - (optional, integer) the width of the modal window that displays the message. Default: 300</li> |
75
|
|
|
* <li>**box_width** - (optional, integer) the height of the modal window that displays the message. Default: 100.</li> |
76
|
|
|
* <ul> |
77
|
|
|
* </li> |
78
|
|
|
* </ul> |
79
|
|
|
* </li> |
80
|
|
|
* </ul> |
81
|
|
|
* @param array (optional) another section array. |
|
|
|
|
82
|
|
|
* @param array (optional) add more section array to the next parameters as many as necessary. |
83
|
|
|
* @return void |
84
|
|
|
*/ |
85
|
|
|
public function addSettingSections( /* $aSection1, $aSection2=null, $_and_more=null */ ) { |
86
|
|
|
|
87
|
|
|
foreach( func_get_args() as $asSection ) { |
88
|
|
|
$this->addSettingSection( $asSection ); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
// reset the stored target tab slug and the target section tab slug |
92
|
|
|
$this->_sTargetTabSlug = null; |
93
|
|
|
$this->_sTargetSectionTabSlug = null; |
94
|
|
|
|
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* A singular form of the adSettingSections() method which takes only a single parameter. |
99
|
|
|
* |
100
|
|
|
* This is useful when adding section arrays in loops. |
101
|
|
|
* |
102
|
|
|
* @since 2.1.2 |
103
|
|
|
* @since 3.0.0 Changed the scope to public from protected. |
104
|
|
|
* @access public |
105
|
|
|
* @param array|string the section array. If a string is passed, it is considered as a target page slug that will be used as a page slug element from the next call so that the element can be omitted. |
106
|
|
|
* @return void |
107
|
|
|
*/ |
108
|
|
|
public function addSettingSection( $asSection ) { |
109
|
|
|
|
110
|
|
|
if ( ! is_array( $asSection ) ) { |
111
|
|
|
$this->_sTargetPageSlug = is_string( $asSection ) |
112
|
|
|
? $asSection |
113
|
|
|
: $this->_sTargetPageSlug; |
114
|
|
|
return; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
$aSection = $asSection; |
118
|
|
|
$this->_sTargetPageSlug = $this->_getTargetPageSlug( $aSection ); |
119
|
|
|
$this->_sTargetTabSlug = $this->_getTargetTabSlug( $aSection ); |
120
|
|
|
$this->_sTargetSectionTabSlug = $this->oUtil->getElement( $aSection, 'section_tab_slug', $this->_sTargetSectionTabSlug ); |
121
|
|
|
|
122
|
|
|
// Pre-format - avoid undefined index warnings. |
123
|
|
|
$aSection = $this->oUtil->uniteArrays( |
124
|
|
|
$aSection, |
125
|
|
|
array( |
126
|
|
|
'page_slug' => $this->_sTargetPageSlug, |
127
|
|
|
'tab_slug' => $this->_sTargetTabSlug, |
128
|
|
|
'section_tab_slug' => $this->_sTargetSectionTabSlug, |
129
|
|
|
) |
130
|
|
|
); |
131
|
|
|
|
132
|
|
|
$aSection[ 'section_tab_slug' ] = $this->oUtil->sanitizeSlug( $aSection[ 'section_tab_slug' ] ); |
133
|
|
|
|
134
|
|
|
// A page slug is required. |
135
|
|
|
if ( ! $aSection[ 'page_slug' ] ) { |
136
|
|
|
return; |
137
|
|
|
} |
138
|
|
|
$this->oForm->addSection( $aSection ); |
139
|
|
|
|
140
|
|
|
} |
141
|
|
|
/** |
142
|
|
|
* Sets the target page slug of the section. |
143
|
|
|
* If a page slug is not set, set the currently loading one from the registered items. |
144
|
|
|
* Do not simply assign the currently loaded page but the one added by the user because the method can be called from anyware. |
145
|
|
|
* @since 3.7.2 |
146
|
|
|
* @return string |
147
|
|
|
*/ |
148
|
|
|
private function _getTargetPageSlug( $aSection ) { |
149
|
|
|
|
150
|
|
|
$_sTargetPageSlug = $this->oUtil->getElement( |
151
|
|
|
$aSection, // subject |
152
|
|
|
'page_slug', // key |
153
|
|
|
$this->_sTargetPageSlug // default |
154
|
|
|
); |
155
|
|
|
|
156
|
|
|
$_sTargetPageSlug = $_sTargetPageSlug |
157
|
|
|
? $this->oUtil->sanitizeSlug( $_sTargetPageSlug ) |
158
|
|
|
: $this->oProp->getCurrentPageSlugIfAdded(); |
159
|
|
|
return $_sTargetPageSlug; |
160
|
|
|
|
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* Sets the target tab slug of the section. |
165
|
|
|
* If a tab slug is not set, set the currently loading one from the registered items. |
166
|
|
|
* Do not simply assign the currently loaded page but the one added by the user because the method can be called from anyware. |
167
|
|
|
* @return string |
168
|
|
|
* @since 3.7.2 |
169
|
|
|
*/ |
170
|
|
|
private function _getTargetTabSlug( $aSection ) { |
171
|
|
|
$_sTargetTabSlug = $this->oUtil->getElement( |
172
|
|
|
$aSection, // subject |
173
|
|
|
'tab_slug', // key |
174
|
|
|
$this->_sTargetTabSlug // default |
175
|
|
|
); |
176
|
|
|
$_sTargetTabSlug = $_sTargetTabSlug |
177
|
|
|
? $this->oUtil->sanitizeSlug( $aSection[ 'tab_slug' ] ) |
178
|
|
|
: $this->oProp->getCurrentInPageTabSlugIfAdded(); |
179
|
|
|
return $_sTargetTabSlug; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* Removes the given section(s) by section ID. |
184
|
|
|
* |
185
|
|
|
* This accesses the property storing the added section arrays and removes the specified ones. |
186
|
|
|
* |
187
|
|
|
* <h4>Example</h4> |
188
|
|
|
* <code>$this->removeSettingSections( 'text_fields', 'selectors', 'another_section', 'yet_another_section' ); |
189
|
|
|
* </code> |
190
|
|
|
* |
191
|
|
|
* @since 2.0.0 |
192
|
|
|
* @since 3.0.0 Changed the scope to public from protected. |
193
|
|
|
* @since 3.5.3 Removed the parameter declarations as they are caught with the func_get_args(). |
194
|
|
|
* @access public |
195
|
|
|
* @remark Accepts variadic parameters; the number of accepted parameters are not limited to three. |
196
|
|
|
* @param string $sSectionID1 the section ID to remove. |
197
|
|
|
* @param string $sSectionID2 (optional) another section ID to remove. |
198
|
|
|
* @param string $_and_more (optional) add more section IDs to the next parameters as many as necessary. |
199
|
|
|
* @return void |
200
|
|
|
*/ |
201
|
|
|
public function removeSettingSections( /* $sSectionID1=null, $sSectionID2=null, $_and_more=null */ ) { |
202
|
|
|
foreach( func_get_args() as $_sSectionID ) { |
203
|
|
|
$this->oForm->removeSection( $_sSectionID ); |
204
|
|
|
} |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* {@inheritdoc} |
209
|
|
|
* |
210
|
|
|
* {@inheritdoc} |
211
|
|
|
* |
212
|
|
|
* <h4>Example</h4> |
213
|
|
|
* <code>$this->addSettingFields( |
214
|
|
|
* array( |
215
|
|
|
* 'field_id' => 'text', |
216
|
|
|
* 'section_id' => 'text_fields', |
217
|
|
|
* 'title' => __( 'Text', 'my-text-domain' ), |
218
|
|
|
* 'description' => __( 'Type something here.', 'my-text-domain' ), |
219
|
|
|
* 'type' => 'text', |
220
|
|
|
* 'order' => 1, |
221
|
|
|
* 'default' => 123456, |
222
|
|
|
* ), |
223
|
|
|
* array( |
224
|
|
|
* 'field_id' => 'text_multiple', |
225
|
|
|
* 'section_id' => 'text_fields', |
226
|
|
|
* 'title' => __( 'Multiple Text Fields', 'my-text-domain' ), |
227
|
|
|
* 'description' => __( 'These are multiple text fields.', 'my-text-domain' ), |
228
|
|
|
* 'type' => 'text', |
229
|
|
|
* 'order' => 2, |
230
|
|
|
* 'default' => __( 'Hello World', 'my-text-domain' ), |
231
|
|
|
* 'label' => __( 'First Item', 'my-text-domain' ), |
232
|
|
|
* 'attributes' => array( |
233
|
|
|
* 'size' => 30 |
234
|
|
|
* ), |
235
|
|
|
* array( |
236
|
|
|
* 'label' => __( 'Second Item', 'my-text-domain' ), |
237
|
|
|
* 'default' => __( 'Foo bar', 'my-text-domain' ), |
238
|
|
|
* 'attributes' => array( |
239
|
|
|
* 'size' => 60, |
240
|
|
|
* ), |
241
|
|
|
* ), |
242
|
|
|
* array( |
243
|
|
|
* 'label' => __( 'Third Item', 'my-text-domain' ), |
244
|
|
|
* 'default' => __( 'Yes, we can.', 'my-text-domain' ), |
245
|
|
|
* 'attributes' => array( |
246
|
|
|
* 'size' => 90, |
247
|
|
|
* ), |
248
|
|
|
* ), |
249
|
|
|
* ) |
250
|
|
|
* );</code> |
251
|
|
|
* |
252
|
|
|
* @since 2.0.0 |
253
|
|
|
* @since 3.0.0 Changed the scope to public from protected. |
254
|
|
|
* @since 3.5.3 Removed the parameter declarations as they are caught with the func_get_args(). |
255
|
|
|
* @access public |
256
|
|
|
* @remark Accepts variadic parameters; the number of accepted parameters are not limited to three. |
257
|
|
|
* @remark The actual registration will be performed in the <em>_replyToRegisterSettings()</em> method with the <em>admin_menu</em> hook. |
258
|
|
|
*/ |
259
|
|
|
public function addSettingFields( /* $aField1, $aField2=null, $_and_more=null */ ) { |
260
|
|
|
foreach( func_get_args() as $aField ) { |
261
|
|
|
$this->addSettingField( $aField ); |
262
|
|
|
} |
263
|
|
|
} |
264
|
|
|
/** |
265
|
|
|
* Adds the given field array items into the field array property. |
266
|
|
|
* |
267
|
|
|
* Identical to the `addSettingFields()` method except that this method does not accept enumerated parameters. |
268
|
|
|
* |
269
|
|
|
* @since 2.1.2 |
270
|
|
|
* @since 3.0.0 Changed the scope to public from protected. |
271
|
|
|
* @access public |
272
|
|
|
* @param array|string $asField the field array or the target section ID. If the target section ID is set, the section_id key can be omitted from the next passing field array. |
273
|
|
|
* @return void |
274
|
|
|
*/ |
275
|
|
|
public function addSettingField( $asField ) { |
276
|
|
|
$this->oForm->addField( $asField ); |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
/** |
280
|
|
|
* Removes the given field(s) by field ID. |
281
|
|
|
* |
282
|
|
|
* This accesses the property storing the added field arrays and removes the specified ones. |
283
|
|
|
* |
284
|
|
|
* <h4>Example</h4> |
285
|
|
|
* <code>$this->removeSettingFields( 'fieldID_A', 'fieldID_B', 'fieldID_C', 'fieldID_D' ); |
286
|
|
|
* </code> |
287
|
|
|
* |
288
|
|
|
* @since 2.0.0 |
289
|
|
|
* @since 3.0.0 Changed the scope to public from protected. |
290
|
|
|
* @access public |
291
|
|
|
* @remark Accepts variadic parameters; the number of accepted parameters are not limited to three. |
292
|
|
|
* @param string $sFieldID1 the field ID to remove. |
293
|
|
|
* @param string $sFieldID2 (optional) another field ID to remove. |
294
|
|
|
* @param string $_and_more (optional) add more field IDs to the next parameters as many as necessary. |
295
|
|
|
* @return void |
296
|
|
|
*/ |
297
|
|
|
public function removeSettingFields( $sFieldID1, $sFieldID2=null, $_and_more=null ) { |
298
|
|
|
foreach( func_get_args() as $_sFieldID ) { |
299
|
|
|
$this->oForm->removeField( $_sFieldID ); |
300
|
|
|
} |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
/** |
304
|
|
|
* Retrieves the specified field value stored in the options by field ID. |
305
|
|
|
* |
306
|
|
|
* <h4>Example</h4> |
307
|
|
|
* <code> |
308
|
|
|
* $this->addSettingFields( |
309
|
|
|
* 'number_section', // section id |
310
|
|
|
* array( |
311
|
|
|
* 'field_id' => 'preset_field', |
312
|
|
|
* 'title' => __( 'Preset', 'admin-page-framework-demo' ), |
313
|
|
|
* 'type' => 'number', |
314
|
|
|
* ), |
315
|
|
|
* array( |
316
|
|
|
* 'field_id' => 'value_based_on_preset', |
317
|
|
|
* 'title' => __( 'Value Based on Preset', 'admin-page-framework-demo' ), |
318
|
|
|
* 'type' => 'number', |
319
|
|
|
* 'default' => 10 + ( int ) $this->getValue( |
320
|
|
|
* 'number_section', // section id |
321
|
|
|
* 'preset_field' // field id |
322
|
|
|
* ), |
323
|
|
|
* ), |
324
|
|
|
* ); |
325
|
|
|
* </code> |
326
|
|
|
* |
327
|
|
|
* @since 3.3.0 |
328
|
|
|
* @since 3.3.5 Made it respect last input arrays. |
329
|
|
|
* @since 3.5.3 When a parameter is not set, it returns the entire options. |
330
|
|
|
* @param The key that points the dimensional array key of the options array. |
|
|
|
|
331
|
|
|
*/ |
332
|
|
|
public function getValue( /* $sDimensionalKey1, $sDimensionalKey2 ... or $aDimensionalKeys, $mDefault */ ) { |
333
|
|
|
|
334
|
|
|
$_aParams = func_get_args(); |
335
|
|
|
$_aDimensionalKeys = $_aParams + array( null, null ); |
336
|
|
|
$_mDefault = null; |
337
|
|
|
if ( is_array( $_aDimensionalKeys[ 0 ] ) ) { |
338
|
|
|
$_mDefault = $_aDimensionalKeys[ 1 ]; |
339
|
|
|
$_aDimensionalKeys = $_aDimensionalKeys[ 0 ]; |
340
|
|
|
} |
341
|
|
|
return AdminPageFramework_WPUtility::getOption( |
342
|
|
|
$this->oProp->sOptionKey, |
343
|
|
|
empty( $_aParams ) |
344
|
|
|
? null // will return the entire options array |
345
|
|
|
: $_aDimensionalKeys, // dimensional keys |
346
|
|
|
$_mDefault, // default |
347
|
|
|
$this->getSavedOptions() + $this->oForm->getDefaultFormValues() |
|
|
|
|
348
|
|
|
); |
349
|
|
|
|
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
/** |
353
|
|
|
* Retrieves the specified field value stored in the options by field ID. |
354
|
|
|
* |
355
|
|
|
* @since 2.1.2 |
356
|
|
|
* @since 3.0.0 Changed the scope to public from protected. Dropped the sections. Made it return a default value even if it's not saved in the database. |
357
|
|
|
* @access public |
358
|
|
|
* @param string $sFieldID The field ID. |
359
|
|
|
* @param string $sSectionID The section ID. |
360
|
|
|
* @return array|string|null If the field ID is not set in the saved option array, it will return null. Otherwise, the set value. |
361
|
|
|
* If the user has not submitted the form, the framework will try to return the default value set in the field definition array. |
362
|
|
|
* @deprecated 3.3.0 |
363
|
|
|
*/ |
364
|
|
|
public function getFieldValue( $sFieldID, $sSectionID='' ) { |
365
|
|
|
|
366
|
|
|
$this->oUtil->showDeprecationNotice( |
367
|
|
|
'The method,' . __METHOD__ . ',', // deprecated item |
368
|
|
|
'getValue()' // alternative |
369
|
|
|
); |
370
|
|
|
|
371
|
|
|
$_aOptions = $this->oUtil->uniteArrays( $this->oProp->aOptions, $this->oForm->getDefaultFormValues() ); |
372
|
|
|
/* If it's saved, return it */ |
373
|
|
|
if ( ! $sSectionID ) { |
374
|
|
|
if ( array_key_exists( $sFieldID, $_aOptions ) ) { |
375
|
|
|
return $_aOptions[ $sFieldID ]; |
376
|
|
|
} |
377
|
|
|
// loop through section elements |
378
|
|
|
foreach( $_aOptions as $aOptions ) { |
379
|
|
|
if ( array_key_exists( $sFieldID, $aOptions ) ) { |
380
|
|
|
return $aOptions[ $sFieldID ]; |
381
|
|
|
} |
382
|
|
|
} |
383
|
|
|
} |
384
|
|
|
if ( $sSectionID ) { |
385
|
|
|
if ( array_key_exists( $sSectionID, $_aOptions ) && array_key_exists( $sFieldID, $_aOptions[ $sSectionID ] ) ) { |
386
|
|
|
return $_aOptions[ $sSectionID ][ $sFieldID ]; |
387
|
|
|
} |
388
|
|
|
} |
389
|
|
|
return null; |
390
|
|
|
|
391
|
|
|
} |
392
|
|
|
|
393
|
|
|
} |
394
|
|
|
|
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths