2011年1月的WordPress管理菜单大挑战(又名如何解决修改WordPress管理菜单系统时的一些挑战?)

时间:2011-01-15 作者:MikeSchinkel

这个问题有点独特

在a部分;挑战“or anyone else)与trac票据相关:#16048, #16050#16204.

目标是在试图修改WordPress管理菜单部分时,绕过以下屏幕截图所示的三(3)个问题:

获取;“微型站点”编辑律师时要突出显示的子菜单页(为此,我们需要能够将“当前”应用于子菜单项,并且some hooks in the _wp_menu_output() function 将提供此处所需的内容),

获取要链接到的律师菜单页链接/wp-admin/edit.php?post_type=attorney 编辑律师时same needed hooks in the _wp_menu_output() function 可以处理此问题)以及

获取;“微型站点”链接不触发;您没有足够的权限访问此页面错误*(这是要解决的最糟糕的问题,并且hook on the return value of user_can_access_admin_page() 可以很好地处理此问题。)

Screenshot for The Great WordPress Admin Menu Challenge of Jan 2011mikeschinkel.com)

这三(3)个问题不仅仅是我的用例,它们是WordPress中配置管理菜单相关问题的象征。

WordPress团队中的一些人说这很简单,因此暗示我遗漏了一些东西(这可能是对的),但我已经研究这个问题好几个星期了,还没有找到解决方法,所以我创建了你在下面看到的插件(also downloadable from Gist) 作为问题的最简单用例示例。中的代码admin_menu2() 这是一个相当粗糙的方法,但这正是在WordPress中修改管理菜单所需要的。

请注意,我没有尝试使用新的remove_menu_page() 也不是新的remove_submenu_page() 3.1中的函数,因为创建插件需要更长的时间——我已经在admin_menu2() 我不相信他们会解决这个问题。

我需要什么

我需要两(2)件事中的一件:

我用这个插件暴露的问题的解决方案,并在这个问题和屏幕截图中解释(顺便说一句,I\'ll disqualify your solution 如果您使用PHP Output Buffering 要解决此问题的任何部分),或

让WordPress团队认识到确实需要这些挂钩,并让他们重新考虑自己在门票上的立场。

你是如何迎接挑战的pristine new copy of WordPress 3.1 (任何修订都可以)

下载、安装并激活;2011年1月WordPress管理菜单大挑战”插件(或download the plugin from Gist),然后

遵循该插件的插件页面上的说明(参见以下屏幕截图),但基本上加载上面看到的屏幕截图,然后尝试找出所述的三(3)个问题:

Screenshot of "The Great WordPress Admin Menu Challenge of Jan 2011" plugin instructionsmikeschinkel.com)

幸运的是,有一线希望Andrew Nacin of the WordPress team offered to look at this 一旦我把它编码好了,我就把它张贴在这里,主要是让他评论和评论,也让其他人评论。我知道他很忙,但我真的希望他(or even you) 在v3的原始安装上安装此插件可能需要一些时间。看看他是否能解决这个问题。

如果你同意挑战是不可能的

