1 <?php
2 /**
3 * Admin Page Framework
4 *
5 * http://en.michaeluno.jp/admin-page-framework/
6 * Copyright (c) 2013-2014 Michael Uno; Licensed MIT
7 *
8 */
9 if ( ! class_exists( 'AdminPageFramework' ) ) :
10 /**
11 * The main class of the framework to create admin pages and forms.
12 *
13 * This class should be extended and the setUp() method should be overridden to define how pages are composed.
14 * Most of the internal methods are prefixed with the underscore like <code>_getSomething()</code> and callback methods are prefixed with <code>_reply</code>.
15 * The methods for the users are public and do not have those prefixes.
16 *
17 * <h2>Hooks</h2>
18 * <p>The class automatically creates WordPress action and filter hooks associated with the class methods.
19 * The class methods corresponding to the name of the below actions and filters can be extended to modify the page output. Those methods are the callbacks of the filters and the actions.</p>
20 * <h3>Methods and Action Hooks</h3>
21 * <ul>
22 * <li><strong>start_{instantiated class name}</strong> – triggered at the end of the class constructor. This will be triggered in any admin page except admin-ajax.php. The class object will be passed to the first parameter [3.1.3+].</li>
23 * <li><strong>set_up_{instantiated class name}</strong> – [3.1.3+] triggered after the setUp() method is called. The class object will be passed to the first parameter.</li>
24 * <li><strong>load_{instantiated class name}</strong> – [2.1.0+] triggered when the framework's page is loaded before the header gets sent. This will not be triggered in the admin pages that are not registered by the framework. The first parameter: class object [3.1.2+].</li>
25 * <li><strong>load_{page slug}</strong> – [2.1.0+] triggered when the framework's page is loaded before the header gets sent. This will not be triggered in the admin pages that are not registered by the framework. The first parameter: class object [3.1.2+].</li>
26 * <li><strong>load_{page slug}_{tab slug}</strong> – [2.1.0+] triggered when the framework's page is loaded before the header gets sent. This will not be triggered in the admin pages that are not registered by the framework. The first parameter: class object [3.1.2+].</li>
27 * <li><strong>load_after_{instantiated class name}</strong> – [3.1.3+] triggered when one of the framework's pages is loaded before the header gets sent. This will not be triggered in the admin pages that are not registered by the framework. The first parameter: class object.</li>
28 * <li><strong>do_before_{instantiated class name}</strong> – triggered before rendering the page. It applies to all the pages created by the instantiated class object. The class object will be passed to the first parameter [3.1.3+].</li>
29 * <li><strong>do_before_{page slug}</strong> – triggered before rendering the page. The class object will be passed to the first parameter [3.1.3+].</li>
30 * <li><strong>do_before_{page slug}_{tab slug}</strong> – triggered before rendering the page. The class object will be passed to the first parameter [3.1.3+].</li>
31 * <li><strong>do_form_{instantiated class name}</strong> – triggered right after the form opening tag. It applies to all the pages created by the instantiated class object. The class object will be passed to the first parameter [3.1.3+].</li>
32 * <li><strong>do_form_{page slug}</strong> – triggered right after the form opening tag. The class object will be passed to the first parameter [3.1.3+].</li>
33 * <li><strong>do_form_{page slug}_{tab slug}</strong> – triggered right after the form opening tag. The class object will be passed to the first parameter [3.1.3+].</li>
34 * <li><strong>do_{instantiated class name}</strong> – triggered in the middle of rendering the page. It applies to all the pages created by the instantiated class object. The class object will be passed to the first parameter [3.1.3+].</li>
35 * <li><strong>do_{page slug}</strong> – triggered in the middle of rendering the page. The class object will be passed to the first parameter [3.1.3+].</li>
36 * <li><strong>do_{page slug}_{tab slug}</strong> – triggered in the middle of rendering the page. The class object will be passed to the first parameter [3.1.3+].</li>
37 * <li><strong>do_after_{instantiated class name}</strong> – triggered after rendering the page. It applies to all the pages created by the instantiated class object. The class object will be passed to the first parameter [3.1.3+].</li>
38 * <li><strong>do_after_{page slug}</strong> – triggered after rendering the page. The class object will be passed to the first parameter [3.1.3+].</li>
39 * <li><strong>do_after_{page slug}_{tab slug}</strong> – triggered after rendering the page. The class object will be passed to the first parameter [3.1.3+].</li>
40 * <li><strong>submit_{instantiated class name}_{submit input id}</strong> – [3.0.0+] triggered after the form is submitted with the submit button of the specified input id.</li>
41 * <li><strong>submit_{instantiated class name}_{submit field id}</strong> – [3.0.0+] triggered after the form is submitted with the submit button of the specified field that does not hava section is submitted.</li>
42 * <li><strong>submit_{instantiated class name}_{submit section id}_{submit field id}</strong> – [3.0.0+] triggered after the form is submitted with the submit button of the specified section and field is submitted.</li>
43 * <li><strong>submit_{instantiated class name}_{submit section id}</strong> – [3.0.0+] triggered after the form is submitted with the submit button of the specified section.</li>
44 * <li><strong>submit_{instantiated class name}</strong> – [3.0.0+] triggered after the form is submitted.</li>
45 * </ul>
46 * <h3>Methods and Filter Hooks</h3>
47 * <ul>
48 * <li><strong>content_foot_{page slug}_{tab slug}</strong> – receives the output of the top part of the page. [3.0.0+] Changed the name from head_{...}.</li>
49 * <li><strong>content_foot_{page slug}</strong> – receives the output of the top part of the page. [3.0.0+] Changed the name from head_{...}.</li>
50 * <li><strong>content_foot_{instantiated class name}</strong> – receives the output of the top part of the page, applied to all pages created by the instantiated class object. [3.0.0+] Changed the name from head_{...}.</li>
51 * <li><strong>content_{page slug}_{tab slug}</strong> – receives the output of the middle part of the page including form input fields.</li>
52 * <li><strong>content_{page slug}</strong> – receives the output of the middle part of the page including form input fields.</li>
53 * <li><strong>content_{instantiated class name}</strong> – receives the output of the middle part of the page, applied to all pages created by the instantiated class object.</li>
54 * <li><strong>content_bottom_{page slug}_{tab slug}</strong> – receives the output of the bottom part of the page. [3.0.0+] Changed the name from foot_{...}.</li>
55 * <li><strong>content_bottom_{page slug}</strong> – receives the output of the bottom part of the page. [3.0.0+] Changed the name from foot_{...}.</li>
56 * <li><strong>content_bottom_{instantiated class name}</strong> – receives the output of the bottom part of the page, applied to all pages created by the instantiated class object. [3.0.0+] Changed the name from foot_{...}.</li>
57 * <li><strong>section_head_{instantiated class name}_{section ID}</strong> – receives the title and the description output of the given form section ID. The first parameter: the output string.</li>
58 * <li><strong>field_{instantiated class name}_{field ID}</strong> – receives the form input field output of the given input field ID that does not have a section. The first parameter: output string. The second parameter: the array of option.</li>
59 * <li><strong>field_{instantiated class name}_{section id}_{field ID}</strong> – [3.0.0+] receives the form input field output of the given input field ID that has a section. The first parameter: output string. The second parameter: the array of option.</li>
60 * <li><strong>sections_{instantiated class name}</strong> – receives the registered section arrays. The first parameter: sections container array.</li>
61 * <li><strong>fields_{instantiated class name}</strong> – receives the registered field arrays. The first parameter: fields container array.</li>
62 * <li><strong>fields_{instantiated class name}_{section id}</strong> – [3.0.0+] receives the registered field arrays which belong to the specified section. The first parameter: fields container array.</li>
63 * <li><strong>field_definition_{instantiated class name}_{field ID}</strong> – [3.0.2+] receives the form field definition array of the given input field ID that does not have a section. The first parameter: the field definition array.</li>
64 * <li><strong>field_definition_{instantiated class name}_{section id}_{field ID}</strong> – [3.0.2+] receives the form field definition array of the given input field ID that has a section. The first parameter: the field definition array. The second parameter: the integer representing sub-section index if the field belongs to a sub-section.</li>
65 * <li><strong>pages_{instantiated class name}</strong> – receives the registered page arrays. The first parameter: pages container array.</li>
66 * <li><strong>tabs_{instantiated class name}_{page slug}</strong> – receives the registered in-page tab arrays. The first parameter: tabs container array.</li>
67 * <li><strong>validation_{instantiated class name}_{field id}</strong> – [3.0.0+] receives the form submission value of the field that does not have a section. The first parameter: ( string|array ) submitted input value. The second parameter: ( string|array ) the old value stored in the database. The third parameter: ( object ) [3.1.0+] the caller object.</li>
68 * <li><strong>validation_{instantiated class name}_{section_id}_{field id}</strong> – [3.0.0+] receives the form submission value of the field that has a section. The first parameter: ( string|array ) submitted input value. The second parameter: ( string|array ) the old value stored in the database. The third parameter: ( object ) [3.1.0+] the caller object.</li>
69 * <li><strong>validation_{instantiated class name}_{section id}</strong> – [3.0.0+] receives the form submission values that belongs to the section.. The first parameter: ( array ) the array of submitted input values that belong to the section. The second parameter: ( array ) the array of the old values stored in the database. The third parameter: ( object ) [3.1.0+] the caller object.</li>
70 * <li><strong>validation_{page slug}_{tab slug}</strong> – receives the form submission values as array. The first parameter: submitted input array. The second parameter: the original array stored in the database. The third parameter: ( object ) [3.1.0+] the caller object.</li>
71 * <li><strong>validation_{page slug}</strong> – receives the form submission values as array. The first parameter: submitted input array. The second parameter: the original array stored in the database. The third parameter: ( object ) [3.1.0+] the caller object.</li>
72 * <li><strong>validation_{instantiated class name}</strong> – receives the form submission values as array. The first parameter: submitted input array. The second parameter: the original array stored in the database. The third parameter: ( object ) [3.1.0+] the caller object.</li>
73 * <li><strong>validation_saved_options_{instantiated class name}</strong> – [3.1.2+] receives the saved form options as an array. The first parameter: the stored options array. The second parameter: the caller object.</li>
74 * <li><strong>validation_saved_options_{page slug}</strong> – [3.0.0+] receives the saved form options as an array of the page. The first parameter: the stored options array of the page. The second parameter: the caller object.</li>
75 * <li><strong>validation_saved_options_{page slug}_{tab slug}</strong> – [3.0.0+] receives the saved form options as an array of the tab. The first parameter: the stored options array of the tab. The second parameter: the caller object.</li>
76 * <li><strong>style_{page slug}_{tab slug}</strong> – receives the output of the CSS rules applied to the tab page of the slug.</li>
77 * <li><strong>style_{page slug}</strong> – receives the output of the CSS rules applied to the page of the slug.</li>
78 * <li><strong>style_{instantiated class name}</strong> – receives the output of the CSS rules applied to the pages added by the instantiated class object.</li>
79 * <li><strong>script_{page slug}_{tab slug}</strong> – receives the output of the JavaScript script applied to the tab page of the slug.</li>
80 * <li><strong>script_{page slug}</strong> – receives the output of the JavaScript script applied to the page of the slug.</li>
81 * <li><strong>script_{instantiated class name}</strong> – receives the output of the JavaScript script applied to the pages added by the instantiated class object.</li>
82 * <li><strong>export_{instantiated class name}_{input id}</strong> – [2.1.5+] receives the exporting array submitted from the specific export button.</li>
83 * <li><strong>export_{instantiated class name}_{field id}</strong> – [2.1.5+] receives the exporting array submitted from the specific field that does not have a section.</li>
84 * <li><strong>export_{instantiated class name}_{section id}_{field id}</strong> – [3.0.0+] receives the exporting array submitted from the specific field that has a section.</li>
85 * <li><strong>export_{page slug}_{tab slug}</strong> – receives the exporting array sent from the tab page.</li>
86 * <li><strong>export_{page slug}</strong> – receives the exporting array submitted from the page.</li>
87 * <li><strong>export_{instantiated class name}</strong> – receives the exporting array submitted from the plugin.</li>
88 * <li><strong>export_name_{instantiated class name}_{input id}</strong> – receives the exporting file name submitted the specified input id.</li>
89 * <li><strong>export_name_{instantiated class name}_{field id}</strong> – receives the exporting file name submitted from the specific field that does not have a section.</li>
90 * <li><strong>export_name_{instantiated class name}_{section id}_{field id}</strong> – [3.0.0+] receives the exporting file name submitted from the specific field that has a section.</li>
91 * <li><strong>export_name_{page slug}_{tab slug}</strong> – receives the exporting file name submitted from the tab page.</li>
92 * <li><strong>export_name_{page slug}</strong> – receives the exporting file name submitted from the page.</li>
93 * <li><strong>export_name_{instantiated class name}</strong> – receives the exporting file name submitted from the script.</li>
94 * <li><strong>export_format_{instantiated class name}_{input id}</strong> – receives the exporting file format submitted from the specific export button.</li>
95 * <li><strong>export_format_{instantiated class name}_{field id}</strong> – receives the exporting file format submitted from the specific field that does not have a section.</li>
96 * <li><strong>export_format_{instantiated class name}_{section id}_{field id}</strong> – [3.0.0+] receives the exporting file format submitted from the specific field that has a section.</li>
97 * <li><strong>export_format_{page slug}_{tab slug}</strong> – receives the exporting file format sent from the tab page.</li>
98 * <li><strong>export_format_{page slug}</strong> – receives the exporting file format submitted from the page.</li>
99 * <li><strong>export_format_{instantiated class name}</strong> – receives the exporting file format submitted from the plugin.</li>
100 * <li><strong>import_{instantiated class name}_{input id}</strong> – [2.1.5+] receives the importing array submitted from the specific import button.</li>
101 * <li><strong>import_{instantiated class name}_{field id}</strong> – [2.1.5+] receives the importing array submitted from the specific import field that does not have a section.</li>
102 * <li><strong>import_{instantiated class name}_{section id}_{field id}</strong> – [3.0.0+] receives the importing array submitted from the specific import field that has a section.</li>
103 * <li><strong>import_{page slug}_{tab slug}</strong> – receives the importing array submitted from the tab page.</li>
104 * <li><strong>import_{page slug}</strong> – receives the importing array submitted from the page.</li>
105 * <li><strong>import_{instantiated class name}</strong> – receives the importing array submitted from the plugin.</li>
106 * <li><strong>import_mime_types_{instantiated class name}_{input id}</strong> – [2.1.5+] receives the mime types of the import data submitted from the specific import button.</li>
107 * <li><strong>import_mime_types_{instantiated class name}_{field id}</strong> – [2.1.5+] receives the mime types of the import data submitted from the specific import field that does not have a section.</li>
108 * <li><strong>import_mime_types_{instantiated class name}_{section id}_{field id}</strong> – [3.0.0+] receives the mime types of the import data submitted from the specific import field that has a section.</li>
109 * <li><strong>import_mime_types_{page slug}_{tab slug}</strong> – receives the mime types of the import data submitted from the tab page.</li>
110 * <li><strong>import_mime_types_{page slug}</strong> – receives the mime types of the import data submitted from the page.</li>
111 * <li><strong>import_mime_types_{instantiated class name}</strong> – receives the mime types of the import data submitted from the plugin.</li>
112 * <li><strong>import_format_{instantiated class name}_{input id}</strong> – [2.1.5+] receives the import data format submitted from the specific import button.</li>
113 * <li><strong>import_format_{instantiated class name}_{field id}</strong> – [2.1.5+] receives the import data format submitted from the specific import field that does not have a section.</li>
114 * <li><strong>import_format_{instantiated class name}_{section id}_{field id}</strong> – [3.0.0+] receives the import data format submitted from the specific import field that has a section.</li>
115 * <li><strong>import_format_{page slug}_{tab slug}</strong> – receives the import data format submitted from the tab page.</li>
116 * <li><strong>import_format_{page slug}</strong> – receives the import data format submitted from the page.</li>
117 * <li><strong>import_format_{instantiated class name}</strong> – receives the import data format submitted from the plugin.</li>
118 * <li><strong>import_option_key_{instantiated class name}_{input id}</strong> – [2.1.5+] receives the option array key of the importing array submitted from the specific import button.</li>
119 * <li><strong>import_option_key_{instantiated class name}_{field id}</strong> – [2.1.5+] receives the option array key of the importing array submitted from the specific import field that does not have a section.</li>
120 * <li><strong>import_option_key_{instantiated class name}_{section id}_{field id}</strong> – [3.0.0+] receives the option array key of the importing array submitted from the specific import field that has a section.</li>
121 * <li><strong>import_option_key_{page slug}_{tab slug}</strong> – receives the option array key of the importing array submitted from the tab page.</li>
122 * <li><strong>import_option_key_{page slug}</strong> – receives the option array key of the importing array submitted from the page.</li>
123 * <li><strong>import_option_key_{instantiated class name}</strong> – receives the option array key of the importing array submitted from the plugin.</li>
124 * <li><strong>options_{instantiated class name}</strong> – [3.1.0+] receives the option array.</li>
125 * </ul>
126 * <h3>Remarks</h3>
127 * <p>The slugs must not contain a dot(.) or a hyphen(-) since it is used in the callback method name.</p>
128 * <h3>Examples</h3>
129 * <p>If the instantiated class name is Sample_Admin_Pages, defining the following class method will embed a banner image in all pages created by the class.</p>
130 * <code>class Sample_Admin_Pages extends AdminPageFramework {
131 * ...
132 * function content_foot_Sample_Admin_Pages( $sContent ) {
133 * return '<div style="float:right;"><img src="' . plugins_url( 'img/banner468x60.gif', __FILE__ ) . '" /></div>'
134 * . $sContent;
135 * }
136 * ...
137 * }</code>
138 * <p>If the created page slug is my_first_setting_page, defining the following class method will filter the middle part of the page output.</p>
139 * <code>class Sample_Admin_Pages extends AdminPageFramework {
140 * ...
141 * function content_my_first_setting_page( $sContent ) {
142 * return $sContent . '<p>Hello world!</p>';
143 * }
144 * ...
145 * }</code>
146 * <h3>Timing of Hooks</h3>
147 * <code>------ After the class is instantiated ------
148 *
149 * start_{instantiated class name}
150 *
151 * ------ When the page starts loading ------
152 *
153 * load_{instantiated class name}
154 * load_{page slug}
155 * load_{page slug}_{tab slug}
156 * load_after_{instantiated class name}
157 *
158 * sections_{instantiated class name}
159 * fields_{instantiated class name}
160 * pages_{instantiated class name}
161 * tabs_{instantiated class name}_{page slug}
162 *
163 * submit_{instantiated class name}_{pressed submit field id}
164 * submit_{instantiated class name}_{section id}
165 * submit_{instantiated class name}_{section id}_{field id}
166 * submit_{instantiated class name}_{page slug}
167 * submit_{instantiated class name}_{page slug}_{tab slug}
168 * submit_{instantiated class name}
169 * validation_saved_options_{instantiated class name}
170 * validation_saved_options_{page slug}_{tab slug}
171 * validation_saved_options_{page slug}
172 * validation_{instantiated class name}_{field id (which does not have a section)}
173 * validation_{instantiated class name}_{section_id}
174 * validation_{instantiated class name}_{section id}_{field id}
175 * validation_{page slug}_{tab slug}
176 * validation_{page slug }
177 * validation_{instantiated class name }
178 * export_{page slug}_{tab slug}
179 * export_{page slug}
180 * export_{instantiated class name}
181 * import_{page slug}_{tab slug}
182 * import_{page slug}
183 * import_{instantiated class name}
184 *
185 * ------ Start Rendering HTML - after HTML header is sent ------
186 *
187 * <head>
188 * <style type="text/css" name="admin-page-framework">
189 * style_{page slug}_{tab slug}
190 * style_{page slug}
191 * style_{instantiated class name}
192 * script_{page slug}_{tab slug}
193 * script_{page slug}
194 * script_{instantiated class name}
195 * </style>
196 *
197 * <head/>
198 *
199 * do_before_{instantiated class name}
200 * do_before_{page slug}
201 * do_before_{page slug}_{tab slug}
202 *
203 * <div class="wrap">
204 *
205 * content_top_{page slug}_{tab slug}
206 * content_top_{page slug}
207 * content_top_{instantiated class name}
208 *
209 * <div class="admin-page-framework-container">
210 * <form action="current page" method="post">
211 *
212 * do_form_{instantiated class name}
213 * do_form_{page slug}
214 * do_form_{page slug}_{tab slug}
215 *
216 * field_definition_{instantiated class name}_{section ID}_{field ID}
217 * field_definition_{instantiated class name}_{field ID (which does not have a section)}
218 * section_head_{instantiated class name}_{section ID}
219 * field_{instantiated class name}_{field ID}
220 *
221 * content_{page slug}_{tab slug}
222 * content_{page slug}
223 * content_{instantiated class name}
224 *
225 * do_{instantiated class name}
226 * do_{page slug}
227 * do_{page slug}_{tab slug}
228 *
229 * </form>
230 * </div>
231 *
232 * content_bottom_{page slug}_{tab slug}
233 * content_bottom_{page slug}
234 * content_bottom_{instantiated class name}
235 *
236 * </div>
237 *
238 * do_after_{instantiated class name}
239 * do_after_{page slug}
240 * do_after_{page slug}_{tab slug}
241 *
242 * </code>
243 * @abstract
244 * @since 2.0.0
245 * @use AdminPageFramework_Property_Page
246 * @use AdminPageFramework_Debug
247 * @use AdminPageFramework_Property_Page
248 * @use AdminPageFramework_Message
249 * @use AdminPageFramework_Link_Page
250 * @use AdminPageFramework_Utility
251 * @remark This class stems from several abstract classes.
252 * @extends AdminPageFramework_Setting
253 * @package AdminPageFramework
254 * @subpackage Page
255 */
256 abstract class AdminPageFramework extends AdminPageFramework_Setting {
257
258 /**
259 * Registers necessary callbacks ans sets up internal components including properties.
260 *
261 * <h4>Example</h4>
262 * <code>if ( is_admin() )
263 * new MyAdminPageClass( 'my_custom_option_key', __FILE__ );</code>
264 *
265 * @access public
266 * @since 2.0.0
267 * @see http://codex.wordpress.org/Roles_and_Capabilities
268 * @see http://codex.wordpress.org/I18n_for_WordPress_Developers#Text_Domains
269 * @param string $sOptionKey ( optional ) specifies the option key name to store in the options table. If this is not set, the instantiated class name will be used.
270 * @param string $sCallerPath ( optional ) used to retrieve the plugin/theme details to auto-insert the information into the page footer.
271 * @param string $sCapability ( optional ) sets the overall access level to the admin pages created by the framework. The used capabilities are listed <a href="http://codex.wordpress.org/Roles_and_Capabilities">here</a>. The capability can be set per page, tab, setting section, setting field. Default: <em>manage_options</em>
272 * @param string $sTextDomain ( optional ) the <a href="http://codex.wordpress.org/I18n_for_WordPress_Developers#Text_Domains" target="_blank">text domain</a> used for the framework's system messages. Default: admin-page-framework.
273 * @return void returns nothing.
274 */
275 public function __construct( $sOptionKey=null, $sCallerPath=null, $sCapability='manage_options', $sTextDomain='admin-page-framework' ){
276
277 if ( ! $this->_isInstantiatable() ) {
278 return;
279 }
280
281 parent::__construct(
282 $sOptionKey,
283 $sCallerPath
284 ? trim( $sCallerPath )
285 : $sCallerPath = ( is_admin() && ( isset( $GLOBALS['pagenow'] ) && in_array( $GLOBALS['pagenow'], array( 'plugins.php', ) ) || isset( $_GET['page'] ) )
286 ? AdminPageFramework_Utility::getCallerScriptPath( __FILE__ )
287 : null
288 ), // this is important to attempt to find the caller script path here when separating the library into multiple files.
289 $sCapability,
290 $sTextDomain
291 );
292
293 $this->oUtil->addAndDoAction( $this, 'start_' . $this->oProp->sClassName, $this );
294
295 }
296
297 /**
298 * The method for all the necessary set-ups.
299 *
300 * The users should override this method to set-up necessary settings. To perform certain tasks prior to this method, use the <strong>start_{instantiated class name}</strong> hook that is triggered at the end of the class constructor.
301 *
302 * <h4>Example</h4>
303 * <code>public function setUp() {
304 * $this->setRootMenuPage( 'APF Form' );
305 * $this->addSubMenuItems(
306 * array(
307 * 'title' => 'Form Fields',
308 * 'page_slug' => 'apf_form_fields',
309 * )
310 * );
311 * $this->addSettingSections(
312 * array(
313 * 'section_id' => 'text_fields',
314 * 'page_slug' => 'apf_form_fields',
315 * 'title' => 'Text Fields',
316 * 'description' => 'These are text type fields.',
317 * )
318 * );
319 * $this->addSettingFields(
320 * array(
321 * 'field_id' => 'text',
322 * 'section_id' => 'text_fields',
323 * 'title' => 'Text',
324 * 'type' => 'text',
325 * )
326 * );
327 * }</code>
328 * @abstract
329 * @since 2.0.0
330 * @remark This is a callback for the <em>wp_loaded</em> hook.
331 * @remark In v1, this is triggered with the <em>admin_menu</em> hook; however, in v2, this is triggered with the <em>wp_loaded</em> hook.
332 * @access public
333 * @return void
334 */
335 public function setUp() {}
336
337 /*
338 * Help Pane Methods
339 */
340
341 /**
342 * Adds the given contextual help tab contents into the property.
343 *
344 * <h4>Example</h4>
345 * <code> $this->addHelpTab(
346 * array(
347 * 'page_slug' => 'first_page', // ( mandatory )
348 * // 'page_tab_slug' => null, // ( optional )
349 * 'help_tab_title' => 'Admin Page Framework',
350 * 'help_tab_id' => 'admin_page_framework', // ( mandatory )
351 * 'help_tab_content' => __( 'This contextual help text can be set with the <em>addHelpTab()</em> method.', 'admin-page-framework' ),
352 * 'help_tab_sidebar_content' => __( 'This is placed in the sidebar of the help pane.', 'admin-page-framework' ),
353 * )
354 * );</code>
355 *
356 * @since 2.1.0
357 * @remark Called when registering setting sections and fields.
358 * @param array The help tab array.
359 * <h4>Contextual Help Tab Array Structure</h4>
360 * <ul>
361 * <li><strong>page_slug</strong> - ( required ) the page slug of the page that the contextual help tab and its contents are displayed.</li>
362 * <li><strong>page_tab_slug</strong> - ( optional ) the tab slug of the page that the contextual help tab and its contents are displayed.</li>
363 * <li><strong>help_tab_title</strong> - ( required ) the title of the contextual help tab.</li>
364 * <li><strong>help_tab_id</strong> - ( required ) the id of the contextual help tab.</li>
365 * <li><strong>help_tab_content</strong> - ( optional ) the HTML string content of the the contextual help tab.</li>
366 * <li><strong>help_tab_sidebar_content</strong> - ( optional ) the HTML string content of the sidebar of the contextual help tab.</li>
367 * </ul>
368 * @return void
369 */
370 public function addHelpTab( $aHelpTab ) {
371 if ( method_exists( $this->oHelpPane, '_addHelpTab' ) ) {
372 $this->oHelpPane->_addHelpTab( $aHelpTab );
373 }
374 }
375
376 /*
377 * Head Tag Methods
378 */
379 /**
380 * Enqueues styles by page slug and tab slug.
381 *
382 * Use this method to pass multiple files to the same page.
383 *
384 * <h4>Example</h4>
385 * <code>$this->enqueueStyle(
386 * array(
387 * dirname( APFDEMO_FILE ) . '/asset/css/code.css',
388 * dirname( APFDEMO_FILE ) . '/asset/css/code2.css',
389 * ),
390 * 'apf_manage_options'
391 * );</code>
392 *
393 * @since 3.0.0
394 * @param array The sources of the stylesheet to enqueue: the url, the absolute file path, or the relative path to the root directory of WordPress. Example: <em>array( '/css/mystyle.css', '/css/mystyle2.css' )</em>
395 * @param string (optional) The page slug that the stylesheet should be added to. If not set, it applies to all the pages created by the framework.
396 * @param string (optional) The tab slug that the stylesheet should be added to. If not set, it applies to all the in-page tabs in the page.
397 * @param array (optional) The argument array for more advanced parameters.
398 * @return array The array holing the queued items.
399 */
400 public function enqueueStyles( $aSRCs, $sPageSlug='', $sTabSlug='', $aCustomArgs=array() ) {
401 if ( method_exists( $this->oHeadTag, '_enqueueStyles' ) ) {
402 return $this->oHeadTag->_enqueueStyles( $aSRCs, $sPageSlug, $sTabSlug, $aCustomArgs );
403 }
404 }
405 /**
406 * Enqueues a style by page slug and tab slug.
407 *
408 * <h4>Example</h4>
409 * <code>$this->enqueueStyle( dirname( APFDEMO_FILE ) . '/asset/css/code.css', 'apf_manage_options' );
410 * $this->enqueueStyle( plugins_url( 'asset/css/readme.css' , APFDEMO_FILE ) , 'apf_read_me' );</code>
411 *
412 * @since 2.1.2
413 * @see http://codex.wordpress.org/Function_Reference/wp_enqueue_style
414 * @param string The source of the stylesheet to enqueue: the url, the absolute file path, or the relative path to the root directory of WordPress. Example: '/css/mystyle.css'.
415 * @param string (optional) The page slug that the stylesheet should be added to. If not set, it applies to all the pages created by the framework.
416 * @param string (optional) The tab slug that the stylesheet should be added to. If not set, it applies to all the in-page tabs in the page.
417 * @param array (optional) The argument array for more advanced parameters.
418 * <h4>Argument Array</h4>
419 * <ul>
420 * <li><strong>handle_id</strong> - ( optional, string ) The handle ID of the stylesheet.</li>
421 * <li><strong>dependencies</strong> - ( optional, array ) The dependency array. For more information, see <a href="http://codex.wordpress.org/Function_Reference/wp_enqueue_style">codex</a>.</li>
422 * <li><strong>version</strong> - ( optional, string ) The stylesheet version number.</li>
423 * <li><strong>media</strong> - ( optional, string ) the description of the field which is inserted into the after the input field tag.</li>
424 * </ul>
425 * @return string The style handle ID. If the passed url is not a valid url string, an empty string will be returned.
426 */
427 public function enqueueStyle( $sSRC, $sPageSlug='', $sTabSlug='', $aCustomArgs=array() ) {
428 if ( method_exists( $this->oHeadTag, '_enqueueStyle' ) ) {
429 return $this->oHeadTag->_enqueueStyle( $sSRC, $sPageSlug, $sTabSlug, $aCustomArgs );
430 }
431 }
432 /**
433 * Enqueues scripts by page slug and tab slug.
434 *
435 * <h4>Example</h4>
436 * <code>
437 * $this->enqueueScripts(
438 * array(
439 * plugins_url( 'asset/js/test.js' , __FILE__ ), // source url or path
440 * plugins_url( 'asset/js/test2.js' , __FILE__ ),
441 * )
442 * 'apf_read_me', // page slug
443 * );
444 * </code>
445 *
446 * @since 2.1.5
447 * @param array The sources of the stylesheets to enqueue: the URL, the absolute file path, or the relative path to the root directory of WordPress. Example: '/js/myscript.js'.
448 * @param string (optional) The page slug that the script should be added to. If not set, it applies to all the pages created by the framework.
449 * @param string (optional) The tab slug that the script should be added to. If not set, it applies to all the in-page tabs in the page.
450 * @param array (optional) The argument array for more advanced parameters.
451 * @return array The array holding the queued items.
452 */
453 public function enqueueScripts( $aSRCs, $sPageSlug='', $sTabSlug='', $aCustomArgs=array() ) {
454 if ( method_exists( $this->oHeadTag, '_enqueueScripts' ) ) {
455 return $this->oHeadTag->_enqueueScripts( $sSRC, $sPageSlug, $sTabSlug, $aCustomArgs );
456 }
457 }
458 /**
459 * Enqueues a script by page slug and tab slug.
460 *
461 * <h4>Example</h4>
462 * <code>$this->enqueueScript(
463 * plugins_url( 'asset/js/test.js' , __FILE__ ), // source url or path
464 * 'apf_read_me', // page slug
465 * '', // tab slug
466 * array(
467 * 'handle_id' => 'my_script', // this handle ID also is used as the object name for the translation array below.
468 * 'translation' => array(
469 * 'a' => 'hello world!',
470 * 'style_handle_id' => $sStyleHandle, // check the enqueued style handle ID here.
471 * ),
472 * )
473 * );</code>
474 *
475 * @since 2.1.2
476 * @since 3.0.0 Changed the scope to public
477 * @see http://codex.wordpress.org/Function_Reference/wp_enqueue_script
478 * @param string The URL of the stylesheet to enqueue, the absolute file path, or the relative path to the root directory of WordPress. Example: '/js/myscript.js'.
479 * @param string (optional) The page slug that the script should be added to. If not set, it applies to all the pages created by the framework.
480 * @param string (optional) The tab slug that the script should be added to. If not set, it applies to all the in-page tabs in the page.
481 * @param array (optional) The argument array for more advanced parameters.
482 * <h4>Argument Array</h4>
483 * <ul>
484 * <li><strong>handle_id</strong> - ( optional, string ) The handle ID of the script.</li>
485 * <li><strong>dependencies</strong> - ( optional, array ) The dependency array. For more information, see <a href="http://codex.wordpress.org/Function_Reference/wp_enqueue_script">codex</a>.</li>
486 * <li><strong>version</strong> - ( optional, string ) The stylesheet version number.</li>
487 * <li><strong>translation</strong> - ( optional, array ) The translation array. The handle ID will be used for the object name.</li>
488 * <li><strong>in_footer</strong> - ( optional, boolean ) Whether to enqueue the script before <code></head></code> or before<code></body></code> Default: <em>false</em>.</li>
489 * </ul>
490 * @return string The script handle ID. If the passed url is not a valid url string, an empty string will be returned.
491 */
492 public function enqueueScript( $sSRC, $sPageSlug='', $sTabSlug='', $aCustomArgs=array() ) {
493 if ( method_exists( $this->oHeadTag, '_enqueueScript' ) ) {
494 return $this->oHeadTag->_enqueueScript( $sSRC, $sPageSlug, $sTabSlug, $aCustomArgs );
495 }
496 }
497
498 /**
499 * Adds the given link(s) into the description cell of the plugin listing table.
500 *
501 * <h4>Example</h4>
502 * <code>$this->addLinkToPluginDescription(
503 * "<a href='http://www.google.com'>Google</a>",
504 * "<a href='http://www.yahoo.com'>Yahoo!</a>"
505 * );</code>
506 *
507 * @since 2.0.0
508 * @since 3.0.0 Changed the scope to public from protected.
509 * @remark Accepts variadic parameters; the number of accepted parameters are not limited to three.
510 * @param string the tagged HTML link text.
511 * @param string ( optional ) another tagged HTML link text.
512 * @param string ( optional ) add more as many as want by adding items to the next parameters.
513 * @access public
514 * @return void
515 */
516 public function addLinkToPluginDescription( $sTaggedLinkHTML1, $sTaggedLinkHTML2=null, $_and_more=null ) {
517 if ( method_exists( $this->oLink, '_addLinkToPluginDescription' ) ) {
518 $this->oLink->_addLinkToPluginDescription( func_get_args() );
519 }
520 }
521
522 /**
523 * Adds the given link(s) into the title cell of the plugin listing table.
524 *
525 * <h4>Example</h4>
526 * <code>$this->addLinkToPluginTitle(
527 * "<a href='http://www.wordpress.org'>WordPress</a>"
528 * );</code>
529 *
530 * @since 2.0.0
531 * @since 3.0.0 Changed the scope to public from protected.
532 * @remark Accepts variadic parameters; the number of accepted parameters are not limited to three.
533 * @param string the tagged HTML link text.
534 * @param string ( optional ) another tagged HTML link text.
535 * @param string ( optional ) add more as many as want by adding items to the next parameters.
536 * @access public
537 * @return void
538 */
539 public function addLinkToPluginTitle( $sTaggedLinkHTML1, $sTaggedLinkHTML2=null, $_and_more=null ) {
540 if ( method_exists( $this->oLink, '_addLinkToPluginTitle' ) ) {
541 $this->oLink->_addLinkToPluginTitle( func_get_args() );
542 }
543 }
544
545 /**
546 * Sets the label applied to the settings link which automatically embedded to the plugin listing table of the plugin title cell.
547 *
548 * To disable the embedded settings link, pass an empty value.
549 *
550 * @since 3.1.0
551 */
552 public function setPluginSettingsLinkLabel( $sLabel ) {
553 $this->oProp->sLabelPluginSettingsLink = $sLabel;
554 }
555
556 /**
557 * Sets the overall capability.
558 *
559 * <h4>Example</h4>
560 * <code>$this->setCpability( 'read' ); // let subscribers access the pages.
561 * </code>
562 *
563 * @since 2.0.0
564 * @since 3.0.0 Changed the scope to public from protected.
565 * @see http://codex.wordpress.org/Roles_and_Capabilities
566 * @param string The <a href="http://codex.wordpress.org/Roles_and_Capabilities">access level</a> for the created pages.
567 * @return void
568 * @access public
569 */
570 public function setCapability( $sCapability ) {
571
572 $this->oProp->sCapability = $sCapability;
573 if ( isset( $this->oForm ) ) {
574 $this->oForm->sCapability = $sCapability;
575 }
576
577 }
578
579 /**
580 * Sets the given HTML text into the footer on the left hand side.
581 *
582 * <h4>Example</h4>
583 * <code>$this->setFooterInfoLeft( '<br />Custom Text on the left hand side.' );
584 * </code>
585 *
586 * @since 2.0.0
587 * @since 3.0.0 Changed the scope to public from protected.
588 * @param string The HTML code to insert.
589 * @param boolean If true, the text will be appended; otherwise, it will replace the default text.
590 * @access public
591 * @return void
592 */
593 public function setFooterInfoLeft( $sHTML, $bAppend=true ) {
594 $this->oProp->aFooterInfo['sLeft'] = $bAppend
595 ? $this->oProp->aFooterInfo['sLeft'] . PHP_EOL . $sHTML
596 : $sHTML;
597 }
598
599 /**
600 * Sets the given HTML text into the footer on the right hand side.
601 *
602 * <h4>Example</h4>
603 * <code>$this->setFooterInfoRight( '<br />Custom Text on the right hand side.' );
604 * </code>
605 *
606 * @access public
607 * @since 2.0.0
608 * @since 3.0.0 Changed the scope to public from protected.
609 * @param string The HTML code to insert.
610 * @param boolean If true, the text will be appended; otherwise, it will replace the default text.
611 * @return void
612 */
613 public function setFooterInfoRight( $sHTML, $bAppend=true ) {
614 $this->oProp->aFooterInfo['sRight'] = $bAppend
615 ? $this->oProp->aFooterInfo['sRight'] . PHP_EOL . $sHTML
616 : $sHTML;
617 }
618
619 /**
620 * Sets an admin notice.
621 *
622 * <h4>Example</h4>
623 * <code>$this->setAdminNotice( sprintf( 'Please click <a href="%1$s">here</a> to upgrade the options.', admin_url( 'admin.php?page="my_page"' ) ), 'updated' );
624 * </code>
625 *
626 * @access public
627 * @remark It should be used before the 'admin_notices' hook is triggered.
628 * @since 2.1.2
629 * @since 3.0.0 Changed the scope to public from protected.
630 * @param string The message to display
631 * @param string ( optional ) The class selector used in the message HTML element. 'error' and 'updated' are prepared by WordPress but it's not limited to them and can pass a custom name. Default: 'error'
632 * @param string ( optional ) The ID of the message. If not set, the hash of the message will be used.
633 */
634 public function setAdminNotice( $sMessage, $sClassSelector='error', $sID='' ) {
635
636 $sID = $sID ? $sID : md5( $sMessage );
637 $this->oProp->aAdminNotices[ md5( $sMessage ) ] = array(
638 'sMessage' => $sMessage,
639 'sClassSelector' => $sClassSelector,
640 'sID' => $sID,
641 );
642 if ( is_network_admin() ) {
643 add_action( 'network_admin_notices', array( $this, '_replyToPrintAdminNotices' ) );
644 } else {
645 add_action( 'admin_notices', array( $this, '_replyToPrintAdminNotices' ) );
646 }
647
648 }
649 /**
650 * A helper function for the above setAdminNotice() method.
651 * @since 2.1.2
652 * @internal
653 */
654 public function _replyToPrintAdminNotices() {
655
656 if ( ! $this->_isInThePage() ) { return; }
657 foreach( $this->oProp->aAdminNotices as $aAdminNotice ) {
658 echo "<div class='{$aAdminNotice['sClassSelector']}' id='{$aAdminNotice['sID']}'>"
659 . "<p>" . $aAdminNotice['sMessage'] . "</p>"
660 . "</div>";
661 }
662
663 }
664
665 /**
666 * Sets the disallowed query keys in the links that the framework generates.
667 *
668 * <h4>Example</h4>
669 * <code>$this->setDisallowedQueryKeys( 'my-custom-admin-notice' );
670 * </code>
671 *
672 * @since 2.1.2
673 * @since 3.0.0 It also accepts a string. Changed the scope to public.
674 * @access public
675 * @param array|string The query key(s) to disallow.
676 * @param boolean If true, the passed key(s) will be appended to the property; otherwise, it will override the property.
677 * @return void
678 */
679 public function setDisallowedQueryKeys( $asQueryKeys, $bAppend=true ) {
680
681 if ( ! $bAppend ) {
682 $this->oProp->aDisallowedQueryKeys = ( array ) $asQueryKeys;
683 return;
684 }
685
686 $aNewQueryKeys = array_merge( ( array ) $asQueryKeys, $this->oProp->aDisallowedQueryKeys );
687 $aNewQueryKeys = array_filter( $aNewQueryKeys ); // drop non-values
688 $aNewQueryKeys = array_unique( $aNewQueryKeys ); // drop duplicates
689 $this->oProp->aDisallowedQueryKeys = $aNewQueryKeys;
690
691 }
692
693 /**
694 * Retrieves the saved option value from the given option key and the dimensional array key representation.
695 *
696 * <h4>Example</h4>
697 * <code>
698 * $aData = AdminPageFramework::getOption( 'APF' );
699 * $aSection = AdminPageFramework::getOption( 'APF', 'my_section' );
700 * $sText = AdminPageFramework::getOption( 'APF', array( 'my_section', 'my_text_field' ), 'foo' );
701 * $sColor = AdminPageFramework::getOption( 'APF', 'my_color_field', '#FFF' );
702 * </code>
703 *
704 * @since 3.0.1
705 * @param string $sOptionKey the option key of the options table.
706 * @param string $asKey the representation of dimensional array keys. If the returning option structure is like the following,
707 * <code>
708 * array(
709 * 'a' => array(
710 * 'b' => array(
711 * 'c' => 'ccc',
712 * ),
713 * ),
714 * )
715 * </code>
716 * then the value 'ccc' can be retrieved with the key representation array of
717 * <code>
718 * array( 'a', 'b', 'c' )
719 * </code>
720 * @param mixed $vDefault the default value that will be returned if nothing is stored.
721 * @return mixed If the field ID is not specified
722 */
723 static public function getOption( $sOptionKey, $asKey=null , $vDefault=null ) {
724 return AdminPageFramework_WPUtility::getOption( $sOptionKey,$asKey, $vDefault );
725 }
726
727 }
728 endif;