### Eclipse Workspace Patch 1.0 #P prev_next Index: prev_next.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/prev_next/prev_next.module,v retrieving revision 1.1 diff -u -r1.1 prev_next.module --- prev_next.module 7 May 2009 22:12:04 -0000 1.1 +++ prev_next.module 30 Oct 2009 14:16:39 -0000 @@ -2,7 +2,12 @@ // $Id: prev_next.module,v 1.1 2009/05/07 22:12:04 kbahey Exp $ define('PREV_NEXT_BATCH_SIZE_DEFAULT', 200); -define('PREV_NEXT_NODE_TYPE', 'prev_next_node_type_'); +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', '[title] »'); +define('PREV_NEXT_DISPLAY_TEXT_NEXT_DEFAULT', '« [title]'); /** * Implementation of hook_menu(). @@ -32,8 +37,8 @@ */ function prev_next_admin() { $form['status'] = array( - '#type' => 'fieldset', - '#title' => t('Indexing status'), + '#type' => 'fieldset', + '#title' => t('Indexing status'), ); $max_nid = variable_get('prev_next_index_nid', 0); @@ -50,14 +55,14 @@ '%remaining' => $remaining, '%total' => $total, )); - $status .= ($max_nid) ? t('
Max node ID for indexing on the next cron run: @max
', array('@max' => $max_nid)) : t('Existing nodes have finished prev/next indexing.
'); + $status .= ($max_nid) ? t('Max node ID for indexing on the next cron run: @max.
', array('@max' => $max_nid)) : t('Existing nodes have finished prev/next indexing.
'); $form['status']['status'] = array( '#value' => $status, ); $form['status']['reindex'] = array( - '#type' => 'submit', + '#type' => 'submit', '#value' => t('Re-index'), ); @@ -71,20 +76,72 @@ '#required' => TRUE, ); + $form['prev_next_num_blocks'] = array( + '#title' => t('Blocks'), + '#description' => t('Number of blocks available.'), + '#type' => 'textfield', + '#size' => 2, + '#maxlength' => 3, + '#default_value' => variable_get('prev_next_num_blocks', PREV_NEXT_NUM_BLOCKS_DEFAULT), + '#required' => TRUE, + ); + $form['node_types'] = array( '#type' => 'fieldset', '#title' => t('Content types'), - '#description' => t('Content types to include in prev/next. If you do not specify content types, then all of them will be included.'), + '#description' => t('Define settings for each content type. If none of them is included, then all of them will be.'), ); foreach (node_get_types() as $type => $name) { - $form['node_types'][PREV_NEXT_NODE_TYPE . $type] = array( + + $form['node_types'][$type] = array( + '#type' => 'fieldset', + '#description' => t('Note: changing one of these values will reset the entire Prev/Next index.'), + '#title' => node_get_types('name', $type), + '#collapsible' => TRUE, + '#collapsed' => !variable_get(PREV_NEXT_NODE_TYPE . $type, 0) + ); + + $form['node_types'][$type][PREV_NEXT_NODE_TYPE . $type] = array( '#type' => 'checkbox', - '#title' => node_get_types('name', $type), + '#title' => t('Include'), '#default_value' => variable_get(PREV_NEXT_NODE_TYPE . $type, 0), ); + $form['node_types'][$type][PREV_NEXT_NODE_TYPE . $type . '_current'] = array( + '#type' => 'hidden', + '#default_value' => variable_get(PREV_NEXT_NODE_TYPE . $type, 0) + ); + + $form['node_types'][$type][PREV_NEXT_NODE_TYPE . $type . '_indexing_criteria'] = array( + '#title' => t('Indexing criteria'), + '#type' => 'select', + '#options' => array( + 'nid' => t('Node ID'), + 'created' => t('Post date'), + 'changed' => t('Updated date'), + 'title' => t('Title') + ), + '#default_value' => variable_get(PREV_NEXT_NODE_TYPE . $type . '_indexing_criteria', PREV_NEXT_INDEXING_CRITERIA_DEFAULT) + ); + $form['node_types'][$type][PREV_NEXT_NODE_TYPE . $type . '_indexing_criteria_current'] = array( + '#type' => 'hidden', + '#value' => variable_get(PREV_NEXT_NODE_TYPE . $type . '_indexing_criteria', PREV_NEXT_INDEXING_CRITERIA_DEFAULT) + ); + + $form['node_types'][$type][PREV_NEXT_NODE_TYPE . $type . '_same_type'] = array( + '#type' => 'checkbox', + '#title' => t('Only nodes with same content type'), + '#default_value' => variable_get(PREV_NEXT_NODE_TYPE . $type . '_same_type', 0), + ); + $form['node_types'][$type][PREV_NEXT_NODE_TYPE . $type . '_same_type_current'] = array( + '#type' => 'hidden', + '#default_value' => variable_get(PREV_NEXT_NODE_TYPE . $type . '_same_type', 0) + ); + } + $form['#submit'][] = 'prev_next_admin_submit'; + return system_settings_form($form); } @@ -105,9 +162,32 @@ } } +/** + * Submit callback. + */ +function prev_next_admin_submit($form, &$form_state) { + $rebuild = FALSE; + + // Test sensitive values. + foreach (node_get_types() as $type => $name) { + if ($form_state['values'][PREV_NEXT_NODE_TYPE . $type . '_current'] != $form_state['values'][PREV_NEXT_NODE_TYPE . $type] + || $form_state['values'][PREV_NEXT_NODE_TYPE . $type . '_indexing_criteria_current'] != $form_state['values'][PREV_NEXT_NODE_TYPE . $type . '_indexing_criteria'] + || $form_state['values'][PREV_NEXT_NODE_TYPE . $type . '_same_type_current'] != $form_state['values'][PREV_NEXT_NODE_TYPE . $type . '_same_type'] + ) + $rebuild = TRUE; + } + + // If the search criterias has been changed, re-index. + if ($rebuild) { + prev_next_reindex(); + drupal_set_message(t('The Prev/Next index will be rebuilt.')); + } + $form_state['redirect'] = 'admin/settings/prev_next'; +} + function prev_next_reindex_confirm() { return confirm_form(array(), t('Are you sure you want to re-index Prev/Next?'), - 'admin/settings/prev_next', t(' The entire Prev/Next index will be reset and rebuilt incrementally as cron runs. action cannot be undone.'), t('Re-index'), t('Cancel')); + 'admin/settings/prev_next', t('The entire Prev/Next index will be reset and rebuilt incrementally as cron runs. action cannot be undone.'), t('Re-index'), t('Cancel')); } function prev_next_reindex_confirm_submit(&$form, &$form_state) { @@ -138,11 +218,10 @@ 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(); + $cond = _prev_next_node_types_sql(); timer_start('prev_next_cron'); - $result = db_query("SELECT nid FROM {node} WHERE nid <= %d AND status = 1 $cond ORDER BY nid DESC LIMIT %d", - $max_nid, $batch_size); + $result = db_query("SELECT nid FROM {node} WHERE nid <= %d AND status = 1 $cond ORDER BY nid DESC LIMIT %d", $max_nid, $batch_size); $count = 0; while ($row = db_fetch_object($result)) { @@ -161,24 +240,179 @@ if ($last_nid !== FALSE) { // Prepare a starting point for the next run. variable_set('prev_next_index_nid', $last_nid - 1); - watchdog('prev_next', 'Indexed %count nodes in %time milliseconds.', array('%count' => $count, '%time' => $time)); } else { // If all nodes have been indexed, set to zero to skip future cron runs. variable_set('prev_next_index_nid', 0); } + watchdog('prev_next', 'Indexed %count nodes in %time milliseconds.', array('%count' => $count, '%time' => $time)); + + $total = db_result(db_query("SELECT COUNT(nid) FROM {node} WHERE status = 1 $cond")); + $completed = db_result(db_query("SELECT COUNT(nid) FROM {prev_next_node}")); + $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 + ))); + } } /** + * Implementation of hook_block(). + */ +function prev_next_block($op = 'list', $delta = 0, $edit = array()) { + switch ($op) { + + case 'list': + $num_blocks = variable_get('prev_next_num_blocks', PREV_NEXT_NUM_BLOCKS_DEFAULT); + for ($b = 0; $b < $num_blocks ; $b++) { + $blocks[$b] = array( + 'info' => t('Prev/Next links !blocknum', array('!blocknum' => 1+$b)), + 'status' => 0, + 'cache' => BLOCK_CACHE_PER_PAGE + ); + } + return $blocks; + break; + + case 'configure': + $description = (module_exists('token')) ? 'Use the available tokens (see below) to customize the link text.' : 'The [title] token will be replaced by the actual node title.'; + + $form['previous'] = array( + '#type' => 'fieldset', + '#title' => t('Previous Node'), + '#collapsible' => TRUE, + ); + $form['previous']['prev_next_display_prev' . $delta] = array( + '#type' => 'checkbox', + '#title' => t('Display'), + '#default_value' => variable_get('prev_next_display_prev' . $delta, PREV_NEXT_DISPLAY_DEFAULT), + ); + $form['previous']['prev_next_display_text_prev' . $delta] = array( + '#type' => 'textfield', + '#title' => t('Link text'), + '#description' => $description, + '#default_value' => variable_get('prev_next_display_text_prev' . $delta, PREV_NEXT_DISPLAY_TEXT_PREV_DEFAULT), + ); + if (module_exists('token')) { + $form['previous']['token_help'] = array( + '#title' => t('Replacement patterns'), + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['previous']['token_help']['help'] = array( + '#value' => theme('token_help', 'node'), + ); + } + + $form['next'] = array( + '#type' => 'fieldset', + '#title' => t('Next Node'), + '#collapsible' => TRUE, + ); + $form['next']['prev_next_display_next' . $delta] = array( + '#type' => 'checkbox', + '#title' => t('Display'), + '#default_value' => variable_get('prev_next_display_next' . $delta, PREV_NEXT_DISPLAY_DEFAULT), + ); + $form['next']['prev_next_display_text_next' . $delta] = array( + '#type' => 'textfield', + '#title' => t('Link text'), + '#description' => $description, + '#default_value' => variable_get('prev_next_display_text_next' . $delta, PREV_NEXT_DISPLAY_TEXT_NEXT_DEFAULT), + ); + if (module_exists('token')) { + $form['next']['token_help'] = array( + '#title' => t('Replacement patterns'), + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['next']['token_help']['help'] = array( + '#value' => theme('token_help', 'node'), + ); + } + return $form; + break; + + case 'save': + variable_set('prev_next_display_prev' . $delta, $edit['prev_next_display_prev' . $delta]); + variable_set('prev_next_display_next' . $delta, $edit['prev_next_display_next' . $delta]); + variable_set('prev_next_display_text_prev' . $delta, $edit['prev_next_display_text_prev' . $delta]); + variable_set('prev_next_display_text_next' . $delta, $edit['prev_next_display_text_next' . $delta]); + break; + + case 'view': + $content = ''; + $next_display = variable_get('prev_next_display_next' . $delta, PREV_NEXT_DISPLAY_DEFAULT); + $next_text = variable_get('prev_next_display_text_next' . $delta, PREV_NEXT_DISPLAY_TEXT_NEXT_DEFAULT); + $prev_display = variable_get('prev_next_display_prev' . $delta, PREV_NEXT_DISPLAY_DEFAULT); + $prev_text = variable_get('prev_next_display_text_prev' . $delta, PREV_NEXT_DISPLAY_TEXT_PREV_DEFAULT); + + if (arg(0) == 'node' && is_numeric(arg(1)) && !arg(2) ) { + $node = node_load(arg(1)); + $n_nid = prev_next_nid($node->nid, 'next'); + $p_nid = prev_next_nid($node->nid, 'prev'); + + if ($n_nid || $p_nid) { + + if ($p_nid && $prev_display && $prev_text != '') { + $p_node = node_load($p_nid); + if (module_exists('token')) { + $link = token_replace($prev_text, 'node', $p_node); + } + else { + $link = str_replace('[title]', $p_node->title, $prev_text); + } + $options = array('html' => TRUE); + $content .= '