From 3ba1e8880a22899017ceea3ed6b05aee066d9ed7 Mon Sep 17 00:00:00 2001 From: Lisa Marie Maginnis Date: Thu, 1 May 2014 17:29:27 -0400 Subject: [PATCH] Additional files for PDF/Latex --- CRM/Contact/Form/Task/LatexPDF.php | 125 +++ CRM/Contact/Form/Task/PDFLatexCommon.php | 434 ++++++++++ CRM/Contribute/Form/Task/PDFLatex.php | 147 ++++ CRM/Contribute/Form/Task/PDFLatexCommon.php | 116 +++ CRM/Core/Payment/TrustCommerce.php | 467 +++++++++++ CRM/Core/Payment/insert_tc.sql | 7 + i/mini_cvv2.gif | Bin 0 -> 509 bytes latex.patch | 764 ++++++++++++++++++ sigjohns.pdf | Bin 0 -> 32559 bytes sigjohns.png | Bin 0 -> 43597 bytes templates/CRM/Contact/Form/Task/LatexPDF.tpl | 33 + .../Contact/Form/Task/LatexPDFLatexCommon.tpl | 312 +++++++ .../CRM/Contribute/Form/Task/PDFLatex.tpl | 48 ++ tmp_table_myisam.patch | 51 ++ 14 files changed, 2504 insertions(+) create mode 100644 CRM/Contact/Form/Task/LatexPDF.php create mode 100644 CRM/Contact/Form/Task/PDFLatexCommon.php create mode 100644 CRM/Contribute/Form/Task/PDFLatex.php create mode 100644 CRM/Contribute/Form/Task/PDFLatexCommon.php create mode 100644 CRM/Core/Payment/TrustCommerce.php create mode 100644 CRM/Core/Payment/insert_tc.sql create mode 100644 i/mini_cvv2.gif create mode 100644 latex.patch create mode 100644 sigjohns.pdf create mode 100644 sigjohns.png create mode 100644 templates/CRM/Contact/Form/Task/LatexPDF.tpl create mode 100644 templates/CRM/Contact/Form/Task/LatexPDFLatexCommon.tpl create mode 100644 templates/CRM/Contribute/Form/Task/PDFLatex.tpl create mode 100644 tmp_table_myisam.patch diff --git a/CRM/Contact/Form/Task/LatexPDF.php b/CRM/Contact/Form/Task/LatexPDF.php new file mode 100644 index 0000000000..3fccdd8d7b --- /dev/null +++ b/CRM/Contact/Form/Task/LatexPDF.php @@ -0,0 +1,125 @@ +skipOnHold = $this->skipDeceased = FALSE; + CRM_Contact_Form_Task_PDFLatexCommon::preProcess($this); + + // store case id if present + $this->_caseId = CRM_Utils_Request::retrieve('caseid', 'Positive', $this, FALSE); + + // retrieve contact ID if this is 'single' mode + $cid = CRM_Utils_Request::retrieve('cid', 'Positive', $this, FALSE); + + if ($cid) { + // this is true in non-search context / single mode + // in search context 'id' is the default profile id for search display + // CRM-11227 + $this->_activityId = CRM_Utils_Request::retrieve('id', 'Positive', $this, FALSE); + } + + if ($cid) { + CRM_Contact_Form_Task_PDFLatexCommon::preProcessSingle($this, $cid); + $this->_single = TRUE; + $this->_cid = $cid; + } + else { + parent::preProcess(); + } + $this->assign('single', $this->_single); + } + + function setDefaultValues() { + $defaults = array(); + if (isset($this->_activityId)) { + $params = array('id' => $this->_activityId); + CRM_Activity_BAO_Activity::retrieve($params, $defaults); + $defaults['html_message'] = CRM_Utils_Array::value('details', $defaults); + } + $defaults = $defaults + CRM_Contact_Form_Task_PDFLatexCommon::setDefaultValues(); + return $defaults; + } + + /** + * Build the form + * + * @access public + * + * @return void + */ + public function buildQuickForm() { + //enable form element + $this->assign('suppressForm', FALSE); + CRM_Contact_Form_Task_PDFLatexCommon::buildQuickForm($this); + } + + /** + * process the form after the input has been submitted and validated + * + * @access public + * + * @return None + */ + public function postProcess() { + CRM_Contact_Form_Task_PDFLatexCommon::postProcess($this); + } +} + diff --git a/CRM/Contact/Form/Task/PDFLatexCommon.php b/CRM/Contact/Form/Task/PDFLatexCommon.php new file mode 100644 index 0000000000..a0ca45339c --- /dev/null +++ b/CRM/Contact/Form/Task/PDFLatexCommon.php @@ -0,0 +1,434 @@ +is_active = 1; + $dao->find(); + while ($dao->fetch()) { + $messageText[$dao->id] = $dao->msg_text; + $messageSubject[$dao->id] = $dao->msg_subject; + } + + $form->assign('message', $messageText); + $form->assign('messageSubject', $messageSubject); + } + + static function preProcessSingle(&$form, $cid) { + $form->_contactIds = array($cid); + // put contact display name in title for single contact mode + CRM_Contact_Page_View::setTitle($cid); + } + + /** + * Build the form + * + * @access public + * + * @return void + */ + static function buildQuickForm(&$form) { + $form->add('static', 'pdf_format_header', NULL, ts('Page Format')); + $form->add( + 'select', + 'format_id', + ts('Select Format'), + array(0 => ts('- default -')) + CRM_Core_BAO_PdfFormat::getList(TRUE), + FALSE, + array('onChange' => "selectFormat( this.value, false );") + );; + $form->add( + 'select', + 'paper_size', + ts('Paper Size'), + array(0 => ts('- default -')) + CRM_Core_BAO_PaperSize::getList(TRUE), + FALSE, + array('onChange' => "selectPaper( this.value ); showUpdateFormatChkBox();") + ); + $form->add('static', 'paper_dimensions', NULL, ts('Width x Height')); + $form->add( + 'select', + 'orientation', + ts('Orientation'), + CRM_Core_BAO_PdfFormat::getPageOrientations(), + FALSE, + array('onChange' => "updatePaperDimensions(); showUpdateFormatChkBox();") + ); + $form->add( + 'select', + 'metric', + ts('Unit of Measure'), + CRM_Core_BAO_PdfFormat::getUnits(), + FALSE, + array('onChange' => "selectMetric( this.value );") + ); + $form->add( + 'text', + 'margin_left', + ts('Left Margin'), + array('size' => 8, 'maxlength' => 8, 'onkeyup' => "showUpdateFormatChkBox();"), + TRUE + ); + $form->add( + 'text', + 'margin_right', + ts('Right Margin'), + array('size' => 8, 'maxlength' => 8, 'onkeyup' => "showUpdateFormatChkBox();"), + TRUE + ); + $form->add( + 'text', + 'margin_top', + ts('Top Margin'), + array('size' => 8, 'maxlength' => 8, 'onkeyup' => "showUpdateFormatChkBox();"), + TRUE + ); + $form->add( + 'text', + 'margin_bottom', + ts('Bottom Margin'), + array('size' => 8, 'maxlength' => 8, 'onkeyup' => "showUpdateFormatChkBox();"), + TRUE + ); + $form->add('checkbox', 'bind_format', ts('Always use this Page Format with the selected Template')); + $form->add('checkbox', 'update_format', ts('Update Page Format (this will affect all templates that use this format)')); + + $form->assign('useThisPageFormat', ts('Always use this Page Format with the new template?')); + $form->assign('useSelectedPageFormat', ts('Should the new template always use the selected Page Format?')); + $form->assign('totalSelectedContacts', count($form->_contactIds)); + + CRM_Mailing_BAO_Mailing::commonLetterCompose($form); + + if ($form->_single) { + $cancelURL = CRM_Utils_System::url( + 'civicrm/contact/view', + "reset=1&cid={$form->_cid}&selectedChild=activity", + FALSE, + NULL, + FALSE + ); + if ($form->get('action') == CRM_Core_Action::VIEW) { + $form->addButtons(array( + array( + 'type' => 'cancel', + 'name' => ts('Done'), + 'js' => array('onclick' => "location.href='{$cancelURL}'; return false;"), + ), + ) + ); + } + else { + $form->addButtons(array( + array( + 'type' => 'submit', + 'name' => ts('Make PDF Letter'), + 'isDefault' => TRUE, + ), + array( + 'type' => 'cancel', + 'name' => ts('Done'), + 'js' => array('onclick' => "location.href='{$cancelURL}'; return false;"), + ), + ) + ); + } + } + else { + $form->addDefaultButtons(ts('Make PDF Letters')); + } + + $form->addFormRule(array('CRM_Contact_Form_Task_PDFLatexCommon', 'formRule'), $form); + } + + /** + * Set default values + */ + static function setDefaultValues() { + $defaultFormat = CRM_Core_BAO_PdfFormat::getDefaultValues(); + $defaultFormat['format_id'] = $defaultFormat['id']; + return $defaultFormat; + } + + /** + * form rule + * + * @param array $fields the input form values + * @param array $dontCare + * @param array $self additional values form 'this' + * + * @return true if no errors, else array of errors + * @access public + * + */ + static function formRule($fields, $dontCare, $self) { + $errors = array(); + $template = CRM_Core_Smarty::singleton(); + + //Added for CRM-1393 + if (CRM_Utils_Array::value('saveTemplate', $fields) && empty($fields['saveTemplateName'])) { + $errors['saveTemplateName'] = ts("Enter name to save message template"); + } + if (!is_numeric($fields['margin_left'])) { + $errors['margin_left'] = 'Margin must be numeric'; + } + if (!is_numeric($fields['margin_right'])) { + $errors['margin_right'] = 'Margin must be numeric'; + } + if (!is_numeric($fields['margin_top'])) { + $errors['margin_top'] = 'Margin must be numeric'; + } + if (!is_numeric($fields['margin_bottom'])) { + $errors['margin_bottom'] = 'Margin must be numeric'; + } + return empty($errors) ? TRUE : $errors; + } + + /** + * part of the post process which prepare and extract information from the template + * + * @access protected + * + * @return array( $categories, $html_message, $messageToken, $returnProperties ) + */ + static protected function processMessageTemplate(&$form) { + $formValues = $form->controller->exportValues($form->getName()); + + // process message template + if (CRM_Utils_Array::value('saveTemplate', $formValues) || CRM_Utils_Array::value('updateTemplate', $formValues)) { + $messageTemplate = array( + 'msg_text' => NULL, + 'msg_html' => $formValues['html_message'], + 'msg_subject' => NULL, + 'is_active' => TRUE, + ); + + $messageTemplate['pdf_format_id'] = 'null'; + if (CRM_Utils_Array::value('bind_format', $formValues) && $formValues['format_id'] > 0) { + $messageTemplate['pdf_format_id'] = $formValues['format_id']; + } + if (CRM_Utils_Array::value('saveTemplate', $formValues) && $formValues['saveTemplate']) { + $messageTemplate['msg_title'] = $formValues['saveTemplateName']; + CRM_Core_BAO_MessageTemplates::add($messageTemplate); + } + + if (CRM_Utils_Array::value('updateTemplate', $formValues) && $formValues['template'] && $formValues['updateTemplate']) { + $messageTemplate['id'] = $formValues['template']; + + unset($messageTemplate['msg_title']); + CRM_Core_BAO_MessageTemplates::add($messageTemplate); + } + } + elseif (CRM_Utils_Array::value('template', $formValues) > 0) { + if (CRM_Utils_Array::value('bind_format', $formValues) && $formValues['format_id'] > 0) { + $query = "UPDATE civicrm_msg_template SET pdf_format_id = {$formValues['format_id']} WHERE id = {$formValues['template']}"; + } + else { + $query = "UPDATE civicrm_msg_template SET pdf_format_id = NULL WHERE id = {$formValues['template']}"; + } + CRM_Core_DAO::executeQuery($query, CRM_Core_DAO::$_nullArray); + } + if (CRM_Utils_Array::value('update_format', $formValues)) { + $bao = new CRM_Core_BAO_PdfFormat(); + $bao->savePdfFormat($formValues, $formValues['format_id']); + } + + $html = array(); + + $tokens = array(); + CRM_Utils_Hook::tokens($tokens); + $categories = array_keys($tokens); + + $html_message = $formValues['html_message']; + + //time being hack to strip ' ' + //from particular letter line, CRM-6798 + self::formatMessage($html_message); + + $messageToken = CRM_Utils_Token::getTokens($html_message); + + $returnProperties = array(); + if (isset($messageToken['contact'])) { + foreach ($messageToken['contact'] as $key => $value) { + $returnProperties[$value] = 1; + } + } + + return array($formValues, $categories, $html_message, $messageToken, $returnProperties); + } + + /** + * process the form after the input has been submitted and validated + * + * @access public + * + * @return None + */ + static function postProcess(&$form) { + list($formValues, $categories, $html_message, $messageToken, $returnProperties) = self::processMessageTemplate($form); + + $skipOnHold = isset($form->skipOnHold) ? $form->skipOnHold : FALSE; + $skipDeceased = isset($form->skipDeceased) ? $form->skipDeceased : TRUE; + + foreach ($form->_contactIds as $item => $contactId) { + $params = array('contact_id' => $contactId); + + list($contact) = CRM_Utils_Token::getTokenDetails($params, + $returnProperties, + $skipOnHold, + $skipDeceased, + NULL, + $messageToken, + 'CRM_Contact_Form_Task_PDFLatexCommon' + ); + if (civicrm_error($contact)) { + $notSent[] = $contactId; + continue; + } + + $tokenHtml = CRM_Utils_Token::replaceContactTokens($html_message, $contact[$contactId], TRUE, $messageToken); + $tokenHtml = CRM_Utils_Token::replaceHookTokens($tokenHtml, $contact[$contactId], $categories, TRUE); + + if (defined('CIVICRM_MAIL_SMARTY') && CIVICRM_MAIL_SMARTY) { + $smarty = CRM_Core_Smarty::singleton(); + // also add the contact tokens to the template + $smarty->assign_by_ref('contact', $contact); + $tokenHtml = $smarty->fetch("string:$tokenHtml"); + } + + $html[] = $tokenHtml; + } + + self::createActivities($form, $html_message, $form->_contactIds); + + CRM_Utils_PDF_Utils::latex2pdf($html, "CiviLatex.pdf", FALSE, $formValues); + + $form->postProcessHook(); + + CRM_Utils_System::civiExit(1); + } + + function createActivities($form, $html_message, $contactIds) { + + $session = CRM_Core_Session::singleton(); + $userID = $session->get('userID'); + $activityTypeID = CRM_Core_OptionGroup::getValue('activity_type', + 'Print PDF LaTeX Letter', + 'name' + ); + $activityParams = array( + 'source_contact_id' => $userID, + 'activity_type_id' => $activityTypeID, + 'activity_date_time' => date('YmdHis'), + 'details' => $html_message, + ); + if (!empty($form->_activityId)) { + $activityParams += array('id' => $form->_activityId); + } + if ($form->_cid) { + $activity = CRM_Activity_BAO_Activity::create($activityParams); + } + else { + // create Print PDF activity for each selected contact. CRM-6886 + $activityIds = array(); + foreach ($contactIds as $contactId) { + $activityID = CRM_Activity_BAO_Activity::create($activityParams); + $activityIds[$contactId] = $activityID->id; + } + } + + foreach ($form->_contactIds as $contactId) { + $activityTargetParams = array( + 'activity_id' => empty($activity->id) ? $activityIds[$contactId] : $activity->id, + 'target_contact_id' => $contactId, + ); + CRM_Activity_BAO_Activity::createActivityTarget($activityTargetParams); + } + } + + function formatMessage(&$message) { + $newLineOperators = array( + 'p' => array( + 'oper' => '

