Nodes"; $output .= "

The core of the Drupal system is the node. All of the contents of the system are placed in nodes, or extensions of nodes."; $output .= "A base node contains:

"; $output .= "
A Title
Up to 128 characters of text that titles the node.
"; $output .= "
A Teaser
A small block of text that is meant to get you interested in the rest of node. Drupal will automatically pull a small amount of the body of the node to make the teaser (To configure how long the teaser will be %teaser). The teaser can be changed if you don't like what Drupal grabs.
"; $output .= "
The Body
The main text that comprises your content.
"; $output .= "
A Type
What kind of node is this? Blog, book, forum, comment, unextended, etc.
"; $output .= "
An Author
The author's name. It will either be \"anonymous\" or a valid user. You cannot set it to an arbitrary value.
"; $output .= "
Authored on
The date the node was written.
"; $output .= "
Changed
The last time this node was changed.
"; $output .= "
Static on front page
The front page is configured to show the teasers from only a few of the total nodes you have on your site (To configure how many teasers %teaser), but if you think a node is important enough that you want it to stay on the front page enable this.
"; $output .= "
Allow user comments
A node can have comments. These comments can be written by other users (Read-write), or only by admins (Read-only).
"; $output .= "
Attributes
A way to sort nodes.
"; $output .= "
Revisions
Drupal has a revision system so that you can \"roll back\" to an older version of a post if the new version is not what you want.
"; $output .= "
Promote to front page
To get people to look at the new stuff on your site you can choose to move it to the front page.
"; $output .= "
In moderation queue
Drupal has a moderation system. If it is active, a node is in one of three states: approved and published, approved and unpublished, and awaiting approval. If you are moderating a node it should be in the moderation queue.
"; $output .= "
Votes
If you are moderating a node this counts how many votes the node has gotten. Once a node gets a certain number of vote if will either be approved or dropped."; $output .= "
Score
The score of the node is gotten by the votes it is given.
"; $output .= "
Users
The list of users who have voted on a moderated node.
"; $output .= "
Published
When using Drupal's moderation system a node remains unpublished -- unavaliable to non-moderators -- until it is marked Published.
"; $output .= "

Now that you know what is in a node, here are some of the types of nodes available.

"; $output = t($output, array("%teaser" => l(t("click here"), "admin/system/modules/node"))); if ($mod == "admin") { foreach (module_list() as $name) { if (module_hook($name, "node") && $name != "node") { $output .= "

". t("Node type: %module", array("%module" => module_invoke($name, "node", "name"))) ."

