-
Notifications
You must be signed in to change notification settings - Fork 0
/
wpsettings.php
2454 lines (1971 loc) · 73.5 KB
/
wpsettings.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?php
/**
* WP Settings - A set of classes to create a WordPress settings page for a Theme or a plugin.
* @author David Mårtensson <david.martensson@gmail.com>
* @version 1.9.1
* @package FeedMeAStrayCat
* @subpackage WPSettings
* @license MIT http://en.wikipedia.org/wiki/MIT_License
*/
// Set namespace
namespace FeedMeAStrayCat\WPSettings_1_9_1;
/*************************************
FEED ME A STRAY CAT
Flattr me here:
http://www.feedmeastraycat.net/projects/wordpress-snippets/wpsettings/
See more WP Snippets by me here:
http://www.feedmeastraycat.net/projects/wordpress-snippets/
I do more WP stuff together with Odd Alice:
http://oddalice.com/
HOW TO
Important note about namespaces:
----------------------------------
To enable WPSettings to work on a WordPress site, where multiple plugins or themes uses WPSettings (even though it might not be that common),
a namespace has been added to WPSettings.
The namespace will always look like this: \FeedMeAStrayCat\WPSettings_1_7_0 (for that specific version).
Use it together with if (!class_exists('\FeedMeAStrayCat\WPSettings_1_7_0\WPSettings')) to only include your WPSettings file with the correct
version if it hasn't already been included.
In you code you can use the namespace to call the function/class directly:
$wp_settings_page = new \FeedMeAStrayCat\WPSettings_1_7_0\WPSettingsPage(...)
Or you use the "use" statement:
use \FeedMeAStrayCat\WPSettings_1_7_0\WPSettingsPage;
if (!class_exists('\FeedMeAStrayCat\WPSettings_1_7_0\WPSettings'))
require_once('/path/to/wpsettings.php');
}
$wp_settings_page = new WPSettingsPage(...)
Just remember to add use statements to all classes that you call directly.
----------------------------------
A simple example:
----------------------------------
use \FeedMeAStrayCat\WPSettings_1_7_0\WPSettingsPage;
if (!class_exists('\FeedMeAStrayCat\WPSettings_1_7_0\WPSettings')) {
require_once('/path/to/wpsettings.php');
}
add_action('admin_menu', 'my_admin_menu');
// This will contain the global WPSettingsPage object
global $wp_settings_page;
$wp_settings_page = null;
function my_admin_menu() {
global $wp_settings_page;
// Create a settings page
$wp_settings_page = new WPSettingsPage('My page title', 'Subtitle', 'My Menu Title', 'manage_options', 'my_unique_slug', 'my_admin_page_output', 'icon-url.png', $position=100);
// Set a id and add a css class so we can change the icon
$wp_settings_page->setIcon('my-icon-id', array('my-icon-class'));
// Adds a config section
$section = $wp_settings_page->addSettingsSection('first_section', 'The first section', 'This is the first section');
// Adds a text input
$section->addField('test_value', 'Test value', 'text', 'my_options[test]', 'Default value', 'Prefixed help text');
// Adds a textarea
$field = $section->addField('textarea_value', 'Textarea', 'textarea', 'my_options[textarea]', 'Default textarea value', 'Prefixed help text');
$field->setSize(200, 80);
// Adds a wysiwyg
$wysiwyg = $section->addField('wysiwyg_value', 'Test wysiwyg', 'wysiwyg', 'my_options[wysiwyg]', 'my_options[wysiwyg]', 'Wysiwyg help text');
$wysiwyg->setSettings(array('textarea_rows' => 5));
// Adds three checkboxes
$section->addField('test_checkboxes', 'Select cake', 'checkbox', array('my_options[cake_1]', 'my_options[cake_2]', 'my_options[cake_3]'), array(false, false, false), array('Cake 1', 'Cake 2', 'Cake 3'));
// Adds a dropdown without a option group
$dropdown = $section->addField('test_select', 'Select day', 'dropdown', 'my_options[day]', 'mon');
$dropdown->addOption('mon', 'Monday');
$dropdown->addOption('tues', 'Tuesday');
// Adds a dropdown with two groups
$dropdown = $section->addField('test_select2', 'Select day again', 'dropdown', 'my_options[day2]', 6);
// Uncomment this option to get a groupless option in the beginning
//$dropdown->addOption(0, 'Choose a Day');
$optgroup = $dropdown->addOptionGroup('Weekday');
$dropdown->addOption(1, 'Monday', $optgroup);
$dropdown->addOption(2, 'Tuesday', $optgroup);
$optgroup = $dropdown->addOptionGroup('Weekend');
$dropdown->addOption(6, 'Saturday', $optgroup);
$dropdown->addOption(7, 'Sunday', $optgroup);
// Adds three "radio" options
$radio = $section->addField('test_radio', 'Select month', 'radio', 'my_options[month]', 'jan');
$radio->addOption('jan', 'January');
$radio->addOption('feb', 'February');
$radio->addOption('mar', 'March');
// Activate settings
$wp_settings_page->activateSettings();
}
function my_admin_page_output() {
global $wp_settings_page;
$wp_settings_page->output();
}
----------------------------------
Subpages:
You can add subpages by calling the function addSubPage() on a WPSettingsPage object.
All the regular WPSettings features works on a sub page. The sub page is put as a sub menu
page link in the WP menu.
----------------------------------
use \FeedMeAStrayCat\WPSettings_1_7_0\WPSettingsPage;
if (!class_exists('\FeedMeAStrayCat\WPSettings_1_7_0\WPSettings')) {
require_once('/path/to/wpsettings.php');
}
add_action('admin_menu', 'my_admin_menu');
// This will contain the global WPSettingsPage object
global $wp_settings_page, $wp_settings_sub_page;
$wp_settings_page = null;
$wp_settings_sub_page = null;
function my_admin_menu() {
global $wp_settings_page, $wp_settings_sub_page;
// Create a settings page
$wp_settings_page = new WPSettingsPage('My page title', 'Subtitle', 'My menu title', 'manage_options', 'my_unique_slug', 'my_admin_page_output', 'icon-url.png', $position=100);
// Create a sub page
$wp_settings_sub_page = $wp_settings_page->addSubPage('My subpage', 'Subtitle', 'My menu subtitle', 'manage_options', 'my_unique_subpage_slug', 'my_admin_subpage_output');
// Create sections and so on ...
}
function my_admin_page_output() {
global $wp_settings_page;
$wp_settings_page->output();
}
function my_admin_subpage_output() {
global $wp_settings_page, $wp_settings_sub_page;
// You can do
$wp_settings_page->output('my_unique_subpage_slug');
// Or you can do
// $wp_settings_sub_page->output();
}
----------------------------------
Filters:
Through WPSettingsField->addFilter() you can add filters that uses the built in WP filters api. Send in which type of filter
you want to use, which must be one of the WPSettingsField::FILTER_ constants, the callback function and a priority integer.
----------------------------------
use \FeedMeAStrayCat\WPSettings_1_7_0\WPSettingsPage;
use \FeedMeAStrayCat\WPSettings_1_7_0\WPSettingsField;
if (!class_exists('\FeedMeAStrayCat\WPSettings_1_7_0\WPSettings')) {
require_once('/path/to/wpsettings.php');
}
add_action('admin_menu', 'my_admin_menu');
// This will contain the global WPSettingsPage object
global $wp_settings_page;
$wp_settings_page = null;
function my_admin_menu() {
global $wp_settings_page;
// Create a settings page
$wp_settings_page = new WPSettingsPage('My page title', 'Subtitle', 'My menu title', 'manage_options', 'my_unique_slug', 'my_admin_page_output', 'icon-url.png', $position=100);
// Adds a config section
$section = $wp_settings_page->addSettingsSection('first_section', 'The first section', 'This is the first section');
// Adds a text input
$field = $section->addField('test_value', 'Test value', 'text', 'my_options[test]', 'Default value', 'Prefixed help text');
// Add a filter for when the text input is updated (1 is it's priority)
// The filters are called using WP built in filter API
$field->addFilter(WPSettingsField::FILTER_UPDATE, 'update_text_value', 1);
// Activate settings
$wp_settings_page->activateSettings();
}
function my_admin_page_output() {
global $wp_settings_page;
$wp_settings_page->output();
}
function update_text_value($field_obj, $input_value) {
// Do stuff or things...
// Optional, return altered input value.
// Return null to leave it as it is
return $input_value;
}
----------------------------------
Output Sections:
Output sections can be used to output custom HTML in the end of a settings page. Each output section is a callback function
that will be called after the settings sections in the order they where added. If you want to input custom form elements, you
need to store them by your self using the "wps_before_update" action.
----------------------------------
use \FeedMeAStrayCat\WPSettings_1_7_0\WPSettingsPage;
if (!class_exists('\FeedMeAStrayCat\WPSettings_1_7_0\WPSettings')) {
require_once('/path/to/wpsettings.php');
}
add_action('admin_menu', 'my_admin_menu');
// This will contain the global WPSettingsPage object
global $wp_settings_page;
$wp_settings_page = null;
function my_admin_menu() {
global $wp_settings_page;
// Create a settings page
$wp_settings_page = new WPSettingsPage('My page title', 'Subtitle', 'My menu title', 'manage_options', 'my_unique_slug', 'my_admin_page_output', 'icon-url.png', $position=100);
// Adds a config section
$section = $wp_settings_page->addSettingsSection('first_section', 'The first section', 'This is the first section');
// Adds a text input
$field = $section->addField('test_value', 'Test value', 'text', 'my_options[test]', 'Default value', 'Prefixed help text');
// Adds custom html in a output sections
$section = $wp_settings_page->addOutputSection('html_section', 'output_my_html_section', 'Optional Headline');
// Activate settings
$wp_settings_page->activateSettings();
}
function my_admin_page_output() {
global $wp_settings_page;
$wp_settings_page->output();
}
function output_my_html_section() {
?>
<p>Some custom HTML here...</p>
<?php
}
----------------------------------
Adding custom style and attributes:
You can set custom style and attribute using $field->setAttribute() and $field->setStyle(). The value you set should be an
array of associative arrays. Even if you only have one don't add multiple fields in one go as in the example below.
It can also be done one attribute or style at a time using $field->addAttribute() or $field->addStyle() where the first two
parameters are the attribute/style name and value and the third parameter is the index for which field to set it to.
Attributes can also be set directly into $section->addField() as the 9th parameter and styles as the 10th.
----------------------------------
use \FeedMeAStrayCat\WPSettings_1_9_1\WPSettingsPage;
if (!class_exists('\FeedMeAStrayCat\WPSettings_1_9_1\WPSettings')) {
require_once('/path/to/wpsettings.php');
}
add_action('admin_menu', 'my_admin_menu');
// This will contain the global WPSettingsPage object
global $wp_settings_page;
$wp_settings_page = null;
function my_admin_menu() {
global $wp_settings_page;
// Create a settings page
$wp_settings_page = new WPSettingsPage('My page title', 'Subtitle', 'My menu title', 'manage_options', 'my_unique_slug', 'my_admin_page_output', 'icon-url.png', $position=100);
// Adds a config section
$section = $wp_settings_page->addSettingsSection('first_section', 'The first section', 'This is the first section');
// Adds a text input
$field = $section->addField('test_value', 'Test', 'text', array('my_options[test]', 'my_options[test2]'));
$field->setAttributes(array(array('readonly' => 'readonly'), array('maxlength' => 10));
$field->setStyle(array(array('wifth' => '200px'), array('width' => '300px'));
// Can also be done like this:
$field = $section->addField('test_value2', 'Test 2', 'text', array('my_options[test3]', 'my_options[test4]'));
$field->addAttribute('readonly', 'readonly', 0);
$field->addAttribute('maxlength', '10', 1);
$field->addStyle('width', '200px', 0);
$field->addStyle('width', '300px', 1);
// Or for only one value
$field = $section->addField('test_value3', 'Test ', 'text', 'my_options[test5]');
$field->addAttribute('readonly', 'readonly');
$field->addAttribute('maxlength', '10');
$field->addStyle('width', '200px');
$field->addStyle('border', '1px solid red');
// Activate settings
$wp_settings_page->activateSettings();
}
function my_admin_page_output() {
global $wp_settings_page;
$wp_settings_page->output();
}
----------------------------------
FIELD TYPES
These are the types that can be used in addField() (the third parameter)
"text"
A standard text input type. Unsanitized.
"textarea"
A textarea input type. Unsanitized. Set size with $field->setSize(int $width, int $height)
"wysiwyg"
A What You See Is What You Get editor using the built in wp_editor() function. Unsanitized. Set settings args with $field->setSettings()
"url"
A URL text. Sanitized with esc_url()
"int"
A integer. Sanitized with (int)
"checkbox"
A checkbox, sanitizes to save 1 or 0
"dropdown"
A select type dropdown. Unsanitized.
"radio"
A set of radio options. Unsanitized.
"hex_color"
A HTML hex color value. Sanitize with allowed hex valued colors.
PAGE TYPES
Stand alone - Using $page = new WPSettingsPage() you can create a stand alone page that can contains sub pages
using $page->addSubPage().
Sub page to Theme section - Use WPSettingsThemePage.
Sub page to Dashboard page - Use WPSettingsDashboardPage.
Sub page to Posts page - Use WPSettingsPostsPage.
Sub page to Media page - Use WPSettingsMediaPage.
Sub page to Links page - Use WPSettingsLinksPage.
Sub page to Pages page - Use WPSettingsPagesPage.
Sub page to Comments page - Use WPSettingsCommentsPage.
Sub page to Plugins page - Use WPSettingsPluginsPage.
Sub page to Users page - Use WPSettingsUsersPage.
Sub page to Management page - Use WPSettingsManagementPage.
Sub page to Options page - Use WPSettingsOptionsPage.
Note that using $page->addSubPage() on any other page then the stand alone WPSettingsPage() object will throw
an exception.
NETWORK ADMIN
From version 1.9.0 there should be no issues creating a network admin settings page. Settings are stored using
update_site_option() and must therefor be fetched using get_site_option() instead of get_option().
http://codex.wordpress.org/Function_Reference/update_site_option
http://codex.wordpress.org/Function_Reference/get_site_option
FILTERS
These filters are available
FILTER_UPDATE
Parameters: 2
Parameter 1: WPSettingsField object
Parameter 2: Input value
Runs after sanitize, before value is stored in DB. The $field_id is the first parameter sent into addField(). This
parameter must be 1 to 50 characters, a-z (case insensitive), 0-9 or "-" and "_".
Note that this filter runs on all inputs in that field. If you send in multiple fields in an array (like in the
example "Adds three checkboxes") the same filter will run on all.
ACTIONS
These are the custom actions that are thrown by WPSettings which can be used to hook in custom features.
wps_before_update
Parameters: 0
Called after validation. Before update. Note that this action is triggered once for each field.
SETTINGS
WPSettings::$no_footer_text = true/false;
To display, or not display, footer information text on WPSettings created pages.
REQUIREMENTS
1) PHP 5.3 (changed from 5.0 to 5.3 in WPSettings 1.6.4)
2) WordPress 3.x (Tested in 3.2.1 and up, but will most likely work in 3.0 or even 2.7 when the Settings API was added)
TODOS
1) Add more types :)
2) Add html5 style input boxes (as well as some setting to create html or xhtml type inputs)
3) Add more filters and actions
IMPORTANT NOTES
1.9.0 - 2013-11-06
I've noticed that the wps_before_update action was only activated when input names existed, and when it was an
array, because the action was just triggered from WPSettingsPage->sanitize().
The action has been moved to WPSettingsField->sanitize() so it will get triggered on regular input names as well.
This means that it will be triggered once for each added input.
I've also noticed that there is no way to only use output settings and store stuff using the regular WPSettings
form. You have to do a output setting that contains the form it self. Or just add some setting through WPSetting
and the specials through a output section.
WPSettings can now also create network admin pages. Fields are stored using update_site_option().
1.7.0 - 2013-01-01
In WordPress 3.5 it seams like a change was made on ajax calls where the admin_menu action isn't triggered which
would cause problems with media upload if you follow the old examples using admin_menu to setup the WPSettingsPage
object and admin_init to register the settings page fields.
The easiest solution is to only use the admin_menu action and setup everything on that action. Another way would
be to make sure that your $wp_settings_page variable is an object before moving on in admin_init.
The examples have been updated to reflect this in 1.7.0.
VERSION HISTORY
1.9.1
Fixed dropdown to work with multiple attribute set (uses in_array() to test value instead of string == compare)
Removed esc_sql() sanitization. Both update_option() and update_site_option() expect unsanitized data and esc_sql() can cause issues.
1.9.0
Changes to wps_before_update action, will now trigger once on each added field
Settings pages are now also functional on network admin pages
Added action to correctly enqueue jquery on admin pages
Replaced deprecated $wpdb->escape() with esc_sql()
Added $field->setCurrentValue()
Added $field->setHelpText()
Added $field->setPlaceholder()
Added $field->setDescription()
Added $field->setAttributes()
Added $field->addAttribute()
Added $field->setStyle()
Added $field->addStyle()
Input fields (not checkbox, radio buttons or the wysiwyg) can have added attributes and custom style
1.8.1
Removed &$this pass by reference (deprecated)
Bugfix. Couldn't use only output sections.
Only output form if there are any settings sections.
1.8.0
Added the possibility to create subpages to the available sections using the objects WPSettingsThemePage,
WPSettingsDashboardPage, WPSettingsPostsPage, WPSettingsMediaPage, WPSettingsLinksPage, WPSettingsPagesPage,
WPSettingsCommentsPage, WPSettingsPluginsPage, WPSettingsUsersPage, WPSettingsManagementPage and
WPSettingsOptionsPage.
1.7.0
Fixed div container width on output regular text field
Added "textare" as field type. Set size using $field->setSize(int $width, int $height).
Added "wysiwyg" as field type. Set settings using $field->setSettings(array $settings)
Changed examples due to changes in WP 3.5 where admin_menu action isn't triggered (I think) on ajax calls which
created an error with media uploads site wide.
1.6.11
Bugfix. Had two places with short php open tags (just <? without "php") as well as missing the "echo".
1.6.10
Added $description as 8th parameter in $field = $section->addField(). Will output a <p class="description"> tag below
the field HTML. (Can, like Headline, Type, InputName, CurrentValue, HelpText and Placeholder be set using
$field->Description = "Foo Bar" because of the magic __set() funciton).
Updated the magic __set() function to always call setX() functions, if they exists, before just setting the value.
Bugfix in activateSettings() which caused subpage forms not submit correctly.
Changed some bas usages of esc_attr_e() to esc_attr()
Added text domain
1.6.9
Removed redundant class_exist check. You should do a class exist like in the examples. :)
Changed bad nameing habit of mine where i use double underscore ("__") as a prefix to private methods/vars. Changed
to single underscore ("_").
1.6.8
Added $placeholder as 7th optional parameter in $section->addField() which is used as placeholder-attribute in
text fields (for example "text" and "url" field type).
1.6.7
Changed how "checkbox" is output by adding a hidden field that is changed to "1" or "0" depending on the checkbox.
It's changed using jQuery (which is required and enqueued when a WPSettingsPage is constructed) and the .change()
event. This way a checkbox is stored as "1" or "0". Not just "1" when it's clicked and not at all when it's "0".
1.6.6
Moved Field sanitize from WPSettingsPage->sanitize() to WPSettingsField->sanitize() and fixed how
register_setting() is called in WPSettingsPage->activateSettings(). This fixes a bug that prevented settings name,
that wasn't part of an array (ex my_settings[name]), to be stored correctly. Settings now registers ones per
name (which must be unique) as well as one per "array name" ("my_settings" from example my_settings[name]).
Array names registers with WPSettingsPage->sanitize() which loops through and calles WPSettingsField->sanitize()
once per field. On the fields that has that specific array name.
Throws an exception when adding fields without a unique name.
Fixed namespace error when throwing Exceptions.
1.6.5
Removed width on container divs for output of dropdowns
1.6.4
Now requires PHP 5.3
WPSettings now is available from namespace FeedMeAStrayCat\WPSettings_X_X_X\ (see first note about namespaces).
Added footer text "Created with WPSettings X.X.X" to admin footer (on pages created with WPSettings). Can be
disabled by setting WPSettings::$no_footer_text to true.
Removed WP_SETTINGS_VERSION (added in 1.6.2) since it's not needed now with the namespace.
1.6.3
New type: "hex_color"
1.6.2
WPSettings now make sure a constant exists called WP_SETTINGS_VERSION. This will contain the version number
of the current loaded WPSettings. If two versions are loaded. The first loaded version number will be in the
const. If WPSettings is loaded, but no WP_SETTINGS_VERSION is found, it is set as 1.0. With this you can
make sure that the latest is loaded, and output an error message if it's not. If multiple WPSettings are
loaded it can still cause some problem, since you need to make sure that the first one loaded is the version
you need. Not sure how to fix that. Now you can see which version is loaded anyway. :)
1.6.1
Added Output Sections (see how to).
Fixed a small error in the how to examples.
Added action "wps_before_update".
Bug fix on FILTER_UPDATE.
1.6
Added validations of the id and field id in addSettingsSection() and addField(). These ids must be 1 to 50
characters, a-z (case insensitive), 0-9 or "-" and "_". The functions will throw an exception if the id
fails the validation.
Added filters function (see how to).
Added filter FILTER_UPDATE.
Had misspelled activateSettings() as activeteSettings() ... Since start. :-| Both works now. Misspelled is
deprecated and might be removed in future releases.
1.5.2
Wrap eeeverything within a class_exists() check to make sure the code isn't included twice through
different files, and by that causes trouble.
1.5.1
Bugfix set default position to null instead of 100. If there is two pages on 100 only one will show. But if
you just use null they will show in the bottom. After each other.
1.5
Added $wp_settings_page->setIcon($icon_id, $add_classes) which can be used to change the HTML id and class
of the settings page icon. Togheter with some css it can be used to change the icon. (WPSettings currently
doesn't create the css required). See the simple example.
1.4.1
Bugfix for subpage settings not beeing saved correct.
1.4
Added the possibility to add subpages to a settings page using $wp_settings_page->addSubPage(). See how to.
Changed a bit on page title and subtitle. On setting page it writes it "Title" if only title is given and
"Title — Subtitle" if both is given.
Changed so a settings form is only outputed if at least one section has been added via addSettingsSection().
This way a settings page can be created and default content can be put into it.
1.3
Added type: radio (see how to)
Added update message to settings page
1.2
Added type: selectbox (see how to)
1.1
Added types: url, int, checkbox
1.0
A first simple version to handle just text values.
LICENSE - MIT
http://en.wikipedia.org/wiki/MIT_License
Copyright (C) 2011 by David Mårtensson <david.martensson@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*************************************/
// Add action to enqueue jQuery
add_action('admin_enqueue_scripts', array('\FeedMeAStrayCat\WPSettings_1_9_1\WPSettingsPage', 'admin_enqueue_scripts'));
// Add action for Network Admin page edits
add_action('network_admin_edit_wps', array('\FeedMeAStrayCat\WPSettings_1_9_1\WPSettingsPage', 'network_admin_edit'));
/**
* WP Settings base class - Extended by WPSettingsPage, WPSettingsSection and WPSettingsField
*/
class WPSettings {
// Version constant
const VERSION = "1.9.1";
/**
* Keeps all input names to make sure that they are unique
* Access is protected because it's only used internally by WPSettingsField->addField()
* @var array
* @static
* @access protected
*/
protected static $_input_names = array();
/**
* Override to true to remove footer text
* @var bool
*/
public static $no_footer_text = false;
/**
* Magic get function, gets method first if exists, or property
* @param string $name
* @return mixed
* @throws Exception
*/
public function __get($name) {
if (method_exists($this, $name)) {
return $this->$name();
}
elseIf (isset($this->$name)) {
return $this->$name;
}
else {
// isset is false on null parameters, this "fixes" that checking if tha parameter truely doesn't exist
$props = get_object_vars($this);
if (array_key_exists($name, $props)) {
return $this->$name;
}
else {
throw new \Exception("Undefined method or property ".$name);
}
}
}
/**
* Magic set function
* @param string $name
* @param mixed $value
* @return void
*/
public function __set($name, $value) {
$method = "set{$name}";
if (method_exists($this, $method)) {
$this->$method($value);
}
elseIf (isset($this->$name)) {
$this->$name = $value;
}
else {
// isset is false on null parameters, this "fixes" that checking if tha parameter truely doesn't exist
$props = get_object_vars($this);
if (array_key_exists($name, $props)) {
$this->$name = $value;
}
else {
throw new \Exception("Failed to set \"".$name."\".");
}
}
}
}
/**
* WP Settings Page class
* @see WPSettings
*/
class WPSettingsPage extends WPSettings {
public $Id;
public $IsStandalonePage = true;
protected $Title;
protected $Subtitle;
protected $SettingsPageDescription;
protected $Sections = array();
protected $OutputSections = array();
protected $MenuSlug;
private $_subpages = array();
private $_pageIconClass = array();
private $_pageIconId;
protected static $RegisteredInputNames = array();
/**
* Create a WP Settings Page
* @todo Allow both menu page and options page?
* @param string $page_title
* @param string $page_subtitle
* @param string $menu_title
* @param string $capability
* @param string $menu_slug
* @param string|array $function
* @param string $icon_url Optional
* @param int|null $position Optional
* @return WPSettingsPage
*/
public function __construct($page_title, $page_subtitle, $menu_title, $capability, $menu_slug, $function, $icon_url='', $position=null) {
$this->Id = $menu_slug;
$this->Title = $page_title;
$this->Subtitle = $page_subtitle;
$this->MenuSlug = $menu_slug;
if ($this->IsStandalonePage) {
add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position);
}
return $this;
}
/**
* Add a sub page
* @param string $page_title
* @param string $page_subtitle
* @param string $menu_title
* @param string $capability
* @param string $menu_slug
* @param string|array $function
* @return WPSettingsPage
*/
public function addSubPage($page_title, $page_subtitle, $menu_title, $capability, $menu_slug, $function) {
// Don't allow on anything but stand alone pages
if (!$this->IsStandalonePage) {
throw new \Exception("Sub pages can not be added to this page type.");
}
// Create sub page as.
$subpage = new WPSettingsSubPage($this, $page_title, $page_subtitle, $menu_title, $capability, $menu_slug, $function);
// Store in this (parent) page array
$this->_subpages[$subpage->Id] = &$subpage;
return $subpage;
}
/**
* Activate settings. Is required to be run after all sections and fields has been added to register the settings so that
* WordPress saves the data
*/
public function activateSettings() {
// Store all registered input names (used by network admin page save)
$registered_input_names = array();
// Start looping through all pages
$pages = array_merge(array($this), $this->_subpages);
foreach ($pages AS $index => $page) {
// Get all uniques post names on array type names (ex my_setting[name])
$array_post_names = array();
// - Start looping through section
foreach ($page->Sections AS $index => $section) {
// - Start looping through each field in section
foreach ($section->Fields AS $index2 => $field) {
// - Start looping through each input name in this field (most often only 1)
foreach ($field->InputName AS $index3 => $input_name) {
// Part of an array name, ex: my_settings[name]
// These registers as one setting for "my_settings", even if there exist my_settings[name]
// and my_settings[name2]. Registers once per $page (in first loop here).
if (strpos($input_name, "[") !== false) {
$temp = explode("[", $input_name);
$name = $temp[0];
$array_post_names[] = $name;
}
// Is it's own name, can only work when the name is unique, registers the setting directly
// with sanitize on the $field object
else {
$registered_input_names[] = $input_name;
register_setting($page->Id, $input_name);
}
}
}
}
// Got any array post names?
if (count($array_post_names) > 0) {
// Get unique names
$array_post_names = array_unique($array_post_names);
// Register them for sanitize on the $page object
foreach ($array_post_names AS $index => $name) {
$registered_input_names[] = $name;
register_setting($page->Id, $name, array($page, 'sanitize'));
}
}
}
self::$RegisteredInputNames[$this->Id] = $registered_input_names;
}
/**
* Had misspelled activate as activete from beta to 1.5.2... :-|
* @deprecated
* @see WPSettingsPage::activateSettings()
*/
public function activeteSettings() {
$this->activateSettings();
}
/**
* Output the settings page
* @param string $subpage
*/
public function output($subpage='') {
// Output a subpage (call that objects output() function)
if ($subpage && isset($this->_subpages[$subpage]) && is_object($this->_subpages[$subpage])) {
$this->_subpages[$subpage]->output();
}
// Output this object page
else {
$this->_output();
}
}
/**
* Output settings page footer (added through action: admin_footer_text)
* Enter description here ...
* @param unknown_type $footer_text
*/
public function outputFooterText($footer_text) {
// Remove action
remove_action('admin_footer_text', array($this, 'outputFooterText'));
// Append and return footer text
$footer_text .= " | ".sprintf(__('Settings page created with <a href="%s">WPSettings %s</a>', 'wpsettings'), 'https://github.com/feedmeastraycat/WPSettings', WPSettings::VERSION);
return $footer_text;
}
/**
* The actual output of this objects page
*/
private function _output() {
// Add action for footer text
if (!$this::$no_footer_text) {
add_action('admin_footer_text', array($this, 'outputFooterText'), 50, 1);
}
// Form action url depending on network or regular admin page
$screen = get_current_screen();
$form_action = ($screen->is_network ? add_query_arg(array('action' => 'wps', 'id' => $this->Id), network_admin_url('edit.php')):admin_url('options.php'));
// Output page
?>
<div class="wrap">
<?php $this->_getIcon(); ?>
<h2><?php echo $this->Title ?><?php echo ($this->Title && $this->Subtitle ? " — ".$this->Subtitle:"") ?></h2>
<?php if( isset($_GET['settings-updated']) ) : ?>
<div id="message" class="updated">
<p><strong><?php _e('Settings saved.', 'wpsettings') ?></strong></p>
</div>
<?php endif; ?>
<?php if ($this->SettingsPageDescription) : ?>
<p><?php echo $this->SettingsPageDescription ?></p>
<?php endif; ?>
<?php if ( !empty($this->Sections) || count($this->OutputSections) > 0 ): ?>
<?php if ( !empty($this->Sections) ) : ?>
<form action="<?php echo $form_action ?>" method="post">
<?php settings_fields($this->Id); ?>
<?php do_settings_sections($this->Id); ?>
<?php endif; ?>
<?php
if (count($this->OutputSections) > 0) {
foreach ($this->OutputSections AS $index => $section) {
if (!empty($section['headline'])) {
?>
<h3><?php echo $section['headline'] ?></h3>
<?php
}
call_user_func($section['callback']);
}
}
if ( !empty($this->Sections) ) :
?>
<p class="submit">
<input name="Submit" type="submit" class="button-primary" value="<?php esc_attr_e('Save Changes', 'wpsettings'); ?>" >
</p>
</form>
<?php
endif;
?>
<?php endif; ?>
</div>
<?php
}
/**
* Sanitize data before it's stored in the databse. This sanitize function is registered when there are array post
* names. For example if the names on three fields are my_settings[name1], my_settings[name2] and other_setting.
* This function will be used to sanitize "my_settings" and $input will be an array containing the values.
* But "other_setting" will be santized directly by the field object sanitize() function (which gets called
* by this function, in the loop, as well).
* @param array $input
*/
public function sanitize($input) {
// Create new input
$new_input = array();
// Loop through sections
foreach ($this->Sections AS $section_index => $section) {
// Loop through fields in section
foreach ($section->Fields AS $field_index => $field) {
// Input name is a loop as well. Even though they all are the same type
foreach ($field->InputName AS $input_index => $input_name) {
// Get name
if (strpos($input_name, "[") !== false) {
// Get name from input name
$temp = explode("[", $input_name);
$name = str_replace("]", "", $temp[1]);
// Isn't a part of this input
if (!isset($input[$name])) {
continue;
}
// Get input
$_input = $input[$name];
}
// Has nothing to do here
else {
continue;
}
// Sanitize on the field
$new_input[$name] = $field->sanitize($_input);
}
}
}
return $new_input;
}
/**
* Add a new section
* @param string $id
* @param string $headline
* @param string $description Optional
* @return WPSettingsSection
* @throws Exception
*/
public function addSettingsSection($id, $headline, $description='') {
if (!preg_match("/^[a-z0-9\-\_]{1,50}$/i", $id)) {
throw new \Exception("Section id failed to validate");
}
$section = new WPSettingsSection($this, $id, $headline, $description);
$this->Sections[] = &$section;
return $section;
}
/**
* Add output section
* @param string $id