Merge pull request #18302 from civicrm/5.29
[civicrm-core.git] / CRM / Campaign / Form / Survey / Results.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 5 | |
bc77d7c0
TO
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 |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035
TO
11
12/**
13 *
14 * @package CRM
ca5cec67 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
6a488035
TO
16 */
17
18/**
3819f101 19 * This class generates form components for processing a survey.
6a488035
TO
20 */
21class CRM_Campaign_Form_Survey_Results extends CRM_Campaign_Form_Survey {
22
23 protected $_reportId;
24
25 protected $_reportTitle;
26
f157740d
SL
27 /**
28 * values
e70a7fc0
TO
29 *
30 * @var array
f157740d 31 *
e70a7fc0 32 */
f157740d 33
6a488035
TO
34 public $_values;
35
7da04cde 36 const NUM_OPTION = 11;
6a488035
TO
37
38 public function preProcess() {
39 parent::preProcess();
40
41 $this->_values = $this->get('values');
42 if (!is_array($this->_values)) {
be2fb01f 43 $this->_values = [];
6a488035 44 if ($this->_surveyId) {
be2fb01f 45 $params = ['id' => $this->_surveyId];
6a488035
TO
46 CRM_Campaign_BAO_Survey::retrieve($params, $this->_values);
47 }
48 $this->set('values', $this->_values);
49 }
50
3636b520 51 $query = "SELECT MAX(id) as id, title FROM civicrm_report_instance WHERE name = %1 GROUP BY id";
be2fb01f 52 $params = [1 => ["survey_{$this->_surveyId}", 'String']];
6a488035 53 $result = CRM_Core_DAO::executeQuery($query, $params);
9d72cede 54 if ($result->fetch()) {
6a488035
TO
55 $this->_reportId = $result->id;
56 $this->_reportTitle = $result->title;
57 }
58 }
59
60 /**
3819f101 61 * Set default values for the form.
62 *
63 * Note that in edit/view mode the default values are retrieved from the database.
6a488035 64 *
a6c01b45
CW
65 * @return array
66 * array of default values
6a488035 67 */
00be9182 68 public function setDefaultValues() {
6a488035
TO
69 $defaults = $this->_values;
70
71 // set defaults for weight.
72 for ($i = 1; $i <= self::NUM_OPTION; $i++) {
73 $defaults["option_weight[{$i}]"] = $i;
74 }
75
76 $defaults['create_report'] = 1;
77 if ($this->_reportId) {
78 $defaults['report_title'] = $this->_reportTitle;
79 }
80 return $defaults;
81 }
82
83 /**
fe482240 84 * Build the form object.
6a488035
TO
85 */
86 public function buildQuickForm() {
87 $optionGroups = CRM_Campaign_BAO_Survey::getResultSets();
88
89 if (empty($optionGroups)) {
be2fb01f 90 $optionTypes = ['1' => ts('Create new result set')];
6a488035
TO
91 }
92 else {
be2fb01f 93 $optionTypes = [
9d72cede 94 '1' => ts('Create new result set'),
6a488035 95 '2' => ts('Use existing result set'),
be2fb01f 96 ];
6a488035
TO
97 $this->add('select',
98 'option_group_id',
99 ts('Select Result Set'),
be2fb01f 100 [
21dfd5f5 101 '' => ts('- select -'),
be2fb01f
CW
102 ] + $optionGroups, FALSE,
103 ['onChange' => 'loadOptionGroup( )']
6a488035
TO
104 );
105 }
106
107 $element = &$this->addRadio('option_type',
108 ts('Survey Responses'),
109 $optionTypes,
be2fb01f 110 [
21dfd5f5 111 'onclick' => "showOptionSelect();",
be2fb01f 112 ], '<br/>', TRUE
6a488035
TO
113 );
114
8cc574cf 115 if (empty($optionGroups) || empty($this->_values['result_id'])) {
be2fb01f 116 $this->setdefaults(['option_type' => 1]);
6a488035 117 }
a7488080 118 elseif (!empty($this->_values['result_id'])) {
be2fb01f 119 $this->setdefaults([
6a488035 120 'option_type' => 2,
9d72cede 121 'option_group_id' => $this->_values['result_id'],
be2fb01f 122 ]);
6a488035
TO
123 }
124
125 // form fields of Custom Option rows
be2fb01f 126 $defaultOption = [];
6a488035
TO
127 $_showHide = new CRM_Core_ShowHideBlocks('', '');
128
129 $optionAttributes = CRM_Core_DAO::getAttribute('CRM_Core_DAO_OptionValue');
130 $optionAttributes['label']['size'] = $optionAttributes['value']['size'] = 25;
131
132 for ($i = 1; $i <= self::NUM_OPTION; $i++) {
133 //the show hide blocks
134 $showBlocks = 'optionField_' . $i;
135 if ($i > 2) {
136 $_showHide->addHide($showBlocks);
137 if ($i == self::NUM_OPTION) {
138 $_showHide->addHide('additionalOption');
139 }
140 }
141 else {
142 $_showHide->addShow($showBlocks);
143 }
144
145 $this->add('text', 'option_label[' . $i . ']', ts('Label'),
146 $optionAttributes['label']
147 );
148
149 // value
150 $this->add('text', 'option_value[' . $i . ']', ts('Value'),
151 $optionAttributes['value']
152 );
153
154 // weight
f20d2b0d 155 $this->add('number', "option_weight[$i]", ts('Order'),
6a488035
TO
156 $optionAttributes['weight']
157 );
158
9d72cede
EM
159 $this->add('text', 'option_interval[' . $i .
160 ']', ts('Recontact Interval'),
6a488035
TO
161 CRM_Core_DAO::getAttribute('CRM_Campaign_DAO_Survey', 'release_frequency')
162 );
163
164 $defaultOption[$i] = $this->createElement('radio', NULL, NULL, NULL, $i);
165 }
166
167 //default option selection
168 $this->addGroup($defaultOption, 'default_option');
169
170 $_showHide->addToTemplate();
171
172 $this->addElement('checkbox', 'create_report', ts('Create Report'));
173 $this->addElement('text', 'report_title', ts('Report Title'));
8ef12e64 174
9d72cede 175 if ($this->_reportId) {
6a488035
TO
176 $this->freeze('create_report');
177 $this->freeze('report_title');
178 }
179
be2fb01f 180 $this->addFormRule([
353ffa53
TO
181 'CRM_Campaign_Form_Survey_Results',
182 'formRule',
be2fb01f 183 ], $this);
6a488035
TO
184
185 parent::buildQuickForm();
186 }
187
188 /**
fe482240 189 * Global validation rules for the form.
c2b5a0af
EM
190 *
191 * @param $fields
192 * @param $files
193 * @param $form
194 *
195 * @return array|bool
6a488035 196 */
00be9182 197 public static function formRule($fields, $files, $form) {
be2fb01f 198 $errors = [];
8cc574cf 199 if (!empty($fields['option_label']) && !empty($fields['option_value']) &&
6a488035
TO
200 (count(array_filter($fields['option_label'])) == 0) &&
201 (count(array_filter($fields['option_value'])) == 0)
202 ) {
203 $errors['option_label[1]'] = ts('Enter at least one result option.');
204 return $errors;
205 }
8cc574cf 206 elseif (empty($fields['option_label']) && empty($fields['option_value'])) {
6a488035
TO
207 return $errors;
208 }
209
968c2c5f 210 if (
9d72cede
EM
211 $fields['option_type'] == 2 && empty($fields['option_group_id'])
212 ) {
6a488035
TO
213 $errors['option_group_id'] = ts("Please select a Survey Result Set.");
214 return $errors;
215 }
216
217 $_flagOption = $_rowError = 0;
218 $_showHide = new CRM_Core_ShowHideBlocks('', '');
219
220 //capture duplicate Custom option values
221 if (!empty($fields['option_value'])) {
222 $countValue = count($fields['option_value']);
223 $uniqueCount = count(array_unique($fields['option_value']));
224
225 if ($countValue > $uniqueCount) {
226 $start = 1;
227 while ($start < self::NUM_OPTION) {
228 $nextIndex = $start + 1;
229
230 while ($nextIndex <= self::NUM_OPTION) {
9d72cede
EM
231 if ($fields['option_value'][$start] ==
232 $fields['option_value'][$nextIndex] &&
6a488035
TO
233 !empty($fields['option_value'][$nextIndex])
234 ) {
235
9d72cede
EM
236 $errors['option_value[' . $start .
237 ']'] = ts('Duplicate Option values');
238 $errors['option_value[' . $nextIndex .
239 ']'] = ts('Duplicate Option values');
6a488035
TO
240 $_flagOption = 1;
241 }
242 $nextIndex++;
243 }
244 $start++;
245 }
246 }
247 }
248
249 //capture duplicate Custom Option label
250 if (!empty($fields['option_label'])) {
251 $countValue = count($fields['option_label']);
252 $uniqueCount = count(array_unique($fields['option_label']));
253
254 if ($countValue > $uniqueCount) {
255 $start = 1;
256 while ($start < self::NUM_OPTION) {
257 $nextIndex = $start + 1;
258
259 while ($nextIndex <= self::NUM_OPTION) {
9d72cede
EM
260 if ($fields['option_label'][$start] ==
261 $fields['option_label'][$nextIndex] &&
262 !empty($fields['option_label'][$nextIndex])
263 ) {
264 $errors['option_label[' . $start .
265 ']'] = ts('Duplicate Option label');
266 $errors['option_label[' . $nextIndex .
267 ']'] = ts('Duplicate Option label');
6a488035
TO
268 $_flagOption = 1;
269 }
270 $nextIndex++;
271 }
272 $start++;
273 }
274 }
275 }
276
277 for ($i = 1; $i <= self::NUM_OPTION; $i++) {
278 if (!$fields['option_label'][$i]) {
279 if ($fields['option_value'][$i]) {
9d72cede
EM
280 $errors['option_label[' . $i .
281 ']'] = ts('Option label cannot be empty');
6a488035
TO
282 $_flagOption = 1;
283 }
284 else {
285 $_emptyRow = 1;
286 }
287 }
288 elseif (!strlen(trim($fields['option_value'][$i]))) {
289 if (!$fields['option_value'][$i]) {
9d72cede
EM
290 $errors['option_value[' . $i .
291 ']'] = ts('Option value cannot be empty');
6a488035
TO
292 $_flagOption = 1;
293 }
294 }
295
9d72cede
EM
296 if (!empty($fields['option_interval'][$i]) &&
297 !CRM_Utils_Rule::integer($fields['option_interval'][$i])
298 ) {
6a488035 299 $_flagOption = 1;
9d72cede
EM
300 $errors['option_interval[' . $i .
301 ']'] = ts('Please enter a valid integer.');
6a488035
TO
302 }
303
304 $showBlocks = 'optionField_' . $i;
305 if ($_flagOption) {
306 $_showHide->addShow($showBlocks);
307 $_rowError = 1;
308 }
309
310 if (!empty($_emptyRow)) {
311 $_showHide->addHide($showBlocks);
312 }
313 else {
314 $_showHide->addShow($showBlocks);
315 }
316
317 if ($i == self::NUM_OPTION) {
318 $hideBlock = 'additionalOption';
319 $_showHide->addHide($hideBlock);
320 }
321
322 $_flagOption = $_emptyRow = 0;
323 }
324 $_showHide->addToTemplate();
325
326 return empty($errors) ? TRUE : $errors;
327 }
328
329 /**
fe482240 330 * Process the form.
6a488035
TO
331 */
332 public function postProcess() {
333 // store the submitted values in an array
334 $status = '';
335 $params = $this->controller->exportValues($this->_name);
336 $params['id'] = $this->_surveyId;
337
338 $updateResultSet = FALSE;
339 $resultSetOptGrpId = NULL;
9d72cede
EM
340 if ((CRM_Utils_Array::value('option_type', $params) == 2) &&
341 !empty($params['option_group_id'])
342 ) {
6a488035
TO
343 $updateResultSet = TRUE;
344 $resultSetOptGrpId = $params['option_group_id'];
345 }
346
be2fb01f 347 $recontactInterval = [];
6a488035
TO
348 if ($updateResultSet) {
349 $optionValue = new CRM_Core_DAO_OptionValue();
350 $optionValue->option_group_id = $resultSetOptGrpId;
351 $optionValue->delete();
352
353 $params['result_id'] = $resultSetOptGrpId;
354 }
355 else {
356 $opGroupName = 'civicrm_survey_' . rand(10, 1000) . '_' . date('YmdHis');
357
358 $optionGroup = new CRM_Core_DAO_OptionGroup();
359 $optionGroup->name = $opGroupName;
360 $optionGroup->title = $this->_values['title'] . ' Result Set';
361 $optionGroup->is_active = 1;
362 $optionGroup->save();
363
364 $params['result_id'] = $optionGroup->id;
365 }
366
367 foreach ($params['option_value'] as $k => $v) {
368 if (strlen(trim($v))) {
369 $optionValue = new CRM_Core_DAO_OptionValue();
370 $optionValue->option_group_id = $params['result_id'];
371 $optionValue->label = $params['option_label'][$k];
372 $optionValue->name = CRM_Utils_String::titleToVar($params['option_label'][$k]);
373 $optionValue->value = trim($v);
374 $optionValue->weight = $params['option_weight'][$k];
375 $optionValue->is_active = 1;
376
a7488080 377 if (!empty($params['default_option']) &&
6a488035
TO
378 $params['default_option'] == $k
379 ) {
380 $optionValue->is_default = 1;
381 }
382
383 $optionValue->save();
384
385 // using is_numeric since 0 is a valid value for option_interval
9d72cede 386 if (is_numeric($params['option_interval'][$k])) {
6a488035
TO
387 $recontactInterval[$optionValue->label] = $params['option_interval'][$k];
388 }
389 }
390 }
391
392 $params['recontact_interval'] = serialize($recontactInterval);
393 $survey = CRM_Campaign_BAO_Survey::create($params);
394
395 // create report if required.
9d72cede 396 if (!$this->_reportId && $survey->id && !empty($params['create_report'])) {
6a488035
TO
397 $activityStatus = CRM_Core_PseudoConstant::activityStatus('name');
398 $activityStatus = array_flip($activityStatus);
be2fb01f 399 $this->_params = [
d5cc0fc2 400 'name' => "survey_{$survey->id}",
401 'title' => $params['report_title'] ? $params['report_title'] : $this->_values['title'],
402 'status_id_op' => 'eq',
5d4fcf54
TO
403 // reserved status
404 'status_id_value' => $activityStatus['Scheduled'],
be2fb01f 405 'survey_id_value' => [$survey->id],
d5cc0fc2 406 'description' => ts('Detailed report for canvassing, phone-banking, walk lists or other surveys.'),
be2fb01f 407 ];
6a488035 408 //Default value of order by
be2fb01f
CW
409 $this->_params['order_bys'] = [
410 1 => [
d5cc0fc2 411 'column' => 'sort_name',
412 'order' => 'ASC',
be2fb01f
CW
413 ],
414 ];
6a488035 415 // for WalkList or default
be2fb01f 416 $displayFields = [
9d72cede
EM
417 'id',
418 'sort_name',
419 'result',
420 'street_number',
421 'street_name',
422 'street_unit',
21dfd5f5 423 'survey_response',
be2fb01f 424 ];
0571e734 425 if (CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'WalkList') ==
9d72cede
EM
426 $this->_values['activity_type_id']
427 ) {
be2fb01f
CW
428 $this->_params['order_bys'] = [
429 1 => [
d5cc0fc2 430 'column' => 'street_name',
431 'order' => 'ASC',
be2fb01f
CW
432 ],
433 2 => [
d5cc0fc2 434 'column' => 'street_number_odd_even',
435 'order' => 'ASC',
be2fb01f
CW
436 ],
437 3 => [
d5cc0fc2 438 'column' => 'street_number',
439 'order' => 'ASC',
be2fb01f
CW
440 ],
441 4 => [
d5cc0fc2 442 'column' => 'sort_name',
443 'order' => 'ASC',
be2fb01f
CW
444 ],
445 ];
6a488035 446 }
0571e734 447 elseif (CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'PhoneBank') ==
9d72cede
EM
448 $this->_values['activity_type_id']
449 ) {
6a488035
TO
450 array_push($displayFields, 'phone');
451 }
0571e734 452 elseif ((CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Survey') ==
9d72cede 453 $this->_values['activity_type_id']) ||
0571e734 454 (CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Canvass') ==
9d72cede
EM
455 $this->_values['activity_type_id'])
456 ) {
457 array_push($displayFields, 'phone', 'city', 'state_province_id', 'postal_code', 'email');
6a488035 458 }
9d72cede 459 foreach ($displayFields as $key) {
6a488035 460 $this->_params['fields'][$key] = 1;
8ef12e64 461 }
6a488035
TO
462 $this->_createNew = TRUE;
463 $this->_id = CRM_Report_Utils_Report::getInstanceIDForValue('survey/detail');
464 CRM_Report_Form_Instance::postProcess($this, FALSE);
8ef12e64 465
6a488035 466 $query = "SELECT MAX(id) FROM civicrm_report_instance WHERE name = %1";
be2fb01f
CW
467 $reportID = CRM_Core_DAO::singleValueQuery($query, [
468 1 => [
353ffa53
TO
469 "survey_{$survey->id}",
470 'String',
be2fb01f
CW
471 ],
472 ]);
6a488035 473 if ($reportID) {
9d72cede 474 $url = CRM_Utils_System::url("civicrm/report/instance/{$reportID}", 'reset=1');
8ef12e64 475 $status = ts("A Survey Detail Report <a href='%1'>%2</a> has been created.",
be2fb01f 476 [1 => $url, 2 => $this->_params['title']]);
6a488035
TO
477 }
478 }
479
480 if ($status) {
481 // reset status as we don't want status set by Instance::postProcess
482 $session = CRM_Core_Session::singleton();
483 $session->getStatus(TRUE);
484 // set new status
485 CRM_Core_Session::setStatus($status, ts('Saved'), 'success');
486 }
487
488 parent::endPostProcess();
489 }
96025800 490
6a488035 491}