タイトルが長すぎですね。
要するにWordPressを利用した会員制サイトの可能性を調査していたらずいぶんハマってしまったというお話です。

 

やりたいこと

  • Webサイトの会員にWordPressのアカウントを与える
  • そのアカウントでログインした場合に限り、サイドバーに任意のカスタム投稿だけを表示し一覧のみ可能にする(新規作成・編集・削除は不可)

試行錯誤

解決までの流れを記録しておきました。過程って大事だよね。

まずは「購読者」権限グループでアカウントを作成しログイン。
「購読者」権限グループのユーザーに限り、「履歴(history)」というカスタム投稿だけ表示させる。
また、「履歴(history)」の新規追加・編集・削除は禁止し、一覧だけを許可する。

1)まずは確認

  • 購読者に「edit_posts」権限を与えてみる

当然、一覧表示できるようになるが、他のカスタム投稿まで表示されてしまう。

2)新しい権限を作る

  • 「edit_posts」権限をはく奪し、代わりに「my_cap」という新しい権限を与える
  • カスタム投稿「履歴(history)」の「edit_posts」権限の名称を「my_cap」に変更

期待通りカスタム投稿「履歴(history)」のみが表示されるようになった。が、なぜか一覧にアクセスできない・・・

3)権限グループを昇格させてみる

  • 権限グループを「寄稿者」に昇格
  • 新しい権限「my_cap」を付与

結果は変わらず・・・

4)逆に

  • 「寄稿者」から「my_cap」権限をはく奪
  • カスタム投稿「履歴(history)」を除いて、権限「edit_posts」の名称を「my_cap」に変更する

一覧にアクセスはできるようになったが新規投稿ができてしまう。

5)新規投稿をできなくする

  • 「create_posts」権限をはく奪させてみる

またしても一覧にアクセスできなくなる・・・・

 

ここでハマります。

 

なんでかサブメニューがひとつもないと権限があってもアクセスできなくなるらしい(なんかバグっぽい?)

どうやらuser_can_access_admin_page()内で$parentがemptyだとだめらしい。
サブメニューがひとつもないとget_admin_page_parent()が「”(ブランク)」を返すのが原因っぽいけどどこにもフックできない。
その結果、$pagenowが「edit.php(投稿)」にされちゃって、投稿は「edit_posts」権限をはく奪してるからアクセスできない・・・というわけらしい。

admin_menuにフックして$pagenowを書き換えればいけたけどなんだか不安なので、ダミーのサブメニューをひとつ追加し、存在しないアクセス権限を付与して非表示にすることで対応しました。

権限の設定は最終的に以下になりました。

  • 権限グループを「投稿者」に変更
  • 「投稿者」の「read」以外の権限をはく奪
  • 新しい権限「my_cap」を付与

なぜ「投稿者」の必要があるか。

  • 「購読者」の場合、「管理者」がそのアカウントを作成者として記事を投稿できない
  • 「寄稿者」の場合、「edit_posts」などの権限に関係なく「レビュー待ち」として記事が作成できてしまう

まとめ

  • 投稿者」権限グループでアカウント作成
  • 投稿者」に新しい権限を与える。例えば「my_cap」
  • 表示させたいカスタム投稿の「edit_posts」権限の名称を「my_cap」に置き換える
  • 「投稿者」の「read」以外の権限をはく奪
  • サブメニューがひとつもない場合、その親は「投稿(ビルトイン)」ってことにされる
  • 故に、「投稿(ビルトイン)」の「edit_posts」権限をはく奪すると、カスタム投稿の「edit_posts」もないとみなされる
  • アクセス不能な権限のサブメニューをくっつけることで対応