如果在尝试了这个挑战后,你得出了与我相同的结论,并且如果你想看到WordPress管理菜单更具可配置性,请对这些trac票证发表评论(#16048 - #16050 - #16204) 投票支持这个问题。

我很乐意承认我错过了什么,如果我真的错过了,当然我可能会在这件事上完全脑死亡,有人会准确地指出怎么做。事实上,我真的希望最终会是这样;我宁愿错了,也不愿让它起作用,反之亦然。

这是插件,您还可以downloadable if from Gist:

<?php
/*
Plugin Name: The Great WordPress Admin Menu Challenge of Jan 2011
Description: <em>"The Great WordPress Admin Menu Challenge of Jan 2011"</em> was inspired by the WordPress team\'s apparent lack of understanding of the problems addressed by trac tickets <a href="http://core.trac.wordpress.org/ticket/16048">#16048</a> and <a href="http://core.trac.wordpress.org/ticket/16050">#16050</a> <em>(See also: <a href="http://core.trac.wordpress.org/ticket/16204">#16204</a>)</em> and suggestion that the <a href="http://wordpress.org/extend/plugins/admin-menu-editor/>Admin Menu Editor</a> plugin handles the use-cases that the tickets address. Debate spilled over onto Twitter with participation from <a href="http://twitter.com/nacin">@nacin</a>, <a href="http://twitter.com/aaronjorbin">@aaronjorbin</a>, <a href="http://twitter.com/petemall">@petemall</a>, <a href="http://twitter.com/westi">@westi</a>, <a href="http://twitter.com/janeforshort">@janeforshort</a>, <a href="http://twitter.com/PatchesWelcome">@PatchesWelcome</a>; supportive comments from <a href="http://twitter.com/ramsey">@ramsey</a>, <a href="http://twitter.com/brianlayman">@brianlayman</a>, <a href="http://twitter.com/TheLeggett">@TheLeggett</a>, a retweeting of @nacin\'s simple yet <em>(AFAICT)</em> insufficient solution by <a href="http://twitter.com/vbakaitis">@vbakaitis</a>, <a href="http://twitter.com/Viper007Bond">@Viper007Bond</a>, <a href="http://twitter.com/nickopris">@nickopris</a>, <a href="http://twitter.com/Trademark">@Trademark</a>, <a href="http://twitter.com/favstar_pop">@favstar_pop</a>, <a href="http://twitter.com/designsimply">@designsimply</a>, <a href="http://twitter.com/darylkoop">@darylkoop</a>, <a href="http://twitter.com/iamjohnford">@iamjohnford</a>, <a href="http://twitter.com/markjaquith">@markjaquith</a>, <a href="http://twitter.com/JohnJamesJacoby">@JohnJamesJacoby</a> and <a href="http://twitter.com/dd32">@dd32</a>. Also see <a href="http://andrewnacin.com/2010/12/20/better-admin-menu-controls-custom-post-types-wordpress-3-1/#comment-6360">comments</a> on @nacin\'s blog post entitled "<em>Better admin menu handling for post types in WordPress 3.1</em>." <strong>The desired goal of the <em>"challenge"</em></strong> is to simply either to find a solution that has eluded me or, to get those who are dismissing it as solvable without added hooks in WordPress to have a tangible example to explore in hopes they will recognize that there is indeed a need for at least some of the requested hooks. <strong>There are three (3) steps to the challenge:</strong> 1.) Get the "Microsite" submenu page to be highlighted when editing an Attorney, 2.) Get the Attorney Menu Page link to link <a href="/wp-admin/edit.php?post_type=attorney">here</a>  when editing an Attorney, and 3.) Get the "Microsite" link not to trigger a "You do not have sufficient permissions to access this page" error.  Here is <a href="https://mikeschinkel.com/websnaps/skitched-20110114-235302.png" target="_blank"><strong>a screenshot</strong> that attempts to illustrate the callenge</a>. The code can be found on gist <a href="https://gist.github.com/780709"><strong>here</strong></a>. Activate it as a plugin in a WordPress 3.1 install and go <a href="/wp-admin/post.php?post=10&action=edit"><strong>here</strong></a> to see what the screenshot illustrates. <strong>Be sure to load the <a href="https://mikeschinkel.com/websnaps/skitched-20110114-235302.png" target="_blank">screenshot</a> in another browser tab or window first</strong>.
Author:      Mike Schinkel
Author URI:  http://about.me/mikeschinkel
Plugin URI:  https://gist.github.com/780709
*/
if (!class_exists(\'TheGreatWordPressAdminMenuChallenge\')) {
  class TheGreatWordPressAdminMenuChallenge {
    static function on_load() {
      add_action(\'init\',array(__CLASS__,\'init\'));
      add_action(\'admin_menu\',array(__CLASS__,\'admin_menu1\'));      // Simulates generic "Microsite" plugin
      add_action(\'admin_menu\',array(__CLASS__,\'admin_menu2\'),100);  // Simulates website-specific plugin
      add_action(\'post_row_actions\',array(__CLASS__,\'post_row_actions\'),10,2);
    }
    static function post_row_actions($actions,$post) {
      $url = admin_url(self::this_microsite_url($post->ID));
      $actions = array_merge(array(\'microsite\'=>"<a href=\\"{$url}\\" title=\\"Manage this Microsite\\">Microsite</a>"),$actions);
      return $actions;
    }
    static function the_microsite_editor() {
      echo "We are in the Microsite Editor for " . self::post_title();
    }
    static function admin_menu1() {
      if (self::this_post_id() && in_array(self::this_post_type(),array(\'attorney\',\'practice_area\'))) {
        add_submenu_page(
          self::this_parent_slug(),
          self::microsite_page_title(),
          self::microsite_page_title(),
          $capability = \'edit_posts\',
          \'microsite\',
          array($microsite,\'the_microsite_editor\')
        );
        global $wp_post_types;
        $parent_type_meta = $wp_post_types[self::this_post_type()];
        global $menu;
        $slug = false;
        foreach($menu as $index => $menu_page)
          if ($menu_page[0]===$parent_type_meta->label) {
            $slug = $menu_page[2];
            break;
          }
        if ($slug) {
          global $pagenow;
          global $submenu;
          // Setting this makes gives the link to the microsite in the menu the highlight for "current" menu option
          global $submenu_file;
          $submenu_file = self::this_microsite_url();
          $index = end(array_keys($submenu[$slug]));
          $submenu[$slug][$index][12] = $submenu_file;
        }
      }
    }
    static function this_parent_slug() {
      return "edit.php?post_type=" . self::this_post_type();
    }
    static function post_title() {
      $post_id = self::this_post_id();
      return ($post_id ? get_post($post_id)->post_title : false);
    }
    static function microsite_page_title() {
      return \'Microsite for \' . self::post_title();
    }
    static function this_post_type($get_post=true) {
      $post_type = (isset($_GET[\'post_type\']) ? $_GET[\'post_type\'] : false);
      if (!$post_type && $get_post) {
        $post_id = self::this_post_id();
        $post_type = get_post($post_id)->post_type;
      }
      return $post_type;
    }
    static function this_post_id() {
      $post_id = false;
      $post_type = self::this_post_type(false);
      if (isset($_GET[$post_type]))
        $post_id = intval($_GET[$post_type]);
      else if (isset($_GET[\'post\']))
        $post_id = intval($_GET[\'post\']);
      return $post_id;
    }
    static function this_microsite_url($post_id=false) {
      $post_type = self::this_post_type();
      $post_id = $post_id ? intval($post_id) : self::this_post_id();
      return "edit.php?post_type={$post_type}&page=microsite&attorney={$post_id}";
    }
    static function admin_menu2() {
      // The code required for this is super, nasty, ugly and shouldn\'t be, but at least it *is* doable
      global $menu;
      global $submenu;
      global $microsite;

      $parent_type = self::this_post_type();
      foreach(array(\'attorney\',\'practice_area\') as $post_type) {
        $slug = "edit.php?post_type={$post_type}";
        if ($post_type==$parent_type) {  // If a microsite remove everything except the microsite editor
          $microsite_url = self::this_microsite_url();
          foreach($submenu[$slug] as $submenu_index => $submenu_page) {
            if ($submenu_page[2]!=$microsite_url) {
              unset($submenu[$slug][$submenu_index]);
            }
          }
        } else {
          $submenu[$slug] = array();
        }
      }

       // Remove the Submenus for each menu
      unset($submenu[\'index.php\']);
      unset($submenu[\'edit.php?post_type=article\']);
      unset($submenu[\'edit.php?post_type=event\']);
      unset($submenu[\'edit.php?post_type=case_study\']);
      unset($submenu[\'edit.php?post_type=news_item\']);
      unset($submenu[\'edit.php?post_type=transaction\']);
      unset($submenu[\'edit.php?post_type=page\']);
      unset($submenu[\'upload.php\']);

      unset($submenu[\'users.php\'][13]); // Removed the "Add New"

      $remove = array_flip(array(
        \'edit.php\',
        \'link-manager.php\',
        \'edit-comments.php\',
        \'edit.php?post_type=microsite-page\',
      ));
      if (!current_user_can(\'manage_tools\'))
        $remove[\'tools.php\'] = count($remove);

      foreach($menu as $index => $menu_page) {
        if (isset($remove[$menu_page[2]])) {
          unset($submenu[$menu_page[2]]);
          unset($menu[$index]);
        }
      }

      $move = array(
        \'edit.php?post_type=page\' => array( \'move-to\' => 35,  0 => \'Other Pages\' ),
        \'separator2\' => array( \'move-to\' => 40 ),
        \'upload.php\' => array( \'move-to\' => 50, 0 => \'Media Library\' ),
      );
      $add = array();
      foreach($menu as $index => $menu_page) {
        if (isset($move[$menu_page[2]])) {
          foreach($move[$menu_page[2]] as $value_index => $value) {
            if ($value_index===\'move-to\') {
              $move_to = $value;
            } else {
              $menu_page[$value_index] = $value;
            }
          }
          $add[$move_to] = $menu_page;
          unset($menu[$index]);
        }
      }
      foreach($add as $index => $value)
        $menu[$index] = $value;

      add_menu_page(
        \'Attorney Positions\',
        \'Attorney Positions\',
        \'edit_posts\',
        \'edit-tags.php?taxonomy=attorney-position&amp;post_type=attorney\',
        false,
        false,
        55);

      ksort($menu); // Need to sort or it doesn\'t come out right.
    }
    static function init() {
      register_post_type(\'attorney\',array(
        \'label\'           => \'Attorneys\',
        \'public\'          => true,
      ));
      register_post_type(\'practice_area\',array(
        \'label\'           => \'Practice Areas\',
        \'public\'          => true,
      ));
      register_taxonomy(\'attorney-position\',\'attorney\',array(
        \'label\'=>\'Attorney Positions\',
      ));
      register_post_type(\'article\',array(
        \'label\'           => \'Articles & Presentations\',
        \'public\'          => true,
      ));
      register_post_type(\'case_study\',array(
        \'label\'           => \'Case Studies\',
        \'public\'          => true,
      ));
      register_post_type(\'news_item\',array(
        \'label\'           => \'Firm News\',
        \'public\'          => true,
      ));
      register_post_type(\'event\',array(
        \'label\'           => \'Events\',
        \'public\'          => true,
      ));
      register_post_type(\'transaction\',array(
        \'label\'           => \'Transactions\',
        \'public\'          => true,
      ));

      // Install the test data
      $post_id = 10;
      $attorney = get_post($post_id);
      if (!$attorney) {
        global $wpdb;
        $wpdb->insert($wpdb->posts,array(
          \'ID\' => $post_id,
          \'post_title\' => \'John Smith\',
          \'post_type\' => \'attorney\',
          \'post_content\' => \'This is a post about the Attorney John Smith.\',
          \'post_status\' => \'publish\',
          \'post_author\' => 1,
        ));
      }
    }
  }
  TheGreatWordPressAdminMenuChallenge::on_load();
}
对于所有读到这篇文章的人,我真的希望你能帮助我。

提前谢谢。

2 个回复
最合适的回答,由SO网友:EAMann 整理而成

Mike,我已经查看了代码和您理想的最终用例。。。坦率地说,其中一些在当前的系统中是不可能实现的。同样,您的要求:

获取;“微型站点”;编辑律师时要突出显示的子菜单页获取要链接到的律师菜单页链接/wp-admin/edit.php?post_type=attorney 编辑律师时,请获取;“微型站点”;链接不触发;您没有足够的权限访问此页面;错误,这里的关键问题是#2。

我尝试的是为律师添加一个自定义的帖子类型,并立即被提醒/wp-admin/edit.php?post_type=attorney 将为您提供律师列表,而不是实际的编辑屏幕。实际编辑发生在/wp-admin/post.php?post=10&action=edit. 所以如果你真的与#2联系在一起。。。其他两个标准不起作用。

这就是#3未能实现的原因。。。我甚至无法尝试#1,因为我走不了那么远。

SO网友:wyrfel

嘿,Mike,您的问题#3是由于您指定($microsite, \'the_microsite_editor\'), 应该在哪里(__CLASS__, \'the_microsite_editor\').

Update: 在花了太多时间试图为我自己的插件解决一些类似的问题之后,我发现了一些可能有助于解决您的挑战的东西(请注意,函数是类下面的方法):

function add_posttype_submenu_page($mytype, $label, $cap, $slug) {  
    /* we add two submenu pages to work around the 
       edit.php?post_type=...&page=...problem and have 
       our page called as admin.php?page=... instead */
    //first create a \'blind\' pseudo-entry to register our page callback
    add_submenu_page($mytype, $label, $label, $cap, $slug, 
                     array( &$this, \'admin_\'.$mytype ));
    //then create a real entry that \'calls\' our pseudo-entry
    add_submenu_page(\'edit.php?post_type=\'.$mytype, $label, 
                     $label, $cap, \'admin.php?page=\'.$slug);
    /* then lets fix/hack the highlighting */
    global $plugin_page;
    global $submenu_file;
    if ($plugin_page == $slug) {
        // this next line highlights the submenu entry
        $submenu_file = \'admin.php?page=\'.$slug; 
        add_filter(\'parent_file\', 
                   array(&$this, \'evil_parent_file_hack\'));
    }
} 

function evil_parent_file_hack() {
    //we do this to get the parent menu properly highlighted, too
    //it only gets called on the submenu menu page in question
    global $self;
    global $parent_file;
    $self = $parent_file;
    remove_filter(\'parent_file\', array(&$this, \'evil_parent_file_hack\'));
}
然后你只要打电话add_posttype_submenu_page() 具有相应的参数。这应该正确地将子菜单项添加到在register_post_type() 呼叫

结束

相关推荐