Merge pull request #4622 from civicrm/4.5
[civicrm-core.git] / CRM / Contact / Form / Task / Batch.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 for batch profile update
38 */
39class CRM_Contact_Form_Task_Batch extends CRM_Contact_Form_Task {
40
41 /**
42 * the title of the group
43 *
44 * @var string
45 */
46 protected $_title;
47
48 /**
49 * maximum contacts that should be allowed to update
50 *
51 */
52 protected $_maxContacts = 100;
53
54 /**
55 * maximum profile fields that will be displayed
56 *
57 */
58 protected $_maxFields = 9;
59
60 /**
61 * variable to store redirect path
62 *
63 */
64 protected $_userContext;
65
66 /**
67 * when not to reset sort_name
68 */
69 protected $_preserveDefault = TRUE;
8ef12e64 70
6a488035
TO
71 /**
72 * build all the data structures needed to build the form
73 *
74 * @return void
75 * @access public
76 */
77 function preProcess() {
78 /*
79 * initialize the task and row fields
80 */
81 parent::preProcess();
82 }
83
84 /**
85 * Build the form
86 *
87 * @access public
88 *
89 * @return void
90 */
91 function buildQuickForm() {
92 $ufGroupId = $this->get('ufGroupId');
93
94 if (!$ufGroupId) {
95 CRM_Core_Error::fatal('ufGroupId is missing');
96 }
97 $this->_title = ts('Batch Update') . ' - ' . CRM_Core_BAO_UFGroup::getTitle($ufGroupId);
98 CRM_Utils_System::setTitle($this->_title);
99
100 $this->addDefaultButtons(ts('Save'));
101 $this->_fields = CRM_Core_BAO_UFGroup::getFields($ufGroupId, FALSE, CRM_Core_Action::VIEW);
102
103 // remove file type field and then limit fields
104 $suppressFields = FALSE;
105 $removehtmlTypes = array('File', 'Autocomplete-Select');
106 foreach ($this->_fields as $name => $field) {
107 if ($cfID = CRM_Core_BAO_CustomField::getKeyID($name) &&
108 in_array($this->_fields[$name]['html_type'], $removehtmlTypes)
109 ) {
110 $suppressFields = TRUE;
111 unset($this->_fields[$name]);
112 }
113 }
114
115 //FIX ME: phone ext field is added at the end and it gets removed because of below code
116 //$this->_fields = array_slice($this->_fields, 0, $this->_maxFields);
117
118 $this->addButtons(array(
119 array(
120 'type' => 'submit',
121 'name' => ts('Update Contact(s)'),
122 'isDefault' => TRUE,
123 ),
124 array(
125 'type' => 'cancel',
126 'name' => ts('Cancel'),
127 ),
128 )
129 );
130
131
132 $this->assign('profileTitle', $this->_title);
133 $this->assign('componentIds', $this->_contactIds);
134
135 // if below fields are missing we should not reset sort name / display name
136 // CRM-6794
137 $preserveDefaultsArray = array(
138 'first_name', 'last_name', 'middle_name',
d8189be2 139 'organization_name', 'prefix_id', 'suffix_id',
6a488035
TO
140 'household_name',
141 );
8ef12e64 142
6a488035
TO
143 foreach ($this->_contactIds as $contactId) {
144 $profileFields = $this->_fields;
145 CRM_Core_BAO_Address::checkContactSharedAddressFields($profileFields, $contactId);
146 foreach ($profileFields as $name => $field) {
147 CRM_Core_BAO_UFGroup::buildProfile($this, $field, NULL, $contactId);
148
149 if (in_array($field['name'], $preserveDefaultsArray)) {
150 $this->_preserveDefault = FALSE;
151 }
152 }
153 }
8ef12e64 154
6a488035
TO
155 $this->assign('fields', $this->_fields);
156
157 // don't set the status message when form is submitted.
158 $buttonName = $this->controller->getButtonName('submit');
159
160 if ($suppressFields && $buttonName != '_qf_BatchUpdateProfile_next') {
0feb9734 161 CRM_Core_Session::setStatus(ts("File or Autocomplete-Select type field(s) in the selected profile are not supported for Batch Update."), ts('Some Fields Excluded'), 'info');
6a488035
TO
162 }
163
164 $this->addDefaultButtons(ts('Update Contacts'));
165 $this->addFormRule(array('CRM_Contact_Form_Task_Batch', 'formRule'));
166 }
167
168 /**
169 * This function sets the default values for the form.
170 *
171 * @access public
172 *
c927c151 173 * @return array
6a488035
TO
174 */
175 function setDefaultValues() {
176 if (empty($this->_fields)) {
177 return;
178 }
179
180 $defaults = $sortName = array();
181 foreach ($this->_contactIds as $contactId) {
182 $details[$contactId] = array();
183
184 //build sortname
185 $sortName[$contactId] = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
186 $contactId,
187 'sort_name'
188 );
189
190 CRM_Core_BAO_UFGroup::setProfileDefaults($contactId, $this->_fields, $defaults, FALSE);
191 }
192
193 $this->assign('sortName', $sortName);
8ef12e64 194
6a488035
TO
195 return $defaults;
196 }
197
198 /**
199 * global form rule
200 *
201 * @param array $fields the input form values
202 *
203 * @return true if no errors, else array of errors
204 * @access public
205 * @static
206 */
207 static function formRule($fields) {
208 $errors = array();
209 $externalIdentifiers = array();
210 foreach ($fields['field'] as $componentId => $field) {
211 foreach ($field as $fieldName => $fieldValue) {
212 if ($fieldName == 'external_identifier') {
213 if (in_array($fieldValue, $externalIdentifiers)) {
7b99ead3 214 $errors["field[$componentId][external_identifier]"] = ts('Duplicate value for External ID.');
6a488035
TO
215 }
216 else {
217 $externalIdentifiers[$componentId] = $fieldValue;
218 }
219 }
220 }
221 }
222
223 return $errors;
224 }
225
226 /**
227 * process the form after the input has been submitted and validated
228 *
229 * @access public
230 *
355ba699 231 * @return void
6a488035
TO
232 */
233 public function postProcess() {
234 $params = $this->exportValues();
235
236 $ufGroupId = $this->get('ufGroupId');
237 $notify = NULL;
238 $inValidSubtypeCnt = 0;
239 //send profile notification email if 'notify' field is set
240 $notify = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $ufGroupId, 'notify');
241 foreach ($params['field'] as $key => $value) {
242
243 //CRM-5521
244 //validate subtype before updating
a7488080 245 if (!empty($value['contact_sub_type']) && !CRM_Contact_BAO_ContactType::isAllowEdit($key)) {
6a488035
TO
246 unset($value['contact_sub_type']);
247 $inValidSubtypeCnt++;
248 }
249
250 $value['preserveDBName'] = $this->_preserveDefault;
251
252 //parse street address, CRM-7768
253 self::parseStreetAddress($value, $this);
254
255 CRM_Contact_BAO_Contact::createProfileContact($value, $this->_fields, $key, NULL, $ufGroupId);
256 if ($notify) {
257 $values = CRM_Core_BAO_UFGroup::checkFieldsEmptyValues($ufGroupId, $key, NULL);
258 CRM_Core_BAO_UFGroup::commonSendMail($key, $values);
259 }
260 }
261
262 CRM_Core_Session::setStatus('', ts("Updates Saved"), 'success');
263 if ($inValidSubtypeCnt) {
b8f96eb8 264 CRM_Core_Session::setStatus(ts('Contact Subtype field of 1 contact has not been updated.', array('plural' => 'Contact Subtype field of %count contacts has not been updated.', 'count' => $inValidSubtypeCnt)), ts('Invalid Subtype'));
6a488035
TO
265 }
266 }
267 //end of function
268
afe349ef 269 /**
270 * parse street address
cdeb4bdf 271 * @param array $contactValues contact values
272 * @param object $form form object
afe349ef 273 */
05d1454b
C
274 public static function parseStreetAddress(&$contactValues, &$form) {
275 if (!is_array($contactValues) || !is_array($form->_fields)) {
6a488035
TO
276 return;
277 }
278
279 static $parseAddress;
280 $addressFldKey = 'street_address';
281 if (!isset($parseAddress)) {
282 $parseAddress = FALSE;
283 foreach ($form->_fields as $key => $fld) {
284 if (strpos($key, $addressFldKey) !== FALSE) {
285 $parseAddress = CRM_Utils_Array::value('street_address_parsing',
286 CRM_Core_BAO_Setting::valueOptions(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
287 'address_options'
288 ),
289 FALSE
290 );
291 break;
292 }
293 }
294 }
295
296 if (!$parseAddress) {
297 return;
298 }
299
300 $allParseValues = array();
301 foreach ($contactValues as $key => $value) {
302 if (strpos($key, $addressFldKey) !== FALSE) {
303 $locTypeId = substr($key, strlen($addressFldKey) + 1);
304
305 // parse address field.
306 $parsedFields = CRM_Core_BAO_Address::parseStreetAddress($value);
307
308 //street address consider to be parsed properly,
309 //If we get street_name and street_number.
8cc574cf 310 if (empty($parsedFields['street_name']) || empty($parsedFields['street_number'])) {
6a488035
TO
311 $parsedFields = array_fill_keys(array_keys($parsedFields), '');
312 }
313
314 //merge parse values.
315 foreach ($parsedFields as $fldKey => $parseVal) {
316 if ($locTypeId) {
317 $fldKey .= "-{$locTypeId}";
318 }
319 $allParseValues[$fldKey] = $parseVal;
320 }
321 }
322 }
323
324 //finally merge all parse values
325 if (!empty($allParseValues)) {
326 $contactValues += $allParseValues;
327 }
328 }
329}
330