Merge pull request #16086 from civicrm/5.21
[civicrm-core.git] / CRM / Campaign / Form / 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 * Files required.
20 */
21 class CRM_Campaign_Form_Search extends CRM_Core_Form_Search {
22
23 /**
24 * The params that are sent to the query.
25 *
26 * @var array
27 */
28 protected $_queryParams;
29
30 /**
31 * Are we restricting ourselves to a single contact.
32 *
33 * @var bool
34 */
35 protected $_single = FALSE;
36
37 /**
38 * Are we restricting ourselves to a single contact.
39 *
40 * @var bool
41 */
42 protected $_limit = NULL;
43
44 /**
45 * Prefix for the controller.
46 * @var string
47 */
48 protected $_prefix = "survey_";
49
50
51 private $_operation = 'reserve';
52
53 /**
54 * Processing needed for buildForm and later.
55 */
56 public function preProcess() {
57 $this->_done = FALSE;
58 $this->_defaults = array();
59
60 //set the button name.
61 $this->_searchButtonName = $this->getButtonName('refresh');
62 $this->_printButtonName = $this->getButtonName('next', 'print');
63 $this->_actionButtonName = $this->getButtonName('next', 'action');
64
65 $this->loadStandardSearchOptionsFromUrl();
66
67 //operation for state machine.
68 $this->_operation = CRM_Utils_Request::retrieve('op', 'String', $this, FALSE, 'reserve');
69 //validate operation.
70 if (!in_array($this->_operation, array(
71 'reserve',
72 'release',
73 'interview',
74 ))
75 ) {
76 $this->_operation = 'reserve';
77 $this->set('op', $this->_operation);
78 }
79 $this->set('searchVoterFor', $this->_operation);
80 $this->assign('searchVoterFor', $this->_operation);
81 $this->assign('isFormSubmitted', $this->isSubmitted());
82
83 //do check permissions.
84 if (!CRM_Core_Permission::check('administer CiviCampaign') &&
85 !CRM_Core_Permission::check('manage campaign') &&
86 !CRM_Core_Permission::check("{$this->_operation} campaign contacts")
87 ) {
88 CRM_Utils_System::permissionDenied();
89 CRM_Utils_System::civiExit();
90 }
91
92 $this->assign("context", $this->_context);
93
94 // get user submitted values
95 // get it from controller only if form has been submitted, else preProcess has set this
96
97 if (empty($_POST)) {
98 $this->_formValues = $this->get('formValues');
99 }
100 else {
101 $this->_formValues = $this->controller->exportValues($this->_name);
102 }
103
104 if ($this->_force) {
105 $this->postProcess();
106 $this->set('force', 0);
107 }
108
109 //get the voter clause.
110 $voterClause = $this->voterClause();
111
112 $this->_queryParams = CRM_Contact_BAO_Query::convertFormValues($this->_formValues);
113
114 $selector = new CRM_Campaign_Selector_Search($this->_queryParams,
115 $this->_action,
116 $voterClause,
117 $this->_single,
118 $this->_limit,
119 $this->_context
120 );
121 $prefix = NULL;
122 if ($this->_context == 'user') {
123 $prefix = $this->_prefix;
124 }
125
126 $this->assign("{$prefix}limit", $this->_limit);
127 $this->assign("{$prefix}single", $this->_single);
128
129 $controller = new CRM_Core_Selector_Controller($selector,
130 $this->get(CRM_Utils_Pager::PAGE_ID),
131 $this->getSortID(),
132 CRM_Core_Action::VIEW,
133 $this,
134 CRM_Core_Selector_Controller::TRANSFER,
135 $prefix
136 );
137
138 $controller->setEmbedded(TRUE);
139 $controller->moveFromSessionToTemplate();
140
141 //append breadcrumb to survey dashboard.
142 if (CRM_Campaign_BAO_Campaign::accessCampaign()) {
143 $url = CRM_Utils_System::url('civicrm/campaign', 'reset=1&subPage=survey');
144 CRM_Utils_System::appendBreadCrumb(array(array('title' => ts('Survey(s)'), 'url' => $url)));
145 }
146
147 //set the form title.
148 CRM_Utils_System::setTitle(ts('Find Respondents To %1', array(1 => ucfirst($this->_operation))));
149 }
150
151 /**
152 * Load the default survey for all actions.
153 *
154 * @return array
155 */
156 public function setDefaultValues() {
157 if (empty($this->_defaults)) {
158 $defaultSurveyId = key(CRM_Campaign_BAO_Survey::getSurveys(TRUE, TRUE));
159 if ($defaultSurveyId) {
160 $this->_defaults['campaign_survey_id'] = $defaultSurveyId;
161 }
162 }
163
164 return $this->_defaults;
165 }
166
167 /**
168 * Build the form object.
169 */
170 public function buildQuickForm() {
171 parent::buildQuickForm();
172 //build the search form.
173 CRM_Campaign_BAO_Query::buildSearchForm($this);
174
175 $rows = $this->get('rows');
176 if (is_array($rows)) {
177 if (!$this->_single) {
178 $this->addRowSelectors($rows);
179 }
180
181 $allTasks = CRM_Campaign_Task::permissionedTaskTitles(CRM_Core_Permission::getPermission());
182
183 //hack to serve right page to state machine.
184 $taskMapping = array(
185 'interview' => CRM_Campaign_Task::INTERVIEW,
186 'reserve' => CRM_Campaign_Task::RESERVE,
187 'release' => CRM_Campaign_Task::RELEASE,
188 );
189
190 $currentTaskValue = CRM_Utils_Array::value($this->_operation, $taskMapping);
191 $taskValue = array($currentTaskValue => $allTasks[$currentTaskValue]);
192 if ($this->_operation == 'interview' && !empty($this->_formValues['campaign_survey_id'])) {
193 $activityTypes = CRM_Core_PseudoConstant::activityType(FALSE, TRUE, FALSE, 'label', TRUE);
194
195 $surveyTypeId = CRM_Core_DAO::getFieldValue('CRM_Campaign_DAO_Survey',
196 $this->_formValues['campaign_survey_id'],
197 'activity_type_id'
198 );
199 $taskValue = array(
200 $currentTaskValue => ts('Record %1 Responses',
201 array(1 => $activityTypes[$surveyTypeId])
202 ),
203 );
204 }
205
206 $this->addTaskMenu($taskValue);
207 }
208
209 }
210
211 /**
212 * The post processing of the form gets done here.
213 *
214 * Key things done during post processing are
215 * - check for reset or next request. if present, skip post procesing.
216 * - now check if user requested running a saved search, if so, then
217 * the form values associated with the saved search are used for searching.
218 * - if user has done a submit with new values the regular post submissing is
219 * done.
220 * The processing consists of using a Selector / Controller framework for getting the
221 * search results.
222 */
223 public function postProcess() {
224 if ($this->_done) {
225 return;
226 }
227
228 $this->_done = TRUE;
229
230 if (!empty($_POST)) {
231 $this->_formValues = $this->controller->exportValues($this->_name);
232 }
233
234 $this->fixFormValues();
235
236 //format params as per task.
237 $this->formatParams();
238
239 $this->_queryParams = CRM_Contact_BAO_Query::convertFormValues($this->_formValues);
240
241 $this->set('formValues', $this->_formValues);
242 $this->set('queryParams', $this->_queryParams);
243
244 $buttonName = $this->controller->getButtonName();
245 if ($buttonName == $this->_actionButtonName) {
246 // check actionName and if next, then do not repeat a search, since we are going to the next page
247
248 // hack, make sure we reset the task values
249 $stateMachine = $this->controller->getStateMachine();
250 $formName = $stateMachine->getTaskFormName();
251
252 $this->controller->resetPage($formName);
253 return;
254 }
255
256 //get the voter clause.
257 $voterClause = $this->voterClause();
258
259 $selector = new CRM_Campaign_Selector_Search($this->_queryParams,
260 $this->_action,
261 $voterClause,
262 $this->_single,
263 $this->_limit,
264 $this->_context
265 );
266 $selector->setKey($this->controller->_key);
267
268 $prefix = NULL;
269 if ($this->_context == 'basic' ||
270 $this->_context == 'user'
271 ) {
272 $prefix = $this->_prefix;
273 }
274
275 $controller = new CRM_Core_Selector_Controller($selector,
276 $this->get(CRM_Utils_Pager::PAGE_ID),
277 $this->getSortID(),
278 CRM_Core_Action::VIEW,
279 $this,
280 CRM_Core_Selector_Controller::SESSION,
281 $prefix
282 );
283 $controller->setEmbedded(TRUE);
284 $query = $selector->getQuery();
285 if ($this->_context == 'user') {
286 $query->setSkipPermission(TRUE);
287 }
288 $controller->run();
289 }
290
291 public function formatParams() {
292 $interviewerId = CRM_Utils_Array::value('survey_interviewer_id', $this->_formValues);
293 if ($interviewerId) {
294 $this->set('interviewerId', $interviewerId);
295 }
296
297 //format multi-select group and contact types.
298 foreach (array('group', 'contact_type') as $param) {
299 if ($this->_force) {
300 continue;
301 }
302 $paramValue = CRM_Utils_Array::value($param, $this->_formValues);
303 if ($paramValue && is_array($paramValue)) {
304 unset($this->_formValues[$param]);
305 foreach ($paramValue as $key => $value) {
306 $this->_formValues[$param][$value] = 1;
307 }
308 }
309 }
310
311 //apply filter of survey contact type for search.
312 $contactType = CRM_Campaign_BAO_Survey::getSurveyContactType(CRM_Utils_Array::value('campaign_survey_id', $this->_formValues));
313 if ($contactType && in_array($this->_operation, ['reserve', 'interview'])) {
314 $this->_formValues['contact_type'][$contactType] = 1;
315 }
316
317 if ($this->_operation == 'reserve') {
318 if (!empty($this->_formValues['campaign_survey_id'])) {
319 $campaignId = CRM_Core_DAO::getFieldValue('CRM_Campaign_DAO_Survey',
320 $this->_formValues['campaign_survey_id'],
321 'campaign_id'
322 );
323
324 //allow voter search in sub-part of given constituents,
325 //but make sure in case user does not select any group.
326 //get all associated campaign groups in where filter, CRM-7406
327 $groups = CRM_Utils_Array::value('group', $this->_formValues);
328 if ($campaignId && CRM_Utils_System::isNull($groups)) {
329 $campGroups = CRM_Campaign_BAO_Campaign::getCampaignGroups($campaignId);
330 foreach ($campGroups as $id => $title) {
331 $this->_formValues['group'][$id] = 1;
332 }
333 }
334
335 //carry servey id w/ this.
336 $this->set('surveyId', $this->_formValues['campaign_survey_id']);
337 unset($this->_formValues['campaign_survey_id']);
338 }
339 unset($this->_formValues['survey_interviewer_id']);
340 }
341 elseif ($this->_operation == 'interview' ||
342 $this->_operation == 'release'
343 ) {
344 //to conduct interview / release activity status should be scheduled.
345 $activityStatus = CRM_Core_PseudoConstant::activityStatus('name');
346 if ($scheduledStatusId = array_search('Scheduled', $activityStatus)) {
347 $this->_formValues['survey_status_id'] = $scheduledStatusId;
348 }
349 }
350
351 //pass voter search operation.
352 $this->_formValues['campaign_search_voter_for'] = $this->_operation;
353 }
354
355 public function fixFormValues() {
356 // if this search has been forced
357 // then see if there are any get values, and if so over-ride the post values
358 // note that this means that GET over-rides POST :)
359
360 //since we have qfKey, no need to manipulate set defaults.
361 $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String');
362
363 if (!$this->_force || CRM_Utils_Rule::qfKey($qfKey)) {
364 return;
365 }
366
367 // get survey id
368 $surveyId = CRM_Utils_Request::retrieve('sid', 'Positive');
369
370 if ($surveyId) {
371 $surveyId = CRM_Utils_Type::escape($surveyId, 'Integer');
372 }
373 else {
374 // use default survey id
375 $surveyId = key(CRM_Campaign_BAO_Survey::getSurveys(TRUE, TRUE));
376 }
377 if (!$surveyId) {
378 CRM_Core_Error::statusBounce(ts('Could not find valid Survey Id.'));
379 }
380 $this->_formValues['campaign_survey_id'] = $this->_formValues['campaign_survey_id'] = $surveyId;
381
382 $session = CRM_Core_Session::singleton();
383 $userId = $session->get('userID');
384
385 // get interviewer id
386 $cid = CRM_Utils_Request::retrieve('cid', 'Positive',
387 CRM_Core_DAO::$_nullObject, FALSE, $userId
388 );
389 //to force other contact as interviewer, user should be admin.
390 if ($cid != $userId &&
391 !CRM_Core_Permission::check('administer CiviCampaign')
392 ) {
393 CRM_Utils_System::permissionDenied();
394 CRM_Utils_System::civiExit();
395 }
396 $this->_formValues['survey_interviewer_id'] = $cid;
397 //get all in defaults.
398 $this->_defaults = $this->_formValues;
399 $this->_limit = CRM_Utils_Request::retrieve('limit', 'Positive', $this);
400 }
401
402 /**
403 * @return array
404 */
405 public function voterClause() {
406 $params = array('campaign_search_voter_for' => $this->_operation);
407
408 $clauseFields = array(
409 'surveyId' => 'campaign_survey_id',
410 'interviewerId' => 'survey_interviewer_id',
411 );
412
413 foreach ($clauseFields as $param => $key) {
414 $params[$key] = CRM_Utils_Array::value($key, $this->_formValues);
415 if (!$params[$key]) {
416 $params[$key] = $this->get($param);
417 }
418 }
419
420 //build the clause.
421 $voterClause = CRM_Campaign_BAO_Query::voterClause($params);
422
423 return $voterClause;
424 }
425
426 /**
427 * Return a descriptive name for the page, used in wizard header
428 *
429 * @return string
430 */
431 public function getTitle() {
432 return ts('Find Respondents');
433 }
434
435 }