/[drupal]/contributions/modules/faceted_search/date_authored_facet.module
ViewVC logotype

Contents of /contributions/modules/faceted_search/date_authored_facet.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.13 - (show annotations) (download) (as text)
Sun Jan 4 19:36:25 2009 UTC (10 months, 3 weeks ago) by davidlesieur
Branch: MAIN
CVS Tags: DRUPAL-6--1-0-BETA2, DRUPAL-6--1-0-BETA1, HEAD
Changes since 1.12: +2 -2 lines
File MIME type: text/x-php
Improved data model for search environment settings.
1 <?php
2 // $Id: date_authored_facet.module,v 1.12 2008/08/26 04:28:10 davidlesieur Exp $
3
4 /**
5 * @file
6 * Provides a facet for searching content by date of creation.
7 */
8
9 require_once('./'. drupal_get_path('module', 'faceted_search') .'/faceted_search.inc');
10
11 // TODO: add setting for granularity.
12
13 /**
14 * Implementation of hook_faceted_search_collect().
15 */
16 function date_authored_facet_faceted_search_collect(&$facets, $domain, $env, $selection, $arg = NULL) {
17 switch ($domain) {
18 case 'facets':
19 // If the date authored facet is allowed.
20 if (!isset($selection) || isset($selection['date_authored'][1])) {
21 $facets[] = new date_authored_facet();
22 }
23 break;
24
25 case 'text':
26 // If the date authored facet is allowed.
27 if (!isset($selection) || isset($selection['date_authored'][1])) {
28 // Scan the given search text for a 'date_authored:date' token, and
29 // extract a category from it. Date is formatted as either YYYY,
30 // YYYY-MM, or YYYY-MM-DD.
31 if ($date = search_query_extract($arg, 'date_authored')) {
32 $matches = array();
33 // Match the three possible date formats.
34 if (preg_match('/^([12][0-9][0-9][0-9])(-([01][0-9])(-([0-3][0-9]))?)?$/', $date, $matches)) {
35 if (_date_authored_facet_check_date($matches[1], $matches[3], $matches[5])) {
36 $path = array(); // Array to build the path of categories.
37 if (isset($matches[1])) {
38 // Found year.
39 $path[] = new date_authored_facet_category($matches[1]);
40 }
41 if (isset($matches[3])) {
42 // Found month.
43 $path[] = new date_authored_facet_category($matches[1], $matches[3]);
44 }
45 if (isset($matches[5])) {
46 // Found day.
47 $path[] = new date_authored_facet_category($matches[1], $matches[3], $matches[5]);
48 }
49 if (!empty($path)) {
50 // Create a facet with the date found in the search text as the
51 // active category.
52 $facets[] = new date_authored_facet($path);
53 }
54 }
55 }
56 // Remove the parsed token from the search text.
57 $arg = search_query_insert($arg, 'date_authored');
58 }
59 }
60 return $arg;
61
62 case 'node':
63 // If the date authored facet is allowed.
64 if (!isset($selection) || isset($selection['date_authored'][1])) {
65 // Convert the node's creation date into the user's timezone.
66 $timestamp = $arg->created + _date_authored_facet_get_user_timezone();
67 $year = gmdate('Y', $timestamp);
68 $month = gmdate('n', $timestamp);
69 $day = gmdate('j', $timestamp);
70
71 // Build the path of categories.
72 $path = array(
73 new date_authored_facet_category($year),
74 new date_authored_facet_category($year, $month),
75 new date_authored_facet_category($year, $month, $day),
76 );
77
78 // Create a facet with the node's creation date as the active category.
79 $facets[] = new date_authored_facet($path);
80 }
81 break;
82 }
83 }
84
85 /**
86 * A facet for searching content by date of creation.
87 */
88 class date_authored_facet extends faceted_search_facet {
89
90 /**
91 * Constructor.
92 */
93 function date_authored_facet($active_path = array()) {
94 parent::faceted_search_facet('date_authored', $active_path);
95 }
96
97 function get_id() {
98 return 1; // This module provides only one facet.
99 }
100
101 function get_label() {
102 return t('Date authored');
103 }
104
105 /**
106 * Returns the available sort options for this facet.
107 */
108 function get_sort_options() {
109 $options = parent::get_sort_options();
110 $options['oldest'] = t('Oldest first');
111 $options['latest'] = t('Latest first');
112 return $options;
113 }
114
115 /**
116 * Handler for the 'count' sort criteria.
117 */
118 function build_sort_query_count(&$query) {
119 $query->add_orderby('count', 'DESC');
120 $query->add_orderby('n.created', 'ASC');
121 }
122
123 /**
124 * Handler for the 'oldest' sort criteria.
125 */
126 function build_sort_query_oldest(&$query) {
127 $query->add_orderby('n.created', 'ASC');
128 }
129
130 /**
131 * Handler for the 'latest' sort criteria.
132 */
133 function build_sort_query_latest(&$query) {
134 $query->add_orderby('n.created', 'DESC');
135 }
136
137 /**
138 * Returns the search text for this facet, taking into account this facet's
139 * active path.
140 */
141 function get_text() {
142 if ($category = $this->get_active_category()) {
143 return $category->get_text();
144 }
145 return '';
146 }
147
148 /**
149 * Updates a query for retrieving the root categories of this facet and their
150 * associated nodes within the current search results.
151 *
152 * @param $query
153 * The query object to update.
154 *
155 * @return
156 * FALSE if this facet can't have root categories.
157 */
158 function build_root_categories_query(&$query) {
159 $timezone = _date_authored_facet_get_timezone();
160 $query->add_field(NULL, "YEAR(FROM_UNIXTIME(n.created + $timezone))", 'node_created_year');
161 $query->add_groupby('node_created_year');
162 return TRUE;
163 }
164
165 /**
166 * This factory method creates categories given query results that include the
167 * fields selected in get_root_categories_query() or get_subcategories_query().
168 *
169 * @param $results
170 * $results A database query result resource.
171 *
172 * @return
173 * Array of categories.
174 */
175 function build_categories($results) {
176 $categories = array();
177 while ($result = db_fetch_object($results)) {
178 $categories[] = new date_authored_facet_category($result->node_created_year, $result->node_created_month, $result->node_created_day, $result->count);
179 }
180 return $categories;
181 }
182 }
183
184 /**
185 * A category for node creation date.
186 */
187 class date_authored_facet_category extends faceted_search_category {
188 var $_year = NULL;
189 var $_month = NULL;
190 var $_day = NULL;
191
192 /**
193 * Constructs a category for the specified date.
194 *
195 * @param $year
196 * Year corresponding to this category.
197 *
198 * @param $month
199 * Month corresponding to this category. Optional, but must be specified if
200 * $day is specified.
201 *
202 * @param $day
203 * Day corresponding to this category. Optional.
204 *
205 * @param $count
206 * The number of nodes associated to this category within the current
207 * search. Optional.
208 *
209 * Note: We consider the specified date as within the user's timezone.
210 */
211 function date_authored_facet_category($year, $month = NULL, $day = NULL, $count = NULL) {
212 parent::faceted_search_category($count);
213 $this->_year = $year;
214 $this->_month = $month;
215 $this->_day = $day;
216 }
217
218 /**
219 * Return the label of this category.
220 *
221 * @param $html
222 * TRUE when HTML is allowed in the label, FALSE otherwise. Checking this
223 * flag allows implementors to provide a rich-text label if desired, and an
224 * alternate plain text version for cases where HTML cannot be used. The
225 * implementor is responsible to ensure adequate security filtering.
226 */
227 function get_label($html = FALSE) {
228 if (isset($this->_day)) {
229 // Format date with YYYY-MM-DD.
230 $timestamp = gmmktime(0, 0, 0, $this->_month, $this->_day, $this->_year);
231 $format = variable_get('date_facets_format_ymd', 'm/d/Y');
232 }
233 elseif (isset($this->_month)) {
234 // Format date with YYYY-MM.
235 $timestamp = gmmktime(0, 0, 0, $this->_month, 1, $this->_year);
236 $format = variable_get('date_facets_format_ym', 'm/Y');
237 }
238 elseif (isset($this->_year)) {
239 // Format date with YYYY.
240 $timestamp = gmmktime(0, 0, 0, 1, 1, $this->_year);
241 $format = variable_get('date_facets_format_y', 'Y');
242 }
243 if ($timestamp) {
244 return format_date($timestamp, 'custom', $format, 0);
245 }
246 }
247
248 function get_text() {
249 $text = sprintf('%04d', $this->_year);
250 if (isset($this->_month)) {
251 $text .= sprintf('-%02d', $this->_month);
252 if (isset($this->_day)) {
253 $text .= sprintf('-%02d', $this->_day);
254 }
255 }
256 return $text;
257 }
258
259 /**
260 * Updates a query for retrieving the subcategories of this category and their
261 * associated nodes within the current search results.
262 *
263 * This only needs to be overridden for hierarchical facets.
264 *
265 * @param $query
266 * The query object to update.
267 *
268 * @return
269 * FALSE if this facet can't have subcategories.
270 */
271 function build_subcategories_query(&$query) {
272 $timezone = _date_authored_facet_get_timezone();
273 if (isset($this->_day)) {
274 return FALSE; // No subcategories.
275 }
276 if (isset($this->_month)) {
277 $from = sprintf("'%04d-%02d-01 00:00:00'", $this->_year, $this->_month);
278 $query->add_field(NULL, "YEAR(FROM_UNIXTIME(n.created + $timezone))", 'node_created_year');
279 $query->add_field(NULL, "MONTH(FROM_UNIXTIME(n.created + $timezone))", 'node_created_month');
280 $query->add_field(NULL, "DAY(FROM_UNIXTIME(n.created + $timezone))", 'node_created_day');
281 $query->add_where("(n.created + $timezone >= UNIX_TIMESTAMP($from))");
282 $query->add_where("(n.created + $timezone < UNIX_TIMESTAMP($from + INTERVAL 1 MONTH))");
283 $query->add_groupby('node_created_day'); // Needed for counting matching nodes.
284 return TRUE;
285 }
286 if (isset($this->_year)) {
287 $from = sprintf("'%04d-01-01 00:00:00'", $this->_year);
288 $query->add_field(NULL, "YEAR(FROM_UNIXTIME(n.created + $timezone))", 'node_created_year');
289 $query->add_field(NULL, "MONTH(FROM_UNIXTIME(n.created + $timezone))", 'node_created_month');
290 $query->add_where("(n.created + $timezone >= UNIX_TIMESTAMP($from))");
291 $query->add_where("(n.created + $timezone < UNIX_TIMESTAMP($from + INTERVAL 1 YEAR))");
292 $query->add_groupby('node_created_month'); // Needed for counting matching nodes.
293 return TRUE;
294 }
295 return FALSE; // Unreachable, unless something is wrong...
296 }
297
298 /**
299 * Updates a query for selecting nodes matching this category.
300 *
301 * @param $query
302 * The query object to update.
303 */
304 function build_results_query(&$query) {
305 $timezone = _date_authored_facet_get_timezone();
306 if (isset($this->_day)) {
307 $from = sprintf("'%04d-%02d-%02d 00:00:00'", $this->_year, $this->_month, $this->_day);
308 $query->add_where("(n.created + $timezone >= UNIX_TIMESTAMP($from))");
309 $query->add_where("(n.created + $timezone < UNIX_TIMESTAMP($from + INTERVAL 1 DAY))");
310 }
311 elseif (isset($this->_month)) {
312 $from = sprintf("'%04d-%02d-01 00:00:00'", $this->_year, $this->_month);
313 $query->add_where("(n.created + $timezone >= UNIX_TIMESTAMP($from))");
314 $query->add_where("(n.created + $timezone < UNIX_TIMESTAMP($from + INTERVAL 1 MONTH))");
315 }
316 elseif (isset($this->_year)) {
317 $from = sprintf("'%04d-01-01 00:00:00'", $this->_year);
318 $query->add_where("(n.created + $timezone >= UNIX_TIMESTAMP($from))");
319 $query->add_where("(n.created + $timezone < UNIX_TIMESTAMP($from + INTERVAL 1 YEAR))");
320 }
321 }
322 }
323
324 /**
325 * Returns the applicable timezone offset (in seconds) for date comparisons in
326 * database queries.
327 */
328 function _date_authored_facet_get_timezone() {
329 return _date_authored_facet_get_user_timezone() - _date_authored_facet_get_system_timezone();
330 }
331
332 /**
333 * Returns current user's timezone offset (in seconds).
334 */
335 function _date_authored_facet_get_user_timezone() {
336 global $user;
337 if (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->timezone)) {
338 return $user->timezone;
339 }
340 else {
341 return variable_get('date_default_timezone', 0);
342 }
343 }
344
345 /**
346 * Returns the database system's timezone offset (in seconds).
347 *
348 * This hack is used to cancel MySQL's timezone conversions when it converts
349 * dates to/from Unix timestamps. We could avoid this if MySQL had functions
350 * that worked directly in UTC (see http://bugs.mysql.com/bug.php?id=28961).
351 */
352 function _date_authored_facet_get_system_timezone() {
353 static $offset = NULL;
354 if (!isset($offset)) {
355 $system = db_result(db_query("SELECT UNIX_TIMESTAMP('2007-01-01 00:00:00')"));
356 $offset = 1167609600 - $system; // Find offset from the timestamp for 2007-01-01 00:00:00 UTC.
357 }
358 return $offset;
359 }
360
361 /**
362 * Checks the validity of a date or partial date.
363 */
364 function _date_authored_facet_check_date($year = NULL, $month = NULL, $day = NULL) {
365 if (!isset($year) || !is_numeric($year) || $year < 1) {
366 return FALSE;
367 }
368 if (isset($month) && (!is_numeric($month) || $month < 1 || $month > 12)) {
369 return FALSE;
370 }
371 if (isset($day) && (!isset($month) || !is_numeric($month) || !is_numeric($day) || !checkdate($month, $day, $year))) {
372 return FALSE;
373 }
374
375 return TRUE;
376 }

  ViewVC Help
Powered by ViewVC 1.1.2