Total Complexity | 44 |
Total Lines | 424 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like AdminPageFramework_FieldType_Base often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use AdminPageFramework_FieldType_Base, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
19 | abstract class AdminPageFramework_FieldType_Base extends AdminPageFramework_Form_Utility { |
||
20 | |||
21 | /** |
||
22 | * Stores the field set type indicating what this field is for such as for meta boxes, taxonomy fields or page fields. |
||
23 | * @remark This will be automatically set when head tag elements are enqueued. |
||
24 | * @since 3.0.0 |
||
25 | * @internal |
||
26 | */ |
||
27 | public $_sFieldSetType = ''; |
||
28 | |||
29 | /** |
||
30 | * Defines the slugs used for this field type. |
||
31 | * |
||
32 | * This should be overridden in the extended class. |
||
33 | * |
||
34 | * @access public This must be public as accessed from outside. |
||
35 | */ |
||
36 | public $aFieldTypeSlugs = array( 'default' ); |
||
37 | |||
38 | /** |
||
39 | * Defines the default key-values of the extended field type. |
||
40 | * This should be overridden in the extended class. |
||
41 | */ |
||
42 | protected $aDefaultKeys = array(); |
||
43 | |||
44 | /** |
||
45 | * Defines the default key-values of all field types. |
||
46 | * |
||
47 | * @internal |
||
48 | */ |
||
49 | protected static $_aDefaultKeys = array( |
||
50 | 'value' => null, // ( array or string ) this suppresses the default key value. This is useful to display the value saved in a custom place other than the framework automatically saves. |
||
51 | 'default' => null, // ( array or string ) |
||
52 | 'repeatable' => false, |
||
53 | 'sortable' => false, |
||
54 | 'label' => '', // ( string ) labels for some input fields. Do not set null here because it is casted as string in the field output methods, which creates an element of empty string so that it can be iterated with foreach(). |
||
55 | 'delimiter' => '', |
||
56 | 'before_input' => '', |
||
57 | 'after_input' => '', |
||
58 | 'before_label' => null, |
||
59 | 'after_label' => null, |
||
60 | 'before_field' => null, |
||
61 | 'after_field' => null, |
||
62 | 'label_min_width' => '', // (string|integer) min-width applied to the input label in pixels. 3.8.0+ Changed the default value from 140 to 0 as it is now applied via embedded CSS. When this value is set by the user, it is set inline and the value will be overridden. [3.8.4+] Changed the value from `0` to `''`. |
||
63 | 'before_fieldset' => null, // 3.1.1+ |
||
64 | 'after_fieldset' => null, // 3.1.1+ |
||
65 | |||
66 | /* Mandatory keys */ |
||
67 | 'field_id' => null, |
||
68 | |||
69 | /* For the meta box class - it does not require the following keys; these are just to help to avoid undefined index warnings. */ |
||
70 | 'page_slug' => null, |
||
71 | 'section_id' => null, |
||
72 | 'before_fields' => null, |
||
73 | 'after_fields' => null, |
||
74 | |||
75 | 'attributes' => array( |
||
76 | /* Root Attributes - the root attributes are assumed to be for the input tag. */ |
||
77 | 'disabled' => null, // set 'Disabled' or an empty value '' to make it disabled. Null will not set the attribute. |
||
78 | 'class' => '', |
||
79 | |||
80 | /* Component Attributes */ |
||
81 | 'fieldrow' => array(), // attributes applied to the field group container row tag that holds all the field components including descriptions and scripts and the title. |
||
82 | 'fieldset' => array(), // attributes applied to the field group container tag that holds all the field components including descriptions and scripts. |
||
83 | 'fields' => array(), // attributes applied to the fields container tag that holds all sub-fields. |
||
84 | 'field' => array(), // attributes applied to each field container tag. |
||
85 | ), |
||
86 | ); |
||
87 | |||
88 | protected $oMsg; |
||
89 | |||
90 | /** |
||
91 | * Sets up hooks and properties. |
||
92 | * |
||
93 | * @internal |
||
94 | * @since 2.1.5 |
||
95 | * @since 3.5.0 'admin_page_framework' can be passed to register the field type site-wide. |
||
96 | * @param string|array $asClassName The instantiated class name that uses the field type(s). To enable it site-wide, pass `admin_page_framework`. |
||
97 | * This value will be used to the `field_types_{instantiated class name}` filter to set field definition callbacks. |
||
98 | * @param string|array $asFieldTypeSlug The field type slugs. To have multiple slugs for one definition, pass an array holding the slugs. |
||
99 | * @param object $oMsg The framework message object. |
||
100 | * @param boolean $bAutoRegister Whether or not to register the field type(s). |
||
101 | */ |
||
102 | public function __construct( $asClassName='admin_page_framework', $asFieldTypeSlug=null, $oMsg=null, $bAutoRegister=true ) { |
||
103 | |||
104 | $this->aFieldTypeSlugs = empty( $asFieldTypeSlug ) |
||
105 | ? $this->aFieldTypeSlugs |
||
106 | : ( array ) $asFieldTypeSlug; |
||
107 | $this->oMsg = $oMsg |
||
108 | ? $oMsg |
||
109 | : AdminPageFramework_Message::getInstance(); |
||
110 | |||
111 | // This automatically registers the field type. The build-in ones will be registered manually so it will be skipped. |
||
112 | if ( $bAutoRegister ) { |
||
113 | foreach( ( array ) $asClassName as $_sClassName ) { |
||
114 | add_filter( |
||
115 | 'field_types_' . $_sClassName, |
||
116 | array( $this, '_replyToRegisterInputFieldType' ) |
||
117 | ); |
||
118 | } |
||
119 | } |
||
120 | |||
121 | // User constructor |
||
122 | $this->construct(); |
||
123 | |||
124 | } |
||
125 | |||
126 | /** |
||
127 | * The user constructor. |
||
128 | * |
||
129 | * When the user defines a field type, they may use this instead of the real constructor |
||
130 | * so that they don't have to care about the internal parameters. |
||
131 | * |
||
132 | * @since 3.1.3 |
||
133 | */ |
||
134 | protected function construct() {} |
||
135 | |||
136 | /** |
||
137 | * Checks whether TinyMCE is supported. |
||
138 | * @since 3.5.8 |
||
139 | * @return boolean |
||
140 | */ |
||
141 | protected function isTinyMCESupported() { |
||
142 | return version_compare( $GLOBALS[ 'wp_version' ], '3.3', '>=' ) |
||
143 | && function_exists( 'wp_editor' ) |
||
144 | ; |
||
145 | } |
||
146 | |||
147 | /** |
||
148 | * Returns the sub-element of a given element by the element key. |
||
149 | * |
||
150 | * @remark Used by the `text`, `textarea`, `size`, 'radio', and `checkbox` field types. |
||
151 | * @since 3.5.8 |
||
152 | * @since 3.7.0 Changed the third parameter to accept a label argument from a boolean value to be usable for other filed types. |
||
153 | * @param array|string $asElement |
||
154 | * @param array|string $asKey |
||
155 | * @param array|string $asLabel |
||
156 | * @return string |
||
157 | */ |
||
158 | protected function getElementByLabel( $asElement, $asKey, $asLabel ) { |
||
159 | if ( is_scalar( $asElement ) ) { |
||
160 | return $asElement; |
||
161 | } |
||
162 | return is_array( $asLabel ) // if the user sets multiple items |
||
|
|||
163 | ? $this->getElement( |
||
164 | $asElement, // subject |
||
165 | $this->getAsArray( $asKey, true /* preserve empty */ ), // dimensional path |
||
166 | '' // default - if the element is not found, return an empty |
||
167 | ) |
||
168 | : $asElement; |
||
169 | } |
||
170 | |||
171 | /** |
||
172 | * Returns another field output by the given field definition array. |
||
173 | * |
||
174 | * This is used to create nested fields or dynamically create a different type of field. |
||
175 | * @since 3.4.0 |
||
176 | * @param array $aFieldset |
||
177 | * @return string The fieldset output. |
||
178 | */ |
||
179 | protected function getFieldOutput( array $aFieldset ) { |
||
180 | |||
181 | if ( ! is_object( $aFieldset[ '_caller_object' ] ) ) { |
||
182 | return ''; |
||
183 | } |
||
184 | |||
185 | $aFieldset[ '_nested_depth' ]++; |
||
186 | $aFieldset[ '_parent_field_object' ] = $aFieldset[ '_field_object' ]; // 3.6.0+ |
||
187 | |||
188 | // 3.7.0+ The caller object is no longer a factory object but a form object. |
||
189 | $_oCallerForm = $aFieldset[ '_caller_object' ]; |
||
190 | |||
191 | $_oFieldset = new AdminPageFramework_Form_View___Fieldset( |
||
192 | $aFieldset, // the field definition array |
||
193 | $_oCallerForm->aSavedData, // the stored form data |
||
194 | $_oCallerForm->getFieldErrors(), // the field error array. |
||
195 | $_oCallerForm->aFieldTypeDefinitions, // the field type definition array. |
||
196 | $_oCallerForm->oMsg, // the system message object |
||
197 | $_oCallerForm->aCallbacks // field output element callables. |
||
198 | ); |
||
199 | return $_oFieldset->get(); |
||
200 | |||
201 | } |
||
202 | /** |
||
203 | * @deprecated Kept for backward compatibility. |
||
204 | * @param array $aFieldset |
||
205 | * @return string |
||
206 | */ |
||
207 | protected function geFieldOutput( array $aFieldset ) { |
||
208 | return $this->getFieldOutput( $aFieldset ); |
||
209 | } |
||
210 | |||
211 | /** |
||
212 | * Registers the field type. |
||
213 | * |
||
214 | * @since 2.1.5 |
||
215 | * @callback filter field_types_{class name} |
||
216 | * @callback filter field_types_admin_page_framework |
||
217 | * @return array |
||
218 | * @internal |
||
219 | */ |
||
220 | public function _replyToRegisterInputFieldType( $aFieldDefinitions ) { |
||
221 | |||
222 | foreach ( $this->aFieldTypeSlugs as $sFieldTypeSlug ) { |
||
223 | $aFieldDefinitions[ $sFieldTypeSlug ] = $this->getDefinitionArray( $sFieldTypeSlug ); |
||
224 | } |
||
225 | return $aFieldDefinitions; |
||
226 | |||
227 | } |
||
228 | |||
229 | /** |
||
230 | * Returns the field type definition array. |
||
231 | * |
||
232 | * @remark The scope is public since AdminPageFramework_FieldType class allows the user to use this method. |
||
233 | * @since 2.1.5 |
||
234 | * @since 3.0.0 Added the $sFieldTypeSlug parameter. |
||
235 | * @since 3.0.3 Tweaked it to have better execution speed. |
||
236 | * @param string $sFieldTypeSlug |
||
237 | * @return array |
||
238 | * @internal |
||
239 | */ |
||
240 | public function getDefinitionArray( $sFieldTypeSlug='' ) { |
||
241 | |||
242 | // The uniteArrays() method resulted in somewhat being slow due to overhead on checking array keys for recursive array merges. |
||
243 | $_aDefaultKeys = $this->aDefaultKeys + self::$_aDefaultKeys; |
||
244 | $_aDefaultKeys['attributes'] = isset( $this->aDefaultKeys['attributes'] ) && is_array( $this->aDefaultKeys['attributes'] ) |
||
245 | ? $this->aDefaultKeys['attributes'] + self::$_aDefaultKeys['attributes'] |
||
246 | : self::$_aDefaultKeys['attributes']; |
||
247 | |||
248 | return array( |
||
249 | 'sFieldTypeSlug' => $sFieldTypeSlug, |
||
250 | 'aFieldTypeSlugs' => $this->aFieldTypeSlugs, |
||
251 | 'hfRenderField' => array( $this, "_replyToGetField" ), |
||
252 | 'hfGetScripts' => array( $this, "_replyToGetScripts" ), |
||
253 | 'hfGetStyles' => array( $this, "_replyToGetStyles" ), |
||
254 | 'hfGetIEStyles' => array( $this, "_replyToGetInputIEStyles" ), |
||
255 | 'hfFieldLoader' => array( $this, "_replyToFieldLoader" ), |
||
256 | 'hfFieldSetTypeSetter' => array( $this, "_replyToFieldTypeSetter" ), |
||
257 | 'hfDoOnRegistration' => array( $this, "_replyToDoOnFieldRegistration" ), // 3.5.0+ |
||
258 | 'aEnqueueScripts' => $this->_replyToGetEnqueuingScripts(), // urls of the scripts |
||
259 | 'aEnqueueStyles' => $this->_replyToGetEnqueuingStyles(), // urls of the styles |
||
260 | 'aDefaultKeys' => $_aDefaultKeys, |
||
261 | ); |
||
262 | |||
263 | } |
||
264 | |||
265 | /* |
||
266 | * These methods should be overridden in the extended class. |
||
267 | */ |
||
268 | /** |
||
269 | * @internal |
||
270 | * @param array $aField |
||
271 | * @return string |
||
272 | */ |
||
273 | public function _replyToGetField( $aField ) { return ''; } // should return the field output |
||
274 | /**#@+ |
||
275 | * @internal |
||
276 | * @return string |
||
277 | */ |
||
278 | public function _replyToGetScripts() { return ''; } // should return the script |
||
279 | public function _replyToGetInputIEStyles() { return ''; } // should return the style for IE |
||
280 | public function _replyToGetStyles() { return ''; } // should return the style |
||
281 | /**#@-*/ |
||
282 | public function _replyToFieldLoader() {} // do stuff that should be done when the field type is loaded for the first time. |
||
283 | |||
284 | /** |
||
285 | * Sets the field set type. |
||
286 | * |
||
287 | * Called when enqueuing the field type's head tag elements. |
||
288 | * @since 3.0.0 |
||
289 | * @param string $sFieldSetType |
||
290 | * @internal |
||
291 | */ |
||
292 | public function _replyToFieldTypeSetter( $sFieldSetType='' ) { |
||
293 | $this->_sFieldSetType = $sFieldSetType; |
||
294 | } |
||
295 | |||
296 | /** |
||
297 | * Called when the given field of this field type is registered. |
||
298 | * |
||
299 | * @since 3.5.0 |
||
300 | * @param array $aField |
||
301 | * @internal |
||
302 | */ |
||
303 | public function _replyToDoOnFieldRegistration( $aField ) {} |
||
304 | |||
305 | /** |
||
306 | * |
||
307 | * @return array e.g. each element can hold a sting of the source url: array( 'http://..../my_script.js', 'http://..../my_script2.js' ) |
||
308 | * Optionally, an option array can be passed to specify dependencies etc. |
||
309 | * array( array( 'src' => 'http://...my_script1.js', 'dependencies' => array( 'jquery' ) ), 'http://.../my_script2.js' ) |
||
310 | * @internal |
||
311 | */ |
||
312 | protected function _replyToGetEnqueuingScripts() { return array(); } // should return an array holding the urls of enqueuing items |
||
313 | |||
314 | /** |
||
315 | * @return array e.g. each element can hold a sting of the source url: array( 'http://..../my_style.css', 'http://..../my_style2.css' ) |
||
316 | * Optionally, an option array can be passed to specify dependencies etc. |
||
317 | * array( array( 'src' => 'http://...my_style1.css', 'dependencies' => array( 'jquery' ) ), 'http://.../my_style2.css' ) |
||
318 | * @internal |
||
319 | */ |
||
320 | protected function _replyToGetEnqueuingStyles() { return array(); } // should return an array holding the urls of enqueuing items |
||
321 | |||
322 | /* |
||
323 | * Shared methods |
||
324 | */ |
||
325 | |||
326 | /** |
||
327 | * Enqueues scripts for the media uploader. |
||
328 | * |
||
329 | * @remark Used by the image and the media field types. |
||
330 | * @internal |
||
331 | */ |
||
332 | protected function enqueueMediaUploader() { |
||
333 | |||
334 | add_filter( 'media_upload_tabs', array( $this, '_replyToRemovingMediaLibraryTab' ) ); |
||
335 | |||
336 | wp_enqueue_script( 'jquery' ); |
||
337 | wp_enqueue_script( 'thickbox' ); |
||
338 | wp_enqueue_style( 'thickbox' ); |
||
339 | |||
340 | // If the WordPress version is 3.5 or above, |
||
341 | if ( function_exists( 'wp_enqueue_media' ) ) { |
||
342 | add_action( is_admin() ? 'admin_footer' : 'wp_footer', array( $this, 'replyToEnqueueScriptsForMediaUpload' ), 1 ); |
||
343 | } else { |
||
344 | wp_enqueue_script( 'media-upload' ); |
||
345 | } |
||
346 | |||
347 | if ( in_array( $this->getPageNow(), array( 'media-upload.php', 'async-upload.php', ) ) ) { |
||
348 | add_filter( 'gettext', array( $this, '_replyToReplaceThickBoxText' ) , 1, 2 ); |
||
349 | } |
||
350 | |||
351 | } |
||
352 | /** |
||
353 | * Enqueues scripts for media upload. |
||
354 | * These must be done after the `admin-page-framework-script-form-media-uploader` script is registered. |
||
355 | * The `enqueueMediaUploader()` method maybe called earlier than that, so do it in the footer action hook. |
||
356 | * @since 3.9.0 |
||
357 | * @callback action wp_footer|admin_footer |
||
358 | */ |
||
359 | public function replyToEnqueueScriptsForMediaUpload() { |
||
360 | wp_enqueue_media(); |
||
361 | wp_enqueue_script( 'admin-page-framework-script-form-media-uploader' ); |
||
362 | } |
||
363 | |||
364 | /** |
||
365 | * Replaces the label text of a button used in the media uploader. |
||
366 | * |
||
367 | * @internal |
||
368 | * @since 2.0.0 |
||
369 | * @param string $sTranslated |
||
370 | * @param string $sText |
||
371 | * @return string |
||
372 | * @callback add_filter() gettext |
||
373 | */ |
||
374 | public function _replyToReplaceThickBoxText( $sTranslated, $sText ) { |
||
392 | // @deprecated 3.8.32 Accessing an unreferenced property |
||
393 | // return $this->oProp->sThickBoxButtonUseThis |
||
394 | // ? $this->oProp->sThickBoxButtonUseThis |
||
395 | // : $this->oMsg->get( 'use_this_image' ); |
||
396 | |||
397 | } |
||
398 | /** |
||
399 | * Removes the From URL tab from the media uploader. |
||
400 | * |
||
401 | * @internal |
||
402 | * @since 2.1.3 |
||
403 | * @since 2.1.5 Moved from AdminPageFramework_Setting. Changed the name from removeMediaLibraryTab() to _replyToRemovingMediaLibraryTab(). |
||
404 | * @callback add_filter() media_upload_tabs |
||
405 | * @param array $aTabs |
||
406 | * @return array |
||
407 | */ |
||
408 | public function _replyToRemovingMediaLibraryTab( $aTabs ) { |
||
417 | |||
418 | } |
||
419 | |||
420 | /** |
||
421 | * Generates HTML attributes of label containers. |
||
422 | * |
||
423 | * This is used for element that `label_min_width` is applied. |
||
424 | * |
||
425 | * @param array $aField |
||
426 | * @param array|string $asClassAttributes |
||
427 | * @param array $aAttributes |
||
428 | * @return string |
||
429 | * @since 3.8.0 |
||
430 | */ |
||
431 | protected function getLabelContainerAttributes( $aField, $asClassAttributes, array $aAttributes=array() ) { |
||
443 | |||
444 | } |
||
445 | |||
446 | } |