|
1
|
|
|
<?php |
|
|
|
|
|
|
2
|
|
|
|
|
3
|
|
|
if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly |
|
4
|
|
|
} |
|
5
|
|
|
class TitanFrameworkAdminPage { |
|
6
|
|
|
|
|
7
|
|
|
private $defaultSettings = array( |
|
8
|
|
|
'name' => '', // Name of the menu item |
|
9
|
|
|
'title' => '', // Title displayed on the top of the admin panel |
|
10
|
|
|
'parent' => null, // id of parent, if blank, then this is a top level menu |
|
11
|
|
|
'id' => '', // Unique ID of the menu item |
|
12
|
|
|
'capability' => 'manage_options', // User role |
|
13
|
|
|
'icon' => 'dashicons-admin-generic', // Menu icon for top level menus only http://melchoyce.github.io/dashicons/ |
|
14
|
|
|
'position' => null, // Menu position. Can be used for both top and sub level menus |
|
15
|
|
|
'use_form' => true, // If false, options will not be wrapped in a form |
|
16
|
|
|
'desc' => '', // Description displayed below the title |
|
17
|
|
|
); |
|
18
|
|
|
|
|
19
|
|
|
public $settings; |
|
20
|
|
|
public $options = array(); |
|
21
|
|
|
public $tabs = array(); |
|
22
|
|
|
public $owner; |
|
23
|
|
|
|
|
24
|
|
|
public $panelID; |
|
25
|
|
|
|
|
26
|
|
|
private $activeTab = null; |
|
27
|
|
|
private static $idsUsed = array(); |
|
28
|
|
|
|
|
29
|
|
|
function __construct( $settings, $owner ) { |
|
|
|
|
|
|
30
|
|
|
$this->owner = $owner; |
|
31
|
|
|
|
|
32
|
|
|
if ( ! is_admin() ) { |
|
33
|
|
|
return; |
|
34
|
|
|
} |
|
35
|
|
|
|
|
36
|
|
|
$this->settings = array_merge( $this->defaultSettings, $settings ); |
|
37
|
|
|
// $this->options = $options; |
|
|
|
|
|
|
38
|
|
|
if ( empty( $this->settings['name'] ) ) { |
|
39
|
|
|
return; |
|
40
|
|
|
} |
|
41
|
|
|
|
|
42
|
|
|
if ( empty( $this->settings['title'] ) ) { |
|
43
|
|
|
$this->settings['title'] = $this->settings['name']; |
|
44
|
|
|
} |
|
45
|
|
|
|
|
46
|
|
|
if ( empty( $this->settings['id'] ) ) { |
|
47
|
|
|
$prefix = ''; |
|
48
|
|
|
if ( ! empty( $this->settings['parent'] ) ) { |
|
49
|
|
|
$prefix = str_replace( ' ', '-', trim( strtolower( $this->settings['parent'] ) ) ) . '-'; |
|
50
|
|
|
} |
|
51
|
|
|
$this->settings['id'] = $prefix . str_replace( ' ', '-', trim( strtolower( $this->settings['name'] ) ) ); |
|
52
|
|
|
$this->settings['id'] = str_replace( '&', '-', $this->settings['id'] ); |
|
53
|
|
|
} |
|
54
|
|
|
|
|
55
|
|
|
// make sure all our IDs are unique |
|
56
|
|
|
$suffix = ''; |
|
57
|
|
|
while ( in_array( $this->settings['id'] . $suffix, self::$idsUsed ) ) { |
|
58
|
|
|
if ( $suffix == '' ) { |
|
59
|
|
|
$suffix = 2; |
|
60
|
|
|
} else { |
|
61
|
|
|
$suffix++; |
|
62
|
|
|
} |
|
63
|
|
|
} |
|
64
|
|
|
$this->settings['id'] .= $suffix; |
|
65
|
|
|
|
|
66
|
|
|
// keep track of all IDs used |
|
67
|
|
|
self::$idsUsed[] = $this->settings['id']; |
|
68
|
|
|
|
|
69
|
|
|
$priority = -1; |
|
70
|
|
|
if ( $this->settings['parent'] ) { |
|
71
|
|
|
$priority = intval( $this->settings['position'] ); |
|
72
|
|
|
} |
|
73
|
|
|
|
|
74
|
|
|
add_action( 'admin_menu', array( $this, 'register' ), $priority ); |
|
75
|
|
|
} |
|
76
|
|
|
|
|
77
|
|
|
public function createAdminPanel( $settings ) { |
|
78
|
|
|
$settings['parent'] = $this->settings['id']; |
|
79
|
|
|
return $this->owner->createAdminPanel( $settings ); |
|
80
|
|
|
} |
|
81
|
|
|
|
|
82
|
|
|
public function register() { |
|
83
|
|
|
// Parent menu |
|
84
|
|
|
if ( empty( $this->settings['parent'] ) ) { |
|
85
|
|
|
$this->panelID = add_menu_page( $this->settings['name'], |
|
86
|
|
|
$this->settings['name'], |
|
87
|
|
|
$this->settings['capability'], |
|
88
|
|
|
$this->settings['id'], |
|
89
|
|
|
array( $this, 'createAdminPage' ), |
|
90
|
|
|
$this->settings['icon'], |
|
91
|
|
|
$this->settings['position'] ); |
|
92
|
|
|
// Sub menu |
|
93
|
|
|
} else { |
|
94
|
|
|
$this->panelID = add_submenu_page( $this->settings['parent'], |
|
95
|
|
|
$this->settings['name'], |
|
96
|
|
|
$this->settings['name'], |
|
97
|
|
|
$this->settings['capability'], |
|
98
|
|
|
$this->settings['id'], |
|
99
|
|
|
array( $this, 'createAdminPage' ) ); |
|
100
|
|
|
} |
|
101
|
|
|
|
|
102
|
|
|
add_action( 'load-' . $this->panelID, array( $this, 'saveOptions' ) ); |
|
103
|
|
|
|
|
104
|
|
|
add_action( 'load-' . $this->panelID, array( $this, 'addTitanCredit' ) ); |
|
105
|
|
|
} |
|
106
|
|
|
|
|
107
|
|
|
|
|
108
|
|
|
public function addTitanCredit() { |
|
109
|
|
|
add_filter( 'admin_footer_text', array( $this, 'addTitanCreditText' ) ); |
|
110
|
|
|
} |
|
111
|
|
|
|
|
112
|
|
|
|
|
113
|
|
|
public function addTitanCreditText() { |
|
114
|
|
|
echo __( "<em>Options Page Created with <a href='http://titanframework.net?utm_source=admin&utm_medium=admin footer'>Titan Framework</a></em>", TF_I18NDOMAIN ); |
|
115
|
|
|
} |
|
116
|
|
|
|
|
117
|
|
|
|
|
118
|
|
|
public function getOptionNamespace() { |
|
119
|
|
|
return $this->owner->optionNamespace; |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
|
|
123
|
|
|
public function saveOptions() { |
|
124
|
|
|
if ( ! $this->verifySecurity() ) { |
|
125
|
|
|
return; |
|
126
|
|
|
} |
|
127
|
|
|
|
|
128
|
|
|
$message = ''; |
|
129
|
|
|
$activeTab = $this->getActiveTab(); |
|
130
|
|
|
|
|
131
|
|
|
/* |
|
132
|
|
|
* Save |
|
133
|
|
|
*/ |
|
134
|
|
|
|
|
135
|
|
|
if ( $_POST['action'] == 'save' ) { |
|
136
|
|
|
|
|
137
|
|
|
// we are in a tab |
|
138
|
|
|
if ( ! empty( $activeTab ) ) { |
|
139
|
|
|
foreach ( $activeTab->options as $option ) { |
|
140
|
|
|
if ( empty( $option->settings['id'] ) ) { |
|
141
|
|
|
continue; |
|
142
|
|
|
} |
|
143
|
|
|
|
|
144
|
|
|
if ( isset( $_POST[ $this->getOptionNamespace() . '_' . $option->settings['id'] ] ) ) { |
|
145
|
|
|
$value = $_POST[ $this->getOptionNamespace() . '_' . $option->settings['id'] ]; |
|
146
|
|
|
} else { |
|
147
|
|
|
$value = ''; |
|
148
|
|
|
} |
|
149
|
|
|
|
|
150
|
|
|
$option->setValue( $value ); |
|
151
|
|
|
} |
|
152
|
|
|
} |
|
153
|
|
|
|
|
154
|
|
|
foreach ( $this->options as $option ) { |
|
155
|
|
|
if ( empty( $option->settings['id'] ) ) { |
|
156
|
|
|
continue; |
|
157
|
|
|
} |
|
158
|
|
|
|
|
159
|
|
|
if ( isset( $_POST[ $this->getOptionNamespace() . '_' . $option->settings['id'] ] ) ) { |
|
160
|
|
|
$value = $_POST[ $this->getOptionNamespace() . '_' . $option->settings['id'] ]; |
|
161
|
|
|
} else { |
|
162
|
|
|
$value = ''; |
|
163
|
|
|
} |
|
164
|
|
|
|
|
165
|
|
|
$option->setValue( $value ); |
|
166
|
|
|
} |
|
167
|
|
|
|
|
168
|
|
|
// Hook 'tf_pre_save_options_{namespace}' - action pre-saving |
|
169
|
|
|
/** |
|
170
|
|
|
* Fired right before options are saved. |
|
171
|
|
|
* |
|
172
|
|
|
* @since 1.0 |
|
173
|
|
|
* |
|
174
|
|
|
* @param TitanFrameworkAdminPage|TitanFrameworkCustomizer|TitanFrameworkMetaBox $this The container currently being saved. |
|
175
|
|
|
*/ |
|
176
|
|
|
$namespace = $this->getOptionNamespace(); |
|
177
|
|
|
do_action( "tf_pre_save_options_{$namespace}", $this ); |
|
178
|
|
|
do_action( "tf_pre_save_admin_{$namespace}", $this, $activeTab, $this->options ); |
|
179
|
|
|
|
|
180
|
|
|
$this->owner->saveInternalAdminPageOptions(); |
|
181
|
|
|
|
|
182
|
|
|
do_action( 'tf_save_admin_' . $this->getOptionNamespace(), $this, $activeTab, $this->options ); |
|
183
|
|
|
|
|
184
|
|
|
$message = 'saved'; |
|
185
|
|
|
|
|
186
|
|
|
/* |
|
187
|
|
|
* Reset |
|
188
|
|
|
*/ |
|
189
|
|
|
|
|
190
|
|
|
} else if ( $_POST['action'] == 'reset' ) { |
|
191
|
|
|
|
|
192
|
|
|
// we are in a tab |
|
193
|
|
|
if ( ! empty( $activeTab ) ) { |
|
194
|
|
|
foreach ( $activeTab->options as $option ) { |
|
195
|
|
|
if ( empty( $option->settings['id'] ) ) { |
|
196
|
|
|
continue; |
|
197
|
|
|
} |
|
198
|
|
|
|
|
199
|
|
|
$option->setValue( $option->settings['default'] ); |
|
200
|
|
|
} |
|
201
|
|
|
} |
|
202
|
|
|
|
|
203
|
|
|
foreach ( $this->options as $option ) { |
|
204
|
|
|
if ( empty( $option->settings['id'] ) ) { |
|
205
|
|
|
continue; |
|
206
|
|
|
} |
|
207
|
|
|
|
|
208
|
|
|
$option->setValue( $option->settings['default'] ); |
|
209
|
|
|
} |
|
210
|
|
|
|
|
211
|
|
|
// Hook 'tf_pre_reset_options_{namespace}' - action pre-saving |
|
212
|
|
|
do_action( 'tf_pre_reset_options_' . $this->getOptionNamespace(), $this ); |
|
213
|
|
|
do_action( 'tf_pre_reset_admin_' . $this->getOptionNamespace(), $this, $activeTab, $this->options ); |
|
214
|
|
|
|
|
215
|
|
|
$this->owner->saveInternalAdminPageOptions(); |
|
216
|
|
|
|
|
217
|
|
|
do_action( 'tf_reset_admin_' . $this->getOptionNamespace(), $this, $activeTab, $this->options ); |
|
218
|
|
|
|
|
219
|
|
|
$message = 'reset'; |
|
220
|
|
|
} |
|
221
|
|
|
|
|
222
|
|
|
/* |
|
223
|
|
|
* Redirect to prevent refresh saving |
|
224
|
|
|
*/ |
|
225
|
|
|
|
|
226
|
|
|
// urlencode to allow special characters in the url |
|
227
|
|
|
$url = wp_get_referer(); |
|
228
|
|
|
$activeTab = $this->getActiveTab(); |
|
229
|
|
|
$url = add_query_arg( 'page', urlencode( $this->settings['id'] ), $url ); |
|
230
|
|
|
if ( ! empty( $activeTab ) ) { |
|
231
|
|
|
$url = add_query_arg( 'tab', urlencode( $activeTab->settings['id'] ), $url ); |
|
232
|
|
|
} |
|
233
|
|
|
if ( ! empty( $message ) ) { |
|
234
|
|
|
$url = add_query_arg( 'message', $message, $url ); |
|
235
|
|
|
} |
|
236
|
|
|
|
|
237
|
|
|
do_action( 'tf_admin_options_saved_' . $this->getOptionNamespace() ); |
|
238
|
|
|
|
|
239
|
|
|
wp_redirect( esc_url_raw( $url ) ); |
|
240
|
|
|
} |
|
241
|
|
|
|
|
242
|
|
|
private function verifySecurity() { |
|
243
|
|
|
if ( empty( $_POST ) || empty( $_POST['action'] ) ) { |
|
244
|
|
|
return false; |
|
245
|
|
|
} |
|
246
|
|
|
|
|
247
|
|
|
$screen = get_current_screen(); |
|
248
|
|
|
if ( $screen->id != $this->panelID ) { |
|
249
|
|
|
return false; |
|
250
|
|
|
} |
|
251
|
|
|
|
|
252
|
|
|
if ( ! current_user_can( $this->settings['capability'] ) ) { |
|
253
|
|
|
return false; |
|
254
|
|
|
} |
|
255
|
|
|
|
|
256
|
|
|
if ( ! check_admin_referer( $this->settings['id'], TF . '_nonce' ) ) { |
|
257
|
|
|
return false; |
|
258
|
|
|
} |
|
259
|
|
|
|
|
260
|
|
|
return true; |
|
261
|
|
|
} |
|
262
|
|
|
|
|
263
|
|
|
public function getActiveTab() { |
|
264
|
|
|
if ( ! count( $this->tabs ) ) { |
|
265
|
|
|
return ''; |
|
266
|
|
|
} |
|
267
|
|
|
if ( ! empty( $this->activeTab ) ) { |
|
268
|
|
|
return $this->activeTab; |
|
269
|
|
|
} |
|
270
|
|
|
|
|
271
|
|
|
if ( empty( $_GET['tab'] ) ) { |
|
272
|
|
|
$this->activeTab = $this->tabs[0]; |
|
273
|
|
|
return $this->activeTab; |
|
274
|
|
|
} |
|
275
|
|
|
|
|
276
|
|
|
foreach ( $this->tabs as $tab ) { |
|
277
|
|
|
if ( $tab->settings['id'] == $_GET['tab'] ) { |
|
278
|
|
|
$this->activeTab = $tab; |
|
279
|
|
|
return $this->activeTab; |
|
280
|
|
|
} |
|
281
|
|
|
} |
|
282
|
|
|
|
|
283
|
|
|
$this->activeTab = $this->tabs[0]; |
|
284
|
|
|
return $this->activeTab; |
|
285
|
|
|
} |
|
286
|
|
|
|
|
287
|
|
|
public function createAdminPage() { |
|
288
|
|
|
do_action( 'tf_admin_page_before' ); |
|
289
|
|
|
do_action( 'tf_admin_page_before_' . $this->getOptionNamespace() ); |
|
290
|
|
|
|
|
291
|
|
|
?> |
|
292
|
|
|
<div class="wrap"> |
|
293
|
|
|
<h2><?php echo $this->settings['title'] ?></h2> |
|
294
|
|
|
<?php |
|
295
|
|
|
if ( ! empty( $this->settings['desc'] ) ) { |
|
296
|
|
|
?><p class='description'><?php echo $this->settings['desc'] ?></p><?php |
|
297
|
|
|
} |
|
298
|
|
|
?> |
|
299
|
|
|
|
|
300
|
|
|
<div class='titan-framework-panel-wrap'> |
|
301
|
|
|
<?php |
|
302
|
|
|
|
|
303
|
|
|
do_action( 'tf_admin_page_start' ); |
|
304
|
|
|
do_action( 'tf_admin_page_start_' . $this->getOptionNamespace() ); |
|
305
|
|
|
|
|
306
|
|
|
if ( count( $this->tabs ) ) : |
|
307
|
|
|
?> |
|
308
|
|
|
<h2 class="nav-tab-wrapper"> |
|
309
|
|
|
<?php |
|
310
|
|
|
|
|
311
|
|
|
do_action( 'tf_admin_page_tab_start' ); |
|
312
|
|
|
do_action( 'tf_admin_page_tab_start_' . $this->getOptionNamespace() ); |
|
313
|
|
|
|
|
314
|
|
|
foreach ( $this->tabs as $tab ) { |
|
315
|
|
|
$tab->displayTab(); |
|
316
|
|
|
} |
|
317
|
|
|
|
|
318
|
|
|
do_action( 'tf_admin_page_tab_end' ); |
|
319
|
|
|
do_action( 'tf_admin_page_tab_end_' . $this->getOptionNamespace() ); |
|
320
|
|
|
|
|
321
|
|
|
?> |
|
322
|
|
|
</h2> |
|
323
|
|
|
<?php |
|
324
|
|
|
endif; |
|
325
|
|
|
|
|
326
|
|
|
?> |
|
327
|
|
|
<div class='options-container'> |
|
328
|
|
|
<?php |
|
329
|
|
|
|
|
330
|
|
|
// Display notification if we did something |
|
331
|
|
|
if ( ! empty( $_GET['message'] ) ) { |
|
332
|
|
|
if ( $_GET['message'] == 'saved' ) { |
|
333
|
|
|
echo TitanFrameworkAdminNotification::formNotification( __( 'Settings saved.', TF_I18NDOMAIN ), esc_html( $_GET['message'] ) ); |
|
334
|
|
|
} else if ( $_GET['message'] == 'reset' ) { |
|
335
|
|
|
echo TitanFrameworkAdminNotification::formNotification( __( 'Settings reset to default.', TF_I18NDOMAIN ), esc_html( $_GET['message'] ) ); |
|
336
|
|
|
} |
|
337
|
|
|
} |
|
338
|
|
|
|
|
339
|
|
|
if ( $this->settings['use_form'] ) : |
|
340
|
|
|
?> |
|
341
|
|
|
<form method='post'> |
|
342
|
|
|
<?php |
|
343
|
|
|
endif; |
|
344
|
|
|
|
|
345
|
|
|
if ( $this->settings['use_form'] ) { |
|
346
|
|
|
// security |
|
347
|
|
|
wp_nonce_field( $this->settings['id'], TF . '_nonce' ); |
|
348
|
|
|
} |
|
349
|
|
|
|
|
350
|
|
|
?> |
|
351
|
|
|
<table class='form-table'> |
|
352
|
|
|
<tbody> |
|
353
|
|
|
<?php |
|
354
|
|
|
|
|
355
|
|
|
do_action( 'tf_admin_page_table_start' ); |
|
356
|
|
|
do_action( 'tf_admin_page_table_start_' . $this->getOptionNamespace() ); |
|
357
|
|
|
|
|
358
|
|
|
$activeTab = $this->getActiveTab(); |
|
359
|
|
|
if ( ! empty( $activeTab ) ) { |
|
360
|
|
|
|
|
361
|
|
|
if ( ! empty( $activeTab->settings['desc'] ) ) { |
|
362
|
|
|
?><p class='description'><?php echo $activeTab->settings['desc'] ?></p><?php |
|
363
|
|
|
} |
|
364
|
|
|
|
|
365
|
|
|
$activeTab->displayOptions(); |
|
366
|
|
|
} |
|
367
|
|
|
|
|
368
|
|
|
foreach ( $this->options as $option ) { |
|
369
|
|
|
$option->display(); |
|
370
|
|
|
} |
|
371
|
|
|
|
|
372
|
|
|
do_action( 'tf_admin_page_table_end' ); |
|
373
|
|
|
do_action( 'tf_admin_page_table_end_' . $this->getOptionNamespace() ); |
|
374
|
|
|
|
|
375
|
|
|
?> |
|
376
|
|
|
</tbody> |
|
377
|
|
|
</table> |
|
378
|
|
|
<?php |
|
379
|
|
|
|
|
380
|
|
|
if ( $this->settings['use_form'] ) : |
|
381
|
|
|
?> |
|
382
|
|
|
</form> |
|
383
|
|
|
<?php |
|
384
|
|
|
endif; |
|
385
|
|
|
|
|
386
|
|
|
// Reset form. We use JS to trigger a reset from other buttons within the main form |
|
387
|
|
|
// This is used by class-option-save.php |
|
388
|
|
|
if ( $this->settings['use_form'] ) : |
|
389
|
|
|
?> |
|
390
|
|
|
<form method='post' id='tf-reset-form'> |
|
391
|
|
|
<?php |
|
392
|
|
|
// security |
|
393
|
|
|
wp_nonce_field( $this->settings['id'], TF . '_nonce' ); |
|
394
|
|
|
?> |
|
395
|
|
|
<input type='hidden' name='action' value='reset'/> |
|
396
|
|
|
</form> |
|
397
|
|
|
<?php |
|
398
|
|
|
endif; |
|
399
|
|
|
|
|
400
|
|
|
do_action( 'tf_admin_page_end' ); |
|
401
|
|
|
do_action( 'tf_admin_page_end_' . $this->getOptionNamespace() ); |
|
402
|
|
|
|
|
403
|
|
|
?> |
|
404
|
|
|
<div class='options-container'> |
|
405
|
|
|
</div> |
|
406
|
|
|
</div> |
|
407
|
|
|
</div> |
|
408
|
|
|
</div> |
|
409
|
|
|
<?php |
|
410
|
|
|
|
|
411
|
|
|
do_action( 'tf_admin_page_after' ); |
|
412
|
|
|
do_action( 'tf_admin_page_after_' . $this->getOptionNamespace() ); |
|
413
|
|
|
} |
|
414
|
|
|
|
|
415
|
|
|
public function createTab( $settings ) { |
|
416
|
|
|
$obj = new TitanFrameworkAdminTab( $settings, $this ); |
|
417
|
|
|
$this->tabs[] = $obj; |
|
418
|
|
|
|
|
419
|
|
|
do_action( 'tf_admin_tab_created_' . $this->getOptionNamespace(), $obj ); |
|
420
|
|
|
|
|
421
|
|
|
return $obj; |
|
422
|
|
|
} |
|
423
|
|
|
|
|
424
|
|
|
public function createOption( $settings ) { |
|
425
|
|
|
if ( ! apply_filters( 'tf_create_option_continue_' . $this->getOptionNamespace(), true, $settings ) ) { |
|
426
|
|
|
return null; |
|
427
|
|
|
} |
|
428
|
|
|
|
|
429
|
|
|
$obj = TitanFrameworkOption::factory( $settings, $this ); |
|
430
|
|
|
$this->options[] = $obj; |
|
431
|
|
|
|
|
432
|
|
|
do_action( 'tf_create_option_' . $this->getOptionNamespace(), $obj ); |
|
433
|
|
|
|
|
434
|
|
|
return $obj; |
|
435
|
|
|
} |
|
436
|
|
|
} |
|
437
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.