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