Options Framework - Version 0.9

Version Description

  • Load thickbox using site_url() to allow for https (props @samargulies)
  • Change santization to use $allowedposttags for textarea and info
  • Display notice if theme doesn't support the Options Framework
  • Single checkboxes now use labels
  • CSS updates for formatting long labels
  • Allows dashes in the options id (props @mantone)
  • Uses add_theme_page over add_submenu_page (props @enile8)
Download this release

Release Info

Developer downstairsdev
Plugin Icon wp plugin Options Framework
Version 0.9
Comparing to
See all releases

Code changes from version 0.8 to 0.9

css/admin-style.css CHANGED
@@ -19,7 +19,7 @@
19
  #optionsframework .section {
20
  padding:10px 10px 0;
21
  }
22
- #optionsframework .group .section:last-of-type {
23
  padding-bottom:40px;
24
  }
25
  #optionsframework .section .heading {
@@ -41,22 +41,24 @@
41
  color: #777;
42
  }
43
  #optionsframework .section-checkbox .controls {
44
- min-width:25px;
45
- width:25px
46
  }
47
  #optionsframework .section-checkbox .explain {
48
- max-width:93%;
49
  }
50
  #optionsframework .section-color .controls {
51
  min-width:125px;
52
  width:125px
53
  }
54
  #optionsframework .controls input, #optionsframework .controls select, #optionsframework .controls textarea {
55
- margin-bottom: 10px;
56
  width:100%;
57
  }
58
  #optionsframework .section-radio label, #optionsframework .section-multicheck label {
59
  float:left;
 
 
 
60
  }
61
  #optionsframework input.checkbox, #optionsframework input.of-radio {
62
  width: 30px;
19
  #optionsframework .section {
20
  padding:10px 10px 0;
21
  }
22
+ #optionsframework .group {
23
  padding-bottom:40px;
24
  }
25
  #optionsframework .section .heading {
41
  color: #777;
42
  }
43
  #optionsframework .section-checkbox .controls {
44
+ width: 98%;
 
45
  }
46
  #optionsframework .section-checkbox .explain {
47
+ max-width:94%;
48
  }
49
  #optionsframework .section-color .controls {
50
  min-width:125px;
51
  width:125px
52
  }
53
  #optionsframework .controls input, #optionsframework .controls select, #optionsframework .controls textarea {
54
+ margin-bottom:10px;
55
  width:100%;
56
  }
57
  #optionsframework .section-radio label, #optionsframework .section-multicheck label {
58
  float:left;
59
+ max-width:90%;
60
+ line-height: 16px;
61
+ margin-bottom: 5px;
62
  }
63
  #optionsframework input.checkbox, #optionsframework input.of-radio {
64
  width: 30px;
options-framework.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Options Framework
4
  Plugin URI: http://www.wptheming.com
5
  Description: A framework for building theme options.
6
- Version: 0.8
7
  Author: Devin Price
8
  Author URI: http://www.wptheming.com
9
  License: GPLv2
@@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27
 
28
  /* Basic plugin definitions */
29
 
30
- define('OPTIONS_FRAMEWORK_VERSION', '0.8');
31
  define('OPTIONS_FRAMEWORK_URL', plugin_dir_url( __FILE__ ));
32
 
33
  /* Make sure we don't expose any info if called directly */
@@ -43,10 +43,39 @@ add_action('init', 'optionsframework_rolescheck' );
43
 
44
  function optionsframework_rolescheck () {
45
  if ( current_user_can( 'edit_theme_options' ) ) {
46
- // If the user can edit theme options, let the fun begin!
47
- add_action( 'admin_menu', 'optionsframework_add_page');
48
- add_action( 'admin_init', 'optionsframework_init' );
49
- add_action( 'admin_init', 'optionsframework_mlu_init' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  }
51
  }
52
 
@@ -74,6 +103,7 @@ function optionsframework_delete_options() {
74
  }
75
  }
76
  delete_option('optionsframework');
 
77
  }
78
 
79
  /* Loads the file for option sanitization */