', + 'pattern' => '/<(\s+)?p(\s+)?>/m', + ), + 'br' => array( + 'oper' => '
', + 'pattern' => '/<(\s+)?br(\s+)?\/>/m', + ), + ); + + $htmlMsg = preg_split($newLineOperators['p']['pattern'], $message); + foreach ($htmlMsg as $k => & $m) { + $messages = preg_split($newLineOperators['br']['pattern'], $m); + foreach ($messages as $key => & $msg) { + $msg = trim($msg); + $matches = array(); + if (preg_match('/^( )+/', $msg, $matches)) { + $spaceLen = strlen($matches[0]) / 6; + $trimMsg = ltrim($msg, '  '); + $charLen = strlen($trimMsg); + $totalLen = $charLen + $spaceLen; + if ($totalLen > 100) { + $spacesCount = 10; + if ($spaceLen > 50) { + $spacesCount = 20; + } + if ($charLen > 100) { + $spacesCount = 1; + } + $msg = str_repeat(' ', $spacesCount) . $trimMsg; + } + } + } + $m = implode($newLineOperators['br']['oper'], $messages); + } + $message = implode($newLineOperators['p']['oper'], $htmlMsg); + } +} + diff --git a/CRM/Contribute/Form/Task/PDFLatex.php b/CRM/Contribute/Form/Task/PDFLatex.php new file mode 100644 index 0000000000..f353e00c4e --- /dev/null +++ b/CRM/Contribute/Form/Task/PDFLatex.php @@ -0,0 +1,147 @@ +skipOnHold = $this->skipDeceased = FALSE; + CRM_Contact_Form_Task_PDFLetterCommon::preProcess($this); + + // store case id if present + $this->_caseId = CRM_Utils_Request::retrieve('caseid', 'Positive', $this, FALSE); + + // retrieve contact ID if this is 'single' mode + $cid = CRM_Utils_Request::retrieve('cid', 'Positive', $this, FALSE); + + $this->_activityId = CRM_Utils_Request::retrieve('id', 'Positive', $this, FALSE); + + if ($cid) { + CRM_Contact_Form_Task_PDFLetterCommon::preProcessSingle($this, $cid); + $this->_single = TRUE; + $this->_cid = $cid; + } + else { + parent::preProcess(); + } + $this->assign('single', $this->_single); + } + + function setDefaultValues() { + $defaults = array(); + if (isset($this->_activityId)) { + $params = array('id' => $this->_activityId); + CRM_Activity_BAO_Activity::retrieve($params, $defaults); + $defaults['html_message'] = $defaults['details']; + } + $defaults = $defaults + CRM_Contact_Form_Task_PDFLetterCommon::setDefaultValues(); + return $defaults; + } + + /** + * Build the form + * + * @access public + * + * @return void + */ + public function buildQuickForm() { + //enable form element + $this->assign('suppressForm', FALSE); + + // use contact form as a base + CRM_Contact_Form_Task_PDFLetterCommon::buildQuickForm($this); + + // specific need for contributions + $this->add('static', 'more_options_header', NULL, ts('Record Update Options')); + $this->add('checkbox', 'receipt_update', ts('Update receipt dates for these contributions'), FALSE); + $this->add('checkbox', 'thankyou_update', ts('Update thank-you dates for these contributions'), FALSE); + + // Group options for tokens are not yet implemented. dgg + $options = array(ts('Contact'), ts('Recurring')); + $this->addRadio('is_group_by', ts('Grouping contributions in one letter based on'), $options, array(), "
", FALSE); + + $this->addButtons(array( + array( + 'type' => 'submit', + 'name' => ts('Make Thank-you Letters'), + 'isDefault' => TRUE, + ), + array( + 'type' => 'cancel', + 'name' => ts('Done'), + ), + ) + ); + + } + + /** + * process the form after the input has been submitted and validated + * + * @access public + * + * @return None + */ + public function postProcess() { + // TODO: rewrite using contribution token and one letter by contribution + $this->setContactIDs(); + + CRM_Contribute_Form_Task_PDFLatexCommon::postProcess($this); + } + + +} + diff --git a/CRM/Contribute/Form/Task/PDFLatexCommon.php b/CRM/Contribute/Form/Task/PDFLatexCommon.php new file mode 100644 index 0000000000..862b03f279 --- /dev/null +++ b/CRM/Contribute/Form/Task/PDFLatexCommon.php @@ -0,0 +1,116 @@ +skipOnHold) ? $form->skipOnHold : FALSE; + $skipDeceased = isset($form->skipDeceased) ? $form->skipDeceased : TRUE; + + foreach ($form->getVar('_contributionIds') as $item => $contributionId) { + + // get contact information + $contactId = civicrm_api("Contribution", "getvalue", array('version' => '3', 'id' => $contributionId, 'return' => 'contact_id')); + $params = array('contact_id' => $contactId); + + list($contact) = CRM_Utils_Token::getTokenDetails($params, + $returnProperties, + $skipOnHold, + $skipDeceased, + NULL, + $messageToken, + 'CRM_Contribution_Form_Task_PDFLetterCommon' + ); + if (civicrm_error($contact)) { + $notSent[] = $contributionId; + continue; + } + + // get contribution information + $params = array('contribution_id' => $contributionId); + $contribution = CRM_Utils_Token::getContributionTokenDetails($params, + $returnProperties, + NULL, + $messageToken, + 'CRM_Contribution_Form_Task_PDFLetterCommon' + ); + if (civicrm_error($contribution)) { + $notSent[] = $contributionId; + continue; + } + + $tokenHtml = CRM_Utils_Token::replaceContactTokens($html_message, $contact[$contactId], FALSE, $messageToken); + $tokenHtml = CRM_Utils_Token::replaceContributionTokens($tokenHtml, $contribution[$contributionId], TRUE, $messageToken); + $tokenHtml = CRM_Utils_Token::replaceHookTokens($tokenHtml, $contact[$contactId], $categories, TRUE); + + if (defined('CIVICRM_MAIL_SMARTY') && CIVICRM_MAIL_SMARTY) { + $smarty = CRM_Core_Smarty::singleton(); + // also add the tokens to the template + $smarty->assign_by_ref('contact', $contact); + $tokenHtml = $smarty->fetch("string:$tokenHtml"); + } + + $html[] = $tokenHtml; + + // update dates (do it for each contribution including grouped recurring contribution) + if ($receipt_update) { + $result = CRM_Core_DAO::setFieldValue('CRM_Contribute_DAO_Contribution', $contributionId, 'receipt_date', $nowDate); + // We can't use CRM_Core_Error::fatal here because the api error elevates the exception level. FIXME. dgg + if ($result) { + $receipts++; + } + } + if ($thankyou_update) { + $result = CRM_Core_DAO::setFieldValue('CRM_Contribute_DAO_Contribution', $contributionId, 'thankyou_date', $nowDate); + // We can't use CRM_Core_Error::fatal here because the api error elevates the exception level. FIXME. dgg + if ($result) { + $thanks++; + } + } + } + + self::createActivities($form, $html_message, $form->_contactIds); + + CRM_Utils_PDF_Utils::latex2pdf($html, "CiviLatex.pdf", FALSE, $formValues); + + $form->postProcessHook(); + + if ($receipts) { + $updateStatus = ts('Receipt date has been updated for %1 contributions.', array(1 => $receipts)); + } + if ($thanks) { + $updateStatus .= ' ' . ts('Thank-you date has been updated for %1 contributions.', array(1 => $thanks)); + } + + if ($updateStatus) { + CRM_Core_Session::setStatus($updateStatus); + } + + CRM_Utils_System::civiExit(1); + } + //end of function +} + diff --git a/CRM/Core/Payment/TrustCommerce.php b/CRM/Core/Payment/TrustCommerce.php new file mode 100644 index 0000000000..534bc8fde6 --- /dev/null +++ b/CRM/Core/Payment/TrustCommerce.php @@ -0,0 +1,467 @@ + (http://www.fsf.org) + * + */ + +require_once 'CRM/Core/Payment.php'; +class CRM_Core_Payment_TrustCommerce extends CRM_Core_Payment { + CONST CHARSET = 'iso-8859-1'; + CONST AUTH_APPROVED = 'approve'; + CONST AUTH_DECLINED = 'decline'; + CONST AUTH_BADDATA = 'baddata'; + CONST AUTH_ERROR = 'error'; + + static protected $_mode = NULL; + + static protected $_params = array(); + + /** + * We only need one instance of this object. So we use the singleton + * pattern and cache the instance in this variable + * + * @var object + * @static + */ + static private $_singleton = NULL; + + /** + * Constructor + * + * @param string $mode the mode of operation: live or test + * + * @return void + */ function __construct($mode, &$paymentProcessor) { + $this->_mode = $mode; + + $this->_paymentProcessor = $paymentProcessor; + + $this->_processorName = ts('TrustCommerce'); + + $config = CRM_Core_Config::singleton(); + $this->_setParam('user_name', $paymentProcessor['user_name']); + $this->_setParam('password', $paymentProcessor['password']); + + $this->_setParam('timestamp', time()); + srand(time()); + $this->_setParam('sequence', rand(1, 1000)); + } + + /** + * singleton function used to manage this object + * + * @param string $mode the mode of operation: live or test + * + * @return object + * @static + * + */ + static + function &singleton($mode, &$paymentProcessor) { + $processorName = $paymentProcessor['name']; + if (self::$_singleton[$processorName] === NULL) { + self::$_singleton[$processorName] = new CRM_Core_Payment_TrustCommerce($mode, $paymentProcessor); + } + return self::$_singleton[$processorName]; + } + + /** + * Submit a payment using Advanced Integration Method + * + * @param array $params assoc array of input parameters for this transaction + * + * @return array the result in a nice formatted array (or an error object) + * @public + */ + function doDirectPayment(&$params) { + if (!extension_loaded("tclink")) { + return self::error(9001, 'TrustCommerce requires that the tclink module is loaded'); + } + + /* + * recurpayment function does not compile an array & then proces it - + * - the tpl does the transformation so adding call to hook here + * & giving it a change to act on the params array + */ + + $newParams = $params; + if (CRM_Utils_Array::value('is_recur', $params) && + $params['contributionRecurID'] + ) { + CRM_Utils_Hook::alterPaymentProcessorParams($this, + $params, + $newParams + ); + } + foreach ($newParams as $field => $value) { + $this->_setParam($field, $value); + } + + if (CRM_Utils_Array::value('is_recur', $params) && + $params['contributionRecurID'] + ) { + return $this->doRecurPayment($params); + } + + $postFields = array(); + $tclink = $this->_getTrustCommerceFields(); + + // Set up our call for hook_civicrm_paymentProcessor, + // since we now have our parameters as assigned for the AIM back end. + CRM_Utils_Hook::alterPaymentProcessorParams($this, + $params, + $tclink + ); + + // TrustCommerce will not refuse duplicates, so we should check if the user already submitted this transaction + if ($this->_checkDupe($tclink['ticket'])) { + return self::error(9004, 'It appears that this transaction is a duplicate. Have you already submitted the form once? If so there may have been a connection problem. You can try your transaction again. If you continue to have problems please contact the site administrator.'); + } + + $result = tclink_send($tclink); + + if (!$result) { + return self::error(9002, 'Could not initiate connection to payment gateway'); + } + + foreach ($result as $field => $value) { + error_log("result: $field => $value"); + } + + switch($result['status']) { + case self::AUTH_APPROVED: + // It's all good + break; + case self::AUTH_DECLINED: + // TODO FIXME be more or less specific? + // declinetype can be: decline, avs, cvv, call, expiredcard, carderror, authexpired, fraud, blacklist, velocity + // See TC documentation for more info + return self::error(9009, "Your transaction was declined: {$result['declinetype']}"); + break; + case self::AUTH_BADDATA: + // TODO FIXME do something with $result['error'] and $result['offender'] + return self::error(9011, "Invalid credit card information. Please re-enter."); + break; + case self::AUTH_ERROR: + return self::error(9002, 'Could not initiate connection to payment gateway'); + break; + } + + // Success + + $params['trxn_id'] = $result['transid']; + $params['gross_amount'] = $tclink['amount'] / 100; + + return $params; + } + + /** + * Submit an Automated Recurring Billing subscription + * + * @param array $params assoc array of input parameters for this transaction + * + * @return array the result in a nice formatted array (or an error object) + * @public + */ + function doRecurPayment(&$params) { + $template = CRM_Core_Smarty::singleton(); + + $intervalLength = $this->_getParam('frequency_interval'); + $intervalUnit = $this->_getParam('frequency_unit'); + if ($intervalUnit == 'week') { + $intervalLength *= 7; + $intervalUnit = 'days'; + } + elseif ($intervalUnit == 'year') { + $intervalLength *= 12; + $intervalUnit = 'months'; + } + elseif ($intervalUnit == 'day') { + $intervalUnit = 'days'; + } + elseif ($intervalUnit == 'month') { + $intervalUnit = 'months'; + } + + // interval cannot be less than 7 days or more than 1 year + if ($intervalUnit == 'days') { + if ($intervalLength < 7) { + return self::error(9001, 'Payment interval must be at least one week'); + } + elseif ($intervalLength > 365) { + return self::error(9001, 'Payment interval may not be longer than one year'); + } + } + elseif ($intervalUnit == 'months') { + if ($intervalLength < 1) { + return self::error(9001, 'Payment interval must be at least one week'); + } + elseif ($intervalLength > 12) { + return self::error(9001, 'Payment interval may not be longer than one year'); + } + } + + $template->assign('intervalLength', $intervalLength); + $template->assign('intervalUnit', $intervalUnit); + + $template->assign('apiLogin', $this->_getParam('apiLogin')); + $template->assign('paymentKey', $this->_getParam('paymentKey')); + $template->assign('refId', substr($this->_getParam('invoiceID'), 0, 20)); + + //for recurring, carry first contribution id + $template->assign('invoiceNumber', $this->_getParam('contributionID')); + $firstPaymentDate = $this->_getParam('receive_date'); + if (!empty($firstPaymentDate)) { + //allow for post dated payment if set in form + $template->assign('startDate', date('Y-m-d', strtotime($firstPaymentDate))); + } + else { + $template->assign('startDate', date('Y-m-d')); + } + // for open ended subscription totalOccurrences has to be 9999 + $installments = $this->_getParam('installments'); + $template->assign('totalOccurrences', $installments ? $installments : 9999); + + $template->assign('amount', $this->_getParam('amount')); + + $template->assign('cardNumber', $this->_getParam('credit_card_number')); + $exp_month = str_pad($this->_getParam('month'), 2, '0', STR_PAD_LEFT); + $exp_year = $this->_getParam('year'); + $template->assign('expirationDate', $exp_year . '-' . $exp_month); + // name rather than description is used in the tpl - see http://www.authorize.net/support/ARB_guide.pdf + $template->assign('name', $this->_getParam('description')); + + $template->assign('email', $this->_getParam('email')); + $template->assign('contactID', $this->_getParam('contactID')); + $template->assign('billingFirstName', $this->_getParam('billing_first_name')); + $template->assign('billingLastName', $this->_getParam('billing_last_name')); + $template->assign('billingAddress', $this->_getParam('street_address')); + $template->assign('billingCity', $this->_getParam('city')); + $template->assign('billingState', $this->_getParam('state_province')); + $template->assign('billingZip', $this->_getParam('postal_code')); + $template->assign('billingCountry', $this->_getParam('country')); + + $arbXML = $template->fetch('CRM/Contribute/Form/Contribution/AuthorizeNetARB.tpl'); + // submit to authorize.net + + $submit = curl_init($this->_paymentProcessor['url_recur']); + if (!$submit) { + return self::error(9002, 'Could not initiate connection to payment gateway'); + } + curl_setopt($submit, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($submit, CURLOPT_HTTPHEADER, array("Content-Type: text/xml")); + curl_setopt($submit, CURLOPT_HEADER, 1); + curl_setopt($submit, CURLOPT_POSTFIELDS, $arbXML); + curl_setopt($submit, CURLOPT_POST, 1); + curl_setopt($submit, CURLOPT_SSL_VERIFYPEER, 0); + + $response = curl_exec($submit); + + if (!$response) { + return self::error(curl_errno($submit), curl_error($submit)); + } + + curl_close($submit); + $responseFields = $this->_ParseArbReturn($response); + + if ($responseFields['resultCode'] == 'Error') { + return self::error($responseFields['code'], $responseFields['text']); + } + + // update recur processor_id with subscriptionId + CRM_Core_DAO::setFieldValue('CRM_Contribute_DAO_ContributionRecur', $params['contributionRecurID'], + 'processor_id', $responseFields['subscriptionId'] + ); + //only impact of assigning this here is is can be used to cancel the subscription in an automated test + // if it isn't cancelled a duplicate transaction error occurs + if (CRM_Utils_Array::value('subscriptionId', $responseFields)) { + $this->_setParam('subscriptionId', $responseFields['subscriptionId']); + } + return $params; + } + + function _getTrustCommerceFields() { + // Total amount is from the form contribution field + $amount = $this->_getParam('total_amount'); + // CRM-9894 would this ever be the case?? + if (empty($amount)) { + $amount = $this->_getParam('amount'); + } + $fields = array(); + $fields['custid'] = $this->_getParam('user_name'); + $fields['password'] = $this->_getParam('password'); + $fields['action'] = 'sale'; + + // Enable address verification + $fields['avs'] = 'y'; + + $fields['address1'] = $this->_getParam('street_address'); + $fields['zip'] = $this->_getParam('postal_code'); + + $fields['name'] = $this->_getParam('billing_first_name') . ' ' . $this->_getParam('billing_last_name'); + + // We need to pass the amount to TrustCommerce in dollar cents + $fields['amount'] = $amount * 100; + + // Unique identifier + $fields['ticket'] = substr($this->_getParam('invoiceID'), 0, 20); + + // cc info + $fields['cc'] = $this->_getParam('credit_card_number'); + $fields['cvv'] = $this->_getParam('cvv2'); + $exp_month = str_pad($this->_getParam('month'), 2, '0', STR_PAD_LEFT); + $exp_year = substr($this->_getParam('year'),-2); + $fields['exp'] = "$exp_month$exp_year"; + + if ($this->_mode != 'live') { + $fields['demo'] = 'y'; + } + // TODO FIXME remove + foreach ($fields as $field => $value) { + if ($field == 'custid') $value = '********'; + if ($field == 'password') $value = '********'; + error_log("fields: $field => $value"); + } + + return $fields; + } + + /** + * Checks to see if invoice_id already exists in db + * + * @param int $invoiceId The ID to check + * + * @return bool True if ID exists, else false + */ + function _checkDupe($invoiceId) { + require_once 'CRM/Contribute/DAO/Contribution.php'; + $contribution = new CRM_Contribute_DAO_Contribution(); + $contribution->invoice_id = $invoiceId; + return $contribution->find(); + } + + /** + * Get the value of a field if set + * + * @param string $field the field + * + * @return mixed value of the field, or empty string if the field is + * not set + */ + function _getParam($field) { + return CRM_Utils_Array::value($field, $this->_params, ''); + } + + function &error($errorCode = NULL, $errorMessage = NULL) { + $e = CRM_Core_Error::singleton(); + if ($errorCode) { + $e->push($errorCode, 0, NULL, $errorMessage); + } + else { + $e->push(9001, 0, NULL, 'Unknown System Error.'); + } + return $e; + } + + /** + * Set a field to the specified value. Value must be a scalar (int, + * float, string, or boolean) + * + * @param string $field + * @param mixed $value + * + * @return bool false if value is not a scalar, true if successful + */ + function _setParam($field, $value) { + if (!is_scalar($value)) { + return FALSE; + } + else { + $this->_params[$field] = $value; + } + } + + /** + * This function checks to see if we have the right config values + * + * @return string the error message if any + * @public + */ + function checkConfig() { + $error = array(); + if (empty($this->_paymentProcessor['user_name'])) { + $error[] = ts('Customer ID is not set for this payment processor'); + } + + if (empty($this->_paymentProcessor['password'])) { + $error[] = ts('Password is not set for this payment processor'); + } + + if (!empty($error)) { + return implode('

