options-framework.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. <?php
  2. /*
  3. Description: A framework for building theme options.
  4. Author: Devin Price
  5. Author URI: http://www.wptheming.com
  6. License: GPLv2
  7. Version: 1.4
  8. */
  9. /*
  10. This program is free software; you can redistribute it and/or
  11. modify it under the terms of the GNU General Public License
  12. as published by the Free Software Foundation; either version 2
  13. of the License, or (at your option) any later version.
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. GNU General Public License for more details.
  18. You should have received a copy of the GNU General Public License
  19. along with this program; if not, write to the Free Software
  20. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  21. */
  22. /* If the user can't edit theme options, no use running this plugin */
  23. add_action('init', 'optionsframework_rolescheck' );
  24. function optionsframework_rolescheck () {
  25. if ( current_user_can( 'edit_theme_options' ) ) {
  26. // If the user can edit theme options, let the fun begin!
  27. add_action( 'admin_menu', 'optionsframework_add_page');
  28. add_action( 'admin_init', 'optionsframework_init' );
  29. add_action( 'admin_init', 'optionsframework_mlu_init' );
  30. add_action( 'wp_before_admin_bar_render', 'optionsframework_adminbar' );
  31. }
  32. }
  33. /* Loads the file for option sanitization */
  34. add_action('init', 'optionsframework_load_sanitization' );
  35. function optionsframework_load_sanitization() {
  36. require_once dirname( __FILE__ ) . '/options-sanitize.php';
  37. }
  38. /*
  39. * Creates the settings in the database by looping through the array
  40. * we supplied in options.php. This is a neat way to do it since
  41. * we won't have to save settings for headers, descriptions, or arguments.
  42. *
  43. * Read more about the Settings API in the WordPress codex:
  44. * http://codex.wordpress.org/Settings_API
  45. *
  46. */
  47. function optionsframework_init() {
  48. // Include the required files
  49. require_once dirname( __FILE__ ) . '/options-interface.php';
  50. require_once dirname( __FILE__ ) . '/options-medialibrary-uploader.php';
  51. // Loads the options array from the theme
  52. if ( $optionsfile = locate_template( array('includes/options.php') ) ) {
  53. require_once($optionsfile);
  54. }
  55. else if (file_exists( dirname( __FILE__ ) . '/includes/options.php' ) ) {
  56. require_once dirname( __FILE__ ) . '/includes/options.php';
  57. }
  58. $optionsframework_settings = get_option('optionsframework' );
  59. // Updates the unique option id in the database if it has changed
  60. optionsframework_option_name();
  61. // Gets the unique id, returning a default if it isn't defined
  62. if ( isset($optionsframework_settings['id']) ) {
  63. $option_name = $optionsframework_settings['id'];
  64. }
  65. else {
  66. $option_name = 'optionsframework';
  67. }
  68. // If the option has no saved data, load the defaults
  69. if ( ! get_option($option_name) ) {
  70. optionsframework_setdefaults();
  71. }
  72. // Registers the settings fields and callback
  73. register_setting( 'optionsframework', $option_name, 'optionsframework_validate' );
  74. // Change the capability required to save the 'optionsframework' options group.
  75. add_filter( 'option_page_capability_optionsframework', 'optionsframework_page_capability' );
  76. }
  77. /**
  78. * Ensures that a user with the 'edit_theme_options' capability can actually set the options
  79. * See: http://core.trac.wordpress.org/ticket/14365
  80. *
  81. * @param string $capability The capability used for the page, which is manage_options by default.
  82. * @return string The capability to actually use.
  83. */
  84. function optionsframework_page_capability( $capability ) {
  85. return 'edit_theme_options';
  86. }
  87. /*
  88. * Adds default options to the database if they aren't already present.
  89. * May update this later to load only on plugin activation, or theme
  90. * activation since most people won't be editing the options.php
  91. * on a regular basis.
  92. *
  93. * http://codex.wordpress.org/Function_Reference/add_option
  94. *
  95. */
  96. function optionsframework_setdefaults() {
  97. $optionsframework_settings = get_option('optionsframework');
  98. // Gets the unique option id
  99. $option_name = $optionsframework_settings['id'];
  100. /*
  101. * Each theme will hopefully have a unique id, and all of its options saved
  102. * as a separate option set. We need to track all of these option sets so
  103. * it can be easily deleted if someone wishes to remove the plugin and
  104. * its associated data. No need to clutter the database.
  105. *
  106. */
  107. if ( isset($optionsframework_settings['knownoptions']) ) {
  108. $knownoptions = $optionsframework_settings['knownoptions'];
  109. if ( !in_array($option_name, $knownoptions) ) {
  110. array_push( $knownoptions, $option_name );
  111. $optionsframework_settings['knownoptions'] = $knownoptions;
  112. update_option('optionsframework', $optionsframework_settings);
  113. }
  114. } else {
  115. $newoptionname = array($option_name);
  116. $optionsframework_settings['knownoptions'] = $newoptionname;
  117. update_option('optionsframework', $optionsframework_settings);
  118. }
  119. // Gets the default options data from the array in options.php
  120. $options = optionsframework_options();
  121. // If the options haven't been added to the database yet, they are added now
  122. $values = of_get_default_values();
  123. if ( isset($values) ) {
  124. add_option( $option_name, $values ); // Add option with default settings
  125. }
  126. }
  127. /* Add a subpage called "Theme Options" to the appearance menu. */
  128. if ( !function_exists( 'optionsframework_add_page' ) ) {
  129. function optionsframework_add_page() {
  130. $of_page = add_theme_page( __( 'Foto Theme Options', 'foto' ), __( 'Foto Theme Options', 'foto' ), 'edit_theme_options', 'options-framework','optionsframework_page');
  131. // Load the required CSS and javscript
  132. add_action('admin_enqueue_scripts', 'optionsframework_load_scripts');
  133. add_action( 'admin_print_styles-' . $of_page, 'optionsframework_load_styles' );
  134. }
  135. }
  136. /* Loads the CSS */
  137. function optionsframework_load_styles() {
  138. wp_enqueue_style('optionsframework', OPTIONS_FRAMEWORK_DIRECTORY . 'css/optionsframework.css');
  139. if ( !wp_style_is( 'wp-color-picker','registered' ) ) {
  140. wp_register_style('wp-color-picker', OPTIONS_FRAMEWORK_DIRECTORY . 'css/color-picker.min.css');
  141. }
  142. wp_enqueue_style( 'wp-color-picker' );
  143. }
  144. /* Loads the javascript */
  145. function optionsframework_load_scripts($hook) {
  146. if ( 'appearance_page_options-framework' != $hook )
  147. return;
  148. // Enqueue colorpicker scripts for versions below 3.5
  149. // for compatibility
  150. if ( !wp_script_is( 'wp-color-picker', 'registered' ) ) {
  151. wp_register_script( 'iris', OPTIONS_FRAMEWORK_DIRECTORY . 'js/iris.min.js', array( 'jquery-ui-draggable', 'jquery-ui-slider', 'jquery-touch-punch' ), false, 1 );
  152. wp_register_script( 'wp-color-picker', OPTIONS_FRAMEWORK_DIRECTORY . 'js/color-picker.min.js', array( 'jquery', 'iris' ) );
  153. $colorpicker_l10n = array(
  154. 'clear' => __( 'Clear', 'foto' ),
  155. 'defaultString' => __( 'Default', 'foto' ),
  156. 'pick' => __( 'Select Color', 'foto' )
  157. );
  158. wp_localize_script( 'wp-color-picker', 'wpColorPickerL10n', $colorpicker_l10n );
  159. }
  160. // Enqueue custom option panel JS
  161. wp_enqueue_script( 'options-custom', OPTIONS_FRAMEWORK_DIRECTORY . 'js/options-custom.js', array( 'jquery','wp-color-picker' ) );
  162. // Inline scripts from options-interface.php
  163. add_action( 'admin_head', 'of_admin_head' );
  164. }
  165. function of_admin_head() {
  166. // Hook to add custom scripts
  167. do_action( 'optionsframework_custom_scripts' );
  168. }
  169. /*
  170. * Builds out the options panel.
  171. *
  172. * If we were using the Settings API as it was likely intended we would use
  173. * do_settings_sections here. But as we don't want the settings wrapped in a table,
  174. * we'll call our own custom optionsframework_fields. See options-interface.php
  175. * for specifics on how each individual field is generated.
  176. *
  177. * Nonces are provided using the settings_fields()
  178. *
  179. */
  180. if ( !function_exists( 'optionsframework_page' ) ) :
  181. function optionsframework_page() {
  182. settings_errors(); ?>
  183. <div id="optionsframework-wrap" class="wrap">
  184. <?php screen_icon( 'themes' ); ?>
  185. <h2 class="nav-tab-wrapper">
  186. <?php echo optionsframework_tabs(); ?>
  187. </h2>
  188. <div id="optionsframework-metabox" class="metabox-holder">
  189. <div id="optionsframework" class="postbox">
  190. <form action="options.php" method="post">
  191. <?php settings_fields('optionsframework'); ?>
  192. <?php optionsframework_fields(); /* Settings */ ?>
  193. <div id="optionsframework-submit">
  194. <input type="submit" class="button-primary" name="update" value="<?php esc_attr_e( 'Save Options', 'foto' ); ?>" />
  195. <input type="submit" class="reset-button button-secondary" name="reset" value="<?php esc_attr_e( 'Restore Defaults', 'foto' ); ?>" onclick="return confirm( '<?php print esc_js( __( 'Click OK to reset. Any theme settings will be lost!', 'foto' ) ); ?>' );" />
  196. <div class="clear"></div>
  197. </div>
  198. </form>
  199. </div> <!-- / #container -->
  200. </div>
  201. <?php do_action('optionsframework_after'); ?>
  202. </div> <!-- / .wrap -->
  203. <?php
  204. }
  205. endif;
  206. /**
  207. * Validate Options.
  208. *
  209. * This runs after the submit/reset button has been clicked and
  210. * validates the inputs.
  211. *
  212. * @uses $_POST['reset'] to restore default options
  213. */
  214. function optionsframework_validate( $input ) {
  215. /*
  216. * Restore Defaults.
  217. *
  218. * In the event that the user clicked the "Restore Defaults"
  219. * button, the options defined in the theme's options.php
  220. * file will be added to the option for the active theme.
  221. */
  222. if ( isset( $_POST['reset'] ) ) {
  223. add_settings_error( 'options-framework', 'restore_defaults', __( 'Default options restored.', 'foto' ), 'updated fade' );
  224. return of_get_default_values();
  225. }
  226. /*
  227. * Update Settings
  228. *
  229. * This used to check for $_POST['update'], but has been updated
  230. * to be compatible with the theme customizer introduced in WordPress 3.4
  231. */
  232. $clean = array();
  233. $options = optionsframework_options();
  234. foreach ( $options as $option ) {
  235. if ( ! isset( $option['id'] ) ) {
  236. continue;
  237. }
  238. if ( ! isset( $option['type'] ) ) {
  239. continue;
  240. }
  241. $id = preg_replace( '/[^a-zA-Z0-9._\-]/', '', strtolower( $option['id'] ) );
  242. // Set checkbox to false if it wasn't sent in the $_POST
  243. if ( 'checkbox' == $option['type'] && ! isset( $input[$id] ) ) {
  244. $input[$id] = false;
  245. }
  246. // Set each item in the multicheck to false if it wasn't sent in the $_POST
  247. if ( 'multicheck' == $option['type'] && ! isset( $input[$id] ) ) {
  248. foreach ( $option['options'] as $key => $value ) {
  249. $input[$id][$key] = false;
  250. }
  251. }
  252. // For a value to be submitted to database it must pass through a sanitization filter
  253. if ( has_filter( 'of_sanitize_' . $option['type'] ) ) {
  254. $clean[$id] = apply_filters( 'of_sanitize_' . $option['type'], $input[$id], $option );
  255. }
  256. }
  257. // Hook to run after validation
  258. do_action( 'optionsframework_after_validate', $clean );
  259. return $clean;
  260. }
  261. /**
  262. * Display message when options have been saved
  263. */
  264. function optionsframework_save_options_notice() {
  265. add_settings_error( 'options-framework', 'save_options', __( 'Options saved.', 'foto' ), 'updated fade' );
  266. }
  267. add_action( 'optionsframework_after_validate', 'optionsframework_save_options_notice' );
  268. /**
  269. * Format Configuration Array.
  270. *
  271. * Get an array of all default values as set in
  272. * options.php. The 'id','std' and 'type' keys need
  273. * to be defined in the configuration array. In the
  274. * event that these keys are not present the option
  275. * will not be included in this function's output.
  276. *
  277. * @return array Rey-keyed options configuration array.
  278. *
  279. * @access private
  280. */
  281. function of_get_default_values() {
  282. $output = array();
  283. $config = optionsframework_options();
  284. foreach ( (array) $config as $option ) {
  285. if ( ! isset( $option['id'] ) ) {
  286. continue;
  287. }
  288. if ( ! isset( $option['std'] ) ) {
  289. continue;
  290. }
  291. if ( ! isset( $option['type'] ) ) {
  292. continue;
  293. }
  294. if ( has_filter( 'of_sanitize_' . $option['type'] ) ) {
  295. $output[$option['id']] = apply_filters( 'of_sanitize_' . $option['type'], $option['std'], $option );
  296. }
  297. }
  298. return $output;
  299. }
  300. /**
  301. * Add Theme Options menu item to Admin Bar.
  302. */
  303. function optionsframework_adminbar() {
  304. global $wp_admin_bar;
  305. $wp_admin_bar->add_menu( array(
  306. 'parent' => 'appearance',
  307. 'id' => 'of_theme_options',
  308. 'title' => __( 'Theme Options', 'foto' ),
  309. 'href' => admin_url( 'themes.php?page=options-framework' )
  310. ));
  311. }
  312. if ( ! function_exists( 'of_get_option' ) ) {
  313. /**
  314. * Get Option.
  315. *
  316. * Helper function to return the theme option value.
  317. * If no value has been saved, it returns $default.
  318. * Needed because options are saved as serialized strings.
  319. */
  320. function of_get_option( $name, $default = false ) {
  321. $config = get_option( 'optionsframework' );
  322. if ( ! isset( $config['id'] ) ) {
  323. return $default;
  324. }
  325. $options = get_option( $config['id'] );
  326. if ( isset( $options[$name] ) ) {
  327. return $options[$name];
  328. }
  329. return $default;
  330. }
  331. }