0
|
1 <?php
|
|
2
|
|
3 /**
|
|
4 * @file
|
|
5 * Date query type plugin for the Apache Solr adapter.
|
|
6 */
|
|
7
|
|
8 /**
|
|
9 * Plugin for "date" query types.
|
|
10 */
|
|
11 class ApacheSolrFacetapiDate extends FacetapiQueryTypeDate implements FacetapiQueryTypeInterface {
|
|
12
|
|
13 /**
|
|
14 * Returns the query type associated with the plugin.
|
|
15 *
|
|
16 * @return string
|
|
17 * The query type.
|
|
18 */
|
|
19 static public function getType() {
|
|
20 return 'date';
|
|
21 }
|
|
22
|
|
23 /**
|
|
24 * Adds the filter to the query object.
|
|
25 *
|
|
26 * @param DrupalSolrQueryInterface $query
|
|
27 * An object containing the query in the backend's native API.
|
|
28 */
|
|
29 public function execute($query) {
|
|
30 // Gets the data range in formats that Solr understands.
|
|
31 $date_range = $this->getDateRange($query);
|
|
32 if (empty($date_range)) {
|
|
33 return NULL;
|
|
34 }
|
|
35 list($start, $end, $gap) = $date_range;
|
|
36 $query->addParam('facet.date', $this->facet['field']);
|
|
37 $query->addParam('f.' . $this->facet['field'] . '.facet.date.start', $start);
|
|
38 $query->addParam('f.' . $this->facet['field'] . '.facet.date.end', $end);
|
|
39 $query->addParam('f.' . $this->facet['field'] . '.facet.date.gap', $gap);
|
|
40
|
|
41 // Adds "hard limit" parameter to prevent too many return values.
|
|
42 $settings = $this->adapter->getFacet($this->facet)->getSettings();
|
|
43 $limit = empty($settings->settings['hard_limit']) ? 20 : (int) $settings->settings['hard_limit'];
|
|
44 $query->addParam('f.' . $this->facet['field'] . '.facet.limit', $limit);
|
|
45
|
|
46 $active = $this->adapter->getActiveItems($this->facet);
|
|
47 // Date filters don't support OR operator.
|
|
48 foreach ($active as $value => $item) {
|
|
49 $query->addFilter($this->facet['field'], $value);
|
|
50 }
|
|
51 }
|
|
52
|
|
53 /**
|
|
54 * Gets the range of dates we are using.
|
|
55 *
|
|
56 * @param DrupalSolrQueryInterface $query
|
|
57 * A SolrBaseQuery object.
|
|
58 *
|
|
59 * @return bool|array
|
|
60 * An array containing the gap and range information or false if not present
|
|
61 */
|
|
62 function getDateRange(DrupalSolrQueryInterface $query) {
|
|
63 $return = NULL;
|
|
64 $gap = NULL;
|
|
65
|
|
66 // Attempts to get next gap from passed date filters.
|
|
67 foreach ($this->adapter->getActiveItems($this->facet) as $item) {
|
|
68 if ($gap = facetapi_get_date_gap($item['start'], $item['end'])) {
|
|
69 $next_gap = facetapi_get_next_date_gap($gap, FACETAPI_DATE_SECOND);
|
|
70 if ($next_gap == $gap) {
|
|
71 $next_gap = NULL;
|
|
72 return NULL;
|
|
73 }
|
|
74 $return = array(
|
|
75 "{$item['start']}/$next_gap",
|
|
76 "{$item['end']}+1$next_gap/$next_gap",
|
|
77 "+1$next_gap",
|
|
78 );
|
|
79 }
|
|
80 }
|
|
81
|
|
82 // If no filters were passed, get default range.
|
|
83 if (NULL === $return) {
|
|
84
|
|
85 // Builds SQL that gets minimum and maximum values from node table.
|
|
86 $minimum = $maximum = FALSE;
|
|
87 if ($this->facet['min callback'] && is_callable($this->facet['min callback'])) {
|
|
88 $minimum = $this->facet['min callback']($this->facet);
|
|
89 }
|
|
90 if ($this->facet['max callback'] && is_callable($this->facet['max callback'])) {
|
|
91 $maximum = $this->facet['max callback']($this->facet);
|
|
92 }
|
|
93
|
|
94 // Gets the default gap.
|
|
95 //$gap = FACETAPI_DATE_YEAR;
|
|
96 if ($minimum && $maximum) {
|
|
97 $gap = facetapi_get_timestamp_gap($minimum, $maximum);
|
|
98 $minimum = facetapi_isodate($minimum, $gap);
|
|
99 $maximum = facetapi_isodate($maximum, $gap);
|
|
100 $return = array(
|
|
101 "$minimum/$gap",
|
|
102 "$maximum+1$gap/$gap",
|
|
103 "+1$gap",
|
|
104 );
|
|
105 }
|
|
106 }
|
|
107 // Returns the range information.
|
|
108 return $return;
|
|
109 }
|
|
110
|
|
111 /**
|
|
112 * Initializes the facet's build array.
|
|
113 *
|
|
114 * @return array
|
|
115 * The initialized render array.
|
|
116 */
|
|
117 public function build() {
|
|
118
|
|
119 // Initializes build and gets static response.
|
|
120 if (!$response = apachesolr_static_response_cache($this->adapter->getSearcher())) {
|
|
121 return array();
|
|
122 }
|
|
123 $build = array();
|
|
124
|
|
125 // Gets total number of documents matched in search.
|
|
126 $total = $response->response->numFound;
|
|
127
|
|
128 // Gets the active date facets, starts to builds the "parent - child"
|
|
129 // relationships.
|
|
130 $parent = NULL;
|
|
131 foreach ($this->adapter->getActiveItems($this->facet) as $value => $item) {
|
|
132 // Builds the raw facet "value", the count for selected items will be the
|
|
133 // total number of rows returned in the query.
|
|
134 $build[$value] = array('#count' => $total);
|
|
135
|
|
136 // If there is a previous item, there is a parent, uses a reference so the
|
|
137 // arrays are populated when they are updated.
|
|
138 if (NULL !== $parent) {
|
|
139 $build[$parent]['#item_children'][$value] = &$build[$value];
|
|
140 $build[$value]['#item_parents'][$parent] = $parent;
|
|
141 }
|
|
142
|
|
143 // Stores the last value iterated over.
|
|
144 $parent = $value;
|
|
145 }
|
|
146
|
|
147 // Gets raw facet data from the Solr server.
|
|
148 if (isset($response->facet_counts->facet_dates) && isset($response->facet_counts->facet_dates->{$this->facet['field']})) {
|
|
149 $raw_data = (array) $response->facet_counts->facet_dates->{$this->facet['field']};
|
|
150 }
|
|
151 else {
|
|
152 $raw_data = array();
|
|
153 }
|
|
154 //$end = (!empty($raw_data['end'])) ? $raw_data['end'] : '';
|
|
155 //$start = (!empty($raw_data['start'])) ? $raw_data['start'] : '';
|
|
156 $gap = (!empty($raw_data['gap'])) ? $raw_data['gap'] : '';
|
|
157
|
|
158 // We cannot list anything below a minute (range of 00 seconds till 59
|
|
159 // seconds. Milliseconds are not possible)
|
|
160 if ($gap != "+1SECOND") {
|
|
161 unset($raw_data['start']);
|
|
162 unset($raw_data['end']);
|
|
163 unset($raw_data['gap']);
|
|
164
|
|
165 // Treat each date facet as a range start, and use the next date facet
|
|
166 // as range end. Use 'end' for the final end.
|
|
167 $previous = NULL;
|
|
168
|
|
169 // Builds facet counts object used by the server.
|
|
170 foreach ($raw_data as $value => $count) {
|
|
171 if ($count) {
|
|
172 $from = $value;
|
|
173 $to = facetapi_isodate(strtotime($value . $gap));
|
|
174 $new_value = '[' . $from . ' TO ' . $to . ']';
|
|
175 $build[$new_value] = array('#count' => $count, '#active' => 0);
|
|
176 if (NULL !== $parent) {
|
|
177 $build[$parent]['#item_children'][$new_value] = &$build[$new_value];
|
|
178 $build[$new_value]['#item_parents'][$parent] = $parent;
|
|
179 }
|
|
180 }
|
|
181 }
|
|
182 }
|
|
183 return $build;
|
|
184 }
|
|
185 }
|