node.module
<?php
define('NODE_NOT_PUBLISHED', 0);
define('NODE_PUBLISHED', 1);
define('NODE_NOT_PROMOTED', 0);
define('NODE_PROMOTED', 1);
define('NODE_NOT_STICKY', 0);
define('NODE_STICKY', 1);
define('NODE_NEW_LIMIT', REQUEST_TIME - 30 * 24 * 60 * 60);
define('NODE_ACCESS_ALLOW', 'allow');
define('NODE_ACCESS_DENY', 'deny');
define('NODE_ACCESS_IGNORE', NULL);
function node_help($path, $arg) {
if ($path != 'admin/reports/status/rebuild' && $path != 'batch' && strpos($path, '#') === FALSE
&& user_access('access administration pages') && node_access_needs_rebuild()) {
if ($path == 'admin/reports/status') {
$message = t('The content access permissions need to be rebuilt.');
}
else {
$message = t('The content access permissions need to be rebuilt. Please visit <a href="@node_access_rebuild">this page</a>.', array('@node_access_rebuild' => url('admin/reports/status/rebuild')));
}
drupal_set_message($message, 'error');
}
switch ($path) {
case 'admin/help#node':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The Node module manages the creation, editing, deletion, settings, and display of all site content. For more information, see the online handbook entry for <a href="@node">Node module</a>.', array('@node' => 'http://drupal.org/handbook/modules/node')) . '</p>';
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Creating content') . '</dt>';
$output .= '<dd>' . t('When new content is created, the Node module records basic information about the content, including the author, date of creation, and the <a href="@content-type">Content type</a>. It also manages the <em>publishing options</em>, which define whether or not the content is published, promoted to the front page of the site, and/or sticky at the top of content lists. Default settings can be configured for each <a href="@content-type">type of content</a> on your site.', array('@content-type' => url('admin/structure/types'))) . '</dd>';
$output .= '<dt>' . t('Creating custom content types') . '</dt>';
$output .= '<dd>' . t('The Node module gives users with the <em>Administer content types</em> permission the ability to <a href="@content-new">create new content types</a> in addition to the default ones already configured. Creating custom content types allows you the flexibility to add <a href="@field">fields</a> and configure default settings that suit the differing needs of various site content.', array('@content-new' => url('admin/structure/types/add'), '@field' => url('admin/help/field'))) . '</dd>';
$output .= '<dt>' . t('Administering content') . '</dt>';
$output .= '<dd>' . t('The <a href="@content">Content administration page</a> allows you to review and bulk manage your site content.', array('@content' => url('admin/content'))) . '</dd>';
$output .= '<dt>' . t('Creating revisions') . '</dt>';
$output .= '<dd>' . t('The Node module also enables you to create multiple versions of any content, and revert to older versions using the <em>Revision information</em> settings.') . '</dd>';
$output .= '<dt>' . t('User permissions') . '</dt>';
$output .= '<dd>' . t('The Node module makes a number of permissions available for each content type, which can be set by role on the <a href="@permissions">permissions page</a>.', array('@permissions' => url('admin/settings/permissions'))) . '</dd>';
$output .= '</dl>';
return $output;
case 'admin/content':
return ' ';
case 'admin/structure/types/add':
return '<p>' . t('Individual content types can have different fields, behaviors, and permissions assigned to them.') . '</p>';
case 'admin/structure/types/manage/' . $arg[3] . '/fields':
return '<p>' . t('This form allows you to add, edit, and arrange fields within the %type content type.', array('%type' => node_type_get_name($arg[3]))) . '</p>';
case 'admin/structure/types/manage/' . $arg[3] . '/display':
return '<p>' . t('This form allows you to configure how fields should be displayed when %type content is rendered in the following contexts.', array('%type' => node_type_get_name($arg[3]))) . '</p>';
case 'admin/structure/types/manage/' . $arg[3] . '/display/' . $arg[5]:
return '<p>' . t('This form allows you to configure how fields should be displayed when %type content is rendered in the following contexts.', array('%type' => node_type_get_name($arg[3]))) . '</p>';
case 'node/%/revisions':
return '<p>' . t('Revisions allow you to track differences between multiple versions of your content, and revert back to older versions.') . '</p>';
case 'node/%/edit':
$node = node_load($arg[1]);
$type = node_type_get_type($node);
return (!empty($type->help) ? '<p>' . filter_xss_admin($type->help) . '</p>' : '');
}
if ($arg[0] == 'node' && $arg[1] == 'add' && $arg[2]) {
$type = node_type_get_type(str_replace('-', '_', $arg[2]));
return (!empty($type->help) ? '<p>' . filter_xss_admin($type->help) . '</p>' : '');
}
}
function node_theme() {
return array(
'node' => array(
'render element' => 'elements',
'template' => 'node',
),
'node_list' => array(
'variables' => array('items' => NULL, 'title' => NULL),
),
'node_search_admin' => array(
'render element' => 'form',
),
'node_filter_form' => array(
'render element' => 'form',
'file' => 'node.admin.inc',
),
'node_filters' => array(
'render element' => 'form',
'file' => 'node.admin.inc',
),
'node_add_list' => array(
'variables' => array('content' => NULL),
'file' => 'node.pages.inc',
),
'node_form' => array(
'render element' => 'form',
'file' => 'node.pages.inc',
),
'node_preview' => array(
'variables' => array('node' => NULL),
'file' => 'node.pages.inc',
),
'node_log_message' => array(
'variables' => array('log' => NULL),
),
'node_admin_overview' => array(
'variables' => array('name' => NULL, 'type' => NULL),
),
);
}
function node_cron() {
db_delete('history')
->condition('timestamp', NODE_NEW_LIMIT, '<')
->execute();
}
function node_entity_info() {
$return = array(
'node' => array(
'label' => t('Node'),
'controller class' => 'NodeController',
'base table' => 'node',
'revision table' => 'node_revision',
'fieldable' => TRUE,
'object keys' => array(
'id' => 'nid',
'revision' => 'vid',
'bundle' => 'type',
),
'bundle keys' => array(
'bundle' => 'type',
),
'bundles' => array(),
),
);
foreach (node_type_get_names() as $type => $name) {
$return['node']['bundles'][$type] = array(
'label' => $name,
'admin' => array(
'path' => 'admin/structure/types/manage/%node_type',
'real path' => 'admin/structure/types/manage/' . str_replace('_', '-', $type),
'bundle argument' => 4,
'access arguments' => array('administer content types'),
),
);
}
return $return;
}
function node_field_build_modes($obj_type) {
$modes = array();
if ($obj_type == 'node') {
$modes = array(
'teaser' => t('Teaser'),
'full' => t('Full node'),
'rss' => t('RSS'),
);
if (module_exists('search')) {
$modes += array(
'search_index' => t('Search Index'),
'search_result' => t('Search Result'),
);
}
}
return $modes;
}
function node_admin_paths() {
$paths = array(
'node/*/add' => TRUE,
'node/*/edit' => TRUE,
'node/*/delete' => TRUE,
'node/add' => TRUE,
'node/add/*' => TRUE,
);
return $paths;
}
function node_title_list($result, $title = NULL) {
$items = array();
$num_rows = FALSE;
foreach ($result as $node) {
$items[] = l($node->title, 'node/' . $node->nid, !empty($node->comment_count) ? array('attributes' => array('title' => format_plural($node->comment_count, '1 comment', '@count comments'))) : array());
$num_rows = TRUE;
}
return $num_rows ? theme('node_list', array('items' => $items, 'title' => $title)) : FALSE;
}
function theme_node_list($variables) {
return theme('item_list', $variables);
}
function node_tag_new($nid) {
global $user;
if ($user->uid) {
db_merge('history')
->key(array(
'uid' => $user->uid,
'nid' => $nid,
))
->fields(array('timestamp' => REQUEST_TIME))
->execute();
}
}
function node_last_viewed($nid) {
global $user;
static $history;
if (!isset($history[$nid])) {
$history[$nid] = db_query("SELECT timestamp FROM {history} WHERE uid = :uid AND nid = :nid", array(':uid' => $user->uid, ':nid' => $nid))->fetchObject();
}
return (isset($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_extract_type($node) {
return is_object($node) ? $node->type : $node;
}
function node_type_get_types() {
return _node_types_build()->types;
}
function node_type_get_type($node) {
$type = _node_extract_type($node);
$types = _node_types_build()->types;
return isset($types[$type]) ? $types[$type] : FALSE;
}
function node_type_get_base($node) {
$type = _node_extract_type($node);
$types = _node_types_build()->types;
return isset($types[$type]) && isset($types[$type]->base) ? $types[$type]->base : FALSE;
}
function node_type_get_names() {
return _node_types_build()->names;
}
function node_type_get_name($node) {
$type = _node_extract_type($node);
$types = _node_types_build()->names;
return isset($types[$type]) ? $types[$type] : FALSE;
}
function node_types_rebuild() {
drupal_static_reset('_node_types_build');
foreach (node_type_get_types() as $type => $info) {
if (!empty($info->is_new)) {
node_type_save($info);
}
if (!empty($info->disabled)) {
node_type_delete($info->type);
}
}
}
function node_type_load($name) {
return node_type_get_type(strtr($name, array('-' => '_')));
}
function node_type_save($info) {
$is_existing = FALSE;
$existing_type = !empty($info->old_type) ? $info->old_type : $info->type;
$is_existing = (bool) db_query_range('SELECT 1 FROM {node_type} WHERE type = :type', 0, 1, array(':type' => $existing_type))->fetchField();
$type = node_type_set_defaults($info);
$fields = array(
'type' => (string) $type->type,
'name' => (string) $type->name,
'base' => (string) $type->base,
'has_title' => (int) $type->has_title,
'title_label' => (string) $type->title_label,
'has_body' => (int) $type->has_body,
'body_label' => (string) $type->body_label,
'description' => (string) $type->description,
'help' => (string) $type->help,
'custom' => (int) $type->custom,
'modified' => (int) $type->modified,
'locked' => (int) $type->locked,
);
if ($is_existing) {
db_update('node_type')
->fields($fields)
->condition('type', $existing_type)
->execute();
if (!empty($type->old_type) && $type->old_type != $type->type) {
field_attach_rename_bundle('node', $type->old_type, $type->type);
}
node_configure_fields($type);
module_invoke_all('node_type_update', $type);
$status = SAVED_UPDATED;
}
else {
$fields['orig_type'] = (string) $type->orig_type;
db_insert('node_type')
->fields($fields)
->execute();
field_attach_create_bundle('node', $type->type);
node_configure_fields($type);
module_invoke_all('node_type_insert', $type);
$status = SAVED_NEW;
}
drupal_static_reset('_node_types_build');
return $status;
}
function node_configure_fields($type) {
$field = field_info_field('body');
$instance = field_info_instance('node', 'body', $type->type);
if ($type->has_body) {
if (empty($field)) {
$field = array(
'field_name' => 'body',
'type' => 'text_with_summary',
'translatable' => TRUE,
);
$field = field_create_field($field);
}
if (empty($instance)) {
$instance = array(
'field_name' => 'body',
'object_type' => 'node',
'bundle' => $type->type,
'label' => $type->body_label,
'widget_type' => 'text_textarea_with_summary',
'settings' => array('display_summary' => TRUE),
'display' => array(
'full' => array(
'label' => 'hidden',
'type' => 'text_default',
),
'teaser' => array(
'label' => 'hidden',
'type' => 'text_summary_or_trimmed',
),
),
);
field_create_instance($instance);
}
else {
$instance['label'] = $type->body_label;
$instance['settings']['display_summary'] = TRUE;
field_update_instance($instance);
}
}
elseif (!empty($instance)) {
field_delete_instance($instance);
}
if ($type->has_title) {
$field = field_info_field('title');
$instance = field_info_instance('node', 'title', $type->type);
if (empty($field)) {
$field = array(
'field_name' => 'title',
'type' => 'text',
);
$field = field_create_field($field);
}
if (empty($instance)) {
$weight = -5;
$instance = array(
'field_name' => 'title',
'object_type' => 'node',
'bundle' => $type->type,
'label' => $type->title_label,
'widget_type' => 'text',
'widget' => array(
'weight' => $weight,
),
'required' => TRUE,
'locked' => TRUE,
'display' => array(
'full' => array(
'label' => 'hidden',
'type' => 'text_default',
'weight' => $weight,
),
'teaser' => array(
'label' => 'hidden',
'type' => 'text_default',
'weight' => $weight,
),
),
);
field_create_instance($instance);
}
else {
$instance['label'] = $type->title_label;
field_update_instance($instance);
}
}
}
function node_type_delete($type) {
$info = node_type_get_type($type);
db_delete('node_type')
->condition('type', $type)
->execute();
module_invoke_all('node_type_delete', $info);
drupal_static_reset('_node_types_build');
}
function node_type_update_nodes($old_type, $type) {
return db_update('node')
->fields(array('type' => $type))
->condition('type', $old_type)
->execute();
}
function _node_types_build() {
$_node_types = &drupal_static(__FUNCTION__);
if (is_object($_node_types)) {
return $_node_types;
}
$_node_types = (object)array('types' => array(), 'names' => array());
$info_array = module_invoke_all('node_info');
foreach ($info_array as $type => $info) {
$info['type'] = $type;
$_node_types->types[$type] = node_type_set_defaults($info);
$_node_types->names[$type] = $info['name'];
}
$type_result = db_select('node_type', 'nt')
->addTag('translatable')
->addTag('node_type_access')
->fields('nt')
->orderBy('nt.type', 'ASC')
->execute();
foreach ($type_result as $type_object) {
if (isset($type_object->base) && $type_object->base != 'node_content' && empty($info_array[$type_object->type])) {
$type_object->disabled = TRUE;
}
if (!isset($_node_types->types[$type_object->type]) || $type_object->modified) {
$_node_types->types[$type_object->type] = $type_object;
$_node_types->names[$type_object->type] = $type_object->name;
if ($type_object->type != $type_object->orig_type) {
unset($_node_types->types[$type_object->orig_type]);
unset($_node_types->names[$type_object->orig_type]);
}
}
}
asort($_node_types->names);
return $_node_types;
}
function node_type_set_defaults($info = array()) {
static $type;
if (!isset($type)) {
$type = new stdClass();
$type->type = '';
$type->name = '';
$type->base = '';
$type->description = '';
$type->help = '';
$type->has_title = 1;
$type->has_body = 1;
$type->title_label = t('Title');
$type->body_label = t('Body');
$type->custom = 0;
$type->modified = 0;
$type->locked = 1;
$type->is_new = 1;
}
$new_type = clone $type;
$info = (array) $info;
foreach ($info as $key => $data) {
$new_type->$key = $data;
}
if (!$new_type->has_title) {
$new_type->title_label = '';
}
if (!$new_type->has_body) {
$new_type->body_label = '';
}
$new_type->orig_type = isset($info['type']) ? $info['type'] : '';
return $new_type;
}
function node_rdf_mapping() {
return array(
array(
'type' => 'node',
'bundle' => RDF_DEFAULT_BUNDLE,
'mapping' => array(
'rdftype' => array('sioc:Item', 'foaf:Document'),
'title' => array(
'predicates' => array('dc:title'),
),
'created' => array(
'predicates' => array('dc:date', 'dc:created'),
'datatype' => 'xsd:dateTime',
'callback' => 'date_iso8601',
),
'changed' => array(
'predicates' => array('dc:modified'),
),
'body' => array(
'predicates' => array('content:encoded'),
),
'uid' => array(
'predicates' => array('sioc:has_creator'),
),
'name' => array(
'predicates' => array('foaf:name'),
),
),
),
);
}
function node_hook($node, $hook) {
$base = node_type_get_base($node);
return module_hook($base, $hook);
}
function node_invoke($node, $hook, $a2 = NULL, $a3 = NULL, $a4 = NULL) {
if (node_hook($node, $hook)) {
$base = node_type_get_base($node);
$function = $base . '_' . $hook;
return ($function($node, $a2, $a3, $a4));
}
}
function node_load_multiple($nids = array(), $conditions = array(), $reset = FALSE) {
return entity_load('node', $nids, $conditions, $reset);
}
function node_load($nid = NULL, $vid = NULL, $reset = FALSE) {
$nids = (isset($nid) ? array($nid) : array());
$conditions = (isset($vid) ? array('vid' => $vid) : array());
$node = node_load_multiple($nids, $conditions, $reset);
return $node ? reset($node) : FALSE;
}
function node_validate($node, $form = array()) {
$type = node_type_get_type($node);
if (isset($node->nid) && (node_last_changed($node->nid) > $node->changed)) {
form_set_error('changed', t('The content on this page has either been modified by another user, or you have already submitted modifications using this form. As a result, your changes cannot be saved.'));
}
if (user_access('administer nodes')) {
if (!empty($node->name) && !($account = user_load_by_name($node->name))) {
form_set_error('name', t('The username %name does not exist.', array('%name' => $node->name)));
}
if (!empty($node->date) && strtotime($node->date) === FALSE) {
form_set_error('date', t('You have to specify a valid date.'));
}
}
node_invoke($node, 'validate', $form);
module_invoke_all('node_validate', $node, $form);
}
function node_submit($node) {
global $user;
if (user_access('administer nodes') && !isset($node->uid)) {
if ($account = user_load_by_name($node->name)) {
$node->uid = $account->uid;
}
else {
$node->uid = 0;
}
}
$node->created = !empty($node->date) ? strtotime($node->date) : REQUEST_TIME;
$node->validated = TRUE;
return $node;
}
function node_save($node) {
$transaction = db_transaction();
try {
field_attach_presave('node', $node);
module_invoke_all('node_presave', $node);
global $user;
if (!isset($node->is_new)) {
$node->is_new = empty($node->nid);
}
if ($node->is_new) {
$node->is_new = TRUE;
if (!isset($node->log)) {
$node->log = '';
}
}
elseif (!empty($node->revision)) {
$node->old_vid = $node->vid;
unset($node->vid);
}
else {
if (empty($node->log)) {
unset($node->log);
}
}
if (empty($node->created)) {
$node->created = REQUEST_TIME;
}
$node->changed = REQUEST_TIME;
$node->timestamp = REQUEST_TIME;
$update_node = TRUE;
$title_field = $node->title;
$langcode = LANGUAGE_NONE;
$node->title = $title_field[$langcode][0]['value'];
if ($node->is_new) {
drupal_write_record('node', $node);
_node_save_revision($node, $user->uid);
$op = 'insert';
}
else {
drupal_write_record('node', $node, 'nid');
if (!empty($node->revision)) {
_node_save_revision($node, $user->uid);
}
else {
_node_save_revision($node, $user->uid, 'vid');
$update_node = FALSE;
}
$op = 'update';
}
if ($update_node) {
db_update('node')
->fields(array('vid' => $node->vid))
->condition('nid', $node->nid)
->execute();
}
$node->title = $title_field;
node_invoke($node, $op);
$function = "field_attach_$op";
$function('node', $node);
module_invoke_all('node_' . $op, $node);
node_access_acquire_grants($node);
unset($node->is_new);
cache_clear_all();
db_ignore_slave();
}
catch (Exception $e) {
$transaction->rollback('node', $e->getMessage(), array(), WATCHDOG_ERROR);
}
}
function _node_save_revision($node, $uid, $update = NULL) {
$temp_uid = $node->uid;
$node->uid = $uid;
if (isset($update)) {
drupal_write_record('node_revision', $node, $update);
}
else {
drupal_write_record('node_revision', $node);
}
$node->uid = $temp_uid;
}
function node_delete($nid) {
node_delete_multiple(array($nid));
}
function node_delete_multiple($nids) {
if (!empty($nids)) {
$nodes = node_load_multiple($nids, array());
db_delete('node')
->condition('nid', $nids, 'IN')
->execute();
db_delete('node_revision')
->condition('nid', $nids, 'IN')
->execute();
db_delete('history')
->condition('nid', $nids, 'IN')
->execute();
foreach ($nodes as $nid => $node) {
node_invoke($node, 'delete');
module_invoke_all('node_delete', $node);
field_attach_delete('node', $node);
if (module_exists('search')) {
search_reindex($nid, 'node');
}
}
cache_clear_all();
entity_get_controller('node')->resetCache();
}
}
function node_revision_delete($revision_id) {
if ($revision = node_load(NULL, $revision_id)) {
$node = node_load($revision->nid);
if ($revision_id == $node->vid) {
return FALSE;
}
db_delete('node_revision')
->condition('nid', $revision->nid)
->condition('vid', $revision->vid)
->execute();
module_invoke_all('node_revision_delete', $revision);
field_attach_delete_revision('node', $revision);
return TRUE;
}
return FALSE;
}
function node_build($node, $build_mode = 'full') {
node_build_content($node, $build_mode);
$build = $node->content;
unset($node->content);
$build += array(
'#theme' => 'node',
'#node' => $node,
'#build_mode' => $build_mode,
);
$build['#contextual_links']['node'] = array('node', array($node->nid));
drupal_alter('node_build', $build);
return $build;
}
function node_build_content($node, $build_mode = 'full') {
$node->content = array();
if (node_hook($node, 'view')) {
$node = node_invoke($node, 'view', $build_mode);
}
$node->content += field_attach_view('node', $node, $build_mode);
$links = array();
if ($build_mode == 'teaser') {
$links['node_readmore'] = array(
'title' => t('Read more'),
'href' => 'node/' . $node->nid,
'attributes' => array('rel' => 'tag', 'title' => strip_tags($node->title[LANGUAGE_NONE][0]['value']))
);
}
$node->content['links']['node'] = array(
'#theme' => 'links',
'#links' => $links,
'#attributes' => array('class' => array('links', 'inline')),
);
module_invoke_all('node_view', $node, $build_mode);
}
function node_language_negotiation_info() {
$providers = array();
$providers['node-language'] = array(
'types' => array(LANGUAGE_TYPE_CONTENT),
'callbacks' => array('language' => 'node_language_provider'),
'file' => drupal_get_path('module', 'node') . '/node.module',
'name' => t('Node'),
'description' => t('The current node language is used.'),
);
return $providers;
}
function node_language_provider($languages) {
require_once DRUPAL_ROOT . '/' . variable_get('path_inc', 'includes/path.inc');
$path = isset($_GET['q']) ? $_GET['q'] : '';
list($language, $path) = language_url_split_prefix($path, $languages);
$language = $language ? $language : language_default();
$path = drupal_get_normal_path($path, $language->language);
$path = explode('/', $path);
if (isset($path[0]) && isset($path[1]) && $path[0] == 'node' && $nid = intval($path[1])) {
$result = db_query('SELECT n.language FROM {node} n WHERE n.nid = :nid', array(':nid' => $nid))->fetchAssoc();
return $result['language'];
}
return FALSE;
}
function node_show($node, $message = FALSE) {
if ($message) {
drupal_set_title(t('Revision of %title from %date', array('%title' => $node->title[LANGUAGE_NONE][0]['value'], '%date' => format_date($node->revision_timestamp))), PASS_THROUGH);
}
node_tag_new($node->nid);
return node_build_multiple(array($node->nid => $node), 'full');
}
function template_preprocess_node(&$variables) {
$variables['build_mode'] = $variables['elements']['#build_mode'];
$variables['teaser'] = $variables['build_mode'] == 'teaser';
$variables['node'] = $variables['elements']['#node'];
$node = $variables['node'];
$variables['date'] = format_date($node->created);
$variables['name'] = theme('username', array('account' => $node));
$variables['node_url'] = url('node/' . $node->nid);
$variables['node_title'] = check_plain($node->title[LANGUAGE_NONE][0]['value']);
$variables['page'] = (bool)menu_get_object();
if (!empty($node->in_preview)) {
unset($node->content['links']);
}
$variables = array_merge((array)$node, $variables);
foreach (element_children($variables['elements']) as $key) {
$variables['content'][$key] = $variables['elements'][$key];
}
field_attach_preprocess('node', $node, $variables['content'], $variables);
if (isset($variables['content']['title'])) {
unset($variables['content']['title']);
}
if (variable_get('node_submitted_' . $node->type, TRUE)) {
$variables['display_submitted'] = TRUE;
$variables['user_picture'] = theme_get_setting('toggle_node_user_picture') ? theme('user_picture', array('account' => $node)) : '';
}
else {
$variables['display_submitted'] = FALSE;
$variables['user_picture'] = '';
}
$variables['classes_array'][] = drupal_html_class('node-' . $node->type);
if ($variables['promote']) {
$variables['classes_array'][] = 'node-promoted';
}
if ($variables['sticky']) {
$variables['classes_array'][] = 'node-sticky';
}
if (!$variables['status']) {
$variables['classes_array'][] = 'node-unpublished';
}
if ($variables['teaser']) {
$variables['classes_array'][] = 'node-teaser';
}
if (isset($variables['preview'])) {
$variables['classes_array'][] = 'node-preview';
}
$variables['template_files'][] = 'node-' . str_replace('_', '-', $node->type);
$variables['template_files'][] = 'node-' . $node->nid;
}
function theme_node_log_message($variables) {
return '<div class="log"><div class="title">' . t('Log') . ':</div>' . $variables['log'] . '</div>';
}
function node_permission() {
$perms = array(
'administer content types' => array(
'title' => t('Administer content types'),
),
'administer nodes' => array(
'title' => t('Administer content'),
'description' => theme('placeholder', array('text' => t('Warning: Give to trusted roles only; this permission has security implications.'))),
),
'access content' => array(
'title' => t('View published content'),
),
'access content overview' => array(
'title' => t('Access the content overview page'),
),
'bypass node access' => array(
'title' => t('Bypass content access control'),
'description' => t('View, edit and delete all content regardless of permission restrictions. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))),
),
'view revisions' => array(
'title' => t('View content revisions'),
),
'revert revisions' => array(
'title' => t('Revert content revisions'),
),
'delete revisions' => array(
'title' => t('Delete content revisions'),
),
'view own unpublished content' => array(
'title' => t('View own unpublished content'),
),
);
foreach (node_permissions_get_configured_types() as $type) {
$perms += node_list_permissions($type);
}
return $perms;
}
function _node_rankings(SelectQueryExtender $query) {
if ($ranking = module_invoke_all('ranking')) {
$tables = &$query->getTables();
foreach ($ranking as $rank => $values) {
if ($node_rank = variable_get('node_rank_' . $rank, 0)) {
if (isset($values['join']) && !isset($tables[$values['join']['alias']])) {
$query->addJoin($values['join']['type'], $values['join']['table'], $values['join']['alias'], $values['join']['on']);
}
$arguments = isset($values['arguments']) ? $values['arguments'] : array();
$query->addScore($values['score'], $arguments, $node_rank);
}
}
}
}
function node_search_info() {
return array(
'title' => 'Content',
'path' => 'node',
);
}
function node_search_access() {
return user_access('access content');
}
function node_search_reset() {
db_update('search_dataset')
->fields(array('reindex' => REQUEST_TIME))
->condition('type', 'node')
->execute();
}
function node_search_status() {
$total = db_query('SELECT COUNT(*) FROM {node} WHERE status = :status', array(':status' => NODE_PUBLISHED))->fetchField();
$remaining = db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE n.status = :status AND d.sid IS NULL OR d.reindex <> 0", array(':status' => NODE_PUBLISHED))->fetchField();
return array('remaining' => $remaining, 'total' => $total);
}
function node_search_admin() {
$form['content_ranking'] = array(
'#type' => 'fieldset',
'#title' => t('Content ranking'),
);
$form['content_ranking']['#theme'] = 'node_search_admin';
$form['content_ranking']['info'] = array(
'#value' => '<em>' . t('The following numbers control which properties the content search should favor when ordering the results. Higher numbers mean more influence, zero means the property is ignored. Changing these numbers does not require the search index to be rebuilt. Changes take effect immediately.') . '</em>'
);
$options = drupal_map_assoc(range(0, 10));
foreach (module_invoke_all('ranking') as $var => $values) {
$form['content_ranking']['factors']['node_rank_' . $var] = array(
'#title' => $values['title'],
'#type' => 'select',
'#options' => $options,
'#default_value' => variable_get('node_rank_' . $var, 0),
);
}
return $form;
}
function node_search_execute($keys = NULL) {
$query = db_select('search_index', 'i', array('target' => 'slave'))->extend('SearchQuery')->extend('PagerDefault');
$query->join('node', 'n', 'n.nid = i.sid');
$query
->condition('n.status', 1)
->addTag('node_access')
->searchExpression($keys, 'node');
$query->setOption('type', 'n.type');
$query->setOption('language', 'n.language');
if ($query->setOption('term', 'tn.nid')) {
$query->join('taxonomy_term_node', 'tn', 'n.vid = tn.vid');
}
if (!$query->executeFirstPass()) {
return array();
}
_node_rankings($query);
$inner_query = clone $query;
$count_query = db_select($inner_query->fields('i', array('sid')), NULL, array('target' => 'slave'));
$count_query->addExpression('COUNT(*)');
$query->setCountQuery($count_query);
$find = $query
->limit(10)
->execute();
$results = array();
foreach ($find as $item) {
$node = node_load($item->sid);
$build = node_build($node, 'search_result');
unset($build['#theme']);
$node->rendered = drupal_render($build);
$node->rendered .= ' ' . module_invoke('comment', 'node_update_index', $node);
$node->rendered .= ' ' . module_invoke('taxonomy', 'node_update_index', $node);
$extra = module_invoke_all('node_search_result', $node);
$results[] = array(
'link' => url('node/' . $item->sid, array('absolute' => TRUE)),
'type' => check_plain(node_type_get_name($node)),
'title' => $node->title[LANGUAGE_NONE][0]['value'],
'user' => theme('username', array('account' => $node)),
'date' => $node->changed,
'node' => $node,
'extra' => $extra,
'score' => $item->calculated_score,
'snippet' => search_excerpt($keys, $node->rendered),
);
}
return $results;
}
function node_ranking() {
$ranking = array(
'relevance' => array(
'title' => t('Keyword relevance'),
'score' => 'i.relevance',
),
'sticky' => array(
'title' => t('Content is sticky at top of lists'),
'score' => 'n.sticky',
),
'promote' => array(
'title' => t('Content is promoted to the front page'),
'score' => 'n.promote',
),
);
if ($node_cron_last = variable_get('node_cron_last', 0)) {
$ranking['recent'] = array(
'title' => t('Recently posted'),
'score' => 'POW(2.0, (GREATEST(n.created, n.changed) - :node_cron_last) * 6.43e-8)',
'arguments' => array(':node_cron_last' => $node_cron_last),
);
}
return $ranking;
}
function node_user_cancel($edit, $account, $method) {
switch ($method) {
case 'user_cancel_block_unpublish':
module_load_include('inc', 'node', 'node.admin');
$nodes = db_select('node', 'n')
->fields('n', array('nid'))
->condition('uid', $account->uid)
->execute()
->fetchCol();
node_mass_update($nodes, array('status' => 0));
break;
case 'user_cancel_reassign':
module_load_include('inc', 'node', 'node.admin');
$nodes = db_select('node', 'n')
->fields('n', array('nid'))
->condition('uid', $account->uid)
->execute()
->fetchCol();
node_mass_update($nodes, array('uid' => 0));
db_update('node_revision')
->fields(array('uid' => 0))
->condition('uid', $account->uid)
->execute();
db_delete('history')
->condition('uid', $account->uid)
->execute();
break;
case 'user_cancel_delete':
$nodes = db_select('node', 'n')
->fields('n', array('nid'))
->condition('uid', $account->uid)
->execute()
->fetchCol();
node_delete_multiple($nodes);
$revisions = db_query('SELECT vid FROM {node_revision} WHERE uid = :uid', array(':uid' => $account->uid))->fetchCol();
foreach ($revisions as $revision) {
node_revision_delete($revision);
}
db_delete('history')
->condition('uid', $account->uid)
->execute();
break;
}
}
function theme_node_search_admin($variables) {
$form = $variables['form'];
$output = drupal_render($form['info']);
$header = array(t('Factor'), t('Weight'));
foreach (element_children($form['factors']) as $key) {
$row = array();
$row[] = $form['factors'][$key]['#title'];
unset($form['factors'][$key]['#title']);
$row[] = drupal_render($form['factors'][$key]);
$rows[] = $row;
}
$output .= theme('table', array('header' => $header, 'rows' => $rows));
$output .= drupal_render_children($form);
return $output;
}
function _node_revision_access($node, $op = 'view') {
$access = &drupal_static(__FUNCTION__, array());
if (!isset($access[$node->vid])) {
$node_current_revision = node_load($node->nid);
$is_current_revision = $node_current_revision->vid == $node->vid;
if ($is_current_revision && (db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField() == 1 || $op == 'update' || $op == 'delete')) {
$access[$node->vid] = FALSE;
}
elseif (user_access('administer nodes')) {
$access[$node->vid] = TRUE;
}
else {
$map = array('view' => 'view revisions', 'update' => 'revert revisions', 'delete' => 'delete revisions');
$access[$node->vid] = isset($map[$op]) && user_access($map[$op]) && node_access($op, $node_current_revision) && ($is_current_revision || node_access($op, $node));
}
}
return $access[$node->vid];
}
function _node_add_access() {
$types = node_type_get_types();
foreach ($types as $type) {
if (node_hook($type->type, 'form') && node_access('create', $type->type)) {
return TRUE;
}
}
if (user_access('administer content types')) {
return TRUE;
}
return FALSE;
}
function node_menu() {
$items['admin/content'] = array(
'title' => 'Content',
'description' => 'Find and manage content.',
'page callback' => 'drupal_get_form',
'page arguments' => array('node_admin_content'),
'access arguments' => array('access content overview'),
'weight' => -10,
'file' => 'node.admin.inc',
);
$items['admin/content/node'] = array(
'title' => 'Content',
'description' => "View, edit, and delete your site's content.",
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/reports/status/rebuild'] = array(
'title' => 'Rebuild permissions',
'page callback' => 'drupal_get_form',
'page arguments' => array('node_configure_rebuild_confirm'),
'access arguments' => array('access administration pages'),
'type' => MENU_CALLBACK,
'file' => 'node.admin.inc',
);
$items['admin/structure/types'] = array(
'title' => 'Content types',
'description' => 'Manage content types, including default status, front page promotion, comment settings, etc.',
'page callback' => 'node_overview_types',
'access arguments' => array('administer content types'),
'file' => 'content_types.inc',
);
$items['admin/structure/types/list'] = array(
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/structure/types/add'] = array(
'title' => 'Add content type',
'page callback' => 'drupal_get_form',
'page arguments' => array('node_type_form'),
'access arguments' => array('administer content types'),
'type' => MENU_LOCAL_ACTION,
'file' => 'content_types.inc',
);
$items['admin/structure/types/manage/%node_type'] = array(
'title' => 'Edit content type',
'title callback' => 'node_type_page_title',
'title arguments' => array(4),
'page callback' => 'drupal_get_form',
'page arguments' => array('node_type_form', 4),
'access arguments' => array('administer content types'),
'file' => 'content_types.inc',
);
$items['admin/structure/types/manage/%node_type/edit'] = array(
'title' => 'Edit',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/structure/types/manage/%node_type/delete'] = array(
'title' => 'Delete',
'page arguments' => array('node_type_delete_confirm', 4),
'access arguments' => array('administer content types'),
'type' => MENU_CALLBACK,
'file' => 'content_types.inc',
);
$items['node'] = array(
'title' => 'Content',
'page callback' => 'node_page_default',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
$items['node/add'] = array(
'title' => 'Add new content',
'page callback' => 'node_add_page',
'access callback' => '_node_add_access',
'weight' => 1,
'menu_name' => 'management',
'theme callback' => '_node_custom_theme',
'file' => 'node.pages.inc',
);
$items['rss.xml'] = array(
'title' => 'RSS feed',
'page callback' => 'node_feed',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
drupal_static_reset('_node_types_build');
foreach (node_type_get_types() as $type) {
$type_url_str = str_replace('_', '-', $type->type);
$items['node/add/' . $type_url_str] = array(
'title' => $type->name,
'title callback' => 'check_plain',
'page callback' => 'node_add',
'page arguments' => array(2),
'access callback' => 'node_access',
'access arguments' => array('create', $type->type),
'description' => $type->description,
'file' => 'node.pages.inc',
);
}
$items['node/%node'] = array(
'page callback' => 'node_page_view',
'page arguments' => array(1),
'access callback' => 'node_access',
'access arguments' => array('view', 1),
'type' => MENU_CALLBACK,
);
$items['node/%node/view'] = array(
'title' => 'View',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['node/%node/edit'] = array(
'title' => 'Edit',
'page callback' => 'node_page_edit',
'page arguments' => array(1),
'access callback' => 'node_access',
'access arguments' => array('update', 1),
'theme callback' => '_node_custom_theme',
'weight' => 0,
'type' => MENU_LOCAL_TASK,
'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
'file' => 'node.pages.inc',
);
$items['node/%node/delete'] = array(
'title' => 'Delete',
'page callback' => 'drupal_get_form',
'page arguments' => array('node_delete_confirm', 1),
'access callback' => 'node_access',
'access arguments' => array('delete', 1),
'weight' => 1,
'type' => MENU_LOCAL_TASK,
'context' => MENU_CONTEXT_INLINE,
'file' => 'node.pages.inc',
);
$items['node/%node/revisions'] = array(
'title' => 'Revisions',
'page callback' => 'node_revision_overview',
'page arguments' => array(1),
'access callback' => '_node_revision_access',
'access arguments' => array(1),
'weight' => 2,
'type' => MENU_LOCAL_TASK,
'file' => 'node.pages.inc',
);
$items['node/%node/revisions/%/view'] = array(
'title' => 'Revisions',
'load arguments' => array(3),
'page callback' => 'node_show',
'page arguments' => array(1, TRUE),
'access callback' => '_node_revision_access',
'access arguments' => array(1),
'type' => MENU_CALLBACK,
);
$items['node/%node/revisions/%/revert'] = array(
'title' => 'Revert to earlier revision',
'load arguments' => array(3),
'page callback' => 'drupal_get_form',
'page arguments' => array('node_revision_revert_confirm', 1),
'access callback' => '_node_revision_access',
'access arguments' => array(1, 'update'),
'type' => MENU_CALLBACK,
'file' => 'node.pages.inc',
);
$items['node/%node/revisions/%/delete'] = array(
'title' => 'Delete earlier revision',
'load arguments' => array(3),
'page callback' => 'drupal_get_form',
'page arguments' => array('node_revision_delete_confirm', 1),
'access callback' => '_node_revision_access',
'access arguments' => array(1, 'delete'),
'type' => MENU_CALLBACK,
'file' => 'node.pages.inc',
);
return $items;
}
function node_menu_local_tasks_alter(&$data, $router_item, $root_path) {
if ($root_path == 'admin/content') {
$item = menu_get_item('node/add');
if ($item['access']) {
$data['actions']['output'][] = array(
'#theme' => 'menu_local_action',
'#link' => $item,
);
}
}
}
function node_type_page_title($type) {
return $type->name;
}
function node_page_title($node) {
return $node->title;
}
function _node_custom_theme() {
if (variable_get('node_admin_theme')) {
return variable_get('admin_theme');
}
}
function node_init() {
drupal_add_css(drupal_get_path('module', 'node') . '/node.css');
}
function node_last_changed($nid) {
return db_query('SELECT changed FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetch()->changed;
}
function node_revision_list($node) {
$revisions = array();
$result = db_query('SELECT r.vid, r.title, r.log, r.uid, n.vid AS current_vid, r.timestamp, u.name FROM {node_revision} r LEFT JOIN {node} n ON n.vid = r.vid INNER JOIN {users} u ON u.uid = r.uid WHERE r.nid = :nid ORDER BY r.timestamp DESC', array(':nid' => $node->nid));
foreach ($result as $revision) {
$revisions[$revision->vid] = $revision;
}
return $revisions;
}
function node_block_info() {
$blocks['syndicate']['info'] = t('Syndicate');
$blocks['syndicate']['cache'] = DRUPAL_NO_CACHE;
return $blocks;
}
function node_block_view($delta = '') {
$block['subject'] = t('Syndicate');
$block['content'] = theme('feed_icon', array('url' => url('rss.xml'), 'title' => t('Syndicate')));
return $block;
}
function node_feed($nids = FALSE, $channel = array()) {
global $base_url, $language;
if ($nids === FALSE) {
$nids = db_select('node', 'n')
->fields('n', array('nid', 'created'))
->condition('n.promote', 1)
->condition('status', 1)
->orderBy('n.created', 'DESC')
->range(0, variable_get('feed_default_items', 10))
->addTag('node_access')
->execute()
->fetchCol();
}
$item_length = variable_get('feed_item_length', 'fulltext');
$namespaces = array('xmlns:dc' => 'http://purl.org/dc/elements/1.1/');
$teaser = ($item_length == 'teaser');
$nodes = node_load_multiple($nids);
$items = '';
foreach ($nodes as $node) {
$item_text = '';
$node->link = url("node/$node->nid", array('absolute' => TRUE));
$node->rss_namespaces = array();
$node->rss_elements = array(
array('key' => 'pubDate', 'value' => gmdate('r', $node->created)),
array('key' => 'dc:creator', 'value' => $node->name),
array('key' => 'guid', 'value' => $node->nid . ' at ' . $base_url, 'attributes' => array('isPermaLink' => 'false'))
);
$build = node_build($node, 'rss');
unset($build['#theme']);
if (!empty($node->rss_namespaces)) {
$namespaces = array_merge($namespaces, $node->rss_namespaces);
}
if ($item_length != 'title') {
$build['links']['#weight'] = 1000;
$item_text .= drupal_render($build);
}
$items .= format_rss_item($node->title[LANGUAGE_NONE][0]['value'], $node->link, $item_text, $node->rss_elements);
}
$channel_defaults = array(
'version' => '2.0',
'title' => variable_get('site_name', 'Drupal'),
'link' => $base_url,
'description' => variable_get('feed_description', ''),
'language' => $language->language
);
$channel_extras = array_diff_key($channel, $channel_defaults);
$channel = array_merge($channel_defaults, $channel);
$output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
$output .= "<rss version=\"" . $channel["version"] . "\" xml:base=\"" . $base_url . "\" " . drupal_attributes($namespaces) . ">\n";
$output .= format_rss_channel($channel['title'], $channel['link'], $channel['description'], $items, $channel['language'], $channel_extras);
$output .= "</rss>\n";
drupal_add_http_header('Content-Type', 'application/rss+xml; charset=utf-8');
print $output;
}
function node_build_multiple($nodes, $build_mode = 'teaser', $weight = 0) {
field_attach_prepare_view('node', $nodes, $build_mode);
$build = array();
foreach ($nodes as $node) {
$build['nodes'][$node->nid] = node_build($node, $build_mode);
$build['nodes'][$node->nid]['#weight'] = $weight;
$weight++;
}
$build['nodes']['#sorted'] = TRUE;
return $build;
}
function node_page_default() {
$select = db_select('node', 'n')
->fields('n', array('nid'))
->condition('promote', 1)
->condition('status', 1)
->orderBy('sticky', 'DESC')
->orderBy('created', 'DESC')
->extend('PagerDefault')
->limit(variable_get('default_nodes_main', 10))
->addTag('node_access');
$nids = $select->execute()->fetchCol();
if (!empty($nids)) {
$nodes = node_load_multiple($nids);
$build = node_build_multiple($nodes);
$feed_url = url('rss.xml', array('absolute' => TRUE));
drupal_add_feed($feed_url, variable_get('site_name', 'Drupal') . ' ' . t('RSS'));
$build['pager'] = array(
'#theme' => 'pager',
'#weight' => 5,
);
drupal_set_title('');
}
else {
drupal_set_title(t('Welcome to @site-name', array('@site-name' => variable_get('site_name', 'Drupal'))), PASS_THROUGH);
$default_message = '<p>' . t('No front page content has been created yet.') . '</p>';
$default_links = array();
if (_node_add_access()) {
$default_links[] = l(t('Create content'), 'node/add');
}
if (user_access('administer site configuration')) {
$default_links[] = l(t('Change the default front page'), 'admin/config/system/site-information');
}
if (!empty($default_links)) {
$default_message .= theme('item_list', array('items' => $default_links));
}
$build['default_message'] = array(
'#markup' => $default_message,
'#prefix' => '<div id="first-time">',
'#suffix' => '</div>',
);
}
return $build;
}
function node_page_view($node) {
$return = node_show($node);
if (isset($return['nodes'][$node->nid]['title'])) {
$langcode = $return['nodes'][$node->nid]['title']['#language'];
drupal_set_title($node->title[$langcode][0]['value']);
}
drupal_add_html_head_link(array('rel' => 'canonical', 'href' => url('node/' . $node->nid)), TRUE);
drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => url('node/' . $node->nid, array('alias' => TRUE))), TRUE);
return $return;
}
function node_update_index() {
$limit = (int)variable_get('search_cron_limit', 100);
$result = db_query_range("SELECT n.nid FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE d.sid IS NULL OR d.reindex <> 0 ORDER BY d.reindex ASC, n.nid ASC", 0, $limit, array(), array('target' => 'slave'));
foreach ($result as $node) {
_node_index_node($node);
}
}
function _node_index_node($node) {
$node = node_load($node->nid);
variable_set('node_cron_last', $node->changed);
$build = node_build($node, 'search_index');
unset($build['#theme']);
$node->rendered = drupal_render($build);
$text = '<h1>' . check_plain($node->title[LANGUAGE_NONE][0]['value']) . '</h1>' . $node->rendered;
$extra = module_invoke_all('node_update_index', $node);
foreach ($extra as $t) {
$text .= $t;
}
search_index($node->nid, 'node', $text);
}
function node_form_search_form_alter(&$form, $form_state) {
if ($form['module']['#value'] == 'node' && user_access('use advanced search')) {
$form['advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced search'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#attributes' => array('class' => array('search-advanced')),
);
$form['advanced']['keywords'] = array(
'#prefix' => '<div class="criterion">',
'#suffix' => '</div>',
);
$form['advanced']['keywords']['or'] = array(
'#type' => 'textfield',
'#title' => t('Containing any of the words'),
'#size' => 30,
'#maxlength' => 255,
);
$form['advanced']['keywords']['phrase'] = array(
'#type' => 'textfield',
'#title' => t('Containing the phrase'),
'#size' => 30,
'#maxlength' => 255,
);
$form['advanced']['keywords']['negative'] = array(
'#type' => 'textfield',
'#title' => t('Containing none of the words'),
'#size' => 30,
'#maxlength' => 255,
);
if ($taxonomy = module_invoke('taxonomy', 'form_all', 1)) {
$form['advanced']['term'] = array(
'#type' => 'select',
'#title' => t('Only in the term(s)'),
'#prefix' => '<div class="criterion">',
'#size' => 10,
'#suffix' => '</div>',
'#options' => $taxonomy,
'#multiple' => TRUE,
);
}
$types = array_map('check_plain', node_type_get_names());
$form['advanced']['type'] = array(
'#type' => 'checkboxes',
'#title' => t('Only of the type(s)'),
'#prefix' => '<div class="criterion">',
'#suffix' => '</div>',
'#options' => $types,
);
$form['advanced']['submit'] = array(
'#type' => 'submit',
'#value' => t('Advanced search'),
'#prefix' => '<div class="action">',
'#suffix' => '</div>',
);
$language_options = array();
foreach (language_list('language') as $key => $object) {
$language_options[$key] = $object->name;
}
if (count($language_options) > 1) {
$form['advanced']['language'] = array(
'#type' => 'checkboxes',
'#title' => t('Languages'),
'#prefix' => '<div class="criterion">',
'#suffix' => '</div>',
'#options' => $language_options,
);
}
$form['#validate'][] = 'node_search_validate';
}
}
function node_search_validate($form, &$form_state) {
$keys = $form_state['values']['processed_keys'];
if (isset($form_state['values']['type']) && is_array($form_state['values']['type'])) {
$form_state['values']['type'] = array_filter($form_state['values']['type']);
if (count($form_state['values']['type'])) {
$keys = search_expression_insert($keys, 'type', implode(',', array_keys($form_state['values']['type'])));
}
}
if (isset($form_state['values']['term']) && is_array($form_state['values']['term'])) {
$keys = search_expression_insert($keys, 'term', implode(',', $form_state['values']['term']));
}
if (isset($form_state['values']['language']) && is_array($form_state['values']['language'])) {
$keys = search_expression_insert($keys, 'language', implode(',', array_filter($form_state['values']['language'])));
}
if ($form_state['values']['or'] != '') {
if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' ' . $form_state['values']['or'], $matches)) {
$keys .= ' ' . implode(' OR ', $matches[1]);
}
}
if ($form_state['values']['negative'] != '') {
if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' ' . $form_state['values']['negative'], $matches)) {
$keys .= ' -' . implode(' -', $matches[1]);
}
}
if ($form_state['values']['phrase'] != '') {
$keys .= ' "' . str_replace('"', ' ', $form_state['values']['phrase']) . '"';
}
if (!empty($keys)) {
form_set_value($form['basic']['inline']['processed_keys'], trim($keys), $form_state);
}
}
function node_access($op, $node, $account = NULL) {
global $user;
if (!$node || !in_array($op, array('view', 'update', 'delete', 'create'), TRUE)) {
return FALSE;
}
if (empty($account)) {
$account = $user;
}
if (user_access('bypass node access', $account)) {
return TRUE;
}
if (!user_access('access content', $account)) {
return FALSE;
}
$access = module_invoke_all('node_access', $node, $op, $account);
if (in_array(NODE_ACCESS_DENY, $access, TRUE)) {
return FALSE;
}
elseif (in_array(NODE_ACCESS_ALLOW, $access, TRUE)) {
return TRUE;
}
if ($op == 'view' && !$node->status && user_access('view own unpublished content', $account) && $account->uid == $node->uid && $account->uid != 0) {
return TRUE;
}
if ($op != 'create' && $node->nid) {
$query = db_select('node_access');
$query->addExpression('1');
$query->condition('grant_' . $op, 1, '>=');
$nids = db_or()->condition('nid', $node->nid);
if ($node->status) {
$nids->condition('nid', 0);
}
$query->condition($nids);
$query->range(0, 1);
$grants = db_or();
foreach (node_access_grants($op, $account) as $realm => $gids) {
foreach ($gids as $gid) {
$grants->condition(db_and()
->condition('gid', $gid)
->condition('realm', $realm)
);
}
}
if (count($grants) > 0) {
$query->condition($grants);
}
return (bool) $query
->execute()
->fetchField();
}
return FALSE;
}
function node_node_access($node, $op, $account) {
$type = is_string($node) ? $node : $node->type;
if (in_array($type, node_permissions_get_configured_types())) {
if ($op == 'create' && user_access('create ' . $type . ' content', $account)) {
return NODE_ACCESS_ALLOW;
}
if ($op == 'update') {
if (user_access('edit any ' . $type . ' content', $account) || (user_access('edit own ' . $type . ' content', $account) && ($account->uid == $node->uid))) {
return NODE_ACCESS_ALLOW;
}
}
if ($op == 'delete') {
if (user_access('delete any ' . $type . ' content', $account) || (user_access('delete own ' . $type . ' content', $account) && ($account->uid == $node->uid))) {
return NODE_ACCESS_ALLOW;
}
}
}
return NODE_ACCESS_IGNORE;
}
function node_list_permissions($type) {
$info = node_type_get_type($type);
$type = check_plain($info->type);
$perms = array(
"create $type content" => array(
'title' => t('Create new %type_name content', array('%type_name' => $info->name)),
),
"edit own $type content" => array(
'title' => t('Edit own %type_name content', array('%type_name' => $info->name)),
),
"edit any $type content" => array(
'title' => t('Edit any %type_name content', array('%type_name' => $info->name)),
),
"delete own $type content" => array(
'title' => t('Delete own %type_name content', array('%type_name' => $info->name)),
),
"delete any $type content" => array(
'title' => t('Delete any %type_name content', array('%type_name' => $info->name)),
),
);
return $perms;
}
function node_permissions_get_configured_types() {
$configured_types = array();
foreach (node_type_get_types() as $type => $info) {
if (variable_get('node_permissions_' . $type, 1)) {
$configured_types[] = $type;
}
}
return $configured_types;
}
function node_access_grants($op, $account = NULL) {
if (!isset($account)) {
$account = $GLOBALS['user'];
}
$grants = module_invoke_all('node_grants', $account, $op);
drupal_alter('node_grants', $grants, $account, $op);
return array_merge(array('all' => array(0)), $grants);
}
function node_access_view_all_nodes() {
static $access;
if (!isset($access)) {
if (!module_implements('node_grants')) {
$access = TRUE;
}
else {
$query = db_select('node_access');
$query->addExpression('COUNT(*)');
$query
->condition('nid', 0)
->condition('grant_view', 1, '>=');
$grants = db_or();
foreach (node_access_grants('view') as $realm => $gids) {
foreach ($gids as $gid) {
$grants->condition(db_and()
->condition('gid', $gid)
->condition('realm', $realm)
);
}
}
if (count($grants) > 0 ) {
$query->condition($grants);
}
$access = $query
->execute()
->fetchField();
}
}
return $access;
}
function node_query_node_access_alter(QueryAlterableInterface $query) {
if (!node_access_view_all_nodes()) {
$query->distinct();
if (!$op = $query->getMetaData('op')) {
$op = 'view';
}
if (!user_access('bypass node access')) {
$access_alias = $query->join('node_access', 'na', 'na.nid = n.nid');
$or = db_or();
foreach (node_access_grants($op, $query->getMetaData('account')) as $realm => $gids) {
foreach ($gids as $gid) {
$or->condition(db_and()
->condition("{$access_alias}.gid", $gid)
->condition("{$access_alias}.realm", $realm)
);
}
}
if (count($or->conditions())) {
$query->condition($or);
}
$query->condition("{$access_alias}.grant_$op", 1, '>=');
}
}
}
function node_access_acquire_grants($node) {
$grants = module_invoke_all('node_access_records', $node);
drupal_alter('node_access_records', $grants, $node);
if (empty($grants)) {
$grants[] = array('realm' => 'all', 'gid' => 0, 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0);
}
else {
$grant_by_priority = array();
foreach ($grants as $g) {
$grant_by_priority[intval($g['priority'])][] = $g;
}
krsort($grant_by_priority);
$grants = array_shift($grant_by_priority);
}
node_access_write_grants($node, $grants);
}
function node_access_write_grants($node, $grants, $realm = NULL, $delete = TRUE) {
if ($delete) {
$query = db_delete('node_access')->condition('nid', $node->nid);
if ($realm) {
$query->condition('realm', array($realm, 'all'), 'IN');
}
$query->execute();
}
if (count(module_implements('node_grants'))) {
$query = db_insert('node_access')->fields(array('nid', 'realm', 'gid', 'grant_view', 'grant_update', 'grant_delete'));
foreach ($grants as $grant) {
if ($realm && $realm != $grant['realm']) {
continue;
}
if ($grant['grant_view'] || $grant['grant_update'] || $grant['grant_delete']) {
$grant['nid'] = $node->nid;
$query->values($grant);
}
}
$query->execute();
}
}
function node_access_needs_rebuild($rebuild = NULL) {
if (!isset($rebuild)) {
return variable_get('node_access_needs_rebuild', FALSE);
}
elseif ($rebuild) {
variable_set('node_access_needs_rebuild', TRUE);
}
else {
variable_del('node_access_needs_rebuild');
}
}
function node_access_rebuild($batch_mode = FALSE) {
db_delete('node_access')->execute();
if (count(module_implements('node_grants'))) {
if ($batch_mode) {
$batch = array(
'title' => t('Rebuilding content access permissions'),
'operations' => array(
array('_node_access_rebuild_batch_operation', array()),
),
'finished' => '_node_access_rebuild_batch_finished'
);
batch_set($batch);
}
else {
drupal_set_time_limit(240);
$nids = db_query("SELECT nid FROM {node}")->fetchCol();
foreach ($nids as $nid) {
$node = node_load($nid, NULL, TRUE);
if (!empty($node)) {
node_access_acquire_grants($node);
}
}
}
}
else {
db_insert('node_access')
->fields(array(
'nid' => 0,
'realm' => 'all',
'gid' => 0,
'grant_view' => 1,
'grant_update' => 0,
'grant_delete' => 0,
))
->execute();
}
if (!isset($batch)) {
drupal_set_message(t('Content permissions have been rebuilt.'));
node_access_needs_rebuild(FALSE);
cache_clear_all();
}
}
function _node_access_rebuild_batch_operation(&$context) {
if (empty($context['sandbox'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['current_node'] = 0;
$context['sandbox']['max'] = db_query('SELECT COUNT(DISTINCT nid) FROM {node}')->fetchField();
}
$limit = 20;
$nids = db_query_range("SELECT nid FROM {node} WHERE nid > :nid ORDER BY nid ASC", 0, $limit, array(':nid' => $context['sandbox']['current_node']))->fetchCol();
$nodes = node_load_multiple($nids, array(), TRUE);
foreach ($nodes as $node) {
if (!empty($node)) {
node_access_acquire_grants($node);
}
$context['sandbox']['progress']++;
$context['sandbox']['current_node'] = $node->nid;
}
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
function _node_access_rebuild_batch_finished($success, $results, $operations) {
if ($success) {
drupal_set_message(t('The content access permissions have been rebuilt.'));
node_access_needs_rebuild(FALSE);
}
else {
drupal_set_message(t('The content access permissions have not been properly rebuilt.'), 'error');
}
cache_clear_all();
}
function node_content_form($node, $form_state) {
return array();
}
function node_forms() {
$forms = array();
if ($types = node_type_get_types()) {
foreach (array_keys($types) as $type) {
$forms[$type . '_node_form']['callback'] = 'node_form';
}
}
return $forms;
}
function node_action_info() {
return array(
'node_publish_action' => array(
'type' => 'node',
'label' => t('Publish content'),
'configurable' => FALSE,
'behavior' => array('changes_property'),
'triggers' => array('node_presave', 'comment_insert', 'comment_update', 'comment_delete'),
),
'node_unpublish_action' => array(
'type' => 'node',
'label' => t('Unpublish content'),
'configurable' => FALSE,
'behavior' => array('changes_property'),
'triggers' => array('node_presave', 'comment_insert', 'comment_update', 'comment_delete'),
),
'node_make_sticky_action' => array(
'type' => 'node',
'label' => t('Make content sticky'),
'configurable' => FALSE,
'behavior' => array('changes_property'),
'triggers' => array('node_presave', 'comment_insert', 'comment_update', 'comment_delete'),
),
'node_make_unsticky_action' => array(
'type' => 'node',
'label' => t('Make content unsticky'),
'configurable' => FALSE,
'behavior' => array('changes_property'),
'triggers' => array('node_presave', 'comment_insert', 'comment_update', 'comment_delete'),
),
'node_promote_action' => array(
'type' => 'node',
'label' => t('Promote content to front page'),
'configurable' => FALSE,
'behavior' => array('changes_property'),
'triggers' => array('node_presave', 'comment_insert', 'comment_update', 'comment_delete'),
),
'node_unpromote_action' => array(
'type' => 'node',
'label' => t('Remove content from front page'),
'configurable' => FALSE,
'behavior' => array('changes_property'),
'triggers' => array('node_presave', 'comment_insert', 'comment_update', 'comment_delete'),
),
'node_assign_owner_action' => array(
'type' => 'node',
'label' => t('Change the author of content'),
'configurable' => TRUE,
'behavior' => array('changes_property'),
'triggers' => array('node_presave', 'comment_insert', 'comment_update', 'comment_delete'),
),
'node_save_action' => array(
'type' => 'node',
'label' => t('Save content'),
'configurable' => FALSE,
'triggers' => array('comment_insert', 'comment_update', 'comment_delete'),
),
'node_unpublish_by_keyword_action' => array(
'type' => 'node',
'label' => t('Unpublish content containing keyword(s)'),
'configurable' => TRUE,
'triggers' => array('node_presave', 'node_insert', 'node_update'),
),
);
}
function node_publish_action($node, $context = array()) {
$node->status = NODE_PUBLISHED;
watchdog('action', 'Set @type %title to published.', array('@type' => node_type_get_name($node), '%title' => $node->title[LANGUAGE_NONE][0]['value']));
}
function node_unpublish_action($node, $context = array()) {
$node->status = NODE_NOT_PUBLISHED;
watchdog('action', 'Set @type %title to unpublished.', array('@type' => node_type_get_name($node), '%title' => $node->title[LANGUAGE_NONE][0]['value']));
}
function node_make_sticky_action($node, $context = array()) {
$node->sticky = NODE_STICKY;
watchdog('action', 'Set @type %title to sticky.', array('@type' => node_type_get_name($node), '%title' => $node->title[LANGUAGE_NONE][0]['value']));
}
function node_make_unsticky_action($node, $context = array()) {
$node->sticky = NODE_NOT_STICKY;
watchdog('action', 'Set @type %title to unsticky.', array('@type' => node_type_get_name($node), '%title' => $node->title[LANGUAGE_NONE][0]['value']));
}
function node_promote_action($node, $context = array()) {
$node->promote = NODE_PROMOTED;
watchdog('action', 'Promoted @type %title to front page.', array('@type' => node_type_get_name($node), '%title' => $node->title[LANGUAGE_NONE][0]['value']));
}
function node_unpromote_action($node, $context = array()) {
$node->promote = NODE_NOT_PROMOTED;
watchdog('action', 'Removed @type %title from front page.', array('@type' => node_type_get_name($node), '%title' => $node->title[LANGUAGE_NONE][0]['value']));
}
function node_save_action($node) {
node_save($node);
watchdog('action', 'Saved @type %title', array('@type' => node_type_get_name($node), '%title' => $node->title[LANGUAGE_NONE][0]['value']));
}
function node_assign_owner_action($node, $context) {
$node->uid = $context['owner_uid'];
$owner_name = db_query("SELECT name FROM {users} WHERE uid = :uid", array(':uid' => $context['owner_uid']))->fetchField();
watchdog('action', 'Changed owner of @type %title to uid %name.', array('@type' => node_type_get_type($node), '%title' => $node->title[LANGUAGE_NONE][0]['value'], '%name' => $owner_name));
}
function node_assign_owner_action_form($context) {
$description = t('The username of the user to which you would like to assign ownership.');
$count = db_query("SELECT COUNT(*) FROM {users}")->fetchField();
$owner_name = '';
if (isset($context['owner_uid'])) {
$owner_name = db_query("SELECT name FROM {users} WHERE uid = :uid", array(':uid' => $context['owner_uid']))->fetchField();
}
if (intval($count) < 200) {
$options = array();
$result = db_query("SELECT uid, name FROM {users} WHERE uid > 0 ORDER BY name");
foreach ($result as $data) {
$options[$data->name] = $data->name;
}
$form['owner_name'] = array(
'#type' => 'select',
'#title' => t('Username'),
'#default_value' => $owner_name,
'#options' => $options,
'#description' => $description,
);
}
else {
$form['owner_name'] = array(
'#type' => 'textfield',
'#title' => t('Username'),
'#default_value' => $owner_name,
'#autocomplete_path' => 'user/autocomplete',
'#size' => '6',
'#maxlength' => '60',
'#description' => $description,
);
}
return $form;
}
function node_assign_owner_action_validate($form, $form_state) {
$exists = (bool) db_query_range('SELECT 1 FROM {users} WHERE name = :name', 0, 1, array(':name' => $form_state['values']['owner_name']))->fetchField();
if (!$exists) {
form_set_error('owner_name', t('Please enter a valid username.'));
}
}
function node_assign_owner_action_submit($form, $form_state) {
$uid = db_query('SELECT uid from {users} WHERE name = :name', array(':name' => $form_state['values']['owner_name']))->fetchField();
return array('owner_uid' => $uid);
}
function node_unpublish_by_keyword_action_form($context) {
$form['keywords'] = array(
'#title' => t('Keywords'),
'#type' => 'textarea',
'#description' => t('The content will be unpublished if it contains any of the phrases above. Use a case-sensitive, comma-separated list of phrases. Example: funny, bungee jumping, "Company, Inc."'),
'#default_value' => isset($context['keywords']) ? drupal_implode_tags($context['keywords']) : '',
);
return $form;
}
function node_unpublish_by_keyword_action_submit($form, $form_state) {
return array('keywords' => drupal_explode_tags($form_state['values']['keywords']));
}
function node_unpublish_by_keyword_action($node, $context) {
foreach ($context['keywords'] as $keyword) {
if (strpos(drupal_render(node_build(clone $node)), $keyword) !== FALSE || strpos($node->title, $keyword) !== FALSE) {
$node->status = NODE_NOT_PUBLISHED;
watchdog('action', 'Set @type %title to unpublished.', array('@type' => node_type_get_name($node), '%title' => $node->title[LANGUAGE_NONE][0]['value']));
break;
}
}
}
function node_requirements($phase) {
$requirements = array();
$t = get_t();
$grant_count = db_query('SELECT COUNT(*) FROM {node_access}')->fetchField();
if ($grant_count != 1 || count(module_implements('node_grants')) > 0) {
$value = format_plural($grant_count, 'One permission in use', '@count permissions in use', array('@count' => $grant_count));
} else {
$value = $t('Disabled');
}
$description = $t('If the site is experiencing problems with permissions to content, you may have to rebuild the permissions cache. Rebuilding will remove all privileges to content and replace them with permissions based on the current modules and settings. Rebuilding may take some time if there is a lot of content or complex permission settings. After rebuilding has completed, content will automatically use the new permissions.');
$requirements['node_access'] = array(
'title' => $t('Node Access Permissions'),
'value' => $value,
'description' => $description . ' ' . l(t('Rebuild permissions'), 'admin/reports/status/rebuild'),
);
return $requirements;
}
class NodeController extends DrupalDefaultEntityController {
protected function attachLoad(&$nodes) {
$typed_nodes = array();
foreach ($nodes as $id => $object) {
unset($object->title);
$typed_nodes[$object->type][$id] = $object;
}
foreach ($typed_nodes as $node_type => $nodes_of_type) {
if (node_hook($node_type, 'load')) {
$function = node_type_get_base($node_type) . '_load';
$function($nodes_of_type);
}
}
$this->hookLoadArguments[] = array_keys($typed_nodes);
parent::attachLoad($nodes);
}
}