Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Patch to Michael Simpson's Wordpress Plugin Template to store options as an array with a single wp_options entry.
diff --git a/wp-content/plugins/xxx/XXX_OptionsManager.php b/wp-content/plugins/xxx/XXX_OptionsManager.php
index 4315551..6ed8f27 100644
--- a/wp-content/plugins/xxx/XXX_OptionsManager.php
+++ b/wp-content/plugins/xxx/XXX_OptionsManager.php
@@ -21,16 +21,15 @@
class XXX_OptionsManager {
- public function getOptionNamePrefix() {
- return get_class($this) . '_';
+ public function getOptionName() {
+ return get_class( $this );
}
/**
* Define your options meta data here as an array, where each element in the array
* @return array of key=>display-name and/or key=>array(display-name, choice1, choice2, ...)
- * key: an option name for the key (this name will be given a prefix when stored in
- * the database to ensure it does not conflict with other plugin options)
+ * key: an option name for the key
* value: can be one of two things:
* (1) string display name for displaying the name of the option to the user on a web page
* (2) array where the first element is a display name (as above) and the rest of
@@ -61,16 +60,21 @@ class XXX_OptionsManager {
}
/**
- * Cleanup: remove all options from the DB
+ * Cleanup: remove all known options from the DB
* @return void
*/
protected function deleteSavedOptions() {
$optionMetaData = $this->getOptionMetaData();
- if (is_array($optionMetaData)) {
- foreach ($optionMetaData as $aOptionKey => $aOptionMeta) {
- $prefixedOptionName = $this->prefix($aOptionKey); // how it is stored in DB
- delete_option($prefixedOptionName);
+ if ( is_array( $optionMetaData ) ) {
+ $options = get_option( $this->getOptionName() );
+ if ( ! is_array( $options ) )
+ $options = array();
+ foreach ( $optionMetaData as $aOptionKey => $aOptionMeta ) {
+ if ( isset( $options[$aOptionKey] ) ) {
+ unset( $options[$aOptionKey] );
+ }
}
+ update_option( $this->getOptionName(), $options );
}
}
@@ -83,83 +87,72 @@ class XXX_OptionsManager {
}
/**
- * Get the prefixed version input $name suitable for storing in WP options
- * Idempotent: if $optionName is already prefixed, it is not prefixed again, it is returned without change
- * @param $name string option name to prefix. Defined in settings.php and set as keys of $this->optionMetaData
- * @return string
- */
- public function prefix($name) {
- $optionNamePrefix = $this->getOptionNamePrefix();
- if (strpos($name, $optionNamePrefix) === 0) { // 0 but not false
- return $name; // already prefixed
- }
- return $optionNamePrefix . $name;
- }
-
- /**
- * Remove the prefix from the input $name.
- * Idempotent: If no prefix found, just returns what was input.
- * @param $name string
- * @return string $optionName without the prefix.
- */
- public function &unPrefix($name) {
- $optionNamePrefix = $this->getOptionNamePrefix();
- if (strpos($name, $optionNamePrefix) === 0) {
- return substr($name, strlen($optionNamePrefix));
- }
- return $name;
- }
-
- /**
- * A wrapper function delegating to WP get_option() but it prefixes the input $optionName
- * to enforce "scoping" the options in the WP options table thereby avoiding name conflicts
+ * A wrapper function delegating to WP get_option().
+ *
* @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
* @param $default string default value to return if the option is not set
* @return string the value from delegated call to get_option(), or optional default value
* if option is not set.
*/
- public function getOption($optionName, $default = null) {
- $prefixedOptionName = $this->prefix($optionName); // how it is stored in DB
- $retVal = get_option($prefixedOptionName);
- if (!$retVal && $default) {
+ public function getOption( $optionName, $default = null ) {
+ $options = get_option( $this->getOptionName() );
+ if ( ! is_array( $options ) )
+ $options = array();
+
+ if ( isset( $options[$optionName] ) ) {
+ $retVal = $options[$optionName];
+ } elseif ( $default ) {
$retVal = $default;
- }
+ } else {
+ $retVal = '';
+ }
+
return $retVal;
}
/**
- * A wrapper function delegating to WP delete_option() but it prefixes the input $optionName
- * to enforce "scoping" the options in the WP options table thereby avoiding name conflicts
+ * A wrapper function delegating to WP delete_option().
+ *
* @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
- * @return bool from delegated call to delete_option()
+ * @return bool indicating whether wp_options was changed or not
*/
- public function deleteOption($optionName) {
- $prefixedOptionName = $this->prefix($optionName); // how it is stored in DB
- return delete_option($prefixedOptionName);
+ public function deleteOption( $optionName ) {
+ $options = get_option( $this->getOptionName() );
+ if ( ! is_array( $options ) )
+ $options = array();
+
+ if ( isset( $options[$optionName] ) ) {
+ unset( $options[$optionName] );
+ return update_option( $this->getOptionName(), $options );
+ } else {
+ return true;
+ }
}
/**
- * A wrapper function delegating to WP add_option() but it prefixes the input $optionName
- * to enforce "scoping" the options in the WP options table thereby avoiding name conflicts
+ * A wrapper function delegating to updateOption().
+ *
* @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
* @param $value mixed the new value
- * @return null from delegated call to delete_option()
+ * @return bool from delegated call to updateOption()
*/
- public function addOption($optionName, $value) {
- $prefixedOptionName = $this->prefix($optionName); // how it is stored in DB
- return add_option($prefixedOptionName, $value);
+ public function addOption( $optionName, $value ) {
+ return updateOption( $optionName, $value );
}
/**
- * A wrapper function delegating to WP add_option() but it prefixes the input $optionName
- * to enforce "scoping" the options in the WP options table thereby avoiding name conflicts
+ * A wrapper function delegating to WP update_option().
+ *
* @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
* @param $value mixed the new value
- * @return null from delegated call to delete_option()
+ * @return bool from delegated call to update_option()
*/
- public function updateOption($optionName, $value) {
- $prefixedOptionName = $this->prefix($optionName); // how it is stored in DB
- return update_option($prefixedOptionName, $value);
+ public function updateOption( $optionName, $value ) {
+ $options = get_option( $this->getOptionName() );
+ if ( ! is_array( $options ) )
+ $options = array();
+ $options[$optionName] = $value;
+ return update_option( $this->getOptionName(), $options );
}
/**
<?php
/*
"WordPress Plugin Template" Copyright (C) 2013 Michael Simpson (email : michael.d.simpson@gmail.com)
This file is part of WordPress Plugin Template for WordPress.
WordPress Plugin Template is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
WordPress Plugin Template is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Contact Form to Database Extension.
If not, see http://www.gnu.org/licenses/gpl-3.0.html
*/
class XXX_OptionsManager {
public function getOptionName() {
return get_class( $this );
}
/**
* Define your options meta data here as an array, where each element in the array
* @return array of key=>display-name and/or key=>array(display-name, choice1, choice2, ...)
* key: an option name for the key
* value: can be one of two things:
* (1) string display name for displaying the name of the option to the user on a web page
* (2) array where the first element is a display name (as above) and the rest of
* the elements are choices of values that the user can select
* e.g.
* array(
* 'item' => 'Item:', // key => display-name
* 'rating' => array( // key => array ( display-name, choice1, choice2, ...)
* 'CanDoOperationX' => array('Can do Operation X', 'Administrator', 'Editor', 'Author', 'Contributor', 'Subscriber'),
* 'Rating:', 'Excellent', 'Good', 'Fair', 'Poor')
*/
public function getOptionMetaData() {
return array();
}
/**
* @return array of string name of options
*/
public function getOptionNames() {
return array_keys($this->getOptionMetaData());
}
/**
* Override this method to initialize options to default values and save to the database with add_option
* @return void
*/
protected function initOptions() {
}
/**
* Cleanup: remove all known options from the DB
* @return void
*/
protected function deleteSavedOptions() {
$optionMetaData = $this->getOptionMetaData();
if ( is_array( $optionMetaData ) ) {
$options = get_option( $this->getOptionName() );
if ( ! is_array( $options ) )
$options = array();
foreach ( $optionMetaData as $aOptionKey => $aOptionMeta ) {
if ( isset( $options[$aOptionKey] ) ) {
unset( $options[$aOptionKey] );
}
}
update_option( $this->getOptionName(), $options );
}
}
/**
* @return string display name of the plugin to show as a name/title in HTML.
* Just returns the class name. Override this method to return something more readable
*/
public function getPluginDisplayName() {
return get_class($this);
}
/**
* A wrapper function delegating to WP get_option().
*
* @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
* @param $default string default value to return if the option is not set
* @return string the value from delegated call to get_option(), or optional default value
* if option is not set.
*/
public function getOption( $optionName, $default = null ) {
$options = get_option( $this->getOptionName() );
if ( ! is_array( $options ) )
$options = array();
if ( isset( $options[$optionName] ) ) {
$retVal = $options[$optionName];
} elseif ( $default ) {
$retVal = $default;
} else {
$retVal = '';
}
return $retVal;
}
/**
* A wrapper function delegating to WP delete_option().
*
* @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
* @return bool indicating whether wp_options was changed or not
*/
public function deleteOption( $optionName ) {
$options = get_option( $this->getOptionName() );
if ( ! is_array( $options ) )
$options = array();
if ( isset( $options[$optionName] ) ) {
unset( $options[$optionName] );
return update_option( $this->getOptionName(), $options );
} else {
return true;
}
}
/**
* A wrapper function delegating to updateOption().
*
* @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
* @param $value mixed the new value
* @return bool from delegated call to updateOption()
*/
public function addOption( $optionName, $value ) {
return updateOption( $optionName, $value );
}
/**
* A wrapper function delegating to WP update_option().
*
* @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
* @param $value mixed the new value
* @return bool from delegated call to update_option()
*/
public function updateOption( $optionName, $value ) {
$options = get_option( $this->getOptionName() );
if ( ! is_array( $options ) )
$options = array();
$options[$optionName] = $value;
return update_option( $this->getOptionName(), $options );
}
/**
* A Role Option is an option defined in getOptionMetaData() as a choice of WP standard roles, e.g.
* 'CanDoOperationX' => array('Can do Operation X', 'Administrator', 'Editor', 'Author', 'Contributor', 'Subscriber')
* The idea is use an option to indicate what role level a user must minimally have in order to do some operation.
* So if a Role Option 'CanDoOperationX' is set to 'Editor' then users which role 'Editor' or above should be
* able to do Operation X.
* Also see: canUserDoRoleOption()
* @param $optionName
* @return string role name
*/
public function getRoleOption($optionName) {
$roleAllowed = $this->getOption($optionName);
if (!$roleAllowed || $roleAllowed == '') {
$roleAllowed = 'Administrator';
}
return $roleAllowed;
}
/**
* Given a WP role name, return a WP capability which only that role and roles above it have
* http://codex.wordpress.org/Roles_and_Capabilities
* @param $roleName
* @return string a WP capability or '' if unknown input role
*/
protected function roleToCapability($roleName) {
switch ($roleName) {
case 'Super Admin':
return 'manage_options';
case 'Administrator':
return 'manage_options';
case 'Editor':
return 'publish_pages';
case 'Author':
return 'publish_posts';
case 'Contributor':
return 'edit_posts';
case 'Subscriber':
return 'read';
case 'Anyone':
return 'read';
}
return '';
}
/**
* @param $roleName string a standard WP role name like 'Administrator'
* @return bool
*/
public function isUserRoleEqualOrBetterThan($roleName) {
if ('Anyone' == $roleName) {
return true;
}
$capability = $this->roleToCapability($roleName);
return current_user_can($capability);
}
/**
* @param $optionName string name of a Role option (see comments in getRoleOption())
* @return bool indicates if the user has adequate permissions
*/
public function canUserDoRoleOption($optionName) {
$roleAllowed = $this->getRoleOption($optionName);
if ('Anyone' == $roleAllowed) {
return true;
}
return $this->isUserRoleEqualOrBetterThan($roleAllowed);
}
/**
* see: http://codex.wordpress.org/Creating_Options_Pages
* @return void
*/
public function createSettingsMenu() {
$pluginName = $this->getPluginDisplayName();
//create new top-level menu
add_menu_page($pluginName . ' Plugin Settings',
$pluginName,
'administrator',
get_class($this),
array(&$this, 'settingsPage')
/*,plugins_url('/images/icon.png', __FILE__)*/); // if you call 'plugins_url; be sure to "require_once" it
//call register settings function
add_action('admin_init', array(&$this, 'registerSettings'));
}
public function registerSettings() {
$settingsGroup = get_class($this) . '-settings-group';
$optionMetaData = $this->getOptionMetaData();
foreach ($optionMetaData as $aOptionKey => $aOptionMeta) {
register_setting($settingsGroup, $aOptionMeta);
}
}
/**
* Creates HTML for the Administration page to set options for this plugin.
* Override this method to create a customized page.
* @return void
*/
public function settingsPage() {
if (!current_user_can('manage_options')) {
wp_die(__('You do not have sufficient permissions to access this page.', 'xxx'));
}
$optionMetaData = $this->getOptionMetaData();
// Save Posted Options
if ($optionMetaData != null) {
foreach ($optionMetaData as $aOptionKey => $aOptionMeta) {
if (isset($_POST[$aOptionKey])) {
$this->updateOption($aOptionKey, $_POST[$aOptionKey]);
}
}
}
// HTML for the page
$settingsGroup = get_class($this) . '-settings-group';
?>
<div class="wrap">
<h2><?php _e('System Settings', 'xxx'); ?></h2>
<table class="form-table"><tbody>
<tr><td><?php _e('System', 'xxx'); ?></td><td><?php echo php_uname(); ?></td></tr>
<tr><td><?php _e('PHP Version', 'xxx'); ?></td>
<td><?php echo phpversion(); ?>
<?php
if (version_compare('5.2', phpversion()) > 0) {
echo '&nbsp;&nbsp;&nbsp;<span style="background-color: #ffcc00;">';
_e('(WARNING: This plugin may not work properly with versions earlier than PHP 5.2)', 'xxx');
echo '</span>';
}
?>
</td>
</tr>
<tr><td><?php _e('MySQL Version', 'xxx'); ?></td>
<td><?php echo $this->getMySqlVersion() ?>
<?php
echo '&nbsp;&nbsp;&nbsp;<span style="background-color: #ffcc00;">';
if (version_compare('5.0', $this->getMySqlVersion()) > 0) {
_e('(WARNING: This plugin may not work properly with versions earlier than MySQL 5.0)', 'xxx');
}
echo '</span>';
?>
</td>
</tr>
</tbody></table>
<h2><?php echo $this->getPluginDisplayName(); echo ' '; _e('Settings', 'xxx'); ?></h2>
<form method="post" action="">
<?php settings_fields($settingsGroup); ?>
<table class="form-table"><tbody>
<?php
if ($optionMetaData != null) {
foreach ($optionMetaData as $aOptionKey => $aOptionMeta) {
$displayText = is_array($aOptionMeta) ? $aOptionMeta[0] : $aOptionMeta;
?>
<tr valign="top">
<th scope="row"><p><label for="<?php echo $aOptionKey ?>"><?php echo $displayText ?></label></p></th>
<td>
<?php $this->createFormControl($aOptionKey, $aOptionMeta, $this->getOption($aOptionKey)); ?>
</td>
</tr>
<?php
}
}
?>
</tbody></table>
<p class="submit">
<input type="submit" class="button-primary"
value="<?php _e('Save Changes', 'xxx') ?>"/>
</p>
</form>
</div>
<?php
}
/**
* Helper-function outputs the correct form element (input tag, select tag) for the given item
* @param $aOptionKey string name of the option (un-prefixed)
* @param $aOptionMeta mixed meta-data for $aOptionKey (either a string display-name or an array(display-name, option1, option2, ...)
* @param $savedOptionValue string current value for $aOptionKey
* @return void
*/
protected function createFormControl($aOptionKey, $aOptionMeta, $savedOptionValue) {
if (is_array($aOptionMeta) && count($aOptionMeta) >= 2) { // Drop-down list
$choices = array_slice($aOptionMeta, 1);
?>
<p><select name="<?php echo $aOptionKey ?>" id="<?php echo $aOptionKey ?>">
<?php
foreach ($choices as $aChoice) {
$selected = ($aChoice == $savedOptionValue) ? 'selected' : '';
?>
<option value="<?php echo $aChoice ?>" <?php echo $selected ?>><?php echo $this->getOptionValueI18nString($aChoice) ?></option>
<?php
}
?>
</select></p>
<?php
}
else { // Simple input field
?>
<p><input type="text" name="<?php echo $aOptionKey ?>" id="<?php echo $aOptionKey ?>"
value="<?php echo esc_attr($savedOptionValue) ?>" size="50"/></p>
<?php
}
}
/**
* Override this method and follow its format.
* The purpose of this method is to provide i18n display strings for the values of options.
* For example, you may create a options with values 'true' or 'false'.
* In the options page, this will show as a drop down list with these choices.
* But when the the language is not English, you would like to display different strings
* for 'true' and 'false' while still keeping the value of that option that is actually saved in
* the DB as 'true' or 'false'.
* To do this, follow the convention of defining option values in getOptionMetaData() as canonical names
* (what you want them to literally be, like 'true') and then add each one to the switch statement in this
* function, returning the "__()" i18n name of that string.
* @param $optionValue string
* @return string __($optionValue) if it is listed in this method, otherwise just returns $optionValue
*/
protected function getOptionValueI18nString($optionValue) {
switch ($optionValue) {
case 'true':
return __('true', 'xxx');
case 'false':
return __('false', 'xxx');
case 'Administrator':
return __('Administrator', 'xxx');
case 'Editor':
return __('Editor', 'xxx');
case 'Author':
return __('Author', 'xxx');
case 'Contributor':
return __('Contributor', 'xxx');
case 'Subscriber':
return __('Subscriber', 'xxx');
case 'Anyone':
return __('Anyone', 'xxx');
}
return $optionValue;
}
/**
* Query MySQL DB for its version
* @return string|false
*/
protected function getMySqlVersion() {
global $wpdb;
$rows = $wpdb->get_results('select version() as mysqlversion');
if (!empty($rows)) {
return $rows[0]->mysqlversion;
}
return false;
}
/**
* If you want to generate an email address like "no-reply@your-site.com" then
* you can use this to get the domain name part.
* E.g. 'no-reply@' . $this->getEmailDomain();
* This code was stolen from the wp_mail function, where it generates a default
* from "wordpress@your-site.com"
* @return string domain name
*/
public function getEmailDomain() {
// Get the site domain and get rid of www.
$sitename = strtolower($_SERVER['SERVER_NAME']);
if (substr($sitename, 0, 4) == 'www.') {
$sitename = substr($sitename, 4);
}
return $sitename;
}
}
@emcniece

This comment has been minimized.

Copy link

commented Mar 28, 2014

Should line 140 be $this->updateOption() instead? https://gist.github.com/emcniece/9843769

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.