2

I have a settings page for my plugin in which the user can toggle a custom post type on or off. When the plugin is initialized I then check this setting to see if the custom content type should be registered or not. The registerPostType() method is called on the init action:

class CPT {
  private $enabled = false;

  public function __construct()
  {
    // Handle form submission.
    add_action('init', array($this, 'checkFormSubmission'), 8);

    // Load settings.
    $settings = get_option('cpt_settings');
    $this->enabled = $settings['enabled'];

    // Add menu.
    add_action('admin_menu', array($this, 'registerMenu'));

    // Register custom post type if enabled.
    if ($this->enabled) {
        add_action('init', array($this, 'registerPostType'));
    }
  }

  public function registerMenu()
  {
    add_submenu_page(
        'options-general.php',
        __('CPT Settings', 'cpt'),
        __('CPT Settings', 'cpt'),
        'manage_options',
        'cpt',
        array($this, 'renderSettingsPage')
    );
  }

  public function registerPostType()
  {
    $args = array(
        'labels' => array(
          'name' => 'CPT',
        ),
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => true,
        'show_in_menu' => true,
        'query_var' => true,
        'capability_type' => 'post',
        'has_archive' => true,
        'hierarchical' => false,
        'menu_position' => null,
        'supports' => array('title', 'editor', 'author', 'thumbnail', 'excerpt')
    );
    register_post_type('sample-cpt',  $args);
  }

  public function checkFormSubmission()
  {
    // Validate so user has correct privileges.
    if (!current_user_can('manage_options')) {
      die(__('You are not allowed to perform this action.', 'cpt'));
    }

    // Check if settings form is submitted.
    if (filter_input(INPUT_POST, 'cpt-settings', FILTER_SANITIZE_STRING)) {
      // Verify nonce and referer.
      check_admin_referer('cpt-settings-action', 'cpt-settings-nonce');
      $this->enabled = filter_input(
          INPUT_POST,
          'cpt-enable',
          FILTER_VALIDATE_BOOLEAN
      );
      update_option('cpt_settings', array('enabled' => $this->enabled));
    }
  }

  public function renderSettingsPage()
  {
    require_once plugin_dir_path(__FILE__ ) . '/admin/templates/settings-page.php';
  }
}

new CPT();

This works as expected, but the problem is that when I'm saving the form the menu item for the custom post type is not updated until I reload the page. Obviously this is because the menu is already created.

My first thought is that I am not using the correct hooks for taking care of the form submission and registering my custom post, or perhaps the hooks should be added with a higher priority?

I tried to use wp_redirect() after the setting is saved, but I'm not able to set any headers because the output has already started.

Can someone please explain how I can make the menu item for my custom post type update when saving the setting for my plugin?

Cyclonecode
  • 1,184
  • 1
  • 9
  • 32

1 Answers1

1

I initially misunderstood your question completely (too much tea, too focused on my initial idea of what your problem is instead of carefully reading ;).

I believe that the problem isn't that the menu is already created (admin_menu runs after init) but rather that registerPostType will only run in init if it is enabled (and not when it is being enabled).

Moving the if ($this->enabled) { into registerPostType and running it unconditionally on init, e.g. just putting

if (!$this->enabled) return;

at the top of registerPostType and changing

// Register custom post type if enabled.
if ($this->enabled) {
    add_action('init', array($this, 'registerPostType'));
}

to

// Register custom post type if enabled.
add_action('init', array($this, 'registerPostType'));

seems most logical to me.

janh
  • 2,758
  • 12
  • 13