Commit d6d7c227 authored by KarenS's avatar KarenS

Add sanitize operation to nodereference to select only nodes the user has access to.

parent 6dd9b4e4
......@@ -14,7 +14,8 @@ function nodereference_menu() {
$items['nodereference/autocomplete'] = array(
'title' => 'Nodereference autocomplete',
'page callback' => 'nodereference_autocomplete',
'access arguments' => array('access content'),
'access callback' => 'nodereference_autocomplete_access',
'access arguments' => array(2),
'type' => MENU_CALLBACK
);
return $items;
......@@ -181,6 +182,8 @@ function nodereference_field_settings($op, $field) {
* Implementation of hook_field().
*/
function nodereference_field($op, &$node, $field, &$items, $teaser, $page) {
static $sanitized_nodes = array();
switch ($op) {
// When preparing a translation, load any translations of existing references.
case 'prepare translation':
......@@ -231,6 +234,43 @@ function nodereference_field($op, &$node, $field, &$items, $teaser, $page) {
}
}
return $items;
case 'sanitize':
// We can't just check the node is 'referenceable', because Views-mode
// could rely on 'current user' (at edit time).
// Extract nids to check.
$ids = array();
foreach ($items as $delta => $item) {
if (is_array($item)) {
// Default to 'non accessible'.
$items[$delta]['safe'] = array();
if (!empty($item['nid']) && is_numeric($item['nid'])) {
$ids[] = $item['nid'];
}
}
}
if ($ids) {
// Load information about nids that we haven't already loaded during
// this page request.
$missing_ids = array_diff($ids, array_keys($sanitized_nodes));
if (!empty($missing_ids)) {
$where = array('n.nid in ('. db_placeholders($missing_ids) . ')');
if (!user_access('administer nodes')) {
$where[] = 'n.status = 1';
}
$result = db_query(db_rewrite_sql('SELECT n.nid, n.title, n.status FROM {node} n WHERE '. implode(' AND ', $where)), $missing_ids);
while ($row = db_fetch_array($result)) {
$sanitized_nodes[$row['nid']] = $row;
}
}
foreach ($items as $delta => $item) {
if (is_array($item) && !empty($item['nid']) && isset($sanitized_nodes[$item['nid']])) {
$items[$delta]['safe'] = $sanitized_nodes[$item['nid']];
}
}
}
return $items;
}
}
......@@ -277,9 +317,12 @@ function nodereference_field_formatter_info() {
*/
function theme_nodereference_formatter_default($element) {
$output = '';
if (!empty($element['#item']['nid']) && is_numeric($element['#item']['nid']) && ($title = _nodereference_titles($element['#item']['nid']))) {
$output = l($title, 'node/'. $element['#item']['nid']);
}
if (!empty($element['#item']['safe']['nid'])) {
$output = l($element['#item']['safe']['title'], 'node/'. $element['#item']['safe']['nid']);
if (!$element['#item']['safe']['status']) {
$output = '<span class="node-unpublished"> '. t('(Unpublished)') ." $output</span>";
}
}
return $output;
}
......@@ -288,8 +331,11 @@ function theme_nodereference_formatter_default($element) {
*/
function theme_nodereference_formatter_plain($element) {
$output = '';
if (!empty($element['#item']['nid']) && is_numeric($element['#item']['nid']) && ($title = _nodereference_titles($element['#item']['nid']))) {
$output = check_plain($title);
if (!empty($element['#item']['safe']['nid'])) {
$output = check_plain($element['#item']['safe']['title']);
if (!$element['#item']['safe']['status']) {
$output = '<span class="node-unpublished"> '. t('(Unpublished)') ." $output</span>";
}
}
return $output;
}
......@@ -300,7 +346,8 @@ function theme_nodereference_formatter_plain($element) {
function theme_nodereference_formatter_full_teaser($element) {
static $recursion_queue = array();
$output = '';
if (!empty($element['#item']['nid']) && is_numeric($element['#item']['nid'])) {
if (!empty($element['#item']['safe']['nid'])) {
$nid = $element['#item']['safe']['nid'];
$node = $element['#node'];
$field = content_fields($element['#field_name'], $element['#type_name']);
// If no 'referencing node' is set, we are starting a new 'reference thread'
......@@ -308,18 +355,16 @@ function theme_nodereference_formatter_full_teaser($element) {
$recursion_queue = array();
}
$recursion_queue[] = $node->nid;
if (in_array($element['#item']['nid'], $recursion_queue)) {
if (in_array($nid, $recursion_queue)) {
// Prevent infinite recursion caused by reference cycles:
// if the node has already been rendered earlier in this 'thread',
// we fall back to 'default' (node title) formatter.
return theme('nodereference_formatter_default', $element);
}
if ($referenced_node = node_load($element['#item']['nid'])) {
if (_nodereference_titles($element['#item']['nid'])) {
$referenced_node->referencing_node = $node;
$referenced_node->referencing_field = $field;
$output = node_view($referenced_node, $element['#formatter'] == 'teaser');
}
if ($referenced_node = node_load($nid)) {
$referenced_node->referencing_node = $node;
$referenced_node->referencing_field = $field;
$output = node_view($referenced_node, $element['#formatter'] == 'teaser');
}
}
return $output;
......@@ -908,6 +953,16 @@ function _nodereference_potential_references_standard($field, $string = '', $mat
return $references;
}
/**
* Check access to the menu callback of the autocomplete widget.
*
* Check for both 'edit' and 'view' access in the unlikely event
* a user has edit but not view access.
*/
function nodereference_autocomplete_access($field_name) {
return user_access('access content') && ($field = content_fields($field_name)) && content_access('view', $field) && content_access('edit', $field);
}
/**
* Menu callback; Retrieve a pipe delimited string of autocomplete suggestions for existing users
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment