Merge branch '4.4' of https://github.com/civicrm/civicrm-core into 4.5
[civicrm-core.git] / CRM / Campaign / Form / Task / Reserve.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
06b69b18 4 | CiviCRM version 4.5 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
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
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35
36/**
37 * This class provides the functionality to add contacts for
38 * voter reservation.
39 */
40class CRM_Campaign_Form_Task_Reserve extends CRM_Campaign_Form_Task {
41
42 /**
43 * survet id`
44 *
45 * @var int
46 */
47 protected $_surveyId;
48
49 /**
50 * interviewer id
51 *
52 * @var int
53 */
54 protected $_interviewerId;
55
56 /**
57 * survey details
58 *
59 * @var object
60 */
61 protected $_surveyDetails;
62
63 /**
64 * number of voters
65 *
66 * @var int
67 */
68 protected $_numVoters;
69
70 /**
71 * build all the data structures needed to build the form
72 *
73 * @return void
74 * @access public
75 */
76 function preProcess() {
77 parent::preProcess();
78
79 //get the survey id from user submitted values.
80 $this->_surveyId = $this->get('surveyId');
81 $this->_interviewerId = $this->get('interviewerId');
82 if (!$this->_surveyId) {
83 CRM_Core_Error::statusBounce(ts("Could not find Survey Id."));
84 }
85 if (!$this->_interviewerId) {
86 CRM_Core_Error::statusBounce(ts("Missing Interviewer contact."));
87 }
88 if (!is_array($this->_contactIds) || empty($this->_contactIds)) {
89 CRM_Core_Error::statusBounce(ts("Could not find contacts for reservation."));
90 }
91
92 $params = array('id' => $this->_surveyId);
93 CRM_Campaign_BAO_Survey::retrieve($params, $this->_surveyDetails);
94
95 //get the survey activities.
96 $activityStatus = CRM_Core_PseudoConstant::activityStatus('name');
97 $statusIds = array();
98 foreach (array(
99 'Scheduled') as $name) {
100 if ($statusId = array_search($name, $activityStatus)) {
101 $statusIds[] = $statusId;
102 }
103 }
104
105 // these are the activities count that are linked to the current
106 // interviewer and current survey and not the list of ALL survey activities
107 $this->_numVoters = CRM_Campaign_BAO_Survey::getSurveyActivities($this->_surveyId,
108 $this->_interviewerId,
109 $statusIds,
110 NULL,
111 TRUE
112 );
113 //validate the selected survey.
114 $this->validateSurvey();
115 $this->assign('surveyTitle', $this->_surveyDetails['title']);
116 $this->assign('activityType', $this->_surveyDetails['activity_type_id']);
117 $this->assign('surveyId', $this->_surveyId);
118
119 //append breadcrumb to survey dashboard.
120 if (CRM_Campaign_BAO_Campaign::accessCampaign()) {
121 $url = CRM_Utils_System::url('civicrm/campaign', 'reset=1&subPage=survey');
122 CRM_Utils_System::appendBreadCrumb(array(array('title' => ts('Survey(s)'), 'url' => $url)));
123 }
124
125 //set the title.
126 CRM_Utils_System::setTitle(ts('Reserve Respondents'));
127 }
128
129 function validateSurvey() {
130 $errorMsg = NULL;
131 $maxVoters = CRM_Utils_Array::value('max_number_of_contacts', $this->_surveyDetails);
132 if ($maxVoters) {
133 if ($maxVoters <= $this->_numVoters) {
134 $errorMsg = ts('The maximum number of contacts is already reserved for this interviewer.');
135 }
136 elseif (count($this->_contactIds) > ($maxVoters - $this->_numVoters)) {
137 $errorMsg = ts('You can reserve a maximum of %1 contact(s) at a time for this survey.',
138 array(1 => $maxVoters - $this->_numVoters)
139 );
140 }
141 }
142
143 $defaultNum = CRM_Utils_Array::value('default_number_of_contacts', $this->_surveyDetails);
144 if (!$errorMsg && $defaultNum && (count($this->_contactIds) > $defaultNum)) {
145 $errorMsg = ts('You can reserve a maximum of %1 contact(s) at a time for this survey.',
146 array(1 => $defaultNum)
147 );
148 }
149
150 if ($errorMsg) {
151 CRM_Core_Error::statusBounce($errorMsg);
152 }
153 }
154
155 /**
156 * Build the form
157 *
158 * @access public
159 *
160 * @return void
161 */
162 function buildQuickForm() {
163 // allow to add contact to either new or existing group.
164 $this->addElement('text', 'ActivityType', ts('Activity Type'));
165 $this->addElement('text', 'newGroupName', ts('Name for new group'));
166 $this->addElement('text', 'newGroupDesc', ts('Description of new group'));
24431f7b 167 $groups = CRM_Core_PseudoConstant::nestedGroup();
6a488035
TO
168 $hasExistingGroups = FALSE;
169 if (is_array($groups) && !empty($groups)) {
170 $hasExistingGroups = TRUE;
171 $this->addElement('select', 'groups', ts('Add respondent(s) to existing group(s)'),
24431f7b 172 $groups, array('multiple' => "multiple", 'class' => 'crm-select2')
6a488035
TO
173 );
174 }
175 $this->assign('hasExistingGroups', $hasExistingGroups);
176
177 $buttons = array(
178 array('type' => 'done',
179 'name' => ts('Reserve'),
180 'subName' => 'reserve',
181 'isDefault' => TRUE,
182 ));
183
184 if (CRM_Core_Permission::check('manage campaign') ||
185 CRM_Core_Permission::check('administer CiviCampaign') ||
186 CRM_Core_Permission::check('interview campaign contacts')
187 ) {
188 $buttons[] = array(
189 'type' => 'next',
190 'name' => ts('Reserve and Interview'),
191 'subName' => 'reserveToInterview',
192 );
193 }
194 $buttons[] = array(
195 'type' => 'back',
196 'name' => ts('Cancel'),
197 );
198
199 $this->addButtons($buttons);
200 $this->addFormRule(array('CRM_Campaign_Form_Task_Reserve', 'formRule'), $this);
201 }
202
203 /**
204 * global validation rules for the form
205 *
206 * @param array $fields posted values of the form
207 *
da6b46f4
EM
208 * @param $files
209 * @param $self
210 *
6a488035
TO
211 * @return array list of errors to be posted back to the form
212 * @static
213 * @access public
214 */
215 static function formRule($fields, $files, $self) {
216 $errors = array();
217 $invalidGroupName = FALSE;
a7488080 218 if (!empty($fields['newGroupName'])) {
6a488035
TO
219 $title = trim($fields['newGroupName']);
220 $name = CRM_Utils_String::titleToVar($title);
221 $query = 'select count(*) from civicrm_group where name like %1 OR title like %2';
222 $grpCnt = CRM_Core_DAO::singleValueQuery($query, array(1 => array($name, 'String'),
223 2 => array($title, 'String'),
224 ));
225 if ($grpCnt) {
226 $invalidGroupName = TRUE;
227 $errors['newGroupName'] = ts('Group \'%1\' already exists.', array(1 => $fields['newGroupName']));
228 }
229 }
230 $self->assign('invalidGroupName', $invalidGroupName);
231
232 return empty($errors) ? TRUE : $errors;
233 }
234
235 /**
236 * process the form after the input has been submitted and validated
237 *
238 * @access public
239 *
355ba699 240 * @return void
6a488035
TO
241 */
242 public function postProcess() {
243 //add reservation.
244 $countVoters = 0;
245 $maxVoters = CRM_Utils_Array::value('max_number_of_contacts', $this->_surveyDetails);
246 $activityStatus = CRM_Core_PseudoConstant::activityStatus('name');
247 $statusHeld = array_search('Scheduled', $activityStatus);
248
249 $reservedVoterIds = array();
250 foreach ($this->_contactIds as $cid) {
251 $subject = ts('%1', array(1 => $this->_surveyDetails['title'])) . ' - ' . ts('Respondent Reservation');
252 $session = CRM_Core_Session::singleton();
253 $activityParams = array('source_contact_id' => $session->get('userID'),
254 'assignee_contact_id' => array($this->_interviewerId),
255 'target_contact_id' => array($cid),
256 'source_record_id' => $this->_surveyId,
257 'activity_type_id' => $this->_surveyDetails['activity_type_id'],
258 'subject' => $subject,
259 'activity_date_time' => date('YmdHis'),
260 'status_id' => $statusHeld,
261 'skipRecentView' => 1,
262 'campaign_id' => CRM_Utils_Array::value('campaign_id', $this->_surveyDetails),
263 );
264 $activity = CRM_Activity_BAO_Activity::create($activityParams);
265 if ($activity->id) {
266 $countVoters++;
267 $reservedVoterIds[$cid] = $cid;
268 }
269 if ($maxVoters && ($maxVoters <= ($this->_numVoters + $countVoters))) {
270 break;
271 }
272 }
273
274 //add reserved voters to groups.
275 $groupAdditions = $this->_addRespondentToGroup($reservedVoterIds);
276
277 // Success message
278 if ($countVoters > 0) {
279 $status = '<p>' . ts("%1 Contact(s) have been reserved.", array(1 => $countVoters)) . '</p>';
280 if ($groupAdditions) {
281 $status .= '<p>' . ts('Respondent(s) has been added to %1 group(s).',
282 array(1 => implode(', ', $groupAdditions))
283 ) . '</p>';
284 }
285 CRM_Core_Session::setStatus($status, ts('Reservation Added'), 'success');
286 }
287 // Error message
288 if (count($this->_contactIds) > $countVoters) {
289 CRM_Core_Session::setStatus(ts('Reservation did not add for %1 contact(s).',
290 array(1 => (count($this->_contactIds) - $countVoters))
291 ), ts('Notice'));
292 }
293
294 //get ready to jump to voter interview form.
295 $buttonName = $this->controller->getButtonName();
296 if (!empty($reservedVoterIds) &&
297 $buttonName == '_qf_Reserve_next_reserveToInterview'
298 ) {
299 $this->controller->set('surveyId', $this->_surveyId);
300 $this->controller->set('contactIds', $reservedVoterIds);
301 $this->controller->set('interviewerId', $this->_interviewerId);
302 $this->controller->set('reserveToInterview', TRUE);
303 }
304 }
305
30c4e065
EM
306 /**
307 * @param $contactIds
308 *
309 * @return array
310 */
6a488035
TO
311 private function _addRespondentToGroup($contactIds) {
312 $groupAdditions = array();
313 if (empty($contactIds)) {
314 return $groupAdditions;
315 }
316
317 $params = $this->controller->exportValues($this->_name);
318 $groups = CRM_Utils_Array::value('groups', $params, array());
319 $newGroupName = CRM_Utils_Array::value('newGroupName', $params);
320 $newGroupDesc = CRM_Utils_Array::value('newGroupDesc', $params);
321
322 $newGroupId = NULL;
323 //create new group.
324 if ($newGroupName) {
325 $grpParams = array(
326 'title' => $newGroupName,
327 'description' => $newGroupDesc,
328 'is_active' => TRUE,
329 );
330 $group = CRM_Contact_BAO_Group::create($grpParams);
331 $groups[] = $newGroupId = $group->id;
332 }
333
334 //add the respondents to groups.
335 if (is_array($groups)) {
336 $existingGroups = CRM_Core_PseudoConstant::group();
337 foreach ($groups as $groupId) {
338 $addCount = CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIds, $groupId);
339 $totalCount = CRM_Utils_Array::value(1, $addCount);
340 if ($groupId == $newGroupId) {
341 $name = $newGroupName;
342 $new = TRUE;
343 }
344 else {
345 $name = $existingGroups[$groupId];
346 $new = FALSE;
347 }
348 if ($totalCount) {
349 $url = CRM_Utils_System::url('civicrm/group/search',
350 'reset=1&force=1&context=smog&gid=' . $groupId
351 );
352 $groupAdditions[] = '<a href="' . $url . '">' . $name . '</a>';
353 }
354 }
355 }
356
357 return $groupAdditions;
358 }
359}
360