Le grand défi du menu d'administration WordPress de janvier 2011 (alias Comment résoudre certains défis lors de la modification du système du menu d'administration WordPress?)


14

Cette question est un peu unique.

C'est en partie un "défi" que je lance à l'équipe WordPress ( ou à toute autre personne ) concernant les tickets Trac : # 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 lorsque vous essayez de modifier la section du menu Admin WordPress:

  1. Obtenez la page du sous - menu "Microsite" à mettre en évidence lors de la modification d'un avocat (pour cela, nous devons en quelque sorte être en mesure d'appliquer "en cours" à l'élément de sous-menu, _ et certains crochets dans la fonction _wp_menu_output () fourniraient ce qui est nécessaire ici) ,

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

  3. Obtenez le lien "Microsite" pour ne pas déclencher une erreur "Vous n'avez pas les autorisations suffisantes pour accéder à cette page" * (c'est la plus méchante à résoudre, et un crochet sur la valeur de retour deuser_can_access_admin_page() pourrait bien gérer ce problème.)

Capture d'écran du Grand défi du menu d'administration WordPress de janvier 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 dit que c'était facile et impliquaient donc que je manque quelque chose (ce qui peut être correct) mais j'ai examiné ce problème pendant des semaines et je n'ai pas compris comment le contourner, j'ai donc créé le plugin que vous voyez ci-dessous ( également téléchargeable depuis Gist ) comme exemple de cas d'utilisation le plus simple des problèmes. Le codeadmin_menu2()est plutôt hackeux mais c'est à peu près ce qui est nécessaire pour modifier les menus d'administration dans WordPress.

Notez que je n'ai pas essayé d'utiliser le nouveau remove_menu_page() ni les nouvelles remove_submenu_page()en 3.1 car cela aurait pris plus de temps pour créer le plugin - j'avais déjà le code admin_menu2()d'un projet existant - et je ne pense pas qu'ils aborderaient le problème de toute façon.

De quoi ai-je besoin?

J'ai besoin d'une des deux (2) choses:

  1. Une solution aux problèmes que j'expose avec ce plugin et expliquer dans cette question et dans la capture d'écran (BTW, je disqualifierai votre solution si vous utilisez PHP Output Buffering pour résoudre n'importe quelle partie de cela) , ou

  2. Pour que l'équipe WordPress reconnaisse qu'il y a effectivement un besoin pour ces crochets et pour les amener à reconsidérer leur position sur les tickets.

Comment relevez-vous le défi?

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

  2. Téléchargez, installez et activez le plugin "The Great WordPress Admin Menu Challenge of Jan 2011" ci-dessous (ou téléchargez le plugin depuis Gist ) , puis

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

Capture d'écran des instructions du plugin "The Great WordPress Admin Menu Challenge of Jan 2011"
(source: mikeschinkel.com )

Un rayon d'espoir

Heureusement, Andrew Nacin de l'équipe WordPress a proposé de regarder cela une fois que je l'avais codé, donc je poste principalement ici pour qu'il puisse le réviser et le commenter ainsi que d'avoir d'autres personnes à commenter. 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 voir s'il peut résoudre le problème.

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

Si après avoir essayé ce défi, vous arrivez à la même conclusion que moi, et si vous souhaitez que les menus Admin WordPress soient plus configurables, veuillez commenter ces tickets Trac ( # 16048 - # 16050 - # 16204 ) et voter pour cette question. pour montrer son soutien.

J'admets volontiers que j'ai raté quelque chose, si je l'ai fait

Bien sûr, il est possible que je sois complètement mort de cervelle à 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ère me tromper et faire fonctionner cela que vice-versa.

Et voici le plugin

Vous pouvez également le télécharger depuis 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="/wordpress//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="/wordpress//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.


Je suis intéressé (et j'ai vraiment besoin de mettre à niveau mon expérience avec le côté administrateur), mais j'attendrai probablement la version 3.1 finale. Ma pile de test locale n'est pas très adaptée pour plusieurs versions de base, je m'en tiens donc à l'écurie actuelle.
2011

Je connais exactement le problème dont vous parlez de Mike, je ne pense pas que je pourrais le décrire mieux que vous, mais j'ai vu les mêmes problèmes lors de l'écriture d'un menu déroulant pour l'administrateur (pour le plaisir), juste en ajoutant mon +1.
t31os

@ t310s - Merci d'avoir ajouté votre +1. Il m'a fallu probablement 2 semaines de recherche pour pouvoir décrire le problème, de sorte que le fait que vous puissiez même reconnaître qu'il est pertinent (et que je n'ai pas passé les 2 semaines que j'ai) signifie que vous êtes bien en avance sur la plupart des gens à ce sujet, y compris moi!
MikeSchinkel

Réponses:


2

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

  1. Obtenez la page de sous-menu "Microsite" à mettre en évidence lors de la modification d'un avocat
  2. Obtenez le lien de la page du menu du mandataire vers /wp-admin/edit.php?post_type=attorneylequel vous souhaitez créer un lien lors de la modification d'un mandataire
  3. Obtenez le lien "Microsite" pour ne pas déclencher une erreur "Vous ne disposez pas des autorisations suffisantes pour accéder à cette page"

Et le problème clé ici est le n ° 2.

Ce que j'ai essayé

J'ai essayé d'ajouter un type de publication personnalisé pour les avocats et on m'a immédiatement rappelé que /wp-admin/edit.php?post_type=attorneycela vous donnerait une liste d'avocats, pas un véritable écran d'édition. L'édition proprement dite a lieu le/wp-admin/post.php?post=10&action=edit . Donc, si vous êtes vraiment lié au n ° 2 ... les deux autres critères ne fonctionneront pas.

C'est pourquoi # 3 échoue dans l'implémentation ... et je n'ai même pas pu essayer # 1 parce que je ne pouvais pas aller aussi loin.


Croyez que votre analyse est correcte. La disposition montrée en question est celle que j'ai eu plus d'une demande client dans leurs objectifs de simplifier les structures de menu pour leurs cas d'utilisation. J'ai proposé d'utiliser des sous-menus mais ils n'ont pas aimé ça; ils pensaient que ce serait trop déroutant pour leurs utilisateurs. Une chose que je n'ai peut-être pas mentionné, c'est que je développe un produit basé sur WordPress pour eux à distribuer par rapport à un site Web WordPress pour eux où je peux simplement les former à savoir comment faire fonctionner les choses. Leur autre option est d'abandonner WordPress; pas ce que je veux qu'ils fassent.
MikeSchinkel

2

Hé Mike, votre problème # 3 est dû au fait que vous spécifiez ($microsite, 'the_microsite_editor')où il devrait être (__CLASS__, 'the_microsite_editor').

Mise à jour: Après avoir passé beaucoup trop de temps à essayer de résoudre des problèmes similaires pour mon propre plugin, voici quelque chose que j'ai trouvé qui peut vous aider avec votre défi (notez que les fonctions sont des méthodes 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 ajouter correctement un élément de sous-menu à un menu qui a été créé automatiquement pendant un register_post_type()appel.


oups ... les doubles
traits de

Je l'ai corrigé. :)
fuxia

Oh, c'est tout simplement génial; Merci! Comment ai-je pu manquer ce premier point?!? Ah!
MikeSchinkel

Merci, Mike. Revenons à votre sujet d'origine ... WP génère en interne un ID pour certaines entrées de menu et le stocke dans la valeur 4 des tableaux de menu. Tels que les hooks de page de plugin. Cependant, pour les post-types personnalisés, il stocke un ID qui n'est pas cohérent avec le format du plugin-page-hook. Je pense que beaucoup pourrait être aidé si WP voulait rendre cela cohérent (c'est-à-dire créer des crochets de page pour tout et les utiliser pour associer des entrées de menu les uns aux autres, plutôt que d'attacher des sous-menus au moyen du `` slug / fichier parent ''.
wyrfel
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.