Index: misc/drupal.css =================================================================== RCS file: /cvs/drupal/drupal/misc/drupal.css,v retrieving revision 1.120 diff -u -r1.120 drupal.css --- misc/drupal.css 7 Sep 2005 20:56:00 -0000 1.120 +++ misc/drupal.css 8 Sep 2005 20:16:39 -0000 @@ -238,6 +238,37 @@ margin-bottom: 1em; margin-top: 0; } +#archive_container dt { + font-weight: bold; + margin: 0.5em 0 0 0; + padding: 0.2em 0.5em; + background-color: #eee; +} +#archive_container dd { + margin: 0; + border: 1px solid #eee; +} +#archive_container ul { + margin: 0; + padding: 4px 10px 4px 10px; + border-bottom: 1px solid #ddd; +} +#archive_container ul li { + margin: 0; + padding: 0 0.2em; + display: inline; + list-style-type: none; +} +#archive_years .selected, +#archive_months .selected { + border-bottom: 4px solid #ddd; +} +ul#archive_days { + border: 0px; +} +#archive_days .selected { + background-color: #ddd; +} .book { margin: 1em 0 1em 0; } @@ -282,33 +313,6 @@ .book .nav .up { text-align: center; } -.calendar .row-week td a { - display: block; -} -.calendar .row-week td a:hover { - background-color: #888; color: #fff; -} -.calendar a { - text-decoration: none; -} -.calendar a:hover { - text-decoration: none; -} -.calendar table { - border-collapse: collapse; - width: 100%; - border: 1px solid #000; -} -.calendar td, .calendar th { - text-align: center; - border: 1px solid #000; - padding: 1px; - margin: 0; - font-size: 0.8em; -} -.calendar td.day-blank { - border: 0; -} .tips { margin-top: 0; margin-bottom: 0; Index: modules/archive.module =================================================================== RCS file: /cvs/drupal/drupal/modules/archive.module,v retrieving revision 1.82 diff -u -r1.82 archive.module --- modules/archive.module 25 Aug 2005 21:14:16 -0000 1.82 +++ modules/archive.module 8 Sep 2005 20:13:30 -0000 @@ -1,11 +1,11 @@ timezone; - $end_of_today = mktime(23, 59, 59, date('n', time()), date('d', time()), date('Y', time())) + $user->timezone; - - // Extract the requested date: - if ($edit['year'] && $edit['month'] && $edit['day']) { - $year = $edit['year']; - $month = $edit['month']; - $day = $edit['day']; - - $requested = mktime(0, 0, 0, $month, $day, $year) + $user->timezone; - } - else if (arg(0) == 'archive' && arg(3)) { - $year = arg(1); - $month = arg(2); - $day = arg(3); +function archive_menu($may_cache) { + $items = array(); - $requested = mktime(0, 0, 0, $month, $day, $year) + $user->timezone; + if ($may_cache) { + $items[] = array('path' => 'archive', 'title' => t('archives'), + 'callback' => 'archive_page', 'access' => user_access('access content')); } - else { - $year = date('Y', time()); - $month = date('n', time()); - $day = date('d', time()); - $requested = $end_of_today + $user->timezone; + return $items; +} + +/** + * Menu callback; displays the archives based on the selected date. + */ +function archive_page() { + $arch_data = archive_selected_date(); + + $output = theme("archive_navigation", $arch_data); + + // Fetch nodes for the selected date, or current date if none selected. + $result = pager_query(archive_build_query($arch_data), variable_get('default_nodes_main', 10)); + + if (db_num_rows($result)) { + while ($node = db_fetch_object($result)) { + $output .= node_view(node_load(array('nid' => $node->nid, 'type' => $node->type)), 1); + } + + $output .= theme('pager', NULL, variable_get('default_nodes_main', 10)); + } + + return $output; +} + +/** + * Parses URL and returns a data object with the selected date information. + */ +function archive_selected_date() { + $arch_data->year = 0; + $arch_data->month = 0; + $arch_data->day = 0; + + // Determine the date user has requested. + if (arg(1) && archive_valid_year(arg(1))) { + $arch_data->year = arg(1); + + if (arg(2) && archive_valid_month(arg(2))) { + $arch_data->month = arg(2); + + if (arg(3) && archive_valid_day(arg(3), arg(2), arg(1))) { + $arch_data->day = arg(3); + } + } + } + else { // If no user date, start with today. + $arch_data->year = date("Y", time()); } - $start_of_month = mktime(0, 0, 0, $month, 1, $year); + // determine if we have any term filters in our URL. we do it + // via the URL instead of arg() to prevent huge if/else trees. + preg_match('/term\/(\d+)/', $_GET['q'], $matches); + if (isset($matches[1])) { $arch_data->tid = $matches[1]; } - // Extract first day of the month: - $first = date('w', $start_of_month); + $arch_data->start_of_month = mktime(0, 0, 0, $arch_data->month, 1, $arch_data->year); + $arch_data->end_of_month = mktime(0, 0, 0, $arch_data->month + 1, 1, $arch_data->year); + $arch_data->years = archive_years($arch_data); + $arch_data->months = archive_months($arch_data); + $arch_data->days = archive_days($arch_data); - // Extract last day of the month: - $last = date('t', $start_of_month); + return $arch_data; +} + +/** + * Create and return a SQL string based on our parsed date data. + */ +function archive_build_query($arch_data) { + if ($arch_data->day > 0 && $arch_data->month > 0) { + // Limit the display interval to only one day. + $date_begin = mktime(0, 0, 0, $arch_data->month, $arch_data->day, $arch_data->year); + $date_end = mktime(0, 0, 0, $arch_data->month, $arch_data->day + 1, $arch_data->year); + } + elseif ($arch_data->month > 0) { + // Limit the display interval to one month. + $date_begin = $arch_data->start_of_month; + $date_end = $arch_data->end_of_month; + } + else { + // Limit the display interval to one year. + $date_begin = mktime(0, 0, 0, 1, 1, $arch_data->year); + $date_end = mktime(0, 0, 0, 1, 1, $arch_data->year + 1); + } + + // filtered by terms? + return isset($arch_data->tid) + ? "SELECT n.nid, n.type FROM {node} n LEFT JOIN {term_node} tn ON tn.nid = n.nid WHERE status = 1 AND n.created >= $date_begin AND n.created < $date_end AND tn.tid = $arch_data->tid ORDER BY n.created DESC" + : "SELECT nid, type FROM {node} WHERE status = 1 AND created >= $date_begin AND created < $date_end ORDER BY created DESC"; +} - $end_of_month = mktime(23, 59, 59, $month, $last, $year); +/** + * Returns the range of years with posts as an array with two + * values: the earlist year (ex. '2001') and the latest. + */ +function archive_years($arch_data) { + $years = isset($arch_data->tid) + ? db_fetch_object(db_query('SELECT MIN(n.created) AS min_date, MAX(n.created) AS max_date FROM {node} n LEFT JOIN {term_node} tn ON tn.nid = n.nid WHERE status = 1 AND tn.tid = %d', $arch_data->tid)) + : db_fetch_object(db_query('SELECT MIN(created) AS min_date, MAX(created) AS max_date FROM {node} WHERE status = 1')); + + if ($years->min_date && $years->max_date) { + return array(date("Y", $years->min_date), date("Y", $years->max_date)); + } + else { // no content at all! + return array(date("Y", time())); + } +} + +/** + * Returns an array of months of the passed year which have nodes. + */ +function archive_months($arch_data) { + $date_begin = mktime(0, 0, 0, 1, 1, $arch_data->year); + $date_end = mktime(0, 0, 0, 1, 1, $arch_data->year + 1); - $cache = cache_get("archive:calendar:$day-$month-$year"); + $result = isset($arch_data->tid) + ? db_query('SELECT DISTINCT MONTH(FROM_UNIXTIME(n.created)) AS m_month FROM {node} n LEFT JOIN {term_node} tn ON tn.nid = n.nid WHERE n.status = 1 AND n.created >= %d AND n.created < %d AND tn.tid = %d', $date_begin, $date_end, $arch_data->tid) + : db_query('SELECT DISTINCT MONTH(FROM_UNIXTIME(created)) AS m_month FROM {node} WHERE status = 1 AND created >= %d AND created < %d', $date_begin, $date_end); - if (!empty($cache)) { - return $cache->data; + $months_with_posts = array(); + while ($month = db_fetch_object($result)) { + $months_with_posts[] = $month->m_month; } - // Calculate previous and next months dates and check for shorter months (28/30 days) - $prevmonth = mktime(23, 59, 59, $month - 1, 1, $year); - $prev = mktime(23, 59, 59, $month - 1, min(date('t', $prevmonth), $day), $year); - $nextmonth = mktime(23, 59, 59, $month + 1, 1, $year); - $next = mktime(23, 59, 59, $month + 1, min(date('t', $nextmonth), $day), $year); + return $months_with_posts; +} - $sql = 'SELECT n.nid, n.created FROM {node} n WHERE n.status = 1 AND n.created > %d AND n.created < %d ORDER BY n.created'; - $sql = db_rewrite_sql($sql); - $result = db_query($sql, $start_of_month, $end_of_month); +/** + * Returns an array of days of a given month/year which have nodes. + */ +function archive_days($arch_data) { + $result = isset($arch_data->tid) + ? db_query('SELECT n.nid, n.created FROM {node} n LEFT JOIN {term_node} tn ON tn.nid = n.nid WHERE status = 1 AND n.created >= %d AND n.created < %d AND tn.tid = %d ORDER BY n.created', $arch_data->start_of_month, $arch_data->end_of_month, $arch_data->tid) + : db_query('SELECT nid, created FROM {node} WHERE status = 1 AND created >= %d AND created < %d ORDER BY created', $arch_data->start_of_month, $arch_data->end_of_month); $days_with_posts = array(); while ($day_with_post = db_fetch_object($result)) { - $daynum = date('j', $day_with_post->created + $user->timezone); + $daynum = date('j', $day_with_post->created); if (isset($days_with_posts[$daynum])) { $days_with_posts[$daynum]++; } @@ -87,169 +171,167 @@ } } - // Generate calendar header: - $output .= "\n\n"; - $output .= '
'; - $output .= '\n"; - $output .= ' \n"; - - // First day of week (0 => Sunday, 1 => Monday, ...) - $weekstart = variable_get('date_first_day', 0); - - // Last day of week - ($weekstart - 1 == -1) ? $lastday = 6 : $lastday = $weekstart - 1; - - // Generate the days of the week: - $firstcolumn = mktime(0, 0, 0, 3, 20 + $weekstart, 1994); - - $output .= " \n"; - $days = array(t('Sunday') => t('Su'), t('Monday') => t('Mo'), t('Tuesday') => t('Tu'), t('Wednesday') => t('We'), t('Thursday') => t('Th'), t('Friday') => t('Fr'), t('Saturday') => t('Sa')); - if ($weekstart) { - $days = array_merge(array_slice($days, $weekstart), array_slice($days, 0, $weekstart)); - } - - foreach ($days as $fullname => $name) { - $output .= ' \n"; - } - $output .= "\n"; - - // Initialize temporary variables: - $nday = 1; - $sday = $first; - - // Loop through all the days of the month: - while ($nday <= $last) { - // Set up blank days for first week of the month (allowing individual blank day styling): - if ($first != $weekstart) { - $blankdays = ($first - $weekstart + 7) % 7; - $output .= " " . str_repeat("\n", $blankdays); - $first = $weekstart; - } - // Start every week on a new line: - if ($sday == $weekstart) { - $output .= " \n"; - } - - // Print one cell: - $date = mktime(0, 0, 0, $month, $nday, $year) + $user->timezone; - if (isset($days_with_posts[$nday])) { - $daytext = l($nday, "archive/$year/$month/$nday", array("title" => format_plural($days_with_posts[$nday], "1 post", "%count posts"))); - $dayclass = 'day-link'; - } - else { - $daytext = $nday; - $dayclass = 'day-normal'; - } - if ($date == $requested) { - $output .= " \n"; - } - else if ($date == $start_of_today) { - $output .= " \n"; - } - else if ($date > $end_of_today) { - $output .= " \n"; - } - else { - $output .= " \n"; - } + return $days_with_posts; +} - // Start every week on a new line: - if ($sday == $lastday) { - $output .= " \n"; - } +/** + * Determines if the passed $year is between 1990 and 2040. + */ +function archive_valid_year($year) { + return (1990 < $year && $year < 2040); +} + +/** + * Determines if the passed $month is between 1 and 12. + */ +function archive_valid_month($month) { + return (1 <= $month && $month <= 12); +} - // Update temporary variables: - $sday++; - $sday = $sday % 7; - $nday++; +/** + * Determines if the passed values are a valid day. + */ +function archive_valid_day($day, $month, $year) { + if (archive_valid_month($month) && archive_valid_year($year)) { + $last_day = date("t", mktime(0, 0, 0, $month, 1, $year)); + return (1 <= $day && $day <= $last_day); } - // Complete the calendar (allowing individual blank day styling): - if ($sday != $weekstart) { - $end = (7 - $sday + $weekstart) % 7; - $output .= str_repeat("\n", $end) . "\n"; + return 0; +} + +/** + * Given the current data and URL, return a URL path. This routine + * is used by all the theming navigation functions - passing $arch_data + * allows us to determine currently selected years and months without + * forcing that logic into the themer's hands. + */ +function archive_build_url($arch_data, $year = 0, $month = 0, $day = 0) { + $url = 'archive'; + + if (archive_valid_year($year)) { + $url .= '/'. $year; + + if (archive_valid_month($month)) { + $url .= '/'. $month; + + if (archive_valid_day($day, $month, $year)) { + $url .= '/'. $day; + } + } } + else if (archive_valid_year($arch_data->year) && archive_valid_month($month)) { + $url .= '/'. $arch_data->year .'/'. $month; - $output .= "
'. l('«', 'archive/'. date('Y/m/d', $prev), array('title' => t('Previous month'))) .' '. format_date($requested, 'custom', 'F') . date(' Y', $requested) .' '. ($nextmonth <= time() ? l('»', 'archive/'. date('Y/m/d', $next), array('title' => t('Next month'))) : ' ') ."
'. $name . "
 
