2011 년 1 월의 위대한 WordPress 관리 메뉴 과제 (일명 WordPress 관리 메뉴 시스템을 수정할 때 일부 문제를 해결하는 방법)


14

이 질문은 조금 독특합니다.

그것은 trac 티켓과 관련된 WordPress 팀 ( 또는 다른 사람 ) 에게 발행 하는 "도전"입니다 : # 16048 , # 16050# 16204 .

목표

목표는 WordPress 관리 메뉴 섹션을 수정할 때 아래 스크린 샷에 설명 된 3 가지 문제를 해결하는 것입니다 .

  1. 가져 오기 "마이크로" 변호사를 편집 할 때 강조하는 하위 메뉴 페이지 (우리는 어떻게 든 하위 메뉴 항목, _ 및에 "현재"적용 할 수 있어야이를 위해 _wp_menu_output 일부 후크 () 함수가 어떻게 여기에 필요한 제공 할 것) ,

  2. 링크에 변호사 메뉴 페이지 링크 가져 오기 /wp-admin/edit.php?post_type=attorney변호사 편집 할 때 (그 () 함수는 _wp_menu_output에서 같은 필요한 후크를 이 문제를 해결할 수)를 하고,

  3. " 이 페이지에 액세스 할 수있는 충분한 권한이 없습니다" 오류가 발생 하지 않도록 "마이크로 사이트" 링크를 가져 옵니다. * (이것은 가장 해결하기 어려운 것이므로 의 반환 값에user_can_access_admin_page() 대한 후크 가이 문제를 잘 처리 할 수 ​​있습니다.)

2011 년 1 월 Great WordPress 관리 메뉴 챌린지 스크린 샷
(출처 : mikeschinkel.com )

내 유스 케이스 그 이상

이 세 가지 문제는 사용 사례에 관한 것이지만 WordPress의 관리 메뉴 구성과 관련된 문제를 상징합니다.

WordPress 팀의 일부 사람들은 쉽고 빠르다는 것을 암시한다고 말 했지만 (올바르지 않을 수도 있음) 몇 주 동안이 문제를 보았고 해결 방법을 찾지 못하여 아래에서 볼 수있는 플러그인을 만들었습니다. ( Gist에서 다운로드 할 수 있음 ) 문제의 가장 간단한 사용 사례입니다. 코드 admin_menu2()는 다소 해킹 적이지만 WordPress의 관리 메뉴를 수정하는 데 필요한 것입니다.

플러그인을 만드는 데 시간이 오래 걸렸기 때문에 3.1 remove_menu_page()에서 새로운 remove_submenu_page()기능 이나 새로운 기능 을 사용하려고 시도하지 않았습니다 admin_menu2(). 기존 프로젝트 에서 이미 코드를 가지고 있었기 때문에 그것들을 해결할 것이라고 생각하지 않습니다. 어쨌든 문제.

내가 무엇이 필요 하나?

두 가지 중 하나가 필요합니다.

  1. 이 플러그인으로 노출 되고이 질문과 스크린 샷에서 설명하는 문제에 대한 해결책 (BTW, PHP 출력 버퍼링 을 사용 하여이 부분을 해결 하면 솔루션을 실격 처리합니다 ) 또는

  2. WordPress 팀이 실제로 이러한 후크가 필요하다는 것을 인식하고 티켓에서 자신의 위치를 ​​재고하도록하십시오.

어떻게 도전을합니까?

  1. 다운로드 및 설치 워드 프레스 3.1의 깨끗한 새 복사본을 (모든 버전은 아마 할 것) ,

  2. 다운로드, 설치 및 활성화 "위대한 워드 프레스 관리자 메뉴를 도전 2011년 1월의" 아래 플러그인 (또는 요점에서 플러그인을 다운로드 ) 다음과

  3. 이 플러그인의 플러그인 페이지에있는 지침을 따르고 (다음 스크린 샷 참조) 기본적으로 위에서 본 스크린 샷을로드 한 다음 설명 된 3 가지 문제를 파악하십시오.

"2011 년 1 월의 Great WordPress 관리 메뉴 챌린지"플러그인 스크린 샷
(출처 : mikeschinkel.com )

희망의 한 광선

다행스럽게도 WordPress 팀의 Andrew Nacin은 코드를 작성했을 때 이것을 보겠다고 제안 했습니다. 그래서 나는 주로 여기에 게시하여 리뷰하고 의견을 남기고 다른 사람들도 의견을 말하도록합니다. 나는 그가 바쁘다는 것을 알고 있지만 그가 (또는 심지어 당신도) v3.1의 초기 설치 에이 플러그인을 설치하고 그가 문제를 해결할 수 있는지 확인하기를 바랍니다.

당신이 동의한다면 도전은 불가능합니까?

