Fix test
[civicrm-core.git] / CRM / Core / Form / Task / PDFLetterCommon.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
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 |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 *
14 * @package CRM
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
16 */
17
18 /**
19 * This is the base class for common PDF/Doc Merge functionality.
20 * Most CRM_*_Form_Task_PDFLetterCommon classes extend the Contact version
21 * but the assumptions there are not always appropriate for other classes
22 * resulting in code duplication and unexpected dependencies.
23 * The intention is that common functionality can be moved here and the other
24 * classes cleaned up.
25 * Keep old-style token handling out of this class.
26 *
27 * @deprecated
28 */
29 class CRM_Core_Form_Task_PDFLetterCommon {
30
31 /**
32 * @var CRM_Core_Form $form
33 *
34 * @deprecated
35 */
36 public static function preProcess(&$form) {
37 CRM_Core_Error::deprecatedFunctionWarning('no alternative');
38
39 $form->setTitle('Print/Merge Document');
40 }
41
42 /**
43 * Build the form object.
44 *
45 * @deprecated
46 *
47 * @var CRM_Core_Form $form
48 * @throws \CRM_Core_Exception
49 */
50 public static function buildQuickForm(&$form) {
51 CRM_Core_Error::deprecatedFunctionWarning('no supported alternative for non-core code');
52 // This form outputs a file so should never be submitted via ajax
53 $form->preventAjaxSubmit();
54
55 //Added for CRM-12682: Add activity subject and campaign fields
56 CRM_Campaign_BAO_Campaign::addCampaign($form);
57 $form->add(
58 'text',
59 'subject',
60 ts('Activity Subject'),
61 ['size' => 45, 'maxlength' => 255],
62 FALSE
63 );
64
65 // Added for core#2121,
66 // To support sending a custom pdf filename before downloading.
67 $form->addElement('hidden', 'pdf_file_name');
68
69 $form->addSelect('format_id', [
70 'label' => ts('Select Format'),
71 'placeholder' => ts('Default'),
72 'entity' => 'message_template',
73 'field' => 'pdf_format_id',
74 'option_url' => 'civicrm/admin/pdfFormats',
75 ]);
76 $form->add(
77 'select',
78 'paper_size',
79 ts('Paper Size'),
80 [0 => ts('- default -')] + CRM_Core_BAO_PaperSize::getList(TRUE),
81 FALSE,
82 ['onChange' => "selectPaper( this.value ); showUpdateFormatChkBox();"]
83 );
84 $form->add(
85 'select',
86 'orientation',
87 ts('Orientation'),
88 CRM_Core_BAO_PdfFormat::getPageOrientations(),
89 FALSE,
90 ['onChange' => "updatePaperDimensions(); showUpdateFormatChkBox();"]
91 );
92 $form->add(
93 'select',
94 'metric',
95 ts('Unit of Measure'),
96 CRM_Core_BAO_PdfFormat::getUnits(),
97 FALSE,
98 ['onChange' => "selectMetric( this.value );"]
99 );
100 $form->add(
101 'text',
102 'margin_left',
103 ts('Left Margin'),
104 ['size' => 8, 'maxlength' => 8, 'onkeyup' => "showUpdateFormatChkBox();"],
105 TRUE
106 );
107 $form->add(
108 'text',
109 'margin_right',
110 ts('Right Margin'),
111 ['size' => 8, 'maxlength' => 8, 'onkeyup' => "showUpdateFormatChkBox();"],
112 TRUE
113 );
114 $form->add(
115 'text',
116 'margin_top',
117 ts('Top Margin'),
118 ['size' => 8, 'maxlength' => 8, 'onkeyup' => "showUpdateFormatChkBox();"],
119 TRUE
120 );
121 $form->add(
122 'text',
123 'margin_bottom',
124 ts('Bottom Margin'),
125 ['size' => 8, 'maxlength' => 8, 'onkeyup' => "showUpdateFormatChkBox();"],
126 TRUE
127 );
128
129 $config = CRM_Core_Config::singleton();
130 /** CRM-15883 Suppressing Stationery path field until we switch from DOMPDF to a library that supports it.
131 * if ($config->wkhtmltopdfPath == FALSE) {
132 * $form->add(
133 * 'text',
134 * 'stationery',
135 * ts('Stationery (relative path to PDF you wish to use as the background)'),
136 * array('size' => 25, 'maxlength' => 900, 'onkeyup' => "showUpdateFormatChkBox();"),
137 * FALSE
138 * );
139 * }
140 */
141 $form->add('checkbox', 'bind_format', ts('Always use this Page Format with the selected Template'));
142 $form->add('checkbox', 'update_format', ts('Update Page Format (this will affect all templates that use this format)'));
143
144 $form->assign('useThisPageFormat', ts('Always use this Page Format with the new template?'));
145 $form->assign('useSelectedPageFormat', ts('Should the new template always use the selected Page Format?'));
146 $form->assign('totalSelectedContacts', !is_null($form->_contactIds) ? count($form->_contactIds) : 0);
147
148 $form->add('select', 'document_type', ts('Document Type'), CRM_Core_SelectValues::documentFormat());
149
150 $documentTypes = implode(',', CRM_Core_SelectValues::documentApplicationType());
151 $form->addElement('file', "document_file", 'Upload Document', 'size=30 maxlength=255 accept="' . $documentTypes . '"');
152 $form->addUploadElement("document_file");
153
154 CRM_Mailing_BAO_Mailing::commonCompose($form);
155
156 $buttons = [];
157 if ($form->get('action') != CRM_Core_Action::VIEW) {
158 $buttons[] = [
159 'type' => 'upload',
160 'name' => ts('Download Document'),
161 'isDefault' => TRUE,
162 'icon' => 'fa-download',
163 ];
164 $buttons[] = [
165 'type' => 'submit',
166 'name' => ts('Preview'),
167 'subName' => 'preview',
168 'icon' => 'fa-search',
169 'isDefault' => FALSE,
170 ];
171 }
172 $buttons[] = [
173 'type' => 'cancel',
174 'name' => $form->get('action') == CRM_Core_Action::VIEW ? ts('Done') : ts('Cancel'),
175 ];
176 $form->addButtons($buttons);
177
178 $form->addFormRule(['CRM_Core_Form_Task_PDFLetterCommon', 'formRule'], $form);
179 }
180
181 /**
182 * Set default values.
183 *
184 * @deprecated
185 */
186 public static function setDefaultValues() {
187 CRM_Core_Error::deprecatedFunctionWarning('no alternative');
188 $defaultFormat = CRM_Core_BAO_PdfFormat::getDefaultValues();
189 $defaultFormat['format_id'] = $defaultFormat['id'];
190 return $defaultFormat;
191 }
192
193 /**
194 * Form rule.
195 *
196 * @param array $fields
197 * The input form values.
198 * @param array $files
199 * @param array $self
200 * Additional values form 'this'.
201 *
202 * @return bool
203 * TRUE if no errors, else array of errors.
204 */
205 public static function formRule($fields, $files, $self) {
206 $errors = [];
207 $deprecatedTokens = [
208 '{case.status_id}' => '{case.status_id:label}',
209 '{case.case_type_id}' => '{case.case_type_id:label}',
210 '{membership.status}' => '{membership.status_id:label}',
211 '{membership.type}' => '{membership.membership_type_id:label}',
212 '{contribution.campaign}' => '{contribution.campaign_id:label}',
213 '{contribution.payment_instrument}' => '{contribution.payment_instrument_id:label}',
214 '{contribution.contribution_id}' => '{contribution.id}',
215 '{contribution.contribution_source}' => '{contribution.source}',
216 ];
217 $tokenErrors = [];
218 foreach ($deprecatedTokens as $token => $replacement) {
219 if (strpos($fields['html_message'], $token) !== FALSE) {
220 $tokenErrors[] = ts('Token %1 is no longer supported - use %2 instead', [$token, $replacement]);
221 }
222 }
223 if (!empty($tokenErrors)) {
224 $errors['html_message'] = implode('<br>', $tokenErrors);
225 }
226
227 // If user uploads non-document file other than odt/docx
228 if (empty($fields['template']) &&
229 !empty($files['document_file']['tmp_name']) &&
230 array_search($files['document_file']['type'], CRM_Core_SelectValues::documentApplicationType()) == NULL
231 ) {
232 $errors['document_file'] = ts('Invalid document file format');
233 }
234 //Added for CRM-1393
235 if (!empty($fields['saveTemplate']) && empty($fields['saveTemplateName'])) {
236 $errors['saveTemplateName'] = ts("Enter name to save message template");
237 }
238 if (!is_numeric($fields['margin_left'])) {
239 $errors['margin_left'] = 'Margin must be numeric';
240 }
241 if (!is_numeric($fields['margin_right'])) {
242 $errors['margin_right'] = 'Margin must be numeric';
243 }
244 if (!is_numeric($fields['margin_top'])) {
245 $errors['margin_top'] = 'Margin must be numeric';
246 }
247 if (!is_numeric($fields['margin_bottom'])) {
248 $errors['margin_bottom'] = 'Margin must be numeric';
249 }
250 return empty($errors) ? TRUE : $errors;
251 }
252
253 /**
254 * Handle the template processing part of the form
255 *
256 * @param array $formValues
257 *
258 * @return string $html_message
259 *
260 * @deprecated
261 *
262 * @throws \CRM_Core_Exception
263 * @throws \CiviCRM_API3_Exception
264 * @throws \Civi\API\Exception\UnauthorizedException
265 */
266 public static function processTemplate(&$formValues) {
267 CRM_Core_Error::deprecatedFunctionWarning('no alternative');
268
269 $html_message = $formValues['html_message'] ?? NULL;
270
271 // process message template
272 if (!empty($formValues['saveTemplate']) || !empty($formValues['updateTemplate'])) {
273 $messageTemplate = [
274 'msg_text' => NULL,
275 'msg_html' => $formValues['html_message'],
276 'msg_subject' => NULL,
277 'is_active' => TRUE,
278 ];
279
280 $messageTemplate['pdf_format_id'] = 'null';
281 if (!empty($formValues['bind_format']) && $formValues['format_id']) {
282 $messageTemplate['pdf_format_id'] = $formValues['format_id'];
283 }
284 if (!empty($formValues['saveTemplate'])) {
285 $messageTemplate['msg_title'] = $formValues['saveTemplateName'];
286 CRM_Core_BAO_MessageTemplate::add($messageTemplate);
287 }
288
289 if ($formValues['template'] && !empty($formValues['updateTemplate'])) {
290 $messageTemplate['id'] = $formValues['template'];
291
292 unset($messageTemplate['msg_title']);
293 CRM_Core_BAO_MessageTemplate::add($messageTemplate);
294 }
295 }
296 elseif (CRM_Utils_Array::value('template', $formValues) > 0) {
297 if (!empty($formValues['bind_format']) && $formValues['format_id']) {
298 $query = "UPDATE civicrm_msg_template SET pdf_format_id = {$formValues['format_id']} WHERE id = {$formValues['template']}";
299 }
300 else {
301 $query = "UPDATE civicrm_msg_template SET pdf_format_id = NULL WHERE id = {$formValues['template']}";
302 }
303 CRM_Core_DAO::executeQuery($query);
304
305 $documentInfo = CRM_Core_BAO_File::getEntityFile('civicrm_msg_template', $formValues['template']);
306 foreach ((array) $documentInfo as $info) {
307 [$html_message, $formValues['document_type']] = CRM_Utils_PDF_Document::docReader($info['fullPath'], $info['mime_type']);
308 $formValues['document_file_path'] = $info['fullPath'];
309 }
310 }
311 // extract the content of uploaded document file
312 elseif (!empty($formValues['document_file'])) {
313 [$html_message, $formValues['document_type']] = CRM_Utils_PDF_Document::docReader($formValues['document_file']['name'], $formValues['document_file']['type']);
314 $formValues['document_file_path'] = $formValues['document_file']['name'];
315 }
316
317 if (!empty($formValues['update_format'])) {
318 $bao = new CRM_Core_BAO_PdfFormat();
319 $bao->savePdfFormat($formValues, $formValues['format_id']);
320 }
321
322 return $html_message;
323 }
324
325 /**
326 * @deprecated
327 *
328 * @param $message
329 */
330 public static function formatMessage(&$message) {
331 $newLineOperators = [
332 'p' => [
333 'oper' => '<p>',
334 'pattern' => '/<(\s+)?p(\s+)?>/m',
335 ],
336 'br' => [
337 'oper' => '<br />',
338 'pattern' => '/<(\s+)?br(\s+)?\/>/m',
339 ],
340 ];
341
342 $htmlMsg = preg_split($newLineOperators['p']['pattern'], $message);
343 foreach ($htmlMsg as $k => & $m) {
344 $messages = preg_split($newLineOperators['br']['pattern'], $m);
345 foreach ($messages as $key => & $msg) {
346 $msg = trim($msg);
347 $matches = [];
348 if (preg_match('/^(&nbsp;)+/', $msg, $matches)) {
349 $spaceLen = strlen($matches[0]) / 6;
350 $trimMsg = ltrim($msg, '&nbsp; ');
351 $charLen = strlen($trimMsg);
352 $totalLen = $charLen + $spaceLen;
353 if ($totalLen > 100) {
354 $spacesCount = 10;
355 if ($spaceLen > 50) {
356 $spacesCount = 20;
357 }
358 if ($charLen > 100) {
359 $spacesCount = 1;
360 }
361 $msg = str_repeat('&nbsp;', $spacesCount) . $trimMsg;
362 }
363 }
364 }
365 $m = implode($newLineOperators['br']['oper'], $messages);
366 }
367 $message = implode($newLineOperators['p']['oper'], $htmlMsg);
368 }
369
370 /**
371 * Render html from rows
372 *
373 * @param $rows
374 * @param string $msgPart
375 * The name registered with the TokenProcessor
376 * @param array $formValues
377 * The values submitted through the form
378 *
379 * @deprecated
380 */
381 public static function renderFromRows($rows, $msgPart, $formValues): void {
382 CRM_Core_Error::deprecatedFunctionWarning('no alternative');
383 $html = [];
384 foreach ($rows as $row) {
385 $html[] = $row->render($msgPart);
386 }
387
388 if (!empty($html)) {
389 self::outputFromHtml($formValues, $html);
390 }
391 }
392
393 /**
394 * List the available tokens
395 * @return array of token name => label
396 *
397 * @deprecated
398 */
399 public static function listTokens() {
400 CRM_Core_Error::deprecatedFunctionWarning('no alternative');
401 $class = get_called_class();
402 if (method_exists($class, 'createTokenProcessor')) {
403 return $class::createTokenProcessor()->listTokens();
404 }
405 }
406
407 /**
408 * Output the pdf or word document from the generated html.
409 *
410 * @deprecated
411 *
412 * @param array $formValues
413 * @param array $html
414 */
415 protected static function outputFromHtml($formValues, array $html) {
416 CRM_Core_Error::deprecatedFunctionWarning('no alternative');
417 // Set the filename for the PDF using the Activity Subject, if defined. Remove unwanted characters and limit the length to 200 characters.
418 if (!empty($formValues['subject'])) {
419 $fileName = CRM_Utils_File::makeFilenameWithUnicode($formValues['subject'], '_', 200);
420 }
421 else {
422 $fileName = 'CiviLetter';
423 }
424 if ($formValues['document_type'] === 'pdf') {
425 CRM_Utils_PDF_Utils::html2pdf($html, $fileName . '.pdf', FALSE, $formValues);
426 }
427 else {
428 CRM_Utils_PDF_Document::html2doc($html, $fileName . '.' . $formValues['document_type'], $formValues);
429 }
430 }
431
432 }