管理/コンテンツフォームの変更


8

ノード「変更者」を追加した後、各ノードを変更したユーザーをnode_admin_contentフォームの(admin/content)の[作成者]列のすぐ隣に表示する必要があります。

node.admin.incを変更して2行のコードを追加するだけで、これを簡単に解決できました。

...
'changed_by' => t('Changed By'),
...

...
'changed_by' => theme('username', array('account' => user_load($node->changed_by))),
...

もちろん、これはコアを変更するため、適切なソリューションではありません。

だから私はそれからフォームを変更しようとしました:

function hook_form_node_admin_content_alter(&$form, &$form_state, $form_id) { 
  $form['admin']['nodes']['#header']['changed_by'] = t('Changed By');
  // ... ?
}

を使用dpmすると、フォームにオプションのノードがあることがわかります。問題は、これがノードをテーブルオプションとしてレンダリングした結果であるということです。元のノードにアクセスできません。また、「変更者」情報を取得するためにノードフェッチクエリを再実行しません。フォームフックでこれを行うと、正しいレイヤーでそれを解決できないと思います。またはそれは?

では、node_admin_contentノードに存在するデータをさらに追加するためにフォームを変更する良い方法は何ですか?

回答:


18

悪いニュースは、コードを検査した後、フォーム変更レイヤーが実際にこれを行う唯一の場所であることです。あなたのアプローチはかなり適切です。

良いニュースは、Drupalがページの読み込み全体であらゆる種類の静的キャッシュを実装することです。これにより、データベースに戻る必要が最小限になります。したがって、コンテンツテーブルを変更するのは面倒に見えるかもしれませんが、実際には目立ったパフォーマンスへの影響はありません。

次のコード(または類似のコード)が機能するはずです。キャッシュの問題の詳細については、コメントを参照してください。

function MYMODULE_form_node_admin_content_alter(&$form, &$form_state, $form_id) {
  // Load the nodes. This incurrs very little overhead as 
  // "$nodes = node_load_multiple($nids);" has already been run on these
  // nids in node_admin_nodes(). The static cache will be used instead of
  // another db query being invoked
  $nodes = node_load_multiple(array_keys($form['admin']['nodes']['#options']));

  // Grab a list of all user ids that have been responsible for changing the node
  $uids = array();
  foreach ($nodes as $node) {
    $uids[] = $node->changed_by;
  }

  // Filter out duplicates (one user may have been the last to change more than one node)
  $uids = array_unique($uids);

  // Load a list of all involved users in one go. This is about as performant
  // as this is going to get, as you're going to need the user objects one
  // way or the other for the call to theme_username
  $users = user_load_multiple($uids);

  // Add another column to the table header
  $form['admin']['nodes']['#header']['changed_by'] = array('data' => t('Changed by'));

  // Loop through the rows in the table and add the changed by column
  foreach ($form['admin']['nodes']['#options'] as $nid => $row) {
    // Grab the user related to this node.
    $this_user = $users[$nodes[$nid]->changed_by];

    // Add data for the new column
    $form['admin']['nodes']['#options'][$nid]['changed_by'] = theme('username', array('account' => $this_user));
  }
}

上記のコードは、コンテンツ管理ページに次のような素敵な光沢のある新しい列を生成します。

ここに画像の説明を入力してください


4
見事!質の高いドキュメントを提供していただき、ありがとうございます。
cherouvim

@cherouvim心配ありません:)
クライブ

私にとってもその働きに感謝しますが、著者の列に著者の電子メールではなく著者のユーザー名または本名を表示したいように、既存の列を変更したいと思います。
Pranav Gandhi 2013

3

admin / contentをViewに置き換え、必要なフィールドを追加します。 管理者ビューはあなたのためにもそれを行います。


それも私の最初の考えでしたが、ビューはノードテーブルに追加された新しい列について自動的に認識しますか?hook_schema()/ hook_schema_alter()実装からエンティティプロパティに関する情報を取得しますか?
クライヴ

CCKフィールドを追加したと思います。これで、hook_schema_alter()を使用したことがわかりました。それでも、hook_views_data_alter()を実装して新しい列を公開できます。
Bojan Zivanovic

ええ、それをするのは「正しい」とは思われませんでした。この方法で列を追加すると実際に問題が発生するシナリオを考えられますか?
クライヴ

それは問題を引き起こさず、「イデオロギー的に」間違っている間、あなたにちょっと余分な仕事を与えます(ビューのためにhook_views_data_alter()が必要です、プロパティについても同じです)、それは非常にDrupal 5の考え方です。まあ、大したことはありません。
Bojan Zivanovic、2012年

知ってありがとう。個人的には、私は常にこの種のことにフィールドを使用していましたが、大きな副作用なしで実行できることを知るのは興味深いことでした。しかし、あなたの答えはそれについて多くを語っています。適切な/推奨される方法で(つまりフィールドを使用して)実行すると、後で多くの作業を節約できます
Clive

0

少しずれていますが、この回答は、プログラムでこれを行う方法を示しています(たとえば、MY_MODULE.installファイルにモジュール更新として追加することによって)。

最後の既存のフィールドの前に新しいフィールドを追加する場合は、もう少し作業が必要になります。$ view-> display ['default']-> display_options ['fields']配列の最後の前にマージします。

    function MY_MODULE_update_7101(){
        // update the admin/content view, need to do it manually because it's
        // set by admin_views module
        $view_name = 'admin_views_node';
        $view = views_get_view($view_name, TRUE);

        //  add the relationship
        $view->display['default']->display_options['relationships']['uid_1']['id'] = 'uid_1';
        $view->display['default']->display_options['relationships']['uid_1']['table'] = 'node_revision';
        $view->display['default']->display_options['relationships']['uid_1']['field'] = 'uid';
        $view->display['default']->display_options['relationships']['uid_1']['label'] = 'Revision User';
        // new column settings
        $new_column = array(
            'name_1' => array(
                'id' => 'name_1',
                'table' => 'users',
                'field' => 'name',
                'relationship' => 'uid_1',
                'label' => 'Updated By',
            )
        );
        // need to use this because array_splice by itself resets 'name_1' key to '0'
        // see http://php.net/manual/en/function.array-splice.php#56794
        $temp_array = array_splice( $view->display['default']->display_options['fields'] , 0, 7);
        $view->display['default']->display_options['fields'] = array_merge($temp_array , $new_column, $view->display['default']->display_options['fields']);

        views_save_view($view);
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.