node.module
<?php
define('NODE_NEW_LIMIT', time() - 30 * 24 * 60 * 60);
function node_help($section) {
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 <em>cannot</em> 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>Sticky at top of lists</dt><dd>In listings such as the frontpage or a taxonomy overview the teasers of a selected amount of nodes is displayed. If you want to force a node to appear on the top of such a listing, you must set it to 'sticky'. This way it will float to the top of a listing, and it will not be pushed down by newer content.
<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>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. 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>).</dd>
<dt>Published</dt><dd>When using Drupal's moderation system a node remains unpublished -- unavailable 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/node/configure/settings")));
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));
}
return $output;
case 'admin/modules#description':
return t('Allows content to be submitted to the site and displayed on pages.');
case 'admin/node/configure':
case 'admin/node/configure/settings':
return t('<p>Settings for the core of Drupal. Almost everything is a node so these settings will affect most of the site.</p>');
case 'admin/node':
return t('<p>Below is a list of all of the posts on your site. Other forms of content are listed elsewhere (e.g. <a href="%comments">comments</a>).</p><p>Clicking a title views the post, while clicking an author\'s name views their user information.</p>', array('%comments' => url('admin/comment')));
case 'admin/node/search':
return t('<p>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".</p>');
}
if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == 'revisions') {
return t('The revisions let you track differences between multiple versions of a post.');
}
if (arg(0) == 'node' && arg(1) == 'add' && $type = arg(2)) {
return variable_get($type .'_help', '');
}
}
function node_cron() {
db_query('DELETE FROM {history} WHERE timestamp < %d', NODE_NEW_LIMIT);
}
function node_title_list($result, $title = NULL) {
while ($node = db_fetch_object($result)) {
$items[] = l($node->title, 'node/'. $node->nid, $node->comment_count ? array('title' => format_plural($node->comment_count, '1 comment', '%count comments')) : '');
}
return theme('node_list', $items, $title);
}
function theme_node_list($items, $title = NULL) {
return theme('item_list', $items, $title);
}
function node_tag_new($nid) {
global $user;
if ($user->uid) {
if (node_last_viewed($nid)) {
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());
}
}
}
function node_last_viewed($nid) {
global $user;
static $history;
if (!isset($history[$nid])) {
$history[$nid] = db_fetch_object(db_query("SELECT timestamp FROM {history} WHERE uid = '$user->uid' AND nid = %d", $nid));
}
return ($history[$nid]->timestamp ? $history[$nid]->timestamp : 0);
}
function node_mark($nid, $timestamp) {
global $user;
static $cache;
if (!$user->uid) {
return MARK_READ;
}
if (!isset($cache[$nid])) {
$cache[$nid] = node_last_viewed($nid);
}
if ($cache[$nid] == 0 && $timestamp > NODE_NEW_LIMIT) {
return MARK_NEW;
}
elseif ($timestamp > $cache[$nid] && $timestamp > NODE_NEW_LIMIT) {
return MARK_UPDATED;
}
return MARK_READ;
}
function node_teaser($body, $format = NULL) {
$size = variable_get('teaser_length', 600);
$delimiter = strpos($body, '<!--break-->');
if ($size == 0 && $delimiter == 0) {
return $body;
}
if (isset($format)) {
$filters = filter_list_format($format);
if (isset($filters['filter/1']) && strpos($body, '<?') !== false) {
return $body;
}
}
if ($delimiter > 0) {
return substr($body, 0, $delimiter);
}
if (strlen($body) < $size) {
return $body;
}
$breakpoints = array('</p>' => 4, '<br />' => 0, '<br>' => 0, "\n" => 0, '. ' => 1, '! ' => 1, '? ' => 1, '。' => 1, '؟ ' => 1);
foreach ($breakpoints as $point => $charnum) {
if ($length = strpos($body, $point, $size)) {
return substr($body, 0, $length + $charnum);
}
}
return truncate_utf8($body, $size);
}
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;
}
}
}
function node_list() {
$types = array();
foreach (module_list() as $module) {
if (module_hook($module, 'node_name')) {
$module_types = module_invoke($module, 'node_types');
if (is_array($module_types)) {
foreach ($module_types as $type) {
$types[] = $type;
}
}
else {
$types[] = $module;
}
}
}
return $types;
}
function node_hook(&$node, $hook) {
$function = node_get_module_name($node) ."_$hook";
return function_exists($function);
}
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, $a3 = NULL, $a4 = NULL) {
$return = array();
foreach (module_list() as $name) {
$function = $name .'_nodeapi';
if (function_exists($function)) {
$result = $function($node, $op, $a3, $a4);
if (is_array($result)) {
$return = array_merge($return, $result);
}
else if (isset($result)) {
$return[] = $result;
}
}
}
return $return;
}
function node_load($conditions, $revision = NULL, $reset = NULL) {
static $nodes = array();
if ($reset) {
$nodes = array();
}
$cachable = (count($conditions) == 1 && isset($conditions['nid']) && $revision == NULL);
if ($cachable && isset($nodes[$conditions['nid']])) {
return $nodes[$conditions['nid']];
}
foreach ($conditions as $key => $value) {
$cond[] = 'n.'. db_escape_string($key) ." = '". db_escape_string($value) ."'";
}
$node = db_fetch_object(db_query(db_rewrite_sql('SELECT n.*, u.uid, u.name, u.picture, u.data FROM {node} n INNER JOIN {users} u ON u.uid = n.uid WHERE '. implode(' AND ', $cond))));
$node = drupal_unpack($node);
if ($node->revisions) {
$node->revisions = unserialize($node->revisions);
}
if ($extra = node_invoke($node, 'load')) {
foreach ($extra as $key => $value) {
$node->$key = $value;
}
}
if ($extra = node_invoke_nodeapi($node, 'load')) {
foreach ($extra as $key => $value) {
$node->$key = $value;
}
}
if (!is_null($revision) && is_array($node->revisions[$revision])) {
$node = $node->revisions[$revision]['node'];
}
if ($cachable) {
$nodes[$conditions['nid']] = $node;
}
return $node;
}
function node_save($node) {
$fields = node_invoke_nodeapi($node, 'fields');
if ($node->revisions) {
$node->revisions = serialize($node->revisions);
}
if (empty($node->nid)) {
if (!$node->created) {
$node->created = time();
}
if (!$node->changed) {
$node->changed = time();
}
$node->nid = db_next_id('{node}_nid');
foreach ($node as $key => $value) {
if (in_array((string) $key, $fields)) {
$k[] = db_escape_string($key);
$v[] = $value;
$s[] = "'%s'";
}
}
db_query("INSERT INTO {node} (". implode(", ", $k) .") VALUES(". implode(", ", $s) .")", $v);
node_invoke($node, 'insert');
node_invoke_nodeapi($node, 'insert');
}
else {
$node->changed = time();
foreach ($node as $key => $value) {
if (in_array($key, $fields)) {
$q[] = db_escape_string($key) ." = '%s'";
$v[] = $value;
}
}
db_query("UPDATE {node} SET ". implode(', ', $q) ." WHERE nid = '$node->nid'", $v);
node_invoke($node, 'update');
node_invoke_nodeapi($node, 'update');
}
cache_clear_all();
return $node->nid;
}
function node_view($node, $teaser = FALSE, $page = FALSE, $links = TRUE) {
$node = array2object($node);
$node->body = str_replace('<!--break-->', '', $node->body);
if (node_hook($node, 'view')) {
node_invoke($node, 'view', $teaser, $page);
}
else {
$node = node_prepare($node, $teaser);
}
node_invoke_nodeapi($node, 'view', $teaser, $page);
if ($links) {
$node->links = module_invoke_all('link', 'node', $node, !$page);
}
if ($teaser) {
unset($node->body);
}
else {
unset($node->teaser);
}
return theme('node', $node, $teaser, $page);
}
function node_prepare($node, $teaser = FALSE) {
$node->readmore = (strlen($node->teaser) < strlen($node->body));
if ($teaser == FALSE) {
$node->body = check_output($node->body, $node->format);
}
else {
$node->teaser = check_output($node->teaser, $node->format);
}
return $node;
}
function node_show($node, $cid) {
$output = node_view($node, FALSE, TRUE);
if (function_exists('comment_render') && $node->comment) {
$output .= comment_render($node, $cid);
}
node_tag_new($node->nid);
return $output;
}
function node_perm() {
return array('administer nodes', 'access content');
}
function node_search($op = 'search', $keys = null) {
switch ($op) {
case 'name':
return t('content');
case 'reset':
variable_del('node_cron_last');
return;
case 'status':
$last = variable_get('node_cron_last', 0);
$total = db_result(db_query('SELECT COUNT(*) FROM {node} WHERE status = 1 AND moderate = 0'));
$remaining = db_result(db_query('SELECT COUNT(*) FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE n.status = 1 AND n.moderate = 0 AND (n.created > %d OR n.changed > %d OR c.last_comment_timestamp > %d)', $last, $last, $last));
return array('remaining' => $remaining, 'total' => $total);
case 'search':
list($join, $where) = _db_rewrite_sql();
$find = do_search($keys, 'node', 'INNER JOIN {node} n ON n.nid = i.sid '. $join .' INNER JOIN {users} u ON n.uid = u.uid', 'n.status = 1'. (empty($where) ? '' : ' AND '. $where));
$results = array();
foreach ($find as $item) {
$node = node_load(array('nid' => $item));
if (node_hook($node, 'view')) {
node_invoke($node, 'view', false, false);
}
else {
$node = node_prepare($node, false);
}
node_invoke_nodeapi($node, 'view', false, false);
$extra = node_invoke_nodeapi($node, 'search result');
$results[] = array('link' => url('node/'. $item),
'type' => node_invoke($node, 'node_name'),
'title' => $node->title,
'user' => format_name($node),
'date' => $node->changed,
'extra' => $extra,
'snippet' => search_excerpt($keys, $node->body));
}
return $results;
}
}
function node_configure() {
if ($_POST) {
system_settings_save();
}
$output .= form_select(t('Number of posts on main page'), 'default_nodes_main', variable_get('default_nodes_main', 10), drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 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'. Note that this setting will only affect new or updated content and will not affect existing teasers."));
$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?'));
print theme('page', system_settings_form($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 (array_key_exists('links', $node)) {
$links = $node->links;
}
if ($main == 1 && $node->teaser && $node->readmore) {
$links[] = l(t('read more'), "node/$node->nid", array('title' => t('Read the rest of this posting.'), 'class' => 'read-more'));
}
}
return $links;
}
function node_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array('path' => 'admin/node', 'title' => t('content'),
'callback' => 'node_admin',
'access' => user_access('administer nodes'));
$items[] = array('path' => 'admin/node/action', 'title' => t('content'),
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/node/overview', 'title' => t('list'),
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
$items[] = array('path' => 'admin/node/configure', 'title' => t('configure'),
'callback' => 'node_configure',
'access' => user_access('administer nodes'),
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => 'admin/node/configure/settings', 'title' => t('settings'),
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
$items[] = array('path' => 'admin/node/configure/types', 'title' => t('content types'),
'callback' => 'node_types_configure',
'access' => user_access('administer nodes'),
'type' => MENU_LOCAL_TASK);
if (module_exist('search')) {
$items[] = array('path' => 'admin/node/search', 'title' => t('search'),
'callback' => 'node_admin',
'access' => user_access('administer nodes'),
'type' => MENU_LOCAL_TASK);
}
$items[] = array('path' => 'node', 'title' => t('content'),
'callback' => 'node_page',
'access' => user_access('access content'),
'type' => MENU_SUGGESTED_ITEM);
$items[] = array('path' => 'node/add', 'title' => t('create content'),
'callback' => 'node_page',
'access' => user_access('access content'),
'type' => MENU_ITEM_GROUPING,
'weight' => 1);
}
else {
if (arg(0) == 'node' && is_numeric(arg(1))) {
$node = node_load(array('nid' => arg(1)));
if ($node->nid) {
$items[] = array('path' => 'node/'. arg(1), 'title' => t('view'),
'callback' => 'node_page',
'access' => node_access('view', $node),
'type' => MENU_CALLBACK);
$items[] = array('path' => 'node/'. arg(1) .'/view', 'title' => t('view'),
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
$items[] = array('path' => 'node/'. arg(1) .'/edit', 'title' => t('edit'),
'callback' => 'node_page',
'access' => node_access('update', $node),
'weight' => 1,
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => 'node/'. arg(1) .'/delete', 'title' => t('delete'),
'callback' => 'node_page',
'access' => node_access('delete', $node),
'weight' => 1,
'type' => MENU_CALLBACK);
if ($node->revisions) {
$items[] = array('path' => 'node/'. arg(1) .'/revisions', 'title' => t('revisions'),
'callback' => 'node_page',
'access' => user_access('administer nodes'),
'weight' => 2,
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => 'node/'. arg(1) .'/rollback-revision', 'title' => t('Revert revision'),
'callback' => 'node_page',
'access' => user_access('administer nodes'),
'weight' => 1,
'type' => MENU_CALLBACK);
$items[] = array('path' => 'node/'. arg(1) .'/delete-revision', 'title' => t('Delete revision'),
'callback' => 'node_page',
'access' => user_access('administer nodes'),
'weight' => 1,
'type' => MENU_CALLBACK);
}
}
}
else if (arg(0) == 'admin' && arg(1) == 'node' && arg(2) == 'configure' && arg(3) == 'types' && is_string(arg(4))) {
$arg4 = arg(4);
$items[] = array('path' => 'admin/node/configure/types/'. arg(4),
'title' => t("'%name' content type", array('%name' => node_invoke($arg4, 'node_name'))),
'type' => MENU_CALLBACK);
}
}
return $items;
}
function node_last_changed($nid) {
$node = db_fetch_object(db_query('SELECT changed FROM {node} WHERE nid = %d', $nid));
return ($node->changed);
}
function node_admin_nodes() {
$operations = array(
'approve' => array(t('Approve the selected posts'), 'UPDATE {node} SET status = 1, moderate = 0 WHERE nid = %d'),
'promote' => array(t('Promote the selected posts'), 'UPDATE {node} SET status = 1, promote = 1 WHERE nid = %d'),
'sticky' => array(t('Make the selected posts sticky'), 'UPDATE {node} SET status = 1, sticky = 1 WHERE nid = %d'),
'demote' => array(t('Demote the selected posts'), 'UPDATE {node} SET promote = 0 WHERE nid = %d'),
'unpublish' => array(t('Unpublish the selected posts'), 'UPDATE {node} SET status = 0 WHERE nid = %d'),
'delete' => array(t('Delete the selected posts'), '')
);
$op = $_POST['op'];
$edit = $_POST['edit'];
if (($op == t('Update') || $op == t('Delete all')) && isset($edit['operation']) && isset($edit['nodes'])) {
$edit['nodes'] = array_diff($edit['nodes'], array(0));
if (count($edit['nodes']) == 0) {
form_set_error('', t('Please select some items to perform the update on.'));
}
else {
if ($operations[$edit['operation']][1]) {
$operation = $operations[$edit['operation']][1];
foreach ($edit['nodes'] as $nid => $value) {
if ($value) {
db_query($operation, $nid);
}
}
drupal_set_message(t('The update has been performed.'));
}
else if ($edit['operation'] == 'delete') {
if ($edit['confirm']) {
foreach ($edit['nodes'] as $nid => $value) {
node_delete(array('nid' => $nid, 'confirm' => 1));
}
drupal_set_message(t('The items have been deleted.'));
}
else {
$extra = '<ul>';
foreach ($edit['nodes'] as $nid => $value) {
if ($value) {
$title = db_result(db_query('SELECT title FROM {node} WHERE nid = %d', $nid));
$extra .= '<li>'. form_hidden('nodes]['. $nid, 1) . check_plain($title) .'</li>';
}
}
$extra .= '</ul>';
$extra .= form_hidden('operation', 'delete');
$output = theme('confirm',
t('Are you sure you want to delete these items?'),
'admin/node',
t('This action cannot be undone.'),
t('Delete all'),
t('Cancel'),
$extra);
return $output;
}
}
}
}
$node_types = drupal_map_assoc(node_list());
foreach ($node_types as $k => $v) {
$node_types[$k] = node_invoke($v, 'node_name');
}
$filters = array(
'status' => array('title' => t('status'),
'options' => array('status-1' => t('published'), 'status-0' => t('not published'),
'moderate-1' => t('in moderation'), 'moderate-0' => t('not in moderation'),
'promote-1' => t('promoted'), 'promote-0' => t('not promoted'),
'sticky-1' => t('sticky'), 'sticky-0' => t('not sticky'))),
'type' => array('title' => t('type'), 'where' => "n.type = '%s'",
'options' => $node_types));
if ($taxonomy = module_invoke('taxonomy', 'form_all')) {
$terms = array();
foreach ($taxonomy as $key => $value) {
$terms = $terms + $value;
}
$filters['category'] = array('title' => t('category'), 'where' => 'tn.tid = %d',
'options' => $terms, 'join' => 'INNER JOIN {term_node} tn ON n.nid = tn.nid');
}
if (!isset($_SESSION['node_overview_filter']) || !is_array($_SESSION['node_overview_filter']) || $op == t('Reset')) {
$_SESSION['node_overview_filter'] = array();
}
$session = &$_SESSION['node_overview_filter'];
$filter = $edit['filter'];
if (($op == t('Filter') || $op == t('Refine')) && isset($filter)) {
if (isset($filters[$filter]['options'][$edit[$filter]])) {
$session[] = array($filter, $edit[$filter]);
}
}
if ($op == t('Undo')) {
array_pop($session);
}
if ($op != '') {
drupal_goto('admin/node');
}
$output .= '<div id="node-admin-filter">';
$form = '<ul>';
$i = 0;
foreach ($session as $filter) {
list($type, $value) = $filter;
$params = array('%a' => '<strong>'. $filters[$type]['title'] .'</strong>', '%b' => '<strong>'. $filters[$type]['options'][$value] .'</strong>');
$form .= '<li>'. ($i++ ? t('<em>and</em> where <strong>%a</strong> is <strong>%b</strong>', $params) : t('<strong>%a</strong> is <strong>%b</strong>', $params)) .'</li>';
}
if (isset($filters['category'])) {
$filters['category']['options'] = $taxonomy;
}
$values = '';
$options = array();
foreach ($filters as $key => $value) {
$options[$key] = $value['title'];
$b .= form_select('', $key, 1, $filters[$key]['options']);
}
$buttons = '';
if (count($options)) {
$form .= '<li><dl class="multiselect">';
$a = '';
foreach ($options as $key => $value) {
$a .= form_radio($value, 'filter', $key);
}
if (!$i) {
$form .= t('<dd class="a">%a</dd> <dt>is</dt> <dd class="b">%b</dd>', array('%a' => $a, '%b' => $b));
}
else {
$form .= t('<dt><em>and</em> where</dt> <dd class="a">%a</dd> <dt>is</dt> <dd class="b">%b</dd>', array('%a' => $a, '%b' => $b));
}
$form .= '</dl>';
$buttons = form_submit(count($session) ? t('Refine') : t('Filter'));
}
if (count($session)) {
$buttons .= form_submit(t('Undo')) . form_submit(t('Reset'));
}
$form .= '<div class="container-inline" id="node-admin-buttons">'. $buttons .'</div>';
$form .= '</li></ul><br class="clear" />';
$output .= form_group(t('Show only items where'), $form);
$where = $args = array();
$join = '';
foreach ($session as $filter) {
list($key, $value) = $filter;
if ($key == 'status') {
list($key, $value) = explode('-', $value, 2);
$where[] = 'n.'. $key .' = %d';
}
else {
$where[] = $filters[$key]['where'];
}
$args[] = $value;
$join .= $filters[$key]['join'];
}
$where = count($where) ? 'WHERE '. implode(' AND ', $where) : '';
$result = pager_query('SELECT n.*, u.name, u.uid FROM {node} n '. $join .' INNER JOIN {users} u ON n.uid = u.uid '. $where .' ORDER BY n.changed DESC', 50, 0, NULL, $args);
$disabled = !db_num_rows($result);
$options = array();
foreach ($operations as $key => $value) {
$options[$key] = $value[0];
}
$form = form_select(NULL, 'operation', 'approve', $options, NULL, ($disabled ? 'disabled="disabled"' : ''));
$form .= form_submit(t('Update'), 'op', ($disabled ? array('disabled' => 'disabled') : array()));
$output .= form_group(t('Update options'), "<div class=\"container-inline\">$form</div>");
$output .= '</div>';
$header = array(NULL, t('Title'), t('Type'), t('Author'), t('Status'), t('Operations'));
$destination = drupal_get_destination();
while ($node = db_fetch_object($result)) {
$rows[] = array(form_checkbox(NULL, 'nodes]['. $node->nid, 1, 0),
l($node->title, 'node/'. $node->nid) .' '. theme('mark', node_mark($node->nid, $node->changed)),
node_invoke($node, 'node_name'),
format_name($node),
($node->status ? t('published') : t('not published')),
l(t('edit'), 'node/'. $node->nid .'/edit', array(), $destination));
}
if ($pager = theme('pager', NULL, 50, 0)) {
$rows[] = array(array('data' => $pager, 'colspan' => '7'));
}
if (!$rows) {
$rows[] = array(array('data' => t('No posts available.'), 'colspan' => '6'));
}
$output .= theme('table', $header, $rows);
return form($output, 'post', url('admin/node/action'));
}
function node_types_configure($type = NULL) {
if (isset($type)) {
if ($_POST['op']) {
$_GET['q'] = 'admin/node/configure/types';
}
system_settings_save();
$node = new stdClass();
$node->type = $type;
$group = form_textarea(t('Explanation or submission guidelines'), $type .'_help', variable_get($type .'_help', ''), 70, 5, t('This text will be displayed at the top of the %type submission form. It is useful for helping or instructing your users.', array('%type' => node_invoke($type, 'node_name'))));
$group .= form_select(t('Minimum number of words'), 'minimum_'. $type .'_size', variable_get('minimum_'. $type .'_size', 0), drupal_map_assoc(array(0, 10, 25, 50, 75, 100, 125, 150, 175, 200)), t('The minimum number of words a %type must be to be considered valid. This can be useful to rule out submissions that do not meet the site\'s standards, such as short test posts.', array('%type' => node_invoke($type, 'node_name'))));
$output = form_group(t('Submission form'), $group);
$output .= form_group(t('Workflow'), implode('', node_invoke_nodeapi($node, 'settings')));
print theme('page', system_settings_form($output));
}
else {
$header = array(t('Type'), t('Operations'));
$rows = array();
foreach (node_list() as $type) {
$rows[] = array(node_invoke($type, 'node_name'), l(t('configure'), 'admin/node/configure/types/'. $type));
}
print theme('page', theme('table', $header, $rows));
}
}
function node_revision_overview($nid) {
if (user_access('administer nodes')) {
$node = node_load(array('nid' => $nid));
drupal_set_title(check_plain($node->title));
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/$node->nid", array(), "revision=$key"), l(t('rollback'), "node/$node->nid/rollback-revision/$key"), l(t('delete'), "node/$node->nid/delete-revision/$key"));
}
$output .= theme('table', $header, $rows);
}
}
return $output;
}
function node_revision_load($node, $revision) {
return $node->revisions[$revision]['node'];
}
function node_revision_create($node) {
global $user;
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;
}
function node_revision_rollback($nid, $revision) {
global $user;
if (user_access('administer nodes')) {
$node = node_load(array('nid' => $nid));
$rev = $node->revisions[$revision]['node'];
if ($_POST['edit']['confirm']) {
$rev->revisions = $node->revisions;
$rev->revisions[] = array('uid' => $user->uid, 'timestamp' => time(), 'node' => $node);
unset($rev->revisions[$revision]);
foreach ($node as $key => $value) {
$filter[] = $key;
}
node_save($rev, $filter);
drupal_set_message(t('Rolled back to revision %revision of %title', array('%revision' => "<em>#$revision</em>", '%title' => theme('placeholder', $node->title))));
drupal_goto('node/'. $nid .'/revisions');
}
else {
$output = theme('confirm',
t('Are you sure you want to revert %title? to the revision from %revision-date?', array('%title' => theme('placeholder', $node->title), '%revision-date' => theme('placeholder', format_date($node->revisions[$revision]['timestamp'])))),
'node/'. $nid .'/revisions',
t('This action cannot be undone.'),
t('Revert'));
print theme('page', $output);
}
}
}
function node_revision_delete($nid, $revision) {
if (user_access('administer nodes')) {
$node = node_load(array('nid' => $nid));
if ($_POST['edit']['confirm']) {
unset($node->revisions[$revision]);
if (count($node->revisions) == 0) {
$node->revisions = '';
}
node_save($node, array('nid', 'revisions'));
drupal_set_message(t('Deleted revision %revision of %title', array('%revision' => "<em>#$revision</em>", '%title' => theme('placeholder', $node->title))));
drupal_goto('node/'. $nid . (count($node->revisions) ? '/revisions' : ''));
}
else {
$output = theme('confirm',
t('Are you sure you want to delete the revision of %title from %revision-date?', array('%title' => theme('placeholder', $node->title), '%revision-date' => theme('placeholder', format_date($node->revisions[$revision]['timestamp'])))),
'node/'. $nid .'/revisions',
t('This action cannot be undone.'),
t('Delete revision'));
print theme('page', $output);
}
}
}
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 (empty($op)) {
$op = arg(2);
}
switch ($op) {
case 'search':
case t('Search'):
$output = search_form(url('admin/node/search'), $_POST['edit']['keys'], 'node') . search_data($_POST['edit']['keys'], 'node');
break;
default:
$output = node_admin_nodes();
}
print theme('page', $output);
}
function node_block($op = 'list', $delta = 0) {
if ($op == 'list') {
$blocks[0]['info'] = t('Syndicate');
return $blocks;
}
else if ($op == 'view') {
$block['subject'] = t('Syndicate');
$block['content'] = theme('xml_icon', url('node/feed'));
return $block;
}
}
function node_feed($nodes = 0, $channel = array()) {
global $base_url, $locale;
if (!$nodes) {
$nodes = db_query_range(db_rewrite_sql('SELECT n.nid FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.created DESC'), 0, 15);
}
while ($node = db_fetch_object($nodes)) {
$item = node_load(array('nid' => $node->nid));
$link = url("node/$node->nid", NULL, NULL, 1);
if (node_hook($item, 'view')) {
node_invoke($item, 'view', TRUE, FALSE);
}
else {
$item = node_prepare($item, TRUE);
}
node_invoke_nodeapi($item, 'view', true, false);
$extra = node_invoke_nodeapi($item, 'rss item');
$extra = array_merge($extra, array(array('key' => 'pubDate', 'value' => date('r', $item->created))));
$items .= format_rss_item($item->title, $link, $item->teaser, $extra);
}
$slogan = variable_get('site_slogan', '');
$spacer = ' - ';
if (empty($slogan)) {
$spacer = '';
}
$channel_defaults = array(
'version' => '2.0',
'title' => variable_get('site_name', 'drupal') . $spacer . $slogan,
'link' => $base_url,
'description' => variable_get('site_mission', ''),
'language' => $locale
);
$channel = array_merge($channel_defaults, $channel);
$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";
$output .= "<rss version=\"". $channel["version"] . "\" xml:base=\"". $base_url ."\">\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) {
global $user;
$node = array2object($node);
if (isset($node->title)) {
if (trim($node->title) == '') {
form_set_error('title', t('You have to specify a title.'));
}
}
if (isset($node->body) && count(explode(' ', $node->body)) < variable_get('minimum_'. $node->type .'_size', 0)) {
form_set_error('body', t('The body of your %type is too short. You need at least %words words.', array('%words' => variable_get('minimum_'. $node->type .'_size', 0), '%type' => node_invoke($node->type, 'node_name'))));
}
if (!isset($node->teaser)) {
$node->teaser = node_teaser($node->body, $node->format);
}
if (node_last_changed($node->nid) > $node->changed) {
form_set_error('changed', t('This content has been modified by another user, unable to save changes.'));
}
if (user_access('administer nodes')) {
if (!$node->created) {
$node->created = time();
}
if (!$node->date) {
$node->date = format_date($node->created, 'custom', 'Y-m-d H:i:s O');
}
if (empty($node->name)) {
$node->uid = 0;
}
else if ($account = user_load(array('name' => $node->name))) {
$node->uid = $account->uid;
}
else {
form_set_error('name', t('The username %name does not exist.', array ('%name' => theme('placeholder', $node->name))));
}
if (strtotime($node->date) != -1) {
$node->created = strtotime($node->date);
}
else {
form_set_error('date', t('You have to specify a valid date.'));
}
}
else {
$node->uid = $user->uid ? $user->uid : 0;
$node_options = variable_get('node_options_'. $node->type, array('status', 'promote'));
$node->status = in_array('status', $node_options);
$node->moderate = in_array('moderate', $node_options);
$node->promote = in_array('promote', $node_options);
$node->sticky = in_array('sticky', $node_options);
$node->revision = in_array('revision', $node_options);
unset($node->created);
}
$node = node_revision_create($node);
node_invoke($node, 'validate');
node_invoke_nodeapi($node, 'validate');
if (array_key_exists('format', $node) && !filter_access($node->format)) {
form_set_error('format', t('The supplied input format is invalid.'));
}
$node->validated = TRUE;
return $node;
}
function node_form($edit) {
if (!$edit->validated) {
$edit = node_validate($edit);
}
$form = implode('', node_invoke_nodeapi($edit, 'form pre'));
$function = node_get_module_name($edit) .'_form';
$param = array();
if (function_exists($function)) {
$form .= $function($edit, $param);
}
$form .= implode('', node_invoke_nodeapi($edit, 'form post'));
$output .= '<div class="node-form">';
$output .= '<input type="hidden" name="op" value="'. check_plain(t('Preview')) ."\" />\n";
if (user_access('administer nodes')) {
$output .= '<div class="admin">';
$author = form_textfield(t('Authored by'), 'name', $edit->name, 20, 60);
$author .= form_textfield(t('Authored on'), 'date', $edit->date, 20, 25, NULL, NULL, TRUE);
$output .= '<div class="authored">';
$output .= form_group(t('Authoring information'), $author);
$output .= "</div>\n";
$node_options = variable_get('node_options_'. $edit->type, array('status', 'promote'));
$options .= form_checkbox(t('Published'), 'status', 1, isset($edit->status) ? $edit->status : in_array('status', $node_options));
$options .= form_checkbox(t('In moderation queue'), 'moderate', 1, isset($edit->moderate) ? $edit->moderate : in_array('moderate', $node_options));
$options .= form_checkbox(t('Promoted to front page'), 'promote', 1, isset($edit->promote) ? $edit->promote : in_array('promote', $node_options));
$options .= form_checkbox(t('Sticky at top of lists'), 'sticky', 1, isset($edit->sticky) ? $edit->sticky : in_array('sticky', $node_options));
$options .= form_checkbox(t('Create new revision'), 'revision', 1, isset($edit->revision) ? $edit->revision : in_array('revision', $node_options));
$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>';
}
$output .= '<div class="standard">';
$output .= form_textfield(t('Title'), 'title', $edit->title, 60, 128, NULL, NULL, TRUE);
$output .= $form;
if ($edit->nid) {
$output .= form_hidden('nid', $edit->nid);
}
if (isset($edit->uid)) {
$output .= form_hidden('uid', $edit->uid);
}
if ($edit->created) {
$output .= form_hidden('created', $edit->created);
}
if ($edit->changed) {
$output .= form_hidden('changed', $edit->changed);
}
$output .= form_hidden('type', $edit->type);
$output .= form_submit(t('Preview'));
if ($edit->type && (($_POST['op'] == t('Preview') && !form_get_errors()) || !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>';
$extra = node_invoke_nodeapi($edit, 'form param');
foreach ($extra as $key => $value) {
if (is_array($value)) {
if (isset($param[$key])) {
$param[$key] = array_merge($param[$key], $value);
}
else {
$param[$key] = $value;
}
}
else {
$param[$key] = $value;
}
}
$attributes = array('id' => 'node-form');
if (is_array($param['options'])) {
$attributes = array_merge($param['options'], $attributes);
}
return form($output, ($param['method'] ? $param['method'] : 'post'), $param['action'], $attributes);
}
function node_add($type) {
global $user;
$edit = $_POST['edit'];
if (in_array($type, node_list()) && node_access('create', $type)) {
$node = array('uid' => $user->uid, 'name' => $user->name, 'type' => $type);
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'))));
}
else {
foreach (node_list() as $type) {
if (node_access('create', $type)) {
$out = '<li>';
$out .= ' '. l(node_invoke($type, 'node_name'), "node/add/$type", array('title' => t('Add a new %s.', array('%s' => node_invoke($type, 'node_name')))));
$out .= " <div style=\"margin-left: 20px;\">". implode("\n", module_invoke_all('help', 'node/add#'. $type)) .'</div>';
$out .= '</li>';
$item[node_invoke($type, 'node_name')] = $out;
}
}
if (isset($item)) {
ksort($item);
$output = t('Choose the appropriate item from the list:') .'<ul>'. implode('', $item) .'</ul>';
}
else {
$output = message_access();
}
}
return $output;
}
function node_edit($id) {
global $user;
$node = node_load(array('nid' => $id));
drupal_set_title(check_plain($node->title));
$output = node_form($node);
return $output;
}
function node_preview($node) {
$node = array2object($node);
if (node_access('create', $node) || node_access('update', $node)) {
if (isset($node->name)) {
if ($user = user_load(array('name' => $node->name))) {
$node->uid = $user->uid;
}
else {
$node->uid = 0; }
}
else if ($node->uid) {
$user = user_load(array('uid' => $node->uid));
$node->name = $user->name;
}
if (empty($node->created)) {
$node->created = time();
}
if (!isset($node->teaser)) {
$node->teaser = node_teaser($node->body, $node->format);
}
if (!form_get_errors()) {
$output = theme('node_preview', clone($node));
}
$output .= node_form($node);
$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 theme_node_preview($node) {
$output = '<div class="preview">';
if ($node->teaser && $node->teaser != $node->body) {
$output .= '<h3>'. t('Preview trimmed version') .'</h3>';
$output .= node_view(clone($node), 1, FALSE, 0);
$output .= '<p><em>'. t('The trimmed version of your post shows what your post looks like when promoted to the main page or when exported for syndication. You can insert the delimiter "<!--break-->" (without the quotes) to fine-tune where your post gets split.') .'</em></p>';
$output .= '<h3>'. t('Preview full version') .'</h3>';
$output .= node_view($node, 0, FALSE, 0);
}
else {
$output .= node_view($node, 0, FALSE, 0);
}
$output .= "</div>\n";
return $output;
}
function node_submit(&$node) {
global $user;
$node = node_validate($node);
if (form_get_errors()) {
return false;
}
if ($node->nid) {
if (node_access('update', $node)) {
$node->nid = node_save($node);
watchdog('content', t('%type: updated %title.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title))), WATCHDOG_NOTICE, l(t('view'), 'node/'. $node->nid));
$msg = t('The %post was updated.', array ('%post' => node_invoke($node, 'node_name')));
}
}
else {
if (node_access('create', $node)) {
$node->nid = node_save($node);
watchdog('content', t('%type: added %title.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title))), WATCHDOG_NOTICE, l(t('view'), "node/$node->nid"));
$msg = t('Your %post was created.', array ('%post' => node_invoke($node, 'node_name')));
}
}
drupal_set_message($msg);
return $node->nid;
}
function node_delete($edit) {
$node = node_load(array('nid' => $edit['nid']));
if (node_access('delete', $node)) {
if ($edit['confirm']) {
db_query('DELETE FROM {node} WHERE nid = %d', $node->nid);
node_invoke($node, 'delete');
node_invoke_nodeapi($node, 'delete');
cache_clear_all();
if (function_exists('search_wipe')) {
search_wipe($node->nid, 'node');
}
watchdog('content', t('%type: deleted %title.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title))));
}
else {
$extra = form_hidden('nid', $node->nid);
$output = theme('confirm',
t('Are you sure you want to delete %title?', array('%title' => theme('placeholder', $node->title))),
$_GET['destination'] ? $_GET['destination'] : 'node/'. $node->nid,
t('This action cannot be undone.'),
t('Delete'),
t('Cancel'),
$extra);
}
}
return $output;
}
function node_page_default() {
$result = pager_query(db_rewrite_sql('SELECT n.nid, n.sticky, n.created FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC'), variable_get('default_nodes_main', 10));
if (db_num_rows($result)) {
drupal_add_link(array('rel' => 'alternate',
'type' => 'application/rss+xml',
'title' => 'RSS',
'href' => url('node/feed', NULL, NULL, TRUE)));
$output = '';
while ($node = db_fetch_object($result)) {
$output .= node_view(node_load(array('nid' => $node->nid)), 1);
}
$output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
}
else {
$output = t("
<p>Welcome to your new <a href=\"%drupal\">Drupal</a>-powered website. This message will guide you through your first steps with Drupal, and will disappear once you have posted your first piece of content.</p>
<p>The first thing you will need to do is <a href=\"%register\">create the first account</a>. This account will have full administration rights and will allow you to configure your website. Once logged in, you can visit the <a href=\"%admin\">administration section</a> and <a href=\"%config\">set up your site's configuration</a>.</p>
<p>Drupal comes with various modules, each of which contains a specific piece of functionality. You should visit the <a href=\"%modules\">module list</a> and enable those modules which suit your website's needs.</p>
<p><a href=\"%themes\">Themes</a> handle the presentation of your website. You can use one of the existing themes, modify them or create your own from scratch.</p>
<p>We suggest you look around the administration section and explore the various options Drupal offers you. For more information, you can refer to the <a href=\"%handbook\">Drupal handbooks online</a>.</p>", array('%drupal' => 'http://www.drupal.org/', '%register' => url('user/register'), '%admin' => url('admin'), '%config' => url('admin'), '%modules' => url('admin/modules'), '%themes' => url('admin/themes'), '%handbook' => 'http://www.drupal.org/handbooks'));
}
return $output;
}
function node_page() {
global $user;
$op = $_POST['op'] ? $_POST['op'] : arg(1);
$edit = $_POST['edit'];
if (is_numeric($op)) {
$op = (arg(2) && !is_numeric(arg(2))) ? arg(2) : 'view';
}
switch ($op) {
case 'feed':
node_feed();
return;
case 'add':
print theme('page', node_add(arg(2)));
break;
case 'edit':
print theme('page', node_edit(arg(1)));
break;
case 'revisions':
print theme('page', node_revision_overview(arg(1)));
break;
case t('Revert'):
case 'rollback-revision':
node_revision_rollback(arg(1), arg(3));
break;
case t('Delete revision'):
case 'delete-revision':
node_revision_delete(arg(1), arg(3));
break;
case 'view':
if (is_numeric(arg(1))) {
$node = node_load(array('nid' => arg(1)), $_GET['revision']);
if ($node->nid) {
drupal_set_title(check_plain($node->title));
print theme('page', node_show($node, arg(2)));
}
else if (db_result(db_query('SELECT nid FROM {node} WHERE nid = %d', arg(1)))) {
drupal_access_denied();
}
else {
drupal_not_found();
}
}
break;
case t('Preview'):
$edit = node_validate($edit);
drupal_set_title(t('Preview'));
print theme('page', node_preview($edit));
break;
case t('Submit'):
if ($nid = node_submit($edit)) {
if (node_access('view', $edit)) {
drupal_goto('node/'. $nid);
}
else if (db_result(db_query('SELECT nid FROM {node} WHERE nid = %d', arg(1)))) {
drupal_access_denied();
}
else {
drupal_goto();
}
}
else {
drupal_set_title(t('Submit'));
print theme('page', node_preview($edit));
}
break;
case 'delete':
case t('Delete'):
$edit['nid'] = $edit['nid'] ? $edit['nid'] : arg(1);
$node = node_load(array('nid' => $edit['nid']));
$breadcrumb[] = array('path' => 'node/'. $edit['nid'], 'title' => $node->title);
$breadcrumb[] = array('path' => 'node/'. arg(1) .'/delete', 'title' => t('delete'));
menu_set_location($breadcrumb);
$output = node_delete($edit);
if (!$output) {
drupal_set_message(t('The node has been deleted.'));
drupal_goto('admin/node');
}
print theme('page', node_delete($edit));
break;
default:
drupal_set_title('');
print theme('page', node_page_default());
}
}
function node_update_index() {
$last = variable_get('node_cron_last', 0);
$limit = (int)variable_get('search_cron_limit', 100);
$result = db_query_range('SELECT n.nid, c.last_comment_timestamp FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE n.status = 1 AND n.moderate = 0 AND (n.created > %d OR n.changed > %d OR c.last_comment_timestamp > %d) ORDER BY GREATEST(n.created, n.changed, c.last_comment_timestamp) ASC', $last, $last, $last, 0, $limit);
while ($node = db_fetch_object($result)) {
$last_comment = $node->last_comment_timestamp;
$node = node_load(array('nid' => $node->nid));
variable_set('node_cron_last', max($last_comment, $node->changed, $node->created));
if (node_hook($node, 'view')) {
node_invoke($node, 'view', false, false);
}
else {
$node = node_prepare($node, false);
}
node_invoke_nodeapi($node, 'view', false, false);
$text = '<h1>'. check_plain($node->title) .'</h1>'. $node->body;
$extra = node_invoke_nodeapi($node, 'update index');
foreach ($extra as $t) {
$text .= $t;
}
search_index($node->nid, 'node', $text);
}
}
function node_nodeapi(&$node, $op, $arg = 0) {
switch ($op) {
case 'settings':
return form_checkboxes(t('Default options'), 'node_options_'. $node->type, variable_get('node_options_'. $node->type, array('status', 'promote')), array('status' => t('Published'), 'moderate' => t('In moderation queue'), 'promote' => t('Promoted to front page'), 'sticky' => t('Sticky at top of lists'), 'revision' => t('Create new revision')), t('Users with the <em>administer nodes</em> permission will be able to override these options.'));
case 'fields':
return array('nid', 'uid', 'type', 'title', 'teaser', 'body', 'revisions', 'status', 'promote', 'moderate', 'sticky', 'created', 'changed', 'format');
}
}
function node_access($op, $node = NULL, $uid = NULL) {
$node = array2object($node);
if ($op == 'update' && !filter_access($node->format)) {
return FALSE;
}
if (user_access('administer nodes')) {
return TRUE;
}
if (!user_access('access content')) {
return FALSE;
}
$access = module_invoke(node_get_module_name($node), 'access', $op, $node);
if (!is_null($access)) {
return $access;
}
if ($node->nid && $node->status) {
$sql = 'SELECT COUNT(*) FROM {node_access} WHERE (nid = 0 OR nid = %d) AND CONCAT(realm, gid) IN (';
$grants = array();
foreach (node_access_grants($op, $uid) as $realm => $gids) {
foreach ($gids as $gid) {
$grants[] = "'". $realm . $gid ."'";
}
}
$sql .= implode(',', $grants) .') AND grant_'. $op .' = 1';
$result = db_query($sql, $node->nid);
return (db_result($result));
}
return FALSE;
}
function _node_access_join_sql($node_alias = 'n', $node_access_alias = 'na') {
if (user_access('administer nodes')) {
return '';
}
return 'INNER JOIN {node_access} '. $node_access_alias .' ON '. $node_access_alias .'.nid = '. $node_alias .'.nid';
}
function _node_access_where_sql($op = 'view', $node_access_alias = 'na', $uid = NULL) {
if (user_access('administer nodes')) {
return;
}
$sql = $node_access_alias .'.grant_'. $op .' = 1 AND CONCAT('. $node_access_alias .'.realm, '. $node_access_alias .'.gid) IN (';
$grants = array();
foreach (node_access_grants($op, $uid) as $realm => $gids) {
foreach ($gids as $gid) {
$grants[] = "'". $realm . $gid ."'";
}
}
$sql .= implode(',', $grants) .')';
return $sql;
}
function node_access_grants($op, $uid = NULL) {
global $user;
if (isset($uid)) {
$user_object = user_load(array('uid' => $uid));
}
else {
$user_object = $user;
}
return array_merge(array('all' => array(0)), module_invoke_all('node_grants', $user_object, $op));
}
function node_access_view_all_nodes() {
static $access;
if (!isset($access)) {
$sql = 'SELECT COUNT(*) FROM {node_access} WHERE nid = 0 AND CONCAT(realm, gid) IN (';
$grants = array();
foreach (node_access_grants('view') as $realm => $gids) {
foreach ($gids as $gid) {
$grants[] = "'". $realm . $gid ."'";
}
}
$sql .= implode(',', $grants) .') AND grant_view = 1';
$result = db_query($sql, $node->nid);
$access = db_result($result);
}
return $access;
}
function node_db_rewrite_sql($query, $primary_table, $primary_field) {
if ($primary_field == 'nid' && !node_access_view_all_nodes()) {
$return['join'] = _node_access_join_sql($primary_table);
$return['where'] = _node_access_where_sql();
$return['distinct'] = 1;
return $return;
}
}
?>