From: Tim Otten Date: Thu, 13 Apr 2017 05:07:37 +0000 (-0700) Subject: CRM-20420 - PDFLetterCommon - Record attachments (in mode "combined-attached") X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=3c48a60caeb1694b78f483bf2db110ef5ea92668;p=civicrm-core.git CRM-20420 - PDFLetterCommon - Record attachments (in mode "combined-attached") If the setting `recordGeneratedLetters` is `combined-attached`, then we should capture the content of the generated file and save it to an attachment. Note: There are several different ways generating files (eg HTML=>PDF, HTML=>docx/ODT, or docx/ODT template file). Ideally, these would support common set of options for directing output (to a file, string, or console). In fact, some do, and all the underlying libraries do... but the middle-logic only handles the console consistently. We use output buffering (ob_start()) to capture the content and save it to a file. --- diff --git a/CRM/Contact/Form/Task/PDFLetterCommon.php b/CRM/Contact/Form/Task/PDFLetterCommon.php index 404f2ef0d6..bb423eb25d 100644 --- a/CRM/Contact/Form/Task/PDFLetterCommon.php +++ b/CRM/Contact/Form/Task/PDFLetterCommon.php @@ -359,11 +359,11 @@ class CRM_Contact_Form_Task_PDFLetterCommon { $buttonName = $form->controller->getButtonName(); $skipOnHold = isset($form->skipOnHold) ? $form->skipOnHold : FALSE; $skipDeceased = isset($form->skipDeceased) ? $form->skipDeceased : TRUE; - $html = $document = array(); + $html = $activityIds = array(); // CRM-16725 Skip creation of activities if user is previewing their PDF letter(s) if ($buttonName == '_qf_PDF_upload') { - self::createActivities($form, $html_message, $form->_contactIds); + $activityIds = self::createActivities($form, $html_message, $form->_contactIds); } if (!empty($formValues['document_file_path'])) { @@ -410,17 +410,53 @@ class CRM_Contact_Form_Task_PDFLetterCommon { $html[] = $tokenHtml; } + $saveToFile = count($activityIds) === 1 && Civi::settings()->get('recordGeneratedLetters') === 'combined-attached'; + if ($saveToFile) { + // We need to capture data from various output-generators whose only + // consistent output format is writing to the console (for download). + $tmpFile = tempnam(sys_get_temp_dir(), 'PDFLetterCommon-'); + $tmpFh = fopen($tmpFile, 'w'); + ob_start(function ($buf) use ($tmpFh) { + // Pass to file, then continue to stdout. + fwrite($tmpFh, $buf); + return FALSE; + }); + } + $type = $formValues['document_type']; + $mimeType = self::getMimeType($type); if ($type == 'pdf') { - CRM_Utils_PDF_Utils::html2pdf($html, "CiviLetter.pdf", FALSE, $formValues); + $fileName = "CiviLetter.$type"; + CRM_Utils_PDF_Utils::html2pdf($html, $fileName, FALSE, $formValues); } elseif (!empty($formValues['document_file_path'])) { $fileName = pathinfo($formValues['document_file_path'], PATHINFO_FILENAME) . '.' . $type; CRM_Utils_PDF_Document::printDocuments($html, $fileName, $type, $zip); } else { - CRM_Utils_PDF_Document::html2doc($html, "CiviLetter.$type", $formValues); + $fileName = "CiviLetter.$type"; + CRM_Utils_PDF_Document::html2doc($html, $fileName, $formValues); + } + + if ($saveToFile) { + ob_end_flush(); + fclose($tmpFh); + $content = file_get_contents($tmpFile, NULL, NULL, NULL, 5); + if (empty($content)) { + throw new \CRM_Core_Exception("Failed to capture document content (type=$type)!"); + } + foreach ($activityIds as $activityId) { + civicrm_api3('Attachment', 'create', array( + 'entity_table' => 'civicrm_activity', + 'entity_id' => $activityId, + 'name' => $fileName, + 'mime_type' => $mimeType, + 'options' => array( + 'move-file' => $tmpFile, + ), + )); + } } $form->postProcessHook(); @@ -562,4 +598,26 @@ class CRM_Contact_Form_Task_PDFLetterCommon { $message = implode($newLineOperators['p']['oper'], $htmlMsg); } + /** + * Convert from a vague-type/file-extension to mime-type. + * + * @param string $type + * @return string + * @throws \CRM_Core_Exception + */ + private static function getMimeType($type) { + $mimeTypes = array( + 'pdf' => 'applicatoin/pdf', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'odt' => 'application/vnd.oasis.opendocument.text', + 'html' => 'text/html', + ); + if (isset($mimeTypes[$type])) { + return $mimeTypes[$type]; + } + else { + throw new \CRM_Core_Exception("Cannot determine mime type"); + } + } + }