WP-PageNavi - Version 2.83

Version Description

  • added 'echo' parameter
  • added Estonian and Bengali translations
  • updated scbFramework
Download this release

Release Info

Developer scribu
Plugin Icon WP-PageNavi
Version 2.83
Comparing to
See all releases

Code changes from version 2.82 to 2.83

core.php CHANGED
@@ -22,7 +22,8 @@ function wp_pagenavi( $args = array() ) {
22
  'after' => '',
23
  'options' => array(),
24
  'query' => $GLOBALS['wp_query'],
25
- 'type' => 'posts'
 
26
  ) );
27
 
28
  extract( $args, EXTR_SKIP );
@@ -172,7 +173,12 @@ function wp_pagenavi( $args = array() ) {
172
  }
173
  $out = $before . "<div class='wp-pagenavi'>\n$out\n</div>" . $after;
174
 
175
- echo apply_filters( 'wp_pagenavi', $out );
 
 
 
 
 
176
  }
177
 
178
 
@@ -260,13 +266,13 @@ function wp_pagenavi_dropdown() {
260
  class PageNavi_Core {
261
  static $options;
262
 
263
- function init( $options ) {
264
  self::$options = $options;
265
 
266
  add_action( 'wp_print_styles', array( __CLASS__, 'stylesheets' ) );
267
  }
268
 
269
- function stylesheets() {
270
  if ( !self::$options->use_pagenavi_css )
271
  return;
272
 
22
  'after' => '',
23
  'options' => array(),
24
  'query' => $GLOBALS['wp_query'],
25
+ 'type' => 'posts',
26
+ 'echo' => true
27
  ) );
28
 
29
  extract( $args, EXTR_SKIP );
173
  }
174
  $out = $before . "<div class='wp-pagenavi'>\n$out\n</div>" . $after;
175
 
176
+ $out = apply_filters( 'wp_pagenavi', $out );
177
+
178
+ if ( !$echo )
179
+ return $out;
180
+
181
+ echo $out;
182
  }
183
 
184
 
