PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / 7.9.8
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI v7.9.8
8.0.4 8.0.3 8.0.1 8.0.2 8.0.0 7.9.9.7 7.9.9.6 7.9.9.5 7.9.9.4 7.9.9.3 7.9.9.2 7.9.9.1 7.9.9 7.9.8 7.9.7 7.9.6 7.9.5 7.9.4 7.9.3 7.9.2 7.9.1 7.9.0 7.8.9 7.8.8 7.8.7 All 46 releases
gamipress / libraries / cmb2 / includes / CMB2_Options_Hookup.php

CMB2_Options_Hookup.php in GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI 7.9.8, at libraries/cmb2/includes/CMB2_Options_Hookup.php

391 lines 11.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handles hooking CMB2 forms/metaboxes into the post/attachement/user screens
4 * and handles hooking in and saving those fields.
5 *
6 * @since 2.0.0
7 *
8 * @category WordPress_Plugin
9 * @package CMB2
10 * @author CMB2 team
11 * @license GPL-2.0+
12 * @link https://cmb2.io
13 */
14 class CMB2_Options_Hookup extends CMB2_Hookup {
15
16 /**
17 * The object type we are performing the hookup for
18 *
19 * @var string
20 * @since 2.0.9
21 */
22 protected $object_type = 'options-page';
23
24 /**
25 * Options page key.
26 *
27 * @var string
28 * @since 2.2.5
29 */
30 protected $option_key = '';
31
32 /**
33 * Constructor
34 *
35 * @since 2.0.0
36 * @param CMB2 $cmb The CMB2 object to hookup.
37 * @param string $option_key Option key to use.
38 */
39 public function __construct( CMB2 $cmb, $option_key ) {
40 $this->cmb = $cmb;
41 $this->option_key = $option_key;
42 }
43
44 public function hooks() {
45 if ( empty( $this->option_key ) ) {
46 return;
47 }
48
49 if ( ! $this->cmb->prop( 'autoload', true ) ) {
50 // Disable option autoload if requested.
51 add_filter( "cmb2_should_autoload_{$this->option_key}", '__return_false' );
52 }
53
54 /**
55 * For WP < 4.7. Ensure the register_setting function exists.
56 */
57 if ( ! CMB2_Utils::wp_at_least( '4.7' ) && ! function_exists( 'register_setting' ) ) {
58 require_once ABSPATH . 'wp-admin/includes/plugin.php';
59 }
60
61 // Register setting to cmb2 group.
62 register_setting( 'cmb2', $this->option_key, array(
63 'type' => 'array',
64 'sanitize_callback' => 'cmb2_settings_sanitization_cb',
65 ) );
66
67 // Handle saving the data.
68 add_action( 'admin_post_' . $this->option_key, array( $this, 'save_options' ) );
69
70 // Optionally network_admin_menu.
71 $hook = $this->cmb->prop( 'admin_menu_hook' );
72
73 // Hook in to add our menu.
74 add_action( $hook, array( $this, 'options_page_menu_hooks' ), $this->get_priority() );
75
76 // If in the network admin, need to use get/update_site_option.
77 if ( 'network_admin_menu' === $hook ) {
78 // Override CMB's getter.
79 add_filter( "cmb2_override_option_get_{$this->option_key}", array( $this, 'network_get_override' ), 10, 2 );
80 // Override CMB's setter.
81 add_filter( "cmb2_override_option_save_{$this->option_key}", array( $this, 'network_update_override' ), 10, 2 );
82 }
83 }
84
85 /**
86 * Hook up our admin menu item and admin page.
87 *
88 * @since 2.2.5
89 *
90 * @return void
91 */
92 public function options_page_menu_hooks() {
93 $parent_slug = $this->cmb->prop( 'parent_slug' );
94 $title = $this->cmb->prop( 'title' );
95 $menu_title = $this->cmb->prop( 'menu_title', $title );
96 $capability = $this->cmb->prop( 'capability' );
97 $callback = array( $this, 'options_page_output' );
98
99 if ( $parent_slug ) {
100 $page_hook = add_submenu_page(
101 $parent_slug,
102 $title,
103 $menu_title,
104 $capability,
105 $this->option_key,
106 $callback
107 );
108 } else {
109 $page_hook = add_menu_page(
110 $title,
111 $menu_title,
112 $capability,
113 $this->option_key,
114 $callback,
115 $this->cmb->prop( 'icon_url' ),
116 $this->cmb->prop( 'position' )
117 );
118 }
119
120 if ( $this->cmb->prop( 'cmb_styles' ) ) {
121 // Include CMB CSS in the head to avoid FOUC.
122 add_action( "admin_print_styles-{$page_hook}", array( 'CMB2_Hookup', 'enqueue_cmb_css' ) );
123 }
124
125 $this->maybe_register_message();
126 }
127
128 /**
129 * If there is a message callback, let it determine how to register the message,
130 * else add a settings message if on this settings page.
131 *
132 * @since 2.2.6
133 *
134 * @return void
135 */
136 public function maybe_register_message() {
137 $is_options_page = self::is_page( $this->option_key );
138 $should_notify = ! $this->cmb->prop( 'disable_settings_errors' ) && isset( $_GET['settings-updated'] ) && $is_options_page;
139 $is_updated = $should_notify && 'true' === $_GET['settings-updated'];
140 $setting = "{$this->option_key}-notices";
141 $code = '';
142 $message = __( 'Nothing to update.', 'cmb2' );
143 $type = 'notice-warning';
144
145 if ( $is_updated ) {
146 $message = __( 'Settings updated.', 'cmb2' );
147 $type = 'updated';
148 }
149
150 // Check if parameter has registered a callback.
151 if ( $cb = $this->cmb->maybe_callback( 'message_cb' ) ) {
152
153 /**
154 * The 'message_cb' callback will receive the following parameters.
155 * Unless there are other reasons for notifications, the callback should only
156 * `add_settings_error()` if `$args['should_notify']` is truthy.
157 *
158 * @param CMB2 $cmb The CMB2 object.
159 * @param array $args {
160 * An array of message arguments
161 *
162 * @type bool $is_options_page Whether current page is this options page.
163 * @type bool $should_notify Whether options were saved and we should be notified.
164 * @type bool $is_updated Whether options were updated with save (or stayed the same).
165 * @type string $setting For add_settings_error(), Slug title of the setting to which
166 * this error applies.
167 * @type string $code For add_settings_error(), Slug-name to identify the error.
168 * Used as part of 'id' attribute in HTML output.
169 * @type string $message For add_settings_error(), The formatted message text to display
170 * to the user (will be shown inside styled `<div>` and `<p>` tags).
171 * Will be 'Settings updated.' if $is_updated is true, else 'Nothing to update.'
172 * @type string $type For add_settings_error(), Message type, controls HTML class.
173 * Accepts 'error', 'updated', '', 'notice-warning', etc.
174 * Will be 'updated' if $is_updated is true, else 'notice-warning'.
175 * }
176 */
177 $args = compact( 'is_options_page', 'should_notify', 'is_updated', 'setting', 'code', 'message', 'type' );
178
179 $this->cmb->do_callback( $cb, $args );
180
181 } elseif ( $should_notify ) {
182
183 add_settings_error( $setting, $code, $message, $type );
184 }
185 }
186
187 /**
188 * Display options-page output. To override, set 'display_cb' box property.
189 *
190 * @since 2.2.5
191 */
192 public function options_page_output() {
193 $this->maybe_output_settings_notices();
194
195 $callback = $this->cmb->prop( 'display_cb' );
196 if ( is_callable( $callback ) ) {
197 return call_user_func( $callback, $this );
198 }
199
200 ?>
201 <div class="wrap cmb2-options-page option-<?php echo esc_attr( sanitize_html_class( $this->option_key ) ); ?>">
202 <?php if ( $this->cmb->prop( 'title' ) ) : ?>
203 <h2><?php echo wp_kses_post( $this->cmb->prop( 'title' ) ); ?></h2>
204 <?php endif; ?>
205 <?php $this->options_page_tab_nav_output(); ?>
206 <form class="cmb-form" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="POST" id="<?php echo $this->cmb->cmb_id; ?>" enctype="multipart/form-data" encoding="multipart/form-data">
207 <input type="hidden" name="action" value="<?php echo esc_attr( $this->option_key ); ?>">
208 <?php $this->options_page_metabox(); ?>
209 <?php submit_button( esc_attr( $this->cmb->prop( 'save_button' ) ), 'primary', 'submit-cmb' ); ?>
210 </form>
211 </div>
212 <?php
213 }
214
215 /**
216 * Display options-page Tab Navigation output.
217 *
218 * @since 2.9.0
219 */
220 public function options_page_tab_nav_output() {
221 $tabs = $this->get_tab_group_tabs();
222 if ( empty( $tabs ) ) {
223 return;
224 }
225 ?>
226 <h2 class="nav-tab-wrapper">
227 <?php foreach ( $tabs as $option_key => $tab_title ) : ?>
228 <a class="nav-tab<?php if ( self::is_page( $option_key ) ) : ?> nav-tab-active<?php endif; ?>" href="<?php menu_page_url( $option_key ); ?>"><?php echo wp_kses_post( $tab_title ); ?></a>
229 <?php endforeach; ?>
230 </h2>
231 <?php
232 }
233
234 /**
235 * Outputs the settings notices if a) not a sub-page of 'options-general.php'
236 * (because settings_errors() already called in wp-admin/options-head.php),
237 * and b) the 'disable_settings_errors' prop is not set or truthy.
238 *
239 * @since 2.2.5
240 * @return void
241 */
242 public function maybe_output_settings_notices() {
243 global $parent_file;
244
245 // The settings sub-pages will already have settings_errors() called in wp-admin/options-head.php.
246 if ( 'options-general.php' !== $parent_file ) {
247 settings_errors( "{$this->option_key}-notices" );
248 }
249 }
250
251 /**
252 * Gets navigation tabs array for CMB2 options pages which share the
253 * same tab_group property.
254 *
255 * @since 2.4.0
256 * @return array Array of tab information ($option_key => $tab_title)
257 */
258 public function get_tab_group_tabs() {
259 $tab_group = $this->cmb->prop( 'tab_group' );
260 $tabs = array();
261
262 if ( $tab_group ) {
263 $boxes = CMB2_Boxes::get_by( 'tab_group', $tab_group );
264
265 foreach ( $boxes as $cmb_id => $cmb ) {
266 $option_key = $cmb->options_page_keys();
267
268 // Must have an option key, must be an options page box.
269 if ( ! isset( $option_key[0] ) || 'options-page' !== $cmb->mb_object_type() ) {
270 continue;
271 }
272
273 $tabs[ $option_key[0] ] = $cmb->prop( 'tab_title', $cmb->prop( 'title' ) );
274 }
275 }
276
277 return apply_filters( 'cmb2_tab_group_tabs', $tabs, $tab_group );
278 }
279
280 /**
281 * Display metaboxes for an options-page object.
282 *
283 * @since 2.2.5
284 */
285 public function options_page_metabox() {
286 $this->show_form_for_type( 'options-page' );
287 }
288
289 /**
290 * Save data from options page, then redirects back.
291 *
292 * @since 2.2.5
293 * @return void
294 */
295 public function save_options() {
296 $url = wp_get_referer();
297 if ( ! $url ) {
298 $url = admin_url();
299 }
300
301 if (
302 $this->can_save( 'options-page' )
303 // check params.
304 && isset( $_POST['submit-cmb'], $_POST['action'] )
305 && $this->option_key === $_POST['action']
306 ) {
307
308 $updated = $this->cmb
309 ->save_fields( $this->option_key, $this->cmb->object_type(), $_POST )
310 ->was_updated(); // Will be false if no values were changed/updated.
311
312 $url = add_query_arg( 'settings-updated', $updated ? 'true' : 'false', $url );
313 }
314
315 wp_safe_redirect( esc_url_raw( $url ), 303 /* WP_Http::SEE_OTHER */ );
316 exit;
317 }
318
319 /**
320 * Replaces get_option with get_site_option.
321 *
322 * @since 2.2.5
323 *
324 * @param mixed $test Not used.
325 * @param mixed $default Default value to use.
326 * @return mixed Value set for the network option.
327 */
328 public function network_get_override( $test, $default = false ) {
329 return get_site_option( $this->option_key, $default );
330 }
331
332 /**
333 * Replaces update_option with update_site_option.
334 *
335 * @since 2.2.5
336 *
337 * @param mixed $test Not used.
338 * @param mixed $option_value Value to use.
339 * @return bool Success/Failure
340 */
341 public function network_update_override( $test, $option_value ) {
342 return update_site_option( $this->option_key, $option_value );
343 }
344
345 /**
346 * Determines if given page slug matches the 'page' GET query variable.
347 *
348 * @since 2.4.0
349 *
350 * @param string $page Page slug.
351 * @return boolean
352 */
353 public static function is_page( $page ) {
354 return isset( $_GET['page'] ) && $page === $_GET['page'];
355 }
356
357 /**
358 * Magic getter for our object.
359 *
360 * @param string $field Property to retrieve.
361 *
362 * @throws Exception Throws an exception if the field is invalid.
363 * @return mixed
364 */
365 public function __get( $field ) {
366 switch ( $field ) {
367 case 'object_type':
368 case 'option_key':
369 case 'cmb':
370 return $this->{$field};
371 default:
372 throw new Exception( sprintf( esc_html__( 'Invalid %1$s property: %2$s', 'cmb2' ), __CLASS__, $field ) );
373 }
374 }
375 }
376
377 if( ! function_exists( 'cmb2_settings_sanitization_cb' ) ) {
378 function cmb2_settings_sanitization_cb( $settings ) {
379 global $cmb2_settings_sanitizated;
380
381 if( $cmb2_settings_sanitizated === true ) {
382 return $settings;
383 }
384
385 $cmb2_settings_sanitizated = true;
386
387 return map_deep( $settings, 'sanitize_text_field' );
388 }
389
390 }
391