@@ -101,12 +131,8 @@ function optionsframework_init() {
101
  require_once dirname( __FILE__ ) . '/options-medialibrary-uploader.php';
102
 
103
  // Loads the options array from the theme
104
- if ( $optionsfile = locate_template( array('options.php') ) ) {
105
- require_once($optionsfile);
106
- }
107
- else if (file_exists( dirname( __FILE__ ) . '/options.php' ) ) {
108
- require_once dirname( __FILE__ ) . '/options.php';
109
- }
110
 
111
  $optionsframework_settings = get_option('optionsframework' );
112
 
@@ -184,7 +210,7 @@ function optionsframework_setdefaults() {
184
  if ( !function_exists( 'optionsframework_add_page' ) ) {
185
  function optionsframework_add_page() {
186
 
187
- $of_page = add_submenu_page('themes.php', 'Theme Options', 'Theme Options', 'edit_theme_options', 'options-framework','optionsframework_page');
188
 
189
  // Adds actions to hook in the required css and javascript
190
  add_action("admin_print_styles-$of_page",'optionsframework_load_styles');
@@ -305,7 +331,7 @@ function optionsframework_validate( $input ) {
305
  continue;
306
  }
307
 
308
- $id = preg_replace( '/\W/', '', strtolower( $option['id'] ) );
309
 
310
  // Set checkbox to false if it wasn't sent in the $_POST
311
  if ( 'checkbox' == $option['type'] && ! isset( $input[$id] ) ) {
3
  Plugin Name: Options Framework
4
  Plugin URI: http://www.wptheming.com
5
  Description: A framework for building theme options.
6
+ Version: 0.9
7
  Author: Devin Price
8
  Author URI: http://www.wptheming.com
9
  License: GPLv2
27
 
28
  /* Basic plugin definitions */
29
 
30
+ define('OPTIONS_FRAMEWORK_VERSION', '0.9');
31
  define('OPTIONS_FRAMEWORK_URL', plugin_dir_url( __FILE__ ));
32
 
33
  /* Make sure we don't expose any info if called directly */
43
 
44
  function optionsframework_rolescheck () {
45
  if ( current_user_can( 'edit_theme_options' ) ) {
46
+ $optionsfile = locate_template( array('options.php') );
47
+ if ($optionsfile) {
48
+ // If the user can edit theme options, let the fun begin!
49
+ add_action( 'admin_menu', 'optionsframework_add_page');
50
+ add_action( 'admin_init', 'optionsframework_init' );
51
+ add_action( 'admin_init', 'optionsframework_mlu_init' );
52
+ }
53
+ else {
54
+ // Display a notice if options.php isn't present in the theme
55
+ add_action('admin_notices', 'optionsframework_admin_notice');
56
+ add_action('admin_init', 'optionsframework_nag_ignore');
57
+ }
58
+ }
59
+ }
60
+
61
+ function optionsframework_admin_notice() {
62
+ global $pagenow;
63
+ if ( !is_multisite() && ( $pagenow == 'plugins.php' || $pagenow == 'themes.php') ) {
64
+ global $current_user ;
65
+ $user_id = $current_user->ID;
66
+ if ( ! get_user_meta($user_id, 'optionsframework_ignore_notice') ) {
67
+ echo '<div class="updated optionsframework_setup_nag"><p>';
68
+ printf(__('Your current theme does not have support for the Options Framework plugin. <a href="%1$s" target="_blank">Learn More</a> | <a href="%2$s">Hide Notice</a>'), 'http://wptheming.com/options-framework-plugin', '?optionsframework_nag_ignore=0');
69
+ echo "</p></div>";
70
+ }
71
+ }
72
+ }
73
+
74
+ function optionsframework_nag_ignore() {
75
+ global $current_user;
76
+ $user_id = $current_user->ID;
77
+ if ( isset($_GET['optionsframework_nag_ignore']) && '0' == $_GET['optionsframework_nag_ignore'] ) {
78
+ add_user_meta($user_id, 'optionsframework_ignore_notice', 'true', true);
79
  }
80
  }
81
 
103
  }
104
  }
105
  delete_option('optionsframework');
106
+ delete_user_meta($user_id, 'optionsframework_ignore_notice', 'true');
107
  }
108
 
109
  /* Loads the file for option sanitization */
131
  require_once dirname( __FILE__ ) . '/options-medialibrary-uploader.php';
132
 
133
  // Loads the options array from the theme
134
+ $optionsfile = locate_template( array('options.php') );
135
+ require_once($optionsfile);
 
 
 
 
136
 
137
  $optionsframework_settings = get_option('optionsframework' );
138
 
210
  if ( !function_exists( 'optionsframework_add_page' ) ) {
211
  function optionsframework_add_page() {
212
 
213
+ $of_page = add_theme_page('Theme Options', 'Theme Options', 'edit_theme_options', 'options-framework','optionsframework_page');
214
 
215
  // Adds actions to hook in the required css and javascript
216
  add_action("admin_print_styles-$of_page",'optionsframework_load_styles');
331
  continue;
332
  }
333
 
334
+ $id = preg_replace( '/[^a-zA-Z0-9._\-]/', '', strtolower( $option['id'] ) );
335
 
336
  // Set checkbox to false if it wasn't sent in the $_POST
337
  if ( 'checkbox' == $option['type'] && ! isset( $input[$id] ) ) {
options-interface.php CHANGED
@@ -39,7 +39,7 @@ function optionsframework_fields() {
39
  if ( ($value['type'] != "heading") && ($value['type'] != "info") ) {
40
 
41
  // Keep all ids lowercase with no spaces
42
- $value['id'] = preg_replace('/\W/', '', strtolower($value['id']) );
43
 
44
  $id = 'section-' . $value['id'];
45
 
@@ -71,6 +71,12 @@ function optionsframework_fields() {
71
  }
72
  }
73
  }
 
 
 
 
 
 
74
 
75
  switch ( $value['type'] ) {
76
 
@@ -141,6 +147,7 @@ function optionsframework_fields() {
141
  // Checkbox
142
  case "checkbox":
143
  $output .= '<input id="' . esc_attr( $value['id'] ) . '" class="checkbox of-input" type="checkbox" name="' . esc_attr( $option_name . '[' . $value['id'] . ']' ) . '" '. checked( $val, 1, false) .' />';
 
144
  break;
145
 
146
  // Multicheck
@@ -148,7 +155,7 @@ function optionsframework_fields() {
148
  foreach ($value['options'] as $key => $option) {
149
  $checked = '';
150
  $label = $option;
151
- $option = preg_replace('/\W/', '', strtolower($key));
152
 
153
  $id = $option_name . '-' . $value['id'] . '-'. $option;
154
  $name = $option_name . '[' . $value['id'] . '][' . $option .']';
@@ -284,10 +291,10 @@ function optionsframework_fields() {
284
 
285
  // Heading for Navigation
286
  case "heading":
287
- if($counter >= 2){
288
  $output .= '</div>'."\n";
289
  }
290
- $jquery_click_hook = preg_replace('/\W/', '', strtolower($value['name']) );
291
  $jquery_click_hook = "of-option-" . $jquery_click_hook;
292
  $menu .= '<a id="'. esc_attr( $jquery_click_hook ) . '-tab" class="nav-tab" title="' . esc_attr( $value['name'] ) . '" href="' . esc_attr( '#'. $jquery_click_hook ) . '">' . esc_html( $value['name'] ) . '</a>';
293
  $output .= '<div class="group" id="' . esc_attr( $jquery_click_hook ) . '">';
@@ -299,11 +306,10 @@ function optionsframework_fields() {
299
  if ( $value['type'] != "checkbox" ) {
300
  $output .= '<br/>';
301
  }
302
- $explain_value = '';
303
- if ( isset( $value['desc'] ) ) {
304
- $explain_value = $value['desc'];
305
  }
306
- $output .= '</div><div class="explain">' . wp_kses( $explain_value, $allowedtags) . '</div>'."\n";
307
  $output .= '<div class="clear"></div></div></div>'."\n";
308
  }
309
  }
39
  if ( ($value['type'] != "heading") && ($value['type'] != "info") ) {
40
 
41
  // Keep all ids lowercase with no spaces
42
+ $value['id'] = preg_replace('/[^a-zA-Z0-9._\-]/', '', strtolower($value['id']) );
43
 
44
  $id = 'section-' . $value['id'];
45
 
71
  }
72
  }
73
  }
74
+
75
+ // If there is a description save it for labels
76
+ $explain_value = '';
77
+ if ( isset( $value['desc'] ) ) {
78
+ $explain_value = $value['desc'];
79
+ }
80
 
81
  switch ( $value['type'] ) {
82
 
147
  // Checkbox
148
  case "checkbox":
149
  $output .= '<input id="' . esc_attr( $value['id'] ) . '" class="checkbox of-input" type="checkbox" name="' . esc_attr( $option_name . '[' . $value['id'] . ']' ) . '" '. checked( $val, 1, false) .' />';
150
+ $output .= '<label class="explain" for="' . esc_attr( $value['id'] ) . '">' . wp_kses( $explain_value, $allowedtags) . '</label>';
151
  break;
152
 
153
  // Multicheck
155
  foreach ($value['options'] as $key => $option) {
156
  $checked = '';
157
  $label = $option;
158
+ $option = preg_replace('/[^a-zA-Z0-9._\-]/', '', strtolower($key));
159
 
160
  $id = $option_name . '-' . $value['id'] . '-'. $option;
161
  $name = $option_name . '[' . $value['id'] . '][' . $option .']';
291
 
292
  // Heading for Navigation
293
  case "heading":
294
+ if ($counter >= 2) {
295
  $output .= '</div>'."\n";
296
  }
297
+ $jquery_click_hook = preg_replace('/[^a-zA-Z0-9._\-]/', '', strtolower($value['name']) );
298
  $jquery_click_hook = "of-option-" . $jquery_click_hook;
299
  $menu .= '<a id="'. esc_attr( $jquery_click_hook ) . '-tab" class="nav-tab" title="' . esc_attr( $value['name'] ) . '" href="' . esc_attr( '#'. $jquery_click_hook ) . '">' . esc_html( $value['name'] ) . '</a>';
300
  $output .= '<div class="group" id="' . esc_attr( $jquery_click_hook ) . '">';
306
  if ( $value['type'] != "checkbox" ) {
307
  $output .= '<br/>';
308
  }
309
+ $output .= '</div>';
310
+ if ( $value['type'] != "checkbox" ) {
311
+ $output .= '<div class="explain">' . wp_kses( $explain_value, $allowedtags) . '</div>'."\n";
312
  }
 
313
  $output .= '<div class="clear"></div></div></div>'."\n";
314
  }
315
  }
options-medialibrary-uploader.php CHANGED
@@ -48,10 +48,10 @@ if ( ! function_exists( 'optionsframework_mlu_css' ) ) {
48
  function optionsframework_mlu_css () {
49
 
50
  $_html = '';
51
- $_html .= '<link rel="stylesheet" href="' . get_option('siteurl') . '/' . WPINC . '/js/thickbox/thickbox.css" type="text/css" media="screen" />' . "\n";
52
  $_html .= '<script type="text/javascript">
53
- var tb_pathToImage = "' . get_option('siteurl') . '/' . WPINC . '/js/thickbox/loadingAnimation.gif";
54
- var tb_closeImage = "' . get_option('siteurl') . '/' . WPINC . '/js/thickbox/tb-close.png";
55
  </script>' . "\n";
56
 
57
  echo $_html;
48
  function optionsframework_mlu_css () {
49
 
50
  $_html = '';
51
+ $_html .= '<link rel="stylesheet" href="' . site_url() . '/' . WPINC . '/js/thickbox/thickbox.css" type="text/css" media="screen" />' . "\n";
52
  $_html .= '<script type="text/javascript">
53
+ var tb_pathToImage = "' . site_url() . '/' . WPINC . '/js/thickbox/loadingAnimation.gif";
54
+ var tb_closeImage = "' . site_url() . '/' . WPINC . '/js/thickbox/tb-close.png";
55
  </script>' . "\n";
56
 
57
  echo $_html;
options-sanitize.php CHANGED
@@ -7,8 +7,8 @@ add_filter( 'of_sanitize_text', 'sanitize_text_field' );
7
  /* Textarea */
8
 
9
  function of_sanitize_textarea($input) {
10
- global $allowedtags;
11
- $output = wp_kses( $input, $allowedtags);
12
  return $output;
13
  }
14
 
@@ -16,13 +16,7 @@ add_filter( 'of_sanitize_textarea', 'of_sanitize_textarea' );
16
 
17
  /* Info */
18
 
19
- function of_sanitize_allowedtags($input) {
20
- global $allowedtags;
21
- $output = wpautop(wp_kses( $input, $allowedtags));
22
- return $output;
23
- }
24
-
25
- add_filter( 'of_sanitize_info', 'of_sanitize_allowedtags' );
26
 
27
  /* Select */
28
 
@@ -82,6 +76,27 @@ function of_sanitize_upload( $input ) {
82
  }
83
  add_filter( 'of_sanitize_upload', 'of_sanitize_upload' );
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  /* Check that the key value sent is valid */
86
 
87
  function of_sanitize_enum( $input, $option ) {
7
  /* Textarea */
8
 
9
  function of_sanitize_textarea($input) {
10
+ global $allowedposttags;
11
+ $output = wp_kses( $input, $allowedposttags);
12
  return $output;
13
  }
14
 
16
 
17
  /* Info */
18
 
19
+ add_filter( 'of_sanitize_info', 'of_sanitize_allowedposttags' );
 
 
 
 
 
 
20
 
21
  /* Select */
22
 
76
  }
77
  add_filter( 'of_sanitize_upload', 'of_sanitize_upload' );
78
 
79
+ /* Allowed Tags */
80
+
81
+ function of_sanitize_allowedtags($input) {
82
+ global $allowedtags;
83
+ $output = wpautop(wp_kses( $input, $allowedtags));
84
+ return $output;
85
+ }
86
+
87
+ add_filter( 'of_sanitize_info', 'of_sanitize_allowedtags' );
88
+
89
+ /* Allowed Post Tags */
90
+
91
+ function of_sanitize_allowedposttags($input) {
92
+ global $allowedposttags;
93
+ $output = wpautop(wp_kses( $input, $allowedposttags));
94
+ return $output;
95
+ }
96
+
97
+ add_filter( 'of_sanitize_info', 'of_sanitize_allowedposttags' );
98
+
99
+
100
  /* Check that the key value sent is valid */
101
 
102
  function of_sanitize_enum( $input, $option ) {
options.php DELETED
@@ -1,39 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * This file should only load if options.php isn't present in the theme.
5
- *
6
- */
7
-
8
- /* Defaults the settings to 'optionsframework' */
9
-
10
- function optionsframework_option_name() {
11
-
12
- $optionsframework_settings = get_option('optionsframework');
13
- $optionsframework_settings['id'] = 'optionsframework';
14
- update_option('optionsframework', $optionsframework_settings);
15
- }
16
-
17
- /**
18
- * Displays a message that options aren't available in the current theme
19
- *
20
- */
21
-
22
- function optionsframework_options() {
23
-
24
- $options[] = array( "name" => "Theme Options",
25
- "type" => "heading");
26
-
27
- $options[] = array( "name" => "No Options Are Loaded",
28
- "desc" => "Your theme doesn't appear to support the Options Framework yet.",
29
- "type" => "info");
30
-
31
- $options[] = array( "desc" => "If this is a mistake, make sure that the file options.php is in your theme folder and that you have the correct theme activated.",
32
- "type" => "info");
33
-
34
- $options[] = array( "name" => "How to Set Up Options",
35
- "desc" => "If you are trying to set up new options for a theme, visit the <a href=\"http://wptheming.com/options-framework-plugin\" />Options Framework plugin page</a>.",
36
- "type" => "info");
37
-
38
- return $options;
39
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: options, theme options
4
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=X238BDP4QGTV2
5
  Requires at least: 3.0
6
  Tested up to: 3.2
7
- Stable tag: 0.8
8
  License: GPLv2
9
 
10
  == Description ==
@@ -51,6 +51,16 @@ You can also watch the video screencast I have at [http://wptheming.com/options-
51
 
52
  == Changelog ==
53
 
 
 
 
 
 
 
 
 
 
 
54
  = 0.8 =
55
 
56
  * Saves tab states using local storage
@@ -66,8 +76,8 @@ You can also watch the video screencast I have at [http://wptheming.com/options-
66
 
67
  = 0.6 =
68
 
69
- * Introduces validation filters
70
- * Better data sanitization and escaping
71
  * Updates labels in options-interface.php
72
  * Changes how checkboxes saved in database ("0" or "1")
73
  * Stores typography, backgrounds and multichecks directly as arrays
4
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=X238BDP4QGTV2
5
  Requires at least: 3.0
6
  Tested up to: 3.2
7
+ Stable tag: 0.9
8
  License: GPLv2
9
 
10
  == Description ==
51
 
52
  == Changelog ==
53
 
54
+ = 0.9 =
55
+
56
+ * Load thickbox using site_url() to allow for https (props @samargulies)
57
+ * Change santization to use $allowedposttags for textarea and info
58
+ * Display notice if theme doesn't support the Options Framework
59
+ * Single checkboxes now use labels
60
+ * CSS updates for formatting long labels
61
+ * Allows dashes in the options id (props @mantone)
62
+ * Uses add_theme_page over add_submenu_page (props @enile8)
63
+
64
  = 0.8 =
65
 
66
  * Saves tab states using local storage
76
 
77
  = 0.6 =
78
 
79
+ * Introduces validation filters (props @_mfields)
80
+ * Better data sanitization and escaping (props @_mfields)
81
  * Updates labels in options-interface.php
82
  * Changes how checkboxes saved in database ("0" or "1")
83
  * Stores typography, backgrounds and multichecks directly as arrays