"; $output .= module_invoke($name, "node", "description"); } } } break; case 'admin/system/modules#description': $output = t("The core that allows content to be submitted to the site."); break; case 'admin/system/modules/node': $output = t("Settings for the core of Drupal. Almost everything is a node so these settings will affect most of the site."); break; case 'admin/node': $output = t("Below is a list of all of the nodes in your site. Other forms of content are listed elsewhere (e.g. %comments).
Clicking a title views that node, while clicking an author's name edits their user information.
Other node-related tasks are available from the menu on the left.", array("%comments" => l(t("comments"), "admin/comment"))); break; case 'admin/node/search': $output = t("Enter a simple pattern to search for a post. This can include the wildcard character *.
For example, a search for \"br*\" might return \"bread bakers\", \"our daily bread\" and \"brenda\"."); break; case 'admin/node/settings': $output = t("This page lets you set the defaults used during creation of nodes for all the different node types.
comment: Read/write setting for comments.
publish: Is this node publicly viewable, has it been published?
promote: Is this node to be promoted to the front page?
moderate: Does this node need approval before it can be viewed?
static: Is this node always visible on the front page?
revision: Will this node go into the revision system allowing multiple versions to be saved?"); break; } return $output; } function node_help_page() { print theme("page", node_help()); } /* ** Accepts a DB result object which can be used to fetch node objects. ** Returns an HTML list suitable as content for a block. */ function node_title_list($result, $title = NULL) { while ($node = db_fetch_object($result)) { $number = module_invoke("comment", "num_all", $node->nid); $items[] = l($node->title, "node/view/$node->nid", array("title" => format_plural($number, "%count comment", "%count comments"))); } return theme("node_list", $items, $title); } function theme_node_list($items, $title = NULL) { return theme("item_list", $items, $title); } // Update the 'last viewed' timestamp of the specified node for current user. function node_tag_new($nid) { global $user; if ($user->uid) { $result = db_query("SELECT timestamp FROM {history} WHERE uid = %d AND nid = %d", $user->uid, $nid); if (db_fetch_object($result)) { db_query("UPDATE {history} SET timestamp = %d WHERE uid = %d AND nid = %d", time(), $user->uid, $nid); } else { db_query("INSERT INTO {history} (uid, nid, timestamp) VALUES (%d, %d, %d)", $user->uid, $nid, time()); } } } /* ** Retrieves the timestamp at which the current user last viewed the ** specified node. */ function node_last_viewed($nid) { global $user; $history = db_fetch_object(db_query("SELECT timestamp FROM {history} WHERE uid = '$user->uid' AND nid = %d", $nid)); return ($history->timestamp ? $history->timestamp : 0); } /** * Determines whether the supplied timestamp is newer than the user's last view * of a given node * * @param $nid node-id twhose history supplies the 'last viewed' timestamp * @param $timestamp time which is compared against node's 'last veiwed' * timestamp */ function node_is_new($nid, $timestamp) { global $user; static $cache; if (!isset($cache[$nid])) { if ($user->uid) { $history = db_fetch_object(db_query("SELECT timestamp FROM {history} WHERE uid = %d AND nid = %d", $user->uid, $nid)); $cache[$nid] = $history->timestamp ? $history->timestamp : 0; } else { $cache[$nid] = time(); } } if ($timestamp > $cache[$nid]) { return 1; } else { return 0; } } function node_teaser($body) { $size = variable_get("teaser_length", 600); /* ** If the size is zero, teasers are disabled so we ** return the entire body. */ if ($size == 0) { return $body; } /* ** If a valid delimiter has been specified, use it to ** chop of the teaser. The delimiter can be outside ** the allowed range but no more than a factor two. */ $delimiter = strpos($body, ""); if ($delimiter > 0) { return substr($body, 0, $delimiter); } /* ** If we have a short body, return the entire body: */ if (strlen($body) < $size) { return $body; } /* ** In some cases no delimiter has been specified (eg. ** when posting using the Blogger API) in which case ** we try to split at paragraph boundaries. */ if ($length = strpos($body, "

", $size)) { return substr($body, 0, $length + 4); } if ($length = strpos($body, "
", $size)) { return substr($body, 0, $length); } if ($length = strpos($body, "
", $size)) { return substr($body, 0, $length); } if ($length = strpos($body, "\n", $size)) { return substr($body, 0, $length); } /* ** When even the first paragraph is too long, try to ** split at the end of the next sentence. */ if ($length = strpos($body, ". ", $size)) { return substr($body, 0, $length + 1); } if ($length = strpos($body, "! ", $size)) { return substr($body, 0, $length + 1); } if ($length = strpos($body, "? ", $size)) { return substr($body, 0, $length + 1); } /* ** Nevermind, we split it the hard way ... */ return substr($body, 0, $size); } function node_invoke(&$node, $hook, $a2 = NULL, $a3 = NULL, $a4 = NULL) { if (is_array($node)) { $function = $node["type"] ."_$hook"; } else if (is_object($node)) { $function = $node->type ."_$hook"; } else if (is_string($node)) { $function = $node ."_$hook"; } if (function_exists($function)) { return ($function($node, $a2, $a3, $a4)); } } function node_invoke_nodeapi(&$node, $op, $arg = 0) { $return = array(); foreach (module_list() as $name) { $function = $name ."_nodeapi"; if (function_exists($function)) { $result = $function($node, $op, $arg); if (isset($result)) { $return = array_merge($return, $result); } } } return $return; } function node_load($conditions, $revision = -1) { /* ** Turn the conditions into a query: */ foreach ($conditions as $key => $value) { $cond[] = "n.". check_query($key) ." = '". check_query($value) ."'"; } /* ** Retrieve the node: */ $node = db_fetch_object(db_query("SELECT n.*, u.uid, u.name FROM {node} n INNER JOIN {users} u ON u.uid = n.uid WHERE ". implode(" AND ", $cond))); /* ** Unserialize the revisions field: */ if ($node->revisions) { $node->revisions = unserialize($node->revisions); } /* ** Call the node specific callback (if any) and piggy-back the ** results to the node or overwrite some values: */ if ($extra = node_invoke($node, "load")) { foreach ($extra as $key => $value) { $node->$key = $value; } } /* ** Return the desired revision */ if ($revision != -1 && isset($node->revisions[$revision])) { $node = $node->revisions[$revision]["node"]; } return $node; } function node_save($node) { /* ** Fetch fields to save to node table: */ $fields = node_invoke_nodeapi($node, "fields"); /* ** Serialize the revisions field: */ if ($node->revisions) { $node->revisions = serialize($node->revisions); } /* ** Apply filters to some default node fields: */ if (empty($node->nid)) { /* ** Insert a new node: */ // Set some required fields: if (!$node->created) { $node->created = time(); } $node->changed = time(); $node->nid = db_next_id("{node}_nid"); // Prepare the query: foreach ($node as $key => $value) { if (in_array($key, $fields)) { $k[] = check_query($key); $v[] = $value; $s[] = "'%s'"; } } $keysfmt = implode(", ", $s); // need to quote the placeholders for the values $valsfmt = "'". implode("', '", $s) ."'"; // Insert the node into the database: db_query("INSERT INTO {node} (". implode(", ", $k) .") VALUES(". implode(", ", $s) .")", $v); // Call the node specific callback (if any): node_invoke($node, "insert"); node_invoke_nodeapi($node, "insert"); } else { /* ** Update an existing node: */ // Set some required fields: $node->changed = time(); // Prepare the query: foreach ($node as $key => $value) { if (in_array($key, $fields)) { $q[] = check_query($key) ." = '%s'"; $v[] = $value; } } // Update the node in the database: db_query("UPDATE {node} SET ". implode(", ", $q) ." WHERE nid = '$node->nid'", $v); // Call the node specific callback (if any): node_invoke($node, "update"); node_invoke_nodeapi($node, "update"); } /* ** Clear the cache so an anonymous poster can see the node being ** added or updated. */ cache_clear_all(); /* ** Return the node ID: */ return $node->nid; } function node_view($node, $main = 0, $page = 0) { $node = array2object($node); /* ** Remove the delimiter (if any) that seperates the teaser from the ** body. TODO: this strips legitimate uses of '' also. */ $node->body = str_replace("", "", $node->body); /* ** The "view" hook can be implemented to overwrite the default function ** to display nodes. */ if (module_hook($node->type, "view")) { return node_invoke($node, "view", $main, $page); } else { /* ** Default behavior: */ return theme("node", node_prepare($node), $main, $page); } } function node_prepare($node) { if ($node->teaser == $node->body) { // Only invoke check_output() once for performance's sake: $node->teaser = $node->body = check_output($node->teaser); } else { $node->teaser = check_output($node->teaser); $node->body = check_output($node->body); } return $node; } function node_show($node, $cid) { if (node_access("view", $node)) { $output = node_view($node, 0, 1); if (function_exists("comment_render") && $node->comment) { $output .= comment_render($node, $cid); } /* ** Update the history table, stating that this user viewed this node. */ node_tag_new($node->nid); return $output; } else { drupal_set_message(message_access()); } } function node_access($op, $node = 0) { if (user_access("administer nodes")) { return 1; } /* ** Convert the node to an object if necessary: */ $node = array2object($node); /* ** Construct a function: */ if ($node->type) { $type = $node->type; } else { $type = $node; } // Can't use node_invoke: // the access hook takes the $op parameter before the $node parameter. return module_invoke($type, "access", $op, $node); } function node_perm() { return array("administer nodes", "access content"); } function node_search($keys) { // Return the results of performing a search using the indexed search // for this particular type of node. // // Pass an array to the "do_search" function which dictates what it // will search through, and what it will search for // // "keys"'s value is the keywords entered by the user // // "type"'s value is used to identify the node type in the search // index. // // "select"'s value is used to relate the data from the specific nodes // table to the data that the search_index table has in it, and the the // do_search functino will rank it. // // The select must always provide the following fields - lno, title, // created, uid, name, count // $find = do_search(array("keys" => $keys, "type" => "node", "select" => "select s.lno as lno, n.title as title, n.created as created, u.uid as uid, u.name as name, s.count as count FROM {search_index} s, {node} n INNER JOIN {users} u ON n.uid = u.uid WHERE s.lno = n.nid AND s.type = 'node' AND s.word like '%' AND n.status = 1")); return $find; } function node_settings() { $output .= form_select(t("Number of posts on main page"), "default_nodes_main", variable_get("default_nodes_main", 10), array(1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, 10 => 10, 15 => 15, 20 => 20, 25 => 25, 30 => 30), t("The default maximum number of posts to display per page on overview pages such as the main page.")); $output .= form_select(t("Length of trimmed posts"), "teaser_length", variable_get("teaser_length", 600), array(0 => t("Unlimited"), 200 => t("200 characters"), 400 => t("400 characters"), 600 => t("600 characters"), 800 => t("800 characters"), 1000 => t("1000 characters"), 1200 => t("1200 characters"), 1400 => t("1400 characters"), 1600 => t("1600 characters"), 1800 => t("1800 characters"), 2000 => t("2000 characters")), t("The maximum number of characters used in the trimmed version of a post. Drupal will use this setting to determine at which offset long posts should be trimmed. The trimmed version of a post is typically used as a teaser when displaying the post on the main page, in XML feeds, etc. To disable teasers, set to 'Unlimited'.")); $output .= form_radios(t("Preview post"), "node_preview", variable_get("node_preview", 0), array(t("Optional"), t("Required")), t("Must users preview posts before submitting?")); return $output; } function node_comment_mode($nid) { static $comment_mode; if (!isset($comment_mode[$nid])) { $comment_mode[$nid] = db_result(db_query("SELECT comment FROM {node} WHERE nid = %d", $nid)); } return $comment_mode[$nid]; } function node_link($type, $node = 0, $main = 0) { $links = array(); if ($type == "node") { if ($node->links) { $links = $node->links; } if ($main == 1 && $node->teaser && strlen($node->teaser) != strlen($node->body)) { $links[] = l(t("read more"), "node/view/$node->nid", array("title" => t("Read the rest of this posting."), "class" => "read-more")); } if (user_access("administer nodes")) { $links[] = l(t("administer"), "admin/node/edit/$node->nid", array("title" => t("Administer this node."))); } if (user_access("administer nodes") && $node->revisions) { $links[] = l(t("revisions"), "node/revisions/$node->nid", array("title" => t("Administer revisions."))); } } if ($type == "system") { menu("node/add", t("create content"), 'node_page', 1, MENU_HIDE_NOCHILD); if (user_access("administer nodes")) { menu("admin/node", t("content"), "node_admin"); menu("admin/node/search", t("search"), "node_admin", 8); menu("admin/node/help", t("help"), "node_help_page", 9); menu("admin/node/edit", t("edit post"), "node_admin", 0, MENU_HIDE); menu("admin/node/settings", t("settings"), "node_admin", 8); } if (user_access("access content")) { menu("node", t("content"), "node_page", 0, MENU_HIDE); } } return $links; } function node_admin_edit($node) { if (is_numeric($node)) { $node = node_load(array("nid" => $node)); } $output .= node_form($node); /* ** Display the node form extensions: */ $output .= implode("\n", module_invoke_all("node_link", $node)); return $output; } function node_admin_nodes() { $filters = array( array(t("View posts that are new or updated"), "ORDER BY n.changed DESC"), array(t("View posts that need approval"), "WHERE n.status = 0 OR n.moderate = 1 ORDER BY n.changed DESC"), array(t("View posts that are promoted"), "WHERE n.status = 1 AND n.promote = 1 ORDER BY n.changed DESC"), array(t("View posts that are not promoted"), "WHERE n.status = 1 AND n.promote = 0 ORDER BY n.changed DESC"), array(t("View posts that are static"), "WHERE n.status = 1 AND n.static = 1 ORDER BY n.changed DESC"), array(t("View posts that are unpublished"), "WHERE n.status = 0 AND n.moderate = 0 ORDER BY n.changed DESC") ); $operations = array( array(t("Approve the selected posts"), "UPDATE {node} SET status = 1, moderate = 0 WHERE nid = %d"), array(t("Promote the selected posts"), "UPDATE {node} SET status = 1, promote = 1 WHERE nid = %d"), array(t("Make the selected posts static"), "UPDATE {node} SET status = 1, static = 1 WHERE nid = %d"), array(t("Demote the selected posts"), "UPDATE {node} SET promote = 0 WHERE nid = %d"), array(t("Unpublish the selected posts"), "UPDATE {node} SET status = 0 WHERE nid = %d") ); /* ** Handle operations: */ if (empty($_SESSION["node_overview_filter"])) { $_SESSION["node_overview_filter"] = 0; } if (isset($_POST["edit"]["filter"])) { $_SESSION["node_overview_filter"] = $_POST["edit"]["filter"]; } if (isset($_POST["edit"]["operation"])) { $operation = $operations[$_POST["edit"]["operation"]][1]; foreach ($_POST["edit"]["status"] as $nid => $value) { if ($value) { db_query($operation, $nid); } } drupal_set_message(t("the update has been performed.")); } $filter = $_SESSION["node_overview_filter"]; /* ** Render filter form: */ $options = array(); foreach ($filters as $key => $value) { $options[] = $value[0]; } $form = form_select(NULL, "filter", $filter, $options); $form .= form_submit(t("Go")); $output .= "

". t("Filter options") ."

"; $output .= "
$form
"; /* ** Render operations form: */ $options = array(); foreach ($operations as $key => $value) { $options[] = $value[0]; } $form = form_select(NULL, "operation", 0, $options); $form .= form_submit(t("Go")); $output .= "

". t("Update options") ."

"; $output .= "
$form
"; /* ** Overview table: */ $result = pager_query("SELECT n.*, u.name, u.uid FROM {node} n INNER JOIN {users} u ON n.uid = u.uid ". $filters[$filter][1], 50); $header = array(NULL, t("title"), t("type"), t("author"), t("status"), array("data" => t("operations"), "colspan" => 2)); while ($node = db_fetch_object($result)) { $rows[] = array(form_checkbox(NULL, "status][$node->nid", 1, 0), l($node->title, "node/view/$node->nid") ." ". (node_is_new($node->nid, $node->changed) ? theme_mark() : ""), module_invoke($node->type, "node", "name"), format_name($node), ($node->status ? t("published") : t("not published")), l(t("edit node"), "admin/node/edit/$node->nid"), l(t("delete node"), "admin/node/delete/$node->nid")); } if ($pager = theme("pager", NULL, 50, 0)) { $rows[] = array(array("data" => $pager, "colspan" => 7)); } $output .= "

". $filters[$filter][0] ."

"; $output .= theme("table", $header, $rows); return form($output); } function node_admin_settings($edit) { $op = $_POST["op"]; if ($op == t("Save configuration")) { /* ** Save the configuration options: */ foreach ($edit as $name => $value) { variable_set($name, $value); } drupal_set_message(t("the content settings have been saved.")); } if ($op == t("Reset to defaults")) { /* ** Reset the configuration options to their default value: */ foreach ($edit as $name => $value) { variable_del($name); } drupal_set_message(t("the content settings have been reset to their default values.")); } $header = array_merge(array(t("type")), array_keys(node_invoke_nodeapi($node, "settings"))); foreach (module_list() as $name) { if (module_hook($name, "node")) { $node->type = $name; $cols = array(); foreach (node_invoke_nodeapi($node, "settings") as $setting) { $cols[] = array("data" => $setting, "align" => "center", "width" => 55); } $rows[] = array_merge(array(module_invoke($name, "node", "name")), $cols); } } $output .= theme("table", $header, $rows); /* This is an idea for the future. foreach (module_list() as $name) { if (module_hook($name, "node")) { $node->type = $name; // Create theme("table", ) data: $header = array_keys(node_invoke_nodeapi($node, "settings")); $cols = array(); foreach (node_invoke_nodeapi($node, "settings") as $setting) { $cols[] = array("data" => $setting, "align" => "center", "width" => 75); } $output .= "

". module_invoke($name, "node", "name") ."

"; $output .= theme("table", $header, array($cols)); $output .= "

"; } } */ $output .= form_submit(t("Save configuration")); $output .= form_submit(t("Reset to defaults")); return form($output); } function node_revision_overview($nid) { if (user_access("administer nodes")) { $node = node_load(array("nid" => $nid)); if ($node->revisions) { $header = array(t("older revisions"), array("colspan" => "3", "data" => t("operations"))); foreach ($node->revisions as $key => $revision) { $rows[] = array(t("revision #%r revised by %u on %d", array("%r" => $key, "%u" => format_name(user_load(array("uid" => $revision["uid"]))), "%d" => format_date($revision["timestamp"], "small"))) . ($revision["history"] ? "
". $revision["history"] ."" : ""), l(t("view"), "node/view/$node->nid", array(), "revision=$key"), l(t("rollback"), "node/rollback-revision/$node->nid/$key"), l(t("delete"), "node/delete-revision/$node->nid/$key")); } $output .= theme("table", $header, $rows); } } return $output; } /* ** Return the revision with the specified revision number. */ function node_revision_load($node, $revision) { return $node->revisions[$revision]["node"]; } /* ** Create and return a new revision of the given node. */ function node_revision_create($node) { global $user; /* ** 'revision' is the name of the field used to indicicate that we ** have to create a new revision of a node. */ if ($node->nid && $node->revision) { $prev = node_load(array("nid" => $node->nid)); $node->revisions = $prev->revisions; unset($prev->revisions); $node->revisions[] = array("uid" => $user->uid, "timestamp" => time(), "node" => $prev, "history" => $node->history); } return $node; } /* ** Roll-back to the revision with the specified revision number. */ function node_revision_rollback($nid, $revision) { global $user; if (user_access("administer nodes")) { $node = node_load(array("nid" => $nid)); /* ** Extract the specified revision: */ $rev = $node->revisions[$revision]["node"]; /* ** Inherit all the past revisions: */ $rev->revisions = $node->revisions; /* ** Save the original/current node: */ $rev->revisions[] = array("uid" => $user->uid, "timestamp" => time(), "node" => $node); /* ** Remove the specified revision: */ unset($rev->revisions[$revision]); /* ** Save the node: */ foreach ($node as $key => $value) { $filter[] = $key; } node_save($rev, $filter); drupal_set_message(t("rollbacked to revision #%revision of '%title'", array("%revision" => $revision, "%title" => $node->title))); } } /* ** Delete the revision with specified revision number. */ function node_revision_delete($nid, $revision) { if (user_access("administer nodes")) { $node = node_load(array("nid" => $nid)); unset($node->revisions[$revision]); node_save($node, array("nid", "revisions")); drupal_set_message(t("deleted revision #%revision of '%title'", array("%revision" => $revision, "%title" => $node->title))); } } /* ** Return a list of all the existing revision numbers. */ function node_revision_list($node) { if (is_array($node->revisions)) { return array_keys($node->revisions); } else { return array(); } } function node_admin() { $op = $_POST["op"]; $edit = $_POST["edit"]; if (user_access("administer nodes")) { if (empty($op)) { $op = arg(2); } /* ** Compile a list of the administrative links: */ switch ($op) { case "search": $output = search_type("node", url("admin/node/search"), $_POST["keys"]); break; case "edit": $output = node_admin_edit(arg(3)); break; case "delete": $output = node_delete(array("nid" => arg(3))); break; case t("Preview"): $edit = node_validate($edit, $error); $output = node_preview($edit, $error); break; case t("Submit"): $output = node_submit($edit); break; case t("Delete"): $output = node_delete($edit); break; case t("Save configuration"): case t("Reset to defaults"): case "settings": $output = node_admin_settings($edit); break; default: $output = node_admin_nodes(); } print theme("page", $output); } else { print theme("page", message_access()); } } function node_block($op = "list", $delta = 0) { if ($op == "list") { $blocks[0]["info"] = t("Syndicate"); return $blocks; } else { $block["subject"] = t("Syndicate"); $block["content"] = "
". l("\"XML\"", "node/feed", array("title" => t("Read the XML version of this page."))) ."
"; return $block; } } function node_feed($nodes = 0, $channel = array()) { global $base_url, $languages; /* ** A generic function for generating RSS feeds from a set of nodes. ** - $nodes should be an object as returned by db_query() which contains ** the nid field. ** - $channel is an associative array containing title, link, and ** description keys. */ if (!$nodes) { $nodes = db_query_range("SELECT nid FROM {node} WHERE promote = '1' AND status = '1' ORDER BY created DESC", 0, 15); } while ($node = db_fetch_object($nodes)) { /* ** Load the specified node: */ $item = node_load(array("nid" => $node->nid)); $link = url("node/view/$node->nid"); $items .= format_rss_item($item->title, $link, ($item->teaser ? $item->teaser : $item->body), array("pubDate" => date("r", $item->changed))); } $output .= "\n"; $output .= "]>\n"; if (!$channel["version"]) $channel["version"] = "0.92"; if (!$channel["title"]) $channel["title"] = variable_get("site_name", "drupal") ." - ". variable_get("site_slogan", ""); if (!$channel["link"]) $channel["link"] = $base_url; if (!$channel["description"]) $channel["description"] = variable_get("site_mission", ""); foreach ($languages as $key => $value) break; if (!$channel["language"]) $channel["language"] = $key ? $key : "en"; $output .= "\n"; $output .= format_rss_channel($channel["title"], $channel["link"], $channel["description"], $items, $channel["language"]); $output .= "\n"; header("Content-Type: text/xml"); print $output; } function node_validate($node, &$error) { global $user; $error = array(); /* ** Convert the node to an object if necessary: */ $node = array2object($node); /* ** Validate the title field: */ if (isset($node->title)) { $node->title = strip_tags($node->title); if (!$node->title) { $error["title"] = theme("error", t("You have to specify a valid title.")); } } /* ** Common default values: */ $node->teaser = node_teaser($node->body); /* ** Create a new revision when required: */ $node = node_revision_create($node); if (user_access("administer nodes")) { /* ** Setup default values if required: */ if (!$node->created) { $node->created = time(); } if (!$node->date) { $node->date = date("M j, Y g:i a", $node->created); } if (!is_numeric($node->status)) { $node->status = 1; } /* ** Validate the "authored by"-field: */ if (empty($node->name) || empty($node->uid)){ /* ** The use of empty() is mandatory in the context of usernames ** as the empty string denotes the anonymous user. In case we ** are dealing with an anomymous user we set the user ID to 0. */ $node->uid = 0; } else if ($account = user_load(array("name" => $node->name))) { $node->uid = $account->uid; } else { $error["name"] = theme("error", t("The name '%u' does not exist.", array ("%u" => $node->name))); } /* ** Validate the "authored on"-field: */ if (strtotime($node->date) > 1000) { $node->created = strtotime($node->date); } else { $error["date"] = theme("error", t("You have to specifiy a valid date.")); } } else { // Validate for normal users: $node->uid = $user->uid ? $user->uid : 0; // Force defaults in case people modify the form: $node->status = variable_get("node_status_$node->type", 1); $node->promote = variable_get("node_promote_$node->type", 1); $node->moderate = variable_get("node_moderate_$node->type", 0); $node->static = variable_get("node_static_$node->type", 0); $node->revision = variable_get("node_revision_$node->type", 0); unset($node->created); } /* ** Do node type specific validation checks. */ $result = node_invoke($node, "validate"); $error = $error + (is_array($result) ? $result : array()) + node_invoke_nodeapi($node, "validate"); return $node; } function node_form($edit, $error = NULL) { /* ** Validate the node: */ if ($error === NULL) { /* Only validate if we don't already know the errors. */ $edit = node_validate($edit, $error); } // Prepend extra node form: $form = implode("", node_invoke_nodeapi($edit, "form pre", $error)); // Get the node specific bits: // Can't use node_invoke: // $error and $param must be passed by reference. $function = $edit->type ."_form"; if (function_exists($function)) { $form .= $function($edit, $help, $error, $param); } // Append extra node form: $form .= implode("", node_invoke_nodeapi($edit, "form post", $error)); /* ** Add the help text: */ if ($help) { $output .= "