', $error); + } + else { + return NULL; + } + } + + function cancelSubscriptionURL($entityID = NULL, $entity = NULL) { + if ($entityID && $entity == 'membership') { + require_once 'CRM/Contact/BAO/Contact/Utils.php'; + $contactID = CRM_Core_DAO::getFieldValue("CRM_Member_DAO_Membership", $entityID, "contact_id"); + $checksumValue = CRM_Contact_BAO_Contact_Utils::generateChecksum($contactID, NULL, 'inf'); + + return CRM_Utils_System::url('civicrm/contribute/unsubscribe', + "reset=1&mid={$entityID}&cs={$checksumValue}", TRUE, NULL, FALSE, FALSE + ); + } + + return ($this->_mode == 'test') ? 'https://test.authorize.net' : 'https://authorize.net'; + } + + function cancelSubscription() { + $template = CRM_Core_Smarty::singleton(); + + $template->assign('subscriptionType', 'cancel'); + + $template->assign('apiLogin', $this->_getParam('apiLogin')); + $template->assign('paymentKey', $this->_getParam('paymentKey')); + $template->assign('subscriptionId', $this->_getParam('subscriptionId')); + + $arbXML = $template->fetch('CRM/Contribute/Form/Contribution/AuthorizeNetARB.tpl'); + + // submit to authorize.net + $submit = curl_init($this->_paymentProcessor['url_recur']); + if (!$submit) { + return self::error(9002, 'Could not initiate connection to payment gateway'); + } + + curl_setopt($submit, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($submit, CURLOPT_HTTPHEADER, array("Content-Type: text/xml")); + curl_setopt($submit, CURLOPT_HEADER, 1); + curl_setopt($submit, CURLOPT_POSTFIELDS, $arbXML); + curl_setopt($submit, CURLOPT_POST, 1); + curl_setopt($submit, CURLOPT_SSL_VERIFYPEER, 0); + + $response = curl_exec($submit); + + if (!$response) { + return self::error(curl_errno($submit), curl_error($submit)); + } + + curl_close($submit); + + $responseFields = $this->_ParseArbReturn($response); + + if ($responseFields['resultCode'] == 'Error') { + return self::error($responseFields['code'], $responseFields['text']); + } + + // carry on cancelation procedure + return TRUE; + } +} + diff --git a/CRM/Core/Payment/insert_tc.sql b/CRM/Core/Payment/insert_tc.sql new file mode 100644 index 0000000000..3bbd1e55b8 --- /dev/null +++ b/CRM/Core/Payment/insert_tc.sql @@ -0,0 +1,7 @@ + INSERT INTO civicrm_payment_processor_type + (name, title, description, is_active, is_default, user_name_label, password_label, signature_label, subject_label, class_name, url_site_default, url_recur_default, url_button_default, url_site_test_default, url_recur_test_default, url_button_test_default, billing_mode, is_recur ) + VALUES + ('TrustCommerce','TrustCommerce',NULL,1,0,'Customer ID','Password',NULL,NULL,'Payment_TrustCommerce',NULL,NULL,NULL,NULL,NULL,NULL,1,NULL); + + + diff --git a/i/mini_cvv2.gif b/i/mini_cvv2.gif new file mode 100644 index 0000000000000000000000000000000000000000..c3d6a8dd99761bd718ddf849b5829ad22fad152e GIT binary patch literal 509 zcmZ?wbhEHbG-i-zxT?+Y{rmT;SFi5ab8yFmdLBg^M(1PguNs#iXTk=dWBhbG7!o^;@QItgYXfvVGUy#69~`lnx&` zdL;gU=Bd+X&YnB3bpDLei8-6% |x-nw)5{_R`0PhEU;@A(z2lQ&O2yz}_Y#H*BY!(h>}v$HLVU){+JKHM(FU7R3f5wK{*#l;?zwPLfr RFf?*{E%KV%rNY5r4FCzS1}^{r literal 0 HcmV?d00001 diff --git a/latex.patch b/latex.patch new file mode 100644 index 0000000000..4a59aa2461 --- /dev/null +++ b/latex.patch @@ -0,0 +1,764 @@ +diff --git a/CRM/Contribute/Form/Task/PDFLatex.php b/CRM/Contribute/Form/Task/PDFLatex.php +new file mode 100644 +index 0000000..f353e00 +--- /dev/null ++++ b/CRM/Contribute/Form/Task/PDFLatex.php +@@ -0,0 +1,147 @@ ++skipOnHold = $this->skipDeceased = FALSE; ++ CRM_Contact_Form_Task_PDFLetterCommon::preProcess($this); ++ ++ // store case id if present ++ $this->_caseId = CRM_Utils_Request::retrieve('caseid', 'Positive', $this, FALSE); ++ ++ // retrieve contact ID if this is 'single' mode ++ $cid = CRM_Utils_Request::retrieve('cid', 'Positive', $this, FALSE); ++ ++ $this->_activityId = CRM_Utils_Request::retrieve('id', 'Positive', $this, FALSE); ++ ++ if ($cid) { ++ CRM_Contact_Form_Task_PDFLetterCommon::preProcessSingle($this, $cid); ++ $this->_single = TRUE; ++ $this->_cid = $cid; ++ } ++ else { ++ parent::preProcess(); ++ } ++ $this->assign('single', $this->_single); ++ } ++ ++ function setDefaultValues() { ++ $defaults = array(); ++ if (isset($this->_activityId)) { ++ $params = array('id' => $this->_activityId); ++ CRM_Activity_BAO_Activity::retrieve($params, $defaults); ++ $defaults['html_message'] = $defaults['details']; ++ } ++ $defaults = $defaults + CRM_Contact_Form_Task_PDFLetterCommon::setDefaultValues(); ++ return $defaults; ++ } ++ ++ /** ++ * Build the form ++ * ++ * @access public ++ * ++ * @return void ++ */ ++ public function buildQuickForm() { ++ //enable form element ++ $this->assign('suppressForm', FALSE); ++ ++ // use contact form as a base ++ CRM_Contact_Form_Task_PDFLetterCommon::buildQuickForm($this); ++ ++ // specific need for contributions ++ $this->add('static', 'more_options_header', NULL, ts('Record Update Options')); ++ $this->add('checkbox', 'receipt_update', ts('Update receipt dates for these contributions'), FALSE); ++ $this->add('checkbox', 'thankyou_update', ts('Update thank-you dates for these contributions'), FALSE); ++ ++ // Group options for tokens are not yet implemented. dgg ++ $options = array(ts('Contact'), ts('Recurring')); ++ $this->addRadio('is_group_by', ts('Grouping contributions in one letter based on'), $options, array(), "
", FALSE); ++ ++ $this->addButtons(array( ++ array( ++ 'type' => 'submit', ++ 'name' => ts('Make Thank-you Letters'), ++ 'isDefault' => TRUE, ++ ), ++ array( ++ 'type' => 'cancel', ++ 'name' => ts('Done'), ++ ), ++ ) ++ ); ++ ++ } ++ ++ /** ++ * process the form after the input has been submitted and validated ++ * ++ * @access public ++ * ++ * @return None ++ */ ++ public function postProcess() { ++ // TODO: rewrite using contribution token and one letter by contribution ++ $this->setContactIDs(); ++ ++ CRM_Contribute_Form_Task_PDFLatexCommon::postProcess($this); ++ } ++ ++ ++} ++ +diff --git a/CRM/Contribute/Form/Task/PDFLatexCommon.php b/CRM/Contribute/Form/Task/PDFLatexCommon.php +new file mode 100644 +index 0000000..862b03f +--- /dev/null ++++ b/CRM/Contribute/Form/Task/PDFLatexCommon.php +@@ -0,0 +1,116 @@ ++skipOnHold) ? $form->skipOnHold : FALSE; ++ $skipDeceased = isset($form->skipDeceased) ? $form->skipDeceased : TRUE; ++ ++ foreach ($form->getVar('_contributionIds') as $item => $contributionId) { ++ ++ // get contact information ++ $contactId = civicrm_api("Contribution", "getvalue", array('version' => '3', 'id' => $contributionId, 'return' => 'contact_id')); ++ $params = array('contact_id' => $contactId); ++ ++ list($contact) = CRM_Utils_Token::getTokenDetails($params, ++ $returnProperties, ++ $skipOnHold, ++ $skipDeceased, ++ NULL, ++ $messageToken, ++ 'CRM_Contribution_Form_Task_PDFLetterCommon' ++ ); ++ if (civicrm_error($contact)) { ++ $notSent[] = $contributionId; ++ continue; ++ } ++ ++ // get contribution information ++ $params = array('contribution_id' => $contributionId); ++ $contribution = CRM_Utils_Token::getContributionTokenDetails($params, ++ $returnProperties, ++ NULL, ++ $messageToken, ++ 'CRM_Contribution_Form_Task_PDFLetterCommon' ++ ); ++ if (civicrm_error($contribution)) { ++ $notSent[] = $contributionId; ++ continue; ++ } ++ ++ $tokenHtml = CRM_Utils_Token::replaceContactTokens($html_message, $contact[$contactId], FALSE, $messageToken); ++ $tokenHtml = CRM_Utils_Token::replaceContributionTokens($tokenHtml, $contribution[$contributionId], TRUE, $messageToken); ++ $tokenHtml = CRM_Utils_Token::replaceHookTokens($tokenHtml, $contact[$contactId], $categories, TRUE); ++ ++ if (defined('CIVICRM_MAIL_SMARTY') && CIVICRM_MAIL_SMARTY) { ++ $smarty = CRM_Core_Smarty::singleton(); ++ // also add the tokens to the template ++ $smarty->assign_by_ref('contact', $contact); ++ $tokenHtml = $smarty->fetch("string:$tokenHtml"); ++ } ++ ++ $html[] = $tokenHtml; ++ ++ // update dates (do it for each contribution including grouped recurring contribution) ++ if ($receipt_update) { ++ $result = CRM_Core_DAO::setFieldValue('CRM_Contribute_DAO_Contribution', $contributionId, 'receipt_date', $nowDate); ++ // We can't use CRM_Core_Error::fatal here because the api error elevates the exception level. FIXME. dgg ++ if ($result) { ++ $receipts++; ++ } ++ } ++ if ($thankyou_update) { ++ $result = CRM_Core_DAO::setFieldValue('CRM_Contribute_DAO_Contribution', $contributionId, 'thankyou_date', $nowDate); ++ // We can't use CRM_Core_Error::fatal here because the api error elevates the exception level. FIXME. dgg ++ if ($result) { ++ $thanks++; ++ } ++ } ++ } ++ ++ self::createActivities($form, $html_message, $form->_contactIds); ++ ++ CRM_Utils_PDF_Utils::latex2pdf($html, "CiviLatex.pdf", FALSE, $formValues); ++ ++ $form->postProcessHook(); ++ ++ if ($receipts) { ++ $updateStatus = ts('Receipt date has been updated for %1 contributions.', array(1 => $receipts)); ++ } ++ if ($thanks) { ++ $updateStatus .= ' ' . ts('Thank-you date has been updated for %1 contributions.', array(1 => $thanks)); ++ } ++ ++ if ($updateStatus) { ++ CRM_Core_Session::setStatus($updateStatus); ++ } ++ ++ CRM_Utils_System::civiExit(1); ++ } ++ //end of function ++} ++ +diff --git a/CRM/Contribute/Task.php b/CRM/Contribute/Task.php +index 987b280..129cb45 100644 +--- a/CRM/Contribute/Task.php ++++ b/CRM/Contribute/Task.php +@@ -39,7 +39,7 @@ + * + */ + class CRM_Contribute_Task { +- CONST DELETE_CONTRIBUTIONS = 1, PRINT_CONTRIBUTIONS = 2, EXPORT_CONTRIBUTIONS = 3, BATCH_CONTRIBUTIONS = 4, EMAIL_CONTACTS = 5, UPDATE_STATUS = 6, PDF_RECEIPT = 7; ++ CONST DELETE_CONTRIBUTIONS = 1, PRINT_CONTRIBUTIONS = 2, EXPORT_CONTRIBUTIONS = 3, BATCH_CONTRIBUTIONS = 4, EMAIL_CONTACTS = 5, UPDATE_STATUS = 6, PDF_RECEIPT = 7, LATEX_TEST = 9; + + /** + * the task array +@@ -106,6 +106,10 @@ static function &tasks() { + 'class' => 'CRM_Contribute_Form_Task_PDFLetter', + 'result' => FALSE, + ), ++ 9 => array('title' => ts('Latex Letters for Contributions'), ++ 'class' => 'CRM_Contribute_Form_Task_PDFLatex', ++ 'result' => FALSE, ++ ), + ); + + //CRM-4418, check for delete +diff --git a/CRM/Utils/PDF/Utils.php b/CRM/Utils/PDF/Utils.php +index 72d4880..e9d59b9 100644 +--- a/CRM/Utils/PDF/Utils.php ++++ b/CRM/Utils/PDF/Utils.php +@@ -34,6 +34,69 @@ + */ + class CRM_Utils_PDF_Utils { + ++ static function latex2pdf(&$text, $fileName = 'civicrm.pdf', $output = FALSE, $pdfFormat = NULL) { ++ /* FIXME: get $paper_size, $orientation, $margins */ ++ ++ if (is_array($text)) { ++ $pages = &$text; ++ } ++ else { ++ $pages = array($text); ++ } ++ ++ ++ $head='\documentclass[12pt]{letter} ++\oddsidemargin 0in ++\evensidemargin 0in ++\textwidth 6.5in ++ ++\topmargin -.25in ++\textheight 8.15in ++ ++\address{\vspace{0.354in}} ++ ++\begin{document} ++ ++'; ++ $footer=' ++\end{document}'; ++ ++ $latex = $head; ++ foreach ($pages as $page) { ++ $latex.=$page; ++ } ++ $latex.=$footer; ++ ++ $descriptorspec = array( ++ 0 => array("pipe", "r"), ++ 1 => array("pipe", "w") ++ ); ++ ++ ++ ++ $process = proc_open("/usr/local/bin/pdflatex_wrapper.sh", $descriptorspec, $pipes); ++ ++ ++ if (is_resource($process)) { ++ fwrite($pipes[0], $latex); ++ fclose($pipes[0]); ++ ++ $pdf = stream_get_contents($pipes[1]); ++ fclose($pipes[1]); ++ } else { ++ CRM_Core_Error::debug_log_message("ERROR creating PDF. Check /tmp/pdflatex_*"); ++ } ++ ++ if ($output) { ++ return $pdf; ++ } ++ else { ++ header('Content-Type: application/pdf'); ++ header('Content-Disposition: attachment; filename="' . $fileName . '"'); ++ echo $pdf; ++ } ++ } ++ + static function html2pdf(&$text, $fileName = 'civicrm.pdf', $output = FALSE, $pdfFormat = NULL) { + if (is_array($text)) { + $pages = &$text; +diff --git a/CRM/Utils/Token.php b/CRM/Utils/Token.php +index 28ca941..e8df124 100644 +--- a/CRM/Utils/Token.php ++++ b/CRM/Utils/Token.php +@@ -619,7 +619,10 @@ function ($matches) use(&$contact, $html, $returnBlankToken, $escapeSmarty) { + $str + ); + +- $str = preg_replace('/\\\\|\{(\s*)?\}/', ' ', $str); ++ // 2013-08-31 nico@fsf.org this replacement is stripping all the '{' and '}' from the LaTeX files ++ // maybe it got solved at some point. maybe it has undesired collateral effects. I'm bugging the ++ // CiviCRM community to take a look at this pull request. ++ //$str = preg_replace('/\\\\|\{(\s*)?\}/', ' ', $str); + return $str; + } + +diff --git a/templates/CRM/Contact/Form/Task/PDFLatexCommon.tpl b/templates/CRM/Contact/Form/Task/PDFLatexCommon.tpl +new file mode 100644 +index 0000000..1f75f97 +--- /dev/null ++++ b/templates/CRM/Contact/Form/Task/PDFLatexCommon.tpl +@@ -0,0 +1,312 @@ ++{* ++ +--------------------------------------------------------------------+ ++ | CiviCRM version 4.4 | ++ +--------------------------------------------------------------------+ ++ | Copyright CiviCRM LLC (c) 2004-2013 | ++ +--------------------------------------------------------------------+ ++ | This file is a part of CiviCRM. | ++ | | ++ | CiviCRM is free software; you can copy, modify, and distribute it | ++ | under the terms of the GNU Affero General Public License | ++ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | ++ | | ++ | CiviCRM is distributed in the hope that it will be useful, but | ++ | WITHOUT ANY WARRANTY; without even the implied warranty of | ++ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ++ | See the GNU Affero General Public License for more details. | ++ | | ++ | You should have received a copy of the GNU Affero General Public | ++ | License and the CiviCRM Licensing Exception along | ++ | with this program; if not, contact CiviCRM LLC | ++ | at info[AT]civicrm[DOT]org. If you have questions about the | ++ | GNU Affero General Public License or the licensing of CiviCRM, | ++ | see the CiviCRM license FAQ at http://civicrm.org/licensing | ++ +--------------------------------------------------------------------+ ++*} ++{*common template for compose PDF letters*} ++{if $form.template.html} ++ ++ ++ ++ ++ ++
{$form.template.label}{$form.template.html}
++{/if} ++ ++

