├── README.md ├── cfs-options-screens.php ├── index.php ├── readme.txt └── style.css /README.md: -------------------------------------------------------------------------------- 1 | This is a WordPress plugin, [Official download available on WordPress.org](http://wordpress.org/plugins/cfs-options-screens/) 2 | 3 | # Custom Field Suite Options Screens 4 | 5 | Create any number of options screens powered by [Custom Field Suite](http://customfieldsuite.com) 6 | 7 | ## Documentation 8 | 9 | Begin by creating your Field Group(s) as you normally would. *Unless setting up an [override](#overrides)*, be sure to set **NO Placement Rules**, this is handled automagically. 10 | 11 | Register an Options Screen (with all options) 12 | 13 | ```php 14 | function my_cfs_options_screens( $screens ) { 15 | $screens[] = array( 16 | 'name' => 'options', 17 | 'menu_title' => __( 'Site Options' ), 18 | 'page_title' => __( 'Customize Site Options' ), 19 | 'menu_position' => 100, 20 | 'icon' => 'dashicons-admin-generic', // optional, dashicons-admin-generic is the default 21 | 'field_groups' => array( 'My Field Group' ), // Field Group name(s) of CFS Field Group to use on this page (can also be post IDs) 22 | ); 23 | 24 | return $screens; 25 | } 26 | 27 | add_filter( 'cfs_options_screens', 'my_cfs_options_screens' ); 28 | ``` 29 | 30 | or register multiple Options Screens 31 | 32 | ```php 33 | function my_cfs_options_screens( $screens ) { 34 | 35 | // Parent 36 | $screens[] = array( 37 | 'name' => 'options', 38 | 'field_groups' => array( 'My Parent Field Group Name' ), 39 | ); 40 | 41 | // Child 42 | $screens[] = array( 43 | 'name' => 'options-nav', 44 | 'parent' => 'options', // name of the parent 45 | 'field_groups' => array( 'My Child Field Group Name' ), 46 | ); 47 | 48 | return $screens; 49 | } 50 | 51 | add_filter( 'cfs_options_screens', 'my_cfs_options_screens' ); 52 | ``` 53 | 54 | Once your options screen(s) have been registered you can attach CFS Field Groups to them. Done! 55 | 56 | ### Overrides 57 | 58 | You can also use CFS Options Screens to set up Field Group overrides, allowing a Field Group to appear both on a CFS Options Screen and a post edit screen. The CFS Options Screen will act as the default/fallback and the post edit screen will override those defaults. 59 | 60 | ```php 61 | function my_cfs_options_screens( $screens ) { 62 | $screens[] = array( 63 | 'name' => 'options', 64 | 'menu_title' => __( 'Site Options' ), 65 | 'page_title' => __( 'Customize Site Options' ), 66 | 'menu_position' => 100, 67 | 'icon' => 'dashicons-admin-generic', // optional, dashicons-admin-generic is the default 68 | 'field_groups' => array( 69 | array( 70 | 'title' => 'My CFS Field Group Name', 71 | 'has_overrides' => true, 72 | ), 73 | ), 74 | ); 75 | 76 | return $screens; 77 | } 78 | 79 | add_filter( 'cfs_options_screens', 'my_cfs_options_screens' ); 80 | ``` 81 | 82 | Check out the `cfs_options_screens_override_note_default` and `cfs_options_screens_override_note_override` filters to customize the messaging for CFS Options Screens overrides. 83 | 84 | ## Retrieve options 85 | 86 | Option retrieval requires the screen and field names, it's as easy as: 87 | 88 | ```php 89 | $value = cfs_get_option( 'options_screen_name', 'field_name_from_field_group' ); 90 | ``` 91 | -------------------------------------------------------------------------------- /cfs-options-screens.php: -------------------------------------------------------------------------------- 1 | . 25 | */ 26 | 27 | // exit if accessed directly 28 | if ( ! defined( 'ABSPATH' ) ) { 29 | exit; 30 | } 31 | 32 | class CFS_Options_Screens { 33 | 34 | /** 35 | * @var CFS_Options_Screens Singleton 36 | */ 37 | private static $instance; 38 | 39 | /** 40 | * @var array Options screens to create and utilize 41 | */ 42 | public $screens = array(); 43 | 44 | /** 45 | * @var string Post Type that powers options screens 46 | */ 47 | public $post_type = 'options'; 48 | 49 | /** 50 | * @var string Meta key used to store options screen name 51 | */ 52 | public $meta_key = '_cfs_options_screen_name'; 53 | 54 | /** 55 | * @var bool Whether we are applicable on this page load 56 | */ 57 | private $applicable = false; 58 | 59 | function __construct() { 60 | add_action( 'init', array( $this, 'init' ) ); 61 | add_action( 'admin_print_scripts', array( $this, 'admin_inline_css' ) ); 62 | 63 | add_action( 'cfs_matching_groups', array( $this, 'cfs_rule_override' ), 10, 3 ); 64 | add_action( 'cfs_form_before_fields', array( $this, 'output_override_note' ) ); 65 | } 66 | 67 | /** 68 | * Output some markup above all Field Group fields in override cases, explaining 69 | * that editing these fields will override the defaults 70 | * 71 | * @since 1.2 72 | * 73 | * @param $params 74 | * 75 | * @return void 76 | */ 77 | function output_override_note( $params ) { 78 | 79 | if ( empty( $params['field_groups'] ) ) { 80 | return; 81 | } 82 | 83 | $screens = $this->get_screens_from_field_group_id( $params['field_groups'] ); 84 | 85 | foreach ( $screens as $screen ) { 86 | foreach ( $screen['field_groups'] as $field_group ) { 87 | if ( 88 | is_array( $field_group ) 89 | && array_key_exists( 'id', $field_group ) 90 | && $params['field_groups'] == $field_group['id'] 91 | && array_key_exists( 'has_overrides', $field_group ) 92 | && ! empty( $field_group['has_overrides'] ) ) { 93 | 94 | // set up the note when editing the default 95 | $editing_default_note = __( 'Note: These defaults can be overridden when editing the applicable page.', 96 | 'cfsos' ); 97 | $editing_default_note = apply_filters( 'cfs_options_screens_override_note_default', 98 | '

' . $editing_default_note . '

', 99 | $screen 100 | ); 101 | 102 | // set up the note when editing the override 103 | /** @noinspection HtmlUnknownTarget */ 104 | $editing_override_note = sprintf( 105 | __( 'Optional: Editing these fields will override %s which will be used if these fields are left empty', 106 | 'cfsos' ), 107 | esc_url( admin_url() . $this->get_options_screen_edit_slug( $screen['id'] ) ), 108 | esc_html( $screen['menu_title'] ) 109 | ); 110 | $editing_override_note = apply_filters( 'cfs_options_screens_override_note_override', 111 | '

' . $editing_override_note . '

', 112 | $screen 113 | ); 114 | 115 | $note = $this->applicable ? $editing_default_note : $editing_override_note; 116 | 117 | echo wp_kses_post( 118 | apply_filters( 'cfs_options_screens_override_note', 119 | $note, 120 | $screen, 121 | $this->applicable // indicates whether editing the default (when true) or the override (when false) 122 | ) 123 | ); 124 | 125 | break; 126 | } 127 | } 128 | } 129 | } 130 | 131 | /** 132 | * Retrieve an array of Options Screens models that utilize a Field Group ID 133 | * 134 | * @since 1.2 135 | * @param $field_group_id 136 | * 137 | * @return array 138 | */ 139 | function get_screens_from_field_group_id( $field_group_id ) { 140 | 141 | $field_group_id = absint( $field_group_id ); 142 | $screens = array(); 143 | 144 | foreach ( $this->screens as $screen ) { 145 | 146 | $screen_field_groups = $this->get_field_group_ids( $screen['field_groups'] ); 147 | 148 | if ( in_array( $field_group_id, $screen_field_groups ) ) { 149 | $screens[] = $screen; 150 | } 151 | } 152 | 153 | return $screens; 154 | } 155 | 156 | /** 157 | * Singleton 158 | * 159 | * @return CFS_Options_Screens 160 | */ 161 | public static function instance() { 162 | if ( ! isset( self::$instance ) && ! ( self::$instance instanceof CFS_Options_Screens ) ) { 163 | self::$instance = new CFS_Options_Screens; 164 | } 165 | return self::$instance; 166 | } 167 | 168 | /** 169 | * Initialize everything 170 | */ 171 | function init() { 172 | 173 | // hide the 'Edit Post' title, 'Add New' button, and 'updated' notification when editing all options screens 174 | add_action( 'admin_enqueue_scripts', array( $this, 'assets' ) ); 175 | 176 | // reinstate the 'updated' notification 177 | add_action( 'admin_notices', array( $this, 'maybe_updated_notice' ) ); 178 | 179 | // let developers customize the post type used 180 | $this->post_type = apply_filters( 'cfs_options_screens_post_type', $this->post_type ); 181 | 182 | // register our custom post type 183 | $this->register_cpt(); 184 | 185 | // allow registration of options screens 186 | $this->screens = apply_filters( 'cfs_options_screens', $this->screens ); 187 | 188 | // make sure our posts exist 189 | $this->init_screens(); 190 | 191 | // add menus 192 | add_action( 'admin_menu', array( $this, 'maybe_add_menus' ) ); 193 | } 194 | 195 | /** 196 | * Maybe enqueue our stylesheet 197 | * @param $hook 198 | */ 199 | function assets( $hook ) { 200 | global $post; 201 | 202 | if ( 'post.php' == $hook && $this->post_type == $post->post_type ) { 203 | wp_enqueue_style( 'cfs-options-screen', plugin_dir_url( __FILE__ ) . 'style.css' ); 204 | $this->applicable = true; 205 | } 206 | 207 | return; 208 | } 209 | 210 | /** 211 | * Output CSS in the footer that will customize the page title 212 | */ 213 | function admin_inline_css() { 214 | global $post; 215 | 216 | $heading = __( 'Options' ); 217 | 218 | // determine which screen we're on 219 | if ( isset( $this->screens ) && is_object( $post ) ) { 220 | foreach ( $this->screens as $screen ) { 221 | if ( $post->ID == $screen['id'] ) { 222 | $heading = $screen['page_title']; 223 | } 224 | } 225 | } 226 | 227 | if ( $this->applicable ) { ?> 228 | 234 | post_type ) || $this->post_type !== $screen->post_type ) { 247 | return; 248 | } 249 | 250 | if ( isset( $_GET['message'] ) && $this->post_type == $post->post_type ) { 251 | ?> 252 |

253 | screens ) ) { 262 | foreach ( $this->screens as $screen_key => $screen_meta ) { 263 | $this->screens[ $screen_key ]['name'] = isset( $screen_meta['name'] ) ? $screen_meta['name'] : 'options'; 264 | $this->screens[ $screen_key ]['page_title'] = isset( $screen_meta['page_title'] ) ? $screen_meta['page_title'] : ucfirst( (string) $this->screens[ $screen_key ]['name'] ); 265 | $this->screens[ $screen_key ]['menu_title'] = isset( $screen_meta['menu_title'] ) ? $screen_meta['menu_title'] : ucfirst( (string) $this->screens[ $screen_key ]['name'] ); 266 | $this->screens[ $screen_key ]['menu_icon'] = isset( $screen_meta['icon'] ) ? $screen_meta['icon'] : 'dashicons-admin-generic'; 267 | $this->screens[ $screen_key ]['menu_position'] = isset( $screen_meta['menu_position'] ) ? $screen_meta['menu_position'] : 100; 268 | $this->screens[ $screen_key ]['field_groups'] = isset( $screen_meta['field_groups'] ) ? $screen_meta['field_groups'] : array(); 269 | 270 | $this->screens[ $screen_key ]['capability'] = apply_filters( 'cfs_options_screens_capability', 'manage_options', $screen_meta ); 271 | 272 | // check to see if the post for this screen exists 273 | $screen = get_page_by_title( $this->screens[ $screen_key ]['name'], 'OBJECT', $this->post_type ); 274 | 275 | if ( empty( $screen ) ) { 276 | // post doesn't exist, create and flag it 277 | $this->screens[ $screen_key ]['id'] = wp_insert_post( 278 | array( 279 | 'post_title' => sanitize_text_field( $this->screens[ $screen_key ]['name'] ), 280 | 'post_type' => sanitize_text_field( $this->post_type ) 281 | ) 282 | ); 283 | } else { 284 | $this->screens[ $screen_key ]['id'] = absint( $screen->ID ); 285 | } 286 | } 287 | } 288 | } 289 | 290 | /** 291 | * Registers the CPT that powers everything 292 | */ 293 | function register_cpt() { 294 | $args = array( 295 | 'label' => __( 'CFS Options Screen', '' ), 296 | 'public' => false, 297 | 'publicly_queryable' => false, 298 | 'show_ui' => true, 299 | 'show_in_nav_menus' => false, 300 | 'show_in_menu' => false, 301 | 'query_var' => false, 302 | 'rewrite' => false, 303 | 'supports' => false, 304 | ); 305 | 306 | $args = apply_filters( 'cfs_options_screens_post_type_args', $args ); 307 | 308 | register_post_type( $this->post_type, $args ); 309 | } 310 | 311 | /** 312 | * Retrieve the slug for an Options Screen edit URL 313 | * 314 | * @since 1.2 315 | * 316 | * @param $screen_id 317 | * 318 | * @return mixed 319 | */ 320 | function get_options_screen_edit_slug( $screen_id ) { 321 | $url = add_query_arg( 322 | array( 323 | 'post' => absint( $screen_id ), 324 | 'action' => 'edit', 325 | ), 326 | admin_url( 'post.php' ) 327 | ); 328 | 329 | $url = esc_url( $url ); 330 | 331 | return str_replace( admin_url(), '', $url ); 332 | } 333 | 334 | /** 335 | * Add applicable Admin menus 336 | */ 337 | function maybe_add_menus() { 338 | 339 | if ( empty( $this->screens ) ) { 340 | return; 341 | } 342 | 343 | // screens were registered during init so the ID is already prepped and the post exists 344 | foreach ( $this->screens as $screen ) { 345 | $edit_link = $this->get_options_screen_edit_slug( $screen['id'] ); 346 | 347 | // if this screen doesn't have a parent, it IS a parent 348 | if ( empty( $screen['parent'] ) ) { 349 | add_menu_page( 350 | $screen['page_title'], 351 | $screen['menu_title'], 352 | $screen['capability'], 353 | $edit_link, 354 | '', 355 | $screen['menu_icon'], 356 | $screen['menu_position'] 357 | ); 358 | } else { 359 | // it's a sub-menu, so add it to the parent 360 | $parent = (string) $screen['parent']; 361 | 362 | foreach ( $this->screens as $maybe_parent_screen ) { 363 | 364 | if ( $parent == $maybe_parent_screen['name'] ) { 365 | 366 | $parent_slug = $this->get_options_screen_edit_slug( $maybe_parent_screen['id'] ); 367 | 368 | add_submenu_page( 369 | $parent_slug, 370 | $screen['page_title'], 371 | $screen['menu_title'], 372 | $screen['capability'], 373 | $edit_link, 374 | '' 375 | ); 376 | 377 | break; 378 | } 379 | } 380 | } 381 | } 382 | } 383 | 384 | /** 385 | * By default CFS Options Screens only supports Field Groups with no placement rules 386 | * 'Overrides' are for the cases where you want to use a Field Group to facilitate setting 387 | * defaults on an Options Screen, but also allow for an override for that field data 388 | * on specific edit screens that follow the placement rules of CFS itself 389 | * 390 | * @param $matches 391 | * @param $params 392 | * @param $rule_types 393 | * @param $options_screen 394 | * 395 | * @return mixed 396 | */ 397 | function maybe_has_overrides( $matches, /** @noinspection PhpUnusedParameterInspection */ $params, /** @noinspection PhpUnusedParameterInspection */ $rule_types, $options_screen ) { 398 | // didn't find an options screen? 399 | if ( empty( $options_screen ) ) { 400 | return $matches; 401 | } 402 | 403 | // segment defaults 404 | if ( empty( $options_screen['field_groups'] ) ) { 405 | return $matches; 406 | } 407 | 408 | // move over all of these Field Groups into $matches 409 | foreach ( $options_screen['field_groups'] as $field_group ) { 410 | $key = $this->get_field_group_id( $field_group ); 411 | 412 | if ( ! array_key_exists( $key, $matches ) ) { 413 | $matches[ $key ] = get_the_title( $key ); 414 | } 415 | } 416 | 417 | return $matches; 418 | } 419 | 420 | /** 421 | * Version 1.2 introduced overrides, so we need back compat 422 | * 423 | * @since 1.2 424 | * 425 | * @param $field_group 426 | * 427 | * @return int 428 | */ 429 | function get_field_group_id( $field_group ) { 430 | 431 | if ( is_string( $field_group ) ) { 432 | 433 | $field_group = $this->get_field_group_id_from_title( $field_group ); 434 | 435 | } elseif ( is_array( $field_group ) ) { 436 | 437 | if ( array_key_exists( 'id', $field_group ) ) { 438 | 439 | $field_group = $field_group['id']; 440 | 441 | } elseif ( array_key_exists( 'title', $field_group ) ) { 442 | 443 | $field_group = $this->get_field_group_id_from_title( $field_group['title'] ); 444 | 445 | } 446 | 447 | } 448 | 449 | return absint( $field_group ); 450 | } 451 | 452 | /** 453 | * Retrieve CFS Field Group ID from title 454 | * 455 | * @param string $title 456 | * 457 | * @return int 458 | */ 459 | function get_field_group_id_from_title( $title = '' ) { 460 | $id = 0; 461 | 462 | $field_group_obj = get_page_by_title( $title, 'OBJECT', 'cfs' ); 463 | 464 | if ( $field_group_obj instanceof WP_Post ) { 465 | $id = $field_group_obj->ID; 466 | } 467 | 468 | return $id; 469 | } 470 | 471 | /** 472 | * Retrieve the CFS Options Screen model from its post ID 473 | * 474 | * @param $post_id 475 | * 476 | * @return bool|array 477 | */ 478 | function get_options_screen_from_post_id( $post_id ) { 479 | $options_screen = false; 480 | 481 | // we need to validate that this post ID is actually a registered options screen 482 | if ( ! empty( $this->screens ) ) { 483 | foreach ( $this->screens as $screen_key => $screen_meta ) { 484 | if ( isset( $screen_meta['id'] ) && $post_id == $screen_meta['id'] ) { 485 | $options_screen = $screen_meta; 486 | break; 487 | } 488 | } 489 | } 490 | 491 | return $options_screen; 492 | } 493 | 494 | /** 495 | * Retrieve an array of Field Group IDs from a field_groups definition, takes into consideration 496 | * whether you want to include overrides or not 497 | * 498 | * @since 1.2 499 | * @param $field_groups 500 | * @param bool $include_overrides 501 | * 502 | * @return array 503 | */ 504 | function get_field_group_ids( $field_groups, $include_overrides = true ) { 505 | 506 | $field_group_ids = array(); 507 | 508 | foreach ( $field_groups as $field_group ) { 509 | 510 | if ( 511 | ( $include_overrides || is_numeric( $field_group ) ) // include by intention or by legacy field_groups value (pre 1.2) 512 | || ( 513 | ! $include_overrides // don't include overrides 514 | && is_array( $field_group ) // 1.2 or later 515 | && array_key_exists( 'has_overrides', $field_group ) && empty( $field_group['has_overrides'] ) // does not have overrides 516 | ) ) { 517 | // include it in the list 518 | $field_group_ids[] = $this->get_field_group_id( $field_group ); 519 | } elseif ( is_string( $field_group ) ) { 520 | $field_group = $this->get_field_group_id_from_title( $field_group ); 521 | if ( ! empty( $field_group ) ) { 522 | $field_group_ids[] = absint( $field_group ); 523 | } 524 | } 525 | } 526 | 527 | return $field_group_ids; 528 | } 529 | 530 | 531 | /** 532 | * Custom Field Suite doesn't support single post IDs for placement rules, so we're going to inject our own. 533 | * 534 | * @param $matches 535 | * @param $params 536 | * @param $rule_types 537 | * 538 | * @return mixed 539 | */ 540 | function cfs_rule_override( $matches, $params, $rule_types ) { 541 | 542 | if ( is_array( $params ) || ! is_numeric( $params ) ) { 543 | return $matches; 544 | } 545 | 546 | $post_id = absint( $params ); 547 | $options_screen = $this->get_options_screen_from_post_id( $post_id ); 548 | 549 | $matches = $this->maybe_has_overrides( $matches, $params, $rule_types, $options_screen ); 550 | 551 | // let developers override the matches and parameters 552 | // maybe_has_overrides() use case: setting up 'defaults' for a Field Group - you want the 553 | // same Field Group to appear both in it's defined locations (which when defined omit it 554 | // from $matches from the start) and in the options screen to act as the defaults 555 | $matches = apply_filters( 'cfs_options_screens_rule_matches', $matches, $params, $rule_types, $this ); 556 | 557 | if ( $options_screen && is_array( $matches ) && ! empty( $matches ) ) { 558 | 559 | // we need to strip out the Field Groups that are not registered with this options screen 560 | $field_group_ids = $this->get_field_group_ids( $options_screen['field_groups'] ); 561 | 562 | foreach ( $matches as $match_key => $match_title ) { 563 | if ( ! in_array( $match_key, $field_group_ids ) ) { 564 | unset( $matches[ $match_key ] ); 565 | } 566 | } 567 | 568 | } else { 569 | 570 | // we need to strip out all Field Groups related to Options Screens else they'll show up where we don't want them 571 | $options_screens_field_groups = array(); 572 | 573 | foreach ( $this->screens as $screen_meta ) { 574 | $field_group_ids = $this->get_field_group_ids( $screen_meta['field_groups'], false ); 575 | $options_screens_field_groups = array_merge( $options_screens_field_groups, $field_group_ids ); 576 | } 577 | 578 | foreach ( $matches as $match_key => $match_title ) { 579 | if ( in_array( $match_key, $options_screens_field_groups ) ) { 580 | unset( $matches[ $match_key ] ); 581 | } 582 | } 583 | } 584 | 585 | return $matches; 586 | } 587 | 588 | } 589 | 590 | /** 591 | * Retrieve an option from a settings screen 592 | * Usage: $value = cfs_get_option( 'options', 'my_field' ); 593 | * 594 | * @param string $screen The options screen name 595 | * @param string $field The field name 596 | * 597 | * @return bool|mixed The field value as returned by the CFS API 598 | */ 599 | if ( ! function_exists( 'cfs_get_option' ) ) { 600 | function cfs_get_option( $screen = 'options', $field = '', $post_id = 0 ) { 601 | $value = false; 602 | 603 | if ( ! function_exists( 'CFS' ) ) { 604 | return false; 605 | } 606 | 607 | $cfs_options_screens = CFS_Options_Screens::instance(); 608 | 609 | if ( ! empty( $cfs_options_screens->screens ) ) { 610 | foreach ( $cfs_options_screens->screens as $screen_meta ) { 611 | if ( $screen == $screen_meta['name'] ) { 612 | 613 | // support the overrides concept by first checking for the override 614 | // and automatically falling back to the Options Screen value if needed 615 | $post_id = empty( $post_id ) ? get_queried_object_id() : absint( $post_id ); 616 | 617 | if ( ! empty( $post_id ) ) { 618 | $value = CFS()->get( $field, absint( $post_id ) ); 619 | } 620 | 621 | if ( empty( $value ) ) { 622 | $value = CFS()->get( $field, $screen_meta['id'] ); 623 | } 624 | 625 | break; 626 | } 627 | } 628 | } 629 | 630 | return $value; 631 | } 632 | } 633 | 634 | 635 | 636 | /** 637 | * Retrieve all option from a settings screen 638 | * Usage: $value = cfs_get_option( 'options' ); 639 | * 640 | * @param string $screen The options screen name 641 | * 642 | * @return bool|mixed The field value as returned by the CFS API 643 | */ 644 | if ( ! function_exists( 'cfs_get_options' ) ) { 645 | function cfs_get_options( $screen = 'options' ) { 646 | $value = false; 647 | 648 | if ( ! function_exists( 'CFS' ) ) { 649 | return false; 650 | } 651 | 652 | $cfs_options_screens = CFS_Options_Screens::instance(); 653 | 654 | if ( ! empty( $cfs_options_screens->screens ) ) { 655 | foreach ( $cfs_options_screens->screens as $screen_meta ) { 656 | if ( $screen == $screen_meta['name'] ) { 657 | $value = CFS()->get( false, $screen_meta['id'] ); 658 | } 659 | } 660 | } 661 | 662 | return $value; 663 | } 664 | } 665 | 666 | /** 667 | * Initializer 668 | * 669 | * @return CFS_Options_Screens 670 | */ 671 | if ( ! function_exists( 'cfs_options_screens_init' ) ) { 672 | function cfs_options_screens_init() { 673 | $cfs_options_screens = CFS_Options_Screens::instance(); 674 | return $cfs_options_screens; 675 | } 676 | } 677 | 678 | // kickoff 679 | cfs_options_screens_init(); 680 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 'options', 24 | 'menu_title' => __( 'Site Options' ), 25 | 'page_title' => __( 'Customize Site Options' ), 26 | 'menu_position' => 100, 27 | 'icon' => 'dashicons-admin-generic', // optional, dashicons-admin-generic is the default 28 | 'field_groups' => array( 'My Field Group' ), // Field Group name(s) of CFS Field Group to use on this page (can also be post IDs) 29 | ); 30 | 31 | return $screens; 32 | } 33 | 34 | add_filter( 'cfs_options_screens', 'my_cfs_options_screens' );` 35 | 36 | = Retrieve your options like so: = 37 | 38 | `$value = cfs_get_option( 'options_screen_name', 'cfs_field_name_from_field_group' );` 39 | 40 | You can set up multiple top level and/or children options pages by adding a `parent` argument when registering your screen: 41 | 42 | `function my_cfs_options_screens( $screens ) { 43 | 44 | // Parent 45 | $screens[] = array( 46 | 'name' => 'options', 47 | 'field_groups' => array( 'My Parent Field Group Name' ), 48 | ); 49 | 50 | // Child 51 | $screens[] = array( 52 | 'name' => 'options-nav', 53 | 'parent' => 'options', // name of the parent 54 | 'field_groups' => array( 'My Child Field Group Name' ), 55 | ); 56 | 57 | return $screens; 58 | } 59 | 60 | add_filter( 'cfs_options_screens', 'my_cfs_options_screens' );` 61 | 62 | You can also use CFS Options Screens to set up Field Group 'defaults', allowing a Field Group to appear both on a CFS Options Screen and a post edit screen. The CFS Options Screen will act as the default/fallback and the post edit screen will override those defaults. 63 | 64 | `function my_cfs_options_screens( $screens ) { 65 | $screens[] = array( 66 | 'name' => 'options', 67 | 'menu_title' => __( 'Site Options' ), 68 | 'page_title' => __( 'Customize Site Options' ), 69 | 'menu_position' => 100, 70 | 'icon' => 'dashicons-admin-generic', // optional, dashicons-admin-generic is the default 71 | 'field_groups' => array( 72 | array( 73 | 'title' => 'My CFS Field Group Name', 74 | 'has_overrides' => true, 75 | ), 76 | ), 77 | ); 78 | 79 | return $screens; 80 | } 81 | 82 | add_filter( 'cfs_options_screens', 'my_cfs_options_screens' );` 83 | 84 | Check out the `cfs_options_screens_override_note_default` and `cfs_options_screens_override_note_override` filters to customize the messaging for CFS Options Screens overrides. 85 | 86 | == Installation == 87 | 88 | 1. Upload `cfs-options-screens` to the `/wp-content/plugins/` directory 89 | 1. Activate the plugin through the 'Plugins' menu in WordPress 90 | 1. Register your options screen(s) using the code snippets from this readme 91 | 92 | == Frequently Asked Questions == 93 | 94 | = How do I add a Field Group to my options screen? = 95 | 96 | You must specify the Field Group Title(s) in the `field_groups` parameter when using the `cfs_options_screens` hook 97 | 98 | = How do I retrieve saved options? = 99 | 100 | `$value = cfs_get_option( 'options_screen_name', 'field_name_from_field_group' );` 101 | 102 | == Changelog == 103 | 104 | = 1.2.7 = 105 | * Add support for using CFS Field Group title instead of ID 106 | 107 | = 1.2.5 = 108 | * Better handling of overrides when not viewing a single post 109 | 110 | = 1.2.4 = 111 | * PHP Warning cleanup 112 | 113 | = 1.2.3 = 114 | * Fixed an issue that would output override note if any Field Group on an Options Screen had one 115 | * Fixed an issue where multiple override notes would be output when there were multiple override Field Groups 116 | 117 | = 1.2.1 = 118 | * PHP Warning cleanup for `cfs_get_option` 119 | 120 | = 1.2 = 121 | * Added support for Field Group defaults/overrides where a Field Group can appear both on a CFS Options Screen and a post edit screen, and 'fall back' to the CFS Options Screen where applicable 122 | 123 | = 1.1.2 = 124 | * Refined the arguments for the underlying CPT to hide it from the Admin menu, filterable with `cfs_options_screens_post_type_args` 125 | 126 | = 1.1.1 = 127 | * Fixed an issue resulting in a change in WordPress 4.4 that prevented editing options screens 128 | 129 | = 1.1 = 130 | * Added new `cfs_get_options()` function to retrieve all CFS data for an options screen 131 | 132 | = 1.0.3 = 133 | * Fixed an issue in WordPress 4.3 where customized edit screen titles were not shown 134 | 135 | = 1.0.2 = 136 | * Only show 'Saved' update notice when editing an options screen 137 | 138 | = 1.0.1 = 139 | * Proper page title is now output when editing a screen 140 | 141 | = 1.0 = 142 | * Initial release 143 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | #wpbody-content .wrap > h1, 2 | #wpbody-content .wrap > h2 { 3 | position:relative; 4 | visibility:hidden; 5 | } 6 | 7 | #wpbody-content .wrap > h1:after, 8 | #wpbody-content .wrap > h2:after { 9 | display:block; 10 | position:absolute; 11 | left:0; 12 | top:0.4em; 13 | visibility:visible; 14 | } 15 | 16 | #wpbody-content #message, 17 | #wpbody-content #minor-publishing, 18 | #wpbody-content #submitdiv .handlediv, 19 | #wpbody-content #submitdiv .hndle, 20 | #wpbody-content #delete-action, 21 | #wpbody-content #screen-meta, 22 | #wpbody-content #screen-meta-links, 23 | #wpbody-content #post-body-content { 24 | display:none; 25 | } 26 | 27 | #wpbody-content #major-publishing-actions { 28 | border-top:0; 29 | } 30 | 31 | #wpbody-content .wrap { 32 | padding-top:10px; 33 | } 34 | --------------------------------------------------------------------------------