diff options
author | Dries Buytaert <dries@buytaert.net> | 2001-07-11 22:06:24 +0000 |
---|---|---|
committer | Dries Buytaert <dries@buytaert.net> | 2001-07-11 22:06:24 +0000 |
commit | d6d60de3ccac7b26ed3a14498279c8f16cdcefe7 (patch) | |
tree | d50339aa8c59aa34edb34c257fd854223024390c | |
parent | ee12d11165f867e8442d5e12e6325f0c4f2e6d0d (diff) | |
download | brdo-d6d60de3ccac7b26ed3a14498279c8f16cdcefe7.tar.gz brdo-d6d60de3ccac7b26ed3a14498279c8f16cdcefe7.tar.bz2 |
- Added blog.module to replace diary.module (contrubeted by Julian):
+ feedback wanted
- Added updated import.module (contributed by Julian):
+ user page do browse the headlines by feed and bundle, to display
the item descriptions, etc.
- Fixed small bug in common.inc.
- Updated database.mysql
-rw-r--r-- | database/database.mysql | 27 | ||||
-rw-r--r-- | includes/common.inc | 2 | ||||
-rw-r--r-- | misc/blog.gif | bin | 0 -> 930 bytes | |||
-rw-r--r-- | misc/earth.gif | bin | 0 -> 888 bytes | |||
-rw-r--r-- | misc/xml.gif | bin | 0 -> 429 bytes | |||
-rw-r--r-- | modules/aggregator.module | 320 | ||||
-rw-r--r-- | modules/aggregator/aggregator.module | 320 | ||||
-rw-r--r-- | modules/blog.module | 404 | ||||
-rw-r--r-- | modules/blog/blog.module | 404 | ||||
-rw-r--r-- | modules/diary.module | 362 | ||||
-rw-r--r-- | modules/import.module | 320 | ||||
-rw-r--r-- | updates/2.00-to-x.xx.sql | 8 |
12 files changed, 1679 insertions, 488 deletions
diff --git a/database/database.mysql b/database/database.mysql index 404eb587f..ba13a912d 100644 --- a/database/database.mysql +++ b/database/database.mysql @@ -18,6 +18,13 @@ CREATE TABLE blocks ( PRIMARY KEY (name) ); +CREATE TABLE blog ( + lid int(10) unsigned DEFAULT '0' NOT NULL auto_increment, + nid int(10) unsigned DEFAULT '0' NOT NULL, + body text NOT NULL, + PRIMARY KEY (lid) +); + CREATE TABLE book ( lid int(10) unsigned DEFAULT '0' NOT NULL auto_increment, nid int(10) unsigned DEFAULT '0' NOT NULL, @@ -84,6 +91,20 @@ CREATE TABLE channel ( PRIMARY KEY (id) ); +CREATE TABLE chatevents ( + id int(11) DEFAULT '0' NOT NULL auto_increment, + body varchar(255) DEFAULT '' NOT NULL, + timestamp int(11) DEFAULT '0' NOT NULL, + PRIMARY KEY (id) +); + +CREATE TABLE chatmembers ( + id int(11) DEFAULT '0' NOT NULL auto_increment, + nick varchar(32) DEFAULT '' NOT NULL, + timestamp int(11) DEFAULT '0' NOT NULL, + PRIMARY KEY (id) +); + CREATE TABLE collection ( cid int(10) unsigned DEFAULT '0' NOT NULL auto_increment, name varchar(32) DEFAULT '' NOT NULL, @@ -144,13 +165,15 @@ CREATE TABLE entry ( CREATE TABLE feed ( fid int(11) DEFAULT '0' NOT NULL auto_increment, title varchar(255) DEFAULT '' NOT NULL, - link varchar(255) DEFAULT '' NOT NULL, + url varchar(255) DEFAULT '' NOT NULL, refresh int(11), uncache int(11), timestamp int(11), attributes varchar(255) DEFAULT '' NOT NULL, + link varchar(255) DEFAULT '' NOT NULL, + description text NOT NULL, UNIQUE title (title), - UNIQUE link (link), + UNIQUE link (url), PRIMARY KEY (fid) ); diff --git a/includes/common.inc b/includes/common.inc index 1bb337280..8eca80048 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -172,7 +172,7 @@ function format_email($address) { return ($address) ? "<a href=\"mailto:$address\">$address</A>" : message_na(); } -function format_url($address, $description = "") { +function format_url($address, $description = 0) { $description = ($description) ? $description : $address; return ($address) ? "<a href=\"$address\">". check_output($description) ."</a>" : message_na(); } diff --git a/misc/blog.gif b/misc/blog.gif Binary files differnew file mode 100644 index 000000000..1547cbad0 --- /dev/null +++ b/misc/blog.gif diff --git a/misc/earth.gif b/misc/earth.gif Binary files differnew file mode 100644 index 000000000..3cf5a1212 --- /dev/null +++ b/misc/earth.gif diff --git a/misc/xml.gif b/misc/xml.gif Binary files differnew file mode 100644 index 000000000..ecb095754 --- /dev/null +++ b/misc/xml.gif diff --git a/modules/aggregator.module b/modules/aggregator.module index a80994e8c..11e25fdc4 100644 --- a/modules/aggregator.module +++ b/modules/aggregator.module @@ -11,69 +11,153 @@ function import_help() { <?php } +function import_conf_options() { + $number = array(5 => 5, 10 => 10, 15 => 15, 20 => 20, 25 => 25, 30 => 30, 35 => 35, 40 => 40, 45 => 45, 50 => 50, 55 => 55, 60 => 60, 65 => 65, 70 => 70, 75 => 75, 80 => 80, 85 => 85, 90 => 90, 95 => 95, 100 => 100); + $output .= form_select("Items per block", "import_block_limit", variable_get("import_block_limit", 15), $number, "The maximum number of items displayed in one block."); + $output .= form_select("Items per page", "import_page_limit", variable_get("import_page_limit", 75), $number, "The maximum number of items displayed on one page."); + return $output; +} + function import_perm() { - return array("administer syndication"); + return array("administer news feeds", "access news feeds"); } function import_link($type) { - if ($type == "admin") { - $links[] = "<a href=\"admin.php?mod=import\">syndication</a>"; + if ($type == "admin" && user_access("administer news feeds")) { + $links[] = "<a href=\"admin.php?mod=import\">news feeds</a>"; + } + + if ($type == "menu" && user_access("administer news feeds")) { + $links[] = "<a href=\"module.php?mod=import&op=update\">". t("update all news") ."</a>"; + } + + if ($type == "page" && user_access("access news feeds")) { + $links[] = "<a href=\"module.php?mod=import\">". t("latest news") ."</a>"; } return $links ? $links : array(); } function import_cron() { + $result = db_query("SELECT * FROM feed WHERE timestamp + refresh < ". time()); + while ($feed = db_fetch_array($result)) { + import_refresh($feed); + } +} + +function import_update() { $result = db_query("SELECT * FROM feed"); while ($feed = db_fetch_array($result)) { - // remove expired items: - db_query("DELETE FROM item WHERE fid = '$feed[fid]' AND timestamp < ". (time() - $feed[uncache])); + import_refresh($feed); + } +} + +function import_format_item($item, $feed = 0, $description = 0) { + if (module_hook("blog", "page")) { + $output .= "<a href=\"submit.php?mod=blog&type=import&id=$item->iid\"><img src=\"misc/blog.gif\" border=\"0\" width=\"12\" height=\"16\" alt=\"" . t("Blog this item") . "\" /></a> "; + } + + if ($feed != 1) { + $output .= "<a href=\"module.php?mod=import&op=feed&id=$item->fid\"><img src=\"misc/earth.gif\" border= \"0\" width=\"11\" height=\"11\" alt=\"". t("All headlines from this feed") ."\" /></a> "; + } + + $output .= "<a href=\"". check_output($item->link) ."\" target=\"new\">". check_output($item->title) ."</a>"; - // update feeds: - if ($feed[timestamp] + $feed[refresh] < time()) import_update($feed); + if ($description && ($feed != 1)) { + $output .= " <small>". format_url($item->flink, $item->ftitle) ."</small>"; } + + if ($description) { + $output .= "<br />". check_output($item->description) ."<br />\n"; + } + + return $output ."<br />"; } -function import_bundle($attributes, $limit = 100) { +function import_bundle_block($attributes) { + if ($attributes) { - // compose query: $keys = explode(",", $attributes); foreach ($keys as $key) $where[] = "attributes LIKE '%". trim($key) ."%'"; - $result = db_query("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY iid DESC LIMIT $limit"); + $result = db_query("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY iid DESC LIMIT ". variable_get("import_block_limit", 15)); while ($item = db_fetch_object($result)) { - $output .= "<li><a href=\"". check_output($item->link) ."\">". check_output($item->title) ."</a></li>"; + $output .= import_format_item($item, 0); } - return "$output"; + return $output; } } -function import_view_bundle() { - $result = db_query("SELECT * FROM bundle ORDER BY title"); - while ($bundle = db_fetch_object($result)) { - $output .= "<b>$bundle->title</b><ul>". import_bundle($bundle->attributes) ."</ul>"; - } - return $output; -} +function import_feed_block($feed) { + $result = db_query("SELECT * FROM item WHERE fid = '$feed->fid' ORDER BY iid DESC LIMIT ". variable_get("import_block_limit", 15)); -function import_view_feed() { - $result = db_query("SELECT * FROM feed ORDER BY title"); - while ($feed = db_fetch_object($result)) { - $output .= "<b>$feed->title</b>". ($feed->link ? " (". format_url($feed->link) .")" : "") ."<ul>". check_output($feed->description) ."</ul>"; + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 1); } + + $output .= "<br />". t("Last update:") ." ". format_interval(time() - $feed->timestamp) ." ". t("ago"); + return $output; } function import_block() { + return import_block_bundle(); +} + +function import_block_bundle($attributes = 0) { + + if ($attributes) { + $keys = explode(",", $attributes); + foreach ($keys as $key) $where[] = "attributes LIKE '%". trim($key) ."%'"; + $result = db_query("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY iid DESC LIMIT ". variable_get("import_block_limit", 15)); + } + else { + $result = db_query("SELECT * FROM item ORDER BY iid DESC LIMIT ". variable_get("import_block_limit", 15)); + } + + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 0); + } + + $blocks[0][subject] = format_url("module.php?mod=import", t("Latest news")); + $blocks[0][content] = $output; + $blocks[0][info] = t("Latest news"); + $result = db_query("SELECT * FROM bundle ORDER BY title"); + while ($bundle = db_fetch_object($result)) { $i++; - $blocks[$i][subject] = $bundle->title; - $blocks[$i][content] = import_bundle($bundle->attributes, 10); + + $blocks[$i][subject] = format_url("module.php?mod=import&op=bundle&id=$bundle->bid", $bundle->title); + $blocks[$i][content] = import_bundle_block($bundle->attributes); $blocks[$i][info] = "$bundle->title bundle"; } + + return $blocks; +} + +function import_block_feed($attributes = 0) { + + if ($attributes) { + $keys = explode(",", $attributes); + foreach ($keys as $key) $where[] = "attributes LIKE '%". trim($key) ."%'"; + $result = db_query("SELECT * FROM feed WHERE ". implode(" OR ", $where) ." ORDER BY fid LIMIT ". variable_get("import_block_limit", 15)); + } + else { + $result = db_query("SELECT * FROM feed ORDER BY fid LIMIT ". variable_get("import_block_limit", 15)); + } + + $i = 0; + while ($feed = db_fetch_object($result)) { + $blocks[$i][subject] = format_url("module.php?mod=import&op=feed&id=$feed->fid", $feed->title); + $blocks[$i][content] = import_feed_block($feed); + $blocks[$i][info] = "$feed->title feed"; + + $i++; + } + return $blocks; } @@ -82,7 +166,7 @@ function import_remove($feed) { return "feed '$feed[title]' reset."; } -function import_update($feed) { +function import_refresh($feed) { // open socket: $url = parse_url($feed[url]); @@ -90,16 +174,21 @@ function import_update($feed) { if ($fp) { // fetch data: - fputs($fp, "GET $url[path]?$url[query] HTTP/1.0\nUser-Agent: ". variable_get(site_name, "drupal") ."\nHost: $url[host]\nAccept: */*\n\n"); + fputs($fp, "GET $url[path]?$url[query] HTTP/1.0\nUser-Agent: ". variable_get("site_name", "drupal") ."\nHost: $url[host]\nAccept: */*\n\n"); + + while (!feof($fp)) $data .= fgets($fp, 128); // initialize the translation table: $tt = array_flip(get_html_translation_table(HTML_ENTITIES)); $tt["'"] = "'"; - while(!feof($fp)) $data .= fgets($fp, 128); - if (strstr($data, "200 OK")) { - + /* + ** Remove expired items: + */ + + db_query("DELETE FROM item WHERE fid = '$feed[fid]' AND timestamp < ". (time() - $feed[uncache])); + /* ** Extract and process channel information: */ @@ -118,6 +207,8 @@ function import_update($feed) { eregi("<item([^s].*)</item>", $data, $data); + // print "<PRE>". htmlentities($data[0]) ."</PRE>"; + $items = array_reverse(explode("</item>", $data[0])); foreach ($items as $item) { @@ -134,7 +225,7 @@ function import_update($feed) { } } else { - watchdog("error", "import: failed to syndicate from '$feed[title]'"); + watchdog("error", "failed to syndicate from '$feed[title]'"); } } @@ -148,7 +239,7 @@ function import_save_item($edit) { else if ($edit[iid]) { db_query("DELETE FROM item WHERE iid = '". check_input($edit[iid]) ."'"); } - else { + else if ($edit[title] && $edit[link]) { if (!db_fetch_object(db_query("SELECT iid FROM item WHERE link = '". check_input($edit[link]) ."'"))) { db_query("INSERT INTO item (fid, title, link, author, description, attributes, timestamp) VALUES ('". check_input($edit[fid]) ."', '". check_input($edit[title]) ."', '". check_input($edit[link]) ."', '". check_input($edit[author]) ."', '". check_input($edit[description]) ."', '". check_input($edit[attributes]) ."', '". time() ."')"); } @@ -178,7 +269,7 @@ function import_save_bundle($edit) { else if ($edit[bid]) { db_query("DELETE FROM bundle WHERE bid = '". check_input($edit[bid]) ."'"); } - else { + else if ($edit[title]) { db_query("INSERT INTO bundle (title, attributes) VALUES ('". check_input($edit[title]) ."', '". check_input($edit[attributes]) ."')"); } @@ -190,8 +281,11 @@ function import_form_feed($edit = array()) { $period = array(900 => format_interval(900), 1800 => format_interval(1800), 3600 => format_interval(3600), 7200 => format_interval(7200), 10800 => format_interval(10800), 21600 => format_interval(21600), 32400 => format_interval(32400), 43200 => format_interval(43200), 64800 => format_interval(64800), 86400 => format_interval(86400), 172800 => format_interval(172800), 259200 => format_interval(259200), 604800 => format_interval(604800), 1209600 => format_interval(1209600), 2419200 => format_interval(2419200)); + if ($edit[refresh]== "") $edit[refresh] = 3600; + if ($edit[uncache]== "") $edit[uncache] = 2419200; + $form .= form_textfield("Title", "title", $edit[title], 50, 64, "The name of the feed; typically the name of the website you syndicate content from."); - $form .= form_textfield("URL", "url", $edit[url], 50, 128, "The fully-qualified URL of the feed."); + $form .= form_textfield("Url", "url", $edit[url], 50, 128, "The fully-qualified URL of the feed."); $form .= form_textfield("Attributes", "attributes", $edit[attributes], 50, 128, "A comma-seperated list of keywords describing the feed."); $form .= form_select("Update interval", "refresh", $edit[refresh], $period, "The refresh interval indicating how often you want to update this feed. Requires crontab."); $form .= form_select("Expiration time", "uncache", $edit[uncache], $period, "The time cached items should be kept. Older items will be automatically discarded. Requires crontab."); @@ -215,7 +309,7 @@ function import_save_feed($edit) { db_query("DELETE FROM feed WHERE fid = '". check_input($edit[fid]) ."'"); db_query("DELETE FROM item WHERE fid = '". check_input($edit[fid]) ."'"); } - else { + else if ($edit[title]) { db_query("INSERT INTO feed (title, url, attributes, refresh, uncache) VALUES ('". check_input($edit[title]) ."', '". check_input($edit[url]) ."', '". check_input($edit[attributes]) ."', '". check_input($edit[refresh]) ."', '". check_input($edit[uncache]) ."')"); } } @@ -240,7 +334,7 @@ function import_view() { $output .= "<h3>Feed overview</h3>"; $output .= "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n"; - $output .= " <tr><th>site</th><th>attributes</th><th>items</th><th>last update</th><th>next update</th><th colspan=\"3\">operations</th></tr>\n"; + $output .= " <tr><th>title</th><th>attributes</th><th>items</th><th>last update</th><th>next update</th><th colspan=\"3\">operations</th></tr>\n"; while ($feed = db_fetch_object($result)) { $output .= " <tr><td>". check_output($feed->title) ."</td><td>". check_output($feed->attributes) ."</td><td>". format_plural($feed->items, "item", "items") ."</td><td>". ($feed->timestamp ? format_interval(time() - $feed->timestamp) ." ago" : "never") ."</td><td>". ($feed->timestamp ? format_interval($feed->timestamp + $feed->refresh - time()) ." left" : "never") ."</td><td><a href=\"admin.php?mod=import&type=feed&op=edit&id=$feed->fid\">edit feed</a></td><td><a href=\"admin.php?mod=import&type=feed&op=remove&id=$feed->fid\">remove items</a></td><td><a href=\"admin.php?mod=import&type=feed&op=update&id=$feed->fid\">update items</a></td></tr>\n"; } @@ -259,6 +353,22 @@ function import_view() { return $output; } +function import_view_feed() { + $result = db_query("SELECT * FROM feed ORDER BY title"); + while ($feed = db_fetch_object($result)) { + $output .= "<b>$feed->title</b>". ($feed->link ? " (". format_url($feed->link) .")" : "") ."<ul>". check_output($feed->description) ."</ul>"; + } + return $output; +} + +function import_view_bundle() { + $result = db_query("SELECT * FROM bundle ORDER BY title"); + while ($bundle = db_fetch_object($result)) { + $output .= "<b>$bundle->title</b><ul>". import_bundle_block($bundle->attributes) ."</ul>"; + } + return $output; +} + function import_view_item() { global $REQUEST_URI; @@ -268,7 +378,7 @@ function import_view_item() { $output .= "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n"; $output .= " <tr><th>time</th><th>feed</th><th>item</th></tr>\n"; while ($item = db_fetch_object($result)) { - $output .= " <tr><td valign=\"top\" nowrap=\"nowrap\">". format_date($item->timestamp, "custom", "m/d/y") ."<br />".format_date($item->timestamp, "custom", "H:i") ."</td><td align=\"center\" valign=\"top\" nowrap=\"nowrap\"><a href=\"admin.php?mod=import&type=feed&op=edit&id=$item->fid\">". check_output($item->feed) ."</a></td><td><a href=\"". check_output($item->link) ."\">". check_output($item->title) ."</a>". ($item->description ? "<br /><small><i>". check_output($item->description) ."</i></small>" : "") ."<br /><input type=\"text\" name=\"edit[$item->iid]\" value=\"". check_form($item->attributes) ."\" size=\"50\" /></td></tr>\n"; + $output .= " <tr><td valign=\"top\" nowrap=\"nowrap\">". format_date($item->timestamp, "custom", "m/d/y") ."<br />".format_date($item->timestamp, "custom", "H:i") ."</td><td align=\"center\" valign=\"top\" nowrap=\"nowrap\"><a href=\"admin.php?mod=import&type=feed&op=edit&id=$item->fid\">". check_output($item->feed) ."</a></td><td><a href=\"". check_output($item->url) ."\">". check_output($item->title) ."</a>". ($item->description ? "<br /><small><i>". check_output($item->description) ."</i></small>" : "") ."<br /><input type=\"text\" name=\"edit[$item->iid]\" value=\"". check_form($item->attributes) ."\" size=\"50\" /></td></tr>\n"; } $output .= "</table>\n"; $output .= "<input type=\"submit\" name=\"op\" value=\"Save attributes\" />\n"; @@ -280,7 +390,7 @@ function import_view_item() { function import_admin() { global $op, $id, $type, $edit; - if (user_access("administer syndication")) { + if (user_access("administer news feeds")) { print "<small><a href=\"admin.php?mod=import&type=feed&op=add\">add new feed</a> | <a href=\"admin.php?mod=import&type=bundle&op=add\">add new bundle</a> | <a href=\"admin.php?mod=import&type=feed&op=view\">available feeds</a> | <a href=\"admin.php?mod=import&type=bundle&op=view\">available bundles</a> | <a href=\"admin.php?mod=import&type=item&op=view\">available items</a> | <a href=\"admin.php?mod=import&op=view\">overview</a> | <a href=\"admin.php?mod=import&op=help\">help</a></small><hr />"; @@ -302,11 +412,11 @@ function import_admin() { break; case "remove": print status(import_remove(import_get_feed($id))); - print import_view_feed(); + print import_view(); break; case "update": - print status(import_update(import_get_feed($id))); - print import_view_feed(); + print status(import_refresh(import_get_feed($id))); + print import_view(); break; case "Save attributes": print status(import_save_attributes($edit)); @@ -337,4 +447,132 @@ function import_admin() { } } +function import_page_all() { + global $theme; + + $result = db_query("SELECT i.*, f.title AS ftitle, f.link AS flink FROM item i LEFT JOIN feed f ON i.fid = f.fid ORDER BY i.iid DESC LIMIT ". variable_get("import_page_limit", 75)); + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 0, 1); + } + + $header = t("Latest news for all bundles") ." (<a href=\"module.php?mod=import&op=bundles\">by bundle</A>) (<a href=\"module.php?mod=import&op=feeds\">by feed</a>) "; + + $theme->header(); + $theme->box($header, $output); + $theme->footer(); +} + +function import_page_feed($fid) { + global $theme; + + $result = db_query("SELECT * FROM feed WHERE fid = '". check_input($fid) ."'"); + $feed = db_fetch_object($result); + + $header .= "<a href=\"$feed->url\"><img src=\"misc/xml.gif\" width=\"36\" height=\"14\" align=\"right\" border=\"0\" /></a>"; + $header .= $feed->title . " <a href=\"$feed->link\" target=\"new\"><img src=\"misc/earth.gif\" border= \"0\" width=\"11\" height=\"11\" alt=\"". t("View site") ."\" /></a>"; + + $result = db_query("SELECT * FROM item WHERE fid = '". check_input($fid) ."' ORDER BY iid DESC LIMIT ". variable_get("import_page_limit", 75)); + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 1, 1); + } + + $output .= t("Last update:") ." ". format_interval(time() - $feed->timestamp) ." ". t("ago"); + + $theme->header(); + $theme->box($header, $output); + $theme->footer(); +} + +function import_page_bundle($bid) { + global $theme; + + $bundle = db_fetch_object(db_query("SELECT * FROM bundle where bid = '". check_input($bid) ."'")); + $header = $bundle->title ." ". t("bundle") ." (<a href=\"module.php?mod=import&op=bundlefeeds&id=$bid\">". t("by feed") ."</a>)"; + + $keys = explode(",", $bundle->attributes); + foreach ($keys as $key) $where[] = "i.attributes LIKE '%". trim($key) ."%'"; + $result = db_query("SELECT i.*, f.title AS ftitle, f.link AS flink FROM item i, feed f WHERE (". implode(" OR ", $where) .") AND i.fid = f.fid ORDER BY iid DESC LIMIT ". variable_get("import_page_limit", 75)); + + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 0, 1); + } + + $theme->header(); + $theme->box($header, $output); + $theme->footer(); +} + +function import_page_bundles() { + import_page_blocks(import_block_bundle()); +} + +function import_page_feeds() { + import_page_blocks(import_block_feed()); +} + +function import_page_bundle_feeds($bid) { + $bundle = db_fetch_object(db_query("SELECT * FROM bundle WHERE bid = '". check_input($bid) ."'")); + import_page_blocks(import_block_feed($bundle->attributes)); +} + +function import_page_blocks($blocks) { + global $theme; + + $count = count($blocks); + $items = ceil($count / 3); + $c1 = min($items, $count); + $c2 = min(2 * $items, $count); + $c3 = $count; + $i = 0; + + $theme->header(); + print "<table cellpadding=\"0\" cellspacing=\"5\" border=\"0\" width=\"100%\">\n"; + print " <tr>\n"; + print " <td width=\"33%\" valign=\"top\">\n"; + for ($i; $i < $c1; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]); + print " </td>\n"; + print " <td width=\"33%\" valign=\"top\">\n"; + for ($i; $i < $c2; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]); + print " </td>\n"; + print " <td width=\"33%\" valign=\"top\">\n"; + for ($i; $i < $c3; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]); + print " </td>\n"; + print " </tr>\n"; + print "</table>\n"; + $theme->footer(); +} + +function import_page() { + global $op, $id; + + if (user_access("access news feeds")) { + switch($op) { + case "all": + import_page_all(); + break; + case "feed": + import_page_feed($id); + break; + case "bundle": + import_page_bundle($id); + break; + case "bundlefeeds": + import_page_bundle_feeds($id); + break; + case "bundles": + import_page_bundles(); + break; + case "feeds": + import_page_feeds(); + break; + case "update": + import_update(); + import_page_all(); + break; + default: + import_page_all(); + } + } +} + ?> diff --git a/modules/aggregator/aggregator.module b/modules/aggregator/aggregator.module index a80994e8c..11e25fdc4 100644 --- a/modules/aggregator/aggregator.module +++ b/modules/aggregator/aggregator.module @@ -11,69 +11,153 @@ function import_help() { <?php } +function import_conf_options() { + $number = array(5 => 5, 10 => 10, 15 => 15, 20 => 20, 25 => 25, 30 => 30, 35 => 35, 40 => 40, 45 => 45, 50 => 50, 55 => 55, 60 => 60, 65 => 65, 70 => 70, 75 => 75, 80 => 80, 85 => 85, 90 => 90, 95 => 95, 100 => 100); + $output .= form_select("Items per block", "import_block_limit", variable_get("import_block_limit", 15), $number, "The maximum number of items displayed in one block."); + $output .= form_select("Items per page", "import_page_limit", variable_get("import_page_limit", 75), $number, "The maximum number of items displayed on one page."); + return $output; +} + function import_perm() { - return array("administer syndication"); + return array("administer news feeds", "access news feeds"); } function import_link($type) { - if ($type == "admin") { - $links[] = "<a href=\"admin.php?mod=import\">syndication</a>"; + if ($type == "admin" && user_access("administer news feeds")) { + $links[] = "<a href=\"admin.php?mod=import\">news feeds</a>"; + } + + if ($type == "menu" && user_access("administer news feeds")) { + $links[] = "<a href=\"module.php?mod=import&op=update\">". t("update all news") ."</a>"; + } + + if ($type == "page" && user_access("access news feeds")) { + $links[] = "<a href=\"module.php?mod=import\">". t("latest news") ."</a>"; } return $links ? $links : array(); } function import_cron() { + $result = db_query("SELECT * FROM feed WHERE timestamp + refresh < ". time()); + while ($feed = db_fetch_array($result)) { + import_refresh($feed); + } +} + +function import_update() { $result = db_query("SELECT * FROM feed"); while ($feed = db_fetch_array($result)) { - // remove expired items: - db_query("DELETE FROM item WHERE fid = '$feed[fid]' AND timestamp < ". (time() - $feed[uncache])); + import_refresh($feed); + } +} + +function import_format_item($item, $feed = 0, $description = 0) { + if (module_hook("blog", "page")) { + $output .= "<a href=\"submit.php?mod=blog&type=import&id=$item->iid\"><img src=\"misc/blog.gif\" border=\"0\" width=\"12\" height=\"16\" alt=\"" . t("Blog this item") . "\" /></a> "; + } + + if ($feed != 1) { + $output .= "<a href=\"module.php?mod=import&op=feed&id=$item->fid\"><img src=\"misc/earth.gif\" border= \"0\" width=\"11\" height=\"11\" alt=\"". t("All headlines from this feed") ."\" /></a> "; + } + + $output .= "<a href=\"". check_output($item->link) ."\" target=\"new\">". check_output($item->title) ."</a>"; - // update feeds: - if ($feed[timestamp] + $feed[refresh] < time()) import_update($feed); + if ($description && ($feed != 1)) { + $output .= " <small>". format_url($item->flink, $item->ftitle) ."</small>"; } + + if ($description) { + $output .= "<br />". check_output($item->description) ."<br />\n"; + } + + return $output ."<br />"; } -function import_bundle($attributes, $limit = 100) { +function import_bundle_block($attributes) { + if ($attributes) { - // compose query: $keys = explode(",", $attributes); foreach ($keys as $key) $where[] = "attributes LIKE '%". trim($key) ."%'"; - $result = db_query("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY iid DESC LIMIT $limit"); + $result = db_query("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY iid DESC LIMIT ". variable_get("import_block_limit", 15)); while ($item = db_fetch_object($result)) { - $output .= "<li><a href=\"". check_output($item->link) ."\">". check_output($item->title) ."</a></li>"; + $output .= import_format_item($item, 0); } - return "$output"; + return $output; } } -function import_view_bundle() { - $result = db_query("SELECT * FROM bundle ORDER BY title"); - while ($bundle = db_fetch_object($result)) { - $output .= "<b>$bundle->title</b><ul>". import_bundle($bundle->attributes) ."</ul>"; - } - return $output; -} +function import_feed_block($feed) { + $result = db_query("SELECT * FROM item WHERE fid = '$feed->fid' ORDER BY iid DESC LIMIT ". variable_get("import_block_limit", 15)); -function import_view_feed() { - $result = db_query("SELECT * FROM feed ORDER BY title"); - while ($feed = db_fetch_object($result)) { - $output .= "<b>$feed->title</b>". ($feed->link ? " (". format_url($feed->link) .")" : "") ."<ul>". check_output($feed->description) ."</ul>"; + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 1); } + + $output .= "<br />". t("Last update:") ." ". format_interval(time() - $feed->timestamp) ." ". t("ago"); + return $output; } function import_block() { + return import_block_bundle(); +} + +function import_block_bundle($attributes = 0) { + + if ($attributes) { + $keys = explode(",", $attributes); + foreach ($keys as $key) $where[] = "attributes LIKE '%". trim($key) ."%'"; + $result = db_query("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY iid DESC LIMIT ". variable_get("import_block_limit", 15)); + } + else { + $result = db_query("SELECT * FROM item ORDER BY iid DESC LIMIT ". variable_get("import_block_limit", 15)); + } + + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 0); + } + + $blocks[0][subject] = format_url("module.php?mod=import", t("Latest news")); + $blocks[0][content] = $output; + $blocks[0][info] = t("Latest news"); + $result = db_query("SELECT * FROM bundle ORDER BY title"); + while ($bundle = db_fetch_object($result)) { $i++; - $blocks[$i][subject] = $bundle->title; - $blocks[$i][content] = import_bundle($bundle->attributes, 10); + + $blocks[$i][subject] = format_url("module.php?mod=import&op=bundle&id=$bundle->bid", $bundle->title); + $blocks[$i][content] = import_bundle_block($bundle->attributes); $blocks[$i][info] = "$bundle->title bundle"; } + + return $blocks; +} + +function import_block_feed($attributes = 0) { + + if ($attributes) { + $keys = explode(",", $attributes); + foreach ($keys as $key) $where[] = "attributes LIKE '%". trim($key) ."%'"; + $result = db_query("SELECT * FROM feed WHERE ". implode(" OR ", $where) ." ORDER BY fid LIMIT ". variable_get("import_block_limit", 15)); + } + else { + $result = db_query("SELECT * FROM feed ORDER BY fid LIMIT ". variable_get("import_block_limit", 15)); + } + + $i = 0; + while ($feed = db_fetch_object($result)) { + $blocks[$i][subject] = format_url("module.php?mod=import&op=feed&id=$feed->fid", $feed->title); + $blocks[$i][content] = import_feed_block($feed); + $blocks[$i][info] = "$feed->title feed"; + + $i++; + } + return $blocks; } @@ -82,7 +166,7 @@ function import_remove($feed) { return "feed '$feed[title]' reset."; } -function import_update($feed) { +function import_refresh($feed) { // open socket: $url = parse_url($feed[url]); @@ -90,16 +174,21 @@ function import_update($feed) { if ($fp) { // fetch data: - fputs($fp, "GET $url[path]?$url[query] HTTP/1.0\nUser-Agent: ". variable_get(site_name, "drupal") ."\nHost: $url[host]\nAccept: */*\n\n"); + fputs($fp, "GET $url[path]?$url[query] HTTP/1.0\nUser-Agent: ". variable_get("site_name", "drupal") ."\nHost: $url[host]\nAccept: */*\n\n"); + + while (!feof($fp)) $data .= fgets($fp, 128); // initialize the translation table: $tt = array_flip(get_html_translation_table(HTML_ENTITIES)); $tt["'"] = "'"; - while(!feof($fp)) $data .= fgets($fp, 128); - if (strstr($data, "200 OK")) { - + /* + ** Remove expired items: + */ + + db_query("DELETE FROM item WHERE fid = '$feed[fid]' AND timestamp < ". (time() - $feed[uncache])); + /* ** Extract and process channel information: */ @@ -118,6 +207,8 @@ function import_update($feed) { eregi("<item([^s].*)</item>", $data, $data); + // print "<PRE>". htmlentities($data[0]) ."</PRE>"; + $items = array_reverse(explode("</item>", $data[0])); foreach ($items as $item) { @@ -134,7 +225,7 @@ function import_update($feed) { } } else { - watchdog("error", "import: failed to syndicate from '$feed[title]'"); + watchdog("error", "failed to syndicate from '$feed[title]'"); } } @@ -148,7 +239,7 @@ function import_save_item($edit) { else if ($edit[iid]) { db_query("DELETE FROM item WHERE iid = '". check_input($edit[iid]) ."'"); } - else { + else if ($edit[title] && $edit[link]) { if (!db_fetch_object(db_query("SELECT iid FROM item WHERE link = '". check_input($edit[link]) ."'"))) { db_query("INSERT INTO item (fid, title, link, author, description, attributes, timestamp) VALUES ('". check_input($edit[fid]) ."', '". check_input($edit[title]) ."', '". check_input($edit[link]) ."', '". check_input($edit[author]) ."', '". check_input($edit[description]) ."', '". check_input($edit[attributes]) ."', '". time() ."')"); } @@ -178,7 +269,7 @@ function import_save_bundle($edit) { else if ($edit[bid]) { db_query("DELETE FROM bundle WHERE bid = '". check_input($edit[bid]) ."'"); } - else { + else if ($edit[title]) { db_query("INSERT INTO bundle (title, attributes) VALUES ('". check_input($edit[title]) ."', '". check_input($edit[attributes]) ."')"); } @@ -190,8 +281,11 @@ function import_form_feed($edit = array()) { $period = array(900 => format_interval(900), 1800 => format_interval(1800), 3600 => format_interval(3600), 7200 => format_interval(7200), 10800 => format_interval(10800), 21600 => format_interval(21600), 32400 => format_interval(32400), 43200 => format_interval(43200), 64800 => format_interval(64800), 86400 => format_interval(86400), 172800 => format_interval(172800), 259200 => format_interval(259200), 604800 => format_interval(604800), 1209600 => format_interval(1209600), 2419200 => format_interval(2419200)); + if ($edit[refresh]== "") $edit[refresh] = 3600; + if ($edit[uncache]== "") $edit[uncache] = 2419200; + $form .= form_textfield("Title", "title", $edit[title], 50, 64, "The name of the feed; typically the name of the website you syndicate content from."); - $form .= form_textfield("URL", "url", $edit[url], 50, 128, "The fully-qualified URL of the feed."); + $form .= form_textfield("Url", "url", $edit[url], 50, 128, "The fully-qualified URL of the feed."); $form .= form_textfield("Attributes", "attributes", $edit[attributes], 50, 128, "A comma-seperated list of keywords describing the feed."); $form .= form_select("Update interval", "refresh", $edit[refresh], $period, "The refresh interval indicating how often you want to update this feed. Requires crontab."); $form .= form_select("Expiration time", "uncache", $edit[uncache], $period, "The time cached items should be kept. Older items will be automatically discarded. Requires crontab."); @@ -215,7 +309,7 @@ function import_save_feed($edit) { db_query("DELETE FROM feed WHERE fid = '". check_input($edit[fid]) ."'"); db_query("DELETE FROM item WHERE fid = '". check_input($edit[fid]) ."'"); } - else { + else if ($edit[title]) { db_query("INSERT INTO feed (title, url, attributes, refresh, uncache) VALUES ('". check_input($edit[title]) ."', '". check_input($edit[url]) ."', '". check_input($edit[attributes]) ."', '". check_input($edit[refresh]) ."', '". check_input($edit[uncache]) ."')"); } } @@ -240,7 +334,7 @@ function import_view() { $output .= "<h3>Feed overview</h3>"; $output .= "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n"; - $output .= " <tr><th>site</th><th>attributes</th><th>items</th><th>last update</th><th>next update</th><th colspan=\"3\">operations</th></tr>\n"; + $output .= " <tr><th>title</th><th>attributes</th><th>items</th><th>last update</th><th>next update</th><th colspan=\"3\">operations</th></tr>\n"; while ($feed = db_fetch_object($result)) { $output .= " <tr><td>". check_output($feed->title) ."</td><td>". check_output($feed->attributes) ."</td><td>". format_plural($feed->items, "item", "items") ."</td><td>". ($feed->timestamp ? format_interval(time() - $feed->timestamp) ." ago" : "never") ."</td><td>". ($feed->timestamp ? format_interval($feed->timestamp + $feed->refresh - time()) ." left" : "never") ."</td><td><a href=\"admin.php?mod=import&type=feed&op=edit&id=$feed->fid\">edit feed</a></td><td><a href=\"admin.php?mod=import&type=feed&op=remove&id=$feed->fid\">remove items</a></td><td><a href=\"admin.php?mod=import&type=feed&op=update&id=$feed->fid\">update items</a></td></tr>\n"; } @@ -259,6 +353,22 @@ function import_view() { return $output; } +function import_view_feed() { + $result = db_query("SELECT * FROM feed ORDER BY title"); + while ($feed = db_fetch_object($result)) { + $output .= "<b>$feed->title</b>". ($feed->link ? " (". format_url($feed->link) .")" : "") ."<ul>". check_output($feed->description) ."</ul>"; + } + return $output; +} + +function import_view_bundle() { + $result = db_query("SELECT * FROM bundle ORDER BY title"); + while ($bundle = db_fetch_object($result)) { + $output .= "<b>$bundle->title</b><ul>". import_bundle_block($bundle->attributes) ."</ul>"; + } + return $output; +} + function import_view_item() { global $REQUEST_URI; @@ -268,7 +378,7 @@ function import_view_item() { $output .= "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n"; $output .= " <tr><th>time</th><th>feed</th><th>item</th></tr>\n"; while ($item = db_fetch_object($result)) { - $output .= " <tr><td valign=\"top\" nowrap=\"nowrap\">". format_date($item->timestamp, "custom", "m/d/y") ."<br />".format_date($item->timestamp, "custom", "H:i") ."</td><td align=\"center\" valign=\"top\" nowrap=\"nowrap\"><a href=\"admin.php?mod=import&type=feed&op=edit&id=$item->fid\">". check_output($item->feed) ."</a></td><td><a href=\"". check_output($item->link) ."\">". check_output($item->title) ."</a>". ($item->description ? "<br /><small><i>". check_output($item->description) ."</i></small>" : "") ."<br /><input type=\"text\" name=\"edit[$item->iid]\" value=\"". check_form($item->attributes) ."\" size=\"50\" /></td></tr>\n"; + $output .= " <tr><td valign=\"top\" nowrap=\"nowrap\">". format_date($item->timestamp, "custom", "m/d/y") ."<br />".format_date($item->timestamp, "custom", "H:i") ."</td><td align=\"center\" valign=\"top\" nowrap=\"nowrap\"><a href=\"admin.php?mod=import&type=feed&op=edit&id=$item->fid\">". check_output($item->feed) ."</a></td><td><a href=\"". check_output($item->url) ."\">". check_output($item->title) ."</a>". ($item->description ? "<br /><small><i>". check_output($item->description) ."</i></small>" : "") ."<br /><input type=\"text\" name=\"edit[$item->iid]\" value=\"". check_form($item->attributes) ."\" size=\"50\" /></td></tr>\n"; } $output .= "</table>\n"; $output .= "<input type=\"submit\" name=\"op\" value=\"Save attributes\" />\n"; @@ -280,7 +390,7 @@ function import_view_item() { function import_admin() { global $op, $id, $type, $edit; - if (user_access("administer syndication")) { + if (user_access("administer news feeds")) { print "<small><a href=\"admin.php?mod=import&type=feed&op=add\">add new feed</a> | <a href=\"admin.php?mod=import&type=bundle&op=add\">add new bundle</a> | <a href=\"admin.php?mod=import&type=feed&op=view\">available feeds</a> | <a href=\"admin.php?mod=import&type=bundle&op=view\">available bundles</a> | <a href=\"admin.php?mod=import&type=item&op=view\">available items</a> | <a href=\"admin.php?mod=import&op=view\">overview</a> | <a href=\"admin.php?mod=import&op=help\">help</a></small><hr />"; @@ -302,11 +412,11 @@ function import_admin() { break; case "remove": print status(import_remove(import_get_feed($id))); - print import_view_feed(); + print import_view(); break; case "update": - print status(import_update(import_get_feed($id))); - print import_view_feed(); + print status(import_refresh(import_get_feed($id))); + print import_view(); break; case "Save attributes": print status(import_save_attributes($edit)); @@ -337,4 +447,132 @@ function import_admin() { } } +function import_page_all() { + global $theme; + + $result = db_query("SELECT i.*, f.title AS ftitle, f.link AS flink FROM item i LEFT JOIN feed f ON i.fid = f.fid ORDER BY i.iid DESC LIMIT ". variable_get("import_page_limit", 75)); + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 0, 1); + } + + $header = t("Latest news for all bundles") ." (<a href=\"module.php?mod=import&op=bundles\">by bundle</A>) (<a href=\"module.php?mod=import&op=feeds\">by feed</a>) "; + + $theme->header(); + $theme->box($header, $output); + $theme->footer(); +} + +function import_page_feed($fid) { + global $theme; + + $result = db_query("SELECT * FROM feed WHERE fid = '". check_input($fid) ."'"); + $feed = db_fetch_object($result); + + $header .= "<a href=\"$feed->url\"><img src=\"misc/xml.gif\" width=\"36\" height=\"14\" align=\"right\" border=\"0\" /></a>"; + $header .= $feed->title . " <a href=\"$feed->link\" target=\"new\"><img src=\"misc/earth.gif\" border= \"0\" width=\"11\" height=\"11\" alt=\"". t("View site") ."\" /></a>"; + + $result = db_query("SELECT * FROM item WHERE fid = '". check_input($fid) ."' ORDER BY iid DESC LIMIT ". variable_get("import_page_limit", 75)); + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 1, 1); + } + + $output .= t("Last update:") ." ". format_interval(time() - $feed->timestamp) ." ". t("ago"); + + $theme->header(); + $theme->box($header, $output); + $theme->footer(); +} + +function import_page_bundle($bid) { + global $theme; + + $bundle = db_fetch_object(db_query("SELECT * FROM bundle where bid = '". check_input($bid) ."'")); + $header = $bundle->title ." ". t("bundle") ." (<a href=\"module.php?mod=import&op=bundlefeeds&id=$bid\">". t("by feed") ."</a>)"; + + $keys = explode(",", $bundle->attributes); + foreach ($keys as $key) $where[] = "i.attributes LIKE '%". trim($key) ."%'"; + $result = db_query("SELECT i.*, f.title AS ftitle, f.link AS flink FROM item i, feed f WHERE (". implode(" OR ", $where) .") AND i.fid = f.fid ORDER BY iid DESC LIMIT ". variable_get("import_page_limit", 75)); + + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 0, 1); + } + + $theme->header(); + $theme->box($header, $output); + $theme->footer(); +} + +function import_page_bundles() { + import_page_blocks(import_block_bundle()); +} + +function import_page_feeds() { + import_page_blocks(import_block_feed()); +} + +function import_page_bundle_feeds($bid) { + $bundle = db_fetch_object(db_query("SELECT * FROM bundle WHERE bid = '". check_input($bid) ."'")); + import_page_blocks(import_block_feed($bundle->attributes)); +} + +function import_page_blocks($blocks) { + global $theme; + + $count = count($blocks); + $items = ceil($count / 3); + $c1 = min($items, $count); + $c2 = min(2 * $items, $count); + $c3 = $count; + $i = 0; + + $theme->header(); + print "<table cellpadding=\"0\" cellspacing=\"5\" border=\"0\" width=\"100%\">\n"; + print " <tr>\n"; + print " <td width=\"33%\" valign=\"top\">\n"; + for ($i; $i < $c1; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]); + print " </td>\n"; + print " <td width=\"33%\" valign=\"top\">\n"; + for ($i; $i < $c2; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]); + print " </td>\n"; + print " <td width=\"33%\" valign=\"top\">\n"; + for ($i; $i < $c3; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]); + print " </td>\n"; + print " </tr>\n"; + print "</table>\n"; + $theme->footer(); +} + +function import_page() { + global $op, $id; + + if (user_access("access news feeds")) { + switch($op) { + case "all": + import_page_all(); + break; + case "feed": + import_page_feed($id); + break; + case "bundle": + import_page_bundle($id); + break; + case "bundlefeeds": + import_page_bundle_feeds($id); + break; + case "bundles": + import_page_bundles(); + break; + case "feeds": + import_page_feeds(); + break; + case "update": + import_update(); + import_page_all(); + break; + default: + import_page_all(); + } + } +} + ?> diff --git a/modules/blog.module b/modules/blog.module new file mode 100644 index 000000000..7a6f577ce --- /dev/null +++ b/modules/blog.module @@ -0,0 +1,404 @@ +<?php + +class Blog { + function Blog($blog) { + global $user; + + $this = new Node($blog); + $this->title = $blog[title]; + $this->body = $blog[body]; + $this->userid = $blog[userid] ? $blog[userid] : $user->userid; + $this->timestamp = $blog[timestamp]; + } +} + +function blog_help() { + ?> + <p>Drupal's blog module allows registered users to maintain an online blog or diary. It provides easy-to-write and easy-to-read online diaries or journals that can be filled with daily thoughts, poetry, boneless blabber, spiritual theories, intimate details, valuable experiences, cynical rants, semi-coherent comments, writing experiments, artistic babblings, critics on current facts, fresh insights, diverse dreams, chronicles and mumbling madness available for public consumption.</p> + <p>TODO</p>: + <p>Add an entry on the account display for another user, linked to module.php?mod=blog&name=$userid</p> + <p>Provide links on other "Noded" module displays to allow the node to be blogged module.php?mod=blog&type=blog&id=$nid . Currently these are available on blogs and import displays.</p> + <p>Combine the calendar display class with the node calendar display class.</p> + <?php +} + +function blog_perm() { + return array("administer blogs", "access blogs", "post blogs"); +} + +function blog_page_all($num = 20) { + global $theme, $user; + + $result = db_query("SELECT n.timestamp, n.title, u.userid, n.nid, b.body FROM blog b LEFT JOIN node n ON b.nid = n.nid LEFT JOIN users u ON n.author = u.id ORDER BY b.lid DESC LIMIT $num"); + + while ($blog = db_fetch_object($result)) { + $output .= "<a href=\"submit.php?mod=blog&type=blog&id=$blog->nid\"><img src=\"misc/blog.gif\" border=\"0\" width=\"12\" height=\"16\" alt=\"". t("Blog this item") ."\" /></a> <a href=\"module.php?mod=blog&name=". urlencode($blog->userid) ."\"><img src=\"misc/earth.gif\" border= \"0\" width=\"11\" height=\"11\" alt=\"". t("This blog") ."\" /></a> ". format_username($blog->userid) ." ". t("on") ." ". format_date($blog->timestamp) .":<br />"; + $output .= "<blockquote><b>". check_input($blog->title) ."</b><br />" . check_output($blog->body, 1) ."</blockquote>\n"; + } + + $theme->header(); + $theme->box(t("Latest blogs"), $output); + $theme->footer(); +} + +function blog_page_user($userid = 0, $date = 0) { + global $theme, $user; + + $userid = $userid ? $userid : $user->userid; + + $theme->header(); + + if ($date) { + + /* + ** Displays today's blogs for this user: + */ + + blog_page_day($userid, $date); + } + else { + + /* + ** Display the last blogs for this user: + */ + + $result = db_query("SELECT n.nid, n.timestamp FROM node n LEFT JOIN users u ON u.id = n.author WHERE u.userid = '". check_input($userid) ."' AND n.timestamp > ". (time() - 2592000) ." LIMIT 15"); + while ($blog = db_fetch_object($result)) { + if ($date != date("ndy", $blog->timestamp)) { + $date = date("ndy", $blog->timestamp); + blog_page_day($userid, $blog->timestamp); + } + } + } + + $theme->footer(); +} + + +function blog_page_day($userid = 0, $date = 0) { + global $theme, $user; + + $header .= "<table cellspacing=\"0\" cellpadding=\"0\" width=\"100%\">\n"; + $header .= " <tr>\n"; + $header .= " <td><b><a href=\"module.php?mod=blog&op=view&name=". urlencode($userid) ."\">". check_output($userid) ."'s ". t("blog") ."</a></b></td>\n"; + $header .= " <td align=\"right\"><b><a href=\"module.php?mod=blog&op=view&name=". urlencode($userid) ."&date=$date\">". format_date($date, custom, "d-M-Y") ."</a></b></td>\n"; + $header .= " </tr>\n"; + $header .= "</table>\n"; + + $sdate = mktime(0, 0, 0, date("m", $date), date("d", $date), date("Y", $date)); + $edate = mktime(23, 59, 59, date("m", $date), date("d", $date), date("Y", $date)); + + $result = db_query("SELECT b.body, n.timestamp, n.nid FROM blog b LEFT JOIN node n ON b.nid = n.nid LEFT JOIN users u ON n.author = u.id WHERE u.userid = '". check_input($userid) ."' AND n.timestamp > '$sdate' AND n.timestamp < '$edate' ORDER BY b.lid DESC LIMIT 50"); + + while ($blog = db_fetch_object($result)) { + if (!$first) $first = $blog->nid; + $output .= "<p><a href=\"submit.php?mod=blog&type=blog&id=$blog->nid\"><img src=\"misc/blog.gif\" border=\"0\" width=\"12\" height=\"16\" alt=\"". t("Blog this item") ."\"></a> ". check_output($blog->body, 1) ."</p>\n"; + } + + if ($userid == $user->userid) { + $output .= "<p>[ <a href=\"submit.php?mod=blog&op=edit&id=$first\">". t("edit") ."</a> ]</p>"; + } + + $theme->box($header, $output); +} + +function blog_status() { + return array(dumped, posted); +} + +function blog_remove($nid) { + global $status, $user; + + node_save(array(nid => $nid), array(status => $status[dumped])); + $blog = node_get_object(array(type => "blog", nid => "$nid")); + if ((user_access("administer blogs")) or ($blog->userid == $user->userid)) { + node_del(array(type => "blog", nid => $nid, lid => $blog->lid)); + } +} + +function blog_view($node) { + global $status, $theme; + + $userid = urlencode($node->userid); + + $header .= "<table cellspacing=\"0\" cellpadding=\"0\" width=\"100%\">\n"; + $header .= " <tr>\n"; + $header .= " <td><b><a href=\"module.php?mod=blog&op=view&name=$userid\">". $node->userid ."'s ". t("blog") ."</a></b></td>\n"; + $header .= " <td align=\"right\"><b><a href=\"module.php?mod=blog&op=view&name=$userid&date=$node->timestamp\">". format_date($node->timestamp, custom, "d-M-Y") ."</a></b></td>\n"; + $header .= " </tr>\n"; + $header .= "</table>\n"; + + $output .= "<p>". check_output($node->body, 1) ."</p>\n"; + $output .= "<p>[ ". implode(" | ", link_node($node)) ."]</p>\n"; + + $theme->box($header, $output); +} + +function blog_form($edit = array()) { + global $REQUEST_URI, $id, $type, $user, $theme; + + if ($edit[type] == "blog") { + } + else if ($type == "blog") { + $item = node_get_object(array(type => "blog", nid => $id)); + $edit["title"] = $item->title; + $edit["body"] = $item->body ." [<a href=\"module.php?mod=blog&name=". urlencode($item->userid) ."&date=$item->timestamp\">$item->userid</a>]"; + } + else if ($type == "import") { + $item = db_fetch_object(db_query("SELECT i.*, f.title as ftitle, f.link as flink FROM item i, feed f WHERE i.iid = '". check_input($id) ."' AND i.fid = f.fid")); + $edit["title"] = $item->title; + $edit["body"] = "<a href=\"$item->link\">$item->title</a> - ". check_output($item->description) ." [<a href=\"$item->flink\">$item->ftitle</a>]\n"; + } + + if ($edit[title]) { + $form .= blog_view(new Blog(node_preview($edit))); + } + + $form .= form_textfield(t("Subject"), "title", $edit["title"], 50, 64); + $form .= form_textarea(t("Body"), "body", $edit["body"], 70, 15, t("Allowed HTML tags") .": ". htmlspecialchars(variable_get("allowed_html", ""))); + + $form .= form_hidden("type", "blog"); + + if ($edit["nid"] > 0) { + $form .= form_hidden("nid", $edit["nid"]); + } + + if ($edit && !$edit["title"]) { + $form .= "<font color=\"red\">". t("Warning: you did not supply a subject.") ."</font><p>\n"; + $form .= form_submit(t("Preview")); + } + else if ($edit && !$edit["body"]) { + $form .= "<font color=\"red\">". t("Warning: you did not supply any text.") ."</font><p>\n"; + $form .= form_submit(t("Preview")); + } + else { + $form .= form_submit(t("Preview")); + $form .= form_submit(t("Submit")); + } + + $output .= form($REQUEST_URI, $form); + + return $output; +} + +function blog_save($edit) { + global $status, $user; + + if (!$edit["nid"]) { + node_save($edit, array(author => $user->id, body, status => variable_get("blog_status", $status[posted]), timestamp => time(), title, type => "blog")); + } + else if (user_access("administer blogs")) { + node_save($edit, array(attributes => node_attributes_save("blog", $edit), body, title, type => "blog")); + } +} + +function blog_edit_history($nid) { + global $user; + + // DB: changed this to 15 older blog entries rather than today's entries + // as there was no way to edit entries older than a day. The notion + // of a day can be quite annoying when bloging around midnight. All + // entries are accessible now. + // + // $blog = node_get_object(array(nid => $nid, type => "blog")); + // $sdate = mktime(0, 0, 0, date("m", $blog->timestamp), date("d", $blog->timestamp), date("Y", $blog->timestamp)); + // $edate = mktime(23, 59, 59, date("m", $blog->timestamp), date("d", $blog->timestamp), date("Y", $blog->timestamp)); + // $result = db_query("SELECT n.title, b.body, n.timestamp, n.nid FROM blog b LEFT JOIN node n ON b.nid = n.nid WHERE n.author = '$user->id' AND n.timestamp > '$sdate' AND n.timestamp < '$edate' ORDER BY b.lid DESC LIMIT 100"); + + $result = db_query("SELECT n.nid, n.title, n.timestamp, b.body FROM blog b LEFT JOIN node n ON b.nid = n.nid WHERE n.author = '". check_input($user->id) ."' AND n.nid < '". check_input($nid) ."' ORDER BY b.lid DESC LIMIT 15"); + + $output .= "<table cellpadding=\"3\" cellspacing=\"3\" border=\"0\" width=\"100%\">"; + while ($blog = db_fetch_object($result)) { + $output .= "<tr><td><b>". check_output($blog->title) ."</b><br />". check_output($blog->body, 1) ."</td><td><a href=\"submit.php?mod=blog&op=edit&id=$blog->nid\">". t("edit") ."</a></td><td><a href=\"submit.php?mod=blog&op=delete&id=$blog->nid\">". t("delete") ."</a></td></tr>\n"; + } + $output .= "</table>"; + + return $output; +} + +function blog_page() { + global $op, $name, $date; + + if (user_access("access blogs")) { + if ($name) { + blog_page_user($name, $date); + } + else { + blog_page_all(); + } + } +} + +function blog_user() { + global $op, $id, $name, $date, $edit, $theme, $user; + + if (user_access("post blogs")) { + switch ($op) { + case "delete": + blog_remove($id); + blog_page_day($user->userid, time()); + break; + case "edit": + $theme->box(t("Submit a blog"), blog_form(node_get_array(array("nid" => $id, "type" => "blog")))); + $theme->box(t("Older blogs"), blog_edit_history($id)); + break; + case t("Preview"): + $theme->box(t("Preview Blog"), blog_form($edit)); + break; + case t("Submit"): + blog_save($edit); + blog_page_day($user->userid, time()); + break; + default: + $theme->box(t("Submit a blog"), blog_form($edit)); + } + } +} + + +function blog_link($type) { + global $user; + + if ($type == "page" && user_access("access blogs")) { + $links[] = "<a href=\"module.php?mod=blog\">". t("latest blogs") ."</a>"; + } + + if ($type == "menu" && user_access("post blogs")) { + $links[] = "<a href=\"module.php?mod=blog&op=view&name=". urlencode($user->userid) ."\">". t("your blog") ."</a>"; + } + + return $links ? $links : array(); +} + + +function blog_block() { + global $name, $date, $user, $mod; + + $result = db_query("SELECT u.userid, n.timestamp, n.title, n.nid FROM node n LEFT JOIN users u ON n.author = u.id WHERE n.type = 'blog' ORDER BY n.nid DESC LIMIT 10"); + while ($node = db_fetch_object($result)) { + $output .= "<a href=\"module.php?mod=blog&op=view&name=". urlencode($node->userid) ."\">". check_output($node->title) ."<br />\n"; + } + + $block[0]["subject"] = "<a href=\"module.php?mod=blog\">". t("Latest blogs") ."</a>"; + $block[0]["content"] = $output; + $block[0]["info"] = t("Latest blogs"); + $block[0]["link"] = "module.php?mod=blog"; + + $date = $data ? $data : time(); + $userid = $name ? $name : $user->userid; + + if (($mod == "blog") || ($mod == "block")) { + // Only show this block on "blog pages" and in the admin block section. + $calendar = new BlogCalendar($userid, $date); + $block[1]["subject"] = "<a href=\"module.php?mod=blog&name=". urlencode($userid) ."\">" . t("Browse blog") . "</a>"; + $block[1]["content"] = $calendar->display(); + $block[1]["info"] = t("Calendar to browse blogs"); + } + + return $block; +} + + +function blog_search($keys) { + global $status, $user; + $result = db_query("SELECT n.*, b.* FROM blog b LEFT JOIN node n ON n.nid = b.nid AND n.lid = b.lid WHERE (n.title LIKE '%$keys%' OR b.body LIKE '%$keys%') ORDER BY n.timestamp DESC LIMIT 20"); + while ($blog = db_fetch_object($result)) { + $find[$i++] = array("title" => check_output($blog->title), "link" => (user_access("administer nodes") ? "admin.php?mod=node&type=blog&op=edit&id=$blog->nid" : "node.php?id=$blog->nid"), "user" => $blog->userid, "date" => $blog->timestamp); + } + return $find; +} + + +class BlogCalendar { + var $date; + var $userid; + + function BlogCalendar($userid, $date) { + $this->userid = urlencode($userid); + + // Prevent future dates: + $today = mktime(23, 59, 59, date("n", time()), date("d", time()), date("Y", time())); + $this->date = (($date && $date <= $today) ? $date : $today); + $this->date = mktime(23, 59, 59, date("n", $this->date), date("d", $this->date), date("Y", $this->date)); + } + + function display() { + // Extract information from the given date: + $month = date("n", $this->date); + $year = date("Y", $this->date); + $day = date("d", $this->date); + + // Extract today's date: + $today = mktime(23, 59, 59, date("n", time()), date("d", time()), date("Y", time())); + + // Extract the timestamp of the last day of today's month: + $thislast = mktime(23, 59, 59, date("n", time()), date("t", time()), date("Y", time())); + + // Extract first day of the month: + $first = date("w", mktime(0, 0, 0, $month, 1, $year)); + + // Extract last day of the month: + $last = date("t", mktime(0, 0, 0, $month, 1, $year)); + + // Calculate previous and next months dates and check for shorter months (28/30 days) + $prevmonth = mktime(23, 59, 59, $month - 1, 1, $year); + $prev = mktime(23, 59, 59, $month - 1, min(date("t", $prevmonth), $day), $year); + $nextmonth = mktime(23, 59, 59, $month + 1, 1, $year); + $next = mktime(23, 59, 59, $month + 1, min(date("t", $nextmonth), $day), $year); + + // Generate calendar header: + $output .= "\n<!-- calendar -->\n"; + $output .= "<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"1\">\n"; + $output .= " <TR><TD ALIGN=\"center\" COLSPAN=\"7\"><B><A HREF=\"module.php?mod=blog&name=$this->userid&date=$prev\" STYLE=\"text-decoration: none;\"><<</A> ". date("F Y", $this->date) ." " . ($next <= $thislast ? "<A HREF=\"module.php?mod=blog&name=$this->userid&date=$next\" STYLE=\"text-decoration: none;\">>></A>" : ">>") . "<B></TD></TR>\n"; + + // Generate the days of the week: + $output .= " <TR>"; + $somesunday = mktime(0, 0, 0, 3, 20, 1994); + for ($i = 0; $i < 7; $i++) { + $output .= "<TD ALIGN=\"center\">" . substr(ucfirst(t(date("l", $somesunday + $i * 86400))), 0, 1) . "</TD>"; + } + $output .= "</TR>\n"; + + // Initialize temporary variables: + $nday = 1; + $sday = $first; + + // Loop through all the days of the month: + while ($nday <= $last) { + // Set up blank days for first week of the month: + if ($first) { + $output .= " <TR><TD COLSPAN=\"$first\"> </TD>\n"; + $first = 0; + } + + // Start every week on a new line: + if ($sday == 0) $output .= " <TR>\n"; + + // Print one cell: + $date = mktime(23, 59, 59, $month, $nday, $year); + if ($date == $this->date) $output .= " <TD ALIGN=\"center\" BGCOLOR=\"#CCCCCC\"><B>$nday</B></TD>\n"; + else if ($date > $today) $output .= " <TD ALIGN=\"center\">$nday</TD>\n"; + else $output .= " <TD ALIGN=\"center\"><A HREF=\"module.php?mod=blog&name=$this->userid&date=$date\" STYLE=\"text-decoration: none;\">$nday</A></TD>\n"; + + // Start every week on a new line: + if ($sday == 6) $output .= " </TR>\n"; + + // Update temporary variables: + $sday++; + $sday = $sday % 7; + $nday++; + } + + // Complete the calendar: + if ($sday) { + $end = 7 - $sday; + $output .= " <TD COLSPAN=\"$end\"> </TD>\n </TR>\n"; + } + $output .= "</TABLE>\n\n"; + + // Return calendar: + return $output; + } +} + +?> diff --git a/modules/blog/blog.module b/modules/blog/blog.module new file mode 100644 index 000000000..7a6f577ce --- /dev/null +++ b/modules/blog/blog.module @@ -0,0 +1,404 @@ +<?php + +class Blog { + function Blog($blog) { + global $user; + + $this = new Node($blog); + $this->title = $blog[title]; + $this->body = $blog[body]; + $this->userid = $blog[userid] ? $blog[userid] : $user->userid; + $this->timestamp = $blog[timestamp]; + } +} + +function blog_help() { + ?> + <p>Drupal's blog module allows registered users to maintain an online blog or diary. It provides easy-to-write and easy-to-read online diaries or journals that can be filled with daily thoughts, poetry, boneless blabber, spiritual theories, intimate details, valuable experiences, cynical rants, semi-coherent comments, writing experiments, artistic babblings, critics on current facts, fresh insights, diverse dreams, chronicles and mumbling madness available for public consumption.</p> + <p>TODO</p>: + <p>Add an entry on the account display for another user, linked to module.php?mod=blog&name=$userid</p> + <p>Provide links on other "Noded" module displays to allow the node to be blogged module.php?mod=blog&type=blog&id=$nid . Currently these are available on blogs and import displays.</p> + <p>Combine the calendar display class with the node calendar display class.</p> + <?php +} + +function blog_perm() { + return array("administer blogs", "access blogs", "post blogs"); +} + +function blog_page_all($num = 20) { + global $theme, $user; + + $result = db_query("SELECT n.timestamp, n.title, u.userid, n.nid, b.body FROM blog b LEFT JOIN node n ON b.nid = n.nid LEFT JOIN users u ON n.author = u.id ORDER BY b.lid DESC LIMIT $num"); + + while ($blog = db_fetch_object($result)) { + $output .= "<a href=\"submit.php?mod=blog&type=blog&id=$blog->nid\"><img src=\"misc/blog.gif\" border=\"0\" width=\"12\" height=\"16\" alt=\"". t("Blog this item") ."\" /></a> <a href=\"module.php?mod=blog&name=". urlencode($blog->userid) ."\"><img src=\"misc/earth.gif\" border= \"0\" width=\"11\" height=\"11\" alt=\"". t("This blog") ."\" /></a> ". format_username($blog->userid) ." ". t("on") ." ". format_date($blog->timestamp) .":<br />"; + $output .= "<blockquote><b>". check_input($blog->title) ."</b><br />" . check_output($blog->body, 1) ."</blockquote>\n"; + } + + $theme->header(); + $theme->box(t("Latest blogs"), $output); + $theme->footer(); +} + +function blog_page_user($userid = 0, $date = 0) { + global $theme, $user; + + $userid = $userid ? $userid : $user->userid; + + $theme->header(); + + if ($date) { + + /* + ** Displays today's blogs for this user: + */ + + blog_page_day($userid, $date); + } + else { + + /* + ** Display the last blogs for this user: + */ + + $result = db_query("SELECT n.nid, n.timestamp FROM node n LEFT JOIN users u ON u.id = n.author WHERE u.userid = '". check_input($userid) ."' AND n.timestamp > ". (time() - 2592000) ." LIMIT 15"); + while ($blog = db_fetch_object($result)) { + if ($date != date("ndy", $blog->timestamp)) { + $date = date("ndy", $blog->timestamp); + blog_page_day($userid, $blog->timestamp); + } + } + } + + $theme->footer(); +} + + +function blog_page_day($userid = 0, $date = 0) { + global $theme, $user; + + $header .= "<table cellspacing=\"0\" cellpadding=\"0\" width=\"100%\">\n"; + $header .= " <tr>\n"; + $header .= " <td><b><a href=\"module.php?mod=blog&op=view&name=". urlencode($userid) ."\">". check_output($userid) ."'s ". t("blog") ."</a></b></td>\n"; + $header .= " <td align=\"right\"><b><a href=\"module.php?mod=blog&op=view&name=". urlencode($userid) ."&date=$date\">". format_date($date, custom, "d-M-Y") ."</a></b></td>\n"; + $header .= " </tr>\n"; + $header .= "</table>\n"; + + $sdate = mktime(0, 0, 0, date("m", $date), date("d", $date), date("Y", $date)); + $edate = mktime(23, 59, 59, date("m", $date), date("d", $date), date("Y", $date)); + + $result = db_query("SELECT b.body, n.timestamp, n.nid FROM blog b LEFT JOIN node n ON b.nid = n.nid LEFT JOIN users u ON n.author = u.id WHERE u.userid = '". check_input($userid) ."' AND n.timestamp > '$sdate' AND n.timestamp < '$edate' ORDER BY b.lid DESC LIMIT 50"); + + while ($blog = db_fetch_object($result)) { + if (!$first) $first = $blog->nid; + $output .= "<p><a href=\"submit.php?mod=blog&type=blog&id=$blog->nid\"><img src=\"misc/blog.gif\" border=\"0\" width=\"12\" height=\"16\" alt=\"". t("Blog this item") ."\"></a> ". check_output($blog->body, 1) ."</p>\n"; + } + + if ($userid == $user->userid) { + $output .= "<p>[ <a href=\"submit.php?mod=blog&op=edit&id=$first\">". t("edit") ."</a> ]</p>"; + } + + $theme->box($header, $output); +} + +function blog_status() { + return array(dumped, posted); +} + +function blog_remove($nid) { + global $status, $user; + + node_save(array(nid => $nid), array(status => $status[dumped])); + $blog = node_get_object(array(type => "blog", nid => "$nid")); + if ((user_access("administer blogs")) or ($blog->userid == $user->userid)) { + node_del(array(type => "blog", nid => $nid, lid => $blog->lid)); + } +} + +function blog_view($node) { + global $status, $theme; + + $userid = urlencode($node->userid); + + $header .= "<table cellspacing=\"0\" cellpadding=\"0\" width=\"100%\">\n"; + $header .= " <tr>\n"; + $header .= " <td><b><a href=\"module.php?mod=blog&op=view&name=$userid\">". $node->userid ."'s ". t("blog") ."</a></b></td>\n"; + $header .= " <td align=\"right\"><b><a href=\"module.php?mod=blog&op=view&name=$userid&date=$node->timestamp\">". format_date($node->timestamp, custom, "d-M-Y") ."</a></b></td>\n"; + $header .= " </tr>\n"; + $header .= "</table>\n"; + + $output .= "<p>". check_output($node->body, 1) ."</p>\n"; + $output .= "<p>[ ". implode(" | ", link_node($node)) ."]</p>\n"; + + $theme->box($header, $output); +} + +function blog_form($edit = array()) { + global $REQUEST_URI, $id, $type, $user, $theme; + + if ($edit[type] == "blog") { + } + else if ($type == "blog") { + $item = node_get_object(array(type => "blog", nid => $id)); + $edit["title"] = $item->title; + $edit["body"] = $item->body ." [<a href=\"module.php?mod=blog&name=". urlencode($item->userid) ."&date=$item->timestamp\">$item->userid</a>]"; + } + else if ($type == "import") { + $item = db_fetch_object(db_query("SELECT i.*, f.title as ftitle, f.link as flink FROM item i, feed f WHERE i.iid = '". check_input($id) ."' AND i.fid = f.fid")); + $edit["title"] = $item->title; + $edit["body"] = "<a href=\"$item->link\">$item->title</a> - ". check_output($item->description) ." [<a href=\"$item->flink\">$item->ftitle</a>]\n"; + } + + if ($edit[title]) { + $form .= blog_view(new Blog(node_preview($edit))); + } + + $form .= form_textfield(t("Subject"), "title", $edit["title"], 50, 64); + $form .= form_textarea(t("Body"), "body", $edit["body"], 70, 15, t("Allowed HTML tags") .": ". htmlspecialchars(variable_get("allowed_html", ""))); + + $form .= form_hidden("type", "blog"); + + if ($edit["nid"] > 0) { + $form .= form_hidden("nid", $edit["nid"]); + } + + if ($edit && !$edit["title"]) { + $form .= "<font color=\"red\">". t("Warning: you did not supply a subject.") ."</font><p>\n"; + $form .= form_submit(t("Preview")); + } + else if ($edit && !$edit["body"]) { + $form .= "<font color=\"red\">". t("Warning: you did not supply any text.") ."</font><p>\n"; + $form .= form_submit(t("Preview")); + } + else { + $form .= form_submit(t("Preview")); + $form .= form_submit(t("Submit")); + } + + $output .= form($REQUEST_URI, $form); + + return $output; +} + +function blog_save($edit) { + global $status, $user; + + if (!$edit["nid"]) { + node_save($edit, array(author => $user->id, body, status => variable_get("blog_status", $status[posted]), timestamp => time(), title, type => "blog")); + } + else if (user_access("administer blogs")) { + node_save($edit, array(attributes => node_attributes_save("blog", $edit), body, title, type => "blog")); + } +} + +function blog_edit_history($nid) { + global $user; + + // DB: changed this to 15 older blog entries rather than today's entries + // as there was no way to edit entries older than a day. The notion + // of a day can be quite annoying when bloging around midnight. All + // entries are accessible now. + // + // $blog = node_get_object(array(nid => $nid, type => "blog")); + // $sdate = mktime(0, 0, 0, date("m", $blog->timestamp), date("d", $blog->timestamp), date("Y", $blog->timestamp)); + // $edate = mktime(23, 59, 59, date("m", $blog->timestamp), date("d", $blog->timestamp), date("Y", $blog->timestamp)); + // $result = db_query("SELECT n.title, b.body, n.timestamp, n.nid FROM blog b LEFT JOIN node n ON b.nid = n.nid WHERE n.author = '$user->id' AND n.timestamp > '$sdate' AND n.timestamp < '$edate' ORDER BY b.lid DESC LIMIT 100"); + + $result = db_query("SELECT n.nid, n.title, n.timestamp, b.body FROM blog b LEFT JOIN node n ON b.nid = n.nid WHERE n.author = '". check_input($user->id) ."' AND n.nid < '". check_input($nid) ."' ORDER BY b.lid DESC LIMIT 15"); + + $output .= "<table cellpadding=\"3\" cellspacing=\"3\" border=\"0\" width=\"100%\">"; + while ($blog = db_fetch_object($result)) { + $output .= "<tr><td><b>". check_output($blog->title) ."</b><br />". check_output($blog->body, 1) ."</td><td><a href=\"submit.php?mod=blog&op=edit&id=$blog->nid\">". t("edit") ."</a></td><td><a href=\"submit.php?mod=blog&op=delete&id=$blog->nid\">". t("delete") ."</a></td></tr>\n"; + } + $output .= "</table>"; + + return $output; +} + +function blog_page() { + global $op, $name, $date; + + if (user_access("access blogs")) { + if ($name) { + blog_page_user($name, $date); + } + else { + blog_page_all(); + } + } +} + +function blog_user() { + global $op, $id, $name, $date, $edit, $theme, $user; + + if (user_access("post blogs")) { + switch ($op) { + case "delete": + blog_remove($id); + blog_page_day($user->userid, time()); + break; + case "edit": + $theme->box(t("Submit a blog"), blog_form(node_get_array(array("nid" => $id, "type" => "blog")))); + $theme->box(t("Older blogs"), blog_edit_history($id)); + break; + case t("Preview"): + $theme->box(t("Preview Blog"), blog_form($edit)); + break; + case t("Submit"): + blog_save($edit); + blog_page_day($user->userid, time()); + break; + default: + $theme->box(t("Submit a blog"), blog_form($edit)); + } + } +} + + +function blog_link($type) { + global $user; + + if ($type == "page" && user_access("access blogs")) { + $links[] = "<a href=\"module.php?mod=blog\">". t("latest blogs") ."</a>"; + } + + if ($type == "menu" && user_access("post blogs")) { + $links[] = "<a href=\"module.php?mod=blog&op=view&name=". urlencode($user->userid) ."\">". t("your blog") ."</a>"; + } + + return $links ? $links : array(); +} + + +function blog_block() { + global $name, $date, $user, $mod; + + $result = db_query("SELECT u.userid, n.timestamp, n.title, n.nid FROM node n LEFT JOIN users u ON n.author = u.id WHERE n.type = 'blog' ORDER BY n.nid DESC LIMIT 10"); + while ($node = db_fetch_object($result)) { + $output .= "<a href=\"module.php?mod=blog&op=view&name=". urlencode($node->userid) ."\">". check_output($node->title) ."<br />\n"; + } + + $block[0]["subject"] = "<a href=\"module.php?mod=blog\">". t("Latest blogs") ."</a>"; + $block[0]["content"] = $output; + $block[0]["info"] = t("Latest blogs"); + $block[0]["link"] = "module.php?mod=blog"; + + $date = $data ? $data : time(); + $userid = $name ? $name : $user->userid; + + if (($mod == "blog") || ($mod == "block")) { + // Only show this block on "blog pages" and in the admin block section. + $calendar = new BlogCalendar($userid, $date); + $block[1]["subject"] = "<a href=\"module.php?mod=blog&name=". urlencode($userid) ."\">" . t("Browse blog") . "</a>"; + $block[1]["content"] = $calendar->display(); + $block[1]["info"] = t("Calendar to browse blogs"); + } + + return $block; +} + + +function blog_search($keys) { + global $status, $user; + $result = db_query("SELECT n.*, b.* FROM blog b LEFT JOIN node n ON n.nid = b.nid AND n.lid = b.lid WHERE (n.title LIKE '%$keys%' OR b.body LIKE '%$keys%') ORDER BY n.timestamp DESC LIMIT 20"); + while ($blog = db_fetch_object($result)) { + $find[$i++] = array("title" => check_output($blog->title), "link" => (user_access("administer nodes") ? "admin.php?mod=node&type=blog&op=edit&id=$blog->nid" : "node.php?id=$blog->nid"), "user" => $blog->userid, "date" => $blog->timestamp); + } + return $find; +} + + +class BlogCalendar { + var $date; + var $userid; + + function BlogCalendar($userid, $date) { + $this->userid = urlencode($userid); + + // Prevent future dates: + $today = mktime(23, 59, 59, date("n", time()), date("d", time()), date("Y", time())); + $this->date = (($date && $date <= $today) ? $date : $today); + $this->date = mktime(23, 59, 59, date("n", $this->date), date("d", $this->date), date("Y", $this->date)); + } + + function display() { + // Extract information from the given date: + $month = date("n", $this->date); + $year = date("Y", $this->date); + $day = date("d", $this->date); + + // Extract today's date: + $today = mktime(23, 59, 59, date("n", time()), date("d", time()), date("Y", time())); + + // Extract the timestamp of the last day of today's month: + $thislast = mktime(23, 59, 59, date("n", time()), date("t", time()), date("Y", time())); + + // Extract first day of the month: + $first = date("w", mktime(0, 0, 0, $month, 1, $year)); + + // Extract last day of the month: + $last = date("t", mktime(0, 0, 0, $month, 1, $year)); + + // Calculate previous and next months dates and check for shorter months (28/30 days) + $prevmonth = mktime(23, 59, 59, $month - 1, 1, $year); + $prev = mktime(23, 59, 59, $month - 1, min(date("t", $prevmonth), $day), $year); + $nextmonth = mktime(23, 59, 59, $month + 1, 1, $year); + $next = mktime(23, 59, 59, $month + 1, min(date("t", $nextmonth), $day), $year); + + // Generate calendar header: + $output .= "\n<!-- calendar -->\n"; + $output .= "<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"1\">\n"; + $output .= " <TR><TD ALIGN=\"center\" COLSPAN=\"7\"><B><A HREF=\"module.php?mod=blog&name=$this->userid&date=$prev\" STYLE=\"text-decoration: none;\"><<</A> ". date("F Y", $this->date) ." " . ($next <= $thislast ? "<A HREF=\"module.php?mod=blog&name=$this->userid&date=$next\" STYLE=\"text-decoration: none;\">>></A>" : ">>") . "<B></TD></TR>\n"; + + // Generate the days of the week: + $output .= " <TR>"; + $somesunday = mktime(0, 0, 0, 3, 20, 1994); + for ($i = 0; $i < 7; $i++) { + $output .= "<TD ALIGN=\"center\">" . substr(ucfirst(t(date("l", $somesunday + $i * 86400))), 0, 1) . "</TD>"; + } + $output .= "</TR>\n"; + + // Initialize temporary variables: + $nday = 1; + $sday = $first; + + // Loop through all the days of the month: + while ($nday <= $last) { + // Set up blank days for first week of the month: + if ($first) { + $output .= " <TR><TD COLSPAN=\"$first\"> </TD>\n"; + $first = 0; + } + + // Start every week on a new line: + if ($sday == 0) $output .= " <TR>\n"; + + // Print one cell: + $date = mktime(23, 59, 59, $month, $nday, $year); + if ($date == $this->date) $output .= " <TD ALIGN=\"center\" BGCOLOR=\"#CCCCCC\"><B>$nday</B></TD>\n"; + else if ($date > $today) $output .= " <TD ALIGN=\"center\">$nday</TD>\n"; + else $output .= " <TD ALIGN=\"center\"><A HREF=\"module.php?mod=blog&name=$this->userid&date=$date\" STYLE=\"text-decoration: none;\">$nday</A></TD>\n"; + + // Start every week on a new line: + if ($sday == 6) $output .= " </TR>\n"; + + // Update temporary variables: + $sday++; + $sday = $sday % 7; + $nday++; + } + + // Complete the calendar: + if ($sday) { + $end = 7 - $sday; + $output .= " <TD COLSPAN=\"$end\"> </TD>\n </TR>\n"; + } + $output .= "</TABLE>\n\n"; + + // Return calendar: + return $output; + } +} + +?> diff --git a/modules/diary.module b/modules/diary.module deleted file mode 100644 index 9a39c1c7c..000000000 --- a/modules/diary.module +++ /dev/null @@ -1,362 +0,0 @@ -<?php - -function diary_perm() { - return array("administer diary entries", "access diary entries", "post diary entries"); -} - -function diary_search($keys) { - $result = db_query("SELECT d.*, u.userid FROM diaries d LEFT JOIN users u ON d.author = u.id WHERE d.text LIKE '%$keys%' ORDER BY d.timestamp DESC LIMIT 20"); - while ($diary = db_fetch_object($result)) { - $find[$i++] = array("title" => "$diary->userid's diary", "link" => (user_access("administer diary entries") ? "admin.php?mod=diary&op=edit&id=$diary->id" : "module.php?mod=diary&op=view&name=$diary->userid"), "user" => $diary->userid, "date" => $diary->timestamp); - } - return $find; - -} - -function diary_page_overview($num = 20) { - global $theme, $user; - - if (user_access("access diary entries")) { - $result = db_query("SELECT d.*, u.userid FROM diaries d LEFT JOIN users u ON d.author = u.id ORDER BY d.timestamp DESC LIMIT $num"); - - while ($diary = db_fetch_object($result)) { - if ($time != date("F jS", $diary->timestamp)) { - $output .= "<B>". $date = t(date("l", $diary->timestamp)) .", ". t(date("F", $diary->timestamp)) ." ". date("j", $diary->timestamp) ."</B>\n"; - $time = date("F jS", $diary->timestamp); - } - $output .= "<DL>\n"; - $output .= " <DD><P><B>$diary->userid ". t("wrote") .":</B></P></DD>\n"; - $output .= " <DL>\n"; - $output .= " <DD><P>". check_output($diary->text, 1) ."</P><P>[ <A HREF=\"module.php?mod=diary&op=view&name=$diary->userid\">". t("more") ."</A> ]</P></DD>\n"; - $output .= " </DL>\n"; - $output .= "</DL>\n"; - } - - $theme->header(); - $theme->box(t("Online diary"), $output); - $theme->footer(); - } - else { - $theme->header(); - $theme->box(t("Access denied"), message_access()); - $theme->footer(); - } -} - -function diary_page_entry($timestamp, $text, $id = 0) { - if ($id) { - $output .= "<DL>\n"; - $output .= " <DT><B>". format_date($timestamp, "large") .":</B></DT>\n"; - $output .= " <DD><P>[ <A HREF=\"module.php?mod=diary&op=edit&id=$id\">". t("edit") ."</A> | <A HREF=\"module.php?mod=diary&op=delete&id=$id\">". t("delete") ."</A> ]</P><P>". check_output($text, 1) ."</P></DD>\n"; - $output .= "</DL>\n"; - } - else { - $output .= "<DL>\n"; - $output .= " <DT><B>". format_date($timestamp, "large") .":</B></DT>\n"; - $output .= " <DD><P>". check_output($text, 1) ."</P></DD>\n"; - $output .= "</DL>\n"; - } - return $output; -} - -function diary_page_display($username) { - global $theme, $user; - - $username = empty($username) ? $user->userid : $username; - - $result = db_query("SELECT d.*, u.userid FROM diaries d LEFT JOIN users u ON d.author = u.id WHERE u.userid = '$username' ORDER BY timestamp DESC"); - - if ($username == $user->userid) { - $output .= diary_page_entry(time(), "<BIG><A HREF=\"module.php?mod=diary&op=add\">". t("Add new diary entry!") ."</A></BIG><P>"); - while ($diary = db_fetch_object($result)) $output .= diary_page_entry($diary->timestamp, $diary->text, $diary->id); - } - else { - $output .= "<B>". t("Username") .":</B> ". format_username($username); - while ($diary = db_fetch_object($result)) $output .= diary_page_entry($diary->timestamp, $diary->text); - } - - $theme->header(); - $theme->box(t("Online diary"), $output); - $theme->footer(); -} - -function diary_page_add() { - global $theme, $user; - - $output .= "<FORM ACTION=\"module.php?mod=diary\" METHOD=\"post\">\n"; - - $output .= "<P>\n"; - $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"15\" NAME=\"text\"></TEXTAREA><BR>\n"; - $output .= " <SMALL><I>". t("Allowed HTML tags") .": ". htmlspecialchars(variable_get("allowed_html", "")) .".</I></SMALL>\n"; - $output .= "</P>\n"; - - $output .= "<P>\n"; - $output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Preview diary entry\">\n"; - $output .= "</P>\n"; - - $output .= "</FORM>\n"; - - $theme->header(); - $theme->box(t("Edit your diary"), $output); - $theme->footer(); -} - -function diary_page_delete($id) { - db_query("DELETE FROM diaries WHERE id = '$id'"); - watchdog("message", "diary: diary entry deleted"); -} - -function diary_page_edit($id) { - global $theme, $user; - - $result = db_query("SELECT * FROM diaries WHERE id = '$id'"); - $diary = db_fetch_object($result); - - $output .= diary_page_entry($diary->timestamp, $diary->text); - - $output .= "<FORM ACTION=\"module.php?mod=diary\" METHOD=\"post\">\n"; - $output .= "<P>\n"; - $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"15\" NAME=\"text\">". check_form($diary->text) ."</TEXTAREA><BR>\n"; - $output .= " <SMALL><I>". t("Allowed HTML tags") .": ". htmlspecialchars(variable_get("allowed_html", "")) .".</I></SMALL>\n"; - $output .= "</P>\n"; - $output .= "<P>\n"; - $output .= " <INPUT TYPE=\"hidden\" NAME=\"id\" VALUE=\"$diary->id\">\n"; - $output .= " <INPUT TYPE=\"hidden\" NAME=\"timestamp\" VALUE=\"$diary->timestamp\">\n"; - $output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Preview diary entry\"> <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Submit diary entry\">\n"; - $output .= "</P>\n"; - $output .= "</FORM>\n"; - - $theme->header(); - $theme->box(t("Edit your diary"), $output); - $theme->footer(); -} - -function diary_page_preview($text, $timestamp, $id = 0) { - global $theme, $user; - - $output .= diary_page_entry($timestamp, $text); - - $output .= "<FORM ACTION=\"module.php?mod=diary\" METHOD=\"post\">\n"; - $output .= "<P>\n"; - $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"15\" NAME=\"text\">". check_form($text) ."</TEXTAREA><BR>\n"; - $output .= " <SMALL><I>". t("Allowed HTML tags") .": ". htmlspecialchars(variable_get("allowed_html", "")) .".</I></SMALL>\n"; - $output .= "</P>\n"; - $output .= "<P>\n"; - $output .= " <INPUT TYPE=\"hidden\" NAME=\"id\" VALUE=\"$id\">\n"; - $output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Preview diary entry\">\n"; - $output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Submit diary entry\">\n"; - $output .= "</P>\n"; - - $output .= "</FORM>\n"; - - $theme->header(); - $theme->box(t("Edit your diary"), $output); - $theme->footer(); -} - -function diary_page_submit($text, $id = 0) { - global $user, $theme; - - if ($id) { - watchdog("message", "diary: old diary entry updated"); - db_query("UPDATE diaries SET text = '$text' WHERE id = '$id'"); - } - else { - watchdog("special", "diary: new diary entry added"); - db_query("INSERT INTO diaries (author, text, timestamp) VALUES ('$user->id', '$text', '". time() ."')"); - } - - header("Location: module.php?mod=diary&op=view&name=$user->userid"); -} - -function diary_page() { - global $op, $id, $name, $text, $timestamp; - - // Security check: - if (strstr($id, " ") || strstr($name, " ")) { - watchdog("error", "diary: attempt to provide malicious input through URI"); - exit(); - } - - switch($op) { - case "add": - diary_page_add(); - break; - case "delete": - diary_page_delete(check_input($id)); - diary_page_display(check_input($name)); - break; - case "edit": - diary_page_edit(check_input($id)); - break; - case "view": - diary_page_display(check_input($name)); - break; - case "Preview diary entry": - if ($id) diary_page_preview(($text ? check_output($text) : ""), check_input($timestamp), check_input($id)); - else diary_page_preview(($text ? check_output($text) : ""), time()); - break; - case "Submit diary entry": - if ($id) diary_page_submit(check_input($text), check_input($id)); - else diary_page_submit(check_input($text)); - break; - default: - diary_page_overview(); - } -} - -function diary_help() { - ?> - <P>Drupal's diary module allows registered users to maintain an online diary. It provides easy-to-write and easy-to-read online diaries or journals that can be filled with daily thoughts, poetry, boneless blabber, spiritual theories, intimate details, valuable experiences, cynical rants, semi-coherent comments, writing experiments, artistic babblings, critics on current facts, fresh insights, diverse dreams, chronicles and mumbling madness available for public consumption.</P> - <?php -} - -function diary_link($type) { - - if ($type == "admin" && user_access("administer diary entries")) { - $links[] = "<a href=\"admin.php?mod=diary\">online diaries</a>"; - } - - if ($type == "page" && user_access("access diary entries")) { - $links[] = "<a href=\"module.php?mod=diary\">". t("online diaries") ."</a>"; - } - - if ($type == "menu" && user_access("post diary entries")) { - $links[] = "<a href=\"module.php?mod=diary&op=add\">". t("edit your diary") ."</a>"; - $links[] = "<a href=\"module.php?mod=diary&op=view\">". t("view your diary") ."</a>"; - } - - return $links ? $links : array(); -} - -function diary_block() { - $result = db_query("SELECT u.userid, d.timestamp FROM diaries d LEFT JOIN users u ON d.author = u.id ORDER BY timestamp DESC LIMIT 10"); - - while ($diary = db_fetch_object($result)) { - if ($time != date("F jS", $diary->timestamp)) { - $content .= "<P><B>". t(date("l", $diary->timestamp)) ."</B> (". date("m/d/Y", $diary->timestamp) .")</P>\n"; - $time = date("F jS", $diary->timestamp); - } - $content .= "<LI><A HREF=\"module.php?mod=diary&op=view&name=$diary->userid\">$diary->userid</A></LI>\n"; - } - - $block[0]["subject"] = "Recent diary entries"; - $block[0]["content"] = $content; - $block[0]["info"] = "Recent diary entries"; - $block[0]["link"] = "module.php?mod=diary"; - - return $block; -} - -function diary_admin_edit($id) { - $result = db_query("SELECT d.*, u.userid FROM diaries d LEFT JOIN users u ON d.author = u.id WHERE d.id = '$id'"); - - $diary = db_fetch_object($result); - - $output .= "<FORM ACTION=\"admin.php?mod=diary&op=save&id=$id\" METHOD=\"post\">\n"; - - $output .= "<P>\n"; - $output .= " <B>Author:</B><BR>\n"; - $output .= " ". format_username($diary->userid) ."\n"; - $output .= "</P>\n"; - - $output .= "<P>\n"; - $output .= "<B>Diary entry:</B><BR>\n"; - $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"10\" NAME=\"text\">". check_form($diary->text) ."</TEXTAREA><BR>\n"; - $output .= "</P>\n"; - - $output .= "<P>\n"; - $output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Save diary entry\">\n"; - $output .= "</P>\n"; - $output .= "</FORM>\n"; - - print $output; -} - -function diary_admin_save($id, $text) { - db_query("UPDATE diaries SET text = '$text' WHERE id = $id"); - watchdog("message", "diary: modified entry #$id."); -} - -function diary_admin_delete($id) { - db_query("DELETE FROM diaries WHERE id = '$id'"); - watchdog("message", "diary: deleted entry #$id."); -} - -function diary_admin_display($order = "date") { - // Initialize variables: - $fields = array("author" => "author", "date" => "timestamp DESC"); - - // Perform SQL query: - $result = db_query("SELECT d.*, u.userid FROM diaries d LEFT JOIN users u ON u.id = d.author ORDER BY d.$fields[$order] LIMIT 50"); - - // Display stories: - $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n"; - $output .= " <TR>\n"; - $output .= " <TH ALIGN=\"right\" COLSPAN=\"4\">\n"; - $output .= " <FORM ACTION=\"admin.php?mod=diary\" METHOD=\"post\">\n"; - $output .= " <SELECT NAME=\"order\">\n"; - foreach ($fields as $key=>$value) { - $output .= " <OPTION VALUE=\"$key\"". ($key == $order ? " SELECTED" : "") .">Sort by $key</OPTION>\n"; - } - $output .= " </SELECT>\n"; - $output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Update\">\n"; - $output .= " </FORM>\n"; - $output .= " </TH>\n"; - $output .= " </TR>\n"; - - $output .= " <TR>\n"; - $output .= " <TH>subject</TH>\n"; - $output .= " <TH>author</TH>\n"; - $output .= " <TH COLSPAN=\"2\">operations</TH>\n"; - $output .= " </TR>\n"; - - while ($diary = db_fetch_object($result)) { - $output .= " <TR><TD><A HREF=\"module.php?mod=diary&op=view&name=$diary->userid\">$diary->userid on ". format_date($diary->timestamp, "small") ."</A></TD><TD>". format_username($diary->userid) ."</TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=diary&op=edit&id=$diary->id\">edit</A></TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=diary&op=delete&id=$diary->id\">delete</A></TD></TR>\n"; - } - - $output .= "</TABLE>\n"; - - print $output; -} - - -function diary_admin() { - global $op, $id, $mod, $keys, $text, $order; - - if (user_access("administer diary entries")) { - - print "<SMALL><A HREF=\"admin.php?mod=diary\">overview</A> | <A HREF=\"admin.php?mod=diary&op=search\">search diary</A> | <A HREF=\"admin.php?mod=diary&op=help\">help</A></SMALL><HR>\n"; - - switch ($op) { - case "delete": - diary_admin_delete(check_input($id)); - diary_admin_display(); - break; - case "edit": - diary_admin_edit(check_input($id)); - break; - case "help": - diary_help(); - break; - case "search": - print search_form($keys); - print search_data($keys, $mod); - break; - case "Save diary entry": - diary_admin_save(check_input($id), check_input($text)); - diary_admin_display(); - break; - case "Update": - diary_admin_display(check_input($order)); - break; - default: - diary_admin_display(); - } - } - else { - print message_access(); - } -} - -?> diff --git a/modules/import.module b/modules/import.module index a80994e8c..11e25fdc4 100644 --- a/modules/import.module +++ b/modules/import.module @@ -11,69 +11,153 @@ function import_help() { <?php } +function import_conf_options() { + $number = array(5 => 5, 10 => 10, 15 => 15, 20 => 20, 25 => 25, 30 => 30, 35 => 35, 40 => 40, 45 => 45, 50 => 50, 55 => 55, 60 => 60, 65 => 65, 70 => 70, 75 => 75, 80 => 80, 85 => 85, 90 => 90, 95 => 95, 100 => 100); + $output .= form_select("Items per block", "import_block_limit", variable_get("import_block_limit", 15), $number, "The maximum number of items displayed in one block."); + $output .= form_select("Items per page", "import_page_limit", variable_get("import_page_limit", 75), $number, "The maximum number of items displayed on one page."); + return $output; +} + function import_perm() { - return array("administer syndication"); + return array("administer news feeds", "access news feeds"); } function import_link($type) { - if ($type == "admin") { - $links[] = "<a href=\"admin.php?mod=import\">syndication</a>"; + if ($type == "admin" && user_access("administer news feeds")) { + $links[] = "<a href=\"admin.php?mod=import\">news feeds</a>"; + } + + if ($type == "menu" && user_access("administer news feeds")) { + $links[] = "<a href=\"module.php?mod=import&op=update\">". t("update all news") ."</a>"; + } + + if ($type == "page" && user_access("access news feeds")) { + $links[] = "<a href=\"module.php?mod=import\">". t("latest news") ."</a>"; } return $links ? $links : array(); } function import_cron() { + $result = db_query("SELECT * FROM feed WHERE timestamp + refresh < ". time()); + while ($feed = db_fetch_array($result)) { + import_refresh($feed); + } +} + +function import_update() { $result = db_query("SELECT * FROM feed"); while ($feed = db_fetch_array($result)) { - // remove expired items: - db_query("DELETE FROM item WHERE fid = '$feed[fid]' AND timestamp < ". (time() - $feed[uncache])); + import_refresh($feed); + } +} + +function import_format_item($item, $feed = 0, $description = 0) { + if (module_hook("blog", "page")) { + $output .= "<a href=\"submit.php?mod=blog&type=import&id=$item->iid\"><img src=\"misc/blog.gif\" border=\"0\" width=\"12\" height=\"16\" alt=\"" . t("Blog this item") . "\" /></a> "; + } + + if ($feed != 1) { + $output .= "<a href=\"module.php?mod=import&op=feed&id=$item->fid\"><img src=\"misc/earth.gif\" border= \"0\" width=\"11\" height=\"11\" alt=\"". t("All headlines from this feed") ."\" /></a> "; + } + + $output .= "<a href=\"". check_output($item->link) ."\" target=\"new\">". check_output($item->title) ."</a>"; - // update feeds: - if ($feed[timestamp] + $feed[refresh] < time()) import_update($feed); + if ($description && ($feed != 1)) { + $output .= " <small>". format_url($item->flink, $item->ftitle) ."</small>"; } + + if ($description) { + $output .= "<br />". check_output($item->description) ."<br />\n"; + } + + return $output ."<br />"; } -function import_bundle($attributes, $limit = 100) { +function import_bundle_block($attributes) { + if ($attributes) { - // compose query: $keys = explode(",", $attributes); foreach ($keys as $key) $where[] = "attributes LIKE '%". trim($key) ."%'"; - $result = db_query("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY iid DESC LIMIT $limit"); + $result = db_query("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY iid DESC LIMIT ". variable_get("import_block_limit", 15)); while ($item = db_fetch_object($result)) { - $output .= "<li><a href=\"". check_output($item->link) ."\">". check_output($item->title) ."</a></li>"; + $output .= import_format_item($item, 0); } - return "$output"; + return $output; } } -function import_view_bundle() { - $result = db_query("SELECT * FROM bundle ORDER BY title"); - while ($bundle = db_fetch_object($result)) { - $output .= "<b>$bundle->title</b><ul>". import_bundle($bundle->attributes) ."</ul>"; - } - return $output; -} +function import_feed_block($feed) { + $result = db_query("SELECT * FROM item WHERE fid = '$feed->fid' ORDER BY iid DESC LIMIT ". variable_get("import_block_limit", 15)); -function import_view_feed() { - $result = db_query("SELECT * FROM feed ORDER BY title"); - while ($feed = db_fetch_object($result)) { - $output .= "<b>$feed->title</b>". ($feed->link ? " (". format_url($feed->link) .")" : "") ."<ul>". check_output($feed->description) ."</ul>"; + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 1); } + + $output .= "<br />". t("Last update:") ." ". format_interval(time() - $feed->timestamp) ." ". t("ago"); + return $output; } function import_block() { + return import_block_bundle(); +} + +function import_block_bundle($attributes = 0) { + + if ($attributes) { + $keys = explode(",", $attributes); + foreach ($keys as $key) $where[] = "attributes LIKE '%". trim($key) ."%'"; + $result = db_query("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY iid DESC LIMIT ". variable_get("import_block_limit", 15)); + } + else { + $result = db_query("SELECT * FROM item ORDER BY iid DESC LIMIT ". variable_get("import_block_limit", 15)); + } + + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 0); + } + + $blocks[0][subject] = format_url("module.php?mod=import", t("Latest news")); + $blocks[0][content] = $output; + $blocks[0][info] = t("Latest news"); + $result = db_query("SELECT * FROM bundle ORDER BY title"); + while ($bundle = db_fetch_object($result)) { $i++; - $blocks[$i][subject] = $bundle->title; - $blocks[$i][content] = import_bundle($bundle->attributes, 10); + + $blocks[$i][subject] = format_url("module.php?mod=import&op=bundle&id=$bundle->bid", $bundle->title); + $blocks[$i][content] = import_bundle_block($bundle->attributes); $blocks[$i][info] = "$bundle->title bundle"; } + + return $blocks; +} + +function import_block_feed($attributes = 0) { + + if ($attributes) { + $keys = explode(",", $attributes); + foreach ($keys as $key) $where[] = "attributes LIKE '%". trim($key) ."%'"; + $result = db_query("SELECT * FROM feed WHERE ". implode(" OR ", $where) ." ORDER BY fid LIMIT ". variable_get("import_block_limit", 15)); + } + else { + $result = db_query("SELECT * FROM feed ORDER BY fid LIMIT ". variable_get("import_block_limit", 15)); + } + + $i = 0; + while ($feed = db_fetch_object($result)) { + $blocks[$i][subject] = format_url("module.php?mod=import&op=feed&id=$feed->fid", $feed->title); + $blocks[$i][content] = import_feed_block($feed); + $blocks[$i][info] = "$feed->title feed"; + + $i++; + } + return $blocks; } @@ -82,7 +166,7 @@ function import_remove($feed) { return "feed '$feed[title]' reset."; } -function import_update($feed) { +function import_refresh($feed) { // open socket: $url = parse_url($feed[url]); @@ -90,16 +174,21 @@ function import_update($feed) { if ($fp) { // fetch data: - fputs($fp, "GET $url[path]?$url[query] HTTP/1.0\nUser-Agent: ". variable_get(site_name, "drupal") ."\nHost: $url[host]\nAccept: */*\n\n"); + fputs($fp, "GET $url[path]?$url[query] HTTP/1.0\nUser-Agent: ". variable_get("site_name", "drupal") ."\nHost: $url[host]\nAccept: */*\n\n"); + + while (!feof($fp)) $data .= fgets($fp, 128); // initialize the translation table: $tt = array_flip(get_html_translation_table(HTML_ENTITIES)); $tt["'"] = "'"; - while(!feof($fp)) $data .= fgets($fp, 128); - if (strstr($data, "200 OK")) { - + /* + ** Remove expired items: + */ + + db_query("DELETE FROM item WHERE fid = '$feed[fid]' AND timestamp < ". (time() - $feed[uncache])); + /* ** Extract and process channel information: */ @@ -118,6 +207,8 @@ function import_update($feed) { eregi("<item([^s].*)</item>", $data, $data); + // print "<PRE>". htmlentities($data[0]) ."</PRE>"; + $items = array_reverse(explode("</item>", $data[0])); foreach ($items as $item) { @@ -134,7 +225,7 @@ function import_update($feed) { } } else { - watchdog("error", "import: failed to syndicate from '$feed[title]'"); + watchdog("error", "failed to syndicate from '$feed[title]'"); } } @@ -148,7 +239,7 @@ function import_save_item($edit) { else if ($edit[iid]) { db_query("DELETE FROM item WHERE iid = '". check_input($edit[iid]) ."'"); } - else { + else if ($edit[title] && $edit[link]) { if (!db_fetch_object(db_query("SELECT iid FROM item WHERE link = '". check_input($edit[link]) ."'"))) { db_query("INSERT INTO item (fid, title, link, author, description, attributes, timestamp) VALUES ('". check_input($edit[fid]) ."', '". check_input($edit[title]) ."', '". check_input($edit[link]) ."', '". check_input($edit[author]) ."', '". check_input($edit[description]) ."', '". check_input($edit[attributes]) ."', '". time() ."')"); } @@ -178,7 +269,7 @@ function import_save_bundle($edit) { else if ($edit[bid]) { db_query("DELETE FROM bundle WHERE bid = '". check_input($edit[bid]) ."'"); } - else { + else if ($edit[title]) { db_query("INSERT INTO bundle (title, attributes) VALUES ('". check_input($edit[title]) ."', '". check_input($edit[attributes]) ."')"); } @@ -190,8 +281,11 @@ function import_form_feed($edit = array()) { $period = array(900 => format_interval(900), 1800 => format_interval(1800), 3600 => format_interval(3600), 7200 => format_interval(7200), 10800 => format_interval(10800), 21600 => format_interval(21600), 32400 => format_interval(32400), 43200 => format_interval(43200), 64800 => format_interval(64800), 86400 => format_interval(86400), 172800 => format_interval(172800), 259200 => format_interval(259200), 604800 => format_interval(604800), 1209600 => format_interval(1209600), 2419200 => format_interval(2419200)); + if ($edit[refresh]== "") $edit[refresh] = 3600; + if ($edit[uncache]== "") $edit[uncache] = 2419200; + $form .= form_textfield("Title", "title", $edit[title], 50, 64, "The name of the feed; typically the name of the website you syndicate content from."); - $form .= form_textfield("URL", "url", $edit[url], 50, 128, "The fully-qualified URL of the feed."); + $form .= form_textfield("Url", "url", $edit[url], 50, 128, "The fully-qualified URL of the feed."); $form .= form_textfield("Attributes", "attributes", $edit[attributes], 50, 128, "A comma-seperated list of keywords describing the feed."); $form .= form_select("Update interval", "refresh", $edit[refresh], $period, "The refresh interval indicating how often you want to update this feed. Requires crontab."); $form .= form_select("Expiration time", "uncache", $edit[uncache], $period, "The time cached items should be kept. Older items will be automatically discarded. Requires crontab."); @@ -215,7 +309,7 @@ function import_save_feed($edit) { db_query("DELETE FROM feed WHERE fid = '". check_input($edit[fid]) ."'"); db_query("DELETE FROM item WHERE fid = '". check_input($edit[fid]) ."'"); } - else { + else if ($edit[title]) { db_query("INSERT INTO feed (title, url, attributes, refresh, uncache) VALUES ('". check_input($edit[title]) ."', '". check_input($edit[url]) ."', '". check_input($edit[attributes]) ."', '". check_input($edit[refresh]) ."', '". check_input($edit[uncache]) ."')"); } } @@ -240,7 +334,7 @@ function import_view() { $output .= "<h3>Feed overview</h3>"; $output .= "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n"; - $output .= " <tr><th>site</th><th>attributes</th><th>items</th><th>last update</th><th>next update</th><th colspan=\"3\">operations</th></tr>\n"; + $output .= " <tr><th>title</th><th>attributes</th><th>items</th><th>last update</th><th>next update</th><th colspan=\"3\">operations</th></tr>\n"; while ($feed = db_fetch_object($result)) { $output .= " <tr><td>". check_output($feed->title) ."</td><td>". check_output($feed->attributes) ."</td><td>". format_plural($feed->items, "item", "items") ."</td><td>". ($feed->timestamp ? format_interval(time() - $feed->timestamp) ." ago" : "never") ."</td><td>". ($feed->timestamp ? format_interval($feed->timestamp + $feed->refresh - time()) ." left" : "never") ."</td><td><a href=\"admin.php?mod=import&type=feed&op=edit&id=$feed->fid\">edit feed</a></td><td><a href=\"admin.php?mod=import&type=feed&op=remove&id=$feed->fid\">remove items</a></td><td><a href=\"admin.php?mod=import&type=feed&op=update&id=$feed->fid\">update items</a></td></tr>\n"; } @@ -259,6 +353,22 @@ function import_view() { return $output; } +function import_view_feed() { + $result = db_query("SELECT * FROM feed ORDER BY title"); + while ($feed = db_fetch_object($result)) { + $output .= "<b>$feed->title</b>". ($feed->link ? " (". format_url($feed->link) .")" : "") ."<ul>". check_output($feed->description) ."</ul>"; + } + return $output; +} + +function import_view_bundle() { + $result = db_query("SELECT * FROM bundle ORDER BY title"); + while ($bundle = db_fetch_object($result)) { + $output .= "<b>$bundle->title</b><ul>". import_bundle_block($bundle->attributes) ."</ul>"; + } + return $output; +} + function import_view_item() { global $REQUEST_URI; @@ -268,7 +378,7 @@ function import_view_item() { $output .= "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n"; $output .= " <tr><th>time</th><th>feed</th><th>item</th></tr>\n"; while ($item = db_fetch_object($result)) { - $output .= " <tr><td valign=\"top\" nowrap=\"nowrap\">". format_date($item->timestamp, "custom", "m/d/y") ."<br />".format_date($item->timestamp, "custom", "H:i") ."</td><td align=\"center\" valign=\"top\" nowrap=\"nowrap\"><a href=\"admin.php?mod=import&type=feed&op=edit&id=$item->fid\">". check_output($item->feed) ."</a></td><td><a href=\"". check_output($item->link) ."\">". check_output($item->title) ."</a>". ($item->description ? "<br /><small><i>". check_output($item->description) ."</i></small>" : "") ."<br /><input type=\"text\" name=\"edit[$item->iid]\" value=\"". check_form($item->attributes) ."\" size=\"50\" /></td></tr>\n"; + $output .= " <tr><td valign=\"top\" nowrap=\"nowrap\">". format_date($item->timestamp, "custom", "m/d/y") ."<br />".format_date($item->timestamp, "custom", "H:i") ."</td><td align=\"center\" valign=\"top\" nowrap=\"nowrap\"><a href=\"admin.php?mod=import&type=feed&op=edit&id=$item->fid\">". check_output($item->feed) ."</a></td><td><a href=\"". check_output($item->url) ."\">". check_output($item->title) ."</a>". ($item->description ? "<br /><small><i>". check_output($item->description) ."</i></small>" : "") ."<br /><input type=\"text\" name=\"edit[$item->iid]\" value=\"". check_form($item->attributes) ."\" size=\"50\" /></td></tr>\n"; } $output .= "</table>\n"; $output .= "<input type=\"submit\" name=\"op\" value=\"Save attributes\" />\n"; @@ -280,7 +390,7 @@ function import_view_item() { function import_admin() { global $op, $id, $type, $edit; - if (user_access("administer syndication")) { + if (user_access("administer news feeds")) { print "<small><a href=\"admin.php?mod=import&type=feed&op=add\">add new feed</a> | <a href=\"admin.php?mod=import&type=bundle&op=add\">add new bundle</a> | <a href=\"admin.php?mod=import&type=feed&op=view\">available feeds</a> | <a href=\"admin.php?mod=import&type=bundle&op=view\">available bundles</a> | <a href=\"admin.php?mod=import&type=item&op=view\">available items</a> | <a href=\"admin.php?mod=import&op=view\">overview</a> | <a href=\"admin.php?mod=import&op=help\">help</a></small><hr />"; @@ -302,11 +412,11 @@ function import_admin() { break; case "remove": print status(import_remove(import_get_feed($id))); - print import_view_feed(); + print import_view(); break; case "update": - print status(import_update(import_get_feed($id))); - print import_view_feed(); + print status(import_refresh(import_get_feed($id))); + print import_view(); break; case "Save attributes": print status(import_save_attributes($edit)); @@ -337,4 +447,132 @@ function import_admin() { } } +function import_page_all() { + global $theme; + + $result = db_query("SELECT i.*, f.title AS ftitle, f.link AS flink FROM item i LEFT JOIN feed f ON i.fid = f.fid ORDER BY i.iid DESC LIMIT ". variable_get("import_page_limit", 75)); + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 0, 1); + } + + $header = t("Latest news for all bundles") ." (<a href=\"module.php?mod=import&op=bundles\">by bundle</A>) (<a href=\"module.php?mod=import&op=feeds\">by feed</a>) "; + + $theme->header(); + $theme->box($header, $output); + $theme->footer(); +} + +function import_page_feed($fid) { + global $theme; + + $result = db_query("SELECT * FROM feed WHERE fid = '". check_input($fid) ."'"); + $feed = db_fetch_object($result); + + $header .= "<a href=\"$feed->url\"><img src=\"misc/xml.gif\" width=\"36\" height=\"14\" align=\"right\" border=\"0\" /></a>"; + $header .= $feed->title . " <a href=\"$feed->link\" target=\"new\"><img src=\"misc/earth.gif\" border= \"0\" width=\"11\" height=\"11\" alt=\"". t("View site") ."\" /></a>"; + + $result = db_query("SELECT * FROM item WHERE fid = '". check_input($fid) ."' ORDER BY iid DESC LIMIT ". variable_get("import_page_limit", 75)); + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 1, 1); + } + + $output .= t("Last update:") ." ". format_interval(time() - $feed->timestamp) ." ". t("ago"); + + $theme->header(); + $theme->box($header, $output); + $theme->footer(); +} + +function import_page_bundle($bid) { + global $theme; + + $bundle = db_fetch_object(db_query("SELECT * FROM bundle where bid = '". check_input($bid) ."'")); + $header = $bundle->title ." ". t("bundle") ." (<a href=\"module.php?mod=import&op=bundlefeeds&id=$bid\">". t("by feed") ."</a>)"; + + $keys = explode(",", $bundle->attributes); + foreach ($keys as $key) $where[] = "i.attributes LIKE '%". trim($key) ."%'"; + $result = db_query("SELECT i.*, f.title AS ftitle, f.link AS flink FROM item i, feed f WHERE (". implode(" OR ", $where) .") AND i.fid = f.fid ORDER BY iid DESC LIMIT ". variable_get("import_page_limit", 75)); + + while ($item = db_fetch_object($result)) { + $output .= import_format_item($item, 0, 1); + } + + $theme->header(); + $theme->box($header, $output); + $theme->footer(); +} + +function import_page_bundles() { + import_page_blocks(import_block_bundle()); +} + +function import_page_feeds() { + import_page_blocks(import_block_feed()); +} + +function import_page_bundle_feeds($bid) { + $bundle = db_fetch_object(db_query("SELECT * FROM bundle WHERE bid = '". check_input($bid) ."'")); + import_page_blocks(import_block_feed($bundle->attributes)); +} + +function import_page_blocks($blocks) { + global $theme; + + $count = count($blocks); + $items = ceil($count / 3); + $c1 = min($items, $count); + $c2 = min(2 * $items, $count); + $c3 = $count; + $i = 0; + + $theme->header(); + print "<table cellpadding=\"0\" cellspacing=\"5\" border=\"0\" width=\"100%\">\n"; + print " <tr>\n"; + print " <td width=\"33%\" valign=\"top\">\n"; + for ($i; $i < $c1; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]); + print " </td>\n"; + print " <td width=\"33%\" valign=\"top\">\n"; + for ($i; $i < $c2; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]); + print " </td>\n"; + print " <td width=\"33%\" valign=\"top\">\n"; + for ($i; $i < $c3; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]); + print " </td>\n"; + print " </tr>\n"; + print "</table>\n"; + $theme->footer(); +} + +function import_page() { + global $op, $id; + + if (user_access("access news feeds")) { + switch($op) { + case "all": + import_page_all(); + break; + case "feed": + import_page_feed($id); + break; + case "bundle": + import_page_bundle($id); + break; + case "bundlefeeds": + import_page_bundle_feeds($id); + break; + case "bundles": + import_page_bundles(); + break; + case "feeds": + import_page_feeds(); + break; + case "update": + import_update(); + import_page_all(); + break; + default: + import_page_all(); + } + } +} + ?> diff --git a/updates/2.00-to-x.xx.sql b/updates/2.00-to-x.xx.sql index 0b544edd8..88a7ed12f 100644 --- a/updates/2.00-to-x.xx.sql +++ b/updates/2.00-to-x.xx.sql @@ -317,3 +317,11 @@ CREATE TABLE site ( ALTER TABLE feed CHANGE link url varchar(255) DEFAULT '' NOT NULL; ALTER TABLE feed ADD link varchar(255) DEFAULT '' NOT NULL; ALTER TABLE feed ADD description TEXT DEFAULT '' NOT NULL; + +# 12/06/01 +CREATE TABLE blog ( + lid int(10) unsigned NOT NULL auto_increment, + nid int(10) unsigned NOT NULL, + body text NOT NULL, + PRIMARY KEY (lid) +); |