CIVICRM-1391 Update Smart Group form unsets the existing Group Types for the Group
[civicrm-core.git] / CRM / Contact / Form / Task / Label.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 5 | |
bc77d7c0
TO
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035
TO
11
12/**
13 *
14 * @package CRM
ca5cec67 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
6a488035
TO
16 */
17
18/**
00252851 19 * This class helps to print the labels for contacts.
6a488035
TO
20 */
21class CRM_Contact_Form_Task_Label extends CRM_Contact_Form_Task {
22
23 /**
fe482240 24 * Build all the data structures needed to build the form.
6a488035 25 */
00be9182 26 public function preProcess() {
6a488035
TO
27 $this->set('contactIds', $this->_contactIds);
28 parent::preProcess();
29 }
30
31 /**
fe482240 32 * Build the form object.
6a488035 33 */
00be9182 34 public function buildQuickForm() {
14396107 35 self::buildLabelForm($this);
36 }
37
38 /**
39 * Common Function to build Mailing Label Form.
bf48aa29 40 *
41 * @param CRM_Core_Form $form
14396107 42 */
43 public static function buildLabelForm($form) {
6a488035
TO
44 CRM_Utils_System::setTitle(ts('Make Mailing Labels'));
45
46 //add select for label
47 $label = CRM_Core_BAO_LabelFormat::getList(TRUE);
48
be2fb01f 49 $form->add('select', 'label_name', ts('Select Label'), ['' => ts('- select label -')] + $label, TRUE);
6a488035 50
6a488035 51 // add select for Location Type
14396107 52 $form->addElement('select', 'location_type_id', ts('Select Location'),
be2fb01f 53 [
af9b09df 54 '' => ts('Primary'),
be2fb01f 55 ] + CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id'), TRUE
6a488035
TO
56 );
57
58 // checkbox for SKIP contacts with Do Not Mail privacy option
14396107 59 $form->addElement('checkbox', 'do_not_mail', ts('Do not print labels for contacts with "Do Not Mail" privacy option checked'));
6a488035 60
14396107 61 $form->add('checkbox', 'merge_same_address', ts('Merge labels for contacts with the same address'), NULL);
62 $form->add('checkbox', 'merge_same_household', ts('Merge labels for contacts belonging to the same household'), NULL);
6a488035 63
be2fb01f
CW
64 $form->addButtons([
65 [
85d25c8f
DG
66 'type' => 'submit',
67 'name' => ts('Make Mailing Labels'),
68 'isDefault' => TRUE,
be2fb01f
CW
69 ],
70 [
85d25c8f
DG
71 'type' => 'cancel',
72 'name' => ts('Done'),
be2fb01f
CW
73 ],
74 ]);
6a488035
TO
75 }
76
77 /**
c490a46a 78 * Set default values for the form.
6a488035 79 *
a6c01b45
CW
80 * @return array
81 * array of default values
6a488035 82 */
00be9182 83 public function setDefaultValues() {
be2fb01f 84 $defaults = [];
6a488035
TO
85 $format = CRM_Core_BAO_LabelFormat::getDefaultValues();
86 $defaults['label_name'] = CRM_Utils_Array::value('name', $format);
87 $defaults['do_not_mail'] = 1;
88
89 return $defaults;
90 }
91
92 /**
fe482240 93 * Process the form after the input has been submitted and validated.
6a488035
TO
94 */
95 public function postProcess() {
353ffa53
TO
96 $fv = $this->controller->exportValues($this->_name);
97 $config = CRM_Core_Config::singleton();
6a488035
TO
98 $locName = NULL;
99 //get the address format sequence from the config file
aaffa79f 100 $mailingFormat = Civi::settings()->get('mailing_format');
6a488035
TO
101
102 $sequence = CRM_Utils_Address::sequence($mailingFormat);
103
104 foreach ($sequence as $v) {
105 $address[$v] = 1;
106 }
107
108 if (array_key_exists('postal_code', $address)) {
109 $address['postal_code_suffix'] = 1;
110 }
111
112 //build the returnproperties
be2fb01f 113 $returnProperties = ['display_name' => 1, 'contact_type' => 1, 'prefix_id' => 1];
aaffa79f 114 $mailingFormat = Civi::settings()->get('mailing_format');
6a488035 115
be2fb01f 116 $mailingFormatProperties = [];
6a488035 117 if ($mailingFormat) {
bdd49e38 118 $mailingFormatProperties = CRM_Utils_Token::getReturnProperties($mailingFormat);
6a488035
TO
119 $returnProperties = array_merge($returnProperties, $mailingFormatProperties);
120 }
121 //we should not consider addressee for data exists, CRM-6025
122 if (array_key_exists('addressee', $mailingFormatProperties)) {
123 unset($mailingFormatProperties['addressee']);
124 }
125
be2fb01f 126 $customFormatProperties = [];
6a488035
TO
127 if (stristr($mailingFormat, 'custom_')) {
128 foreach ($mailingFormatProperties as $token => $true) {
129 if (substr($token, 0, 7) == 'custom_') {
a7488080 130 if (empty($customFormatProperties[$token])) {
6a488035
TO
131 $customFormatProperties[$token] = $mailingFormatProperties[$token];
132 }
133 }
134 }
135 }
136
137 if (!empty($customFormatProperties)) {
138 $returnProperties = array_merge($returnProperties, $customFormatProperties);
139 }
140
141 if (isset($fv['merge_same_address'])) {
142 // we need first name/last name for summarising to avoid spillage
143 $returnProperties['first_name'] = 1;
144 $returnProperties['last_name'] = 1;
145 }
146
57884c26
DJ
147 $individualFormat = FALSE;
148
149 /*
150 * CRM-8338: replace ids of household members with the id of their household
151 * so we can merge labels by household.
152 */
153 if (isset($fv['merge_same_household'])) {
154 $this->mergeContactIdsByHousehold();
155 $individualFormat = TRUE;
156 }
157
6a488035 158 //get the contacts information
be2fb01f 159 $params = [];
a7488080 160 if (!empty($fv['location_type_id'])) {
353ffa53
TO
161 $locType = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
162 $locName = $locType[$fv['location_type_id']];
be2fb01f 163 $location = ['location' => ["{$locName}" => $address]];
6a488035 164 $returnProperties = array_merge($returnProperties, $location);
be2fb01f 165 $params[] = ['location_type', '=', [1 => $fv['location_type_id']], 0, 0];
6a488035
TO
166 }
167 else {
168 $returnProperties = array_merge($returnProperties, $address);
169 }
170
be2fb01f 171 $rows = [];
6a488035
TO
172
173 foreach ($this->_contactIds as $key => $contactID) {
be2fb01f 174 $params[] = [
6a488035 175 CRM_Core_Form::CB_PREFIX . $contactID,
353ffa53
TO
176 '=',
177 1,
178 0,
179 0,
be2fb01f 180 ];
6a488035
TO
181 }
182
183 // fix for CRM-2651
a7488080 184 if (!empty($fv['do_not_mail'])) {
be2fb01f 185 $params[] = ['do_not_mail', '=', 0, 0, 0];
6a488035
TO
186 }
187 // fix for CRM-2613
be2fb01f 188 $params[] = ['is_deceased', '=', 0, 0, 0];
6a488035 189
be2fb01f 190 $custom = [];
6a488035
TO
191 foreach ($returnProperties as $name => $dontCare) {
192 $cfID = CRM_Core_BAO_CustomField::getKeyID($name);
193 if ($cfID) {
194 $custom[] = $cfID;
195 }
196 }
197
198 //get the total number of contacts to fetch from database.
199 $numberofContacts = count($this->_contactIds);
353ffa53
TO
200 $query = new CRM_Contact_BAO_Query($params, $returnProperties);
201 $details = $query->apiQuery($params, $returnProperties, NULL, NULL, 0, $numberofContacts);
6a488035
TO
202
203 $messageToken = CRM_Utils_Token::getTokens($mailingFormat);
204
205 // also get all token values
206 CRM_Utils_Hook::tokenValues($details[0],
207 $this->_contactIds,
208 NULL,
209 $messageToken,
210 'CRM_Contact_Form_Task_Label'
211 );
212
be2fb01f 213 $tokens = [];
6a488035 214 CRM_Utils_Hook::tokens($tokens);
be2fb01f 215 $tokenFields = [];
6a488035
TO
216 foreach ($tokens as $category => $catTokens) {
217 foreach ($catTokens as $token => $tokenName) {
218 $tokenFields[] = $token;
219 }
220 }
221
222 foreach ($this->_contactIds as $value) {
223 foreach ($custom as $cfID) {
224 if (isset($details[0][$value]["custom_{$cfID}"])) {
8cee0c70 225 $details[0][$value]["custom_{$cfID}"] = CRM_Core_BAO_CustomField::displayValue($details[0][$value]["custom_{$cfID}"], $cfID);
6a488035
TO
226 }
227 }
228 $contact = CRM_Utils_Array::value($value, $details['0']);
229
230 if (is_a($contact, 'CRM_Core_Error')) {
231 return NULL;
232 }
233
234 // we need to remove all the "_id"
235 unset($contact['contact_id']);
236
8cc574cf 237 if ($locName && !empty($contact[$locName])) {
6a488035
TO
238 // If location type is not primary, $contact contains
239 // one more array as "$contact[$locName] = array( values... )"
240
8bdfc216 241 if (!self::tokenIsFound($contact, $mailingFormatProperties, $tokenFields)) {
6a488035
TO
242 continue;
243 }
244
ceebbde9 245 $contact = array_merge($contact, $contact[$locName]);
6a488035
TO
246 unset($contact[$locName]);
247
a7488080 248 if (!empty($contact['county_id'])) {
6a488035
TO
249 unset($contact['county_id']);
250 }
251
252 foreach ($contact as $field => $fieldValue) {
253 $rows[$value][$field] = $fieldValue;
254 }
255
be2fb01f
CW
256 $valuesothers = [];
257 $paramsothers = ['contact_id' => $value];
6a488035 258 $valuesothers = CRM_Core_BAO_Location::getValues($paramsothers, $valuesothers);
a7488080 259 if (!empty($fv['location_type_id'])) {
6a488035 260 foreach ($valuesothers as $vals) {
353ffa53
TO
261 if (CRM_Utils_Array::value('location_type_id', $vals) ==
262 CRM_Utils_Array::value('location_type_id', $fv)
263 ) {
6a488035 264 foreach ($vals as $k => $v) {
be2fb01f 265 if (in_array($k, [
353ffa53
TO
266 'email',
267 'phone',
268 'im',
af9b09df 269 'openid',
be2fb01f 270 ])) {
6a488035
TO
271 if ($k == 'im') {
272 $rows[$value][$k] = $v['1']['name'];
273 }
274 else {
275 $rows[$value][$k] = $v['1'][$k];
276 }
277 $rows[$value][$k . '_id'] = $v['1']['id'];
278 }
279 }
280 }
281 }
282 }
283 }
284 else {
8bdfc216 285 if (!self::tokenIsFound($contact, $mailingFormatProperties, $tokenFields)) {
6a488035
TO
286 continue;
287 }
288
a7488080 289 if (!empty($contact['addressee_display'])) {
6a488035
TO
290 $contact['addressee_display'] = trim($contact['addressee_display']);
291 }
a7488080 292 if (!empty($contact['addressee'])) {
6a488035
TO
293 $contact['addressee'] = $contact['addressee_display'];
294 }
295
296 // now create the rows for generating mailing labels
297 foreach ($contact as $field => $fieldValue) {
298 $rows[$value][$field] = $fieldValue;
299 }
300 }
301 }
302
6a488035 303 if (isset($fv['merge_same_address'])) {
8bdfc216 304 CRM_Core_BAO_Address::mergeSameAddress($rows);
6a488035
TO
305 $individualFormat = TRUE;
306 }
6a488035
TO
307
308 // format the addresses according to CIVICRM_ADDRESS_FORMAT (CRM-1327)
309 foreach ($rows as $id => $row) {
310 if ($commMethods = CRM_Utils_Array::value('preferred_communication_method', $row)) {
353ffa53 311 $val = array_filter(explode(CRM_Core_DAO::VALUE_SEPARATOR, $commMethods));
e7e657f0 312 $comm = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'preferred_communication_method');
be2fb01f 313 $temp = [];
6a488035
TO
314 foreach ($val as $vals) {
315 $temp[] = $comm[$vals];
316 }
317 $row['preferred_communication_method'] = implode(', ', $temp);
318 }
319 $row['id'] = $id;
4c49535e 320 $formatted = CRM_Utils_Address::format($row, 'mailing_format', FALSE, TRUE, $tokenFields);
6a488035
TO
321
322 // CRM-2211: UFPDF doesn't have bidi support; use the PECL fribidi package to fix it.
323 // On Ubuntu (possibly Debian?) be aware of http://pecl.php.net/bugs/bug.php?id=12366
324 // Due to FriBidi peculiarities, this can't be called on
325 // a multi-line string, hence the explode+implode approach.
326 if (function_exists('fribidi_log2vis')) {
327 $lines = explode("\n", $formatted);
328 foreach ($lines as $i => $line) {
329 $lines[$i] = fribidi_log2vis($line, FRIBIDI_AUTO, FRIBIDI_CHARSET_UTF8);
330 }
331 $formatted = implode("\n", $lines);
332 }
be2fb01f 333 $rows[$id] = [$formatted];
6a488035
TO
334 }
335
336 //call function to create labels
337 self::createLabel($rows, $fv['label_name']);
292c8687 338 CRM_Utils_System::civiExit();
6a488035
TO
339 }
340
c91c5542 341 /**
fe482240 342 * Check for presence of tokens to be swapped out.
77b97be7 343 *
c91c5542 344 * @param array $contact
345 * @param array $mailingFormatProperties
346 * @param array $tokenFields
77b97be7
EM
347 *
348 * @return bool
c91c5542 349 */
8bdfc216 350 public static function tokenIsFound($contact, $mailingFormatProperties, $tokenFields) {
c91c5542 351 foreach (array_merge($mailingFormatProperties, array_fill_keys($tokenFields, 1)) as $key => $dontCare) {
8bdfc216 352 //we should not consider addressee for data exists, CRM-6025
353ffa53 353 if ($key != 'addressee' && !empty($contact[$key])) {
c91c5542 354 return TRUE;
355 }
356 }
357 return FALSE;
358 }
353ffa53 359
6a488035 360 /**
00252851 361 * Create labels (pdf).
6a488035 362 *
77c5b619 363 * @param array $contactRows
00252851 364 * Associated array of contact data.
77c5b619
TO
365 * @param string $format
366 * Format in which labels needs to be printed.
367 * @param string $fileName
368 * The name of the file to save the label in.
6a488035 369 */
00be9182 370 public function createLabel(&$contactRows, &$format, $fileName = 'MailingLabels_CiviCRM.pdf') {
6a488035
TO
371 $pdf = new CRM_Utils_PDF_Label($format, 'mm');
372 $pdf->Open();
373 $pdf->AddPage();
374
375 //build contact string that needs to be printed
376 $val = NULL;
377 foreach ($contactRows as $row => $value) {
378 foreach ($value as $k => $v) {
379 $val .= "$v\n";
380 }
381
382 $pdf->AddPdfLabel($val);
383 $val = '';
384 }
385 $pdf->Output($fileName, 'D');
386 }
387
6a488035 388}