이 문제를 시도한 후 당신은 저와 같은 결론에 도달, 당신은 워드 프레스 관리자 메뉴가이 TRAC 티켓에 대한 자세한 구성하십시오 코멘트 수를 참조하려는 경우 경우 ( 16048 # - 16050 # - # 16204 )이 질문을 투표 지원을 보여주기 위해.

내가 간절히 뭔가를 놓친 걸 인정 할게

물론 나는 이것에 대해 완전히 두뇌 죽을 수 있고 누군가가 그것을하는 방법을 정확하게 지적 할 수 있습니다. 사실, 나는 그것이 사실이되기를 바랍니다. 차라리 오히려 틀렸고 그 반대의 경우도 마찬가지입니다.

그리고 여기 플러그인이 있습니다

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

이 글을 읽는 모든 사람들에게 도움이되기를 바랍니다.

미리 감사드립니다.


나는 관심이 있고 (실제로 관리자 측 경험을 향상시켜야합니다) 3.1 최종 릴리스를 기다릴 것입니다. 내 로컬 테스트 스택은 여러 코어 버전에 적합하지 않으므로 현재 안정 상태를 고수합니다.
Rarst

나는 당신이 Mike에 대해 말한 문제를 정확히 알고 있습니다. 내가 가지고있는 것보다 더 잘 설명 할 수는 없다고 생각하지만 관리자를위한 드롭 다운 메뉴를 작성할 때 (재미있는) 매우 동일한 문제를 보았습니다. 내 +1
t31os

@ t310s-+1을 추가해 주셔서 감사합니다. 당신도 그와 관련이 있음을 인식 할 수 사실, 그래서이 문제를 설명 할 수 아마도 연구의 2 주 걸렸다 (내가 가지고있는 이주를 보낸 적이없는) 을 포함하여 당신이 방법은 앞서이 대부분의 사람의 의미를 나를!
MikeSchinkel

답변:


2

Mike, 코드와 이상적인 최종 사용 사례를 살펴 보았습니다. 솔직히 현재 시스템에서는 불가능합니다. 다시, 요구 사항 :

  1. 변호사를 편집 할 때 "마이크로 사이트"하위 메뉴 페이지를 강조 표시하십시오.
  2. 변호사 메뉴 페이지 링크 받기 /wp-admin/edit.php?post_type=attorney 편집 때 오기
  3. "이 페이지에 액세스 할 수있는 권한이 없습니다"오류가 발생하지 않도록 "마이크로 사이트"링크를 가져옵니다.

여기서 중요한 문제는 # 2입니다.

내가 시도한 것

변호사를위한 맞춤 게시물 유형을 추가하려고했지만 실제 수정 화면이 아니라 변호사 목록/wp-admin/edit.php?post_type=attorney제공 한다는 사실을 즉시 상기했습니다 . 실제 편집은/wp-admin/post.php?post=10&action=edit . 따라서 당신이 정말로 # 2에 묶여 있다면 ... 다른 두 가지 기준은 효과가 없습니다.

이것이 # 3이 구현에 실패하는 이유입니다.


분석이 정확하다고 생각하십시오. 해당 레이아웃은 사용 사례에 대한 메뉴 구조를 단순화하기 위해 하나 이상의 클라이언트 요청을 목표로 한 레이아웃입니다. 하위 메뉴 사용을 제안했지만 그들은 마음에 들지 않았습니다. 그들은 사용자에게 너무 혼란 스러울 것이라고 생각했습니다. 내가 언급하지 않은 한 가지는 배포 할 워드 프레스 기반 제품을 개발하고 있다는 것입니다. 다른 옵션은 WordPress를 포기하는 것입니다. 내가 원하는 것을하지 않았습니다.
MikeSchinkel

2

Mike, 문제 # 3은을 (를) 지정 ($microsite, 'the_microsite_editor')해야합니다 (__CLASS__, 'the_microsite_editor').

업데이트 : 내 플러그인의 비슷한 문제를 해결하기 위해 너무 많은 시간을 보낸 후 여기에 도전에 도움이 될만한 것이 있습니다 (함수는 클래스 아래에있는 메소드입니다).

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

그런 다음 add_posttype_submenu_page()해당 매개 변수로 간단히 호출 하십시오. register_post_type()통화 중에 자동 생성 된 메뉴에 하위 메뉴 항목을 올바르게 추가해야합니다 .


죄송합니다 ... CLASS 주위에 이중 밑줄은 ;-) 굵게 서식으로 전환되었다
wyrfel

나는 그것을 고쳤다. :)
fuxia

오, 정말 대단합니다. 감사! 첫 번째 요점을 어떻게 놓칠 수 있었습니까?!? 도!
MikeSchinkel

고마워, 마이크 원래 주제로 돌아 가기 ... WP는 내부적으로 일부 메뉴 항목의 ID를 생성하고이를 메뉴 배열의 값 4에 저장합니다. 플러그인 페이지 후크와 같은. 그러나 사용자 정의 포스트 타입의 경우 플러그인 페이지 후크 형식과 일치하지 않는 ID를 저장합니다. WP가 일관성을 유지한다면 (예 : '부모 슬러그 / 파일'을 통해 하위 메뉴를 첨부하는 대신 모든 페이지 후크를 만들고 메뉴 항목을 서로 연결하는 데 사용하는 경우) 많은 도움이 될 수 있다고 생각합니다.
wyrfel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.