O grande desafio do menu de administração do WordPress de janeiro de 2011 (também conhecido como resolver alguns desafios ao modificar o sistema de menus de administração do WordPress?)


14

Esta questão é um pouco única.

É em parte um "desafio" que estou emitindo para a equipe do WordPress ( ou qualquer outra pessoa ) relacionada aos tíquetes trac: # 16048 , # 16050 e # 16204 .

O objetivo

O objetivo é solucionar os três (3) problemas ilustrados na captura de tela abaixo ao tentar modificar a seção do menu Admin do WordPress:

  1. Faça com que a página do submenu "Microsite" seja destacada ao editar um advogado (para isso, precisamos de alguma forma aplicar "current" ao item do submenu, _ e alguns ganchos na função _wp_menu_output () forneceriam o necessário aqui) ,

  2. Obtenha o link Página do menu do advogado para vincular ao /wp-admin/edit.php?post_type=attorneyeditar um advogado (e os mesmos ganchos necessários na função _wp_menu_output () poderiam lidar com isso) e

  3. Obtenha o link "Microsite" para não acionar o erro "Você não tem permissões suficientes para acessar esta página" * (este é o mais desagradável de resolver e um gancho no valor de retornouser_can_access_admin_page() pode resolver esse problema de maneira agradável).

Captura de tela para The Great WordPress Admin Menu Challenge of Jan 2011
(fonte: mikeschinkel.com )

Mais do que apenas meu caso de uso

Esses três (3) problemas são para o meu caso de uso, mas são emblemáticos dos problemas relacionados à configuração dos menus de administrador no WordPress.

Vários membros da equipe do WordPress disseram que é fácil e, portanto, está implícito que estou perdendo alguma coisa (o que pode estar certo), mas eu olhei para esse problema por semanas e não descobri como contorná-lo, então criei o plugin que você vê abaixo ( também disponível para download no Gist ) como o exemplo de caso de uso mais simples dos problemas. O código admin_menu2()é bastante tolo, mas é praticamente o necessário para modificar os menus de administrador no WordPress.

Observe que eu não tentei usar as funções novas remove_menu_page()e novas remove_submenu_page()na versão 3.1 porque levaria mais tempo para criar o plug-in - eu já tinha o código admin_menu2()de um projeto existente - e não acredito que elas abordariam o problema de qualquer maneira.

O que eu preciso?

Eu preciso de uma das duas (2) coisas:

  1. Uma solução para os problemas que eu exponho com este plug-in e explico nesta pergunta e na captura de tela (BTW, desqualificarei sua solução se você usar o Buffer de saída do PHP para resolver qualquer parte disso) ou

  2. Fazer com que a equipe do WordPress reconheça que há realmente a necessidade desses ganchos e que eles reconsiderem sua posição nos ingressos.

Como você aceita o desafio?

  1. Faça o download e instale uma nova cópia do WordPress 3.1 (qualquer revisão provavelmente funcionará) ,

  2. Baixe, instale e ative o plug-in "O grande desafio do menu de administração do WordPress de janeiro de 2011" abaixo (ou faça o download do plug-in no Gist ) e, em seguida,

  3. Siga as instruções encontradas na página do plug-in para este plug-in (veja a captura de tela a seguir), mas basicamente carregue a captura de tela que você vê acima e tente descobrir os três (3) problemas descritos:

Captura de tela das instruções do plugin "O grande desafio do menu de administração do WordPress de janeiro de 2011"
(fonte: mikeschinkel.com )

Um raio de esperança

Felizmente, Andrew Nacin, da equipe do WordPress, se ofereceu para analisar isso uma vez que eu o codifiquei, então estou postando principalmente aqui para ele revisar e comentar, além de ter outros para comentar. Sei que ele está ocupado, mas espero que ele (ou até você) possa dedicar algum tempo para instalar este plug-in em uma instalação nova da v3.1 e ver se ele pode resolver o problema.

Se você concorda que o desafio é impossível?

