created + _date_authored_facet_get_user_timezone(); $year = gmdate('Y', $timestamp); $month = gmdate('n', $timestamp); $day = gmdate('j', $timestamp); // Build the path of categories. $path = array( new date_authored_facet_category($year), new date_authored_facet_category($year, $month), new date_authored_facet_category($year, $month, $day), ); // Create a facet with the node's creation date as the active category. $facets[] = new date_authored_facet($path); } break; } } /** * A facet for searching content by date of creation. */ class date_authored_facet extends faceted_search_facet { /** * Constructor. */ function date_authored_facet($active_path = array()) { parent::faceted_search_facet('date_authored', $active_path); } function get_id() { return 1; // This module provides only one facet. } function get_label() { return t('Date authored'); } /** * Returns the available sort options for this facet. */ function get_sort_options() { $options = parent::get_sort_options(); $options['oldest'] = t('Oldest first'); $options['latest'] = t('Latest first'); return $options; } /** * Handler for the 'count' sort criteria. */ function build_sort_query_count(&$query) { $query->add_orderby('count', 'DESC'); $query->add_orderby('n.created', 'ASC'); } /** * Handler for the 'oldest' sort criteria. */ function build_sort_query_oldest(&$query) { $query->add_orderby('n.created', 'ASC'); } /** * Handler for the 'latest' sort criteria. */ function build_sort_query_latest(&$query) { $query->add_orderby('n.created', 'DESC'); } /** * Returns the search text for this facet, taking into account this facet's * active path. */ function get_text() { if ($category = $this->get_active_category()) { return $category->get_text(); } return ''; } /** * Updates a query for retrieving the root categories of this facet and their * associated nodes within the current search results. * * @param $query * The query object to update. * * @return * FALSE if this facet can't have root categories. */ function build_root_categories_query(&$query) { $timezone = _date_authored_facet_get_timezone(); $query->add_field(NULL, "YEAR(FROM_UNIXTIME(n.created + $timezone))", 'node_created_year'); $query->add_groupby('node_created_year'); return TRUE; } /** * This factory method creates categories given query results that include the * fields selected in get_root_categories_query() or get_subcategories_query(). * * @param $results * $results A database query result resource. * * @return * Array of categories. */ function build_categories($results) { $categories = array(); while ($result = db_fetch_object($results)) { $categories[] = new date_authored_facet_category($result->node_created_year, $result->node_created_month, $result->node_created_day, $result->count); } return $categories; } } /** * A category for node creation date. */ class date_authored_facet_category extends faceted_search_category { var $_year = NULL; var $_month = NULL; var $_day = NULL; /** * Constructs a category for the specified date. * * @param $year * Year corresponding to this category. * * @param $month * Month corresponding to this category. Optional, but must be specified if * $day is specified. * * @param $day * Day corresponding to this category. Optional. * * @param $count * The number of nodes associated to this category within the current * search. Optional. * * Note: We consider the specified date as within the user's timezone. */ function date_authored_facet_category($year, $month = NULL, $day = NULL, $count = NULL) { parent::faceted_search_category($count); $this->_year = $year; $this->_month = $month; $this->_day = $day; } /** * Return the label of this category. * * @param $html * TRUE when HTML is allowed in the label, FALSE otherwise. Checking this * flag allows implementors to provide a rich-text label if desired, and an * alternate plain text version for cases where HTML cannot be used. The * implementor is responsible to ensure adequate security filtering. */ function get_label($html = FALSE) { if (isset($this->_day)) { // Format date with YYYY-MM-DD. $timestamp = gmmktime(0, 0, 0, $this->_month, $this->_day, $this->_year); $format = variable_get('date_facets_format_ymd', 'm/d/Y'); } elseif (isset($this->_month)) { // Format date with YYYY-MM. $timestamp = gmmktime(0, 0, 0, $this->_month, 1, $this->_year); $format = variable_get('date_facets_format_ym', 'm/Y'); } elseif (isset($this->_year)) { // Format date with YYYY. $timestamp = gmmktime(0, 0, 0, 1, 1, $this->_year); $format = variable_get('date_facets_format_y', 'Y'); } if ($timestamp) { return format_date($timestamp, 'custom', $format, 0); } } function get_text() { $text = sprintf('%04d', $this->_year); if (isset($this->_month)) { $text .= sprintf('-%02d', $this->_month); if (isset($this->_day)) { $text .= sprintf('-%02d', $this->_day); } } return $text; } /** * Updates a query for retrieving the subcategories of this category and their * associated nodes within the current search results. * * This only needs to be overridden for hierarchical facets. * * @param $query * The query object to update. * * @return * FALSE if this facet can't have subcategories. */ function build_subcategories_query(&$query) { $timezone = _date_authored_facet_get_timezone(); if (isset($this->_day)) { return FALSE; // No subcategories. } if (isset($this->_month)) { $from = sprintf("'%04d-%02d-01 00:00:00'", $this->_year, $this->_month); $query->add_field(NULL, "YEAR(FROM_UNIXTIME(n.created + $timezone))", 'node_created_year'); $query->add_field(NULL, "MONTH(FROM_UNIXTIME(n.created + $timezone))", 'node_created_month'); $query->add_field(NULL, "DAY(FROM_UNIXTIME(n.created + $timezone))", 'node_created_day'); $query->add_where("(n.created + $timezone >= UNIX_TIMESTAMP($from))"); $query->add_where("(n.created + $timezone < UNIX_TIMESTAMP($from + INTERVAL 1 MONTH))"); $query->add_groupby('node_created_day'); // Needed for counting matching nodes. return TRUE; } if (isset($this->_year)) { $from = sprintf("'%04d-01-01 00:00:00'", $this->_year); $query->add_field(NULL, "YEAR(FROM_UNIXTIME(n.created + $timezone))", 'node_created_year'); $query->add_field(NULL, "MONTH(FROM_UNIXTIME(n.created + $timezone))", 'node_created_month'); $query->add_where("(n.created + $timezone >= UNIX_TIMESTAMP($from))"); $query->add_where("(n.created + $timezone < UNIX_TIMESTAMP($from + INTERVAL 1 YEAR))"); $query->add_groupby('node_created_month'); // Needed for counting matching nodes. return TRUE; } return FALSE; // Unreachable, unless something is wrong... } /** * Updates a query for selecting nodes matching this category. * * @param $query * The query object to update. */ function build_results_query(&$query) { $timezone = _date_authored_facet_get_timezone(); if (isset($this->_day)) { $from = sprintf("'%04d-%02d-%02d 00:00:00'", $this->_year, $this->_month, $this->_day); $query->add_where("(n.created + $timezone >= UNIX_TIMESTAMP($from))"); $query->add_where("(n.created + $timezone < UNIX_TIMESTAMP($from + INTERVAL 1 DAY))"); } elseif (isset($this->_month)) { $from = sprintf("'%04d-%02d-01 00:00:00'", $this->_year, $this->_month); $query->add_where("(n.created + $timezone >= UNIX_TIMESTAMP($from))"); $query->add_where("(n.created + $timezone < UNIX_TIMESTAMP($from + INTERVAL 1 MONTH))"); } elseif (isset($this->_year)) { $from = sprintf("'%04d-01-01 00:00:00'", $this->_year); $query->add_where("(n.created + $timezone >= UNIX_TIMESTAMP($from))"); $query->add_where("(n.created + $timezone < UNIX_TIMESTAMP($from + INTERVAL 1 YEAR))"); } } } /** * Returns the applicable timezone offset (in seconds) for date comparisons in * database queries. */ function _date_authored_facet_get_timezone() { return _date_authored_facet_get_user_timezone() - _date_authored_facet_get_system_timezone(); } /** * Returns current user's timezone offset (in seconds). */ function _date_authored_facet_get_user_timezone() { global $user; if (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->timezone)) { return $user->timezone; } else { return variable_get('date_default_timezone', 0); } } /** * Returns the database system's timezone offset (in seconds). * * This hack is used to cancel MySQL's timezone conversions when it converts * dates to/from Unix timestamps. We could avoid this if MySQL had functions * that worked directly in UTC (see http://bugs.mysql.com/bug.php?id=28961). */ function _date_authored_facet_get_system_timezone() { static $offset = NULL; if (!isset($offset)) { $system = db_result(db_query("SELECT UNIX_TIMESTAMP('2007-01-01 00:00:00')")); $offset = 1167609600 - $system; // Find offset from the timestamp for 2007-01-01 00:00:00 UTC. } return $offset; } /** * Checks the validity of a date or partial date. */ function _date_authored_facet_check_date($year = NULL, $month = NULL, $day = NULL) { if (!isset($year) || !is_numeric($year) || $year < 1) { return FALSE; } if (isset($month) && (!is_numeric($month) || $month < 1 || $month > 12)) { return FALSE; } if (isset($day) && (!isset($month) || !is_numeric($month) || !is_numeric($day) || !checkdate($month, $day, $year))) { return FALSE; } return TRUE; }