266
  class PageNavi_Core {
267
  static $options;
268
 
269
+ static function init( $options ) {
270
  self::$options = $options;
271
 
272
  add_action( 'wp_print_styles', array( __CLASS__, 'stylesheets' ) );
273
  }
274
 
275
+ static function stylesheets() {
276
  if ( !self::$options->use_pagenavi_css )
277
  return;
278
 
lang/wp-pagenavi-bn_BD.mo ADDED
Binary file
lang/wp-pagenavi-bn_BD.po ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: WP-PageNavi\n"
4
+ "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: 2009-07-04 01:44+0300\n"
6
+ "PO-Revision-Date: 2012-06-16 12:34+0600\n"
7
+ "Last-Translator: Mehdi Akram <mehdi.akram@gmail.com>\n"
8
+ "Language-Team: Marcis G. <by.marcis@gmail.com>\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Poedit-Language: Belarusian\n"
13
+ "X-Poedit-Country: BELARUS\n"
14
+ "X-Poedit-KeywordsList: __;_e\n"
15
+ "X-Poedit-Basepath: .\n"
16
+ "X-Poedit-SourceCharset: utf-8\n"
17
+ "X-Poedit-SearchPath-0: .\n"
18
+
19
+ #: pagenavi-options.php:48
20
+ #: pagenavi-options.php:110
21
+ #: pagenavi-options.php:174
22
+ msgid "Page Navigation Options"
23
+ msgstr "পেজ নেভিগেশন অপশন"
24
+
25
+ #: pagenavi-options.php:53
26
+ msgid "Updated"
27
+ msgstr "হালনাগাতকৃত"
28
+
29
+ #: pagenavi-options.php:58
30
+ msgid "No Page Navigation Option Updated"
31
+ msgstr "কোন পেজ নেভিগেশন হালনাগাত হয়নি"
32
+
33
+ #: pagenavi-options.php:64
34
+ #: pagenavi-options.php:265
35
+ msgid "UNINSTALL WP-PageNavi"
36
+ msgstr "আনইনস্টল WP-PageNavi"
37
+
38
+ #: pagenavi-options.php:72
39
+ #, php-format
40
+ msgid "Setting Key '%s' has been deleted."
41
+ msgstr "সেটিং কী '%s' ডিলিট করা হয়েছে।"
42
+
43
+ #: pagenavi-options.php:76
44
+ #, php-format
45
+ msgid "Error deleting Setting Key '%s'."
46
+ msgstr "সেটিং কী '%s' ডিলিটে ত্রুটি।"
47
+
48
+ #: pagenavi-options.php:98
49
+ #: pagenavi-options.php:233
50
+ msgid "Uninstall WP-PageNavi"
51
+ msgstr "আনইনস্টল WP-PageNavi"
52
+
53
+ #: pagenavi-options.php:99
54
+ #, php-format
55
+ msgid "<a href=\"%s\">Click Here</a> To Finish The Uninstallation And WP-PageNavi Will Be Deactivated Automatically."
56
+ msgstr "<a href=\"%s\">ক্লিক করুন</a> সয়ংক্রিয়ভাবে WP-PageNavi নিষ্কিয় এবং আনইনষ্টল হবে।"
57
+
58
+ #: pagenavi-options.php:111
59
+ msgid "Page Navigation Text"
60
+ msgstr "পেজ নেভিগেশন টেক্সট"
61
+
62
+ #: pagenavi-options.php:114
63
+ msgid "Text For Number Of Pages"
64
+ msgstr "পেজ নম্বরের টেক্সট"
65
+
66
+ #: pagenavi-options.php:117
67
+ msgid "The current page number."
68
+ msgstr "চলতি পেজ নম্বর।"
69
+
70
+ #: pagenavi-options.php:118
71
+ #: pagenavi-options.php:139
72
+ #: pagenavi-options.php:146
73
+ msgid "The total number of pages."
74
+ msgstr "মোট পেজ নম্বর।"
75
+
76
+ #: pagenavi-options.php:122
77
+ msgid "Text For Current Page"
78
+ msgstr "চলতি পেজের টেক্সট"
79
+
80
+ #: pagenavi-options.php:125
81
+ #: pagenavi-options.php:132
82
+ msgid "The page number."
83
+ msgstr "পেজ নম্বর।"
84
+
85
+ #: pagenavi-options.php:129
86
+ msgid "Text For Page"
87
+ msgstr "পেজের টেক্সট"
88
+
89
+ #: pagenavi-options.php:136
90
+ msgid "Text For First Post"
91
+ msgstr "প্রথম পোষ্টের টেক্সট"
92
+
93
+ #: pagenavi-options.php:143
94
+ msgid "Text For Last Post"
95
+ msgstr "শেষ পোষ্টের টেক্সট"
96
+
97
+ #: pagenavi-options.php:150
98
+ msgid "Text For Next Post"
99
+ msgstr "পরবর্তী পোষ্টের টেক্সট"
100
+
101
+ #: pagenavi-options.php:156
102
+ msgid "Text For Previous Post"
103
+ msgstr "পূর্বের পেজের টেক্সট"
104
+
105
+ #: pagenavi-options.php:162
106
+ msgid "Text For Next ..."
107
+ msgstr "পরবর্তীর জন্য টেক্সট..."
108
+
109
+ #: pagenavi-options.php:168
110
+ msgid "Text For Previous ..."
111
+ msgstr "পূর্বের জন্য টেক্সট..."
112
+
113
+ #: pagenavi-options.php:177
114
+ msgid "Page Navigation Style"
115
+ msgstr "পেজ নেভিগেশন স্টাইল"
116
+
117
+ #: pagenavi-options.php:180
118
+ msgid "Normal"
119
+ msgstr "সাধারণ"
120
+
121
+ #: pagenavi-options.php:181
122
+ msgid "Drop Down List"
123
+ msgstr "ড্রপ-ডাউন তালিকা"
124
+
125
+ #: pagenavi-options.php:186
126
+ msgid "Number Of Pages To Show?"
127
+ msgstr "কত পেজ দেখাবে?"
128
+
129
+ #: pagenavi-options.php:192
130
+ msgid "Always Show Page Navigation?"
131
+ msgstr "সবসময় পেজ নেভিগেশন দেখাবে?"
132
+
133
+ #: pagenavi-options.php:195
134
+ #: pagenavi-options.php:264
135
+ msgid "Yes"
136
+ msgstr "হ্যা"
137
+
138
+ #: pagenavi-options.php:196
139
+ msgid "No"
140
+ msgstr "না"
141
+
142
+ #: pagenavi-options.php:201
143
+ msgid "Number Of Larger Page Numbers To Show?"
144
+ msgstr "বড় পেজের ক্ষেত্রে কতগুলো নম্বর দেখাবে?"
145
+
146
+ #: pagenavi-options.php:205
147
+ msgid "Larger page numbers are in additional to the default page numbers. It is useful for authors who is paginating through many posts."
148
+ msgstr "বড় পেজ নম্বরগুলো ডিফল্ট পেজ নম্বেরের জন্য অতিরিক্ত। এটা লেখেকের জন্য যে অনেক পোষ্টের নম্বর দেয়।"
149
+
150
+ #: pagenavi-options.php:207
151
+ msgid "For example, WP-PageNavi will display: Pages 1, 2, 3, 4, 5, 10, 20, 30, 40, 50"
152
+ msgstr "উদাহারণ, WP-PageNavi দেখাবে: পেজ ১, ২, ৩, ৪, ৫, ১০, ২০, ৩০, ৪০, ৫০"
153
+
154
+ #: pagenavi-options.php:209
155
+ msgid "Enter 0 to disable."
156
+ msgstr "ডিজেবলের জন্য ০ টাপুন।"
157
+
158
+ #: pagenavi-options.php:213
159
+ msgid "Show Larger Page Numbers In Multiples Of:"
160
+ msgstr "অধিকের মধ্যে বড় পেজ নম্বর দেখাও:"
161
+
162
+ #: pagenavi-options.php:217
163
+ msgid "If mutiple is in 5, it will show: 5, 10, 15, 20, 25"
164
+ msgstr "যদি ৫ এর অধিক হয়, তাহলে দেখাবে: ৫, ১০, ১৫, ২০, ২৫"
165
+
166
+ #: pagenavi-options.php:219
167
+ msgid "If mutiple is in 10, it will show: 10, 20, 30, 40, 50"
168
+ msgstr "যদি ১০ এর একাধিক তাহলে দেখাবে: ১০, ২০, ৩০, ৪০, ৫০"
169
+
170
+ #: pagenavi-options.php:224
171
+ msgid "Save Changes"
172
+ msgstr "পরিবর্তন সংরক্ষণ করুন"
173
+
174
+ #: pagenavi-options.php:235
175
+ msgid "Deactivating WP-PageNavi plugin does not remove any data that may have been created, such as the page navigation options. To completely remove this plugin, you can uninstall it here."
176
+ msgstr "WP-PageNav প্লাগইনটি নিষ্ক্রয় করলে এর তথ্যগুলো মুছবে না যা পেজ নেভিগেশন অপশনে তৈরী হয়েছে। সম্পূর্ণভাবে প্লাগইনটি মুছে ফেলতে এখান থেকে আনইনষ্টল করুন।"
177
+
178
+ #: pagenavi-options.php:238
179
+ msgid "WARNING:"
180
+ msgstr "সতর্কতা:"
181
+
182
+ #: pagenavi-options.php:239
183
+ msgid "Once uninstalled, this cannot be undone. You should use a Database Backup plugin of WordPress to back up all the data first."
184
+ msgstr "যদি আনইনষ্টল করেন তাহলে আর ফিরে পাবেন না। আপনার উচিৎ ডাটাবেজ ব্যাকআপ প্লাগইন ব্যবহার করে ওয়ার্ডপ্রেস ব্যাকআপ করা।"
185
+
186
+ #: pagenavi-options.php:242
187
+ msgid "The following WordPress Options will be DELETED:"
188
+ msgstr "ওয়ার্ডপ্রেসের এই অপশনটি মুছে যাবে:"
189
+
190
+ #: pagenavi-options.php:247
191
+ msgid "WordPress Options"
192
+ msgstr "ওয়ার্ডপ্রেস অপশন"
193
+
194
+ #: pagenavi-options.php:265
195
+ msgid ""
196
+ "You Are About To Uninstall WP-PageNavi From WordPress.\\n"
197
+ "This Action Is Not Reversible.\\n"
198
+ "\\n"
199
+ " Choose [Cancel] To Stop, [OK] To Uninstall."
200
+ msgstr ""
201
+ "আপনি WP-PageNavi ওয়ার্ডপেস থেকে আনইনষ্টল করছেন।\\n"
202
+ "এটা আগের অবস্থায় ফিরতে পারবে না।\\n"
203
+ "\\n"
204
+ "বন্ধ করতে [বাতিল] করুন, আনইনষ্টল করতে [ওকে] করুন।"
205
+
206
+ #: wp-pagenavi.php:42
207
+ msgid "PageNavi"
208
+ msgstr "পেজনেভি"
209
+
210
+ #: wp-pagenavi.php:201
211
+ msgid "Page %CURRENT_PAGE% of %TOTAL_PAGES%"
212
+ msgstr "মোট %TOTAL_PAGES% পৃষ্ঠা এর মধ্যে %CURRENT_PAGE%"
213
+
214
+ #: wp-pagenavi.php:204
215
+ msgid "&laquo; First"
216
+ msgstr "&laquo; প্রথম"
217
+
218
+ #: wp-pagenavi.php:205
219
+ msgid "Last &raquo;"
220
+ msgstr "শেষ &raquo;"
221
+
222
+ #: wp-pagenavi.php:206
223
+ msgid "&raquo;"
224
+ msgstr "&raquo;"
225
+
226
+ #: wp-pagenavi.php:207
227
+ msgid "&laquo;"
228
+ msgstr "&laquo;"
229
+
230
+ #: wp-pagenavi.php:208
231
+ #: wp-pagenavi.php:209
232
+ msgid "..."
233
+ msgstr "..."
234
+
readme.txt CHANGED
@@ -1,9 +1,11 @@
1
  === WP-PageNavi ===
2
  Contributors: GamerZ, scribu
3
  Tags: navigation, pagination, paging, pages
4
- Requires at least: 3.1
5
- Tested up to: 3.3
6
- Stable tag: 2.82
 
 
7
 
8
  Adds a more advanced paging navigation interface.
9
 
@@ -15,7 +17,7 @@ Want to replace the old *&larr; Older posts | Newer posts &rarr;* links with som
15
 
16
  This plugin provides the `wp_pagenavi()` template tag which generates fancy pagination links. See the [installation instructions](http://wordpress.org/extend/plugins/wp-pagenavi/installation/) for using it in your theme.
17
 
18
- Links: [Demo](http://lesterchan.net/wordpress/) | [Plugin News](http://scribu.net/wordpress/wp-pagenavi/) | [Translating](http://scribu.net/wordpress/translating-plugins.html)
19
 
20
  == Installation ==
21
 
@@ -24,9 +26,9 @@ You can either install it automatically from the WordPress admin, or do it manua
24
  1. Unzip the archive and put the `wp-pagenavi` folder into your plugins folder (/wp-content/plugins/).
25
  1. Activate the plugin from the Plugins menu.
26
 
27
- = Archives =
28
 
29
- In your theme, you need to find calls to `next_posts_link()` and `previous_posts_link()` and replace them.
30
 
31
  In the Twentyten theme, it looks like this:
32
 
@@ -39,8 +41,6 @@ You would replace those two lines with this:
39
 
40
  `<?php wp_pagenavi(); ?>`
41
 
42
- = Multipart pages =
43
-
44
  For multipart pages, you would look for code like this:
45
 
46
  `<?php wp_link_pages( ... ); ?>`
@@ -90,6 +90,11 @@ You can do that like so:
90
 
91
  == Changelog ==
92
 
 
 
 
 
 
93
  = 2.82 =
94
  * fixed prev/next links not appearing in some conditions
95
  * added Hebrew, Georgian and Azerbaijani translations
1
  === WP-PageNavi ===
2
  Contributors: GamerZ, scribu
3
  Tags: navigation, pagination, paging, pages
4
+ Requires at least: 3.2
5
+ Tested up to: 3.4
6
+ Stable tag: 2.83
7
+ License: GPLv2 or later
8
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
10
  Adds a more advanced paging navigation interface.
11
 
17
 
18
  This plugin provides the `wp_pagenavi()` template tag which generates fancy pagination links. See the [installation instructions](http://wordpress.org/extend/plugins/wp-pagenavi/installation/) for using it in your theme.
19
 
20
+ Links: [Plugin News](http://scribu.net/wordpress/wp-pagenavi/) | [Translating](http://scribu.net/wordpress/translating-plugins.html)
21
 
22
  == Installation ==
23
 
26
  1. Unzip the archive and put the `wp-pagenavi` folder into your plugins folder (/wp-content/plugins/).
27
  1. Activate the plugin from the Plugins menu.
28
 
29
+ = Usage =
30
 
31
+ In your theme, you need to find calls to next_posts_link() and previous_posts_link() and replace them.
32
 
33
  In the Twentyten theme, it looks like this:
34
 
41
 
42
  `<?php wp_pagenavi(); ?>`
43
 
 
 
44
  For multipart pages, you would look for code like this:
45
 
46
  `<?php wp_link_pages( ... ); ?>`
90
 
91
  == Changelog ==
92
 
93
+ = 2.83 =
94
+ * added 'echo' parameter
95
+ * added Estonian and Bengali translations
96
+ * updated scbFramework
97
+
98
  = 2.82 =
99
  * fixed prev/next links not appearing in some conditions
100
  * added Hebrew, Georgian and Azerbaijani translations
scb/AdminPage.php CHANGED
@@ -108,6 +108,13 @@ abstract class scbAdminPage {
108
  // This is where all the page args can be set
109
  function setup(){}
110
 
 
 
 
 
 
 
 
111
  // This is where the css and js go
112
  // Both wp_enqueue_*() and inline code can be added
113
  function page_head(){}
@@ -120,7 +127,7 @@ abstract class scbAdminPage {
120
  function page_header() {
121
  echo "<div class='wrap'>\n";
122
  screen_icon( $this->args['screen_icon'] );
123
- echo "<h2>" . $this->args['page_title'] . "</h2>\n";
124
  }
125
 
126
  // This is where the page content goes
@@ -267,20 +274,6 @@ abstract class scbAdminPage {
267
  return $this->row_wrap( $args['title'], $this->input( $args, $formdata ) );
268
  }
269
 
270
- // Wraps the given content in a <table>
271
- function table_wrap( $content ) {
272
- return
273
- html( 'table class="form-table"', $content );
274
- }
275
-
276
- // Wraps the given content in a <tr><td>
277
- function row_wrap( $title, $content ) {
278
- return
279
- html( 'tr',
280
- html( 'th scope="row"', $title )
281
- .html( 'td', $content ) );
282
- }
283
-
284
  // Mimic scbForms inheritance
285
  function __call( $method, $args ) {
286
  if ( in_array( $method, array( 'input', 'form' ) ) ) {
@@ -296,12 +289,12 @@ abstract class scbAdminPage {
296
 
297
  // Wraps a string in a <script> tag
298
  function js_wrap( $string ) {
299
- return "\n<script type='text/javascript'>\n" . $string . "\n</script>\n";
300
  }
301
 
302
  // Wraps a string in a <style> tag
303
  function css_wrap( $string ) {
304
- return "\n<style type='text/css'>\n" . $string . "\n</style>\n";
305
  }
306
 
307
 
@@ -322,6 +315,8 @@ abstract class scbAdminPage {
322
  if ( ! $this->pagehook )
323
  return;
324
 
 
 
325
  if ( $ajax_submit ) {
326
  $this->ajax_response();
327
  add_action( 'admin_footer', array( $this, 'ajax_submit' ), 20 );
108
  // This is where all the page args can be set
109
  function setup(){}
110
 
111
+ /**
112
+ * Called when the page is loaded, but before any rendering.
113
+ *
114
+ * Useful for calling $screen->add_help_tab() etc.
115
+ */
116
+ function page_loaded() {}
117
+
118
  // This is where the css and js go
119
  // Both wp_enqueue_*() and inline code can be added
120
  function page_head(){}
127
  function page_header() {
128
  echo "<div class='wrap'>\n";
129
  screen_icon( $this->args['screen_icon'] );
130
+ echo html( "h2", $this->args['page_title'] );
131
  }
132
 
133
  // This is where the page content goes
274
  return $this->row_wrap( $args['title'], $this->input( $args, $formdata ) );
275
  }
276
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
  // Mimic scbForms inheritance
278
  function __call( $method, $args ) {
279
  if ( in_array( $method, array( 'input', 'form' ) ) ) {
289
 
290
  // Wraps a string in a <script> tag
291
  function js_wrap( $string ) {
292
+ return html( "script type='text/javascript'", $string );
293
  }
294
 
295
  // Wraps a string in a <style> tag
296
  function css_wrap( $string ) {
297
+ return html( "style type='text/css'", $string );
298
  }
299
 
300
 
315
  if ( ! $this->pagehook )
316
  return;
317
 
318
+ add_action( 'load-' . $this->pagehook, array( $this, 'page_loaded' ) );
319
+
320
  if ( $ajax_submit ) {
321
  $this->ajax_response();
322
  add_action( 'admin_footer', array( $this, 'ajax_submit' ), 20 );
scb/BoxesPage.php CHANGED
@@ -166,8 +166,11 @@ abstract class scbBoxesPage extends scbAdminPage {
166
  ) );
167
 
168
  $registered = array();
169
- foreach( $this->boxes as $box_args ) {
170
- @list( $name, $title, $context, $priority, $args ) = $box_args;
 
 
 
171
 
172
  if ( empty( $title ) )
173
  $title = ucfirst( $name );
166
  ) );
167
 
168
  $registered = array();
169
+ foreach ( $this->boxes as $box_args ) {
170
+ foreach ( array( 'name', 'title', 'context', 'priority', 'args' ) as $i => $arg ) {
171
+ if ( isset( $box_args[$i] ) )
172
+ $$arg = $box_args[$i];
173
+ }
174
 
175
  if ( empty( $title ) )
176
  $title = ucfirst( $name );
scb/Forms.php CHANGED
@@ -6,58 +6,20 @@ class scbForms {
6
 
7
  const TOKEN = '%input%';
8
 
9
- protected static $cur_name;
 
10
 
11
- static function input( $args, $formdata = false ) {
12
- if ( !empty( $formdata ) ) {
13
- $form = new scbForm( $formdata );
14
- return $form->input( $args );
15
- }
16
-
17
- if ( empty( $args['name'] ) ) {
18
- return trigger_error( 'Empty name', E_USER_WARNING );
19
- }
20
-
21
- $args = wp_parse_args( $args, array(
22
- 'desc' => '',
23
- 'desc_pos' => 'after',
24
- 'wrap' => self::TOKEN,
25
- ) );
26
-
27
- if ( isset( $args['value'] ) && is_array( $args['value'] ) ) {
28
- $args['values'] = $args['value'];
29
- unset( $args['value'] );
30
- }
31
-
32
- if ( isset( $args['extra'] ) && !is_array( $args['extra'] ) )
33
- $args['extra'] = shortcode_parse_atts( $args['extra'] );
34
-
35
- self::$cur_name = self::get_name( $args['name'] );
36
-
37
- switch ( $args['type'] ) {
38
- case 'select':
39
- case 'radio':
40
- $input = self::_single_choice( $args );
41
- break;
42
- case 'checkbox':
43
- if ( isset( $args['values'] ) )
44
- $input = self::_multiple_choice( $args );
45
- else
46
- $input = self::_checkbox( $args );
47
- break;
48
- default:
49
- $input = self::_input( $args );
50
- }
51
-
52
- return str_replace( self::TOKEN, $input, $args['wrap'] );
53
  }
54
 
 
 
55
 
56
- // ____________UTILITIES____________
57
-
58
 
59
  // Generates a table wrapped in a form
60
- static function form_table( $rows, $formdata = NULL ) {
61
  $output = '';
62
  foreach ( $rows as $row )
63
  $output .= self::table_row( $row, $formdata );
@@ -68,7 +30,7 @@ class scbForms {
68
  }
69
 
70
  // Generates a form
71
- static function form( $inputs, $formdata = NULL, $nonce ) {
72
  $output = '';
73
  foreach ( $inputs as $input )
74
  $output .= self::input( $input, $formdata );
@@ -79,7 +41,7 @@ class scbForms {
79
  }
80
 
81
  // Generates a table
82
- static function table( $rows, $formdata = NULL ) {
83
  $output = '';
84
  foreach ( $rows as $row )
85
  $output .= self::table_row( $row, $formdata );
@@ -90,7 +52,7 @@ class scbForms {
90
  }
91
 
92
  // Generates a table row
93
- static function table_row( $args, $formdata = NULL ) {
94
  return self::row_wrap( $args['title'], self::input( $args, $formdata ) );
95
  }
96
 
@@ -98,170 +60,315 @@ class scbForms {
98
  // ____________WRAPPERS____________
99
 
100
 
101
- // Wraps the given content in a <form><table>
102
  static function form_table_wrap( $content, $nonce = 'update_options' ) {
103
- $output = self::table_wrap( $content );
104
- $output = self::form_wrap( $output, $nonce );
105
-
106
- return $output;
107
  }
108
 
109
- // Wraps the given content in a <form> tag
110
  static function form_wrap( $content, $nonce = 'update_options' ) {
111
- $output = "\n<form method='post' action=''>\n";
112
- $output .= $content;
113
- $output .= wp_nonce_field( $action = $nonce, $name = "_wpnonce", $referer = true , $echo = false );
114
- $output .= "\n</form>\n";
115
-
116
- return $output;
117
  }
118
 
119
- // Wraps the given content in a <table>
120
  static function table_wrap( $content ) {
121
- $output = "\n<table class='form-table'>\n" . $content . "\n</table>\n";
122
-
123
- return $output;
124
  }
125
 
126
- // Wraps the given content in a <tr><td>
127
  static function row_wrap( $title, $content ) {
128
- return "\n<tr>\n\t<th scope='row'>" . $title . "</th>\n\t<td>\n\t\t" . $content . "\t</td>\n\n</tr>";
 
 
 
129
  }
130
 
131
 
132
  // ____________PRIVATE METHODS____________
133
 
134
 
135
- private static function _single_choice( $args ) {
136
- $args = wp_parse_args( $args, array(
137
- 'numeric' => false, // use numeric array instead of associative
138
- 'selected' => array( 'foo' ), // hack to make default blank
139
- ) );
140
 
141
- self::_expand_values( $args );
142
 
143
- if ( 'select' == $args['type'] )
144
- return self::_select( $args );
145
- else
146
- return self::_radio( $args );
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  }
148
 
149
- private static function _multiple_choice( $args ) {
150
- $args = wp_parse_args( $args, array(
151
- 'numeric' => false, // use numeric array instead of associative
152
- 'checked' => null,
153
- ) );
 
 
 
 
 
 
 
 
154
 
155
- self::$cur_name .= '[]';
 
156
 
157
- self::_expand_values( $args );
 
158
 
159
- extract( $args );
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
- if ( !is_array( $checked ) )
162
- $checked = array();
163
 
164
- $opts = '';
165
- foreach ( $values as $value => $title ) {
166
- if ( empty( $value ) || empty( $title ) )
167
- continue;
168
 
169
- $opts .= self::_checkbox( array(
170
- 'type' => 'checkbox',
171
- 'value' => $value,
172
- 'checked' => in_array( $value, $checked ),
173
- 'desc' => $title,
174
- 'desc_pos' => 'after'
175
- ) );
176
  }
177
 
178
- return self::add_desc( $opts, $desc, $desc_pos );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  }
180
 
181
- private static function _expand_values( &$args ) {
182
- $values =& $args['values'];
 
183
 
184
- if ( !empty( $values ) && !self::is_associative( $values ) ) {
185
- if ( is_array( $args['desc'] ) ) {
186
- $values = array_combine( $values, $args['desc'] ); // back-compat
187
- $args['desc'] = false;
188
- } elseif ( !$args['numeric'] ) {
189
- $values = array_combine( $values, $values );
 
 
 
 
 
 
 
 
 
 
 
190
  }
191
  }
192
  }
193
 
194
- private static function _radio( $args ) {
195
- extract( $args );
196
 
197
- if ( array( 'foo' ) == $selected ) {
198
- // radio buttons should always have one option selected
199
- $selected = key( $values );
 
 
 
 
 
 
200
  }
201
 
202
- $opts = '';
203
- foreach ( $values as $value => $title ) {
204
- if ( empty( $value ) || empty( $title ) )
205
- continue;
206
 
207
- $opts .= self::_checkbox( array(
208
- 'type' => 'radio',
209
- 'value' => $value,
210
- 'checked' => ( (string) $value == (string) $selected ),
211
- 'desc' => $title,
212
- 'desc_pos' => 'after'
213
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  }
215
 
216
- return self::add_desc( $opts, $desc, $desc_pos );
217
  }
 
218
 
219
- private static function _select( $args ) {
220
- extract( wp_parse_args( $args, array(
221
- 'text' => '',
222
- 'extra' => array()
223
- ) ) );
224
 
225
- $options = array();
226
 
227
- if ( false !== $text ) {
228
- $options[] = array(
229
- 'value' => '',
230
- 'selected' => ( $selected == array( 'foo' ) ),
231
- 'title' => $text
232
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  }
234
 
235
- foreach ( $values as $value => $title ) {
236
- if ( empty( $value ) || empty( $title ) )
237
- continue;
 
238
 
239
- $options[] = array(
240
- 'value' => $value,
241
- 'selected' => ( (string) $value == (string) $selected ),
242
- 'title' => $title
243
- );
244
  }
245
 
246
- $opts = '';
247
- foreach ( $options as $option ) {
248
- extract( $option );
249
 
250
- $opts .= html( 'option', compact( 'value', 'selected' ), $title );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  }
 
252
 
253
- $extra['name'] = self::$cur_name;
 
 
254
 
255
- $input = html( 'select', $extra, $opts );
 
 
256
 
257
- return self::add_label( $input, $desc, $desc_pos );
 
258
  }
259
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  // Handle args for a single checkbox or radio input
261
- private static function _checkbox( $args ) {
262
  $args = wp_parse_args( $args, array(
263
  'value' => true,
264
- 'desc' => NULL,
265
  'checked' => false,
266
  'extra' => array(),
267
  ) );
@@ -278,33 +385,15 @@ class scbForms {
278
  return self::_input_gen( $args );
279
  }
280
 
281
- // Handle args for text inputs
282
- private static function _input( $args ) {
283
- $args = wp_parse_args( $args, array(
284
- 'value' => '',
285
- 'desc_pos' => 'after',
286
- 'extra' => array( 'class' => 'regular-text' ),
287
- ) );
288
-
289
- foreach ( $args as $key => &$val )
290
- $$key = &$val;
291
- unset( $val );
292
-
293
- if ( !isset( $extra['id'] ) && !is_array( $name ) && false === strpos( $name, '[' ) )
294
- $extra['id'] = $name;
295
-
296
- return self::_input_gen( $args );
297
- }
298
-
299
  // Generate html with the final args
300
- private static function _input_gen( $args ) {
301
  extract( wp_parse_args( $args, array(
302
- 'value' => NULL,
303
- 'desc' => NULL,
304
  'extra' => array()
305
  ) ) );
306
 
307
- $extra['name'] = self::$cur_name;
308
 
309
  if ( 'textarea' == $type ) {
310
  $input = html( 'textarea', $extra, esc_textarea( $value ) );
@@ -317,11 +406,11 @@ class scbForms {
317
  return self::add_label( $input, $desc, $desc_pos );
318
  }
319
 
320
- private static function add_label( $input, $desc, $desc_pos ) {
321
  return html( 'label', self::add_desc( $input, $desc, $desc_pos ) ) . "\n";
322
  }
323
 
324
- private static function add_desc( $input, $desc, $desc_pos ) {
325
  if ( empty( $desc ) )
326
  return $input;
327
 
@@ -331,154 +420,251 @@ class scbForms {
331
  return $input . ' ' . $desc;
332
  }
333
 
 
 
334
 
335
- // Utilities
 
 
 
 
 
 
 
 
336
 
 
 
 
 
 
337
 
338
- /**
339
- * Generates the proper string for a name attribute.
340
- *
341
- * @param array|string $name The raw name
342
- *
343
- * @return string
344
- */
345
- static function get_name( $name ) {
346
- $name = (array) $name;
347
 
348
- $name_str = array_shift( $name );
349
 
350
- foreach ( $name as $key ) {
351
- $name_str .= '[' . esc_attr( $key ) . ']';
352
- }
353
 
354
- return $name_str;
355
  }
356
 
357
- /**
358
- * Traverses the formdata and retrieves the correct value.
359
- *
360
- * @param array|string $name The name of the value
361
- * @param array $value The data that will be traversed
362
- * @param mixed $fallback The value returned when the key is not found
363
- *
364
- * @return mixed
365
- */
366
- static function get_value( $name, $value, $fallback = null ) {
367
- foreach ( (array) $name as $key ) {
368
- if ( !isset( $value[ $key ] ) )
369
- return $fallback;
370
 
371
- $value = $value[$key];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
  }
373
 
374
- return $value;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
  }
 
376
 
377
- /**
378
- * Given a list of fields, extract the appropriate POST data and return it.
379
- *
380
- * @param array $fields List of args that would be sent to scbForms::input()
381
- * @param array $to_update Existing data to update
382
- *
383
- * @return array
384
- */
385
- static function validate_post_data( $fields, $to_update = array() ) {
386
- foreach ( $fields as $field ) {
387
- $value = scbForms::get_value( $field['name'], $_POST );
388
 
389
- $value = stripslashes_deep( $value );
390
 
391
- switch ( $field['type'] ) {
392
- case 'checkbox':
393
- if ( isset( $field['values'] ) && is_array( $field['values'] ) )
394
- $value = array_intersect( $field['values'], (array) $value );
395
- else
396
- $value = (bool) $value;
397
 
398
- break;
399
- case 'radio':
400
- case 'select':
401
- if ( !isset( $field['values'][ $value ] ) )
402
- continue 2;
403
- }
 
 
 
 
 
 
 
 
 
404
 
405
- self::set_value( $to_update, $field['name'], $value );
406
  }
407
 
408
- return $to_update;
409
  }
 
410
 
411
- private static function set_value( &$arr, $name, $value ) {
412
- $name = (array) $name;
413
 
414
- $final_key = array_pop( $name );
415
 
416
- while ( !empty( $name ) ) {
417
- $key = array_shift( $name );
 
418
 
419
- if ( !isset( $arr[ $key ] ) )
420
- $arr[ $key ] = array();
 
 
 
421
 
422
- $arr =& $arr[ $key ];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
423
  }
424
 
425
- $arr[ $final_key ] = $value;
426
  }
427
 
428
- private static function is_associative( $array ) {
429
- $keys = array_keys( $array );
430
- return array_keys( $keys ) !== $keys;
431
  }
432
  }
433
 
434
- /**
435
- * A wrapper for scbForms, containing the formdata
436
- */
437
- class scbForm {
438
- protected $data = array();
439
- protected $prefix = array();
440
 
441
- function __construct( $data, $prefix = false ) {
442
- if ( is_array( $data ) )
443
- $this->data = $data;
444
 
445
- if ( $prefix )
446
- $this->prefix = (array) $prefix;
447
  }
448
 
449
- function traverse_to( $path ) {
450
- $data = scbForms::get_value( $path, $this->data );
 
 
 
 
 
451
 
452
- $prefix = array_merge( $this->prefix, (array) $path );
 
 
453
 
454
- return new scbForm( $data, $prefix );
 
 
 
 
 
455
  }
456
 
457
- function input( $args ) {
458
- $value = scbForms::get_value( $args['name'], $this->data );
 
 
459
 
460
- if ( !is_null( $value ) ) {
461
- switch ( $args['type'] ) {
462
- case 'select':
463
- case 'radio':
464
- $args['selected'] = $value;
465
- break;
466
- case 'checkbox':
467
- if ( is_array( $value ) )
468
- $args['checked'] = $value;
469
- else
470
- $args['checked'] = ( $value || ( isset( $args['value'] ) && $value == $args['value'] ) );
471
- break;
472
- default:
473
- $args['value'] = $value;
474
- }
475
- }
476
 
477
- if ( !empty( $this->prefix ) ) {
478
- $args['name'] = array_merge( $this->prefix, (array) $args['name'] );
479
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
480
 
481
- return scbForms::input( $args );
 
482
  }
483
  }
484
 
6
 
7
  const TOKEN = '%input%';
8
 
9
+ static function input_with_value( $args, $value ) {
10
+ $field = scbFormField::create( $args );
11
 
12
+ return $field->render( $value );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  }
14
 
15
+ static function input( $args, $formdata = null ) {
16
+ $field = scbFormField::create( $args );
17
 
18
+ return $field->render( scbForms::get_value( $args['name'], $formdata ) );
19
+ }
20
 
21
  // Generates a table wrapped in a form
22
+ static function form_table( $rows, $formdata = null ) {
23
  $output = '';
24
  foreach ( $rows as $row )
25
  $output .= self::table_row( $row, $formdata );
30
  }
31
 
32
  // Generates a form
33
+ static function form( $inputs, $formdata = null, $nonce ) {
34
  $output = '';
35
  foreach ( $inputs as $input )
36
  $output .= self::input( $input, $formdata );
41
  }
42
 
43
  // Generates a table
44
+ static function table( $rows, $formdata = null ) {
45
  $output = '';
46
  foreach ( $rows as $row )
47
  $output .= self::table_row( $row, $formdata );
52
  }
53
 
54
  // Generates a table row
55
+ static function table_row( $args, $formdata = null ) {
56
  return self::row_wrap( $args['title'], self::input( $args, $formdata ) );
57
  }
58
 
60
  // ____________WRAPPERS____________
61
 
62
 
 
63
  static function form_table_wrap( $content, $nonce = 'update_options' ) {
64
+ return self::form_wrap( self::table_wrap( $content ), $nonce );
 
 
 
65
  }
66
 
 
67
  static function form_wrap( $content, $nonce = 'update_options' ) {
68
+ return html( "form method='post' action=''",
69
+ $content,
70
+ wp_nonce_field( $nonce, '_wpnonce', $referer = true, $echo = false )
71
+ );
 
 
72
  }
73
 
 
74
  static function table_wrap( $content ) {
75
+ return html( "table class='form-table'", $content );
 
 
76
  }
77
 
 
78
  static function row_wrap( $title, $content ) {
79
+ return html( "tr",
80
+ html( "th scope='row'", $title ),
81
+ html( "td", $content )
82
+ );
83
  }
84
 
85
 
86
  // ____________PRIVATE METHODS____________
87
 
88
 
89
+ // Utilities
 
 
 
 
90
 
 
91
 
92
+ /**
93
+ * Generates the proper string for a name attribute.
94
+ *
95
+ * @param array|string $name The raw name
96
+ *
97
+ * @return string
98
+ */
99
+ static function get_name( $name ) {
100
+ $name = (array) $name;
101
+
102
+ $name_str = array_shift( $name );
103
+
104
+ foreach ( $name as $key ) {
105
+ $name_str .= '[' . esc_attr( $key ) . ']';
106
+ }
107
+
108
+ return $name_str;
109
  }
110
 
111
+ /**
112
+ * Traverses the formdata and retrieves the correct value.
113
+ *
114
+ * @param array|string $name The name of the value
115
+ * @param array $value The data that will be traversed
116
+ * @param mixed $fallback The value returned when the key is not found
117
+ *
118
+ * @return mixed
119
+ */
120
+ static function get_value( $name, $value, $fallback = null ) {
121
+ foreach ( (array) $name as $key ) {
122
+ if ( !isset( $value[ $key ] ) )
123
+ return $fallback;
124
 
125
+ $value = $value[$key];
126
+ }
127
 
128
+ return $value;
129
+ }
130
 
131
+ /**
132
+ * Given a list of fields, validate some data.
133
+ *
134
+ * @param array $fields List of args that would be sent to scbForms::input()
135
+ * @param array $data The data to validate. Defaults to $_POST
136
+ * @param array $to_update Existing data to populate. Necessary for nested values
137
+ *
138
+ * @return array
139
+ */
140
+ static function validate_post_data( $fields, $data = null, $to_update = array() ) {
141
+ if ( null === $data ) {
142
+ $data = stripslashes_deep( $_POST );
143
+ }
144
 
145
+ foreach ( $fields as $field ) {
146
+ $value = scbForms::get_value( $field['name'], $data );
147
 
148
+ $fieldObj = scbFormField::create( $field );
 
 
 
149
 
150
+ $value = $fieldObj->validate( $value );
151
+
152
+ if ( null !== $value )
153
+ self::set_value( $to_update, $field['name'], $value );
 
 
 
154
  }
155
 
156
+ return $to_update;
157
+ }
158
+
159
+ /**
160
+ * For multiple-choice fields, we can never distinguish between "never been set" and "set to none".
161
+ * For single-choice fields, we can't distinguish either, because of how self::update_meta() works.
162
+ * Therefore, the 'default' parameter is always ignored.
163
+ *
164
+ * @param array $args Field arguments.
165
+ * @param int $object_id The object ID the metadata is attached to
166
+ * @param string $meta_type
167
+ *
168
+ * @return string
169
+ */
170
+ static function input_from_meta( $args, $object_id, $meta_type = 'post' ) {
171
+ $single = ( 'checkbox' != $args['type'] );
172
+
173
+ $key = (array) $args['name'];
174
+ $key = end( $key );
175
+
176
+ $value = get_metadata( $meta_type, $object_id, $key, $single );
177
+
178
+ return self::input_with_value( $args, $value );
179
  }
180
 
181
+ static function update_meta( $fields, $data, $object_id, $meta_type = 'post' ) {
182
+ foreach ( $fields as $field_args ) {
183
+ $key = $field_args['name'];
184
 
185
+ if ( 'checkbox' == $field_args['type'] ) {
186
+ $new_values = isset( $data[$key] ) ? $data[$key] : array();
187
+
188
+ $old_values = get_metadata( $meta_type, $object_id, $key );
189
+
190
+ foreach ( array_diff( $new_values, $old_values ) as $value )
191
+ add_metadata( $meta_type, $object_id, $key, $value );
192
+
193
+ foreach ( array_diff( $old_values, $new_values ) as $value )
194
+ delete_metadata( $meta_type, $object_id, $key, $value );
195
+ } else {
196
+ $value = $data[$key];
197
+
198
+ if ( '' === $value )
199
+ delete_metadata( $meta_type, $object_id, $key );
200
+ else
201
+ update_metadata( $meta_type, $object_id, $key, $value );
202
  }
203
  }
204
  }
205
 
206
+ private static function set_value( &$arr, $name, $value ) {
207
+ $name = (array) $name;
208
 
209
+ $final_key = array_pop( $name );
210
+
211
+ while ( !empty( $name ) ) {
212
+ $key = array_shift( $name );
213
+
214
+ if ( !isset( $arr[ $key ] ) )
215
+ $arr[ $key ] = array();
216
+
217
+ $arr =& $arr[ $key ];
218
  }
219
 
220
+ $arr[ $final_key ] = $value;
221
+ }
222
+ }
 
223
 
224
+
225
+ /**
226
+ * A wrapper for scbForms, containing the formdata
227
+ */
228
+ class scbForm {
229
+ protected $data = array();
230
+ protected $prefix = array();
231
+
232
+ function __construct( $data, $prefix = false ) {
233
+ if ( is_array( $data ) )
234
+ $this->data = $data;
235
+
236
+ if ( $prefix )
237
+ $this->prefix = (array) $prefix;
238
+ }
239
+
240
+ function traverse_to( $path ) {
241
+ $data = scbForms::get_value( $path, $this->data );
242
+
243
+ $prefix = array_merge( $this->prefix, (array) $path );
244
+
245
+ return new scbForm( $data, $prefix );
246
+ }
247
+
248
+ function input( $args ) {
249
+ $value = scbForms::get_value( $args['name'], $this->data );
250
+
251
+ if ( !empty( $this->prefix ) ) {
252
+ $args['name'] = array_merge( $this->prefix, (array) $args['name'] );
253
  }
254
 
255
+ return scbForms::input_with_value( $args, $value );
256
  }
257
+ }
258
 
 
 
 
 
 
259
 
260
+ interface scbFormField_I {
261
 
262
+ /**
263
+ * Generate the corresponding HTML for a field
264
+ *
265
+ * @param mixed $value The value to use
266
+ *
267
+ * @return string
268
+ */
269
+ function render( $value = null );
270
+
271
+ /**
272
+ * Validates a value against a field.
273
+ *
274
+ * @param mixed $value The value to check
275
+ *
276
+ * @return mixed null if the validation failed, sanitized value otherwise.
277
+ */
278
+ function validate( $value );
279
+ }
280
+
281
+
282
+ abstract class scbFormField implements scbFormField_I {
283
+
284
+ protected $args;
285
+
286
+ public static function create( $args ) {
287
+ if ( is_a( $args, 'scbFormField_I' ) )
288
+ return $args;
289
+
290
+ if ( empty( $args['name'] ) ) {
291
+ return trigger_error( 'Empty name', E_USER_WARNING );
292
  }
293
 
294
+ if ( isset( $args['value'] ) && is_array( $args['value'] ) ) {
295
+ $args['choices'] = $args['value'];
296
+ unset( $args['value'] );
297
+ }
298
 
299
+ if ( isset( $args['values'] ) ) {
300
+ $args['choices'] = $args['values'];
301
+ unset( $args['values'] );
 
 
302
  }
303
 
304
+ if ( isset( $args['extra'] ) && !is_array( $args['extra'] ) )
305
+ $args['extra'] = shortcode_parse_atts( $args['extra'] );
 
306
 
307
+ $args = wp_parse_args( $args, array(
308
+ 'desc' => '',
309
+ 'desc_pos' => 'after',
310
+ 'wrap' => scbForms::TOKEN,
311
+ 'wrap_each' => scbForms::TOKEN,
312
+ ) );
313
+
314
+ // depends on $args['desc']
315
+ if ( isset( $args['choices'] ) )
316
+ self::_expand_choices( $args );
317
+
318
+ switch ( $args['type'] ) {
319
+ case 'radio':
320
+ return new scbRadiosField( $args );
321
+ case 'select':
322
+ return new scbSelectField( $args );
323
+ case 'checkbox':
324
+ if ( isset( $args['choices'] ) )
325
+ return new scbMultipleChoiceField( $args );
326
+ else
327
+ return new scbSingleCheckboxField( $args );
328
+ case 'custom':
329
+ return new scbCustomField( $args );
330
+ default:
331
+ return new scbTextField( $args );
332
  }
333
+ }
334
 
335
+ protected function __construct( $args ) {
336
+ $this->args = $args;
337
+ }
338
 
339
+ public function __get( $key ) {
340
+ return $this->args[ $key ];
341
+ }
342
 
343
+ public function __isset( $key ) {
344
+ return isset( $this->args[ $key ] );
345
  }
346
 
347
+ public function render( $value = null ) {
348
+ if ( null === $value && isset( $this->default ) )
349
+ $value = $this->default;
350
+
351
+ $args = $this->args;
352
+
353
+ if ( null !== $value )
354
+ $this->_set_value( $args, $value );
355
+
356
+ $args['name'] = scbForms::get_name( $args['name'] );
357
+
358
+ return str_replace( scbForms::TOKEN, $this->_render( $args ), $this->wrap );
359
+ }
360
+
361
+ // Mutate the field arguments so that the value passed is rendered.
362
+ abstract protected function _set_value( &$args, $value );
363
+
364
+ // The actual rendering
365
+ abstract protected function _render( $args );
366
+
367
  // Handle args for a single checkbox or radio input
368
+ protected static function _checkbox( $args ) {
369
  $args = wp_parse_args( $args, array(
370
  'value' => true,
371
+ 'desc' => null,
372
  'checked' => false,
373
  'extra' => array(),
374
  ) );
385
  return self::_input_gen( $args );
386
  }
387
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  // Generate html with the final args
389
+ protected static function _input_gen( $args ) {
390
  extract( wp_parse_args( $args, array(
391
+ 'value' => null,
392
+ 'desc' => null,
393
  'extra' => array()
394
  ) ) );
395
 
396
+ $extra['name'] = $name;
397
 
398
  if ( 'textarea' == $type ) {
399
  $input = html( 'textarea', $extra, esc_textarea( $value ) );
406
  return self::add_label( $input, $desc, $desc_pos );
407
  }
408
 
409
+ protected static function add_label( $input, $desc, $desc_pos ) {
410
  return html( 'label', self::add_desc( $input, $desc, $desc_pos ) ) . "\n";
411
  }
412
 
413
+ protected static function add_desc( $input, $desc, $desc_pos ) {
414
  if ( empty( $desc ) )
415
  return $input;
416
 
420
  return $input . ' ' . $desc;
421
  }
422
 
423
+ private static function _expand_choices( &$args ) {
424
+ $choices =& $args['choices'];
425
 
426
+ if ( !empty( $choices ) && !self::is_associative( $choices ) ) {
427
+ if ( is_array( $args['desc'] ) ) {
428
+ $choices = array_combine( $choices, $args['desc'] ); // back-compat
429
+ $args['desc'] = false;
430
+ } elseif ( !isset( $args['numeric'] ) || !$args['numeric'] ) {
431
+ $choices = array_combine( $choices, $choices );
432
+ }
433
+ }
434
+ }
435
 
436
+ private static function is_associative( $array ) {
437
+ $keys = array_keys( $array );
438
+ return array_keys( $keys ) !== $keys;
439
+ }
440
+ }
441
 
 
 
 
 
 
 
 
 
 
442
 
443
+ class scbTextField extends scbFormField {
444
 
445
+ public function validate( $value ) {
446
+ $sanitize = isset( $this->sanitize ) ? $this->sanitize : 'wp_filter_kses';
 
447
 
448
+ return call_user_func( $sanitize, $value, $this );
449
  }
450
 
451
+ protected function _render( $args ) {
452
+ $args = wp_parse_args( $args, array(
453
+ 'value' => '',
454
+ 'desc_pos' => 'after',
455
+ 'extra' => array( 'class' => 'regular-text' ),
456
+ ) );
 
 
 
 
 
 
 
457
 
458
+ foreach ( $args as $key => &$val )
459
+ $$key = &$val;
460
+ unset( $val );
461
+
462
+ if ( !isset( $extra['id'] ) && !is_array( $name ) && false === strpos( $name, '[' ) )
463
+ $extra['id'] = $name;
464
+
465
+ return scbFormField::_input_gen( $args );
466
+ }
467
+
468
+ protected function _set_value( &$args, $value ) {
469
+ $args['value'] = $value;
470
+ }
471
+ }
472
+
473
+
474
+ abstract class scbSingleChoiceField extends scbFormField {
475
+
476
+ public function validate( $value ) {
477
+ if ( isset( $this->choices[ $value ] ) )
478
+ return $value;
479
+
480
+ return null;
481
+ }
482
+
483
+ protected function _render( $args ) {
484
+ $args = wp_parse_args( $args, array(
485
+ 'numeric' => false, // use numeric array instead of associative
486
+ 'selected' => array( 'foo' ), // hack to make default blank
487
+ ) );
488
+
489
+ return $this->_render_specific( $args );
490
+ }
491
+
492
+ protected function _set_value( &$args, $value ) {
493
+ $args['selected'] = $value;
494
+ }
495
+
496
+ abstract protected function _render_specific( $args );
497
+ }
498
+
499
+
500
+ class scbSelectField extends scbSingleChoiceField {
501
+
502
+ protected function _render_specific( $args ) {
503
+ extract( wp_parse_args( $args, array(
504
+ 'text' => false,
505
+ 'extra' => array()
506
+ ) ) );
507
+
508
+ $options = array();
509
+
510
+ if ( false !== $text ) {
511
+ $options[] = array(
512
+ 'value' => '',
513
+ 'selected' => ( $selected == array( 'foo' ) ),
514
+ 'title' => $text
515
+ );
516
  }
517
 
518
+ foreach ( $choices as $value => $title ) {
519
+ $options[] = array(
520
+ 'value' => $value,
521
+ 'selected' => ( $value == $selected ),
522
+ 'title' => $title
523
+ );
524
+ }
525
+
526
+ $opts = '';
527
+ foreach ( $options as $option ) {
528
+ extract( $option );
529
+
530
+ $opts .= html( 'option', compact( 'value', 'selected' ), $title );
531
+ }
532
+
533
+ $extra['name'] = $name;
534
+
535
+ $input = html( 'select', $extra, $opts );
536
+
537
+ return scbFormField::add_label( $input, $desc, $desc_pos );
538
  }
539
+ }
540
 
 
 
 
 
 
 
 
 
 
 
 
541
 
542
+ class scbRadiosField extends scbSelectField {
543
 
544
+ protected function _render_specific( $args ) {
545
+ extract( $args );
 
 
 
 
546
 
547
+ if ( array( 'foo' ) == $selected ) {
548
+ // radio buttons should always have one option selected
549
+ $selected = key( $choices );
550
+ }
551
+
552
+ $opts = '';
553
+ foreach ( $choices as $value => $title ) {
554
+ $single_input = scbFormField::_checkbox( array(
555
+ 'name' => $name,
556
+ 'type' => 'radio',
557
+ 'value' => $value,
558
+ 'checked' => ( $value == $selected ),
559
+ 'desc' => $title,
560
+ 'desc_pos' => 'after'
561
+ ) );
562
 
563
+ $opts .= str_replace( scbForms::TOKEN, $single_input, $wrap_each );
564
  }
565
 
566
+ return scbFormField::add_desc( $opts, $desc, $desc_pos );
567
  }
568
+ }
569
 
 
 
570
 
571
+ class scbMultipleChoiceField extends scbFormField {
572
 
573
+ public function validate( $value ) {
574
+ return array_intersect( array_keys( $this->choices ), (array) $value );
575
+ }
576
 
577
+ protected function _render( $args ) {
578
+ $args = wp_parse_args( $args, array(
579
+ 'numeric' => false, // use numeric array instead of associative
580
+ 'checked' => null,
581
+ ) );
582
 
583
+ extract( $args );
584
+
585
+ if ( !is_array( $checked ) )
586
+ $checked = array();
587
+
588
+ $opts = '';
589
+ foreach ( $choices as $value => $title ) {
590
+ $single_input = scbFormField::_checkbox( array(
591
+ 'name' => $name . '[]',
592
+ 'type' => 'checkbox',
593
+ 'value' => $value,
594
+ 'checked' => in_array( $value, $checked ),
595
+ 'desc' => $title,
596
+ 'desc_pos' => 'after'
597
+ ) );
598
+
599
+ $opts .= str_replace( scbForms::TOKEN, $single_input, $wrap_each );
600
  }
601
 
602
+ return scbFormField::add_desc( $opts, $desc, $desc_pos );
603
  }
604
 
605
+ protected function _set_value( &$args, $value ) {
606
+ $args['checked'] = (array) $value;
 
607
  }
608
  }
609
 
 
 
 
 
 
 
610
 
611
+ class scbSingleCheckboxField extends scbFormField {
 
 
612
 
613
+ public function validate( $value ) {
614
+ return (bool) $value;
615
  }
616
 
617
+ protected function _render( $args ) {
618
+ $args = wp_parse_args( $args, array(
619
+ 'value' => true,
620
+ 'desc' => null,
621
+ 'checked' => false,
622
+ 'extra' => array(),
623
+ ) );
624
 
625
+ foreach ( $args as $key => &$val )
626
+ $$key = &$val;
627
+ unset( $val );
628
 
629
+ $extra['checked'] = $checked;
630
+
631
+ if ( is_null( $desc ) && !is_bool( $value ) )
632
+ $desc = str_replace( '[]', '', $value );
633
+
634
+ return scbFormField::_input_gen( $args );
635
  }
636
 
637
+ protected function _set_value( &$args, $value ) {
638
+ $args['checked'] = ( $value || ( isset( $args['value'] ) && $value == $args['value'] ) );
639
+ }
640
+ }
641
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
642
 
643
+ class scbCustomField implements scbFormField_I {
644
+
645
+ protected $args;
646
+
647
+ function __construct( $args ) {
648
+ $this->args = wp_parse_args( $args, array(
649
+ 'render' => 'var_dump',
650
+ 'sanitize' => 'wp_filter_kses',
651
+ ) );
652
+ }
653
+
654
+ public function __get( $key ) {
655
+ return $this->args[ $key ];
656
+ }
657
+
658
+ public function __isset( $key ) {
659
+ return isset( $this->args[ $key ] );
660
+ }
661
+
662
+ public function render( $value = null ) {
663
+ return call_user_func( $this->render, $value, $this );
664
+ }
665
 
666
+ public function validate( $value ) {
667
+ return call_user_func( $this->sanitize, $value, $this );
668
  }
669
  }
670
 
scb/Options.php CHANGED
@@ -35,27 +35,25 @@ class scbOptions {
35
  }
36
 
37
  /**
38
- * Get option values for one, many or all fields
39
  *
40
- * @param string|array $field The field(s) to get
41
  * @return mixed Whatever is in those fields
42
  */
43
- public function get( $field = '' ) {
44
- $data = get_option( $this->key, array() );
45
 
46
- $data = array_merge( $this->defaults, $data );
47
-
48
- return $this->_get( $field, $data );
49
  }
50
 
51
  /**
52
- * Get default values for one, many or all fields
53
  *
54
- * @param string|array $field The field( s ) to get
55
  * @return mixed Whatever is in those fields
56
  */
57
- public function get_defaults( $field = '' ) {
58
- return $this->_get( $field, $this->defaults );
59
  }
60
 
61
  /**
@@ -89,7 +87,7 @@ class scbOptions {
89
  * @return bool
90
  */
91
  public function cleanup() {
92
- $this->update( $this->_clean( $this->get() ) );
93
  }
94
 
95
  /**
@@ -129,19 +127,7 @@ class scbOptions {
129
  return wp_array_slice_assoc( $data, array_keys( $this->defaults ) );
130
  }
131
 
132
- // Get one, more or all fields from an array
133
  private function &_get( $field, $data ) {
134
- if ( empty( $field ) )
135
- return $data;
136
-
137
- if ( is_string( $field ) )
138
- return $data[$field];
139
-
140
- foreach ( $field as $key )
141
- if ( isset( $data[$key] ) )
142
- $result[] = $data[$key];
143
-
144
- return $result;
145
  }
146
 
147
  // Magic method: $options->field
35
  }
36
 
37
  /**
38
+ * Get option values for one or all fields
39
  *
40
+ * @param string|array $field The field to get
41
  * @return mixed Whatever is in those fields
42
  */
43
+ public function get( $field = null, $default = null ) {
44
+ $data = array_merge( $this->defaults, get_option( $this->key, array() ) );
45
 
46
+ return scbForms::get_value( $field, $data, $default );
 
 
47
  }
48
 
49
  /**
50
+ * Get default values for one or all fields
51
  *
52
+ * @param string|array $field The field to get
53
  * @return mixed Whatever is in those fields
54
  */
55
+ public function get_defaults( $field = null ) {
56
+ return scbForms::get_value( $field, $this->defaults );
57
  }
58
 
59
  /**
87
  * @return bool
88
  */
89
  public function cleanup() {
90
+ $this->update( $this->get(), true );
91
  }
92
 
93
  /**
127
  return wp_array_slice_assoc( $data, array_keys( $this->defaults ) );
128
  }
129
 
 
130
  private function &_get( $field, $data ) {
 
 
 
 
 
 
 
 
 
 
 
131
  }
132
 
133
  // Magic method: $options->field
scb/Util.php CHANGED
@@ -40,6 +40,7 @@ class scbUtil {
40
  add_action( 'scb_activation_' . plugin_basename( $plugin ), $callback );
41
  }
42
 
 
43
  static function do_activation( $plugin ) {
44
  do_action( 'scb_activation_' . plugin_basename( $plugin ) );
45
  }
@@ -47,11 +48,15 @@ class scbUtil {
47
  // Allows more than one uninstall hooks.
48
  // Also prevents an UPDATE query on each page load.
49
  static function add_uninstall_hook( $plugin, $callback ) {
 
 
 
50
  register_uninstall_hook( $plugin, '__return_false' ); // dummy
51
 
52
  add_action( 'uninstall_' . plugin_basename( $plugin ), $callback );
53
  }
54
 
 
55
  static function do_uninstall( $plugin ) {
56
  do_action( 'uninstall_' . plugin_basename( $plugin ) );
57
  }
@@ -114,7 +119,7 @@ class scbUtil {
114
 
115
  // Return a standard admin notice
116
  function scb_admin_notice( $msg, $class = 'updated' ) {
117
- return "<div class='$class fade'><p>$msg</p></div>\n";
118
  }
119
 
120
  // Transform a list of objects into an associative array
@@ -140,6 +145,8 @@ function scb_list_fold( $list, $key, $value ) {
140
  */
141
  if ( ! function_exists( 'html' ) ):
142
  function html( $tag ) {
 
 
143
  $args = func_get_args();
144
 
145
  $tag = array_shift( $args );
@@ -160,7 +167,7 @@ function html( $tag ) {
160
  list( $closing ) = explode( ' ', $tag, 2 );
161
  }
162
 
163
- if ( in_array( $closing, array( 'area', 'base', 'basefont', 'br', 'hr', 'input', 'img', 'link', 'meta' ) ) ) {
164
  return "<{$tag} />";
165
  }
166
 
40
  add_action( 'scb_activation_' . plugin_basename( $plugin ), $callback );
41
  }
42
 
43
+ // For debugging
44
  static function do_activation( $plugin ) {
45
  do_action( 'scb_activation_' . plugin_basename( $plugin ) );
46
  }
48
  // Allows more than one uninstall hooks.
49
  // Also prevents an UPDATE query on each page load.
50
  static function add_uninstall_hook( $plugin, $callback ) {
51
+ if ( !is_admin() )
52
+ return;
53
+
54
  register_uninstall_hook( $plugin, '__return_false' ); // dummy
55
 
56
  add_action( 'uninstall_' . plugin_basename( $plugin ), $callback );
57
  }
58
 
59
+ // For debugging
60
  static function do_uninstall( $plugin ) {
61
  do_action( 'uninstall_' . plugin_basename( $plugin ) );
62
  }
119
 
120
  // Return a standard admin notice
121
  function scb_admin_notice( $msg, $class = 'updated' ) {
122
+ return html( "div class='$class fade'", html( "p", $msg ) );
123
  }
124
 
125
  // Transform a list of objects into an associative array
145
  */
146
  if ( ! function_exists( 'html' ) ):
147
  function html( $tag ) {
148
+ static $SELF_CLOSING_TAGS = array( 'area', 'base', 'basefont', 'br', 'hr', 'input', 'img', 'link', 'meta' );
149
+
150
  $args = func_get_args();
151
 
152
  $tag = array_shift( $args );
167
  list( $closing ) = explode( ' ', $tag, 2 );
168
  }
169
 
170
+ if ( in_array( $closing, $SELF_CLOSING_TAGS ) ) {
171
  return "<{$tag} />";
172
  }
173
 
scb/load.php CHANGED
@@ -1,12 +1,17 @@
1
  <?php
2
 
3
- $GLOBALS['_scb_data'] = array( 49, __FILE__, array(
4
  'scbUtil', 'scbOptions', 'scbForms', 'scbTable',
5
  'scbWidget', 'scbAdminPage', 'scbBoxesPage',
6
  'scbCron', 'scbHooks',
7
  ) );
8
 
9
  if ( !class_exists( 'scbLoad4' ) ) :
 
 
 
 
 
10
  class scbLoad4 {
11
 
12
  private static $candidates = array();
@@ -27,8 +32,10 @@ class scbLoad4 {
27
  add_action( 'activate_plugin', array( __CLASS__, 'delayed_activation' ) );
28
  }
29
 
30
- // TODO: don't load when activating a plugin ?
31
- add_action( 'plugins_loaded', array( __CLASS__, 'load' ), 9, 0 );
 
 
32
  }
33
 
34
  static function delayed_activation( $plugin ) {
1
  <?php
2
 
3
+ $GLOBALS['_scb_data'] = array( 56, __FILE__, array(
4
  'scbUtil', 'scbOptions', 'scbForms', 'scbTable',
5
  'scbWidget', 'scbAdminPage', 'scbBoxesPage',
6
  'scbCron', 'scbHooks',
7
  ) );
8
 
9
  if ( !class_exists( 'scbLoad4' ) ) :
10
+ /**
11
+ * The main idea behind this class is to load the most recent version of the scb classes available.
12
+ *
13
+ * It waits until all plugins are loaded and then does some crazy hacks to make activation hooks work.
14
+ */
15
  class scbLoad4 {
16
 
17
  private static $candidates = array();
32
  add_action( 'activate_plugin', array( __CLASS__, 'delayed_activation' ) );
33
  }
34
 
35
+ if ( did_action( 'plugins_loaded' ) )
36
+ self::load();
37
+ else
38
+ add_action( 'plugins_loaded', array( __CLASS__, 'load' ), 9, 0 );
39
  }
40
 
41
  static function delayed_activation( $plugin ) {
test.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Template Name: WPN Debug
3
+
4
+ get_header();
5
+
6
+ query_posts( array( 'post_type' => 'post', 'paged' => get_query_var( 'paged' ) ) );
7
+ ?>
8
+
9
+ <div id="primary">
10
+ <div id="content" role="main">
11
+
12
+ <ul>
13
+ <?php while ( have_posts() ) : the_post(); ?>
14
+ <li><?php the_title(); ?>
15
+ <?php endwhile?>
16
+ </ul>
17
+
18
+ <?php wp_pagenavi(); ?>
19
+ <?php echo wp_pagenavi( array( 'echo' => false ) ); ?>
20
+
21
+ </div><!-- #content -->
22
+ </div><!-- #primary -->
23
+
24
+ <?php get_footer(); ?>
wp-pagenavi.php CHANGED
@@ -1,29 +1,12 @@
1
  <?php
2
  /*
3
  Plugin Name: WP-PageNavi
4
- Version: 2.82
5
  Description: Adds a more advanced paging navigation to your WordPress blog
6
  Author: Lester 'GaMerZ' Chan & scribu
7
  Plugin URI: http://wordpress.org/extend/plugins/wp-pagenavi/
8
  Text Domain: wp-pagenavi
9
  Domain Path: /lang
10
-
11
-
12
- Copyright 2009 Lester Chan (lesterchan@gmail.com)
13
-
14
- This program is free software; you can redistribute it and/or modify
15
- it under the terms of the GNU General Public License as published by
16
- the Free Software Foundation; either version 2 of the License, or
17
- (at your option) any later version.
18
-
19
- This program is distributed in the hope that it will be useful,
20
- but WITHOUT ANY WARRANTY; without even the implied warranty of
21
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
- GNU General Public License for more details.
23
-
24
- You should have received a copy of the GNU General Public License
25
- along with this program; if not, write to the Free Software
26
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
  */
28
 
29
  include dirname( __FILE__ ) . '/scb/load.php';
1
  <?php
2
  /*
3
  Plugin Name: WP-PageNavi
4
+ Version: 2.83
5
  Description: Adds a more advanced paging navigation to your WordPress blog
6
  Author: Lester 'GaMerZ' Chan & scribu
7
  Plugin URI: http://wordpress.org/extend/plugins/wp-pagenavi/
8
  Text Domain: wp-pagenavi
9
  Domain Path: /lang
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  */
11
 
12
  include dirname( __FILE__ ) . '/scb/load.php';