Forum markieren als gelesen, nicht neu
Eingetragen von Q-Base (339)
am 04.10.2006 - 09:53 Uhr in
am 04.10.2006 - 09:53 Uhr in
Hallo,
wie funktioniert das bei Drupal? Wenn ich mich einlogge, werden mir im Forum verschiedene Beiträge als 'neu' markiert, andere nicht. Jedoch habe ich ja nicht alle anderen Beiträge gelesen. Kann ich auch aktiv alle Foren als 'gelesen' markieren? Ich will das für meine Webseite wissen. Hier ist es zwar auch interessant, aber ich hätte gerne irgendwo ein Link/Button auf den ich klicken kann.
Ciao, Q
- Anmelden oder Registrieren um Kommentare zu schreiben
Eine Funktion, damit man
am 05.10.2006 - 07:11 Uhr
Eine Funktion, damit man alle neue Beiträge als gelesen markieren kann, gibt es meines Wissens nach nicht.
So eine habe ich heute auch gesucht, denn nach drei Wochen Urlaub ist hier eine Menge 'neu'.
Gruß, Frank
wie funktioniert denn das?
am 05.10.2006 - 08:04 Uhr
Hallo,
na gut. Ist dann ein Feature-Request. Weiß denn jemand, wie ermittelt wird, ob 'neu' angezeigt wird oder nicht? Die Zeichenkette 'neu' oder 'new' ist einfach zu kurz und zu allgemein, als dass man sie einfach im Quellcode suchen sollte. Letztlich ließe sich dann ja auch eine kurze Funktion in einem Block einbinden, wenn man weiß, wie es als 'alt' (nicht 'neu') markiert wird.
Ciao, Q
Ciao, Q
---
Running Gag der IT seit den 70er: "Machen wir eben mal schnell ...".
Allzu viele Möglichkeiten
am 05.10.2006 - 08:30 Uhr
Allzu viele Möglichkeiten gibt es nicht. Entweder du speicherst zu jeder Node, wer sie denn schon gelesen hat und wer nicht (das wäre wohl relativ aufwendig) oder du arbeitest mit den Timestamps, die eine Node sowieso hat, und jeder User merkt sich den Timestamp, bis zu dem er alle Artikel gelesen hat, sowie zusätzlich nur die Nodes, die zu diesem Timestamp zwar schon existierten, aber noch nicht gelesen wurden (oder andersrum die Nodes, die zwar neuer sind, aber trotzdem schon gelesen wurden) oder so ähnlich. Das ganze eventuell noch getrennt pro Unterforum (User merkt sich also pro Unterforum 1 Timestamp + ggf. Liste).
Falls das bei Drupal genauso funktioniert, müsste eine 'alle als gelesen markieren' Funktion trivial zu implementieren sein: man setzt einfach den Timestamp des Users auf die aktuelle Zeit und schon gelten alle Nodes als gelesen. Wenn es das ist, wäre es allerdings so lächerlich einfach, das es kaum denkbar ist, daß das noch niemand eingebaut haben soll...
D.h. entweder gibt es ein entsprechendes Modul auf Drupal.org dazu oder das System von Drupal zur Neu / Nicht Neu Unterscheidung ist aus irgend einem Grund komplizierter. Das könnte bei Drupal der Fall sein, weil es intern sowas wie Foren nicht gibt - Forenthemen, Artikel und alles andere sind einfach Nodes, d.h. wenn es keine forenspezifischen Timestamps wie oben gedacht gibt, muss man tatsächlich die Liste der Artikel im jeweiligen Unterforum durchgehen, und jeden einzelnen Artikel als gelesen setzen, damit nach dem 'als gelesen markieren' im Forum wirklich nur Forenthemen als gelesen markiert sind und nicht noch ganz andere Nodes auf der Seite.
Re: Allzu viele Möglichkeiten
am 05.10.2006 - 09:10 Uhr
... du speicherst zu jeder Node, wer sie denn schon gelesen ...
So ähnlich scheint es Drupal auch zu machen. Es gibt eine Tabelle {history}, in der User-ID, Node-ID und Timestamp gespeichert sind. Dann gibt es noch eine Funktion namens 'node_last_viewed' mit dem Parameter Node-ID.
Diese Funktion gibt 0 zurück, wenn es keine Zeile uid, nid, timestamp gibt, so den timestamp. Aufgerufen wird diese Funktion von einer anderen Funktion namens 'node_mark($nid, $timestamp)'. Diese gibt in Abhängigkeit des zurückgegebenen Timestamps entweder die Konstante MARK_READ, MARK_NEW oder MARK_UPDATE zurück.
anders erklärt (Kurzbeschreibung, Pseudosprache):
Ist User-ID mit Node-ID nicht in der Tabelle, so hat der User den Node noch nicht gelesen => 'neu'.
Ist timestampt(Node-ID) > now, so hat der User den Node noch nicht gelesen => 'neu'.
Lösungsansatz
Man müsste also die Timestamps in der Tabelle {history} des Nutzers mit der aktuellen $uid updaten. Wäre sicher nicht schlecht, wenn man das nur mit Nodes macht, die den Type (node.type) = 'forum' haben.
Das nur so auf die Schnelle, bei Comments muss ich noch nachschauen.
Ciao, Q
---
Update:
Die Funktion node_tag_new($nid) setzt in der Tabelle {history} für den aktuellen Nutzer den aktuellen Timestamp. Man könnte sich nun alle NIDs aus dem Forum besorgen und dann in einer Schleife die Funktion node_tag_new() aufrufen.
Ciao, Q
---
Running Gag der IT seit den 70er: "Machen wir eben mal schnell ...".
Bitte Lösung prüfen
am 05.10.2006 - 09:49 Uhr
Hallo,
also meine Lösung für dieses Problem sieht jetzt so aus. Ich füge in der Datei forum.module eine Funktion 'forum_mark_as_read()' hinzu.
<?php
function forum_mark_as_read() {
$result = db_query('SELECT nid FROM {node} WHERE type = \'forum\'');
while ($t = db_fetch_object($result)) {
node_tag_new($t->nid);
}
}
?>
Natürlich muss hook_menu() aktualisiert werden. Ich habe mich dazu entschlossen, die URI q=forum/mark zu nutzen.
<?php
...
$items[] = array('path' => 'forum/mark',
'title' => t('mark forums as read'),
'callback' => 'forum_mark_as_read',
'access' => user_access('access content'));
...
?>
Ich kann leider mit den anderen möglichen Arraywerten nichts anfangen und weiß nicht was sie tun. Ich meine sowas wie "'type' => MENU_NORMAL_ITEM" oder "'type' => MENU_SUGGESTED_ITEM".
Die Funktionalität, die ich erwarte: wenn jemand in einem Block oder woanders meine URI q=forum/mark aufruft, werden alle Foren als gelesen markiert und dann weitergeleitet auf q=forum.
Frage: Wie kann ich diese Weiterleitung in der Funktion forum_mark_as_read() realisieren?
Zweite noch wichtigere Frage: Ist das so OK? Ich weiß nicht, ob sich das so in Drupal integrieren wird.
Ciao, Q
Ciao, Q
---
Running Gag der IT seit den 70er: "Machen wir eben mal schnell ...".
Hey Q-Base, denke, das ist
am 05.10.2006 - 10:34 Uhr
Hey Q-Base,
denke, das ist ein ganz guter Ansatz. Sieht soweit auch funktional aus.
SQL-Queries sollten nach Definition in doppelte Anführungszeichen eingeschlossen sein, also hier
db_query("SELECT nid FROM {node} WHERE type = 'forum'")
.Klickt man auf den Link im Menu, bekommt man wahrscheinlich lediglich eine weiße Seite angezeigt - schöner wäre ein Redirect auf die Seite, von der man kam und ein Hinweis darauf, daß die Aktion ausgeführt wurde.
Die Funktion skaliert allerdings nicht besonders gut, denn du wählst alle Forenbeiträge, ohne zu prüfen, ob überhaupt eine neuer Kommentar dran hängt. Das bedeutet schon hier im Forum pro Klick auf den neuen Menueintrag mehr als 1500 SQL-Abfragen über die Funktion node_tag_new [1].
Das scheint mir etwas heftig, stell Dir ein großes/älteres Forum mit mehr als 10000 oder gar 100000 Einträgen vor ?!
Also mein Vorschlag wäre, erst zu prüfen, wo was neu ist, anhand dessen entscheiden, was als kürzlich gelesen mariert werden soll.
vg
[1] http://api.drupal.org/api/4.7/function/node_tag_new
--
sanduhrs - drupalcenter
--------------------------------
http://erdfisch.de
--
sanduhrs · Stefan Auditor · Drupalcenter
http://drupal.org/user/28074 · http://association.drupal.org/user/646
schon klar
am 05.10.2006 - 11:00 Uhr
Hallo,
das mit der weißen Seite war mir schon klar. Daher die Frage
Frage: Wie kann ich diese Weiterleitung in der Funktion forum_mark_as_read() realisieren?
Bisher programmiere ich auch nur Funktionen in Drupal. Mit echten Seiten, die sich jemand anschaut, habe ich noch nichts gemacht. Daher schreibe ich viele Buttons immer in Blöcke, dann muss ich mich nicht um Theming etc kümmern.
Das mit den SQL-Abfragen verstehe ich. Die Frage ist nun nur, was mehr Aufwand macht, mehrere kleinere Abfragen (so wie jetzt) oder eine Monsterabfrage. Wobei der Monsterabfrage dann nur noch inkrementelle Abfragen folgen, denn das Forum markiert sich (hoffentlich) nicht alle Nase lange als 'neu'.
Ich denke mal über eine bessere SQL-Abfrage für die NIDs nach.
Ein zweiter Ansatz wäre es ...
Ich habe mich nicht seit Anbeginn von Drupalcenter.org angemeldet und habe sicher auch nicht alle Foren gelesen, trotzdem werden mit im Forum 'Allgemeines zu Drupal' von den insgesamt 670 Themen nur 56 als 'neu' angezeigt. Warum? Was ist also mit den Themen, die schon vor meiner Anmeldung da waren? Falls es noch eine Prüfung eines Anmeldedatums gibt, wäre es vielleicht hilfreich, man würde dieses Datum ändern. Also nicht unbedingt das Anmeldedatum, irgendwie eine Kopie oder ein ähnliches Datum davon. Das würde aber bedeuten, dass man nicht nur in einer Drupal-Funktion eine Änderung schreibt.
Das sind so die beiden einfachen Wege, die mir auf Anhieb einfallen. Gibt sicherlich noch einen Weg mit einer LEFT AND RIGHT JOIN-with-TEMPORARY TABLE-SQL-Monsterabfrage. ;-)
Ciao, Q
Ciao, Q
---
Running Gag der IT seit den 70er: "Machen wir eben mal schnell ...".
Also, eine SQL-Abfrage mit
am 05.10.2006 - 12:05 Uhr
Also, eine SQL-Abfrage mit einem kleinen JOIN (das hat nichts mit Monster zu tun, sondern heisst lediglich, dass mehrere Tabellen verwendet werden sollen), die 100000 Datensätze prüft und eine kleine Menge Datensätze zurückgibt, ist mit Sicherheit performanter - denn dafür ist eine Datenbank da -, als eine Abfrage, die 100000 Datensätze zurückgibt (PHP memory_limit Problem) und 100000 Einzelabfragen durchführt (Performance Problem), für die für jede Abfrage eine Dantebankverbindung hergestellt werden muss (Performance Problem).
Schon bei 1500 SQL-Abfragen, wie es hier im Forum wäre, kriegst Du bei jedem Shared-Hosting-Anbieter eine Fehlermeldung aufgrund zu vieler Datenbank-Verbindungen - das ist so schon häufig ein Problem.
Ich würde tatsächlich beim ersten Ansatz bleiben und versuchen, mit einer LEFT AND/OR RIGHT JOIN-WITHOUT-TEMPORARY TABLE-SQL-Monsterabfrage ein keleines zu Modul erstellen, das diese Funktionalität dann anbietet.
--
sanduhrs - drupalcenter
--------------------------------
http://erdfisch.de
--
sanduhrs · Stefan Auditor · Drupalcenter
http://drupal.org/user/28074 · http://association.drupal.org/user/646
Im node.module gibts es
am 05.10.2006 - 14:46 Uhr
Im node.module gibts es übrigens eine Konstante:
define('NODE_NEW_LIMIT', time() - 30 * 24 * 60 * 60);
Ich nehme an, dass damit definiert wird wie alt nodes höchstens sein dürfen, um als neu markiert werden zu können.
Hier gibts eine Thread zum Thema auf Drupal.org [1]
vg
[1] http://drupal.org/node/63416
--
sanduhrs - drupalcenter
--------------------------------
http://erdfisch.de
--
sanduhrs · Stefan Auditor · Drupalcenter
http://drupal.org/user/28074 · http://association.drupal.org/user/646
Danke
am 06.10.2006 - 01:41 Uhr
Super Tipp. Ich arbeite dran, aber ich kämpfe mit SQL, um die Abfrage wie in dem Artikel mittels Replace zu tun und somit nur eine Abfrage abzusetzen.
Ciao, Q
Ciao, Q
---
Running Gag der IT seit den 70er: "Machen wir eben mal schnell ...".
Nochmal dieses Thema
am 30.10.2006 - 17:22 Uhr
Hallo,
ich habe nochmal dieses Thema auf dem Tisch. Ich habe nun folgendes Code-Schnipsel entwickelt.
<?php
$forum_nodes = db_query("SELECT n.nid FROM {node} AS n, {comments} AS c WHERE n.type='forum' AND n.nid=c.nid AND c.timestamp>".(time() - NODE_NEW_LIMIT ).";");
while ($forum = db_fetch_object($forum_nodes)) {
node_tag_new($forum->nid);
}
?>
Ziel: alle Forenbeiträge, samt deren Kommentare als gelesen markieren.
1) Ist das so OK?
2) Wie kann ich das jetzt so einbinden, dass ich bei jedem Forum so ein Link steht und genau dieses Forum dann als gelesen markiert ist?
Wenn also die Übersicht aller Foren zu sehen ist (q=forum/0), dann müssen halt alle markiert werden.
Ciao, Q
Ciao, Q
---
Running Gag der IT seit den 70er: "Machen wir eben mal schnell ...".
Dein SQL-Statement
am 31.10.2006 - 17:37 Uhr
Dein SQL-Statement funktioniert für mich nicht.
Es ist auch nirgends an eine Benutzer-ID gebunden.
Nach einigem Nachdenken, bin ich auf folgendes gekommen:
Neue Foren-Nodes und Foren-Nodes mit neuen Kommentaren für einen bestimmten Taxonomy-Term und Benutzer:
<?php
/* Get new forum nodes */
global $user;
$term = 4;
$sql = "SELECT DISTINCT(n.nid) FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid AND tn.tid = %d LEFT JOIN {comments} c ON n.nid = c.nid LEFT JOIN {history} h ON n.nid = h.nid AND h.uid = %d WHERE (n.status = 1 AND n.type = 'forum' AND n.created > %d AND h.nid IS NULL) OR (h.timestamp < c.timestamp AND c.status='%s')";
$forum_nodes = db_queryd($sql, $term, $user->uid, NODE_NEW_LIMIT, COMMENT_PUBLISHED);
while ($forum = db_fetch_object($forum_nodes)) {
node_tag_new($forum->nid);
}
?>
Alle neue Foren-Nodes und Foren-Nodes mit neuen Kommentaren für einen bestimmten Benutzer:
<?php
/* Get new forum nodes */
global $user;
$sql = "SELECT DISTINCT(n.nid) FROM {node} n LEFT JOIN {comments} c ON n.nid = c.nid LEFT JOIN {history} h ON n.nid = h.nid AND h.uid = %d WHERE (n.status = 1 AND n.type = 'forum' AND n.created > %d AND h.nid IS NULL) OR (h.timestamp < c.timestamp AND c.status='%s')";
$forum_nodes = db_queryd($sql, $user->uid, NODE_NEW_LIMIT, COMMENT_PUBLISHED);
while ($forum = db_fetch_object($forum_nodes)) {
node_tag_new($forum->nid);
}
?>
Versuch das mal und sag mir, ob es bei Dir funktioniert.
Ein echter SQL-Guru kann das sicherlich besser, aber in meinen Tests hat es bisher einwandfrei funktioniert.
Bitte um Rückmeldung.
--
sanduhrs - drupalcenter
--------------------------------
http://erdfisch.de
--
sanduhrs · Stefan Auditor · Drupalcenter
http://drupal.org/user/28074 · http://association.drupal.org/user/646
Gut, hier ein schnelles
am 31.10.2006 - 19:56 Uhr
Gut, hier ein schnelles Modul:
<?php
// $Id$
/**
* @file
* Allow users to mark all new forum nodes as read.
*/
/**
* Implementation of hook_help().
*/
function forum_mark_read_help($section) {
switch ($section) {
case 'admin/help#forum_mark_read':
return t('Allow users to mark all new forum nodes as read.');
case 'admin/modules#description':
return t('Allow users to mark all new forum nodes as read.');
}
}
/**
* Implementation of hook_menu().
*/
function forum_mark_read_menu($may_cache) {
$items = array();
$tid = is_numeric(arg(1)) ? arg(1) : 0;
if ($may_cache) {
} else {
$items[] = array('path' => 'forum/'.$tid.'/markasread',
'title' => t('mark all content read'),
'callback' => '_forum_mark_read_markasread',
'access' => user_access('access content'),
'type' => MENU_NORMAL_ITEM,
'callback arguments' => array($tid),
);
}
return $items;
}
function _forum_mark_read_markasread($tid = '') {
global $user;
if ($tid == 0) {
// Select all new forum nodes and nodes with new comments
$sql = "SELECT DISTINCT(n.nid) FROM {node} n LEFT JOIN {comments} c ON n.nid = c.nid LEFT JOIN {history} h ON n.nid = h.nid AND h.uid = %d WHERE (n.status = 1 AND n.type = 'forum' AND n.created > %d AND h.nid IS NULL) OR (h.timestamp < c.timestamp AND c.status='%s')";
$result = db_query($sql, $user->uid, NODE_NEW_LIMIT, COMMENT_PUBLISHED);
while ($node = db_fetch_object($result)) {
// Mark the node as read
node_tag_new($node->nid);
}
// Tell the user what we did
drupal_set_message(t('All new nodes in all forums were marked as read.'));
// Redirect to where we came from
drupal_goto('forum');
} else if (is_numeric($tid)) {
// Select all new forum nodes and nodes with new comments from term $tid
$sql = "SELECT DISTINCT(n.nid) FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid AND tn.tid = %d LEFT JOIN {comments} c ON n.nid = c.nid LEFT JOIN {history} h ON n.nid = h.nid AND h.uid = %d WHERE (n.status = 1 AND n.type = 'forum' AND n.created > %d AND h.nid IS NULL) OR (h.timestamp < c.timestamp AND c.status='%s')";
$result = db_queryd($sql, $tid, $user->uid, NODE_NEW_LIMIT, COMMENT_PUBLISHED);
while ($node = db_fetch_object($result)) {
node_tag_new($node->nid);
}
// Tell the user what we did
drupal_set_message(t('All new nodes in this forum were marked as read.'));
// Redirect to where we came from
drupal_goto('forum/'.$tid);
}
}
?>
--
sanduhrs - drupalcenter
--------------------------------
http://erdfisch.de
--
sanduhrs · Stefan Auditor · Drupalcenter
http://drupal.org/user/28074 · http://association.drupal.org/user/646
leider nein
am 01.11.2006 - 17:40 Uhr
Hallo,
das war ja gut gemeint, aber nachdem das Modul aktiviert hatte, bekam ich nur noch blank-Seiten. Nichts, nichtmal 'ne Fehlermeldung. Das kann aber auch sein, dass hier Debian sicherheitshalber dazwischen funkt. Und deshalb keine Ausgabe kommt.
Dein SQL sieht doch nicht so schlimm aus.
Ciao, Q
Ciao, Q
---
Running Gag der IT seit den 70er: "Machen wir eben mal schnell ...".
Ist Dein Arbeotsspeicher
am 01.11.2006 - 17:50 Uhr
Ist Dein memory_limit vielleicht ausgereizt?
vg
--
sanduhrs - drupalcenter
--------------------------------
http://erdfisch.de
--
sanduhrs · Stefan Auditor · Drupalcenter
http://drupal.org/user/28074 · http://association.drupal.org/user/646
Vielen Dank
am 04.11.2006 - 16:28 Uhr
Das funktioniert super, ich werde es noch ein bissle anpassen, weil ich das gerne anders hätte.
Das memory_limit für PHP war OK, aber ich musste 'outputbuffer' einschalten. Das war noch nicht aktiv.
Ciao, Q
---
Running Gag der IT seit den 70er: "Machen wir eben mal schnell ...".
Was wirst Du noch
am 06.11.2006 - 11:03 Uhr
Was wirst Du noch anpassen?
--
sanduhrs - drupalcenter
--------------------------------
http://erdfisch.de
--
sanduhrs · Stefan Auditor · Drupalcenter
http://drupal.org/user/28074 · http://association.drupal.org/user/646
Meine Vorstellung war es,
am 06.11.2006 - 11:47 Uhr
Meine Vorstellung war es, dass bei der Forenübersicht unter dem dritten Punkt 'Neues Thema erstellen' ein 'mark as read' vorhanden ist.
Deine Realisierung springt auch bei Nodes außerhalb des Forums an und markiert dann aber die Foren-Nodes.
Ich möchte also irgendwie herausbekommen, wie ich auf die Seiten 'q=forum' einen Punkt hinzufüge ggf. passe ich das forum.module an und kopiere meine Anpassungen bei jedem Update.
So hatte ich mir das vorgestellt :)
Ciao, Q
---
Running Gag der IT seit den 70er: "Machen wir eben mal schnell ...".
Gib mir bitte bescheid, wenn
am 06.11.2006 - 12:51 Uhr
Gib mir bitte bescheid, wenn Du das geschafft hast.
Das wäre auch meine Lieblingslösung gewesen, diese Links sind allerdings nicht über das Menusystem erreichbar und auch nicht über eine enzelne Themeable-Function.
Bin gespannt.
vg
--
sanduhrs - drupalcenter
--------------------------------
http://erdfisch.de
--
sanduhrs · Stefan Auditor · Drupalcenter
http://drupal.org/user/28074 · http://association.drupal.org/user/646