CRM-13863 - Update pdf letter to use select2
[civicrm-core.git] / CRM / Contact / Form / Task / PDFLetterCommon.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.4 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
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-2013
32 * $Id$
33 *
34 */
35
36 /**
37 * This class provides the common functionality for creating PDF letter for
38 * one or a group of contact ids.
39 */
40 class CRM_Contact_Form_Task_PDFLetterCommon {
41
42 /**
43 * build all the data structures needed to build the form
44 *
45 * @return void
46 * @access public
47 */
48 static function preProcess(&$form) {
49 $messageText = array();
50 $messageSubject = array();
51 $dao = new CRM_Core_BAO_MessageTemplate();
52 $dao->is_active = 1;
53 $dao->find();
54 while ($dao->fetch()) {
55 $messageText[$dao->id] = $dao->msg_text;
56 $messageSubject[$dao->id] = $dao->msg_subject;
57 }
58
59 $form->assign('message', $messageText);
60 $form->assign('messageSubject', $messageSubject);
61 }
62
63 static function preProcessSingle(&$form, $cid) {
64 $form->_contactIds = array($cid);
65 // put contact display name in title for single contact mode
66 CRM_Contact_Page_View::setTitle($cid);
67 }
68
69 /**
70 * Build the form
71 *
72 * @var CRM_Core_Form $form
73 *
74 * @return void
75 */
76 static function buildQuickForm(&$form) {
77 // This form outputs a file so should never be submitted via ajax
78 $form->preventAjaxSubmit();
79
80 //Added for CRM-12682: Add activity subject and campaign fields
81 CRM_Campaign_BAO_Campaign::addCampaign($form);
82 $form->add(
83 'text',
84 'subject',
85 ts('Activity Subject'),
86 array('size' => 45, 'maxlength' => 255),
87 FALSE
88 );
89
90 $form->add('static', 'pdf_format_header', NULL, ts('Page Format: %1', array(1 => '<span class="pdf-format-header-label"></span>')));
91 $form->addSelect('format_id', array(
92 'label' => ts('Select Format'),
93 'placeholder' => ts('Default'),
94 'entity' => 'message_template',
95 'field' => 'pdf_format_id',
96 'option_url' => 'civicrm/admin/pdfFormats',
97 ));
98 $form->add(
99 'select',
100 'paper_size',
101 ts('Paper Size'),
102 array(0 => ts('- default -')) + CRM_Core_BAO_PaperSize::getList(TRUE),
103 FALSE,
104 array('onChange' => "selectPaper( this.value ); showUpdateFormatChkBox();")
105 );
106 $form->add('static', 'paper_dimensions', NULL, ts('Width x Height'));
107 $form->add(
108 'select',
109 'orientation',
110 ts('Orientation'),
111 CRM_Core_BAO_PdfFormat::getPageOrientations(),
112 FALSE,
113 array('onChange' => "updatePaperDimensions(); showUpdateFormatChkBox();")
114 );
115 $form->add(
116 'select',
117 'metric',
118 ts('Unit of Measure'),
119 CRM_Core_BAO_PdfFormat::getUnits(),
120 FALSE,
121 array('onChange' => "selectMetric( this.value );")
122 );
123 $form->add(
124 'text',
125 'margin_left',
126 ts('Left Margin'),
127 array('size' => 8, 'maxlength' => 8, 'onkeyup' => "showUpdateFormatChkBox();"),
128 TRUE
129 );
130 $form->add(
131 'text',
132 'margin_right',
133 ts('Right Margin'),
134 array('size' => 8, 'maxlength' => 8, 'onkeyup' => "showUpdateFormatChkBox();"),
135 TRUE
136 );
137 $form->add(
138 'text',
139 'margin_top',
140 ts('Top Margin'),
141 array('size' => 8, 'maxlength' => 8, 'onkeyup' => "showUpdateFormatChkBox();"),
142 TRUE
143 );
144 $form->add(
145 'text',
146 'margin_bottom',
147 ts('Bottom Margin'),
148 array('size' => 8, 'maxlength' => 8, 'onkeyup' => "showUpdateFormatChkBox();"),
149 TRUE
150 );
151 $form->add('checkbox', 'bind_format', ts('Always use this Page Format with the selected Template'));
152 $form->add('checkbox', 'update_format', ts('Update Page Format (this will affect all templates that use this format)'));
153
154 $form->assign('useThisPageFormat', ts('Always use this Page Format with the new template?'));
155 $form->assign('useSelectedPageFormat', ts('Should the new template always use the selected Page Format?'));
156 $form->assign('totalSelectedContacts', count($form->_contactIds));
157
158 CRM_Mailing_BAO_Mailing::commonLetterCompose($form);
159
160 if ($form->_single) {
161 $cancelURL = CRM_Utils_System::url(
162 'civicrm/contact/view',
163 "reset=1&cid={$form->_cid}&selectedChild=activity",
164 FALSE,
165 NULL,
166 FALSE
167 );
168 if ($form->get('action') == CRM_Core_Action::VIEW) {
169 $form->addButtons(array(
170 array(
171 'type' => 'cancel',
172 'name' => ts('Done'),
173 'js' => array('onclick' => "location.href='{$cancelURL}'; return false;"),
174 ),
175 )
176 );
177 }
178 else {
179 $form->addButtons(array(
180 array(
181 'type' => 'submit',
182 'name' => ts('Make PDF Letter'),
183 'isDefault' => TRUE,
184 ),
185 array(
186 'type' => 'cancel',
187 'name' => ts('Done'),
188 'js' => array('onclick' => "location.href='{$cancelURL}'; return false;"),
189 ),
190 )
191 );
192 }
193 }
194 else {
195 $form->addButtons(array(
196 array(
197 'type' => 'submit',
198 'name' => ts('Make PDF Letters'),
199 'isDefault' => TRUE,
200 ),
201 array(
202 'type' => 'cancel',
203 'name' => ts('Done'),
204 ),
205 ));
206 }
207
208 $form->addFormRule(array('CRM_Contact_Form_Task_PDFLetterCommon', 'formRule'), $form);
209 }
210
211 /**
212 * Set default values
213 */
214 static function setDefaultValues() {
215 $defaultFormat = CRM_Core_BAO_PdfFormat::getDefaultValues();
216 $defaultFormat['format_id'] = $defaultFormat['id'];
217 return $defaultFormat;
218 }
219
220 /**
221 * form rule
222 *
223 * @param array $fields the input form values
224 * @param array $dontCare
225 * @param array $self additional values form 'this'
226 *
227 * @return true if no errors, else array of errors
228 * @access public
229 *
230 */
231 static function formRule($fields, $dontCare, $self) {
232 $errors = array();
233 $template = CRM_Core_Smarty::singleton();
234
235 //Added for CRM-1393
236 if (!empty($fields['saveTemplate']) && empty($fields['saveTemplateName'])) {
237 $errors['saveTemplateName'] = ts("Enter name to save message template");
238 }
239 if (!is_numeric($fields['margin_left'])) {
240 $errors['margin_left'] = 'Margin must be numeric';
241 }
242 if (!is_numeric($fields['margin_right'])) {
243 $errors['margin_right'] = 'Margin must be numeric';
244 }
245 if (!is_numeric($fields['margin_top'])) {
246 $errors['margin_top'] = 'Margin must be numeric';
247 }
248 if (!is_numeric($fields['margin_bottom'])) {
249 $errors['margin_bottom'] = 'Margin must be numeric';
250 }
251 return empty($errors) ? TRUE : $errors;
252 }
253
254 /**
255 * part of the post process which prepare and extract information from the template
256 *
257 * @access protected
258 *
259 * @return array( $categories, $html_message, $messageToken, $returnProperties )
260 */
261 static protected function processMessageTemplate(&$form) {
262 $formValues = $form->controller->exportValues($form->getName());
263
264 // process message template
265 if (!empty($formValues['saveTemplate']) || !empty($formValues['updateTemplate'])) {
266 $messageTemplate = array(
267 'msg_text' => NULL,
268 'msg_html' => $formValues['html_message'],
269 'msg_subject' => NULL,
270 'is_active' => TRUE,
271 );
272
273 $messageTemplate['pdf_format_id'] = 'null';
274 if (!empty($formValues['bind_format']) && $formValues['format_id']) {
275 $messageTemplate['pdf_format_id'] = $formValues['format_id'];
276 }
277 if (!empty($formValues['saveTemplate']) && $formValues['saveTemplate']) {
278 $messageTemplate['msg_title'] = $formValues['saveTemplateName'];
279 CRM_Core_BAO_MessageTemplate::add($messageTemplate);
280 }
281
282 if (!empty($formValues['updateTemplate']) && $formValues['template'] && $formValues['updateTemplate']) {
283 $messageTemplate['id'] = $formValues['template'];
284
285 unset($messageTemplate['msg_title']);
286 CRM_Core_BAO_MessageTemplate::add($messageTemplate);
287 }
288 }
289 elseif (CRM_Utils_Array::value('template', $formValues) > 0) {
290 if (!empty($formValues['bind_format']) && $formValues['format_id']) {
291 $query = "UPDATE civicrm_msg_template SET pdf_format_id = {$formValues['format_id']} WHERE id = {$formValues['template']}";
292 }
293 else {
294 $query = "UPDATE civicrm_msg_template SET pdf_format_id = NULL WHERE id = {$formValues['template']}";
295 }
296 CRM_Core_DAO::executeQuery($query, CRM_Core_DAO::$_nullArray);
297 }
298 if (!empty($formValues['update_format'])) {
299 $bao = new CRM_Core_BAO_PdfFormat();
300 $bao->savePdfFormat($formValues, $formValues['format_id']);
301 }
302
303 $html = array();
304
305 $tokens = array();
306 CRM_Utils_Hook::tokens($tokens);
307 $categories = array_keys($tokens);
308
309 $html_message = $formValues['html_message'];
310
311 //time being hack to strip '&nbsp;'
312 //from particular letter line, CRM-6798
313 self::formatMessage($html_message);
314
315 $messageToken = CRM_Utils_Token::getTokens($html_message);
316
317 $returnProperties = array();
318 if (isset($messageToken['contact'])) {
319 foreach ($messageToken['contact'] as $key => $value) {
320 $returnProperties[$value] = 1;
321 }
322 }
323
324 return array($formValues, $categories, $html_message, $messageToken, $returnProperties);
325 }
326
327 /**
328 * process the form after the input has been submitted and validated
329 *
330 * @access public
331 *
332 * @return void
333 */
334 static function postProcess(&$form) {
335 list($formValues, $categories, $html_message, $messageToken, $returnProperties) = self::processMessageTemplate($form);
336
337 $skipOnHold = isset($form->skipOnHold) ? $form->skipOnHold : FALSE;
338 $skipDeceased = isset($form->skipDeceased) ? $form->skipDeceased : TRUE;
339
340 foreach ($form->_contactIds as $item => $contactId) {
341 $params = array('contact_id' => $contactId);
342
343 list($contact) = CRM_Utils_Token::getTokenDetails($params,
344 $returnProperties,
345 $skipOnHold,
346 $skipDeceased,
347 NULL,
348 $messageToken,
349 'CRM_Contact_Form_Task_PDFLetterCommon'
350 );
351 if (civicrm_error($contact)) {
352 $notSent[] = $contactId;
353 continue;
354 }
355
356 $tokenHtml = CRM_Utils_Token::replaceContactTokens($html_message, $contact[$contactId], TRUE, $messageToken);
357 $tokenHtml = CRM_Utils_Token::replaceHookTokens($tokenHtml, $contact[$contactId], $categories, TRUE);
358
359 if (defined('CIVICRM_MAIL_SMARTY') && CIVICRM_MAIL_SMARTY) {
360 $smarty = CRM_Core_Smarty::singleton();
361 // also add the contact tokens to the template
362 $smarty->assign_by_ref('contact', $contact);
363 $tokenHtml = $smarty->fetch("string:$tokenHtml");
364 }
365
366 $html[] = $tokenHtml;
367 }
368
369 self::createActivities($form, $html_message, $form->_contactIds);
370
371 CRM_Utils_PDF_Utils::html2pdf($html, "CiviLetter.pdf", FALSE, $formValues);
372
373 $form->postProcessHook();
374
375 CRM_Utils_System::civiExit(1);
376 }
377
378 static function createActivities($form, $html_message, $contactIds) {
379 //Added for CRM-12682: Add activity subject and campaign fields
380 $formValues = $form->controller->exportValues($form->getName());
381
382 $session = CRM_Core_Session::singleton();
383 $userID = $session->get('userID');
384 $activityTypeID = CRM_Core_OptionGroup::getValue(
385 'activity_type',
386 'Print PDF Letter',
387 'name'
388 );
389 $activityParams = array(
390 'subject' => $formValues['subject'],
391 'campaign_id' => CRM_Utils_Array::value('campaign_id', $formValues),
392 'source_contact_id' => $userID,
393 'activity_type_id' => $activityTypeID,
394 'activity_date_time' => date('YmdHis'),
395 'details' => $html_message,
396 );
397 if (!empty($form->_activityId)) {
398 $activityParams += array('id' => $form->_activityId);
399 }
400 if ($form->_cid) {
401 $activity = CRM_Activity_BAO_Activity::create($activityParams);
402 }
403 else {
404 // create Print PDF activity for each selected contact. CRM-6886
405 $activityIds = array();
406 foreach ($contactIds as $contactId) {
407 $activityID = CRM_Activity_BAO_Activity::create($activityParams);
408 $activityIds[$contactId] = $activityID->id;
409 }
410 }
411
412 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
413 $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
414
415 foreach ($form->_contactIds as $contactId) {
416 $activityTargetParams = array(
417 'activity_id' => empty($activity->id) ? $activityIds[$contactId] : $activity->id,
418 'contact_id' => $contactId,
419 'record_type_id' => $targetID
420 );
421 CRM_Activity_BAO_ActivityContact::create($activityTargetParams);
422 }
423 }
424
425 static function formatMessage(&$message) {
426 $newLineOperators = array(
427 'p' => array(
428 'oper' => '<p>',
429 'pattern' => '/<(\s+)?p(\s+)?>/m',
430 ),
431 'br' => array(
432 'oper' => '<br />',
433 'pattern' => '/<(\s+)?br(\s+)?\/>/m',
434 ),
435 );
436
437 $htmlMsg = preg_split($newLineOperators['p']['pattern'], $message);
438 foreach ($htmlMsg as $k => & $m) {
439 $messages = preg_split($newLineOperators['br']['pattern'], $m);
440 foreach ($messages as $key => & $msg) {
441 $msg = trim($msg);
442 $matches = array();
443 if (preg_match('/^(&nbsp;)+/', $msg, $matches)) {
444 $spaceLen = strlen($matches[0]) / 6;
445 $trimMsg = ltrim($msg, '&nbsp; ');
446 $charLen = strlen($trimMsg);
447 $totalLen = $charLen + $spaceLen;
448 if ($totalLen > 100) {
449 $spacesCount = 10;
450 if ($spaceLen > 50) {
451 $spacesCount = 20;
452 }
453 if ($charLen > 100) {
454 $spacesCount = 1;
455 }
456 $msg = str_repeat('&nbsp;', $spacesCount) . $trimMsg;
457 }
458 }
459 }
460 $m = implode($newLineOperators['br']['oper'], $messages);
461 }
462 $message = implode($newLineOperators['p']['oper'], $htmlMsg);
463 }
464 }
465