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