Se, depois de tentar esse desafio, você chegar à mesma conclusão que eu e se quiser ver os menus Admin do WordPress mais configuráveis, comente esses tickets trac ( # 16048 - # 16050 - # 16204 ) e vote nesta pergunta para mostrar apoio a isso.

Vou admitir alegremente que perdi algo, se eu fiz

É claro que é possível que eu esteja completamente com morte cerebral e alguém possa apontar exatamente como fazê-lo. Na verdade, eu realmente espero que isso aconteça; Prefiro estar errado e ter isso funcionando do que vice-versa.

E aqui está o plugin

Você também pode fazer o download se estiver no 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 que leram isso, realmente espero que você possa ajudar.

Desde já, obrigado.


Estou interessado (e realmente preciso melhorar minha experiência com o lado do administrador), mas provavelmente esperarei pela versão final do 3.1. Minha pilha de testes local não é muito adequada para várias versões principais, por isso continuo com o estável atual.
Rarst

Eu sei exatamente o problema que você fala do Mike, acho que não poderia descrevê-lo melhor do que o seu, mas vi os mesmos problemas ao escrever um menu suspenso para o administrador (por diversão), apenas adicionando meu +1.
t31os 17/01

@ t310s - Obrigado por adicionar o seu +1. Levei provavelmente duas semanas de pesquisa para poder descrever o problema, de modo que você pode até reconhecer que é relevante (e não passou as duas semanas que tenho) significa que você está muito à frente de quase todo mundo, incluindo mim!
MikeSchinkel

Respostas:


2

Mike, dei uma olhada no código e no seu caso de uso final ideal ... e alguns deles, francamente, não são possíveis no sistema atual. Novamente, seus requisitos:

  1. Destaque a página do submenu "Microsite" ao editar um advogado
  2. Obtenha o link Página do menu do advogado para vincular ao /wp-admin/edit.php?post_type=attorneyeditar um advogado
  3. Obtenha o link "Microsite" para não acionar o erro "Você não tem permissões suficientes para acessar esta página"

E a questão principal aqui é a segunda.

O que eu tentei

Tentei adicionar um tipo de postagem personalizado para advogados e fui imediatamente lembrado que /wp-admin/edit.php?post_type=attorneyfornecerá uma lista de advogados, não uma tela de edição real. A edição real ocorre em /wp-admin/post.php?post=10&action=edit. Portanto, se você estiver realmente vinculado ao item 2 ... os outros dois critérios não funcionarão.

É por isso que o nº 3 falha na implementação ... e eu nem consegui tentar o nº 1 porque não consegui chegar tão longe.


Acredite que sua análise está correta. O layout mostrado em questão é aquele em que tive mais de uma solicitação de cliente em seus objetivos para simplificar as estruturas de menu para seus casos de uso. Propus usar submenus, mas eles não gostaram disso; eles acharam que seria muito confuso para seus usuários. Uma coisa que posso não ter mencionado é que estou desenvolvendo um produto baseado no WordPress para distribuir em comparação com um site WordPress, onde eu posso treiná-los para saber como fazer as coisas funcionarem. A outra opção é abandonar o WordPress; não é o que eu quero que eles façam.
precisa saber é o seguinte

2

Olá, Mike, seu problema nº 3 deve-se a você especificar ($microsite, 'the_microsite_editor')onde deveria estar (__CLASS__, 'the_microsite_editor').

Atualização: Depois de gastar muito tempo tentando resolver algum problema semelhante para o meu próprio plug-in, aqui está algo que eu achei que pode ajudar com o seu desafio (observe que as funções são métodos abaixo da sua 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'));
}

Então você simplesmente chama add_posttype_submenu_page()com os parâmetros correspondentes. Isso deve adicionar corretamente um item de submenu a um menu criado automaticamente durante uma register_post_type()chamada.


oops ... os sublinhados duplos em torno de CLASS foram transformados em formatação ousada ;-) #
11124 wyrfel

Eu consertei isso. :)
fuxia

Oh, isso é simplesmente demais; obrigado! Como eu poderia ter perdido esse primeiro ponto?!? Doh!
21811 MikeSchinkel

Obrigado, Mike. Voltar ao tópico original ... O WP gera internamente um ID para algumas entradas do menu e o armazena no valor 4 das matrizes de menu. Como os ganchos de página de plug-in. No entanto, para pós-tipos personalizados, ele armazena um ID que é inconsistente com o formato plug-in-page-hook. Eu acho que muito poderia ser ajudado se o WP tornasse isso consistente (ou seja, crie ganchos de página para tudo e use-os para associar entradas de menu uns aos outros, em vez de anexar submenus por meio do 'arquivo / slug pai'.
wyrfel
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.