Merge pull request #15756 from eileenmcnaughton/qfbug
[civicrm-core.git] / CRM / Event / Form / Search.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2020 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2020
32 */
33
34 /**
35 * This file is for civievent search
36 */
37 class CRM_Event_Form_Search extends CRM_Core_Form_Search {
38
39 /**
40 * The params that are sent to the query.
41 *
42 * @var array
43 */
44 protected $_queryParams;
45
46 /**
47 * Are we restricting ourselves to a single contact.
48 *
49 * @var bool
50 */
51 protected $_single = FALSE;
52
53 /**
54 * Are we restricting ourselves to a single contact.
55 *
56 * @var bool
57 */
58 protected $_limit = NULL;
59
60 /**
61 * Prefix for the controller.
62 * @var string
63 */
64 protected $_prefix = "event_";
65
66 /**
67 * The saved search ID retrieved from the GET vars.
68 *
69 * @var int
70 */
71 protected $_ssID;
72
73 /**
74 * Metadata of all fields to include on the form.
75 *
76 * @var array
77 */
78 protected $searchFieldMetadata = [];
79
80 /**
81 * Get the default entity for the form.
82 *
83 * @return string
84 */
85 public function getDefaultEntity() {
86 return 'Participant';
87 }
88
89 /**
90 * Processing needed for buildForm and later.
91 *
92 * @return void
93 *
94 * @throws \CRM_Core_Exception
95 * @throws \CiviCRM_API3_Exception
96 */
97 public function preProcess() {
98 $this->set('searchFormName', 'Search');
99
100 /**
101 * set the button names
102 */
103 $this->_searchButtonName = $this->getButtonName('refresh');
104 $this->_actionButtonName = $this->getButtonName('next', 'action');
105
106 $this->_done = FALSE;
107
108 parent::preProcess();
109
110 $this->_queryParams = CRM_Contact_BAO_Query::convertFormValues($this->_formValues, 0, FALSE, NULL, ['event_id']);
111 $selector = new CRM_Event_Selector_Search($this->_queryParams,
112 $this->_action,
113 NULL,
114 $this->_single,
115 $this->_limit,
116 $this->_context
117 );
118 $prefix = NULL;
119 if ($this->_context == 'user') {
120 $prefix = $this->_prefix;
121 }
122
123 $this->assign("{$prefix}limit", $this->_limit);
124 $this->assign("{$prefix}single", $this->_single);
125
126 $controller = new CRM_Core_Selector_Controller($selector,
127 $this->get(CRM_Utils_Pager::PAGE_ID),
128 $this->getSortID(),
129 CRM_Core_Action::VIEW,
130 $this,
131 CRM_Core_Selector_Controller::TRANSFER,
132 $prefix
133 );
134 $controller->setEmbedded(TRUE);
135 $controller->moveFromSessionToTemplate();
136
137 $this->assign('summary', $this->get('summary'));
138 }
139
140 /**
141 * Build the form object.
142 *
143 * @return void
144 *
145 * @throws \CRM_Core_Exception
146 */
147 public function buildQuickForm() {
148 parent::buildQuickForm();
149 $this->addContactSearchFields();
150
151 CRM_Event_BAO_Query::buildSearchForm($this);
152
153 $rows = $this->get('rows');
154 if (is_array($rows)) {
155 $lineItems = $eventIds = [];
156 if (!$this->_single) {
157 $this->addRowSelectors($rows);
158 }
159 foreach ($rows as $row) {
160 $eventIds[$row['event_id']] = $row['event_id'];
161 if (CRM_Event_BAO_Event::usesPriceSet($row['event_id'])) {
162 // add line item details if applicable
163 $lineItems[$row['participant_id']] = CRM_Price_BAO_LineItem::getLineItems($row['participant_id']);
164 }
165 }
166
167 //get actual count only when we are dealing w/ single event.
168 $participantCount = 0;
169 if (count($eventIds) == 1) {
170 //convert form values to clause.
171 $seatClause = [];
172 if (CRM_Utils_Array::value('participant_test', $this->_formValues) == '1' || CRM_Utils_Array::value('participant_test', $this->_formValues) == '0') {
173 $seatClause[] = "( participant.is_test = {$this->_formValues['participant_test']} )";
174 }
175 if (!empty($this->_formValues['participant_status_id'])) {
176 $seatClause[] = CRM_Contact_BAO_Query::buildClause("participant.status_id", 'IN', $this->_formValues['participant_status_id'], 'Int');
177 if ($status = CRM_Utils_Array::value('IN', $this->_formValues['participant_status_id'])) {
178 $this->_formValues['participant_status_id'] = $status;
179 }
180 }
181 if (!empty($this->_formValues['participant_role_id'])) {
182 $escapedRoles = [];
183 foreach ((array) $this->_formValues['participant_role_id'] as $participantRole) {
184 $escapedRoles[] = CRM_Utils_Type::escape($participantRole, 'String');
185 }
186 $seatClause[] = "( participant.role_id IN ( '" . implode("' , '", $escapedRoles) . "' ) )";
187 }
188
189 // CRM-15379
190 if (!empty($this->_formValues['participant_fee_id'])) {
191 $participant_fee_id = $this->_formValues['participant_fee_id'];
192 $val_regexp = [];
193 foreach ($participant_fee_id as $k => &$val) {
194 $val = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue', $val, 'label');
195 $val_regexp[$k] = CRM_Core_DAO::escapeString(preg_quote(trim($val)));
196 $val = CRM_Core_DAO::escapeString(trim($val));
197 }
198 $feeLabel = implode('|', $val_regexp);
199 $seatClause[] = "( participant.fee_level REGEXP '{$feeLabel}' )";
200 }
201
202 $seatClause = implode(' AND ', $seatClause);
203 $participantCount = CRM_Event_BAO_Event::eventTotalSeats(array_pop($eventIds), $seatClause);
204 }
205 $this->assign('participantCount', $participantCount);
206 $this->assign('lineItems', $lineItems);
207
208 $taskParams['ssID'] = isset($this->_ssID) ? $this->_ssID : NULL;
209 $tasks = CRM_Event_Task::permissionedTaskTitles(CRM_Core_Permission::getPermission(), $taskParams);
210
211 if (isset($this->_ssID)) {
212 $savedSearchValues = [
213 'id' => $this->_ssID,
214 'name' => CRM_Contact_BAO_SavedSearch::getName($this->_ssID, 'title'),
215 ];
216 $this->assign_by_ref('savedSearch', $savedSearchValues);
217 $this->assign('ssID', $this->_ssID);
218 }
219
220 $this->addTaskMenu($tasks);
221 }
222
223 }
224
225 /**
226 * Get the label for the sortName field if email searching is on.
227 *
228 * (email searching is a setting under search preferences).
229 *
230 * @return string
231 */
232 protected function getSortNameLabelWithEmail() {
233 return ts('Participant Name or Email');
234 }
235
236 /**
237 * Get the label for the sortName field if email searching is off.
238 *
239 * (email searching is a setting under search preferences).
240 *
241 * @return string
242 */
243 protected function getSortNameLabelWithOutEmail() {
244 return ts('Participant Name');
245 }
246
247 /**
248 * Get the label for the tag field.
249 *
250 * We do this in a function so the 'ts' wraps the whole string to allow
251 * better translation.
252 *
253 * @return string
254 */
255 protected function getTagLabel() {
256 return ts('Participant Tag(s)');
257 }
258
259 /**
260 * Get the label for the group field.
261 *
262 * @return string
263 */
264 protected function getGroupLabel() {
265 return ts('Participant Group(s)');
266 }
267
268 /**
269 * Get the label for the group field.
270 *
271 * @return string
272 */
273 protected function getContactTypeLabel() {
274 return ts('Participant Contact Type');
275 }
276
277 /**
278 * Test submit the form.
279 * @param $formValues
280 */
281 public function testSubmit($formValues) {
282 $this->submit($formValues);
283 }
284
285 /**
286 * Submit the search form with given values.
287 * @param $formValues
288 */
289 private function submit($formValues) {
290 $this->_formValues = $formValues;
291
292 $this->fixFormValues();
293
294 if (isset($this->_ssID) && empty($_POST)) {
295 // if we are editing / running a saved search and the form has not been posted
296 $this->_formValues = CRM_Contact_BAO_SavedSearch::getFormValues($this->_ssID);
297 }
298
299 // We don't show test records in summaries or dashboards
300 if (empty($this->_formValues['participant_test']) && $this->_force) {
301 $this->_formValues["participant_test"] = 0;
302 }
303
304 CRM_Core_BAO_CustomValue::fixCustomFieldValue($this->_formValues);
305
306 $this->_queryParams = CRM_Contact_BAO_Query::convertFormValues($this->_formValues, 0, FALSE, NULL, ['event_id']);
307
308 $this->set('formValues', $this->_formValues);
309 $this->set('queryParams', $this->_queryParams);
310
311 $buttonName = $this->controller->getButtonName();
312 if ($buttonName == $this->_actionButtonName) {
313 // check actionName and if next, then do not repeat a search, since we are going to the next page
314
315 // hack, make sure we reset the task values
316 $stateMachine = $this->controller->getStateMachine();
317 $formName = $stateMachine->getTaskFormName();
318 $this->controller->resetPage($formName);
319 return;
320 }
321
322 $this->_queryParams = CRM_Contact_BAO_Query::convertFormValues($this->_formValues, 0, FALSE, NULL, ['event_id']);
323
324 $selector = new CRM_Event_Selector_Search($this->_queryParams,
325 $this->_action,
326 NULL,
327 $this->_single,
328 $this->_limit,
329 $this->_context
330 );
331
332 $selector->setKey($this->controller->_key);
333
334 $prefix = NULL;
335 if ($this->_context == 'user') {
336 $prefix = $this->_prefix;
337 }
338
339 $this->assign("{$prefix}limit", $this->_limit);
340 $this->assign("{$prefix}single", $this->_single);
341
342 $controller = new CRM_Core_Selector_Controller($selector,
343 $this->get(CRM_Utils_Pager::PAGE_ID),
344 $this->getSortID(),
345 CRM_Core_Action::VIEW,
346 $this,
347 CRM_Core_Selector_Controller::SESSION,
348 $prefix
349 );
350 $controller->setEmbedded(TRUE);
351
352 $query = $selector->getQuery();
353 if ($this->_context == 'user') {
354 $query->setSkipPermission(TRUE);
355 }
356 $controller->run();
357 }
358
359 /**
360 * The post processing of the form gets done here.
361 *
362 * Key things done during post processing are
363 * - check for reset or next request. if present, skip post procesing.
364 * - now check if user requested running a saved search, if so, then
365 * the form values associated with the saved search are used for searching.
366 * - if user has done a submit with new values the regular post submissing is
367 * done.
368 * The processing consists of using a Selector / Controller framework for getting the
369 * search results.
370 *
371 * @param
372 *
373 * @return void
374 * @throws \CRM_Core_Exception
375 */
376 public function postProcess() {
377 if ($this->_done) {
378 return;
379 }
380
381 $this->_done = TRUE;
382 $formValues = $this->getFormValues();
383
384 $this->submit($formValues);
385 }
386
387 /**
388 * add the rules (mainly global rules) for form.
389 * All local rules are added near the element
390 *
391 * @return void
392 * @see valid_date
393 */
394 public function addRules() {
395 }
396
397 public function fixFormValues() {
398 // if this search has been forced
399 // then see if there are any get values, and if so over-ride the post values
400 // note that this means that GET over-rides POST :)
401 $event = CRM_Utils_Request::retrieve('event', 'Positive');
402 if ($event) {
403 $this->_formValues['event_id'] = $event;
404 $this->_formValues['event_name'] = CRM_Event_PseudoConstant::event($event, TRUE);
405 }
406
407 $status = CRM_Utils_Request::retrieve('status', 'String');
408
409 if (isset($status)) {
410 if ($status === 'true') {
411 $statusTypes = CRM_Event_PseudoConstant::participantStatus(NULL, "is_counted = 1");
412 }
413 elseif ($status === 'false') {
414 $statusTypes = CRM_Event_PseudoConstant::participantStatus(NULL, "is_counted = 0");
415 }
416 elseif (is_numeric($status)) {
417 $statusTypes = (int) $status;
418 }
419 elseif (is_array($status) && !array_key_exists('IN', $status)) {
420 $statusTypes = array_keys($status);
421 }
422 $this->_formValues['participant_status_id'] = is_array($statusTypes) ? ['IN' => array_keys($statusTypes)] : $statusTypes;
423 }
424
425 $role = CRM_Utils_Request::retrieve('role', 'String');
426
427 if (isset($role)) {
428 if ($role === 'true') {
429 $roleTypes = CRM_Event_PseudoConstant::participantRole(NULL, "filter = 1");
430 }
431 elseif ($role === 'false') {
432 $roleTypes = CRM_Event_PseudoConstant::participantRole(NULL, "filter = 0");
433 }
434 elseif (is_numeric($role)) {
435 $roleTypes = (int) $role;
436 }
437 $this->_formValues['participant_role_id'] = is_array($roleTypes) ? array_keys($roleTypes) : $roleTypes;
438 }
439
440 $type = CRM_Utils_Request::retrieve('type', 'Positive');
441 if ($type) {
442 $this->_formValues['event_type'] = $type;
443 }
444
445 $cid = CRM_Utils_Request::retrieve('cid', 'Positive', $this);
446
447 if ($cid) {
448 $cid = CRM_Utils_Type::escape($cid, 'Integer');
449 if ($cid > 0) {
450 $this->_formValues['contact_id'] = $cid;
451
452 // also assign individual mode to the template
453 $this->_single = TRUE;
454 }
455 }
456 }
457
458 /**
459 * Return a descriptive name for the page, used in wizard header
460 *
461 * @return string
462 */
463 public function getTitle() {
464 return ts('Find Participants');
465 }
466
467 /**
468 * Set the metadata for the form.
469 *
470 * @throws \CiviCRM_API3_Exception
471 */
472 protected function setSearchMetadata() {
473 $this->addSearchFieldMetadata(['Participant' => CRM_Event_BAO_Query::getSearchFieldMetadata()]);
474 }
475
476 }