1589 lines
47 KiB
Plaintext
1589 lines
47 KiB
Plaintext
<?php
|
|
// $Id$
|
|
|
|
define('NODE_NEW_LIMIT', time() - 30 * 24 * 60 * 60);
|
|
|
|
function node_help($section = 'admin/help#node') {
|
|
global $mod;
|
|
$output = '';
|
|
|
|
switch ($section) {
|
|
|
|
case 'admin/help#node':
|
|
$output .= t("
|
|
<h3>Nodes</h3>
|
|
<p>The core of the Drupal system is the node. All of the contents of the system are placed in nodes, or extensions of nodes.
|
|
A base node contains:<dl>
|
|
<dt>A Title</dt><dd>Up to 128 characters of text that titles the node.</dd>
|
|
<dt>A Teaser</dt><dd>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 <a href=\"%teaser\">click here</a>). The teaser can be changed if you don't like what Drupal grabs.</dd>
|
|
<dt>The Body</dt><dd>The main text that comprises your content.</dd>
|
|
<dt>A Type</dt><dd>What kind of node is this? Blog, book, forum, comment, unextended, etc.</dd>
|
|
<dt>An Author</dt><dd>The author's name. It will either be \"anonymous\" or a valid user. You <i>cannot</i> set it to an arbitrary value.</dd>
|
|
<dt>Authored on</dt><dd>The date the node was written.</dd>
|
|
<dt>Changed</dt><dd>The last time this node was changed.</dd>
|
|
<dt>Static on front page</dt><dd>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 <a href=\"%teaser\">click here</a>), but if you think a node is important enough that you want it to stay on the front page enable this.</dd>
|
|
<dt>Allow user comments</dt><dd>A node can have comments. These comments can be written by other users (Read-write), or only by admins (Read-only).</dd>
|
|
<dt>Attributes</dt><dd>A way to sort nodes.</dd>
|
|
<dt>Revisions</dt><dd>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.</dd>
|
|
<dt>Promote to front page</dt><dd>To get people to look at the new stuff on your site you can choose to move it to the front page.</dd>
|
|
<dt>In moderation queue</dt><dd>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.</dd>
|
|
<dt>Votes</dt><dd>If you are moderating a node this counts how many votes the node has gotten. Once a node gets a certain number of vote it will either be approved or dropped.
|
|
<dt>Score</dt><dd>The score of the node is gotten by the votes it is given.</dd>
|
|
<dt>Users</dt><dd>The list of users who have voted on a moderated node.</dd>
|
|
<dt>Published</dt><dd>When using Drupal's moderation system a node remains unpublished -- unavaliable to non-moderators -- until it is marked Published.</dd></dl>
|
|
<p>Now that you know what is in a node, here are some of the types of nodes available.</p>", array("%teaser" => url("admin/system/modules/node")));
|
|
|
|
if ($mod == 'admin') {
|
|
foreach (node_list() as $type) {
|
|
$output .= '<h3>'. t('Node type: %module', array('%module' => node_invoke($type, 'node_name'))). '</h3>';
|
|
$output .= implode("\n", module_invoke_all('help', 'node/add#'. $type));
|
|
}
|
|
}
|
|
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. <a href=\"%comments\">comments</a>).<br />Clicking a title views that node, while clicking an author's name edits their user information.<br />Other node-related tasks are available from the menu on the left.", array('%comments' => url('admin/comment')));
|
|
break;
|
|
case 'admin/node/search':
|
|
$output = t("Enter a simple pattern to search for a post. This can include the wildcard character *.<br />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.<br /><strong>comment:</strong> Read/write setting for comments.<br /><strong>publish:</strong> Is this node publicly viewable, has it been published?<br /><strong>promote:</strong> Is this node to be promoted to the front page?<br /><strong>moderate:</strong> Does this node need approval before it can be viewed?<br /><strong>static:</strong> Is this node always visible on the front page?<br /><strong>revision:</strong> Will this node go into the revision system allowing multiple versions to be saved?');
|
|
break;
|
|
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
|
|
function node_cron() {
|
|
db_query('DELETE FROM {history} WHERE timestamp < %d', NODE_NEW_LIMIT);
|
|
}
|
|
|
|
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 : NODE_NEW_LIMIT);
|
|
}
|
|
|
|
/**
|
|
* Determines whether the supplied timestamp is newer than the user's last view
|
|
* of a given node
|
|
*
|
|
* @param $nid node-id whose history supplies the 'last viewed' timestamp
|
|
* @param $timestamp time which is compared against node's 'last viewed'
|
|
* 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();
|
|
}
|
|
}
|
|
|
|
return ($timestamp > $cache[$nid] && $timestamp > NODE_NEW_LIMIT);
|
|
}
|
|
|
|
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, '<!--break-->');
|
|
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, '</p>', $size)) {
|
|
return substr($body, 0, $length + 4);
|
|
}
|
|
|
|
if ($length = strpos($body, '<br />', $size)) {
|
|
return substr($body, 0, $length);
|
|
}
|
|
|
|
if ($length = strpos($body, '<br>', $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);
|
|
}
|
|
|
|
|
|
/*
|
|
* Determines the module that defines the node type of the given node.
|
|
*
|
|
* @param &$node
|
|
* Either a node object, node array, or a string containing the node type.
|
|
* @return
|
|
* A string containing the name of the defining module.
|
|
*/
|
|
function node_get_module_name($node) {
|
|
if (is_array($node)) {
|
|
if ($pos = strpos($node['type'], '/')) {
|
|
return substr($node['type'], 0, $pos);
|
|
} else {
|
|
return $node['type'];
|
|
}
|
|
}
|
|
else if (is_object($node)) {
|
|
if ($pos = strpos($node->type, '/')) {
|
|
return substr($node->type, 0, $pos);
|
|
} else {
|
|
return $node->type;
|
|
}
|
|
}
|
|
else if (is_string($node)) {
|
|
if ($pos = strpos($node, '/')) {
|
|
return substr($node, 0, $pos);
|
|
} else {
|
|
return $node;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Get a list of all the defined node types.
|
|
*
|
|
* @return
|
|
* An list of all node types.
|
|
*/
|
|
function node_list() {
|
|
$types = array();
|
|
foreach (module_list() as $module) {
|
|
if (module_hook($module, 'node_name')) {
|
|
$module_types = module_invoke($module, 'node_types');
|
|
if ($module_types) {
|
|
foreach ($module_types as $type) {
|
|
$types[] = $type;
|
|
}
|
|
} else {
|
|
$types[] = $module;
|
|
}
|
|
}
|
|
}
|
|
return $types;
|
|
}
|
|
|
|
/*
|
|
* Determine whether a node hook exists.
|
|
*
|
|
* @param &$node
|
|
* Either a node object, node array, or a string containing the node type.
|
|
* @param $hook
|
|
* A string containing the name of the hook.
|
|
* @return
|
|
* TRUE iff the $hook exists in the node type of $node.
|
|
*/
|
|
function node_hook(&$node, $hook) {
|
|
$function = node_get_module_name($node) ."_$hook";
|
|
|
|
return function_exists($function);
|
|
}
|
|
|
|
/*
|
|
* Invoke a node hook.
|
|
*
|
|
* @param &$node
|
|
* Either a node object, node array, or a string containing the node type.
|
|
* @param $hook
|
|
* A string containing the name of the hook.
|
|
* @param $a2, $a3, $a4
|
|
* Arguments to pass on to the hook, after the $node argument.
|
|
* @return
|
|
* The returned value of the invoked hook is returned.
|
|
*/
|
|
function node_invoke(&$node, $hook, $a2 = NULL, $a3 = NULL, $a4 = NULL) {
|
|
$function = node_get_module_name($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, u.data FROM {node} n INNER JOIN {users} u ON u.uid = n.uid WHERE '. implode(' AND ', $cond)));
|
|
$node = drupal_unpack($node);
|
|
|
|
/*
|
|
** Unserialize the revisions and user data fields:
|
|
*/
|
|
|
|
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 '<!--break-->' also.
|
|
*/
|
|
|
|
$node->body = str_replace('<!--break-->', '', $node->body);
|
|
|
|
/*
|
|
** The 'view' hook can be implemented to overwrite the default function
|
|
** to display nodes.
|
|
*/
|
|
|
|
if (node_hook($node, 'view')) {
|
|
return node_invoke($node, 'view', $main, $page);
|
|
}
|
|
else {
|
|
|
|
/*
|
|
** Default behavior:
|
|
*/
|
|
|
|
return theme('node', node_prepare($node, $main), $main, $page);
|
|
}
|
|
}
|
|
|
|
function node_prepare($node, $main = 0) {
|
|
if ($main == 0) {
|
|
$node->body = check_output($node->body);
|
|
}
|
|
else {
|
|
$node->teaser = check_output($node->teaser);
|
|
}
|
|
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);
|
|
|
|
// Can't use node_invoke:
|
|
// the access hook takes the $op parameter before the $node parameter.
|
|
return module_invoke(node_get_module_name($node), '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 array(t('Matching nodes ranked in order of relevance'), $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 .= '<h3>'. t('Filter options') .'</h3>';
|
|
$output .= "<div class=\"container-inline\">$form</div>";
|
|
|
|
/*
|
|
** 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 .= '<h3>'. t('Update options') .'</h3>';
|
|
$output .= "<div class=\"container-inline\">$form</div>";
|
|
|
|
/*
|
|
** 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() : ''), node_invoke($node, '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 .= '<h3>'. $filters[$filter][0] .'</h3>';
|
|
$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 (node_list() as $type) {
|
|
$node->type = $type;
|
|
$cols = array();
|
|
foreach (node_invoke_nodeapi($node, 'settings') as $setting) {
|
|
$cols[] = array('data' => $setting, 'align' => 'center', 'width' => 55);
|
|
}
|
|
$rows[] = array_merge(array(node_invoke($node, 'node_name')), $cols);
|
|
}
|
|
|
|
$output .= theme('table', $header, $rows);
|
|
|
|
/* This is an idea for the future.
|
|
foreach (node_list() as $type) {
|
|
$node->type = $type;
|
|
|
|
// 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 .= '<h2>'. node_invoke($node, 'node_name') .'</h2>';
|
|
$output .= theme('table', $header, array($cols));
|
|
$output .= '<br /><br />';
|
|
}
|
|
}
|
|
*/
|
|
|
|
$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'] ? '<br /><small>'. $revision['history'] .'</small>' : ''), 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'] = theme('xml_icon', url('node/feed'));
|
|
|
|
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 .= "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
|
|
$output .= "<!DOCTYPE rss [<!ENTITY % HTMLlat1 PUBLIC \"-//W3C//ENTITIES Latin 1 for XHTML//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent\">]>\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 .= "<rss version=\"". $channel["version"] . "\">\n";
|
|
$output .= format_rss_channel($channel['title'], $channel['link'], $channel['description'], $items, $channel['language']);
|
|
$output .= "</rss>\n";
|
|
|
|
drupal_set_header('Content-Type: text/xml; charset=utf-8');
|
|
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 = node_get_module_name($edit) .'_form';
|
|
if (function_exists($function)) {
|
|
$form .= $function($edit, $error, $param);
|
|
}
|
|
|
|
// Append extra node form:
|
|
$form .= implode('', node_invoke_nodeapi($edit, 'form post', $error));
|
|
|
|
$output .= "<div class=\"node-form\">";
|
|
|
|
/*
|
|
** Add the admin specific parts:
|
|
*/
|
|
|
|
if (user_access('administer nodes')) {
|
|
$output .= "<div class=\"admin\">";
|
|
|
|
$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 .= "<div class=\"authored\">";
|
|
$output .= form_group(t('Authoring information'), $author);
|
|
$output .= "</div>\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 .= "<div class=\"options\">";
|
|
$output .= form_group(t('Options'), $options);
|
|
$output .= "</div>\n";
|
|
|
|
$extras .= implode("</div><div class=\"extra\">", node_invoke_nodeapi($edit, 'form admin'));
|
|
$output .= $extras ? "<div class=\"extra\">$extras</div></div>" : "</div>";
|
|
}
|
|
|
|
/*
|
|
** Add the default fields:
|
|
*/
|
|
$output .= "<div class=\"standard\">";
|
|
$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 .= "</div></div>";
|
|
|
|
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_title(t('Submit %name', array('%name' => node_invoke($node, 'node_name'))));
|
|
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 (node_list() as $type) {
|
|
if (node_access('create', $type)) {
|
|
$output .= '<li>';
|
|
$output .= ' '. l(node_invoke($type, 'node_name'), "node/add/$type", array('title' => t('Add a new %s.', array('%s' => node_invoke($type, 'node_name')))));
|
|
$output .= " <div style=\"margin-left: 20px;\">". implode("\n", module_invoke_all('help', 'node/add#'. $type)) .'</div>';
|
|
$output .= '</li>';
|
|
}
|
|
}
|
|
|
|
$output = t('Choose the appropriate item from the list:') ."<ul>$output</ul>";
|
|
drupal_set_breadcrumb(array(l(t('Home'), NULL)));
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
|
|
function node_edit($id) {
|
|
global $user;
|
|
|
|
$node = node_load(array('nid' => $id));
|
|
|
|
drupal_set_title(t('Edit %name', array('%name' => node_invoke($node, 'node_name'))));
|
|
|
|
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);
|
|
|
|
/*
|
|
** Display a preview of the node:
|
|
*/
|
|
|
|
if ($node->teaser && $node->teaser != $node->body) {
|
|
$output = '<h3>'. t('Preview trimmed version') .'</h3>';
|
|
$output .= node_view($node, 1);
|
|
$output .= '<p><i>'. 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.") .'</i></p>';
|
|
$output .= '<h3>'. t('Preview full version') .'</h3>';
|
|
$output .= node_view($node, 0);
|
|
}
|
|
else {
|
|
$output .= node_view($node, 0);
|
|
}
|
|
|
|
$output .= node_form($node, $error);
|
|
|
|
$name = node_invoke($node, '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' => node_invoke($node, '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' => node_invoke($node, '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() {
|
|
if (user_access('access content')) {
|
|
$op = $_POST['op'] ? $_POST['op'] : arg(1);
|
|
$edit = $_POST['edit'];
|
|
|
|
switch ($op) {
|
|
case 'feed':
|
|
node_feed();
|
|
return;
|
|
case 'add':
|
|
// When a module defines multiple node types, the URL is of the form 'foo/bar':
|
|
print theme('page', node_add(arg(3) ? arg(2) ."/". arg(3) : arg(2)));
|
|
break;
|
|
case 'edit':
|
|
print theme('page', node_edit(arg(2)));
|
|
break;
|
|
case 'view':
|
|
if ($node = node_load(array('nid' => arg(2)), $_GET['revision'])) {
|
|
print theme('page', node_show($node, arg(3)), $node->title);
|
|
}
|
|
else {
|
|
drupal_not_found();
|
|
}
|
|
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));
|
|
drupal_set_html_head('<link rel="alternate" type="application/rss+xml" title="RSS" href="'. url('node/feed') .'" />');
|
|
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');
|
|
}
|
|
}
|
|
|
|
?>
|