$daytext$daytext$daytext$daytext
 
\n\n"; + if (archive_valid_day($day, $month, $arch_data->year)) { + $url .= '/'. $day; + } + } + else if (archive_valid_year($arch_data->year) && archive_valid_month($arch_data->month)) { + $url .= '/'. $arch_data->year .'/'. $arch_data->month; - cache_set("archive:calendar:$day-$month-$year", $output, CACHE_TEMPORARY); + if (archive_valid_day($day, $arch_data->month, $arch_data->year)) { + $url .= '/'. $day; + } + } + + if (isset($arch_data->tid)) { + $url .= '/term/'.$arch_data->tid; + } - return $output; + return $url; } /** - * Implementation of hook_block(). - * - * Generates a calendar for the current month, with links to the archives - * for each day. - */ -function archive_block($op = 'list', $delta = 0) { - if ($op == 'list') { - $blocks[0]['info'] = t('Calendar to browse archives'); - return $blocks; - } - else if ($op == 'view' && user_access('access content')) { - $block['subject'] = t('Browse archives'); - $block['content'] = archive_calendar(); - return $block; + * Theming; master wrapper that controls the display of our navigation. + */ +function theme_archive_navigation($arch_data) { + $output = '
'; + $output .= '
'. t('Date') .'
'; + + $output .= theme("archive_navigation_years", $arch_data); + + if (archive_valid_year($arch_data->year)) { + $output .= theme("archive_navigation_months", $arch_data); + } + if (archive_valid_month($arch_data->month)) { + $output .= theme("archive_navigation_days", $arch_data); } + + $output .= '
'; + return $output; } /** - * Implementation of hook_menu(). + * Theming; displays the navigation for archives by year. */ -function archive_menu($may_cache) { - $items = array(); +function theme_archive_navigation_years($arch_data) { + $output = ''; + return $output; } /** - * Menu callback; lists all nodes posted on a given date. + * Theming; displays the navigation for archives by month. */ -function archive_page($year = 0, $month = 0, $day = 0) { - global $user; +function theme_archive_navigation_months($arch_data) { + $output = ''; return $output; } +/** + * Theming; displays the navigation for archives by day. + */ +function theme_archive_navigation_days($arch_data) { + $output = ''; + return $output; +}