Tantangan Besar Admin Menu WordPress pada Januari 2011 (alias Cara Mengatasi Beberapa Tantangan saat Memodifikasi Sistem Menu Admin WordPress?)

14

Pertanyaan ini agak unik.

Ini sebagian merupakan "tantangan" yang saya keluarkan untuk tim WordPress ( atau siapa pun ) yang terkait dengan tiket trac: # 16048 , # 16050 dan # 16204 .

Target

Tujuannya adalah untuk mengatasi tiga (3) masalah yang diilustrasikan dalam tangkapan layar di bawah ini ketika mencoba memodifikasi bagian menu Admin WordPress:

  1. Dapatkan halaman submenu "Microsite" yang akan disorot saat mengedit Pengacara (untuk ini kita perlu entah bagaimana dapat menerapkan "saat ini" ke item submenu, _ dan beberapa kait di fungsi _wp_menu_output () akan menyediakan apa yang dibutuhkan di sini) ,

  2. Dapatkan tautan Halaman Menu Pengacara untuk ditautkan /wp-admin/edit.php?post_type=attorneysaat mengedit Pengacara (dan pengait yang sama yang dibutuhkan dalam fungsi _wp_menu_output () dapat menangani hal ini) , dan

  3. Dapatkan tautan "Microsite" untuk tidak memicu kesalahan "Anda tidak memiliki izin yang memadai untuk mengakses halaman ini" * (ini adalah yang paling menjengkelkan untuk diselesaikan, dan kait pada nilai balik dariuser_can_access_admin_page() dapat menangani masalah ini dengan baik.)

Cuplikan layar untuk Tantangan Menu Admin WordPress Hebat Januari 2011
(sumber: mikeschinkel.com )

Lebih dari sekadar kasus penggunaan saya

Tiga (3) masalah ini adalah untuk kasus penggunaan saya tetapi mereka merupakan simbol dari masalah yang berkaitan dengan mengkonfigurasi menu admin di WordPress.

Beberapa di tim WordPress mengatakan bahwa itu mudah dan dengan demikian menyiratkan saya kehilangan sesuatu (yang mungkin benar) tapi saya sudah melihat masalah ini selama berminggu-minggu dan tidak tahu bagaimana cara mengatasinya sehingga saya membuat plugin yang Anda lihat di bawah ini ( juga dapat diunduh dari Gist ) sebagai contoh kasus penggunaan yang paling sederhana. Kode dalam admin_menu2()agak retas tapi itu cukup banyak yang diperlukan untuk memodifikasi Menu Admin di WordPress.

Perhatikan bahwa saya tidak mencoba menggunakan fungsi baru remove_menu_page()atau remove_submenu_page()fungsi baru di 3.1 karena akan membutuhkan waktu lebih lama untuk membuat plugin - saya sudah memiliki kode admin_menu2()dari proyek yang ada - dan saya tidak percaya mereka akan mengatasi masalah tetap.

Apa yang saya butuhkan?

Saya membutuhkan satu dari dua (2) hal:

  1. Solusi untuk masalah yang saya paparkan dengan plugin ini dan jelaskan dalam pertanyaan ini dan dalam tangkapan layar (BTW, saya akan mendiskualifikasi solusi Anda jika Anda menggunakan PHP Output Buffering untuk menyelesaikan bagian mana pun dari ini) , atau

  2. Agar Tim WordPress mengenali bahwa memang ada kebutuhan untuk kaitan ini dan membuat mereka mempertimbangkan kembali posisi mereka di tiket.

Bagaimana Anda Menerima Tantangan?

  1. Unduh dan pasang salinan baru WordPress 3.1 yang asli (revisi apa pun mungkin akan dilakukan) ,

  2. Unduh, pasang dan aktifkan plugin "Tantangan Menu Admin WordPress Hebat Jan 2011" di bawah ini (atau unduh plugin dari Gist ) , lalu

  3. Ikuti instruksi yang ditemukan pada halaman plugin untuk plugin ini (lihat screenshot berikut) tetapi pada dasarnya memuat screenshot yang Anda lihat di atas dan kemudian coba mencari tahu tiga (3) masalah yang dijelaskan:

Cuplikan layar instruksi plugin "The Great WordPress Menu Tantangan Januari 2011"
(sumber: mikeschinkel.com )

Satu Sinar Harapan

Untungnya Andrew Nacin dari tim WordPress menawarkan untuk melihat ini setelah saya mengkodekannya jadi saya terutama memposting di sini untuk dia tinjau dan komentari serta meminta orang lain untuk berkomentar. Saya tahu dia sibuk tetapi saya berharap dia (atau bahkan Anda) dapat meluangkan waktu untuk menginstal plugin ini pada instalasi murni v3.1 dan melihat apakah dia dapat menyelesaikan masalah.

Jika Anda Setuju, Tantangannya Tidak Mungkin?

Jika setelah mencoba tantangan ini, Anda sampai pada kesimpulan yang sama dengan saya, dan jika Anda ingin melihat menu Admin WordPress lebih dapat dikonfigurasi, silakan komentari tiket trac ini ( # 16048 - # 16050 - # 16204 ) dan pilih pertanyaan ini. untuk menunjukkan dukungan untuk itu.

Saya dengan senang hati akan mengakui bahwa saya kehilangan sesuatu, jika saya melakukannya

Tentu saja mungkin saya bisa benar-benar mati dalam hal ini dan seseorang dapat menunjukkan dengan tepat bagaimana melakukannya. Sebenarnya, saya benar-benar berharap yang akhirnya menjadi kasus; Saya lebih suka salah dan ini berfungsi daripada sebaliknya.

Dan Ini Pluginnya

Anda juga dapat mengunduh jika dari 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();
}

