3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2014
37 * This class provides the common functionality for sending email to
38 * one or a group of contact ids. This class is reused by all the search
39 * components in CiviCRM (since they all have send email as a task)
41 class CRM_Contact_Form_Task_LabelCommon
{
43 * Check for presence of tokens to be swapped out
45 * @param array $contact
46 * @param array $mailingFormatProperties
47 * @param array $tokenFields
51 function tokenIsFound($contact, $mailingFormatProperties, $tokenFields) {
52 foreach (array_merge($mailingFormatProperties, array_fill_keys($tokenFields, 1)) as $key => $dontCare) {
53 //we should not consider addressee for data exists, CRM-6025
54 if ($key != 'addressee' && !empty($contact[$key])) {
61 * function to create labels (pdf)
63 * @param array $contactRows assciated array of contact data
64 * @param string $format format in which labels needs to be printed
65 * @param string $fileName The name of the file to save the label in
70 static function createLabel(&$contactRows, &$format, $fileName = 'MailingLabels_CiviCRM.pdf') {
71 $pdf = new CRM_Utils_PDF_Label($format, 'mm');
75 //build contact string that needs to be printed
77 foreach ($contactRows as $row => $value) {
78 foreach ($value as $k => $v) {
82 $pdf->AddPdfLabel($val);
85 $pdf->Output($fileName, 'D');
90 * function to get the rows for the labels
93 * @param integer $locationTypeID
94 * @param boolean $respectDoNotMail
95 * @param $mergeSameAddress
96 * @param $mergeSameHousehold
98 * @internal param array $contactIds Contact IDS to do labels for
99 * @return array of rows for labels
103 static function getRows($contactIDs, $locationTypeID, $respectDoNotMail, $mergeSameAddress, $mergeSameHousehold) {
105 //get the address format sequence from the config file
106 $addressReturnProperties = CRM_Contact_Form_Task_LabelCommon
::getAddressReturnProperties();
108 //build the returnproperties
109 $returnProperties = array('display_name' => 1, 'contact_type' => 1);
110 $mailingFormat = CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::SYSTEM_PREFERENCES_NAME
,
114 $mailingFormatProperties = array();
115 if ($mailingFormat) {
116 $mailingFormatProperties = CRM_Contact_Form_Task_LabelCommon
::regexReturnProperties($mailingFormat);
117 $returnProperties = array_merge($returnProperties, $mailingFormatProperties);
120 $customFormatProperties = array();
121 if (stristr($mailingFormat, 'custom_')) {
122 foreach ($mailingFormatProperties as $token => $true) {
123 if (substr($token, 0, 7) == 'custom_') {
124 if (empty($customFormatProperties[$token])) {
125 $customFormatProperties[$token] = $mailingFormatProperties[$token];
130 $returnProperties = array_merge($returnProperties, $customFormatProperties);
132 if ($mergeSameAddress) {
133 // we need first name/last name for summarising to avoid spillage
134 $returnProperties['first_name'] = 1;
135 $returnProperties['last_name'] = 1;
138 //get the contacts information
139 $params = $custom = array();
140 foreach ($contactIDs as $key => $contactID) {
142 CRM_Core_Form
::CB_PREFIX
. $contactID,
148 if (!empty($respectDoNotMail['do_not_mail'])) {
149 $params[] = array('do_not_mail', '=', 0, 0, 0);
152 $params[] = array('is_deceased', '=', 0, 0, 0);
154 if ($locationTypeID) {
155 $locType = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Address', 'location_type_id');
156 $locName = $locType[$locationTypeID];
157 $location = array('location' => array("{$locName}" => $addressReturnProperties));
158 $returnProperties = array_merge($returnProperties, $location);
159 $params[] = array('location_type', '=', array($locationTypeID => 1), 0, 0);
162 $returnProperties = array_merge($returnProperties, $addressReturnProperties);
165 foreach ($returnProperties as $name) {
166 $cfID = CRM_Core_BAO_CustomField
::getKeyID($name);
172 //get the total number of contacts to fetch from database.
173 $numberofContacts = count($contactIDs);
174 //this does the same as calling civicrm_api3('contact, get, array('id' => array('IN' => $this->_contactIds)
175 // except it also handles multiple locations
176 $query = new CRM_Contact_BAO_Query($params, $returnProperties);
177 $details = $query->apiQuery($params, $returnProperties, NULL, NULL, 0, $numberofContacts);
179 $messageToken = CRM_Utils_Token
::getTokens($mailingFormat);
180 $details = $details[0];
181 $tokenFields = CRM_Contact_Form_Task_LabelCommon
::getTokenData($details);
183 foreach ($contactIDs as $value) {
184 foreach ($custom as $cfID) {
185 if (isset($details[$value]["custom_{$cfID}"])) {
186 $details[$value]["custom_{$cfID}"] = CRM_Core_BAO_CustomField
::getDisplayValue($details[$value]["custom_{$cfID}"], $cfID, $details[1]);
189 $contact = CRM_Utils_Array
::value($value, $details);
191 if (is_a($contact, 'CRM_Core_Error')) {
195 // we need to remove all the "_id"
196 unset($contact['contact_id']);
198 if ($locName && !empty($contact[$locName])) {
199 // If location type is not primary, $contact contains
200 // one more array as "$contact[$locName] = array( values... )"
202 if(!CRM_Contact_Form_Task_LabelCommon
::tokenIsFound($contact, $mailingFormatProperties, $tokenFields)) {
206 unset($contact[$locName]);
208 if (!empty($contact['county_id'])) {
209 unset($contact['county_id']);
212 foreach ($contact as $field => $fieldValue) {
213 $rows[$value][$field] = $fieldValue;
216 $valuesothers = array();
217 $paramsothers = array('contact_id' => $value);
218 $valuesothers = CRM_Core_BAO_Location
::getValues($paramsothers, $valuesothers);
219 if ($locationTypeID) {
220 foreach ($valuesothers as $vals) {
221 if ( CRM_Utils_Array
::value('location_type_id', $vals) ==
223 foreach ($vals as $k => $v) {
224 if (in_array($k, array(
225 'email', 'phone', 'im', 'openid'))) {
227 $rows[$value][$k] = $v['1']['name'];
230 $rows[$value][$k] = $v['1'][$k];
232 $rows[$value][$k . '_id'] = $v['1']['id'];
240 if(!CRM_Contact_Form_Task_LabelCommon
::tokenIsFound($contact, $mailingFormatProperties, $tokenFields)) {
244 if (!empty($contact['addressee_display'])) {
245 $contact['addressee_display'] = trim($contact['addressee_display']);
247 if (!empty($contact['addressee'])) {
248 $contact['addressee'] = $contact['addressee_display'];
251 // now create the rows for generating mailing labels
252 foreach ($contact as $field => $fieldValue) {
253 $rows[$value][$field] = $fieldValue;
257 // sigh couldn't extract out tokenfields yet
258 return array($rows, $tokenFields);
262 * function to extract the return properties from the mailing format
263 * @todo I'm placing bets this is a duplicate of code elsewhere - find & merge
264 * @param unknown_type $format
265 * @return multitype:number
267 function regexReturnProperties(&$format) {
268 $returnProperties = array();
270 preg_match_all('/(?<!\{|\\\\)\{(\w+\.\w+)\}(?!\})/',
276 foreach ($matches[1] as $token) {
277 list($type, $name) = preg_split('/\./', $token, 2);
279 $returnProperties["{$name}"] = 1;
284 return $returnProperties;
288 * Get array of return properties for address fields required for mailing label
289 * @return array return properites for address e.g
291 * - [street_address] => 1,
292 * - [supplemental_address_1] => 1,
293 * - [supplemental_address_2] => 1
296 function getAddressReturnProperties() {
297 $mailingFormat = CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::SYSTEM_PREFERENCES_NAME
,
301 $addressFields = CRM_Utils_Address
::sequence($mailingFormat);
302 $addressReturnProperties = array_fill_keys($addressFields, 1);
304 if (array_key_exists('postal_code', $addressReturnProperties)) {
305 $addressReturnProperties['postal_code_suffix'] = 1;
307 return $addressReturnProperties;
311 * Get token list from mailing format & contacts
312 * @param unknown_type $contacts
315 function getTokenData(&$contacts) {
316 $mailingFormat = CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::SYSTEM_PREFERENCES_NAME
,
319 $tokens = $tokenFields = array();
320 $messageToken = CRM_Utils_Token
::getTokens($mailingFormat);
322 // also get all token values
323 CRM_Utils_Hook
::tokenValues($contacts,
324 array_keys($contacts),
327 'CRM_Contact_Form_Task_LabelCommon'
330 CRM_Utils_Hook
::tokens($tokens);
332 foreach ($tokens as $category => $catTokens) {
333 foreach ($catTokens as $token => $tokenName) {
334 $tokenFields[] = $token;
341 * Merge contacts with the Same address to get one shared label
342 * @param unknown_type $rows
344 function mergeSameAddress(&$rows) {
345 $uniqueAddress = array();
346 foreach (array_keys($rows) as $rowID) {
347 // load complete address as array key
349 trim($rows[$rowID]['street_address']) . trim($rows[$rowID]['city']) . trim($rows[$rowID]['state_province']) . trim($rows[$rowID]['postal_code']) . trim($rows[$rowID]['country']);
350 if (isset($rows[$rowID]['last_name'])) {
351 $name = $rows[$rowID]['last_name'];
354 $name = $rows[$rowID]['display_name'];
356 // fill uniqueAddress array with last/first name tree
357 if (isset($uniqueAddress[$address])) {
358 $uniqueAddress[$address]['names'][$name][] = $rows[$rowID]['first_name'];
359 // drop unnecessary rows
360 unset($rows[$rowID]);
361 // this is the first listing at this address
364 $uniqueAddress[$address]['ID'] = $rowID;
365 $uniqueAddress[$address]['names'][$name][] = $rows[$rowID]['first_name'];
368 foreach ($uniqueAddress as $address => $data) {
369 // copy data back to $rows
371 // one last name list per row
372 foreach ($data['names'] as $last_name => $first_names) {
377 // collapse the tree to summarize
378 $family = trim(implode(" & ", $first_names) . " " . $last_name);
380 $processedNames .= "\n" . $family;
383 // build display_name string
384 $processedNames = $family;
388 $rows[$data['ID']]['addressee'] = $rows[$data['ID']]['addressee_display'] = $rows[$data['ID']]['display_name'] = $processedNames;
397 function mergeSameHousehold(&$rows) {
398 # group selected contacts by type
399 $individuals = array();
400 $households = array();
401 foreach ($rows as $contact_id => $row) {
402 if ($row['contact_type'] == 'Household') {
403 $households[$contact_id] = $row;
405 elseif ($row['contact_type'] == 'Individual') {
406 $individuals[$contact_id] = $row;
410 # exclude individuals belonging to selected households
411 foreach ($households as $household_id => $row) {
412 $dao = new CRM_Contact_DAO_Relationship();
413 $dao->contact_id_b
= $household_id;
415 while ($dao->fetch()) {
416 $individual_id = $dao->contact_id_a
;
417 if (array_key_exists($individual_id, $individuals)) {
418 unset($individuals[$individual_id]);
423 # merge back individuals and households
424 $rows = array_merge($individuals, $households);