El gran desafío del menú de administración de WordPress de enero de 2011 (también conocido como ¿Cómo resolver algunos desafíos al modificar el sistema de menú de administración de WordPress?)

14

Esta pregunta es un poco única.

En parte es un "desafío" que estoy enviando al equipo de WordPress ( o cualquier otra persona ) relacionado con los tickets de tráficos : # 16048 , # 16050 y # 16204 .

La meta

El objetivo es evitar los tres (3) problemas ilustrados en la captura de pantalla a continuación cuando se intenta modificar la sección del menú Administrador de WordPress:

  1. Haga que se resalte la página del submenú "Micrositio" cuando edite un abogado (para esto necesitamos de alguna manera poder aplicar "actual" al elemento del submenú, _ y algunos ganchos en la función _wp_menu_output () proporcionarían lo que se necesita aquí) ,

  2. Obtenga el enlace de la página del menú del abogado para vincularlo /wp-admin/edit.php?post_type=attorneyal editar un abogado (y esos mismos ganchos necesarios en la función _wp_menu_output () podrían manejar esto) , y

  3. Obtenga el enlace "Micrositio" para no activar un error "No tiene permisos suficientes para acceder a esta página" * (este es el más desagradable para resolver, y un enganche en el valor de retorno deuser_can_access_admin_page() podría manejar este problema muy bien).

Captura de pantalla para The Great WordPress Admin Menu Challenge de Jan 2011
(fuente: mikeschinkel.com )

Más que solo mi caso de uso

Estos tres (3) problemas son para mi caso de uso, pero son emblemáticos de los problemas relacionados con la configuración de los menús de administración en WordPress.

Varios miembros del equipo de WordPress dijeron que es fácil y, por lo tanto, implica que me falta algo (lo cual puede ser correcto), pero he analizado este problema durante semanas y no he descubierto cómo solucionarlo, así que creé el complemento que ves a continuación. ( también descargable desde Gist ) como el ejemplo de caso de uso más simple de los problemas. El código en admin_menu2()es bastante hack pero eso es más o menos lo que se requiere para modificar los menús de administración en WordPress.

Tenga en cuenta que no intenté usar las funciones nuevas remove_menu_page()ni las nuevas remove_submenu_page()en 3.1 porque me habría llevado más tiempo crear el complemento, ya tenía el código admin_menu2()de un proyecto existente, y no creo que aborden el problema. problema de todos modos

¿Qué necesito?

Necesito una de dos (2) cosas:

  1. Una solución a los problemas que expongo con este complemento y explico en esta pregunta y en la captura de pantalla (por cierto, descalificaré su solución si usa PHP Output Buffering para resolver cualquier parte de esto) , o

  2. Para que el equipo de WordPress reconozca que de hecho existe la necesidad de estos ganchos y hacer que reconsideren su posición en los boletos.

¿Cómo afrontas el desafío?

  1. Descargue e instale una nueva copia inmaculada de WordPress 3.1 (probablemente cualquier revisión lo haga) ,

  2. Descargue, instale y active el complemento "The Great WordPress Admin Menu Challenge of Jan 2011" a continuación (o descargue el complemento de Gist ) , y luego

  3. Siga las instrucciones que se encuentran en la página del complemento para este complemento (vea la siguiente captura de pantalla), pero básicamente cargue la captura de pantalla que ve arriba y luego intente resolver los tres (3) problemas descritos:

Captura de pantalla de las instrucciones del complemento "The Great WordPress Admin Menu Challenge of Jan 2011"
(fuente: mikeschinkel.com )

Un rayo de esperanza

Afortunadamente, Andrew Nacin, del equipo de WordPress, se ofreció a ver esto una vez que lo codifiqué, así que principalmente publico aquí para que lo revise y comente, así como para que otros comenten. Sé que está ocupado, pero espero que él (o incluso usted) pueda tomarse el tiempo para instalar este complemento en una instalación prístina de v3.1 y ver si puede resolver el problema.

Si está de acuerdo, el desafío es imposible?

Si después de intentar este desafío llega a la misma conclusión que yo, y si desea ver que los menús de administración de WordPress sean más configurables, comente estos tickets de trác ( # 16048 - # 16050 - # 16204 ) y vote esta pregunta para mostrar su apoyo

Con mucho gusto admitiré que me perdí algo, si lo hiciera

Por supuesto, es posible que pueda estar completamente muerto de cerebro con esto y alguien pueda señalar exactamente cómo hacerlo. En realidad, realmente espero que ese sea el caso; Prefiero estar equivocado y tener esto funcionando que viceversa.

Y aquí está el complemento

También puedes descargarlo desde 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();
}

Para todos los que leen esto, realmente espero que puedan ayudar.

Gracias por adelantado.

MikeSchinkel
fuente
Estoy interesado (y realmente necesito subir de nivel mi experiencia con el lado administrativo), pero probablemente esperaré la versión 3.1 final. Mi pila de prueba local no es muy adecuada para versiones de núcleo múltiple, por lo que me quedo con el actual estable.
Rarst
Sé exactamente el problema que hablas de Mike, no creo que pueda describirlo mejor de lo que tienes allí, pero he visto los mismos problemas al escribir un menú desplegable para el administrador (por diversión), solo agrego mi +1.
t31os
@ t310s - Gracias por agregar tu +1. Probablemente me tomó 2 semanas de investigación para poder describir el problema, por lo que incluso puede reconocer que es relevante (y no ha pasado las 2 semanas que tengo) significa que está muy por delante de la mayoría de los demás en esto, incluido ¡yo!
MikeSchinkel

Respuestas:

2

Mike, he echado un vistazo al código y tu caso de uso final ideal ... y algunos de ellos, francamente, no son posibles con el sistema actual. De nuevo, sus requisitos:

  1. Obtenga la página del submenú "Micrositio" que se resaltará al editar un abogado
  2. Obtenga el enlace de la página del menú del abogado para vincularlo /wp-admin/edit.php?post_type=attorneyal editar un abogado
  3. Obtenga el enlace "Micrositio" para no activar el error "No tiene permisos suficientes para acceder a esta página"

Y el tema clave aquí es el # 2.

Lo que probé

Intenté agregar un tipo de publicación personalizada para Abogados y me recordó de inmediato que /wp-admin/edit.php?post_type=attorneyle dará una lista de abogados, no una pantalla de edición real. La edición real tiene lugar el /wp-admin/post.php?post=10&action=edit. Entonces, si realmente está atado al # 2 ... los otros dos criterios no funcionarán.

Es por eso que el n. ° 3 falla en la implementación ... y ni siquiera pude intentar el n. ° 1 porque no pude llegar tan lejos.

EAMann
fuente
Cree que tu análisis es correcto. El diseño que se muestra en cuestión es uno en el que he tenido más de una solicitud de cliente en sus objetivos para simplificar las estructuras de menú para sus casos de uso. He propuesto usar submenús pero no les gustó eso; sentían que sería demasiado confuso para sus usuarios. Una cosa que quizás no haya mencionado es que estoy desarrollando un producto basado en WordPress para que lo distribuyan frente a un sitio web de WordPress para ellos, donde puedo entrenarlos para que sepan cómo hacer que las cosas funcionen. Su otra opción es abandonar WordPress; No es lo que quiero que hagan.
MikeSchinkel
2

Hola Mike, tu problema # 3 se debe a que especificas ($microsite, 'the_microsite_editor')dónde debería estar (__CLASS__, 'the_microsite_editor').

Actualización: después de pasar demasiado tiempo tratando de resolver algunos problemas similares para mi propio complemento, aquí hay algo que encontré que puede ayudar con su desafío (tenga en cuenta que las funciones son métodos debajo de su clase):

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

Luego simplemente llama add_posttype_submenu_page()con los parámetros correspondientes. Esto debería agregar correctamente un elemento de submenú a un menú que se creó automáticamente durante una register_post_type()llamada.

wyrfel
fuente
oops ... los guiones bajos dobles alrededor de CLASS se convirtieron en formato negrita ;-)
wyrfel
Lo arreglé. :)
fuxia
Oh, eso es simplemente asombroso; ¡Gracias! ¿Cómo podría haberme perdido ese primer punto? Doh!
MikeSchinkel
Gracias Mike. Volviendo a su tema original ... WP genera internamente una ID para algunas entradas de menú y la almacena en el valor 4 de las matrices de menú. Tales como el plugin-page-hooks. Sin embargo, para los posttipos personalizados, almacena una ID que no es coherente con el formato de enlace de página del complemento. Creo que se podría ayudar mucho si WP lo hiciera coherente (es decir, crear enlaces de página para todo y usarlos para asociar entradas de menú entre sí, en lugar de adjuntar submenús mediante el 'archivo / babosa principal'
wyrfel