'. t('The archive module allows your users to browse your content by its type and date of publication. The archive module interface, available at the path !archive_link, presents simple controls for selecting a year, month or day. All available posts published within this range are displayed beneath the control. Administrators may select the content types to be displayed. The archive module adds an Archives menu item to the default Navigation menu (the item is disabled by default), and displays the current month and year within an optional block.', array('!archive_link' => l(t('archive'), 'archive'))) .'
';
$output .= ''. t('You can') .'
';
$output .= theme('item_list', array('items' => array(
t('view your !archive_link.', array('!archive_link' => l(t('Archive'), 'archive'))),
t('enable, position and configure the Current calendar month with archive links block at the !blocks.', array('!blocks' => l(t('blocks administration page'), 'admin/build/block'))),
t('enable or disable the Archives menu item on the !menu-administration.', array('!menu-administration' => l(t('navigation menu administration page'), 'admin/build/menu-customize/navigation')))
)));
$output .= ''. t('For more information, see the online handbook entry for !handbook-page.', array('!handbook-page' => l(t('Archive module'), 'http://drupal.org/handbook/modules/archive'))) .'
';
return $output;
}
}
/**
* Implementation of hook_menu().
*/
function archive_menu() {
$items = array();
$items['archive'] = array(
'title' => 'Archives',
'access arguments' => array('access content'),
'page callback' => 'archive_page',
'file' => 'archive.pages.inc',
'type' => MENU_SUGGESTED_ITEM
);
$items['admin/config/user-interface/archive'] = array(
'title' => 'Archives',
'description' => 'Select the content types listed in the archives.',
'page callback' => 'drupal_get_form',
'page arguments' => array('archive_admin_settings'),
'access arguments' => array('access administration pages'),
'file' => 'archive.admin.inc',
'type' => MENU_NORMAL_ITEM
);
return $items;
}
/**
* Implementation of hook_uninstall().
*/
function archive_uninstall() {
variable_del('archive_type_filters');
}
/**
* Implementation of hook_theme().
*/
function archive_theme() {
return array(
'archive_block_calendar' => array('variables' => array('timestamp' => 0)),
'archive_block_month_list' => array('variables' => array('list_items' => array())),
'archive_page_title' => array('variables' => array('type' => '', 'year' => NULL, 'month' => NULL, 'day' => NULL)),
'archive_navigation' => array('variables' => array('type' => '', 'date' => NULL)),
'archive_navigation_days' => array('variables' => array('type' => '', 'date' => NULL)),
'archive_navigation_months' => array('variables' => array('type' => '', 'date' => NULL)),
'archive_navigation_node_types' => array('variables' => array('type' => '', 'date' => NULL)),
'archive_navigation_years' => array('variables' => array('type' => '', 'date' => NULL)),
'archive_separator' => array('variables' => array('date_created' => 0, 'separators' => array())),
);
}
/**
* Function used in theme_archive_block_calendar from php calendar functions.
* Unfortunatly some php versions don't have it compiled so we add it.
*/
if (!defined('CAL_GREGORIAN'))
define('CAL_GREGORIAN', 1);
if (!function_exists('cal_days_in_month')){
function cal_days_in_month($calendar,$month, $year) {
// $calendar just gets ignored, assume gregorian
// calculate number of days in a month
return $month == 2 ? ($year % 4 ? 28 : ($year % 100 ? 29 : ($year % 400 ? 28 : 29))) : (($month - 1) % 7 % 2 ? 30 : 31);
}
}
function archive_debugout($str) {
return; // for production
$outfile = "/tmp/debug.txt";
if(is_array($str) || is_object($str)) {
error_log(print_r($str, TRUE) . "\n", 3, $outfile);
}
else {
error_log($str . "\n", 3, $outfile);
}
}
/**
* Returns a single month as a calendar grid.
*
* @todo
* Take the archive logic out to allow better theme-overloading
* of this function.
*/
function theme_archive_block_calendar($variables) {
$timestamp = $variables['timestamp'];
$the_date = explode(' ', format_date($timestamp, 'custom', 'F Y n t'));
$title = $the_date[0] .' '. $the_date[1];
$year = $the_date[1];
$month = $the_date[2];
$num_days = (int)$the_date[3];
// get information about oldest and newest posts
$date = _archive_date('all', $year, $month);
archive_debugout("-------------archive_date returned-----------");
archive_debugout($date);
// get the date of the oldest post
$oldest = _archive_get_oldest_date('all');
list($oldest_year, $oldest_month, $oldest_day)
= explode(' ', format_date($oldest, 'custom', 'Y n j'));
$newest = _archive_get_newest_date('all');
list($newest_year, $newest_month, $newest_day)
= explode(' ', format_date($newest, 'custom', 'Y n j'));
// get year/month of the previous post and then the number of post in the month
$prev_post_date = _archive_get_prev_post_date('all', $year, $month);
if(empty($prev_post_date)) {
// no more post in any earlier month/year
// use previous month even if there's no posts
$prev_year = $year;
$prev_month = $month - 1;
if($month == 0) {
$prev_month = 12;
$prev_year--;
}
$num_days_prev = cal_days_in_month(CAL_GREGORIAN, $prev_month, $prev_year);
}
else {
$prev_year = date('Y', $prev_post_date);
$prev_month = date('n', $prev_post_date);
$num_prev_month = _archive_get_num_posts('all', $prev_year, $prev_month);
$num_days_prev = cal_days_in_month(CAL_GREGORIAN, $prev_month, $prev_year);
}
// get month/year of the next post and then the number of post in the month
$next_post_date = _archive_get_next_post_date('all', $year, $month);
if(empty($next_post_date)) {
// no more post in any later month/year
$next_year = 9999;
$next_month = 0;
$num_next_month = 0;
}
else {
$next_year = date('Y', $next_post_date);
$next_month = date('n', $next_post_date);
$num_next_month = _archive_get_num_posts('all', $next_year, $next_month);
}
$month_title = '';
// add a link to the previous month
if (($oldest_year < $prev_year) ||
($oldest_year == $prev_year && $oldest_month <= $prev_month)) {
$month_title .= '';
$month_title .= l('<', _archive_url('all', $prev_year, $prev_month), array('attributes' => array('title' => format_plural($num_prev_month, '1 post', '@count posts'))));
$month_title .= '';
$month_title .= " ";
}
else {
// no more previous month
$month_title .= ' ';
}
// add a title (month and year)
$month_title .= '';
if (isset($date->months[$month])) {
// $month_title = l($title, _archive_url('all', $year, $month), array('title' => format_plural($date->months[format_date($variables['timestamp'], 'custom', 'n')], '1 post', '@count posts')));
$month_title .= l($title, _archive_url('all', $year, $month), array('title' => format_plural($date->months[$month], 'custom', 'n'), '1 post', '@count posts'));
}
else {
// $month_title = $title;
$month_title .= $title;
}
$month_title .= '';
// add a link to the next month
if (($next_year < $newest_year) ||
($next_year == $newest_year && $next_month <= $newest_month)) {
$month_title .= " ";
$month_title .= '';
$month_title .= l('>', _archive_url('all', $next_year, $next_month), array('attributes' => array('title' => format_plural($num_next_month, '1 post', '@count posts'))));
$month_title .= '';
}
else {
// no more next month
$month_title .= ' ';
}
// Build the week starting with
$first_day_of_week = variable_get('date_first_day', 0);
$week = array(t('Sun'), t('Mon'), t('Tue'), t('Wed'), t('Thu'), t('Fri'), t('Sat'));
$day_headers = array();
for ($i = $first_day_of_week; $i < $first_day_of_week + 7; $i++) {
$day_headers[] = $week[$i%7];
}
// Grab the first day of the month using the user's timezone
// list($start_year, $start_month) = explode(' ', format_date($variables['timestamp'], 'custom', 'Y m'));
list($start_year, $start_month) = explode(' ', format_date($timestamp, 'custom', 'Y m'));
$start = gmmktime( 0, 0, 0, (int)$start_month, 1, (int)$start_year);
$weekday = gmdate('w', $start);
if ($first_day_of_week) {
$weekday = ($weekday ? $weekday : 7) - $first_day_of_week;
}
$days_row = array();
// From http://www.theadminzone.com/forums/showthread.php?t=17490
for ($i = 1-$weekday;$i <= ceil(($weekday+$num_days)/7)*7;$i++) {
if ($i > 0) {
if (array_key_exists($i, $date->days)) {
$days_row[] = l($i,
_archive_url('all', $year, $month, $i),
array('attributes' => array('title' => format_plural($date->days[$i], '1 post', '@count posts'))));
}
elseif ($i <= $num_days) {
$days_row[] = $i;
}
// Add days for the next month.
else {
$curr_cal_date = $i - $num_days;
if (isset($date->next_month_days[$curr_cal_date])) {
$data = l($curr_cal_date,
_archive_url('all', $next_year, $next_month, $curr_cal_date),
array('attributes' => array('title' => format_plural($date->next_month_days[$curr_cal_date], '1 post', '@count posts'))));
}
else {
$data = $curr_cal_date;
}
$days_row[] = array(
'data' => $data,
'class' => 'out-of-month'
);
}
// Add the week table row we just created if we've finished it
if (($i+$weekday)%7 == 0) {
$rows[] = $days_row;
$days_row = array();
}
}
// Add days for previous month also.
else {
$curr_cal_date = $num_days_prev + $i;
if (isset($date->prev_month_days[$curr_cal_date])) {
$data = l($curr_cal_date,
_archive_url('all', $prev_year, $prev_month, $curr_cal_date),
array('attributes' => array('title' => format_plural($date->prev_month_days[$curr_cal_date], '1 post', '@count posts'))));
}
else {
$data = $curr_cal_date;
}
$days_row[] = array(
'data' => $data,
'class' => 'out-of-month'
);
}
}
return theme('table', array('header' => $day_headers, 'rows' => $rows, 'caption' => $month_title, 'sticky' => false));
}
// PIXTURE STUDIO - start:ported from Archive module 6.x
/**
* Return a list of links suitable to be passed to theme_links() that represent
* months containing posts.
*/
function archive_month_list($max_items) {
$final_types = _archive_types_sql_string('all');
$result = db_query('SELECT n.created FROM {node} n WHERE n.status = 1 ' . $final_types . ' ORDER BY n.created DESC');
$months = array();
$total_month = 0;
foreach ($result as $node) {
list($month_name, $year, $month) = explode(' ', format_date($node->created, 'custom', 'F Y n'));
if (isset($months[$year][$month])) {
$months[$year][$month]['count']++;
}
else if (($total_month++ < $max_items) || ($max_items == 0)) {
$months[$year][$month] = array(
'count' => 1,
'month_name' => $month_name
);
}
else {
break; // reached the max number of months to be displayed in a list
}
}
return $months;
}
/**
* Returns a list of archive months.
*/
function theme_archive_block_month_list($variables) {
$list_items = $variables['list_items'];
if (empty($list_items)) {
return '';
}
// Sort by year then by month
krsort($list_items);
foreach ($list_items as $year => $v) {
krsort($list_items[$year]);
}
$links = array();
foreach ($list_items as $year => $months) {
foreach ($months as $month => $data) {
$links[] = l(t($data['month_name'] . ' ' . $year . ' (' . $data['count'] . ')'), 'archive/all/' . $year . '/' . $month, array('title' => format_plural($data['count'], '1 post', '@count posts')));
}
}
$list = theme('item_list', array('items' => $links));
$list .= '' . l(t('all'), 'archive', array('title' => t('Browse all of the archives'))) . '
';
return $list;
}
/**
* Implements hook_block_info().
*/
function archive_block_info() {
$blocks = array();
$blocks['archive_calendar']['info'] = t('Archive: Calendar');
$blocks['archive_months_list']['info'] = t('Archive: Months list');
return $blocks;
}
// PIXTURE STUDIO - end:ported from Archive module 6.x
/**
/*
* Implements hook_block_view().
*/
function archive_block_view($delta = NULL) {
// PIXTURE STUDIO - start
if ($delta == 'archive_calendar') {
// check if a specific node is displayed or not
if(arg(0) != 'archive') {
// a specific node is displayed
if (variable_get('archive_display_block_by_types', 0)) {
// display blocks only when valid content type is displayed
$valid_types = _archive_types_array();
if (empty($valid_types)) {
return '';
}
$node = menu_get_object();
if(empty($node)) {
// it is not single node page (e.g: front page)
if(arg(0) != 'emp_blogs' && arg(0) != 'blogs') {
return '';
}
}
else if (!in_array($node->type, $valid_types)) {
// the node type is not the target of the archive module
if(arg(0) != 'emp_blogs' && arg(0) != 'blogs') {
return '';
}
}
}
}
if(arg(0) == 'blogs' && arg(0) == 'emp_blog') {
variable_set('archive_calendar_year', 0);
variable_set('archive_calendar_month', 0);
}
else if(arg(0) != 'archive') {
// if a specific node is displayed to the page,
// use the date of the node for the calendar
$node = menu_get_object();
if(!empty($node)) {
variable_set('archive_calendar_year', date('Y', $node->created));
variable_set('archive_calendar_month', date('n', $node->created));
}
}
$calendar_year = variable_get('archive_calendar_year', date('Y'));
$calendar_month = variable_get('archive_calendar_month', date('n'));
if ($calendar_year == 0 && $calendar_month == 0) {
$newest = _archive_get_newest_date('all');
list($newest_year, $newest_month, $newest_day) = explode(' ', format_date($newest, 'custom', 'Y n j'));
$timestamp = mktime(0, 0, 0, $newest_month, 1, $newest_year);
}
else {
$timestamp = mktime(0, 0, 0, $calendar_month, 1, $calendar_year);
}
drupal_add_css(drupal_get_path('module', 'archive') . '/archive.css');
$block = array(
'subject' => t('Archives'),
'content' => theme('archive_block_calendar', array('timestamp' => $timestamp)),
);
return $block;
}
else if ($delta == 'archive_months_list') {
$max_items = variable_get('archive_block_months', 12);
$month_list = archive_month_list($max_items);
if (!empty($month_list)) {
$block = array(
'subject' => t('Arvchives'),
'content' => theme('archive_block_month_list', array('list_items' => $month_list)),
);
return $block;
}
return ''; // TBD
}
// PIXTURE STUDIO - end
// PIXTURE STUDIO - start
/*
drupal_add_css(drupal_get_path('module', 'archive') . '/archive.css');
$block = array(
'subject' => t('Archives'),
'content' => theme('archive_block_calendar', array('timestamp' => time())),
);
return $block;
*/
// PIXTURE STUDIO - end
}
/**
* Generate an archive URL based on the $y, $m and $d provided.
*
* @param $type
* The node type to use if valid.
* @param $y
* The year to use if valid.
* @param $m
* The month to use if valid.
* @param $d
* The day to use if valid.
* @return
* A string with the generated archive URL.
*/
function _archive_url($type, $y = 0, $m = 0, $d = 0) {
$url = 'archive';
if (_archive_validate_type($type)) {
$url .= '/'. $type;
}
else {
$url .= '/all';
}
if (_archive_validate_date($y, $m, $d)) {
$url .= '/'. $y .'/'. $m .'/'. $d;
}
elseif (_archive_validate_date($y, $m)) {
$url .= '/'. $y .'/'. $m;
}
elseif (_archive_validate_date($y)) {
$url .= '/'. $y;
}
return $url;
}
/**
* Parses the current URL and populates an archive date object.
*
* @param $year
* Number of year.
* @param $month
* Number of month.
* @param $day
* Number of day.
* @return
* A date object with GMT date values and a timezone value.
*/
function _archive_date($type, $year = 0, $month = 0, $day = 0) {
$date = new stdClass();
$date->tz = _archive_get_timezone();
$date->year = 0;
$date->month = 0;
$date->day = 0;
if (_archive_validate_date($year, $month, $day)) {
$date->year = $year;
$date->month = $month;
$date->day = $day;
}
elseif (_archive_validate_date($year, $month)) {
$date->year = $year;
$date->month = $month;
}
elseif (_archive_validate_date($year)) {
$date->year = $year;
}
$post_counts = _archive_post_count($type, $date);
$date->years = $post_counts['years'];
ksort($date->years);
$date->months = $post_counts['months'];
ksort($date->months);
$date->days = $post_counts['days'];
ksort($date->days);
$date->next_month_days = $post_counts['next_month_days'];
$date->prev_month_days = $post_counts['prev_month_days'];
return $date;
}
/**
* Determine timezone to use for the dates (from format_date).
*
* @return
* Timezone offset to use in time operations.
*/
function _archive_get_timezone() {
global $user;
if (variable_get('configurable_timezones', 1) && $user->uid && drupal_strlen($user->timezone)) {
return $user->timezone;
}
else {
return variable_get('date_default_timezone', 0);
}
}
function _archive_types_sql_string($type) {
// Validate type and specify node types to include
$final_types = '';
if (_archive_validate_type($type) && $type != 'all') {
$final_types = $type;
}
else {
$types = variable_get('archive_type_filters', array());
if (empty($types)) {
return '';
}
// If no checkboxes selected
if (!array_key_exists('0', $types)) {
foreach ($types as $key => $value) {
if (!$value) {
unset($types[$key]);
}
}
$final_types = implode("', '", array_keys($types));
}
}
if (strlen($final_types) > 0) {
$final_types = "AND n.type IN ('". $final_types ."') ";
}
return $final_types;
}
function _archive_types_array() {
$types = variable_get('archive_type_filters', array());
if (empty($types)) {
return array();
}
foreach ($types as $key => $value) {
if (!$value) {
unset($types[$key]);
}
}
return array_keys($types);
}
function _archive_types_sql_array($type) {
// Validate type and specify node types to include
$final_types = array();
if (_archive_validate_type($type) && $type != 'all') {
$final_types[] = $type;
}
else {
$types = variable_get('archive_type_filters', array());
if (empty($types)) {
return array();
}
// If no checkboxes selected
if (!array_key_exists('0', $types)) {
foreach ($types as $key => $value) {
if (!$value) {
unset($types[$key]);
}
}
}
$final_types = $types;
}
return $final_types;
}
/**
* Check if given year, month and date combination is valid for the archive.
*
* @param $year
* The year to check.
* @param $month
* The month to check.
* @param $day
* The day to check.
* @return
* TRUE or FALSE.
*/
function _archive_validate_date($year, $month = NULL, $day = NULL) {
$valid = FALSE;
if ($year && $year <= format_date(time(), 'custom', 'Y')) {
if (!is_null($month)) {
if (!is_null($day)) {
if ($last = gmdate('t', gmmktime(0, 0, 0, $month, 1, $year))) {
$valid = (0 < $day && $day <= $last);
}
}
elseif (0 < $month && $month <= 12) {
$valid = TRUE;
}
}
else {
$valid = TRUE;
}
}
return $valid;
}
/**
* Check if given node type is valid for the archive.
*
* @param $type
* The type to check.
* @return
* TRUE or FALSE.
*/
function _archive_validate_type($type) {
$types = variable_get('archive_type_filters', array());
if(empty($types)) {
return FALSE;
}
return in_array($type, $types);
}
/**
* Returns the range of dates with nodes.
*
* Returns an array with keys of 'years', 'months', and 'days' which map
* their respective timeframe to the number of posts in that timeframe.
*
* @param $type
* The object that is being filtered.
* @param $date
* A date object returned from _archive_date().
* @return
* An array of the (first year with posts, last year with posts).
*/
function _archive_post_count($type, $date) {
$with_posts = array(
'years' => array(),
'months' => array(),
'days' => array(),
'next_month_days' => array(),
'prev_month_days' => array()
);
$final_types = _archive_types_sql_array($type);
$node_query = db_select('node', 'n');
$node_query->fields('n', array('uid', 'created'));
$node_query->condition('n.status', 1);
if (!empty($final_types)) {
$node_query->condition('n.type', $final_types, 'IN');
}
$node_query->addTag('node_access');
$result = $node_query->execute();
$next_month = $date->month==12?1:$date->month+1;
$next_year = $date->month==12?$date->year+1:$date->year;
$prev_month = $date->month==1?12:$date->month-1;
$prev_year = $date->month==1?$date->year-1:$date->year;
foreach ($result as $o) {
list($year, $month, $day) = explode(' ', format_date($o->created, 'custom', 'Y n j'));
// Check for current month.
$with_posts['years'][$year] = array_key_exists($year, $with_posts['years'])?$with_posts['years'][$year]+1:1;
if ($date->year && $year == $date->year) {
$with_posts['months'][$month] = array_key_exists($month, $with_posts['months'])?$with_posts['months'][$month]+1:1;
if ($date->month && $month == $date->month) {
$with_posts['days'][$day] = array_key_exists($day, $with_posts['days'])?$with_posts['days'][$day]+1:1;
}
}
// Check for previous month.
if ($year == $next_year && $month == $next_month) {
if (isset($with_posts['next_month_days'][$day])) {
$with_posts['next_month_days'][$day]++;
}
else {
$with_posts['next_month_days'][$day] = 1;
}
}
// Check for next month.
if ($year == $prev_year && $month == $prev_month) {
if (isset($with_posts['prev_month_days'][$day])) {
$with_posts['prev_month_days'][$day]++;
}
else {
$with_posts['prev_month_days'][$day] = 1;
}
}
}
return $with_posts;
}
/**
* Get the date of the oldest post
*/
function _archive_get_oldest_date($type) {
$final_types = _archive_types_sql_string($type);
$result = db_query('SELECT MIN(n.created) FROM {node} n WHERE n.status = 1 '. $final_types)->fetchField();
return $result;
}
/**
* Get the date of the newest post
*/
function _archive_get_newest_date($type) {
$final_types = _archive_types_sql_string($type);
$result = db_query('SELECT MAX(n.created) FROM {node} n WHERE n.status = 1 '. $final_types)->fetchField();
return $result;
}
/**
* Get the date of the closesr previous post that is not in the specified month
*/
function _archive_get_prev_post_date($type, $year, $month) {
$final_types = _archive_types_sql_string($type);
$timestamp = mktime(0, 0, 0, $month, 1, $year);
$result = db_query('SELECT MAX(n.created) FROM {node} n WHERE n.status = 1 AND DATE(FROM_UNIXTIME(n.created)) < DATE(FROM_UNIXTIME(' . $timestamp . ')) '. $final_types)->fetchField();
// it returns NULL if there's no previous post
return $result;
}
/**
* Get the date of the closesr next post that is not in the specified month
*/
function _archive_get_next_post_date($type, $year, $month) {
$final_types = _archive_types_sql_string($type);
$timestamp = mktime(23, 59, 59, $month+1, 0, $year); // last day of the month
$result = db_query('SELECT MIN(n.created) FROM {node} n WHERE n.status = 1 AND DATE(FROM_UNIXTIME(n.created)) > DATE(FROM_UNIXTIME(' . $timestamp . ')) '. $final_types)->fetchField();
// it returns NULL if there's no previous post
return $result;
}
/**
* Convert UNIX timestamp data to SQL DATE format (YYYY-MM-DD)
*/
function _archive_get_sql_date_from_timestamp($timestamp) {
$y = date('Y', $timestamp);
$m = date('m', $timestamp);
$d = date('d', $timestamp);
return "'$y-$m-$d'";
}
/**
* Get the number of the post in the specified month
*/
function _archive_get_num_posts($type, $year, $month) {
$final_types = _archive_types_sql_string($type);
$from = mktime(0, 0, 0, $month, 1, $year); // first day of the month
$from = _archive_get_sql_date_from_timestamp($from);
$till = mktime(23, 59, 59, $month+1, 0, $year); // last day of the month
$till = _archive_get_sql_date_from_timestamp($till);
$result = db_query('SELECT COUNT(n.created) FROM {node} n WHERE n.status = 1 AND DATE(FROM_UNIXTIME(n.created)) BETWEEN ' . $from . ' AND ' . $till . ' '. $final_types)->fetchField();
return $result;
}