recently_read.module in Recently Read 7
Same filename and directory in other branches
Recently read module file. Displays a history of recently read nodes by currently logged in user.
File
recently_read.moduleView source
<?php
/**
* @file
* Recently read module file.
* Displays a history of recently read nodes by currently logged in user.
*/
/**
* Implements hook_menu().
*/
function recently_read_menu() {
$items['admin/config/system/recently-read'] = array(
'title' => 'Recently read content',
'description' => 'Tracks the history of recently read content by each user.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'recently_read_settings',
),
'access arguments' => array(
'administer site configuration',
),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
/**
* Implements hook_theme().
*/
function recently_read_theme() {
return array(
'recently_read_item' => array(
'variables' => array(
'item' => array(),
),
),
'recently_read_item_list' => array(
'variables' => array(
'items' => array(),
),
),
);
}
/**
* Implements hook_block_info().
*/
function recently_read_block_info() {
// each enabled content type has its own block
$types = node_type_get_types();
$enabled = variable_get('recently_read_node_types', array(
'page',
'article',
));
$blocks = array();
foreach ($enabled as $key) {
if (isset($types[$key])) {
$blocks[$key] = array(
'info' => t('Recently read - @type', array(
'@type' => $types[$key]->name,
)),
);
}
}
return $blocks;
}
/**
* Implements hook_block_configure().
*/
function recently_read_block_configure($delta) {
// allow user to customize the length of a list for each node type
$max_entries = variable_get('recently_read_max_entries', 10);
$max_count = variable_get("recently_read_max_length", array(
'page' => 10,
'article' => 10,
));
$form['items_count'] = array(
'#type' => 'textfield',
'#title' => t('Maximum number of links to display in the block'),
'#description' => t('Enter the positive integer value, less or equal to %limit.', array(
'%limit' => $max_entries,
)),
'#default_value' => key_exists($delta, $max_count) ? $max_count[$delta] : $max_entries,
);
return $form;
}
/**
* Implements hook_block_save().
*/
function recently_read_block_save($delta, $edit) {
// save configuration settings
$max_entries = variable_get('recently_read_max_entries', 10);
$value = max(1, min($edit['items_count'], $max_entries));
$max_count = variable_get('recently_read_max_length', array(
'page' => 10,
'article' => 10,
));
$max_count[$delta] = $value;
variable_set('recently_read_max_length', $max_count);
return;
}
/**
* Implements hook_block_view().
*/
function recently_read_block_view($delta) {
// disable caching of entire page if recently read block is being displayed
recently_read_disable_page_cache();
// view block containing links to recently visited nodes
global $user;
$max_entries = variable_get('recently_read_max_entries', 10);
$max_count = variable_get('recently_read_max_length', array(
'page' => 10,
'story' => 10,
));
isset($max_count[$delta]) ? $limit = $max_count[$delta] : ($limit = $max_entries);
$items = recently_read_get_read_items(array(
$delta,
), $user->uid, $limit);
$types = node_type_get_types();
return array(
'subject' => t('Recently read - @type', array(
'@type' => $types[$delta]->name,
)),
'content' => theme('recently_read_item_list', array(
'items' => $items,
)),
);
}
/**
* Implements hook_exit().
*/
function recently_read_exit($destination = NULL) {
global $user;
// drupal_bootstrap(DRUPAL_BOOTSTRAP_PATH);
// track history for authenticated user
if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == '') {
$nid = arg(1);
// get node type
$type = db_query('SELECT type FROM {node} WHERE nid = :nid', array(
':nid' => $nid,
))
->fetchField();
// track history for authenticated user
if (recently_read_is_enabled($type) && $user->uid) {
$record = new stdClass();
$record->nid = $nid;
$record->type = $type;
$record->uid = $user->uid;
$record->timestamp = REQUEST_TIME;
$count = db_query('SELECT COUNT(*) FROM {recently_read_nodes} WHERE nid = :nid AND uid = :uid AND type = :type', array(
':nid' => $nid,
':uid' => $user->uid,
':type' => $type,
))
->fetchField();
// a node has been viewed before, make an update
if ($count > 0) {
drupal_write_record('recently_read_nodes', $record, array(
'nid',
'uid',
));
}
else {
drupal_write_record('recently_read_nodes', $record);
}
}
// track history for anonymous user
if (recently_read_is_enabled($type) && !$user->uid && variable_get('recently_read_anonymous_enabled', FALSE)) {
$key = "recently_read-{$type}";
if (!isset($_SESSION[$key])) {
$_SESSION[$key] = array();
}
// remove previous entry, if present
unset($_SESSION[$key][$nid]);
// add new entry at the beginning of array
$title = db_query('SELECT title FROM {node} WHERE nid = :nid', array(
':nid' => $nid,
))
->fetchField();
$entry = array(
'nid' => $nid,
'title' => $title,
'type' => $type,
'timestamp' => time(),
);
$_SESSION[$key] = array(
$nid => $entry,
) + $_SESSION[$key];
while (count($_SESSION[$key]) > variable_get('recently_read_max_entries', 10)) {
array_pop($_SESSION[$key]);
}
}
// remove old entries
$nids = array();
$first = variable_get('recently_read_max_entries', 10) + 1;
$result = db_query_range("SELECT nid FROM {recently_read_nodes}\n WHERE uid = :uid ORDER BY timestamp DESC", $first, 1000, array(
':uid' => $user->uid,
));
while ($nid = $result
->fetchField()) {
$nids[] = $nid;
}
if (count($nids)) {
db_query("DELETE FROM {recently_read_nodes} WHERE uid = :uid AND nid IN(:nids)", array(
':uid' => $user->uid,
':nids' => $nids,
));
}
}
}
/**
* Form builder; Configure recently read settings.
*/
function recently_read_settings($form, &$form_state) {
$types = node_type_get_types();
$options = array();
foreach ($types as $key => $type) {
$options[$key] = $type->name;
}
$form['node_types'] = array(
'#type' => 'checkboxes',
'#title' => t('Enable history tracking of the following content'),
'#description' => t('Select which content types will be tracked.'),
'#default_value' => variable_get('recently_read_node_types', array(
'page',
'article',
)),
'#options' => $options,
);
$form['anonymous_enabled'] = array(
'#type' => 'checkbox',
'#title' => t('Enable history tracking also for anonymous users'),
'#description' => t('If disabled, login is required to view recently read block.'),
'#default_value' => variable_get('recently_read_anonymous_enabled', FALSE),
);
$form['max_entries'] = array(
'#type' => 'textfield',
'#title' => t('Recently read list length'),
'#description' => 'Provide the maximum number of entires stored for each read content type (per user) in the database.',
'#default_value' => variable_get('recently_read_max_entries', 10),
'#required' => TRUE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save configuration'),
);
return $form;
}
function recently_read_settings_validate($form, &$form_state) {
$max = $form_state['values']['max_entries'];
if (!is_numeric($max) || $max < 1) {
form_set_error('max_entries', t('%field must be a positive integer value.', array(
'%field' => $form['max_entries']['#title'],
)));
}
}
function recently_read_settings_submit($form, &$form_state) {
$selected = array();
foreach ($form_state['values']['node_types'] as $value) {
if ($value) {
$selected[] = $value;
}
}
variable_set('recently_read_node_types', $selected);
variable_set('recently_read_max_entries', $form_state['values']['max_entries']);
variable_set('recently_read_anonymous_enabled', $form_state['values']['anonymous_enabled']);
drupal_set_message(t('The configuration options have been saved.'));
}
/**
* Function that checks if a specific node type history tracking has been enabled
*/
function recently_read_is_enabled($node_type) {
$enabled_types = variable_get('recently_read_node_types', array(
'page',
'article',
));
return in_array($node_type, $enabled_types);
}
/*
* Get a list of recently read items by node types and for a specific user,
* sorted by read date.
*
* @param $node_types
* An array of node types.
*
* @param $user_id
* Id of a user whose list is returned.
*
* @param $limit
* Number of items to return (zero to return all)
* @return
* An array of recently read items. Each item is an array.
* Properties of the item: nid, title, type, timestamp
*/
function recently_read_get_read_items($node_types, $user_id, $limit = 0) {
// normalize arguments
if (!is_array($node_types)) {
$node_types = array(
$node_types,
);
}
if ($limit == 0) {
$limit = variable_get('recently_read_max_entries', 10) * count($node_types);
}
$items = array();
// get history from _SESSION variable if anonymous
if ($user_id == 0 && variable_get('recently_read_anonymous_enabled', FALSE)) {
foreach ($node_types as $node_type) {
$key = "recently_read-{$node_type}";
if (isset($_SESSION[$key]) && is_array($_SESSION[$key])) {
$items = $items + $_SESSION[$key];
}
}
usort($items, '_recently_read_sort_fcn');
$items = array_slice($items, 0, $limit);
}
// get history from database if authenticated
if ($user_id > 0) {
$query = db_select('node', 'n');
$query
->innerJoin('recently_read_nodes', 'rr', 'n.nid = rr.nid');
$items = $query
->fields('n', array(
'nid',
'title',
'type',
))
->fields('rr', array(
'timestamp',
))
->condition('rr.uid', $user_id)
->condition('n.status', 1)
->condition('n.type', $node_types, 'IN')
->orderBy('rr.timestamp', 'DESC')
->range(0, $limit)
->addTag('node_access')
->execute()
->fetchAll(PDO::FETCH_ASSOC);
}
return $items;
}
/*
* Disables page caching. Call this function if you want to display recently read content (i.e. block).
*/
function recently_read_disable_page_cache() {
$GLOBALS['conf']['cache'] = FALSE;
}
/*
* Return a themed recently read item.
*
* @param $item
* An object containing the properties of the item.
* Properties used: nid, title, type, timestamp
* @return
* A themed HTML string containing a link to the recently read item.
*/
function theme_recently_read_item($variables) {
$item = $variables['item'];
return l($item['title'], 'node/' . $item['nid']);
}
/**
* Return a themed list of recently read items.
*
* @param $items
* An array of recently read items to be displayed in the list.
* @return
* A string containing the list output.
*
*/
function theme_recently_read_item_list($variables) {
$items = $variables['items'];
if (count($items) == 0) {
return t('Nothing has been read yet.');
}
// theme each individual item on the list
foreach ($items as &$item) {
$item = theme('recently_read_item', array(
'item' => $item,
));
}
// theme the list
return theme('item_list', array(
'items' => $items,
));
}
/*
* Compare function for sorting recently read items
*/
function _recently_read_sort_fcn($a, $b) {
$delta = $b['timestamp'] - $a['timestamp'];
if ($delta > 0) {
return 1;
}
if ($delta < 0) {
return -1;
}
return 0;
}
Functions
Name | Description |
---|---|
recently_read_block_configure | Implements hook_block_configure(). |
recently_read_block_info | Implements hook_block_info(). |
recently_read_block_save | Implements hook_block_save(). |
recently_read_block_view | Implements hook_block_view(). |
recently_read_disable_page_cache | |
recently_read_exit | Implements hook_exit(). |
recently_read_get_read_items | |
recently_read_is_enabled | Function that checks if a specific node type history tracking has been enabled |
recently_read_menu | Implements hook_menu(). |
recently_read_settings | Form builder; Configure recently read settings. |
recently_read_settings_submit | |
recently_read_settings_validate | |
recently_read_theme | Implements hook_theme(). |
theme_recently_read_item | |
theme_recently_read_item_list | Return a themed list of recently read items. |
_recently_read_sort_fcn |