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