| 1 |
<?php |
| 2 |
|
| 3 |
|
| 4 |
namespace JP\CC\Admin; |
| 5 |
|
| 6 |
use JP\CC\Helpers; |
| 7 |
use JP\CC\Options; |
| 8 |
|
| 9 |
if ( ! defined( 'ABSPATH' ) ) { |
| 10 |
exit; |
| 11 |
} |
| 12 |
|
| 13 |
class Settings { |
| 14 |
|
| 15 |
private static $title; |
| 16 |
private static $_tabs; |
| 17 |
private static $_prefix; |
| 18 |
|
| 19 |
public static function init( $title, $tabs = array() ) { |
| 20 |
static::$title = $title; |
| 21 |
static::$_tabs = $tabs; |
| 22 |
static::$_prefix = trim( Options::$_prefix, '_' ) . '_'; |
| 23 |
Settings\Restrictions::init(); |
| 24 |
add_action( 'admin_init', array( __CLASS__, 'register_settings' ) ); |
| 25 |
add_filter( static::$_prefix . 'settings_sanitize_text', array( __CLASS__, 'sanitize_text_field' ) ); |
| 26 |
add_filter( static::$_prefix . 'settings_sanitize_field_restrictions', array( __CLASS__, 'sanitize_restrictions' ), 10, 2 ); |
| 27 |
} |
| 28 |
|
| 29 |
/** |
| 30 |
* Render settings page with tabs. |
| 31 |
*/ |
| 32 |
public static function page() { |
| 33 |
?> |
| 34 |
|
| 35 |
<div class="wrap"> |
| 36 |
<h1><?php echo esc_html( static::$title ); ?></h1> |
| 37 |
|
| 38 |
<h2 id="<?php echo static::$_prefix; ?>tabs" class="nav-tab-wrapper"><?php |
| 39 |
foreach ( static::tabs() as $id => $tab ) { |
| 40 |
|
| 41 |
$active = $tab['active'] ? ' nav-tab-active' : ''; |
| 42 |
|
| 43 |
echo '<a href="' . esc_url( $tab['url'] ) . '" title="' . esc_attr( $tab['label'] ) . '" class="nav-tab' . $active . '">'; |
| 44 |
echo esc_html( $tab['label'] ); |
| 45 |
echo '</a>'; |
| 46 |
} ?> |
| 47 |
</h2> |
| 48 |
|
| 49 |
<form id="<?php echo static::$_prefix; ?>settings" method="post" action="options.php"> |
| 50 |
<?php do_action( static::$_prefix . 'form_nonce' ); ?> |
| 51 |
<?php settings_fields( static::$_prefix . 'settings' ); ?> |
| 52 |
<div id="poststuff"> |
| 53 |
<div id="post-body" class="metabox-holder columns-1"> |
| 54 |
<div id="post-body-content"> |
| 55 |
<div id="tab_container"><?php |
| 56 |
if ( static::active_tab() == 'restrictions' ) : |
| 57 |
do_action( 'jp_cc_restriction_editor' ); |
| 58 |
else : ?> |
| 59 |
<table class="form-table"><?php |
| 60 |
Setting_Callbacks::init( static::$_prefix, Options::get_all() ); |
| 61 |
do_settings_fields( static::$_prefix . 'settings_' . static::active_tab(), static::$_prefix . 'settings_' . static::active_tab() ); ?> |
| 62 |
</table> |
| 63 |
<?php endif; |
| 64 |
|
| 65 |
submit_button(); ?> |
| 66 |
</div> |
| 67 |
<!-- #tab_container--> |
| 68 |
</div> |
| 69 |
</div> |
| 70 |
<br class="clear" /> |
| 71 |
</div> |
| 72 |
</form> |
| 73 |
</div> |
| 74 |
|
| 75 |
<?php |
| 76 |
} |
| 77 |
|
| 78 |
/** |
| 79 |
* Returns all settings tabs, with labels, urls & status. |
| 80 |
* |
| 81 |
* @return array |
| 82 |
*/ |
| 83 |
public static function tabs() { |
| 84 |
|
| 85 |
static $tabs; |
| 86 |
|
| 87 |
if ( ! isset( $tabs ) ) { |
| 88 |
$tabs = array(); |
| 89 |
|
| 90 |
$registered_settings = static::registered_settings(); |
| 91 |
|
| 92 |
reset( static::$_tabs ); |
| 93 |
|
| 94 |
$active_tab = isset( $_GET['tab'] ) ? $_GET['tab'] : key( static::$_tabs ); |
| 95 |
|
| 96 |
foreach ( static::$_tabs as $id => $label ) { |
| 97 |
if ( ! empty( $registered_settings[ $id ] ) ) { |
| 98 |
$tabs[ $id ] = array( |
| 99 |
'label' => $label, |
| 100 |
'active' => $id == $active_tab, |
| 101 |
'url' => add_query_arg( array( |
| 102 |
'settings-updated' => false, |
| 103 |
'tab' => $id, |
| 104 |
) ), |
| 105 |
); |
| 106 |
} |
| 107 |
} |
| 108 |
} |
| 109 |
|
| 110 |
return $tabs; |
| 111 |
} |
| 112 |
|
| 113 |
/** |
| 114 |
* Check for the active / current tab. |
| 115 |
* |
| 116 |
* @return bool|string |
| 117 |
*/ |
| 118 |
public static function active_tab() { |
| 119 |
static $active; |
| 120 |
|
| 121 |
if ( ! isset( $active ) ) { |
| 122 |
$active = false; |
| 123 |
foreach ( static::tabs() as $id => $tab ) { |
| 124 |
if ( $tab['active'] ) { |
| 125 |
$active = $id; |
| 126 |
} |
| 127 |
} |
| 128 |
} |
| 129 |
|
| 130 |
return $active; |
| 131 |
} |
| 132 |
|
| 133 |
/** |
| 134 |
* Retrieve the array of plugin settings |
| 135 |
* |
| 136 |
* @since 1.0.0 |
| 137 |
* @return array |
| 138 |
*/ |
| 139 |
public static function registered_settings() { |
| 140 |
|
| 141 |
static $settings; |
| 142 |
|
| 143 |
if ( ! isset( $settings ) ) { |
| 144 |
|
| 145 |
/** |
| 146 |
* 'Whitelisted' settings, filters are provided for each settings. |
| 147 |
*/ |
| 148 |
$settings = array( |
| 149 |
/** General Settings */ |
| 150 |
'restrictions' => apply_filters( static::$_prefix . 'settings_restrictions', array( |
| 151 |
'restrictions' => array( |
| 152 |
'id' => 'restrictions', |
| 153 |
'type' => 'hook', |
| 154 |
), |
| 155 |
) ), |
| 156 |
'general' => apply_filters( static::$_prefix . 'settings_general', array( |
| 157 |
'default_denial_message' => array( |
| 158 |
'id' => 'default_denial_message', |
| 159 |
'label' => __( 'Default Denial Message', 'content-control' ), |
| 160 |
'type' => 'rich_editor', |
| 161 |
), |
| 162 |
) ), |
| 163 |
/** Addon Settings */ |
| 164 |
//'addons' => apply_filters( static::$_prefix . 'settings_addons', array() ), |
| 165 |
//'licenses' => apply_filters( static::$_prefix . 'settings_licenses', array() ), |
| 166 |
/** Misc Settings */ |
| 167 |
'misc' => apply_filters( static::$_prefix . 'settings_misc', array() ), |
| 168 |
); |
| 169 |
|
| 170 |
$settings = apply_filters( static::$_prefix . 'registered_settings', $settings ); |
| 171 |
} |
| 172 |
|
| 173 |
return $settings; |
| 174 |
} |
| 175 |
|
| 176 |
public static function register_settings() { |
| 177 |
|
| 178 |
if ( false == get_option( static::$_prefix . 'settings' ) ) { |
| 179 |
add_option( static::$_prefix . 'settings' ); |
| 180 |
} |
| 181 |
|
| 182 |
foreach ( static::registered_settings() as $tab => $settings ) { |
| 183 |
|
| 184 |
$page = static::$_prefix . 'settings_' . $tab; |
| 185 |
|
| 186 |
add_settings_section( $page, __return_null(), '__return_false', $page ); |
| 187 |
|
| 188 |
foreach ( $settings as $id => $option ) { |
| 189 |
|
| 190 |
$name = isset( $option['label'] ) ? $option['label'] : ''; |
| 191 |
|
| 192 |
if ( method_exists( '\\JP\CC\Admin\Setting_Callbacks', $option['type'] ) ) { |
| 193 |
$callback = array( '\\JP\CC\Admin\Setting_Callbacks', $option['type'] ); |
| 194 |
} elseif ( function_exists( static::$_prefix . $option['type'] . '_callback' ) ) { |
| 195 |
$callback = static::$_prefix . $option['type'] . '_callback'; |
| 196 |
} else { |
| 197 |
$callback = array( '\\JP\CC\Setting_Callbacks', 'missing_callback' ); |
| 198 |
} |
| 199 |
|
| 200 |
add_settings_field( static::$_prefix . 'settings_' . $option['id'], $name, $callback, $page, $page, array( |
| 201 |
'section' => $tab, |
| 202 |
'id' => isset( $option['id'] ) ? $option['id'] : $id, |
| 203 |
'desc' => ! empty( $option['desc'] ) ? $option['desc'] : '', |
| 204 |
// TODO replace the hardcoded names in Setting_Callbacks with this value. |
| 205 |
'name' => isset( $option['name'] ) ? $option['name'] : null, |
| 206 |
'size' => isset( $option['size'] ) ? $option['size'] : null, |
| 207 |
'options' => isset( $option['options'] ) ? $option['options'] : '', |
| 208 |
'std' => isset( $option['std'] ) ? $option['std'] : '', |
| 209 |
'min' => isset( $option['min'] ) ? $option['min'] : null, |
| 210 |
'max' => isset( $option['max'] ) ? $option['max'] : null, |
| 211 |
'step' => isset( $option['step'] ) ? $option['step'] : null, |
| 212 |
'chosen' => isset( $option['chosen'] ) ? $option['chosen'] : null, |
| 213 |
'placeholder' => isset( $option['placeholder'] ) ? $option['placeholder'] : null, |
| 214 |
'allow_blank' => isset( $option['allow_blank'] ) ? $option['allow_blank'] : true, |
| 215 |
'readonly' => isset( $option['readonly'] ) ? $option['readonly'] : false, |
| 216 |
) ); |
| 217 |
} |
| 218 |
|
| 219 |
} |
| 220 |
|
| 221 |
// Creates our settings in the options table |
| 222 |
register_setting( static::$_prefix . 'settings', static::$_prefix . 'settings', array( __CLASS__, 'settings_sanitize' ) ); |
| 223 |
|
| 224 |
} |
| 225 |
|
| 226 |
public static function settings_sanitize( $input ) { |
| 227 |
|
| 228 |
|
| 229 |
if ( empty( $_POST['_wp_http_referer'] ) ) { |
| 230 |
return $input; |
| 231 |
} |
| 232 |
|
| 233 |
$current_values = Options::get_all(); |
| 234 |
|
| 235 |
parse_str( $_POST['_wp_http_referer'], $referrer ); |
| 236 |
|
| 237 |
$prefix = static::$_prefix; |
| 238 |
|
| 239 |
$tab = isset( $referrer['tab'] ) ? $referrer['tab'] : static::active_tab(); |
| 240 |
|
| 241 |
$settings = static::registered_settings(); |
| 242 |
|
| 243 |
$input = $input ? $input : array(); |
| 244 |
|
| 245 |
// Apply a filter per tab like jp_cc_settings_general_sanitize |
| 246 |
$input = apply_filters( "{$prefix}settings_{$tab}_sanitize", $input ); |
| 247 |
|
| 248 |
// Loop through each setting being saved and pass it through a sanitization filter |
| 249 |
foreach ( $input as $key => $value ) { |
| 250 |
|
| 251 |
// Field id specific filter |
| 252 |
$value = apply_filters( "{$prefix}settings_sanitize_field_{$key}", $value ); |
| 253 |
|
| 254 |
// Get the setting type (checkbox, select, etc) |
| 255 |
$type = isset( $settings[ $tab ][ $key ]['type'] ) ? $settings[ $tab ][ $key ]['type'] : false; |
| 256 |
|
| 257 |
if ( $type ) { |
| 258 |
// Field type specific filter |
| 259 |
$value = apply_filters( "{$prefix}settings_sanitize_{$type}", $value, $key ); |
| 260 |
} |
| 261 |
|
| 262 |
// General filter |
| 263 |
$input[ $key ] = apply_filters( "{$prefix}settings_sanitize", $value, $key ); |
| 264 |
|
| 265 |
} |
| 266 |
|
| 267 |
// Loop through the whitelist and unset any that are empty for the tab being saved |
| 268 |
if ( ! empty( $settings[ $tab ] ) ) { |
| 269 |
foreach ( $settings[ $tab ] as $key => $value ) { |
| 270 |
// settings used to have numeric keys, now they have keys that match the option ID. This ensures both methods work |
| 271 |
if ( is_numeric( $key ) ) { |
| 272 |
$key = $value['id']; |
| 273 |
} |
| 274 |
if ( empty( $input[ $key ] ) ) { |
| 275 |
unset( $current_values[ $key ] ); |
| 276 |
} |
| 277 |
} |
| 278 |
} |
| 279 |
|
| 280 |
// Merge our new settings with the existing |
| 281 |
$output = array_merge( $current_values, $input ); |
| 282 |
|
| 283 |
add_settings_error( 'jp-cc-notices', '', __( 'Settings updated.', 'content-control' ), 'updated' ); |
| 284 |
|
| 285 |
return $output; |
| 286 |
} |
| 287 |
|
| 288 |
public static function sanitize_restrictions( $restrictions = array() ) { |
| 289 |
if ( ! empty( $restrictions ) ) { |
| 290 |
|
| 291 |
foreach ( $restrictions as $key => $restriction ) { |
| 292 |
|
| 293 |
if ( is_string( $restriction ) ) { |
| 294 |
try { |
| 295 |
$restriction = json_decode( $restriction ); |
| 296 |
} catch ( \Exception $e ) {}; |
| 297 |
} |
| 298 |
|
| 299 |
$restrictions[ $key ] = Helpers::object_to_array( $restriction ); |
| 300 |
|
| 301 |
} |
| 302 |
} |
| 303 |
|
| 304 |
return $restrictions; |
| 305 |
} |
| 306 |
|
| 307 |
|
| 308 |
/** |
| 309 |
* Sanitize text fields |
| 310 |
* |
| 311 |
* @param array $input The field value |
| 312 |
* |
| 313 |
* @return string $input Sanitizied value |
| 314 |
*/ |
| 315 |
public static function sanitize_text_field( $input ) { |
| 316 |
return trim( $input ); |
| 317 |
} |
| 318 |
|
| 319 |
} |
| 320 |
|