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