Изменение формы администратора / контента

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форму, чтобы добавить больше данных, которые существуют на узлах?

cherouvim
источник

Ответы:

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
Superb! Большое спасибо за предоставление качественной документации с вашим ответом.
Черувим
@cherouvim Не беспокойся :)
Клайв
Спасибо, это работает и для меня, но я хочу изменить существующие столбцы, как если бы я хотел отображать имя автора или реальное имя вместо сообщения автора в столбце автора.
Пранав Ганди
3

Просто замените admin / content на View, а затем добавьте те поля, которые вы хотите. Admin Views даже сделает это за вас.

Боян Живанович
источник
Это была моя первая мысль, но будет ли Views автоматически знать о новом столбце, который был добавлен в таблицу узлов? Получает ли он информацию о свойствах сущности из hook_schema()/ hook_schema_alter()реализаций?
Клайв
Я предположил, что вы только что добавили поле CCK. Теперь я вижу, что вы пошли с hook_schema_alter (), что очень неприятно. Тем не менее, вы можете реализовать hook_views_data_alter (), чтобы открыть новый столбец.
Боян Живанович
Да, это было не совсем правильно, но я не могу понять, почему. Можете ли вы вспомнить сценарий, в котором добавление столбца таким образом на самом деле может вызвать проблемы?
Клайв
Это не вызывает никаких проблем, просто дает вам немного дополнительной работы (например, необходимость использования hook_views_data_alter () для Views, то же самое для свойств, если вы находитесь на D7), хотя «идеологически» неверно, это очень сложное мышление Drupal 5 , Ну да ладно, ничего страшного.
Боян Живанович
Спасибо, это приятно знать. Лично я всегда использовал бы поля для такого рода вещей, но было интересно узнать, что это можно сделать без больших побочных эффектов. Ваш ответ говорит об этом много, хотя; если вы сделаете это надлежащим / рекомендованным способом (то есть с полями), вы сэкономите много работы позже
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);
    }
reedbert
источник