Kepada semua yang membaca ini, saya sangat berharap Anda dapat membantu.

Terima kasih sebelumnya.

MikeSchinkel
sumber
Saya tertarik (dan benar-benar perlu meningkatkan pengalaman saya dengan sisi admin), tetapi mungkin akan menunggu rilis final 3.1. Tumpukan uji lokal saya tidak terlalu cocok untuk beberapa versi inti jadi saya tetap menggunakan stabil saat ini.
Paling lambat
Saya tahu persis masalah Anda berbicara tentang Mike, saya tidak berpikir saya bisa menggambarkannya lebih baik daripada yang Anda miliki di sana, tetapi saya telah melihat masalah yang sama ketika menulis menu dropdown untuk admin (untuk bersenang-senang), hanya menambahkan +1 saya.
t31os
@ t310s - Terima kasih telah menambahkan +1 Anda. Mungkin butuh 2 minggu penelitian untuk dapat menggambarkan masalahnya, sehingga fakta Anda bahkan dapat mengenali bahwa itu relevan (dan belum menghabiskan 2 minggu yang saya miliki) berarti Anda jauh lebih maju dari kebanyakan orang dalam hal ini, termasuk saya!
MikeSchinkel

Jawaban:

2

Mike, saya telah melihat kode dan kasus penggunaan akhir ideal Anda ... dan beberapa dari mereka, sejujurnya, tidak mungkin dengan sistem saat ini. Sekali lagi, persyaratan Anda:

  1. Dapatkan halaman submenu "Microsite" yang akan disorot saat mengedit Pengacara
  2. Dapatkan tautan Halaman Menu Pengacara untuk ditautkan /wp-admin/edit.php?post_type=attorneysaat mengedit suatu Pengacara
  3. Dapatkan tautan "Microsite" untuk tidak memicu kesalahan "Anda tidak memiliki izin yang memadai untuk mengakses halaman ini"

Dan masalah utama di sini adalah # 2.

Apa yang saya coba

Saya mencoba menambahkan jenis pos kustom untuk Pengacara dan segera diingatkan bahwa /wp-admin/edit.php?post_type=attorneyakan memberi Anda daftar pengacara, bukan layar edit yang sebenarnya. Pengeditan aktual berlangsung pada /wp-admin/post.php?post=10&action=edit. Jadi, jika Anda benar-benar terikat dengan # 2 ... dua kriteria lainnya tidak akan berfungsi.

Inilah sebabnya mengapa # 3 gagal dalam implementasi ... dan saya bahkan tidak dapat mencoba # 1 karena saya tidak bisa sejauh itu.

EAMann
sumber
Percayalah analisis Anda benar. Layout yang diperlihatkan dalam pertanyaan adalah salah satu yang saya punya lebih dari satu permintaan klien dalam tujuan mereka untuk menyederhanakan struktur menu untuk kasus penggunaan mereka. Saya sudah mengusulkan menggunakan submenu tetapi mereka tidak menyukainya; mereka merasa itu akan terlalu membingungkan bagi penggunanya. Satu hal yang mungkin tidak saya sebutkan adalah bahwa saya sedang mengembangkan produk berbasis WordPress untuk mereka bagikan vs situs web WordPress untuk mereka di mana saya bisa melatih mereka untuk mengetahui cara membuat sesuatu bekerja. Pilihan lainnya adalah meninggalkan WordPress; bukan apa yang saya ingin mereka lakukan.
MikeSchinkel
2

Hai Mike, masalah Anda # 3 adalah karena Anda menentukan ($microsite, 'the_microsite_editor'), di mana seharusnya (__CLASS__, 'the_microsite_editor').

Pembaruan: Setelah menghabiskan terlalu banyak waktu untuk mencoba memecahkan masalah serupa untuk plugin saya sendiri, berikut adalah sesuatu yang saya temukan yang dapat membantu dengan Tantangan Anda (perhatikan bahwa fungsinya adalah metode di bawah kelas Anda):

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

Maka Anda cukup memanggil add_posttype_submenu_page()dengan parameter yang sesuai. Ini harus menambahkan item submenu ke menu yang dibuat secara otomatis saat register_post_type()panggilan berlangsung.

wyrfel
sumber
oops ... garis bawah ganda di sekitar CLASS diubah menjadi format tebal ;-)
wyrfel
Aku telah memperbaikinya. :)
fuxia
Oh, itu luar biasa; Terima kasih! Bagaimana saya bisa melewatkan poin pertama itu?!? Doh!
MikeSchinkel
Terima kasih, Mike. Kembali ke topik awal Anda ... WP menghasilkan ID untuk beberapa entri menu dan menyimpannya dalam nilai 4 dari susunan menu. Seperti plugin-page-hooks. Namun, untuk posttype khusus, ia menyimpan ID yang tidak konsisten dengan format plugin-page-hook. Saya pikir banyak yang bisa membantu jika WP akan membuat ini konsisten (yaitu membuat kait halaman untuk semuanya dan menggunakannya untuk mengaitkan entri menu satu sama lain, daripada melampirkan submenu dengan menggunakan 'parent slug / file'.
wyrfel