1

So, I was carefully following the Wordpress Codex to create a Custom options panel for a custom post type.(https://codex.wordpress.org/Creating_Options_Pages) Specifically, Example 2.

Everything was actually working well with the post types and the options panel. However, when I later went to the Media Library it wouldn't load. I tried signing out of the admin area but when I tried to sign back in and it wouldn't load. I had to manually remove the plugin from the directory to get back in.

I uploaded an older version of the plugin that did not have the options panel and working fine again.

I thought I would try going line by line to see what the bug was and it seems that as soon as I declare the class, it crashes the admin area and I have to delete it and start over.

I have been scouring the forums and can't figure it out. I have created custom post type plugins in the past but haven't added this options page before so I am really stuck.

CUSTOM POST TYPE PLUGIN CODE: EDIT: (I BROKE UP THE CODE INTO TWO SECTIONS TO MAKE IT A BIT EASIER. THIS IS THE WORKING CODE THAT FOR CREATING THE POST TYPES)

    <?php

/*
 * Plugin Name: Umbrella Custom Post Types
 * Description: Adds custom post types to the top_block page
 * Version 2.0
 * Author: Kevin Meadows 
 * License: GPL2
 */
function umbrella_custom_post_types(){
/*Register Top Block*/
    $labels = array(
        'name'               => 'Top Blocks',
        'singular_name'      => 'Home',
        'menu_name'          => 'Top Blocks',
        'name_admin_bar'     => 'Top Block',
        'add_new'            => 'Add New',
        'add_new_item'       => 'Add New Top Block',
        'new_item'           => 'New Top Block',
        'edit_item'          => 'Edit Top Block',
        'view_item'          => 'View Top Block',
        'all_items'          => 'All Top Blocks',
        'search_items'       => 'Search Top Blocks',
        'parent_item_colon'  => 'Parent Top Blocks:',
        'not_found'          => 'No Top Blocks found.',
        'not_found_in_trash' => 'No Top Blocks found in Trash.',
    );

    $args = array(
        'labels'             => $labels,
        'public'             => true,
        'publicly_queryable' => true,
        'show_ui'            => true,
        'show_in_menu'       => true,
        'menu_icon'          => 'dashicons-admin-home',
        'query_var'          => true,
        'rewrite'            => array( 'slug' => 'top-blocks' ),
        'capability_type'    => 'page',
        'has_archive'        => false,
        'hierarchical'       => false,
        'menu_position'      => 4,
        'supports'           => array( 'title' , 'excerpt' , 'thumbnail' ),
        'show_in_rest'       => true
    );
    register_post_type('top-blocks', $args);

/*Register Stories*/
    $labels = array(
        'name'               => 'Stories',
        'singular_name'      => 'Story',
        'menu_name'          => 'Stories',
        'name_admin_bar'     => 'Story',
        'add_new'            => 'Add New',
        'add_new_item'       => 'Add New Story',
        'new_item'           => 'New Story',
        'edit_item'          => 'Edit Story',
        'view_item'          => 'View Story',
        'all_items'          => 'All Stories',
        'search_items'       => 'Search Stories',
        'parent_item_colon'  => 'Parent Stories:',
        'not_found'          => 'No stories found.',
        'not_found_in_trash' => 'No stories found in Trash.',
    );

    $args = array(
        'labels'             => $labels,
        'public'             => true,
        'publicly_queryable' => true,
        'show_ui'            => true,
        'show_in_menu'       => true,
        'menu_icon'          => 'dashicons-book-alt',
        'query_var'          => true,
        'rewrite'            => array( 'slug' => 'stories' ),
        'capability_type'    => 'post',
        'has_archive'        => true,
        'hierarchical'       => false,
        'menu_position'      => 5,
        'supports'           => array( 'title', 'editor', 'thumbnail' , 'excerpt' ),
        'show_in_rest'       => true
    );
    register_post_type('stories', $args);  

/*Impact Post*/
    $labels = array(
        'name'               => 'Impact Blocks',
        'singular_name'      => 'Impact',
        'menu_name'          => 'Impact Blocks',
        'name_admin_bar'     => 'Impact',
        'add_new'            => 'Add New',
        'add_new_item'       => 'Add New Impact',
        'new_item'           => 'New Impact',
        'edit_item'          => 'Edit Impact',
        'view_item'          => 'View Impact',
        'all_items'          => 'All Impact Blocks',
        'search_items'       => 'Search Impact Blocks',
        'parent_item_colon'  => 'Parent Impact Blocks:',
        'not_found'          => 'No impacts found.',
        'not_found_in_trash' => 'No impacts found in Trash.',
    );

    $args = array(
        'labels'             => $labels,
        'public'             => true,
        'publicly_queryable' => true,
        'show_ui'            => true,
        'show_in_menu'       => true,
        'menu_icon'          => 'dashicons-groups',
        'query_var'          => true,
        'rewrite'            => array( 'slug' => 'impact-blocks' ),
        'capability_type'    => 'post',
        'has_archive'        => true,
        'hierarchical'       => false,
        'menu_position'      => 5,
        'supports'           => array( 'title' , 'editor', 'excerpt' , 'thumbnail'),
        'show_in_rest'       => true
    );
    register_post_type('impact-blocks', $args); 

/*Register Testimonials*/ 
    $labels = array(
        'name'               => 'Testimonials',
        'singular_name'      => 'Testimonial',
        'menu_name'          => 'Testimonials',
        'name_admin_bar'     => 'Testimonial',
        'add_new'            => 'Add New',
        'add_new_item'       => 'Add New Testimonial',
        'new_item'           => 'New Testimonial',
        'edit_item'          => 'Edit Testimonial',
        'view_item'          => 'View Testimonial',
        'all_items'          => 'All Testimonials',
        'search_items'       => 'Search Testimonials',
        'parent_item_colon'  => 'Parent Testimonials:',
        'not_found'          => 'No testimonials found.',
        'not_found_in_trash' => 'No testimonials found in Trash.',
    );

    $args = array(
        'labels'             => $labels,
        'public'             => true,
        'publicly_queryable' => true,
        'show_ui'            => true,
        'show_in_menu'       => true,
        'menu_icon'          => 'dashicons-editor-quote',
        'query_var'          => true,
        'rewrite'            => array( 'slug' => 'testimonials' ),
        'capability_type'    => 'post',
        'has_archive'        => true,
        'hierarchical'       => false,
        'menu_position'      => 5,
        'supports'           => array( 'title', 'thumbnail' , 'excerpt' ),
        'show_in_rest'       => true
    );
    register_post_type('testimonials', $args); 




}

add_action('init' , 'umbrella_custom_post_types');

add_action("admin_init", "admin_init");

    function admin_init(){
      add_meta_box("links", "Page Link", "links", "top-blocks", "normal", "low");
          add_meta_box("location", "Location", "location", "testimonials", "normal", "low");
          add_meta_box("role", "Role", "role", "testimonials", "normal", "low");
          add_meta_box("nation", "Nation", "nation", "stories", "normal", "low");
    }


    function links() {
      global $post;
      $custom = get_post_custom($post->ID);
        $page_link = $custom["page_link"][0];

      ?>
          <h4>Page Link:</h4>
          <p>Paste in the title of the page you want the block to link to.</p>
          <p><em>The title must be exactly the same as the title of the post.</em></p>
      <textarea cols="50" rows="1" name="page_link"><?php echo $page_link; ?></textarea>

      <?php
    }

        function location() {
      global $post;
      $custom = get_post_custom($post->ID);
        $location = $custom["location"][0];

      ?>
          <h4>Location:</h4>
          <p>Enter the location of the person giving the testimonial</p>
      <textarea cols="50" rows="1" name="location"><?php echo $location; ?></textarea>

      <?php
    }

        function role() {
      global $post;
      $custom = get_post_custom($post->ID);
        $role = $custom["role"][0];

      ?>
          <h4>Role:</h4>
          <p>Enter the role of the person giving the testimonial</p>
      <textarea cols="50" rows="1" name="role"><?php echo $role; ?></textarea>

      <?php
    }


        function nation() {
      global $post;
      $custom = get_post_custom($post->ID);
        $nation = $custom["nation"][0];

      ?>
          <p>Select the nation in which the project is being completed.</p>
          <p><em>This will display a little flag next to the title.</em></p>
          <p>The current nation is: <?php echo $nation; ?></p>
          <select name="nation">
              <option value="ug">Uganda</option>
              <option value="nl">The Netherlands</option>
              <option value="other">Other</option>
          </select>

      <?php
    }

    add_action('save_post', 'save_details');

    function save_details(){
            global $post;
                update_post_meta($post->ID, "page_link", $_POST["page_link"]);
                update_post_meta($post->ID, "location", $_POST["location"]);
                update_post_meta($post->ID, "role", $_POST["role"]);
                update_post_meta($post->ID, "nation", $_POST["nation"]);
        }

function make_page_link($custom_post_key){
    if(post_custom($custom_post_key)) {
                    $page_title = post_custom('page_link'); 
                    $page_array = get_page_by_title( $page_title );
                    $page_id = $page_array->ID;
                    $link = get_site_url() . '/' . get_page_uri($page_id);
                    return $link;
                    } 
}   




function my_rewrite_flush() {
    umbrella_custom_post_types();
    flush_rewrite_rules();
}
register_activation_hook( __FILE__, 'my_rewrite_flush' );

?>

EDIT: HERE IS THE CODE FOR ONLY THE OPTIONS PAGE It actually works and does what it is supposed to. However, it prevents the media library from loading and then if I sign out of the admin area I can't get back in without deleting the plugin.

    <?php
class UoHSettingsPage
{
    /**
     * Holds the values to be used in the fields callbacks
     */
    private $options;

    /**
     * Start up
     */
    public function __construct()
    {
        add_action( 'admin_menu', array( $this, 'add_plugin_page' ) );
        add_action( 'admin_init', array( $this, 'page_init' ) );
    }

    /**
     * Add options page
     */
    public function add_plugin_page()
    {
        // This page will be under "Settings"
        add_options_page(
            'Settings Admin', 
            'Umbrella Settings', 
            'manage_options', 
            'my-setting-admin', 
            array( $this, 'create_admin_page' )
        );
    }

    /**
     * Options page callback
     */
    public function create_admin_page()
    {
        // Set class property
        $this->options = get_option( 'uoh_options' );
        ?>
        <div class="wrap">
            <h1>Umbrella Settings</h1>
            <form method="post" action="options.php">
            <?php
                // This prints out all hidden setting fields
                settings_fields( 'uoh_option_group' );
                do_settings_sections( 'my-setting-admin' );
                submit_button();
            ?>
            </form>
        </div>
        <?php
    }

    /**
     * Register and add settings
     */
    public function page_init()
    {        
        register_setting(
            'uoh_option_group', // Option group
            'uoh_options', // Option name
            array( $this, 'sanitize' ) // Sanitize
        );

        /*        
         * Uoh Sections
         */

        add_settings_section(
            'stories_section_id', // ID
            'Stories Settings', // Title
            array( $this, 'print_section_info' ), // Callback
            'my-setting-admin' // Page
        ); 

        add_settings_section(
            'impact_section_id', // ID
            'Impact Settings', // Title
            array( $this, 'print_section_info' ), // Callback
            'my-setting-admin' // Page
        ); 

        add_settings_section(
            'testimonial_section_id', // ID
            'Testimonial Settings', // Title
            array( $this, 'print_section_info' ), // Callback
            'my-setting-admin' // Page
        );

        /*        
         * Uoh Story Fields
         */

        add_settings_field(
            'stories_title_en', // ID
            'Stories Title English', // Title 
            array( $this, 'stories_title_en_callback' ), // Callback
            'my-setting-admin', // Page
            'stories_section_id' // Section           
        );      

        add_settings_field(
            'stories_title_nl', 
            'Stories Title Dutch', 
            array( $this, 'stories_title_nl_callback' ), 
            'my-setting-admin', 
            'stories_section_id'
        );

        add_settings_field(
            'stories_ppp', 
            'Number of Stories to display', 
            array( $this, 'stories_ppp_callback' ), 
            'my-setting-admin', 
            'stories_section_id'
        );

        add_settings_field(
            'stories_order', 
            'Stories Order', 
            array( $this, 'stories_order_callback' ), 
            'my-setting-admin', 
            'stories_section_id'
        );

        /*        
         * Uoh Impact Fields
         */

        add_settings_field(
            'impact_title_en', // ID
            'Impact Title English', // Title 
            array( $this, 'impact_title_en_callback' ), // Callback
            'my-setting-admin', // Page
            'impact_section_id' // Section           
        );      

        add_settings_field(
            'impact_title_nl', 
            'Impact Title Dutch', 
            array( $this, 'impact_title_nl_callback' ), 
            'my-setting-admin', 
            'impact_section_id'
        ); 

        add_settings_field(
            'impact_ppp', 
            'Number of Impact Blocks to display', 
            array( $this, 'impact_ppp_callback' ), 
            'my-setting-admin', 
            'impact_section_id'
        );

        add_settings_field(
            'impact_order', 
            'impact Order', 
            array( $this, 'impact_order_callback' ), 
            'my-setting-admin', 
            'impact_section_id'
        );
        /*        
         * Uoh Testimonial Fields
         */

        add_settings_field(
            'testimonial_title_en', // ID
            'Testimonial Title English', // Title 
            array( $this, 'testimonial_title_en_callback' ), // Callback
            'my-setting-admin', // Page
            'testimonial_section_id' // Section           
        );      

        add_settings_field(
            'testimonial_title_nl', 
            'Testimonial Title Dutch', 
            array( $this, 'testimonial_title_nl_callback' ), 
            'my-setting-admin', 
            'testimonial_section_id'
        ); 

        add_settings_field(
            'testimonial_ppp', 
            'Number of Testimonial Blocks to display', 
            array( $this, 'testimonial_ppp_callback' ), 
            'my-setting-admin', 
            'testimonial_section_id'
        );

        add_settings_field(
            'testimonial_order', 
            'Testimonial Order', 
            array( $this, 'testimonial_order_callback' ), 
            'my-setting-admin', 
            'testimonial_section_id'
        );
    }

    /**
     * Sanitize each setting field as needed
     *
     * @param array $input Contains all settings fields as array keys
     */
    public function sanitize( $input )
    {
        $new_input = array();

        /*        
         * Sanitize Story Fields
         */

        if( isset( $input['stories_title_en'] ) ){
            $new_input['stories_title_en'] = sanitize_text_field( $input['stories_title_en'] );
        }
        if( isset( $input['stories_title_nl'] ) ){
            $new_input['stories_title_nl'] = sanitize_text_field( $input['stories_title_nl'] );
        }
        if( isset( $input['stories_ppp'] ) ){
            $new_input['stories_ppp'] = absint( $input['stories_ppp'] );
        }
        if( isset( $input['stories_order'] ) ){
            $new_input['stories_order'] = sanitize_text_field( $input['stories_order'] );
        }

        /*        
         * Sanitize Impact Fields
         */

        if( isset( $input['impact_title_en'] ) ){
            $new_input['impact_title_en'] = sanitize_text_field( $input['impact_title_en'] );
        }
        if( isset( $input['impact_title_nl'] ) ){
            $new_input['impact_title_nl'] = sanitize_text_field( $input['impact_title_nl'] );
        }
        if( isset( $input['impact_ppp'] ) ){
            $new_input['impact_ppp'] = absint( $input['impact_ppp'] );
        }
        if( isset( $input['impact_order'] ) ){
            $new_input['impact_order'] = sanitize_text_field( $input['impact_order'] );
        }

        /*        
         * Sanitize Testimonial Fields
         */

        if( isset( $input['testimonial_title_en'] ) ){
            $new_input['testimonial_title_en'] = sanitize_text_field( $input['testimonial_title_en'] );
        }
        if( isset( $input['testimonial_title_nl'] ) ){
            $new_input['testimonial_title_nl'] = sanitize_text_field( $input['testimonial_title_nl'] );
        }
        if( isset( $input['testimonial_title_nl'] ) ){
            $new_input['testimonial_ppp'] = absint( $input['testimonial_ppp'] );
        }
        if( isset( $input['testimonial_order'] ) ){
            $new_input['testimonial_order'] = sanitize_text_field( $input['testimonial_order'] );
        }

        return $new_input;
    }

    /** 
     * Print the Section text
     */
    public function print_section_info()
    {
        print 'Enter your settings below:';
    }

    /** 
     * Get the settings option array and print one of its values
     */

    /*        
     * Callbacks for Story Fields
     */

    public function stories_title_en_callback()
    {
        printf(
            '<input type="text" id="stories_title_en" name="uoh_options[stories_title_en]" value="%s" />',
            isset( $this->options['stories_title_en'] ) ? esc_attr( $this->options['stories_title_en']) : ''
        );
    }
    public function stories_title_nl_callback()
    {
        printf(
            '<input type="text" id="stories_title_nl" name="uoh_options[stories_title_nl]" value="%s" />',
            isset( $this->options['stories_title_nl'] ) ? esc_attr( $this->options['stories_title_nl']) : ''
        );
    } 
    public function stories_ppp_callback()
    {
        printf(
            '<input type="text" id="stories_ppp" name="uoh_options[stories_ppp]" value="%s" />',
            isset( $this->options['stories_ppp'] ) ? esc_attr( $this->options['stories_ppp']) : ''
        );
    }
    public function stories_order_callback()
    {   
        $checked = isset( $this->options['stories_order'] ) ? esc_attr( $this->options['stories_order']) : 'ASC';

        $print  = '<input type="radio" name="uoh_options[stories_order]" '; 
        if($checked == 'ASC'){$print .= 'checked ';};
        $print .= 'value="ASC"> Ascending<br>';
        $print .= '<input type="radio" name="uoh_options[stories_order]" ';
        if($checked == 'DSC'){$print .= 'checked ';};
        $print .= 'value="DSC"> Descending<br>';
        $print .= '<input type="radio" name="uoh_options[stories_order]" ';
        if($checked == 'rand'){$print .= 'checked ';};
        $print .= 'value="rand"> Random';

        echo $print;
    }

    /*        
     * Callbacks for Impact Fields
     */

    public function impact_title_en_callback()
    {
        printf(
            '<input type="text" id="impact_title_en" name="uoh_options[impact_title_en]" value="%s" />',
            isset( $this->options['impact_title_en'] ) ? esc_attr( $this->options['impact_title_en']) : ''
        );
    }

    public function impact_title_nl_callback()
    {
        printf(
            '<input type="text" id="impact_title_nl" name="uoh_options[impact_title_nl]" value="%s" />',
            isset( $this->options['impact_title_nl'] ) ? esc_attr( $this->options['impact_title_nl']) : ''
        );
    }

    public function impact_ppp_callback()
    {
        printf(
            '<input type="text" id="impact_ppp" name="uoh_options[impact_ppp]" value="%s" />',
            isset( $this->options['impact_ppp'] ) ? esc_attr( $this->options['impact_ppp']) : ''
        );
    }
    public function impact_order_callback()
    {   
        $checked = isset( $this->options['impact_order'] ) ? esc_attr( $this->options['impact_order']) : 'ASC';

        $print  = '<input type="radio" name="uoh_options[impact_order]" '; 
        if($checked == 'ASC'){$print .= 'checked ';};
        $print .= 'value="ASC"> Ascending<br>';
        $print .= '<input type="radio" name="uoh_options[impact_order]" ';
        if($checked == 'DSC'){$print .= 'checked ';};
        $print .= 'value="DSC"> Descending<br>';
        $print .= '<input type="radio" name="uoh_options[impact_order]" ';
        if($checked == 'rand'){$print .= 'checked ';};
        $print .= 'value="rand"> Random';

        echo $print;
    }
    /*        
     * Callbacks for Testimonial Fields
     */

    public function testimonial_title_en_callback()
    {
        printf(
            '<input type="text" id="testimonial_title_en" name="uoh_options[testimonial_title_en]" value="%s" />',
            isset( $this->options['testimonial_title_en'] ) ? esc_attr( $this->options['testimonial_title_en']) : ''
        );
    }

    public function testimonial_title_nl_callback()
    {
        printf(
            '<input type="text" id="testimonial_title_nl" name="uoh_options[testimonial_title_nl]" value="%s" />',
            isset( $this->options['testimonial_title_nl'] ) ? esc_attr( $this->options['testimonial_title_nl']) : ''
        );
    }

    public function testimonial_ppp_callback()
    {
        printf(
            '<input type="text" id="testimonial_ppp" name="uoh_options[testimonial_ppp]" value="%s" />',
            isset( $this->options['testimonial_ppp'] ) ? esc_attr( $this->options['testimonial_ppp']) : ''
        );
    }
    public function testimonial_order_callback()
    {   
        $checked = isset( $this->options['testimonial_order'] ) ? esc_attr( $this->options['impact_order']) : 'ASC';

        $print  = '<input type="radio" name="uoh_options[testimonial_order]" '; 
        if($checked == 'ASC'){$print .= 'checked ';};
        $print .= 'value="ASC"> Ascending<br>';
        $print .= '<input type="radio" name="uoh_options[testimonial_order]" ';
        if($checked == 'DSC'){$print .= 'checked ';};
        $print .= 'value="DSC"> Descending<br>';
        $print .= '<input type="radio" name="uoh_options[testimonial_order]" ';
        if($checked == 'rand'){$print .= 'checked ';};
        $print .= 'value="rand"> Random';

        echo $print;
    }
}
if( is_admin() ){
    $my_settings_page = new UoHSettingsPage();
}

function uoh_custom_options($option_name, $post_type, $key_root){
    $options = get_option( $option_name );
    $root = isset($key_root) ? $key_root : $post_type;
    $ppp = $root . '_ppp';
    $order = $root . '_order';
    $title_en = $root . '_title_en';
    $title_nl = $root . '_title_nl';
    return array(
        'query_args' => array(
            'post_type' => $post_type,
            'posts_per_page' => $options[$ppp],
            'orderby' => $options[$order],
        ),
        'title-en' => $options[$title_en],
        'title-nl' => $options[$title_nl]
    );
}
  • There's a lot of code here - can you narrow it down a bit? You say it's when you declare the class: does the first half work fine without it? Is the class definition fine if you never reference it? Does removing some or all of the contents of the class help? Why close and reopen the php tag just before the class definition? – Rup Mar 3 at 8:05
  • Everything was working fine until I defined class UoHSettingsPage. I tried removing everything from it and it still crashed. The opening and reopening of the PHP tags was a result of cutting parts in and out a couple times. The same problem was there before without the opening and closing of the tags. For a bit of context, the top half is declaring custom post types for content sections on the homepage. The options page is supposed to allow the user set a title for those sections in English, Dutch, how many posts to display and how to order them. – Kevin Mar 3 at 13:18
  • I broke up the code. As per the edit text: first block for creating post types works fine. Second block is actually doing its job and "working" but then it is crashing the other parts of the admin area. – Kevin Mar 3 at 13:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.