web-dev-qa-db-fra.com

Le grand défi du menu d'administration WordPress de janvier 2011 (a.k.a. Comment résoudre certains problèmes lors de la modification du système de menus d'administration WordPress?)

Cette question est un peu unique.

C’est en partie un "défi" que j’émets à l’équipe WordPress ( ou quelqu'un d’autre ) lié aux tickets de traçage: # 16048 , # 16050 et # 16204 .

Le but

_ {Le but est de contourner les trois (3) problèmes illustrés dans la capture d'écran ci-dessous lors d'une tentative de modification de la section du menu Admin WordPress:

  1. Obtenir la mise en évidence de la page de sous-menu "Microsite" lors de la modification d'un mandataire (pour cela, nous devons pouvoir appliquer "current" à l'élément de sous-menu, _ et certains points d'ancrage de la fonction _wp_menu_output () fourniraient ce dont nous avons besoin ici.,

  2. Obtenir le lien de la page de menu du mandataire vers le lien vers /wp-admin/edit.php?post_type=attorney lors de la modification d'un mandataire (et ceux mêmes crochets nécessaires dans la fonction _wp_menu_output () pourraient gérer cela., et

  3. Obtenez le "microsite"} lien pour ne pas déclencher une "vous ne disposez pas des autorisations suffisantes pour accéder à cette page" erreur * (c'est le plus méchant à résoudre, et un crochet sur la valeur de retour de user_can_access_admin_page() pourrait traiter ce problème bien.)

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

Plus que mon cas d'utilisation

Ces trois (3) problèmes sont pour mon cas d'utilisation mais ils sont emblématiques des problèmes liés à la configuration des menus d'administration dans WordPress.

Plusieurs membres de l’équipe WordPress ont déclaré que c’était facile et qu’il était donc implicite que quelque chose me manquait (ce qui peut être exact)} mais j’ai étudié ce problème pendant des semaines sans savoir comment le contourner. créé le plug-in que vous voyez ci-dessous ( également téléchargeable à partir de Gist ) en tant qu’exemple de cas d’utilisation le plus simple. Le code dans admin_menu2() est plutôt bidon, mais c’est à peu près ce qui est nécessaire pour modifier les menus d’administrateur dans WordPress.

Notez que je n’ai pas essayé d’utiliser les nouvelles fonctions remove_menu_page() et remove_submenu_page() dans la version 3.1, car il aurait fallu plus de temps pour créer le plug-in - j’avais déjà le code dans admin_menu2() à partir d’un projet existant - et je ne crois pas qu’ils permettrait de résoudre le problème de toute façon.

De quoi ai-je besoin?

J'ai besoin de l'une des deux (2) choses suivantes:

  1. Une solution aux problèmes que j'expose avec ce plugin et explique dans cette question et dans la capture d'écran (BTW, Je vais disqualifier votre solution si vous utilisez PHP Sortie en mémoire tampon pour résoudre une partie de celle-ci)}, ou

  2. Pour que l'équipe WordPress reconnaisse la nécessité de ces crochets, demandez-leur de reconsidérer leur position sur les tickets.

Comment relevez-vous le défi?

  1. Téléchargez et installez un nouvelle copie vierge de WordPress 3.1(toute révision le sera probablement)},

  2. Téléchargez, installez et activez le plug-in "Le grand défi du menu d'administration WordPress de janvier 2011" ci-dessous (ou téléchargez le plugin à partir de Gist ), puis

  3. Suivez les instructions de la page du plugin pour ce plugin (voir la capture d'écran suivante)} mais chargez la capture d'écran que vous voyez ci-dessus, puis essayez de résoudre les trois problèmes décrits:

Screenshot of "The Great WordPress Admin Menu Challenge of Jan 2011" plugin instructions
(source: mikeschinkel.com )

Un rayon d'espoir

Heureusement Andrew Nacin de l’équipe WordPress a proposé de regarder cela une fois que j’avais codé, je poste donc principalement ici pour qu’il puisse le commenter et commenter, ainsi que d’autres commentateurs. Je sais qu'il est occupé mais j'espère qu'il (ou même vous) peut prendre le temps d'installer ce plugin sur une installation vierge de la v3.1 et de voir s'il peut résoudre le problème.

Si vous êtes d'accord, le défi est impossible?

Si, après avoir relevé ce défi, vous aboutissez à la même conclusion que moi et si vous souhaitez que les menus de l'administrateur WordPress soient plus configurables, veuillez commenter ces tickets de trac ( # 16048 - # 16050 - # 16204 ) et votez sur cette question pour montrer son soutien.

Je vais volontiers admettre que j'ai raté quelque chose, si je l'avais fait

Bien sûr, il est possible que je sois complètement mort cérébralement à ce sujet et que quelqu'un puisse indiquer exactement comment le faire. En fait, j'espère vraiment que cela finira par être le cas; Je préférerais me tromper et que cela fonctionne plutôt que l'inverse.

Et voici le plugin

Vous pouvez également téléchargeable si de 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();
}

À tous ceux qui lisent ceci, j'espère vraiment que vous pourrez aider.

Merci d'avance.

14
MikeSchinkel

Mike, j'ai jeté un coup d'œil au code et à votre cas d'utilisation final idéal ... et certains d'entre eux, franchement, ne sont pas possibles avec le système actuel. Encore une fois, vos exigences:

  1. Afficher la page du sous-menu "Microsite" lors de la modification d'un avocat
  2. Obtenir le lien de la page de menu du procureur pour créer un lien vers /wp-admin/edit.php?post_type=attorney lors de la modification d'un procureur
  3. Le lien "Microsite" ne doit pas déclencher l'erreur "Vous ne disposez pas des autorisations suffisantes pour accéder à cette page".

Et la question clé ici est la n ° 2.

Ce que j'ai essayé

J'ai essayé d'ajouter un type de message personnalisé pour les avocats et on m'a immédiatement rappelé que /wp-admin/edit.php?post_type=attorney vous donnera un list des avocats, et non un écran d'édition. La modification réelle a lieu sur /wp-admin/post.php?post=10&action=edit. Donc, si vous êtes vraiment lié à # 2 ... les deux autres critères ne fonctionneront pas.

C'est pourquoi la n ° 3 échoue dans la mise en œuvre ... et je n'ai même pas pu tenter la n ° 1 car je ne pouvais pas aller aussi loin.

2
EAMann

Hé Mike, ton problème n ° 3 est dû au fait que tu as spécifié ($microsite, 'the_microsite_editor'), où il devrait s'agir de (__CLASS__, 'the_microsite_editor').

Mise à jour: Après avoir passé trop de temps à essayer de résoudre un problème similaire pour mon propre plugin, voici quelque chose qui pourrait vous aider avec votre Challenge (notez que les fonctions sont des méthodes situées sous votre classe):

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'));
}

Ensuite, vous appelez simplement add_posttype_submenu_page() avec les paramètres correspondants. Cela devrait correctement ajouter un élément de sous-menu à un menu créé automatiquement lors d'un appel register_post_type().

2
wyrfel