Merge pull request #1625 from pradpnayak/CRM-13340
[civicrm-core.git] / CRM / Badge / BAO / Badge.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.4 |
5 +--------------------------------------------------------------------+
6 | This file is a part of CiviCRM. |
7 | |
8 | CiviCRM is free software; you can copy, modify, and distribute it |
9 | under the terms of the GNU Affero General Public License |
10 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
11 | |
12 | CiviCRM is distributed in the hope that it will be useful, but |
13 | WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
15 | See the GNU Affero General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU Affero General Public |
18 | License and the CiviCRM Licensing Exception along |
19 | with this program; if not, contact CiviCRM LLC |
20 | at info[AT]civicrm[DOT]org. If you have questions about the |
21 | GNU Affero General Public License or the licensing of CiviCRM, |
22 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
23 +--------------------------------------------------------------------+
24 */
25
26 /**
27 *
28 * @package CRM
29 * @copyright CiviCRM LLC (c) 2004-2013
30 * $Id$
31 *
32 */
33
34 /**
35 * Class CRM_Badge_Format_Badge
36 *
37 * parent class for building name badges
38 */
39 class CRM_Badge_BAO_Badge {
40
41 public $debug = FALSE;
42
43 public $border = 0;
44
45 /**
46 * This function is called to create name label pdf
47 *
48 * @param array $participants associated array with participant info
49 * @param array $layoutInfo associated array which contains meta data about format/layout
50 *
51 * @return void
52 * @access public
53 */
54 public function createLabels(&$participants, &$layoutInfo) {
55 $this->pdf = new CRM_Utils_PDF_Label($layoutInfo['format'], 'mm');
56 $this->pdf->Open();
57 $this->pdf->setPrintHeader(FALSE);
58 $this->pdf->setPrintFooter(FALSE);
59 $this->pdf->AddPage();
60 $this->pdf->SetGenerator($this, "generateLabel");
61
62 // this is very useful for debugging, by default set to FALSE
63 if ($this->debug) {
64 $this->border = "LTRB";
65 }
66
67 foreach ($participants as $participant) {
68 $formattedRow = self::formatLabel($participant, $layoutInfo);
69 $this->pdf->AddPdfLabel($formattedRow);
70 }
71
72 $this->pdf->Output(CRM_Utils_String::munge($layoutInfo['title'], '_', 64) . '.pdf', 'D');
73 CRM_Utils_System::civiExit(1);
74 }
75
76 /**
77 * Funtion to create structure and add meta data according to layout
78 *
79 * @param array $row row element that needs to be formatted
80 * @param array $layout layout meta data
81 *
82 * @return array $formattedRow row with meta data
83 */
84 static function formatLabel(&$row, &$layout) {
85 $formattedRow = array('labelFormat' => $layout['label_format_name']);
86
87 if (CRM_Utils_Array::value('rowElements', $layout['data'])) {
88 foreach ($layout['data']['rowElements'] as $key => $element) {
89 $value = '';
90 if ($element) {
91 $value = $row[$element];
92 // hack to fix date field display format
93 if (strpos($element, '_date')) {
94 $value = CRM_Utils_Date::customFormat($value, "%B %E%f");
95 }
96 }
97
98 $formattedRow['token'][$key] = array(
99 'value' => $value,
100 'font_name' => $layout['data']['font_name'][$key],
101 'font_size' => $layout['data']['font_size'][$key],
102 'font_style' => $layout['data']['font_style'][$key],
103 'text_alignment' => $layout['data']['text_alignment'][$key],
104 'token' => $layout['data']['token'][$key],
105 );
106 }
107 }
108
109 if (CRM_Utils_Array::value('image_1', $layout['data'])) {
110 $formattedRow['image_1'] = $layout['data']['image_1'];
111 }
112 if (CRM_Utils_Array::value('width_image_1', $layout['data'])) {
113 $formattedRow['width_image_1'] = $layout['data']['width_image_1'];
114 }
115 if (CRM_Utils_Array::value('height_image_1', $layout['data'])) {
116 $formattedRow['height_image_1'] = $layout['data']['height_image_1'];
117 }
118
119 if (CRM_Utils_Array::value('image_2', $layout['data'])) {
120 $formattedRow['image_2'] = $layout['data']['image_2'];
121 }
122 if (CRM_Utils_Array::value('width_image_2', $layout['data'])) {
123 $formattedRow['width_image_2'] = $layout['data']['width_image_2'];
124 }
125 if (CRM_Utils_Array::value('height_image_2', $layout['data'])) {
126 $formattedRow['height_image_2'] = $layout['data']['height_image_2'];
127 }
128
129 if (CRM_Utils_Array::value('add_barcode', $layout['data'])) {
130 $formattedRow['barcode'] = array(
131 'alignment' => $layout['data']['barcode_alignment'],
132 'type' => $layout['data']['barcode_type'],
133 );
134 }
135
136 // finally assign all the row values, so that we can use it for barcode etc
137 $formattedRow['values'] = $row;
138
139 return $formattedRow;
140 }
141
142 public function generateLabel($formattedRow) {
143 switch ($formattedRow['labelFormat']) {
144 case 'Avery 5395':
145 default:
146 self::labelAvery5395($formattedRow);
147 break;
148 }
149 }
150
151 public function labelAvery5395(&$formattedRow) {
152 $this->lMarginLogo = 18;
153 $this->tMarginName = 20;
154
155 $x = $this->pdf->GetAbsX();
156 $y = $this->pdf->GetY();
157
158 $titleWidth = $titleLeftMargin = 0;
159 if (CRM_Utils_Array::value('image_1', $formattedRow)) {
160 $this->printImage($formattedRow['image_1'], NULL, NULL, CRM_Utils_Array::value('width_image_1', $formattedRow),
161 CRM_Utils_Array::value('height_image_1', $formattedRow));
162 $titleWidth = $titleLeftMargin = $this->lMarginLogo;
163 }
164
165 $titleRightMargin = 0;
166 if (CRM_Utils_Array::value('image_2', $formattedRow)) {
167 $this->printImage($formattedRow['image_2'], $x + 68, NULL, CRM_Utils_Array::value('width_image_2', $formattedRow),
168 CRM_Utils_Array::value('height_image_2', $formattedRow));
169 $titleRightMargin = 36;
170 $titleWidth = $this->lMarginLogo;
171 }
172
173 $this->pdf->SetLineStyle(array(
174 'width' => 0.1,
175 'cap' => 'round',
176 'join' => 'round',
177 'dash' => '2,2',
178 'color' => array(0, 0, 200)
179 ));
180
181 if ($titleLeftMargin && $titleRightMargin) {
182 $titleWidth = $titleRightMargin;
183 }
184
185 // first row is a special row because we have images on the side
186 $value = '';
187 if ($formattedRow['token'][1]['token'] != 'spacer') {
188 $value = $formattedRow['token'][1]['value'];
189 }
190
191 $this->pdf->SetFont($formattedRow['token'][1]['font_name'], $formattedRow['token'][1]['font_style'],
192 $formattedRow['token'][1]['font_size']);
193 $this->pdf->MultiCell($this->pdf->width - $titleWidth, 0, $value,
194 $this->border, $formattedRow['token'][1]['text_alignment'], 0, 1, $x + $titleLeftMargin, $y);
195
196 $rowCount = CRM_Badge_Form_Layout::FIELD_ROWCOUNT;
197 for ($i = 2; $i <= $rowCount; $i++) {
198 if (!empty($formattedRow['token'][$i]['token'])) {
199 $value = '';
200 if ($formattedRow['token'][$i]['token'] != 'spacer') {
201 $value = $formattedRow['token'][$i]['value'];
202 }
203
204 $this->pdf->SetFont($formattedRow['token'][$i]['font_name'], $formattedRow['token'][$i]['font_style'],
205 $formattedRow['token'][$i]['font_size']);
206 $this->pdf->MultiCell($this->pdf->width, 0, $value,
207 $this->border, $formattedRow['token'][$i]['text_alignment'], 0, 1, $x, $this->pdf->getY());
208 }
209 }
210
211 if (CRM_Utils_Array::value('barcode', $formattedRow)) {
212 $data = $formattedRow['values'];
213
214 if ($formattedRow['barcode']['type'] == 'barcode') {
215 $data['current_value'] =
216 $formattedRow['values']['contact_id'] . '-' . $formattedRow['values']['participant_id'];
217 }
218 else {
219 // view participant url
220 $data['current_value'] = CRM_Utils_System::url('civicrm/contact/view/participant',
221 'action=view&reset=1&cid=' . $formattedRow['values']['contact_id'] . '&id='
222 . $formattedRow['values']['participant_id'],
223 TRUE,
224 NULL,
225 FALSE
226 );
227 }
228
229 // call hook alterBarcode
230 CRM_Utils_Hook::alterBarcode($data, $formattedRow['barcode']['type']);
231
232 if ($formattedRow['barcode']['type'] == 'barcode') {
233 // barcode position
234 $xAlign = $x;
235
236 switch ($formattedRow['barcode']['alignment']) {
237 case 'L':
238 $xAlign += -14;
239 break;
240 case 'R':
241 $xAlign += 32;
242 break;
243 case 'C':
244 $xAlign += 9;
245 break;
246 }
247
248 $style = array(
249 'position' => '',
250 'align' => '',
251 'stretch' => FALSE,
252 'fitwidth' => TRUE,
253 'cellfitalign' => '',
254 'border' => FALSE,
255 'hpadding' => 13.5,
256 'vpadding' => 'auto',
257 'fgcolor' => array(0, 0, 0),
258 'bgcolor' => FALSE,
259 'text' => FALSE,
260 'font' => 'helvetica',
261 'fontsize' => 8,
262 'stretchtext' => 0,
263 );
264
265 $this->pdf->write1DBarcode($data['current_value'], 'C128', $xAlign, $y + $this->pdf->height - 10, '70',
266 12, 0.4, $style, 'B');
267 }
268 else {
269 // qr code position
270 $xAlign = $x;
271
272 switch ($formattedRow['barcode']['alignment']) {
273 case 'L':
274 $xAlign += -5;
275 break;
276 case 'R':
277 $xAlign += 61;
278 break;
279 case 'C':
280 $xAlign += 29;
281 break;
282 }
283
284 $style = array(
285 'border' => false,
286 'hpadding' => 13.5,
287 'vpadding' => 'auto',
288 'fgcolor' => array(0,0,0),
289 'bgcolor' => false,
290 'position' => '',
291 );
292
293 $this->pdf->write2DBarcode($data['current_value'], 'QRCODE,H', $xAlign, $y + $this->pdf->height - 26, 30,
294 30, $style, 'B');
295 }
296 }
297 }
298
299 /**
300 * Helper function to print images
301 * @param string $img image url
302 *
303 * @return void
304 * @access public
305 */
306 function printImage($img, $x = '', $y = '', $w = NULL, $h = NULL) {
307 if (!$x) {
308 $x = $this->pdf->GetAbsX();
309 }
310
311 if (!$y) {
312 $y = $this->pdf->GetY();
313 }
314
315 $this->imgRes = 300;
316
317 if ($img) {
318 list($w, $h) = self::getImageProperties($img, $this->imgRes, $w, $h);
319 $this->pdf->Image($img, $x, $y, $w, $h, '', '', '', FALSE, 72, '', FALSE,
320 FALSE, $this->debug, FALSE, FALSE, FALSE);
321 }
322 $this->pdf->SetXY($x, $y);
323 }
324
325 static function getImageProperties($img, $imgRes = 300, $w = NULL, $h = NULL) {
326 $imgsize = getimagesize($img);
327 $f = $imgRes / 25.4;
328 $w = !empty($w) ? $w : $imgsize[0] / $f;
329 $h = !empty($h) ? $h : $imgsize[1] / $f;
330 return array($w, $h);
331 }
332
333 /**
334 * function to build badges parameters before actually creating badges.
335 *
336 * @param array $params associated array of submitted values
337 * @params object $form form/controller object
338 *
339 * @return void
340 * @access public
341 * @static
342 */
343 public static function buildBadges(&$params, &$form) {
344 // get name badge layout info
345 $layoutInfo = CRM_Badge_BAO_Layout::buildLayout($params);
346
347 // spit / get actual field names from token
348 $returnProperties = array();
349 if (!empty($layoutInfo['data']['token'])) {
350 foreach ($layoutInfo['data']['token'] as $index => $value) {
351 $element = '';
352 if ($value) {
353 $token = CRM_Utils_Token::getTokens($value);
354 if (key($token) == 'contact') {
355 $element = $token['contact'][0];
356 }
357 elseif (key($token) == 'event') {
358 $element = $token['event'][0];
359 //FIX ME - we need to standardize event token names
360 if (!strpos($element, 'event_')) {
361 $element = 'event_' . $element;
362 }
363 }
364 elseif (key($token) == 'participant') {
365 $element = $token['participant'][0];
366 }
367
368 // build returnproperties for query
369 $returnProperties[$element] = 1;
370 }
371
372 // add actual field name to row element
373 $layoutInfo['data']['rowElements'][$index] = $element;
374 }
375 }
376
377 // add additional required fields for query execution
378 $additionalFields = array('participant_register_date', 'participant_id', 'event_id', 'contact_id');
379 foreach ($additionalFields as $field) {
380 $returnProperties[$field] = 1;
381 }
382
383 if ($form->_single) {
384 $queryParams = NULL;
385 }
386 else {
387 $queryParams = $form->get('queryParams');
388 }
389
390 $query = new CRM_Contact_BAO_Query($queryParams, $returnProperties, NULL, FALSE, FALSE,
391 CRM_Contact_BAO_Query::MODE_EVENT
392 );
393
394 list($select, $from, $where, $having) = $query->query();
395 if (empty($where)) {
396 $where = "WHERE {$form->_componentClause}";
397 }
398 else {
399 $where .= " AND {$form->_componentClause}";
400 }
401
402 $sortOrder = NULL;
403 if ($form->get(CRM_Utils_Sort::SORT_ORDER)) {
404 $sortOrder = $form->get(CRM_Utils_Sort::SORT_ORDER);
405 if (!empty($sortOrder)) {
406 $sortOrder = " ORDER BY $sortOrder";
407 }
408 }
409 $queryString = "$select $from $where $having $sortOrder";
410
411 $dao = CRM_Core_DAO::executeQuery($queryString);
412 $rows = array();
413 while ($dao->fetch()) {
414 $rows[$dao->participant_id] = array();
415 foreach ($returnProperties as $key => $dontCare) {
416 $rows[$dao->participant_id][$key] = isset($dao->$key) ? $dao->$key : NULL;
417 }
418 }
419
420 $eventBadgeClass = new CRM_Badge_BAO_Badge();
421 $eventBadgeClass->createLabels($rows, $layoutInfo);
422 }
423 }
424