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