Alterar el formulario de administrador / contenido

8

Después de haber agregado un "cambiado por" en los nodos , ahora necesito mostrar al usuario que modificó cada nodo en el node_admin_contentformulario (en admin/content) justo al lado de la columna "Autor".

Me las arreglé para resolver esto fácilmente alterando node.admin.inc y agregando solo 2 líneas de código:

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

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

Esto, por supuesto, no es una solución adecuada ya que altera el núcleo.

Entonces intenté alterar el formulario a través de:

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

Usando dpmpuedo ver que el formulario tiene los nodos en opciones. El problema es que este es el resultado de representar los nodos como opciones de tabla. No tengo acceso a los nodos originales, ni quiero volver a ejecutar la consulta de búsqueda de nodos para obtener la información "cambiada por". Supongo que hacer esto en el gancho de la forma no lo resolvería en la capa correcta. ¿O es eso?

Entonces, ¿cuál es una buena manera de alterar el node_admin_contentformulario para agregar más datos que existen en los nodos?

cherouvim
fuente

Respuestas:

18

La mala noticia es que después de haber inspeccionado el código, el formulario alterar capa es el único lugar para hacerlo realmente; su enfoque es bastante acertado.

La buena noticia es que Drupal implementa todo tipo de almacenamiento en caché estático durante la carga de la página, lo que minimiza la necesidad de volver a la base de datos. Por lo tanto, si bien alterar la tabla de contenido puede parecer engorroso, en realidad no está recibiendo un golpe notable en el rendimiento.

El siguiente código (o similar) debería funcionar; Consulte los comentarios para obtener más información sobre el problema de almacenamiento en caché:

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

El código anterior produce una bonita columna nueva y brillante como esta en la página de administración de contenido:

ingrese la descripción de la imagen aquí

Clive
fuente
44
¡Soberbio! Muchas gracias por proporcionar documentación de calidad con su respuesta.
cherouvim
@cherouvim No te preocupes :)
Clive
Gracias, también funciona para mí, pero quiero alterar las columnas existentes como quiero mostrar el nombre de usuario del autor o el nombre real en lugar del correo electrónico del autor en la columna del autor.
Pranav Gandhi
3

Simplemente reemplace el administrador / contenido con una Vista y luego agregue los campos que desee. Las vistas de administrador incluso lo harán por ti.

Bojan Zivanovic
fuente
Ese fue mi primer pensamiento también, pero ¿Vistas automáticamente sabría acerca de la nueva columna que se agregó a la tabla de nodos? ¿Obtiene información sobre las propiedades de la entidad de hook_schema()/ hook_schema_alter()implementaciones?
Clive
Supuse que acaba de agregar un campo CCK. Ahora veo que fuiste con hook_schema_alter (), que es muy asqueroso. Aún así, puede implementar hook_views_data_alter () para exponer la nueva columna.
Bojan Zivanovic
Sí, no me pareció "correcto" hacer eso, pero no puedo entender por qué. ¿Puedes pensar en un escenario en el que agregar la columna de esa manera realmente causaría un problema?
Clive
No causa ningún problema, solo le da un poco de trabajo extra (como necesitar hook_views_data_alter () para Vistas, lo mismo para las propiedades si está en D7) mientras está "ideológicamente" equivocado, es una forma de pensar muy Drupal 5 . Oh bueno, no es gran cosa.
Bojan Zivanovic
Gracias, es bueno saberlo. Personalmente, siempre usaría campos para este tipo de cosas, pero fue interesante descubrir que se podía hacer sin grandes efectos secundarios. Sin embargo, su respuesta dice mucho sobre eso; si lo hace de la manera adecuada / recomendada (es decir, con campos), ahorrará mucho trabajo más adelante
Clive
0

Un poco fuera de tema, pero esta respuesta muestra cómo puede hacer esto mediante programación (por ejemplo, al agregarlo como una actualización del módulo en el archivo MY_MODULE.install).

Necesitará un poco más de trabajo si desea agregar su nuevo campo antes del último campo existente. Combínelo antes del final de $ view-> display ['default'] -> display_options ['fields'] array.

    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
fuente