Merge pull request #15306 from bhahumanists/bhahumanists-mailingID
[civicrm-core.git] / CRM / Campaign / Selector / Search.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 *
14 * @package CRM
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
16 */
17
18 /**
19 * This class is used to retrieve and display a range of contacts that match the given criteria.
20 */
21 class CRM_Campaign_Selector_Search extends CRM_Core_Selector_Base implements CRM_Core_Selector_API {
22
23 /**
24 * This defines two actions- View and Edit.
25 *
26 * @var array
27 */
28 public static $_links = NULL;
29
30 /**
31 * We use desc to remind us what that column is, name is used in the tpl
32 *
33 * @var array
34 */
35 public static $_columnHeaders;
36
37 /**
38 * Properties of contact we're interested in displaying
39 * @var array
40 */
41 public static $_properties = [
42 'contact_id',
43 'sort_name',
44 'street_unit',
45 'street_name',
46 'street_number',
47 'street_address',
48 'city',
49 'postal_code',
50 'state_province',
51 'country',
52 'email',
53 'phone',
54 'campaign_id',
55 'survey_activity_id',
56 'survey_activity_target_id',
57 'survey_activity_target_contact_id',
58 ];
59
60 /**
61 * Are we restricting ourselves to a single contact
62 *
63 * @var bool
64 */
65 protected $_single = FALSE;
66
67 /**
68 * Are we restricting ourselves to a single contact
69 *
70 * @var bool
71 */
72 protected $_limit = NULL;
73
74 /**
75 * What context are we being invoked from
76 *
77 * @var string
78 */
79 protected $_context = NULL;
80
81 /**
82 * QueryParams is the array returned by exportValues called on
83 * the HTML_QuickForm_Controller for that page.
84 *
85 * @var array
86 */
87 public $_queryParams;
88
89 /**
90 * Represent the type of selector.
91 *
92 * @var int
93 */
94 protected $_action;
95
96 /**
97 * The additional clause that we restrict the search with.
98 *
99 * @var string
100 */
101 protected $_surveyClause = NULL;
102
103 /**
104 * The query object.
105 *
106 * @var string
107 */
108 protected $_query;
109
110 /**
111 * Class constructor.
112 *
113 * @param array $queryParams
114 * Array of parameters for query.
115 * @param \const|int $action - action of search basic or advanced.
116 * @param string $surveyClause
117 * If the caller wants to further restrict the search.
118 * @param bool $single
119 * Are we dealing only with one contact?.
120 * @param int $limit
121 * How many voters do we want returned.
122 *
123 * @param string $context
124 *
125 * @return \CRM_Campaign_Selector_Search
126 */
127 public function __construct(
128 &$queryParams,
129 $action = CRM_Core_Action::NONE,
130 $surveyClause = NULL,
131 $single = FALSE,
132 $limit = NULL,
133 $context = 'search'
134 ) {
135 // submitted form values
136 $this->_queryParams = &$queryParams;
137
138 $this->_single = $single;
139 $this->_limit = $limit;
140 $this->_context = $context;
141
142 $this->_campaignClause = $surveyClause;
143 $this->_campaignFromClause = CRM_Utils_Array::value('fromClause', $surveyClause);
144 $this->_campaignWhereClause = CRM_Utils_Array::value('whereClause', $surveyClause);
145
146 // type of selector
147 $this->_action = $action;
148
149 $this->_query = new CRM_Contact_BAO_Query($this->_queryParams,
150 NULL, NULL, FALSE, FALSE,
151 CRM_Contact_BAO_Query::MODE_CAMPAIGN,
152 TRUE
153 );
154 }
155
156 /**
157 * This method returns the links that are given for each search row.
158 * currently the links added for each row are
159 *
160 * - View
161 * - Edit
162 *
163 * @return array
164 */
165 public static function &links() {
166 return self::$_links = [];
167 }
168
169 /**
170 * Getter for array of the parameters required for creating pager.
171 *
172 * @param $action
173 * @param array $params
174 */
175 public function getPagerParams($action, &$params) {
176 $params['csvString'] = NULL;
177 $params['status'] = ts('Respondents') . ' %%StatusMessage%%';
178 $params['rowCount'] = ($this->_limit) ? $this->_limit : CRM_Utils_Pager::ROWCOUNT;
179 $params['buttonTop'] = 'PagerTopButton';
180 $params['buttonBottom'] = 'PagerBottomButton';
181 }
182
183 /**
184 * Returns total number of rows for the query.
185 *
186 * @param string $action
187 *
188 * @return int
189 * Total number of rows
190 */
191 public function getTotalCount($action) {
192 return $this->_query->searchQuery(0, 0, NULL,
193 TRUE, FALSE,
194 FALSE, FALSE, FALSE,
195 $this->_campaignWhereClause,
196 NULL,
197 $this->_campaignFromClause
198 );
199 }
200
201 /**
202 * Returns all the rows in the given offset and rowCount.
203 *
204 * @param string $action
205 * The action being performed.
206 * @param int $offset
207 * The row number to start from.
208 * @param int $rowCount
209 * The number of rows to return.
210 * @param string $sort
211 * The sql string that describes the sort order.
212 * @param string $output
213 * What should the result set include (web/email/csv).
214 *
215 * @return int
216 * the total number of rows for this action
217 */
218 public function &getRows($action, $offset, $rowCount, $sort, $output = NULL) {
219 $result = $this->_query->searchQuery($offset, $rowCount, $sort,
220 FALSE, FALSE,
221 FALSE, FALSE,
222 FALSE, $this->_campaignWhereClause,
223 NULL,
224 $this->_campaignFromClause
225 );
226
227 // process the result of the query
228 $rows = [];
229
230 while ($result->fetch()) {
231 $this->_query->convertToPseudoNames($result);
232 $row = [];
233 // the columns we are interested in
234 foreach (self::$_properties as $property) {
235 if (property_exists($result, $property)) {
236 $row[$property] = $result->$property;
237 }
238 }
239 $row['checkbox'] = CRM_Core_Form::CB_PREFIX . $result->contact_id;
240 $row['contact_type'] = CRM_Contact_BAO_Contact_Utils::getImage($result->contact_type, FALSE, $result->contact_id);
241
242 $rows[] = $row;
243 }
244 $this->buildPrevNextCache($sort);
245
246 return $rows;
247 }
248
249 /**
250 * @param $sort
251 */
252 public function buildPrevNextCache($sort) {
253 //for prev/next pagination
254 $crmPID = CRM_Utils_Request::retrieve('crmPID', 'Integer');
255
256 if (!$crmPID) {
257 $cacheKey = "civicrm search {$this->_key}";
258 Civi::service('prevnext')->deleteItem(NULL, $cacheKey, 'civicrm_contact');
259
260 $sql = $this->_query->getSearchSQLParts(0, 0, $sort,
261 FALSE, FALSE,
262 FALSE, FALSE,
263 $this->_campaignWhereClause,
264 NULL,
265 $this->_campaignFromClause
266 );
267
268 $selectSQL = "
269 SELECT %1, contact_a.id, contact_a.display_name
270 FROM {$sql['from']}
271 ";
272
273 try {
274 Civi::service('prevnext')->fillWithSql($cacheKey, $selectSQL, [1 => [$cacheKey, 'String']]);
275 }
276 catch (CRM_Core_Exception $e) {
277 // Heavy handed, no? Seems like this merits an explanation.
278 return;
279 }
280
281 if (Civi::service('prevnext') instanceof CRM_Core_PrevNextCache_Sql) {
282 // SQL-backed prevnext cache uses an extra record for pruning the cache.
283 // Also ensure that caches stay alive for 2 days a per previous code.
284 Civi::cache('prevNextCache')->set($cacheKey, $cacheKey, 60 * 60 * 24 * CRM_Core_PrevNextCache_Sql::cacheDays);
285 }
286 }
287 }
288
289 /**
290 * @return array
291 * which contains an array of strings
292 */
293 public function getQILL() {
294 return $this->_query->qill();
295 }
296
297 /**
298 * Returns the column headers as an array of tuples:
299 * (name, sortName (key to the sort array))
300 *
301 * @param string $action
302 * The action being performed.
303 * @param string $output
304 * What should the result set include (web/email/csv).
305 *
306 * @return array
307 * the column headers that need to be displayed
308 */
309 public function &getColumnHeaders($action = NULL, $output = NULL) {
310 self::$_columnHeaders = [];
311
312 if (!$this->_single) {
313 $contactDetails = [
314 [
315 'name' => ts('Contact Name'),
316 'sort' => 'sort_name',
317 'direction' => CRM_Utils_Sort::ASCENDING,
318 ],
319 [
320 'name' => ts('Street Number'),
321 'sort' => 'street_number',
322 ],
323 [
324 'name' => ts('Street Name'),
325 'sort' => 'street_name',
326 ],
327 ['name' => ts('Street Address')],
328 [
329 'name' => ts('City'),
330 'sort' => 'city',
331 ],
332 [
333 'name' => ts('Postal Code'),
334 'sort' => 'postal_code',
335 ],
336 [
337 'name' => ts('State'),
338 'sort' => 'state_province_name',
339 ],
340 ['name' => ts('Country')],
341 ['name' => ts('Email')],
342 ['name' => ts('Phone')],
343 ];
344 self::$_columnHeaders = array_merge($contactDetails, self::$_columnHeaders);
345 }
346
347 return self::$_columnHeaders;
348 }
349
350 /**
351 * @return string
352 */
353 public function &getQuery() {
354 return $this->_query;
355 }
356
357 /**
358 * Name of export file.
359 *
360 * @param string $output
361 * Type of output.
362 *
363 * @return string
364 * name of the file
365 */
366 public function getExportFileName($output = 'csv') {
367 return ts('CiviCRM Respondent Search');
368 }
369
370 }