dev/core#2790 Move pdf processTemplate to the trait
[civicrm-core.git] / CRM / Contact / Form / Task / PDFLetterCommon.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/**
424029e3 19 * This class provides the common functionality for creating PDF letter for one or a group of contact ids.
6a488035 20 */
958060c1 21class CRM_Contact_Form_Task_PDFLetterCommon extends CRM_Core_Form_Task_PDFLetterCommon {
6a488035 22
2fe8b920 23 protected static $tokenCategories;
24
cc144465
TO
25 /**
26 * @return array
27 * Array(string $machineName => string $label).
28 */
29 public static function getLoggingOptions() {
be2fb01f 30 return [
cc144465
TO
31 'none' => ts('Do not record'),
32 'multiple' => ts('Multiple activities (one per contact)'),
33 'combined' => ts('One combined activity'),
34 'combined-attached' => ts('One combined activity plus one file attachment'),
35 // 'multiple-attached' <== not worth the work
be2fb01f 36 ];
cc144465
TO
37 }
38
6a488035 39 /**
fe482240 40 * Build all the data structures needed to build the form.
6a488035 41 *
c97bfeff
EM
42 * @deprecated
43 *
c490a46a 44 * @param CRM_Core_Form $form
6a488035 45 */
00be9182 46 public static function preProcess(&$form) {
c97bfeff 47 CRM_Core_Error::deprecatedFunctionWarning('no alternative');
ca5f0b93 48 $defaults = [];
0008e8aa 49 $form->_fromEmails = CRM_Core_BAO_Email::getFromEmail();
ca5f0b93
EM
50 if (is_numeric(key($form->_fromEmails))) {
51 $emailID = (int) key($form->_fromEmails);
52 $defaults = CRM_Core_BAO_Email::getEmailSignatureDefaults($emailID);
53 }
54 if (!Civi::settings()->get('allow_mail_from_logged_in_contact')) {
55 $defaults['from_email_address'] = current(CRM_Core_BAO_Domain::getNameAndEmail(FALSE, TRUE));
56 }
57 $form->setDefaults($defaults);
0008e8aa 58 $form->setTitle('Print/Merge Document');
6a488035
TO
59 }
60
86538308 61 /**
972171bb 62 * @deprecated
c490a46a 63 * @param CRM_Core_Form $form
100fef9d 64 * @param int $cid
86538308 65 */
00be9182 66 public static function preProcessSingle(&$form, $cid) {
972171bb 67 CRM_Core_Error::deprecatedFunctionWarning('no alternative');
fe61faf3 68 $form->_contactIds = explode(',', $cid);
6a488035 69 // put contact display name in title for single contact mode
fe61faf3 70 if (count($form->_contactIds) === 1) {
7e2e2551
MW
71 $form->setTitle(
72 ts('Print/Merge Document for %1',
73 [1 => CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $cid, 'display_name')])
74 );
fe61faf3 75 }
6a488035
TO
76 }
77
6a488035 78 /**
fe482240 79 * Part of the post process which prepare and extract information from the template.
6a488035 80 *
6a488035 81 *
2bd6b6cf 82 * @param array $formValues
dbddfb08 83 *
72b3a70c
CW
84 * @return array
85 * [$categories, $html_message, $messageToken, $returnProperties]
0ceb63d9
EM
86 *
87 * @deprecated
6a488035 88 */
2bd6b6cf 89 public static function processMessageTemplate($formValues) {
0ceb63d9
EM
90 CRM_Core_Error::deprecatedFunctionWarning('no alternative');
91
958060c1 92 $html_message = self::processTemplate($formValues);
6a488035 93
2fe8b920 94 $categories = self::getTokenCategories();
6a488035 95
6a488035
TO
96 //time being hack to strip '&nbsp;'
97 //from particular letter line, CRM-6798
98 self::formatMessage($html_message);
99
100 $messageToken = CRM_Utils_Token::getTokens($html_message);
101
be2fb01f 102 $returnProperties = [];
6a488035
TO
103 if (isset($messageToken['contact'])) {
104 foreach ($messageToken['contact'] as $key => $value) {
105 $returnProperties[$value] = 1;
106 }
107 }
108
be2fb01f 109 return [$formValues, $categories, $html_message, $messageToken, $returnProperties];
6a488035
TO
110 }
111
112 /**
fe482240 113 * Process the form after the input has been submitted and validated.
6a488035 114 *
c490a46a 115 * @param CRM_Core_Form $form
69863342 116 *
2fe8b920 117 * @throws \CRM_Core_Exception
b69df99f 118 * @throws \CiviCRM_API3_Exception
69863342 119 * @throws \API_Exception
fb4f4e89
EM
120 *
121 * @deprecated
6a488035 122 */
69863342 123 public static function postProcess(&$form): void {
fb4f4e89 124 CRM_Core_Error::deprecatedFunctionWarning('no alternative');
2bd6b6cf 125 $formValues = $form->controller->exportValues($form->getName());
69863342 126 [$formValues, $categories, $html_message, $messageToken, $returnProperties] = self::processMessageTemplate($formValues);
be2fb01f 127 $html = $activityIds = [];
ad7fdc34 128
129 // CRM-16725 Skip creation of activities if user is previewing their PDF letter(s)
752cee47 130 if (self::isLiveMode($form)) {
fe61faf3 131 $activityIds = self::createActivities($form, $html_message, $form->_contactIds, $formValues['subject'], CRM_Utils_Array::value('campaign_id', $formValues));
ad7fdc34 132 }
133
134 if (!empty($formValues['document_file_path'])) {
69863342 135 [$html_message, $zip] = CRM_Utils_PDF_Document::unzipDoc($formValues['document_file_path'], $formValues['document_type']);
ad7fdc34 136 }
6a488035
TO
137
138 foreach ($form->_contactIds as $item => $contactId) {
b69df99f
CW
139 $caseId = $form->getVar('_caseId');
140 if (empty($caseId) && !empty($form->_caseIds[$item])) {
141 $caseId = $form->_caseIds[$item];
142 }
b69df99f 143
5ce0a616
EM
144 $tokenHtml = CRM_Core_BAO_MessageTemplate::renderTemplate([
145 'contactId' => $contactId,
69863342 146 'messageTemplate' => ['msg_html' => $html_message],
69863342 147 'tokenContext' => $caseId ? ['caseId' => $caseId] : [],
5ce0a616
EM
148 'disableSmarty' => (!defined('CIVICRM_MAIL_SMARTY') || !CIVICRM_MAIL_SMARTY),
149 ])['html'];
6a488035
TO
150
151 $html[] = $tokenHtml;
152 }
153
38faa439 154 $tee = NULL;
dd8e53c4 155 if (self::isLiveMode($form) && Civi::settings()->get('recordGeneratedLetters') === 'combined-attached') {
bdac10d8
TO
156 if (count($activityIds) !== 1) {
157 throw new CRM_Core_Exception("When recordGeneratedLetters=combined-attached, there should only be one activity.");
158 }
38faa439 159 $tee = CRM_Utils_ConsoleTee::create()->start();
3c48a60c
TO
160 }
161
0aeb5a1e 162 $type = $formValues['document_type'];
3c48a60c 163 $mimeType = self::getMimeType($type);
3ed92c14 164 // ^^ Useful side-effect: consistently throws error for unrecognized types.
0aeb5a1e 165
7c0d6f7a 166 $fileName = method_exists($form, 'getFileName') ? ($form->getFileName() . '.' . $type) : 'CiviLetter.' . $type;
61d0bf1f 167
5ce0a616 168 if ($type === 'pdf') {
3c48a60c 169 CRM_Utils_PDF_Utils::html2pdf($html, $fileName, FALSE, $formValues);
0aeb5a1e 170 }
ad7fdc34 171 elseif (!empty($formValues['document_file_path'])) {
63c8a9ba
TO
172 $fileName = pathinfo($formValues['document_file_path'], PATHINFO_FILENAME) . '.' . $type;
173 CRM_Utils_PDF_Document::printDocuments($html, $fileName, $type, $zip);
ad7fdc34 174 }
0aeb5a1e 175 else {
3c48a60c
TO
176 CRM_Utils_PDF_Document::html2doc($html, $fileName, $formValues);
177 }
178
38faa439
TO
179 if ($tee) {
180 $tee->stop();
181 $content = file_get_contents($tee->getFileName(), NULL, NULL, NULL, 5);
3c48a60c
TO
182 if (empty($content)) {
183 throw new \CRM_Core_Exception("Failed to capture document content (type=$type)!");
184 }
185 foreach ($activityIds as $activityId) {
be2fb01f 186 civicrm_api3('Attachment', 'create', [
3c48a60c
TO
187 'entity_table' => 'civicrm_activity',
188 'entity_id' => $activityId,
189 'name' => $fileName,
190 'mime_type' => $mimeType,
be2fb01f 191 'options' => [
38faa439 192 'move-file' => $tee->getFileName(),
be2fb01f
CW
193 ],
194 ]);
3c48a60c 195 }
0aeb5a1e 196 }
6a488035
TO
197
198 $form->postProcessHook();
199
292c8687 200 CRM_Utils_System::civiExit();
6a488035
TO
201 }
202
86538308 203 /**
c490a46a 204 * @param CRM_Core_Form $form
818b4373
TO
205 * @param string $html_message
206 * @param array $contactIds
3280f327 207 * @param string $subject
208 * @param int $campaign_id
209 * @param array $perContactHtml
210 *
818b4373
TO
211 * @return array
212 * List of activity IDs.
213 * There may be 1 or more, depending on the system-settings
214 * and use-case.
86538308
EM
215 *
216 * @throws CRM_Core_Exception
fb4f4e89
EM
217 *
218 * @deprecated
86538308 219 */
be2fb01f 220 public static function createActivities($form, $html_message, $contactIds, $subject, $campaign_id, $perContactHtml = []) {
fb4f4e89 221 CRM_Core_Error::deprecatedFunctionWarning('no alternative');
6a488035 222
be2fb01f 223 $activityParams = [
3280f327 224 'subject' => $subject,
225 'campaign_id' => $campaign_id,
2dbdb9b9 226 'source_contact_id' => CRM_Core_Session::getLoggedInContactID(),
3280f327 227 'activity_type_id' => CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Print PDF Letter'),
6a488035
TO
228 'activity_date_time' => date('YmdHis'),
229 'details' => $html_message,
be2fb01f 230 ];
6a488035 231 if (!empty($form->_activityId)) {
be2fb01f 232 $activityParams += ['id' => $form->_activityId];
6a488035 233 }
818b4373 234
be2fb01f 235 $activityIds = [];
818b4373
TO
236 switch (Civi::settings()->get('recordGeneratedLetters')) {
237 case 'none':
be2fb01f 238 return [];
818b4373
TO
239
240 case 'multiple':
241 // One activity per contact.
fe61faf3 242 foreach ($contactIds as $i => $contactId) {
be2fb01f 243 $fullParams = [
6d3827cb 244 'target_contact_id' => $contactId,
be2fb01f 245 ] + $activityParams;
fe61faf3
CW
246 if (!empty($form->_caseId)) {
247 $fullParams['case_id'] = $form->_caseId;
248 }
249 elseif (!empty($form->_caseIds[$i])) {
250 $fullParams['case_id'] = $form->_caseIds[$i];
251 }
252
3280f327 253 if (isset($perContactHtml[$contactId])) {
254 $fullParams['details'] = implode('<hr>', $perContactHtml[$contactId]);
255 }
256 $activity = civicrm_api3('Activity', 'create', $fullParams);
257 $activityIds[$contactId] = $activity['id'];
818b4373
TO
258 }
259
260 break;
261
262 case 'combined':
263 case 'combined-attached':
264 // One activity with all contacts.
be2fb01f 265 $fullParams = [
6d3827cb 266 'target_contact_id' => $contactIds,
be2fb01f 267 ] + $activityParams;
fe61faf3
CW
268 if (!empty($form->_caseId)) {
269 $fullParams['case_id'] = $form->_caseId;
270 }
271 elseif (!empty($form->_caseIds)) {
272 $fullParams['case_id'] = $form->_caseIds;
273 }
274 $activity = civicrm_api3('Activity', 'create', $fullParams);
275 $activityIds[] = $activity['id'];
818b4373
TO
276 break;
277
278 default:
279 throw new CRM_Core_Exception("Unrecognized option in recordGeneratedLetters: " . Civi::settings()->get('recordGeneratedLetters'));
6a488035 280 }
818b4373 281
818b4373 282 return $activityIds;
6a488035
TO
283 }
284
86538308 285 /**
3c48a60c
TO
286 * Convert from a vague-type/file-extension to mime-type.
287 *
288 * @param string $type
289 * @return string
290 * @throws \CRM_Core_Exception
fb4f4e89
EM
291 *
292 * @deprecated
3c48a60c
TO
293 */
294 private static function getMimeType($type) {
be2fb01f 295 $mimeTypes = [
4b54b8bb 296 'pdf' => 'application/pdf',
3c48a60c
TO
297 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
298 'odt' => 'application/vnd.oasis.opendocument.text',
299 'html' => 'text/html',
be2fb01f 300 ];
3c48a60c
TO
301 if (isset($mimeTypes[$type])) {
302 return $mimeTypes[$type];
303 }
304 else {
305 throw new \CRM_Core_Exception("Cannot determine mime type");
306 }
307 }
308
2fe8b920 309 /**
310 * Get the categories required for rendering tokens.
311 *
0ceb63d9
EM
312 * @deprecated
313 *
2fe8b920 314 * @return array
315 */
316 protected static function getTokenCategories() {
3280f327 317 if (!isset(Civi::$statics[__CLASS__]['token_categories'])) {
be2fb01f 318 $tokens = [];
2fe8b920 319 CRM_Utils_Hook::tokens($tokens);
3280f327 320 Civi::$statics[__CLASS__]['token_categories'] = array_keys($tokens);
2fe8b920 321 }
3280f327 322 return Civi::$statics[__CLASS__]['token_categories'];
2fe8b920 323 }
324
752cee47 325 /**
326 * Is the form in live mode (as opposed to being run as a preview).
327 *
328 * Returns true if the user has clicked the Download Document button on a
329 * Print/Merge Document (PDF Letter) search task form, or false if the Preview
330 * button was clicked.
331 *
332 * @param CRM_Core_Form $form
333 *
334 * @return bool
335 * TRUE if the Download Document button was clicked (also defaults to TRUE
336 * if the form controller does not exist), else FALSE
fb4f4e89
EM
337 *
338 * @deprecated
752cee47 339 */
340 protected static function isLiveMode($form) {
341 // CRM-21255 - Hrm, CiviCase 4+5 seem to report buttons differently...
342 $buttonName = $form->controller->getButtonName();
343 $c = $form->controller->container();
344 $isLiveMode = ($buttonName == '_qf_PDF_upload') || isset($c['values']['PDF']['buttons']['_qf_PDF_upload']);
345 return $isLiveMode;
346 }
347
6a488035 348}