$help

"; } $output .= "
"; /* ** Add the admin specific parts: */ if (user_access("administer nodes")) { $output .= "
"; $author = form_textfield(t("Authored by"), "name", $edit->name, 20, 60, $error["name"]); $author .= form_textfield(t("Authored on"), "date", $edit->date, 20, 25, $error["date"]); $output .= "
"; $output .= form_group(t("Authoring information"), $author); $output .= "
\n"; $options .= form_checkbox(t("Published"), "status", 1, isset($edit->status) ? $edit->status : variable_get("node_status_$edit->type", 1)); $options .= form_checkbox(t("In moderation queue"), "moderate", 1, isset($edit->moderate) ? $edit->moderate : variable_get("node_moderate_$edit->type", 0)); $options .= form_checkbox(t("Promoted to front page"), "promote", 1, isset($edit->promote) ? $edit->promote : variable_get("node_promote_$edit->type", 1)); $options .= form_checkbox(t("Static on front page"), "static", 1, isset($edit->static) ? $edit->static : variable_get("node_static_$edit->type", 0)); $options .= form_checkbox(t("Create new revision"), "revision", 1, isset($edit->revision) ? $edit->revision : variable_get("node_revision_$edit->type", 0)); $output .= "
"; $output .= form_group(t("Options"), $options); $output .= "
\n"; $extras .= implode("
", node_invoke_nodeapi($edit, "form admin")); $output .= $extras ? "
$extras
" : "
"; } /* ** Add the default fields: */ $output .= "
"; $output .= form_textfield(t("Title"), "title", $edit->title, 60, 128, $error["title"]); /* ** Add the node specific fields: */ $output .= $form; /* ** Add the hidden fields: */ if ($edit->nid) { $output .= form_hidden("nid", $edit->nid); } if (isset($edit->uid)) { /* ** The use of isset() is mandatory in the context of user IDs as uid ** 0 denotes the anonymous user. */ $output .= form_hidden("uid", $edit->uid); } if ($edit->created) { $output .= form_hidden("created", $edit->created); } $output .= form_hidden("type", $edit->type); /* ** Add the buttons: */ $output .= form_submit(t("Preview")); if (!$error) { if ($edit->title && $edit->type) { $output .= form_submit(t("Submit")); } elseif (!variable_get("node_preview", 0)) { $output .= form_submit(t("Submit")); } } if ($edit->nid && node_access("delete", $edit)) { $output .= form_submit(t("Delete")); } $output .= "
"; return form($output, ($param["method"] ? $param["method"] : "post"), $param["action"], array_merge($param["options"], array("id" => "node-form"))); } function node_add($type) { global $user; $edit = $_POST["edit"]; /* ** If a node type has been specified, validate it existence. If no ** (valid) node type has been provied, display a node type overview. */ if ($type && node_access("create", $type)) { // Initialize settings: $node = array("uid" => $user->uid, "name" => $user->name, "type" => $type); /* ** Allow the following fields to be initialized via $_GET (eg. for use ** with a "blog it" bookmarklet): */ foreach (array("title", "teaser", "body") as $field) { if ($_GET["edit"][$field]) { $node[$field] = $_GET["edit"][$field]; } } $output = node_form($node); drupal_set_breadcrumb(array(l(t("Home"), NULL), l(t("create content"), "node/add"))); } else { /* ** Compile a list with the different node types and their explanation: */ foreach (module_list() as $name) { if (module_hook($name, "node") && node_access("create", $name)) { $output .= "
  • "; $output .= " ". l(module_invoke($name, "node", "name"), "node/add/$name", array("title" => t("Add a new %s.", array("%s" => module_invoke($name, "node", "name"))))); $output .= "
    ". module_invoke($name, "node", "description") ."
    "; $output .= "
  • "; } } $output = t("Choose the appropriate item from the list:") .""; drupal_set_breadcrumb(array(l(t("Home"), NULL))); } return $output; } function node_edit($id) { global $user; $node = node_load(array("nid" => $id)); if (node_access("update", $node)) { $output = node_form($node); } else { $output = message_access(); } return $output; } function node_preview($node, $error = NULL) { /* ** Convert the array to an object: */ $node = array2object($node); if (node_access("create", $node) || node_access("update", $node)) { /* ** Load the user's name when needed: */ if (isset($node->name)) { /* ** The use of isset() is mandatory in the context of user IDs as uid ** 0 denotes the anonymous user. */ if ($user = user_load(array("name" => $node->name))) { $node->uid = $user->uid; } else { $node->uid = 0; // anonymous user } } else if ($node->uid) { $user = user_load(array("uid" => $node->uid)); $node->name = $user->name; } /* ** Set the created time when needed: */ if (empty($node->created)) { $node->created = time(); } $node->changed = time(); /* ** Extract a teaser: */ $node->teaser = node_teaser($node->body); /* ** Apply the required filters: */ if ($node->nid) { $view = array2object(array_merge(object2array($node), module_invoke($node->type, "save", "update", $node))); } else { $view = array2object(array_merge(object2array($node), module_invoke($node->type, "save", "create", $node))); } /* ** Display a preview of the node: */ if ($view->teaser && $view->teaser != $view->body) { $output = "

    ". t("Preview trimmed version") ."

    "; $output .= node_view($view, 1); $output .= "

    ". t("The trimmed version of your post shows how your post looks like when promoted to the main page or when exported for syndication. You can insert a delimiter '<!--break-->' (without the quotes) to fine-tune where your post gets split.") ."

    "; $output .= "

    ". t("Preview full version") ."

    "; $output .= node_view($view, 0); } else { $output .= node_view($view, 0); } $output .= node_form($node, $error); $name = module_invoke($node->type, "node", "name"); drupal_set_breadcrumb(array(l(t("Home"), NULL), l(t("create content"), "node/add"), l(t("Submit %name", array("%name" => $name)), "node/add/$node->type"))); return $output; } } function node_submit($node) { global $user; /* ** Fixup the node when required: */ $node = node_validate($node, $error); /* ** If something went wrong, go back to the preview form: */ if ($error) { return node_preview($node, $error); } /* ** Prepare the node's body: */ if ($node->nid) { /* ** Check whether the current user has the proper access rights to ** perform this operation: */ if (node_access("update", $node)) { $node->nid = node_save($node); watchdog("special", "$node->type: updated '$node->title'", l(t("view post"), "node/view/$node->nid")); $msg = t("the %name was updated.", array ("%name" => module_invoke($node->type, "node", "name"))); } } else { /* ** Check whether the current user has the proper access rights to ** perform this operation: */ if (node_access("create", $node)) { /* ** Verify a user's submission rate and avoid duplicate nodes being ** inserted: */ throttle("node", variable_get("max_node_rate", 900)); $node->nid = node_save($node); watchdog("special", "$node->type: added '$node->title'", l(t("view post"), "node/view/$node->nid")); $msg = t("your %name was created.", array ("%name" => module_invoke($node->type, "node", "name"))); } } $node = node_load(array("nid" => $node->nid)); drupal_set_message($msg); drupal_set_title($node->title); return node_show($node, NULL); } function node_delete($edit) { $node = node_load(array("nid" => $edit["nid"])); if (node_access("delete", $node)) { if ($edit["confirm"]) { /* ** Delete the specified node: */ db_query("DELETE FROM {node} WHERE nid = '$node->nid'"); /* ** Call the node specific callback (if any): */ node_invoke($node, "delete"); node_invoke_nodeapi($node, "delete"); /* ** Clear the cache so an anonymous poster can see the node being ** deleted. */ cache_clear_all(); watchdog("special", "$node->type: deleted '$node->title'"); $output = t("The node has been deleted."); } else { $output .= form_item(t("Confirm deletion"), $node->title); $output .= form_hidden("nid", $node->nid); $output .= form_hidden("confirm", 1); $output .= form_submit(t("Delete")); $output = form($output); } } return $output; } function node_page() { global $id, $user, $or, $and; $op = $_POST["op"]; $edit = $_POST["edit"]; if (user_access("access content")) { if (empty($op)) { $op = arg(1); } if ($op == "feed") { node_feed(); return; } if ($op == "view") { $node = node_load(array("nid" => arg(2), "status" => 1), $_GET["revision"]); } $name = module_invoke(arg(2), "node", "name"); switch ($op) { case "add": print theme("page", node_add(arg(2)), arg(2) ? t("Submit %name", array("%name" => $name)) : t("create content")); break; case "edit": print theme("page", node_edit(arg(2)), t("Edit %name", array("%name" => $name))); break; case "view": print theme("page", node_show($node, arg(3)), $node->title); break; case "revisions": print theme("page", node_revision_overview(arg(2)), t("Revisions")); break; case "rollback-revision": node_revision_rollback(arg(2), arg(3)); print theme("page", node_revision_overview(arg(2)), t("Revisions")); break; case "delete-revision": node_revision_delete(arg(2), arg(3)); print theme("page", node_revision_overview(arg(2)), t("Revisions")); break; case t("Preview"): $edit = node_validate($edit, $error); print theme("page", node_preview($edit, $error), t("Preview %name", array("%name" => $name))); break; case t("Submit"): drupal_set_title(t("Submit %name", array("%name" => $name))); print theme("page", node_submit($edit)); break; case t("Delete"): print theme("page", node_delete($edit), t("Delete %name", array("%name" => $name))); break; default: $output = ""; $result = pager_query("SELECT nid, type FROM {node} WHERE promote = '1' AND status = '1' ORDER BY static DESC, created DESC", variable_get("default_nodes_main", 10)); while ($node = db_fetch_object($result)) { $output .= node_view(node_load(array("nid" => $node->nid, "type" => $node->type)), 1); } $output .= theme('pager', NULL, variable_get("default_nodes_main", 10)); print theme("page", $output, ""); } } else { print theme("page", message_access()); } } function node_update_index() { // Return an array of values to dictate how to update the search index // for this particular type of node. // // "last_update"'s value is used with variable_set to set the // last time this node type had an index update run. // // "node_type"'s value is used to identify the node type in the search // index. // // "select"'s value is used to select the node id and text fields from // the table we are indexing. In this case, we also check against the // last run date for the nodes update. return array("last_update" => "node_cron_last", "node_type" => "node", "select" => "SELECT n.nid as lno, n.title as text1, n.body as text2 FROM {node} n WHERE n.status = 1 AND moderate = 0 and (created > " . variable_get("node_cron_last", 1) . " or changed > " . variable_get("node_cron_last", 1) . ")"); } function node_nodeapi(&$node, $op, $arg = 0) { switch ($op) { case "settings": $output[t("publish")] = form_checkbox("", "node_status_$node->type", 1, variable_get("node_status_$node->type", 1)); $output[t("promote")] = form_checkbox("", "node_promote_$node->type", 1, variable_get("node_promote_$node->type", 1)); $output[t("moderate")] = form_checkbox("", "node_moderate_$node->type", 1, variable_get("node_moderate_$node->type", 0)); $output[t("static")] = form_checkbox("", "node_static_$node->type", 1, variable_get("node_static_$node->type", 0)); $output[t("revision")] = form_checkbox("", "node_revision_$node->type", 1, variable_get("node_revision_$node->type", 0)); return $output; case "fields": return array("nid", "uid", "type", "title", "teaser", "body", "revisions", "status", "promote", "moderate", "static", "created", "changed"); } } ?>