++ ++
++
++ {$form.html_message.label} ++
++
++ {if $action neq 4} ++ ++ {$form.token1.label} ++ {help id="id-token-html" file="CRM/Contact/Form/Task/Email.hlp" tplFile=$tplFile isAdmin=$isAdmin editor=$editor} ++ ++ ++ {/if} ++
++
++ {if $editor EQ 'textarea'} ++
{ts}The content of this page should be LaTeX.{/ts}
++ {/if} ++ {$form.html_message.html}
++
++ ++
++
++ {$form.updateTemplate.html} {$form.updateTemplate.label} ++
++
++ {$form.saveTemplate.html} {$form.saveTemplate.label} ++
++
++ ++
++
{$form.saveTemplateName.label}
++
{$form.saveTemplateName.html|crmAddClass:huge}
++
++ ++
++
++ ++{include file="CRM/Mailing/Form/InsertTokens.tpl"} ++ ++{literal} ++ ++{/literal} ++ +diff --git a/templates/CRM/Contribute/Form/Task/PDFLatex.tpl b/templates/CRM/Contribute/Form/Task/PDFLatex.tpl +new file mode 100644 +index 0000000..a7fb259 +--- /dev/null ++++ b/templates/CRM/Contribute/Form/Task/PDFLatex.tpl +@@ -0,0 +1,48 @@ ++{* ++ +--------------------------------------------------------------------+ ++ | CiviCRM version 4.4 | ++ +--------------------------------------------------------------------+ ++ | Copyright CiviCRM LLC (c) 2004-2013 | ++ +--------------------------------------------------------------------+ ++ | This file is a part of CiviCRM. | ++ | | ++ | CiviCRM is free software; you can copy, modify, and distribute it | ++ | under the terms of the GNU Affero General Public License | ++ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | ++ | | ++ | CiviCRM is distributed in the hope that it will be useful, but | ++ | WITHOUT ANY WARRANTY; without even the implied warranty of | ++ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ++ | See the GNU Affero General Public License for more details. | ++ | | ++ | You should have received a copy of the GNU Affero General Public | ++ | License and the CiviCRM Licensing Exception along | ++ | with this program; if not, contact CiviCRM LLC | ++ | at info[AT]civicrm[DOT]org. If you have questions about the | ++ | GNU Affero General Public License or the licensing of CiviCRM, | ++ | see the CiviCRM license FAQ at http://civicrm.org/licensing | ++ +--------------------------------------------------------------------+ ++*} ++
++

{ts}Thank-you Letter In Latex for Contributions (PDF){/ts}

++{if $single eq false} ++
{include file="CRM/Contribute/Form/Task.tpl"}
++{/if} ++ ++
++
++ {$form.more_options_header.html} ++
++
++ ++ ++ ++ ++
{$form.thankyou_update.html} {$form.thankyou_update.label}
{$form.receipt_update.html} {$form.receipt_update.label}
++
++
++ ++{include file="CRM/Contact/Form/Task/PDFLatexCommon.tpl"} ++ ++
{include file="CRM/common/formButtons.tpl" location="bottom"}
++
+-- +1.8.4 + diff --git a/sigjohns.pdf b/sigjohns.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1965aa8c94a15cff177e6039026855e1ccf685df GIT binary patch literal 32559 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 literal 0 HcmV?d00001 diff --git a/templates/CRM/Contact/Form/Task/LatexPDF.tpl b/templates/CRM/Contact/Form/Task/LatexPDF.tpl new file mode 100644 index 0000000000..d260d564d4 --- /dev/null +++ b/templates/CRM/Contact/Form/Task/LatexPDF.tpl @@ -0,0 +1,33 @@ +{* + +--------------------------------------------------------------------+ + | CiviCRM version 4.3 | + +--------------------------------------------------------------------+ + | Copyright CiviCRM LLC (c) 2004-2013 | + +--------------------------------------------------------------------+ + | This file is a part of CiviCRM. | + | | + | CiviCRM is free software; you can copy, modify, and distribute it | + | under the terms of the GNU Affero General Public License | + | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | + | | + | CiviCRM is distributed in the hope that it will be useful, but | + | WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | + | See the GNU Affero General Public License for more details. | + | | + | You should have received a copy of the GNU Affero General Public | + | License and the CiviCRM Licensing Exception along | + | with this program; if not, contact CiviCRM LLC | + | at info[AT]civicrm[DOT]org. If you have questions about the | + | GNU Affero General Public License or the licensing of CiviCRM, | + | see the CiviCRM license FAQ at http://civicrm.org/licensing | + +--------------------------------------------------------------------+ +*} +
+

{ts}Create Printable Latex Letters (PDF){/ts}

+{if $single eq false} +
{include file="CRM/Contact/Form/Task.tpl"}
+{/if} +{include file="CRM/Contact/Form/Task/LatexPDFLatexCommon.tpl"} +
{include file="CRM/common/formButtons.tpl" location="bottom"}
+
diff --git a/templates/CRM/Contact/Form/Task/LatexPDFLatexCommon.tpl b/templates/CRM/Contact/Form/Task/LatexPDFLatexCommon.tpl new file mode 100644 index 0000000000..1f75f97f7a --- /dev/null +++ b/templates/CRM/Contact/Form/Task/LatexPDFLatexCommon.tpl @@ -0,0 +1,312 @@ +{* + +--------------------------------------------------------------------+ + | CiviCRM version 4.4 | + +--------------------------------------------------------------------+ + | Copyright CiviCRM LLC (c) 2004-2013 | + +--------------------------------------------------------------------+ + | This file is a part of CiviCRM. | + | | + | CiviCRM is free software; you can copy, modify, and distribute it | + | under the terms of the GNU Affero General Public License | + | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | + | | + | CiviCRM is distributed in the hope that it will be useful, but | + | WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | + | See the GNU Affero General Public License for more details. | + | | + | You should have received a copy of the GNU Affero General Public | + | License and the CiviCRM Licensing Exception along | + | with this program; if not, contact CiviCRM LLC | + | at info[AT]civicrm[DOT]org. If you have questions about the | + | GNU Affero General Public License or the licensing of CiviCRM, | + | see the CiviCRM license FAQ at http://civicrm.org/licensing | + +--------------------------------------------------------------------+ +*} +{*common template for compose PDF letters*} +{if $form.template.html} + + + + + +
{$form.template.label}{$form.template.html}
+{/if} + + + +
+
+ {$form.html_message.label} +
+
+ {if $action neq 4} + + {$form.token1.label} + {help id="id-token-html" file="CRM/Contact/Form/Task/Email.hlp" tplFile=$tplFile isAdmin=$isAdmin editor=$editor} + + + {/if} +
+
+ {if $editor EQ 'textarea'} +
{ts}The content of this page should be LaTeX.{/ts}
+ {/if} + {$form.html_message.html}
+
+ +
+
+ {$form.updateTemplate.html} {$form.updateTemplate.label} +
+
+ {$form.saveTemplate.html} {$form.saveTemplate.label} +
+
+ +
+
{$form.saveTemplateName.label}
+
{$form.saveTemplateName.html|crmAddClass:huge}
+
+ +
+
+ +{include file="CRM/Mailing/Form/InsertTokens.tpl"} + +{literal} + +{/literal} + diff --git a/templates/CRM/Contribute/Form/Task/PDFLatex.tpl b/templates/CRM/Contribute/Form/Task/PDFLatex.tpl new file mode 100644 index 0000000000..a7fb2599ce --- /dev/null +++ b/templates/CRM/Contribute/Form/Task/PDFLatex.tpl @@ -0,0 +1,48 @@ +{* + +--------------------------------------------------------------------+ + | CiviCRM version 4.4 | + +--------------------------------------------------------------------+ + | Copyright CiviCRM LLC (c) 2004-2013 | + +--------------------------------------------------------------------+ + | This file is a part of CiviCRM. | + | | + | CiviCRM is free software; you can copy, modify, and distribute it | + | under the terms of the GNU Affero General Public License | + | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | + | | + | CiviCRM is distributed in the hope that it will be useful, but | + | WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | + | See the GNU Affero General Public License for more details. | + | | + | You should have received a copy of the GNU Affero General Public | + | License and the CiviCRM Licensing Exception along | + | with this program; if not, contact CiviCRM LLC | + | at info[AT]civicrm[DOT]org. If you have questions about the | + | GNU Affero General Public License or the licensing of CiviCRM, | + | see the CiviCRM license FAQ at http://civicrm.org/licensing | + +--------------------------------------------------------------------+ +*} +
+

{ts}Thank-you Letter In Latex for Contributions (PDF){/ts}

+{if $single eq false} +
{include file="CRM/Contribute/Form/Task.tpl"}
+{/if} + +
+
+ {$form.more_options_header.html} +
+
+ + + + +
{$form.thankyou_update.html} {$form.thankyou_update.label}
{$form.receipt_update.html} {$form.receipt_update.label}
+
+
+ +{include file="CRM/Contact/Form/Task/PDFLatexCommon.tpl"} + +
{include file="CRM/common/formButtons.tpl" location="bottom"}
+
diff --git a/tmp_table_myisam.patch b/tmp_table_myisam.patch new file mode 100644 index 0000000000..a531b5f2a1 --- /dev/null +++ b/tmp_table_myisam.patch @@ -0,0 +1,51 @@ +diff --git a/CRM/Contact/Form/Search/Custom/Group.php b/CRM/Contact/Form/Search/Custom/Group.php +index 999a733..b40d55f 100644 +--- a/CRM/Contact/Form/Search/Custom/Group.php ++++ b/CRM/Contact/Form/Search/Custom/Group.php +@@ -32,7 +32,9 @@ + * $Id$ + * + */ +-class CRM_Contact_Form_Search_Custom_Group extends CRM_Contact_Form_Search_Custom_Base implements CRM_Contact_Form_Search_Interface { ++class CRM_Contact_Form_Search_Custom_Group ++ extends CRM_Contact_Form_Search_Custom_Base ++ implements CRM_Contact_Form_Search_Interface { + + protected $_formValues; + +@@ -283,7 +285,7 @@ function from() { + $xGroups = 0; + } + +- $sql = "CREATE TEMPORARY TABLE Xg_{$this->_tableName} ( contact_id int primary key) ENGINE=HEAP"; ++ $sql = "CREATE TEMPORARY TABLE Xg_{$this->_tableName} ( contact_id int primary key) ENGINE=MyISAM"; + CRM_Core_DAO::executeQuery($sql); + + //used only when exclude group is selected +@@ -318,7 +320,7 @@ function from() { + + $sql = "CREATE TEMPORARY TABLE Ig_{$this->_tableName} ( id int PRIMARY KEY AUTO_INCREMENT, + contact_id int, +- group_names varchar(64)) ENGINE=HEAP"; ++ group_names varchar(64)) ENGINE=MyISAM"; + + CRM_Core_DAO::executeQuery($sql); + +@@ -418,7 +420,7 @@ function from() { + $xTags = 0; + } + +- $sql = "CREATE TEMPORARY TABLE Xt_{$this->_tableName} ( contact_id int primary key) ENGINE=HEAP"; ++ $sql = "CREATE TEMPORARY TABLE Xt_{$this->_tableName} ( contact_id int primary key) ENGINE=MyISAM"; + CRM_Core_DAO::executeQuery($sql); + + //used only when exclude tag is selected +@@ -436,7 +438,7 @@ function from() { + + $sql = "CREATE TEMPORARY TABLE It_{$this->_tableName} ( id int PRIMARY KEY AUTO_INCREMENT, + contact_id int, +- tag_names varchar(64)) ENGINE=HEAP"; ++ tag_names varchar(64)) ENGINE=MyISAM"; + + CRM_Core_DAO::executeQuery($sql); + -- 2.25.1