„Zmienione przez” w węzłach

9
mysql> select nid, uid, created, changed from node;
+-----+-----+------------+------------+
| nid | uid | created    | changed    |
+-----+-----+------------+------------+
|   1 |   8 | 1336040166 | 1336046390 |
+-----+-----+------------+------------+

Chciałbym mieć kolumnę „zmienione przez” w nodetabeli, dokładnie tak, jak mamy „utworzone przez” (pole uid). Pozwoli to śledzić, kto dokonał ostatniej zmiany w tym węźle. Wiem, że można to wyprowadzić z node_revisiontabeli, ale zależy to od włączenia poprawek dla typów zawartości, które mnie interesują.

Więc jaki jest najlepszy sposób, aby to zrobić? I dlaczego rdzeń Drupala nie oferuje tego domyślnie? Pomyślałem, że „zmieniony przez” to dość standardowa informacja, którą CMS powinien dołączyć do treści.

Cherouvim
źródło
2
Czy istnieje powód, dla którego nie można włączyć weryfikacji? Wydaje się, że to najłatwiejszy sposób na zdobycie tego, czego potrzebujesz. Prawdopodobnie tak bym zrobił. Jeśli ludzie będą często edytować węzły, oznacza to również, że masz kopię zapasową poprzednich wersji.
Chapabu
Tak, mogę. Chciałbym jednak wiedzieć, czy można to mieć na głównym nodestole. Wygląda to bardziej prosto.
cherouvim

Odpowiedzi:

18

Myślałem, że będzie to trudne, ale jak się okazuje, jest to dość łatwe.

Wystarczy utworzyć niestandardowy moduł, który dodaje kolumnę do tabeli węzłów podczas instalacji, wdrożyć, hook_schema_alter()aby Drupal wiedział o nowej kolumnie, i dodać logikę, aby podać wartość przed zapisaniem węzła.

Oto mały moduł, który załatwi sprawę:

Plik: node_table_alter.info

name = Node Table Alter
core = 7.x

Plik: node_table_alter.install

function node_table_alter_install() {
  // Add the new field to the node table
  $field = array(
    'description' => 'Stores the user id of the last user to alter the node',
    'type' => 'int',
    'unsigned' => TRUE
  );

  db_add_field('node', 'changed_by', $field);
}

Plik: node_table_alter.module

function node_table_alter_schema_alter(&$schema) {
  // Add the new field to the schema cache
  $schema['node']['fields']['changed_by'] = array(
    'description' => 'Stores the user id of the last user to alter the node',
    'type' => 'int',
    'unsigned' => TRUE
  );
}

function node_table_alter_node_presave($node) {
  // Populate the changed_by column with current user's id
  $node->changed_by = $GLOBALS['user']->uid;
}

Możesz dodać logikę, aby usunąć pole ponownie podczas odinstalowywania i dodać indeks do tabeli dla changed_bykolumny (patrz db_add_index()), ale powinno to dać dobre miejsce do rozpoczęcia.

Zaletą tej metody jest to, że skutecznie dodałeś nową właściwość do węzła. Będziesz mógł używać node_load(), EntityFieldQuerys, itp. Z nim tak, jakby to była dowolna inna standardowa właściwość dla węzła.

Niech Bóg błogosławi Drupalowi za to, że jest tak rozciągliwy!

Clive
źródło
BTW, możesz użyć dokładnie tej samej logiki, aby odpowiedzieć na inne pytanie .
Clive
2
Aby uzyskać pełną integrację encji, a jeśli korzystasz z modułu Entity API, musisz również zaimplementować hook_entity_property_info (), aby uniknąć informiom o tej nowej właściwości.
Pierre Buyle,
@PierreBuyle Dobra uwaga, nie myślałem o tym
Clive
1
Właśnie to robi moduł UUID. Sprawdź to, aby uzyskać pełniejszą implementację czegoś podobnego. drupal.org/project/uuid
paul-m
Bardzo dziękuję za szczegółowe wyjaśnienie i czyste rozwiązanie!
cherouvim
1

Myślę, że możesz dodać pole referencyjne encji (nazwijmy to field_changed_by_user) do typu zawartości, który chcesz śledzić. Następnie możesz użyć, hook_node_presaveaby zapisać identyfikator użytkownika w węźle w następujący sposób:

function hook_node_presave($node) {
  if ($node->nid && $node->type == 'content_type_to_track_changes_for') {
    global $user;
    $node->field_changed_by_user['und'][0]['target_id'] = $user->uid;
  }
}

Myślę, że można również zaktualizować pole z identyfikatorem użytkownika, po prostu tworząc regułę. Możesz przeczytać więcej tutaj .

Marius Ilie
źródło