View source
<?php
define('PREV_NEXT_BATCH_SIZE_DEFAULT', 200);
define('PREV_NEXT_INDEXING_CRITERIA_DEFAULT', 'nid');
define('PREV_NEXT_NODE_TYPE', 'prev_next_node_type_');
define('PREV_NEXT_NUM_BLOCKS_DEFAULT', 1);
define('PREV_NEXT_DISPLAY_DEFAULT', 1);
define('PREV_NEXT_DISPLAY_TEXT_PREV_DEFAULT', '«[node:title]');
define('PREV_NEXT_DISPLAY_TEXT_NEXT_DEFAULT', '[node:title]»');
module_load_include('inc', 'prev_next', 'prev_next.block');
function prev_next_menu() {
$items['admin/config/system/prev_next'] = array(
'title' => 'Prev/Next',
'description' => 'Prev/Next API for nodes',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'prev_next_admin',
),
'access arguments' => array(
'administer prev_next',
),
'file' => 'prev_next.admin.inc',
'file path' => drupal_get_path('module', 'prev_next'),
);
$items['admin/config/system/prev_next/re-index'] = array(
'title' => 'Prev/Next reset',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'prev_next_reindex_confirm',
),
'access arguments' => array(
'administer prev_next',
),
'file' => 'prev_next.admin.inc',
'file path' => drupal_get_path('module', 'prev_next'),
);
return $items;
}
function prev_next_reindex() {
db_query('TRUNCATE {prev_next_node}');
$max_nid = db_query('SELECT MAX(nid) FROM {node}')
->fetchField();
variable_set('prev_next_index_nid', $max_nid);
if ($max_nid) {
drupal_set_message(t('Prev/Next will index from node %nid downward.', array(
'%nid' => $max_nid,
)));
}
}
function prev_next_cron() {
$max_nid = variable_get('prev_next_index_nid', 0);
if ($max_nid) {
$batch_size = variable_get('prev_next_batch_size', PREV_NEXT_BATCH_SIZE_DEFAULT);
$last_nid = FALSE;
$cond = _prev_next_node_types_sql();
timer_start('prev_next_cron');
$result = db_query_range("SELECT nid FROM {node} WHERE nid <= :nid AND status = 1 {$cond} ORDER BY nid DESC", 0, $batch_size, array(
':nid' => $max_nid,
));
$count = 0;
foreach ($result as $row) {
db_delete('prev_next_node')
->condition('nid', $row->nid)
->execute();
_prev_next_add($row->nid);
$last_nid = $row->nid;
$count++;
}
$time = timer_read('prev_next_cron');
if ($last_nid !== FALSE) {
variable_set('prev_next_index_nid', $last_nid - 1);
}
else {
variable_set('prev_next_index_nid', 0);
}
if ($count) {
watchdog('prev_next', 'Indexed %count nodes in %time milliseconds.', array(
'%count' => $count,
'%time' => $time,
));
}
$total = db_query("SELECT COUNT(nid) FROM {node} WHERE status = 1 {$cond}")
->fetchField();
$completed = db_query("SELECT COUNT(nid) FROM {prev_next_node}")
->fetchField();
$remaining = max(0, $total - $completed);
drupal_set_message(t('Indexed %count nodes for the Prev/Next index. There are %remaining items left to index.', array(
'%count' => $count,
'%remaining' => $remaining,
)));
}
}
function _prev_next_add($nid) {
$node_type = db_query_range("SELECT type\n FROM {node}\n WHERE nid = :nid", 0, 1, array(
':nid' => $nid,
))
->fetchField();
$search_criteria = variable_get(PREV_NEXT_NODE_TYPE . $node_type . '_indexing_criteria', PREV_NEXT_INDEXING_CRITERIA_DEFAULT);
$join = _prev_next_category_sql($node_type);
if (strlen($join) > 0) {
$category = variable_get(PREV_NEXT_NODE_TYPE . $node_type . '_category_criteria', 'none');
$category_id = db_query("SELECT " . $category . "_tid FROM {field_data_" . $category . "} WHERE entity_id = :nid", array(
':nid' => $nid,
))
->fetchField();
if (empty($category_id)) {
$cond = '';
}
else {
$cond = " AND " . $category . "_tid = " . $category_id . " ";
$cond .= _prev_next_node_types_sql($node_type);
}
}
else {
$cond = _prev_next_node_types_sql($node_type);
}
if ($search_criteria != 'nid') {
$criteria_value = db_query_range("SELECT {$search_criteria}\n FROM {node}\n WHERE nid = :nid", 0, 1, array(
':nid' => $nid,
))
->fetchField();
$next_nid = db_query_range("SELECT nid FROM {node}\n {$join}\n WHERE (({$search_criteria} = :value AND nid > :nid)\n OR {$search_criteria} > :value)\n AND status = 1\n {$cond} ORDER BY\n {$search_criteria} ASC,nid ASC", 0, 1, array(
':value' => $criteria_value,
':nid' => $nid,
))
->fetchField();
$prev_nid = db_query_range("SELECT nid FROM {node}\n {$join}\n WHERE (({$search_criteria} = :value\n AND nid < :nid)\n OR {$search_criteria} < :value)\n AND status = 1\n {$cond}\n ORDER BY {$search_criteria} DESC,nid DESC", 0, 1, array(
':value' => $criteria_value,
':nid' => $nid,
))
->fetchField();
}
else {
$next_nid = db_query_range("SELECT nid\n FROM {node}\n {$join}\n WHERE nid > :nid\n AND status = 1 {$cond} ORDER BY nid ASC", 0, 1, array(
':nid' => $nid,
))
->fetchField();
$prev_nid = db_query_range("SELECT nid\n FROM {node}\n {$join}\n WHERE nid < :nid\n AND status = 1\n {$cond} ORDER BY nid DESC", 0, 1, array(
':nid' => $nid,
))
->fetchField();
}
$exists = (bool) db_query_range('SELECT 1
FROM {prev_next_node}
WHERE nid = :nid', 0, 1, array(
':nid' => $nid,
))
->fetchField();
if (!empty($exists)) {
db_update('prev_next_node')
->fields(array(
'prev_nid' => $prev_nid ? $prev_nid : 0,
'next_nid' => $next_nid ? $next_nid : 0,
'changed' => REQUEST_TIME,
))
->condition('nid', $nid)
->execute();
}
else {
$id = db_insert('prev_next_node')
->fields(array(
'prev_nid' => $prev_nid ? $prev_nid : 0,
'next_nid' => $next_nid ? $next_nid : 0,
'changed' => REQUEST_TIME,
'nid' => $nid,
))
->execute();
}
foreach (node_type_get_types() as $type => $name) {
if (variable_get(PREV_NEXT_NODE_TYPE . $type, 0)) {
$search_criteria = variable_get(PREV_NEXT_NODE_TYPE . $type . '_indexing_criteria', PREV_NEXT_INDEXING_CRITERIA_DEFAULT);
$join = _prev_next_category_sql($node_type);
if (strlen($join) > 0) {
$category = variable_get(PREV_NEXT_NODE_TYPE . $node_type . '_category_criteria', 'none');
$category_id = db_query("SELECT " . $category . "_tid FROM {field_data_" . $category . "} WHERE entity_id = :nid", array(
':nid' => $nid,
))
->fetchField();
if (empty($category_id)) {
$cond = '';
watchdog('prev_next', 'Node ' . $nid . ' missing taxonomy id for field_data_' . $category, WATCHDOG_ERROR);
}
else {
$cond = " AND " . $category . "_tid = " . $category_id . " ";
$cond .= _prev_next_node_types_sql($node_type);
}
}
else {
$cond = _prev_next_node_types_sql($node_type);
}
if ($search_criteria != 'nid') {
$criteria_value = db_query_range("SELECT {$search_criteria}\n FROM {node}\n WHERE nid = :nid", 0, 1, array(
':nid' => $nid,
))
->fetchField();
$prev_nid = db_query_range("SELECT nid\n FROM {node}\n {$join}\n WHERE (({$search_criteria} = :value\n AND nid < :nid)\n OR {$search_criteria} < :value)\n AND status = 1\n {$cond} ORDER BY {$search_criteria} DESC,nid DESC", 0, 1, array(
':value' => $criteria_value,
':nid' => $nid,
))
->fetchField();
$next_nid = db_query_range("SELECT nid\n FROM {node}\n {$join}\n WHERE (({$search_criteria} = :value\n AND nid > :nid)\n OR {$search_criteria} > :value)\n AND status = 1\n {$cond} ORDER BY\n {$search_criteria} ASC,nid ASC", 0, 1, array(
':value' => $criteria_value,
':nid' => $nid,
))
->fetchField();
}
else {
$prev_nid = db_query_range("SELECT nid\n FROM {node}\n {$join}\n WHERE nid < :nid\n AND status = 1\n {$cond}\n ORDER BY nid DESC", 0, 1, array(
':nid' => $nid,
))
->fetchField();
$next_nid = db_query_range("SELECT nid\n FROM {node}\n {$join}\n WHERE nid > :nid\n AND status = 1\n {$cond}\n ORDER BY nid ASC", 0, 1, array(
':nid' => $nid,
))
->fetchField();
}
}
if ($next_nid) {
db_update('prev_next_node')
->fields(array(
'next_nid' => $next_nid ? $next_nid : 0,
))
->condition('nid', $nid)
->execute();
}
if ($prev_nid) {
db_update('prev_next_node')
->fields(array(
'prev_nid' => $prev_nid ? $prev_nid : 0,
))
->condition('nid', $nid)
->execute();
}
}
}
function _prev_next_modify($nid) {
_prev_next_modify_pointing_nodes($nid);
_prev_next_add($nid);
}
function _prev_next_remove($nid) {
db_delete('prev_next_node')
->condition('nid', $nid)
->execute();
_prev_next_modify_pointing_nodes($nid);
}
function _prev_next_modify_pointing_nodes($nid) {
$prev = db_query("SELECT nid\n FROM {prev_next_node}\n WHERE prev_nid = :prev_nid", array(
':prev_nid' => $nid,
))
->fetchField();
if ($prev) {
_prev_next_add($prev);
}
$next = db_query("SELECT nid\n FROM {prev_next_node}\n WHERE next_nid = :next_nid", array(
':next_nid' => $nid,
))
->fetchField();
if ($next) {
_prev_next_add($next);
}
}
function prev_next_node_insert($node) {
$types = _prev_next_node_types();
if (in_array($node->type, $types)) {
_prev_next_add($node->nid);
}
}
function prev_next_node_update($node) {
$types = _prev_next_node_types();
if (in_array($node->type, $types)) {
_prev_next_modify($node->nid);
}
}
function prev_next_node_delete($node) {
$_SESSION['prev_next_remove_nids'][] = $node->nid;
}
function prev_next_nid($nid, $op = 'next') {
foreach (module_implements('prev_next_nid') as $module) {
$function = $module . '_prev_next_nid';
$ret = $function($nid, $op);
if ($ret !== FALSE) {
return $ret;
}
}
switch ($op) {
case 'prev':
return prev_next_nid_prev($nid);
break;
case 'next':
return prev_next_nid_next($nid);
break;
default:
return 0;
}
}
function prev_next_nid_next($nid) {
return db_query("SELECT next_nid\n FROM {prev_next_node}\n WHERE nid = :nid", array(
':nid' => $nid,
))
->fetchField();
}
function prev_next_nid_prev($nid) {
return db_query("SELECT prev_nid\n FROM {prev_next_node}\n WHERE nid = :nid", array(
':nid' => $nid,
))
->fetchField();
}
function _prev_next_node_types() {
$types = array();
foreach (node_type_get_types() as $type => $name) {
if (variable_get(PREV_NEXT_NODE_TYPE . $type, 0)) {
$types[] = $type;
}
}
return $types;
}
function _prev_next_node_types_sql($node_type = '') {
$same_type = variable_get(PREV_NEXT_NODE_TYPE . $node_type . '_same_type', 0);
if (!$same_type) {
$types = _prev_next_node_types();
$quoted_types = array();
foreach (_prev_next_node_types() as $type) {
$quoted_types[] = "'" . $type . "'";
}
$cond = '';
if (count($types)) {
$cond = ' AND type IN (' . implode(',', $quoted_types) . ')';
}
}
else {
$cond = " AND type = '" . $node_type . "'";
}
return $cond;
}
function _prev_next_category_sql($node_type = '') {
$cond = '';
$same_type = variable_get(PREV_NEXT_NODE_TYPE . $node_type . '_same_type', 0);
$category = variable_get(PREV_NEXT_NODE_TYPE . $node_type . '_category_criteria', 'none');
if (!$same_type || $category == 'none') {
return $cond;
}
$cond = " INNER JOIN {field_data_{$category}} ON nid = entity_id ";
return $cond;
}
function prev_next_init() {
if (!empty($_SESSION['prev_next_remove_nids'])) {
foreach ($_SESSION['prev_next_remove_nids'] as $nid) {
_prev_next_remove($nid);
}
unset($_SESSION['prev_next_remove_nids']);
}
}
function prev_next_permission() {
return array(
'administer prev_next' => array(
'title' => t('Administer the prev/next module for nodes, including re-indexing. This includes /admin/config/system/prev_next and admin/config/system/prev_next/re-index'),
),
);
}