La grande sfida del menu di amministrazione di WordPress del gennaio 2011 (alias Come risolvere alcune sfide quando si modifica il sistema del menu di amministrazione di WordPress?)


14

Questa domanda è un po 'unica.

In parte è una "sfida" che sto inviando al team di WordPress ( o a chiunque altro ) relativo ai biglietti trac: # 16048 , # 16050 e # 16204 .

L'obiettivo. il gol

L'obiettivo è aggirare i tre (3) problemi illustrati nello screenshot seguente quando si tenta di modificare la sezione del menu di amministrazione di WordPress:

  1. Ottieni la pagina del sottomenu "Microsito" da evidenziare quando modifichi un avvocato (per questo dobbiamo in qualche modo essere in grado di applicare "corrente" all'elemento del sottomenu, _ e alcuni hook nella funzione _wp_menu_output () fornirebbero ciò che è necessario qui) ,

  2. Ottieni il collegamento alla pagina del menu Attorney a cui collegarti /wp-admin/edit.php?post_type=attorneyquando modifichi un avvocato (e quegli stessi hook necessari nella funzione _wp_menu_output () potrebbero gestirlo) , e

  3. Ottieni il link "Microsito" per non attivare un errore "Non hai autorizzazioni sufficienti per accedere a questa pagina" * (questo è il più cattivo da risolvere e un hook sul valore di ritorno diuser_can_access_admin_page() potrebbe gestire bene questo problema.)

Screenshot di The Great WordPress Admin Menu Challenge del gennaio 2011
(fonte: mikeschinkel.com )

Più che solo il mio caso d'uso

Questi tre (3) problemi sono per il mio caso d'uso, ma sono emblematici dei problemi relativi alla configurazione dei menu di amministrazione in WordPress.

Diversi membri del team di WordPress hanno detto che è facile e quindi sottinteso che mi manca qualcosa (che potrebbe essere giusto) ma ho esaminato questo problema per settimane e non ho capito come aggirarlo, quindi ho creato il plug-in che vedi di seguito ( scaricabile anche da Gist ) come esempio più semplice di casi d'uso dei problemi. Il codice in admin_menu2()è piuttosto hacker ma è praticamente ciò che è necessario per modificare i menu di amministrazione in WordPress.

Si noti che non ho provato a utilizzare la nuova remove_menu_page()né le nuove remove_submenu_page()funzioni in 3.1 perché ci sarebbe voluto più tempo per creare il plugin - avevo già il codice admin_menu2()di un progetto esistente - e non credo che avrebbero affrontato il problema comunque.

Di cosa ho bisogno?

Ho bisogno di una delle due (2) cose:

  1. Una soluzione ai problemi che espongo con questo plugin e spiegherò in questa domanda e nello screenshot (BTW, squalificherò la tua soluzione se usi PHP Output Buffering per risolvere qualsiasi parte di questo) , oppure

  2. Far riconoscere al team di WordPress la necessità di questi hook e farli riconsiderare la loro posizione sui biglietti.

Come si accetta la sfida?

  1. Scarica e installa una nuova copia incontaminata di WordPress 3.1 (probabilmente funzionerà qualsiasi revisione) ,

  2. Scarica, installa e attiva il plug-in "The Great WordPress Admin Menu Challenge of Jan 2011" di seguito (o scarica il plug-in da Gist ) , quindi

  3. Seguire le istruzioni trovate nella pagina del plug-in per questo plug-in (vedere la schermata seguente) ma fondamentalmente caricare la schermata che vedi sopra e quindi provare a capire i tre (3) problemi descritti:

Schermata delle istruzioni del plug-in "The Great WordPress Admin Menu Challenge of Jan 2011"
(fonte: mikeschinkel.com )

Un raggio di speranza

Fortunatamente Andrew Nacin del team di WordPress si è offerto di guardare questo dopo averlo codificato, quindi sto principalmente postando qui per lui da rivedere e commentare, oltre ad avere altri da commentare. So che è occupato, ma spero che (o anche tu) possa impiegare il tempo per installare questo plugin su un'installazione incontaminata di v3.1 e vedere se riesce a risolvere il problema.

Se accetti che la sfida è impossibile?

Se dopo aver provato questa sfida giungi alla mia stessa conclusione e se desideri che i menu di amministrazione di WordPress siano più configurabili, commenta questi biglietti trac ( # 16048 - # 16050 - # 16204 ) e vota questa domanda per dimostrarne il supporto.

Ammetterò volentieri che mi mancasse qualcosa, se lo facessi

Ovviamente è possibile che io possa essere completamente cerebrale e qualcuno potrebbe indicare esattamente come farlo. In realtà, spero davvero che finisca per essere il caso; Preferirei sbagliarmi e farlo funzionare piuttosto che viceversa.

Ed ecco il plugin

Puoi anche scaricare se da 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();
}

A tutti coloro che leggono questo, spero davvero che tu possa aiutare.

Grazie in anticipo.


Sono interessato (e ho davvero bisogno di aumentare la mia esperienza con l'amministratore), ma probabilmente aspetterò la versione finale 3.1. Il mio stack di test locale non è molto adatto per versioni a più core, quindi rimango con l'attuale stabile.
Rarst

Conosco esattamente il problema che parli di Mike, non credo di poterlo descrivere meglio di quello che hai lì, ma ho visto gli stessi problemi quando ho scritto un menu a discesa per l'amministratore (per divertimento), aggiungendo solo il mio +1.
t31os,

@ t310s - Grazie per aver aggiunto il tuo +1. Mi ci sono volute probabilmente 2 settimane di ricerca per essere in grado di descrivere il problema, quindi quel fatto che puoi persino riconoscere che è rilevante (e non ho trascorso le 2 settimane che ho) significa che sei molto più avanti di quasi tutti su questo, incluso me!
MikeSchinkel,

Risposte:


2

Mike, ho dato un'occhiata al codice e al tuo caso d'uso finale ideale ... e alcuni di loro, francamente, non sono possibili con il sistema attuale. Ancora una volta, i tuoi requisiti:

  1. Ottieni la pagina del sottomenu "Microsito" da evidenziare quando modifichi un avvocato
  2. Ottieni il collegamento alla pagina Menu avvocato a cui collegarti /wp-admin/edit.php?post_type=attorneyquando modifichi un avvocato
  3. Ottieni il link "Microsito" per non attivare un errore "Non hai autorizzazioni sufficienti per accedere a questa pagina"

E la questione chiave qui è # 2.

Quello che ho provato

Ho provato ad aggiungere un tipo di post personalizzato per gli avvocati e mi è stato subito ricordato che /wp-admin/edit.php?post_type=attorneyti fornirà un elenco di avvocati, non una schermata di modifica effettiva. Le modifiche effettive avvengono il /wp-admin/post.php?post=10&action=edit. Quindi, se sei davvero legato al n. 2 ... gli altri due criteri non funzioneranno.

Questo è il motivo per cui il n. 3 fallisce nell'implementazione ... e non ero nemmeno in grado di tentare il n. 1 perché non riuscivo ad arrivare così lontano.


Credi che la tua analisi sia corretta. Il layout mostrato in questione è quello in cui ho avuto più di una richiesta client nei loro obiettivi per semplificare le strutture dei menu per i loro casi d'uso. Ho proposto di usare i sottomenu ma a loro non piaceva; sentivano che sarebbe stato troppo confuso per i loro utenti. Una cosa che potrei non aver menzionato è che sto sviluppando un prodotto basato su WordPress per la loro distribuzione su un sito Web WordPress per loro dove posso semplicemente addestrarli per sapere come far funzionare le cose. L'altra opzione è abbandonare WordPress; non quello che voglio che facciano.
MikeSchinkel,

2

Ehi Mike, il tuo problema n. 3 è dovuto a te che specifica ($microsite, 'the_microsite_editor')dove dovrebbe essere (__CLASS__, 'the_microsite_editor').

Aggiornamento: dopo aver passato troppo tempo a cercare di risolvere alcuni problemi simili per il mio plugin, ecco qualcosa che ho trovato utile per la tua sfida (nota che le funzioni sono metodi sottostanti alla tua 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'));
}

Quindi si chiama semplicemente add_posttype_submenu_page()con i parametri corrispondenti. Ciò dovrebbe aggiungere correttamente una voce di sottomenu a un menu creato automaticamente durante una register_post_type()chiamata.


oops ... le doppie sottolineature intorno a CLASS sono state trasformate in grassetto ;-)
wyrfel,

L'ho riparato. :)
fuxia

Oh, è semplicemente fantastico; Grazie! Come ho potuto perdere quel primo punto?!? Doh!
MikeSchinkel,

Grazie Mike. Torna all'argomento originale ... WP genera internamente un ID per alcune voci di menu e lo memorizza nel valore 4 delle matrici di menu. Come i plugin-page-hook. Tuttavia, per i posttype personalizzati memorizza un ID incompatibile con il formato hook-page-hook. Penso che molto potrebbe essere aiutato se WP lo rendesse coerente (cioè crea ganci di pagina per tutto e li usa per associare tra loro le voci del menu, piuttosto che collegare i sottomenu tramite il 'file / slug genitore'.
Wyrfel
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.