Daten in Listenfeld eines referenzierten (übergeordneten) node ändern
am 11.09.2009 - 08:57 Uhr in
Hallo,
habe ein Problem bei dem mir Anregungen zur Lösung fehlen ...
Also, ich habe 2 content-typen.
1. Projekt (mit Projektbeschreibungsfeldern)
2. Aufgabe (mit Beschreibung einer Teilaufgabe und nodereference auf Projekt).
In beiden Inhaltstypen habe ich auch ein userreference-Feld.
Bei Projekt kann dieses unlimmitiert viele Einträge haben, bei der Aufgabe nur genau 1.
Jetzt möchte ich gerne über rules das Benutzerreference-Feld des Projektes ändern. Dabei ergeben sich für mich 3 Probleme:
1. Wie muss man ein nodereference Feld per php ansprechen, damit man einen neuen Eintrag hinzufügen kann? Also, die bestehende Liste an ref. Benutzern bleibt erhalten, und der neue wird zugefügt.
2. Was passiert wenn der Benutzer schon vorhanden ist? Was würde dann ein Add auslösen? Wird der Benutzer dann 2x in der Liste geführt? Und wenn ja, wäre das schlimm?
3. Ich müsste nämlich auch noch dafür sorgen, dass, wenn ich eine Aufgabe lösche, der Benutzer wieder aus der Projekt-Nodereference-Liste rausgenommen wird. Das darf aber nur dann der Fall sein, wenn es keine weiteren Aufgaben zu dem Projekt gibt, in denen der Benuterz refereziert wurde.
Für diesen Fall dachte ich, gibt es u.U. 2 Lösungen:
a) Wenn beim Zufügen der Benutzer mehrfach hinzugefügt werden kann, so müsste ich ihn beim Entfernen der Aufgabe genau 1x wieder entfernen
b) Ich müsste über php prüfen, ob in dem Inhaltstyp Aufgabe eine weitere Aufgabe die nodereference auf das gleiche Projekt UND die userreference auf den gleichen User enthält.
Wer kann mir hier Denkanstöße geben?
Viele Grüße
Kai
- Anmelden oder Registrieren um Kommentare zu schreiben
Re: Daten in Listenfeld eines referenzierten ...
am 14.09.2009 - 10:59 Uhr
1. Wie muss man ein nodereference Feld per php ansprechen, damit man einen neuen Eintrag hinzufügen kann?
<?php
$new_nid = 15;
$found = false;
foreach ($node->field_project_members as $item) {
if ($item['nid'] == $new_nid) {
$found = true;
break;
}
}
if (!$found) {
$node->field_project_members[] = array('nid' => 15);
}
?>
Also, die bestehende Liste an ref. Benutzern bleibt erhalten, und der neue wird zugefügt.
Ach so, du meinst ein User Reference Feld. Dann ersetze
nid
durchuid
.2. Was passiert wenn der Benutzer schon vorhanden ist?
Keine Ahnung. Wird aber in obigem Code getestet.
3. Ich müsste nämlich auch noch dafür sorgen, dass, wenn ich eine Aufgabe lösche, der Benutzer wieder aus der Projekt-Nodereference-Liste rausgenommen wird. Das darf aber nur dann der Fall sein, wenn es keine weiteren Aufgaben zu dem Projekt gibt, in denen der Benuterz refereziert wurde.
<?php
$uid_old = 15;
$has_tasks = false;
$sql = "
SELECT n.nid
FROM {node} AS n
INNER JOIN {content_type_task} AS c ON n.vid = c.vid
WHERE c.field_assigned_to_uid = %d
";
$result = db_query($sql, $uid_old);
while ($record = db_fetch_array($result)) {
if ($record['nid'] != $node->nid) {
$has_tasks = true;
break;
}
}
if (!$has_tasks) {
$node_project = node_load($node->field_project[0]['nid']);
foreach (array_keys($node_project->field_project_members) as $key) {
if ($node_project->field_project_members[$key]['uid'] == $uid_old) {
unset($node_project->field_project_members[$key]);
break;
}
}
node_save($node_project);
}
?>
Tabellen- und Feldnamen mnüssen an deine Gegebenheiten angepasst werden. Außerdem geht im zweiten Teil die erste SQL-Abfrage kaputt wenn du das Feld in mehr als einem Inhaltstyp verwendest oder eine Aufgabe an mehrere Benutzer gleichzeitig zuweisen kannst.
Ich finde deine Anforderungen etwas zu komplex als das ich es mit Rules umsetzen würde. Schreibe lieber ein Modul dafür.
--
Hallo traxer, das ist genial
am 14.09.2009 - 12:17 Uhr
Hallo traxer,
das ist genial - danke für deine ausführliche Anleitung.
Das mit dem eigenen Modul ist ja eine recht gute Idee - aber leider bin ich total unfähig zu programmieren ;-)
Deshalb der Umweg über das rules-Modul (mit dem ich leztlich das Rechtemanagement in den Griff kriegen möchte, also, wer darf was lesen).
Viele Grüße
Kai
Hallo, jetzt habe ich den
am 14.09.2009 - 13:01 Uhr
Hallo,
jetzt habe ich den Code mal ausprobiert.
Beim Zufügen eines Eintrags zu dem userreference-feld habe ich noch ein kleines Problem.
Also, ich lade das entsprechende Feld momentan über rules und gebe eine Regel zum Befüllen des Feldes im PHP-Bereich an.
Hier stand vorher drin:
<?php
return array( 0 => array('uid' => [angefragter_user:uid] ));
?>
Wobei angefragter_user:uid die ID des neuen Benutzers ist.
Bei diesem Vorgehen wurden dann aber bereits in diesem Feld vorhandene Benutzer gelöscht und als Ergebnis nur noch der neue Benutzer in das Feld geschrieben.
Auf Grundlage deiner schönen Anleitung habe ich nun versucht die rules-Einstellunge wie folgt zu ändern.
Also, ich lade erst den übergeordneten Projektknoten und sage rules dann als Aktion, dass er das Feld der Projektmitglieder füllen soll (heißt bei mir field_refusers).
Dann habe ich beim PHP der rules-Aktion den folgenden Code eingetragen:
<?php
$new_uid = [angefragter_user:uid];
$found = false;
foreach ($referenced_project->field_refusers as $item) {
if ($item['uid'] == $new_uid) {
$found = true;
break;
}
}
if (!$found) {
$referenced_project->field_refusers[] = array('uid' => [angefragter_user:uid]);
}
?>
Wie gesagt, das übergeordnete Projekt wird von rules geladen und als PHP-variable $referenced_project in rules zur Verfügung gestellt (ist die node ID, die zurückgeliefert wird).
So geht das leider nicht, da rules scheinbar um jeden Preis ein return array im PHP-Feld haben will.
Wie kann ich ihm sagen, dass er, statt an Position 0 die neue Benutzer-ID an das array anghängen soll?
Viele Grüße
Kai
Hmm, vielleicht bin ich der
am 14.09.2009 - 17:14 Uhr
Hmm, vielleicht bin ich der Lösung jetzt ja doch schon näher gekommen.
Also, ich habe gesehen, dass ich in rules als Aktion auch einen reinen php-code übergeben kann.
Nun dachte ich, ich könnte einfach über die bereits ermittelte projekt-ID (die nodeid des referenzierten Projektes) auf das Userreference-Feld zugreifen.
Leider führt der folgende code weder zu einem Fehler, noch wird das nodereference-feld angetastet:
<?php
$new_uid = [angefragter_user:uid];
$found = false;
foreach ($referenced_project->field_refusers as $item) {
if ($item['uid'] == $new_uid) {
$found = true;
break;
}
}
if (!$found) {
$referenced_project->field_refusers[] => array('uid' => $new_uid);
}
?>
Wie gesagt, $referenced_project wird vorher durch eine Aktion geladen (referenzierten Beitrag laden).
Was könnte hier falsch sein?
Viele Grüße
Kai
OK, also jetzt habe ich noch
am 14.09.2009 - 17:55 Uhr
OK, also jetzt habe ich noch was rausgefunden.
Ich habe mit drupal_set_message ein wenig den code nachvollzogen.
Es läuft eigentlich alles wie es sollte, das Feld field_refusers wird so wie oben gezeigt tatsächlich korrekt angesprochen ;-)
Auch springt er bei Bedarf in die letzt if-Abfrage (if (!$found)), aber hier scheint nun irgendwie der Hund begraben zu liegen, denn er fügt die neue Benutzer-ID nicht an das bezeichnete Feld-array an.
Es scheint also hier an
<?php
$referenced_project->field_refusers[] => array('uid' => $new_uid);
?>
zu liegen.
Kann es sein, dass rules so den Wert nicht speichern darf?
In den Kommentaren von rules steht:
Zu beachten ist, dass Variablen von der Referenz übergeben werden, daher können sie gändert werden. Wenn die Änderungen dauerhaft erfolgen sollen, können Regeln intelligent die Änderungen speichern, wenn der Datentyp der Variablen dies unterstützt. Um „intelligentes Speichern“ zu verwenden, muss ein Array zu speichernder Variablen zurückgegeben werden. Dadurch werden Variablen nur einmal gespeichert, selbst wenn sie mehrfach geändert werden. Um „intelligentes Speichern“ zu verwenden muss einfach ein Array zu speichernder Variablen zurückgegeben werden, z.B.
return array("node" => $node);