Solving RT ticket #1092988
[civicrm-core.git] / latex.patch
CommitLineData
cb25a178
LMM
1diff --git a/CRM/Contribute/Form/Task/PDFLatex.php b/CRM/Contribute/Form/Task/PDFLatex.php
2new file mode 100644
3index 0000000..f353e00
4--- /dev/null
5+++ b/CRM/Contribute/Form/Task/PDFLatex.php
6@@ -0,0 +1,147 @@
7+<?php
8+/*
9+ +--------------------------------------------------------------------+
10+ | CiviCRM version 4.4 |
11+ +--------------------------------------------------------------------+
12+ | Copyright CiviCRM LLC (c) 2004-2013 |
13+ +--------------------------------------------------------------------+
14+ | This file is a part of CiviCRM. |
15+ | |
16+ | CiviCRM is free software; you can copy, modify, and distribute it |
17+ | under the terms of the GNU Affero General Public License |
18+ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
19+ | |
20+ | CiviCRM is distributed in the hope that it will be useful, but |
21+ | WITHOUT ANY WARRANTY; without even the implied warranty of |
22+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
23+ | See the GNU Affero General Public License for more details. |
24+ | |
25+ | You should have received a copy of the GNU Affero General Public |
26+ | License and the CiviCRM Licensing Exception along |
27+ | with this program; if not, contact CiviCRM LLC |
28+ | at info[AT]civicrm[DOT]org. If you have questions about the |
29+ | GNU Affero General Public License or the licensing of CiviCRM, |
30+ | see the CiviCRM license FAQ at http://civicrm.org/licensing |
31+ +--------------------------------------------------------------------+
32+*/
33+
34+/**
35+ *
36+ * @package CRM
37+ * @copyright CiviCRM LLC (c) 2004-2013
38+ * $Id$
39+ *
40+ */
41+
42+/**
43+ * This class provides the functionality to create PDF letter for a group of
44+ * contacts or a single contact.
45+ */
46+class CRM_Contribute_Form_Task_PDFLatex extends CRM_Contribute_Form_Task {
47+
48+ /**
49+ * all the existing templates in the system
50+ *
51+ * @var array
52+ */
53+ public $_templates = NULL;
54+
55+ public $_single = NULL;
56+
57+ public $_cid = NULL;
58+
59+ /**
60+ * build all the data structures needed to build the form
61+ *
62+ * @return void
63+ * @access public
64+ */
65+ function preProcess() {
66+ $this->skipOnHold = $this->skipDeceased = FALSE;
67+ CRM_Contact_Form_Task_PDFLetterCommon::preProcess($this);
68+
69+ // store case id if present
70+ $this->_caseId = CRM_Utils_Request::retrieve('caseid', 'Positive', $this, FALSE);
71+
72+ // retrieve contact ID if this is 'single' mode
73+ $cid = CRM_Utils_Request::retrieve('cid', 'Positive', $this, FALSE);
74+
75+ $this->_activityId = CRM_Utils_Request::retrieve('id', 'Positive', $this, FALSE);
76+
77+ if ($cid) {
78+ CRM_Contact_Form_Task_PDFLetterCommon::preProcessSingle($this, $cid);
79+ $this->_single = TRUE;
80+ $this->_cid = $cid;
81+ }
82+ else {
83+ parent::preProcess();
84+ }
85+ $this->assign('single', $this->_single);
86+ }
87+
88+ function setDefaultValues() {
89+ $defaults = array();
90+ if (isset($this->_activityId)) {
91+ $params = array('id' => $this->_activityId);
92+ CRM_Activity_BAO_Activity::retrieve($params, $defaults);
93+ $defaults['html_message'] = $defaults['details'];
94+ }
95+ $defaults = $defaults + CRM_Contact_Form_Task_PDFLetterCommon::setDefaultValues();
96+ return $defaults;
97+ }
98+
99+ /**
100+ * Build the form
101+ *
102+ * @access public
103+ *
104+ * @return void
105+ */
106+ public function buildQuickForm() {
107+ //enable form element
108+ $this->assign('suppressForm', FALSE);
109+
110+ // use contact form as a base
111+ CRM_Contact_Form_Task_PDFLetterCommon::buildQuickForm($this);
112+
113+ // specific need for contributions
114+ $this->add('static', 'more_options_header', NULL, ts('Record Update Options'));
115+ $this->add('checkbox', 'receipt_update', ts('Update receipt dates for these contributions'), FALSE);
116+ $this->add('checkbox', 'thankyou_update', ts('Update thank-you dates for these contributions'), FALSE);
117+
118+ // Group options for tokens are not yet implemented. dgg
119+ $options = array(ts('Contact'), ts('Recurring'));
120+ $this->addRadio('is_group_by', ts('Grouping contributions in one letter based on'), $options, array(), "<br/>", FALSE);
121+
122+ $this->addButtons(array(
123+ array(
124+ 'type' => 'submit',
125+ 'name' => ts('Make Thank-you Letters'),
126+ 'isDefault' => TRUE,
127+ ),
128+ array(
129+ 'type' => 'cancel',
130+ 'name' => ts('Done'),
131+ ),
132+ )
133+ );
134+
135+ }
136+
137+ /**
138+ * process the form after the input has been submitted and validated
139+ *
140+ * @access public
141+ *
142+ * @return None
143+ */
144+ public function postProcess() {
145+ // TODO: rewrite using contribution token and one letter by contribution
146+ $this->setContactIDs();
147+
148+ CRM_Contribute_Form_Task_PDFLatexCommon::postProcess($this);
149+ }
150+
151+
152+}
153+
154diff --git a/CRM/Contribute/Form/Task/PDFLatexCommon.php b/CRM/Contribute/Form/Task/PDFLatexCommon.php
155new file mode 100644
156index 0000000..862b03f
157--- /dev/null
158+++ b/CRM/Contribute/Form/Task/PDFLatexCommon.php
159@@ -0,0 +1,116 @@
160+<?php
161+
162+/**
163+ * This class provides the common functionality for creating PDF letter for
164+ * one or a group of contact ids.
165+ */
166+class CRM_Contribute_Form_Task_PDFLatexCommon extends CRM_Contact_Form_Task_PDFLetterCommon {
167+
168+ /**
169+ * process the form after the input has been submitted and validated
170+ *
171+ * @access public
172+ *
173+ * @return None
174+ */
175+ static function postProcess(&$form) {
176+
177+ list($formValues, $categories, $html_message, $messageToken, $returnProperties) = self::processMessageTemplate($form);
178+ //CRM_Core_Error::debug_log_message(":2 $html_message"); //OK
179+
180+ // update dates ?
181+ $receipt_update = isset($formValues['receipt_update']) ? $formValues['receipt_update'] : FALSE;
182+ $thankyou_update = isset($formValues['thankyou_update']) ? $formValues['thankyou_update'] : FALSE;
183+ $nowDate = date('YmdHis');
184+ $receipts = 0;
185+ $thanks = 0;
186+ $updateStatus = '';
187+
188+ // skip some contacts ?
189+ $skipOnHold = isset($form->skipOnHold) ? $form->skipOnHold : FALSE;
190+ $skipDeceased = isset($form->skipDeceased) ? $form->skipDeceased : TRUE;
191+
192+ foreach ($form->getVar('_contributionIds') as $item => $contributionId) {
193+
194+ // get contact information
195+ $contactId = civicrm_api("Contribution", "getvalue", array('version' => '3', 'id' => $contributionId, 'return' => 'contact_id'));
196+ $params = array('contact_id' => $contactId);
197+
198+ list($contact) = CRM_Utils_Token::getTokenDetails($params,
199+ $returnProperties,
200+ $skipOnHold,
201+ $skipDeceased,
202+ NULL,
203+ $messageToken,
204+ 'CRM_Contribution_Form_Task_PDFLetterCommon'
205+ );
206+ if (civicrm_error($contact)) {
207+ $notSent[] = $contributionId;
208+ continue;
209+ }
210+
211+ // get contribution information
212+ $params = array('contribution_id' => $contributionId);
213+ $contribution = CRM_Utils_Token::getContributionTokenDetails($params,
214+ $returnProperties,
215+ NULL,
216+ $messageToken,
217+ 'CRM_Contribution_Form_Task_PDFLetterCommon'
218+ );
219+ if (civicrm_error($contribution)) {
220+ $notSent[] = $contributionId;
221+ continue;
222+ }
223+
224+ $tokenHtml = CRM_Utils_Token::replaceContactTokens($html_message, $contact[$contactId], FALSE, $messageToken);
225+ $tokenHtml = CRM_Utils_Token::replaceContributionTokens($tokenHtml, $contribution[$contributionId], TRUE, $messageToken);
226+ $tokenHtml = CRM_Utils_Token::replaceHookTokens($tokenHtml, $contact[$contactId], $categories, TRUE);
227+
228+ if (defined('CIVICRM_MAIL_SMARTY') && CIVICRM_MAIL_SMARTY) {
229+ $smarty = CRM_Core_Smarty::singleton();
230+ // also add the tokens to the template
231+ $smarty->assign_by_ref('contact', $contact);
232+ $tokenHtml = $smarty->fetch("string:$tokenHtml");
233+ }
234+
235+ $html[] = $tokenHtml;
236+
237+ // update dates (do it for each contribution including grouped recurring contribution)
238+ if ($receipt_update) {
239+ $result = CRM_Core_DAO::setFieldValue('CRM_Contribute_DAO_Contribution', $contributionId, 'receipt_date', $nowDate);
240+ // We can't use CRM_Core_Error::fatal here because the api error elevates the exception level. FIXME. dgg
241+ if ($result) {
242+ $receipts++;
243+ }
244+ }
245+ if ($thankyou_update) {
246+ $result = CRM_Core_DAO::setFieldValue('CRM_Contribute_DAO_Contribution', $contributionId, 'thankyou_date', $nowDate);
247+ // We can't use CRM_Core_Error::fatal here because the api error elevates the exception level. FIXME. dgg
248+ if ($result) {
249+ $thanks++;
250+ }
251+ }
252+ }
253+
254+ self::createActivities($form, $html_message, $form->_contactIds);
255+
256+ CRM_Utils_PDF_Utils::latex2pdf($html, "CiviLatex.pdf", FALSE, $formValues);
257+
258+ $form->postProcessHook();
259+
260+ if ($receipts) {
261+ $updateStatus = ts('Receipt date has been updated for %1 contributions.', array(1 => $receipts));
262+ }
263+ if ($thanks) {
264+ $updateStatus .= ' ' . ts('Thank-you date has been updated for %1 contributions.', array(1 => $thanks));
265+ }
266+
267+ if ($updateStatus) {
268+ CRM_Core_Session::setStatus($updateStatus);
269+ }
270+
271+ CRM_Utils_System::civiExit(1);
272+ }
273+ //end of function
274+}
275+
276diff --git a/CRM/Contribute/Task.php b/CRM/Contribute/Task.php
277index 987b280..129cb45 100644
278--- a/CRM/Contribute/Task.php
279+++ b/CRM/Contribute/Task.php
280@@ -39,7 +39,7 @@
281 *
282 */
283 class CRM_Contribute_Task {
284- CONST DELETE_CONTRIBUTIONS = 1, PRINT_CONTRIBUTIONS = 2, EXPORT_CONTRIBUTIONS = 3, BATCH_CONTRIBUTIONS = 4, EMAIL_CONTACTS = 5, UPDATE_STATUS = 6, PDF_RECEIPT = 7;
285+ 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;
286
287 /**
288 * the task array
289@@ -106,6 +106,10 @@ static function &tasks() {
290 'class' => 'CRM_Contribute_Form_Task_PDFLetter',
291 'result' => FALSE,
292 ),
293+ 9 => array('title' => ts('Latex Letters for Contributions'),
294+ 'class' => 'CRM_Contribute_Form_Task_PDFLatex',
295+ 'result' => FALSE,
296+ ),
297 );
298
299 //CRM-4418, check for delete
300diff --git a/CRM/Utils/PDF/Utils.php b/CRM/Utils/PDF/Utils.php
301index 72d4880..e9d59b9 100644
302--- a/CRM/Utils/PDF/Utils.php
303+++ b/CRM/Utils/PDF/Utils.php
304@@ -34,6 +34,69 @@
305 */
306 class CRM_Utils_PDF_Utils {
307
308+ static function latex2pdf(&$text, $fileName = 'civicrm.pdf', $output = FALSE, $pdfFormat = NULL) {
309+ /* FIXME: get $paper_size, $orientation, $margins */
310+
311+ if (is_array($text)) {
312+ $pages = &$text;
313+ }
314+ else {
315+ $pages = array($text);
316+ }
317+
318+
319+ $head='\documentclass[12pt]{letter}
320+\oddsidemargin 0in
321+\evensidemargin 0in
322+\textwidth 6.5in
323+
324+\topmargin -.25in
325+\textheight 8.15in
326+
327+\address{\vspace{0.354in}}
328+
329+\begin{document}
330+
331+';
332+ $footer='
333+\end{document}';
334+
335+ $latex = $head;
336+ foreach ($pages as $page) {
337+ $latex.=$page;
338+ }
339+ $latex.=$footer;
340+
341+ $descriptorspec = array(
342+ 0 => array("pipe", "r"),
343+ 1 => array("pipe", "w")
344+ );
345+
346+
347+
348+ $process = proc_open("/usr/local/bin/pdflatex_wrapper.sh", $descriptorspec, $pipes);
349+
350+
351+ if (is_resource($process)) {
352+ fwrite($pipes[0], $latex);
353+ fclose($pipes[0]);
354+
355+ $pdf = stream_get_contents($pipes[1]);
356+ fclose($pipes[1]);
357+ } else {
358+ CRM_Core_Error::debug_log_message("ERROR creating PDF. Check /tmp/pdflatex_*");
359+ }
360+
361+ if ($output) {
362+ return $pdf;
363+ }
364+ else {
365+ header('Content-Type: application/pdf');
366+ header('Content-Disposition: attachment; filename="' . $fileName . '"');
367+ echo $pdf;
368+ }
369+ }
370+
371 static function html2pdf(&$text, $fileName = 'civicrm.pdf', $output = FALSE, $pdfFormat = NULL) {
372 if (is_array($text)) {
373 $pages = &$text;
374diff --git a/CRM/Utils/Token.php b/CRM/Utils/Token.php
375index 28ca941..e8df124 100644
376--- a/CRM/Utils/Token.php
377+++ b/CRM/Utils/Token.php
378@@ -619,7 +619,10 @@ function ($matches) use(&$contact, $html, $returnBlankToken, $escapeSmarty) {
379 $str
380 );
381
382- $str = preg_replace('/\\\\|\{(\s*)?\}/', ' ', $str);
383+ // 2013-08-31 nico@fsf.org this replacement is stripping all the '{' and '}' from the LaTeX files
384+ // maybe it got solved at some point. maybe it has undesired collateral effects. I'm bugging the
385+ // CiviCRM community to take a look at this pull request.
386+ //$str = preg_replace('/\\\\|\{(\s*)?\}/', ' ', $str);
387 return $str;
388 }
389
390diff --git a/templates/CRM/Contact/Form/Task/PDFLatexCommon.tpl b/templates/CRM/Contact/Form/Task/PDFLatexCommon.tpl
391new file mode 100644
392index 0000000..1f75f97
393--- /dev/null
394+++ b/templates/CRM/Contact/Form/Task/PDFLatexCommon.tpl
395@@ -0,0 +1,312 @@
396+{*
397+ +--------------------------------------------------------------------+
398+ | CiviCRM version 4.4 |
399+ +--------------------------------------------------------------------+
400+ | Copyright CiviCRM LLC (c) 2004-2013 |
401+ +--------------------------------------------------------------------+
402+ | This file is a part of CiviCRM. |
403+ | |
404+ | CiviCRM is free software; you can copy, modify, and distribute it |
405+ | under the terms of the GNU Affero General Public License |
406+ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
407+ | |
408+ | CiviCRM is distributed in the hope that it will be useful, but |
409+ | WITHOUT ANY WARRANTY; without even the implied warranty of |
410+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
411+ | See the GNU Affero General Public License for more details. |
412+ | |
413+ | You should have received a copy of the GNU Affero General Public |
414+ | License and the CiviCRM Licensing Exception along |
415+ | with this program; if not, contact CiviCRM LLC |
416+ | at info[AT]civicrm[DOT]org. If you have questions about the |
417+ | GNU Affero General Public License or the licensing of CiviCRM, |
418+ | see the CiviCRM license FAQ at http://civicrm.org/licensing |
419+ +--------------------------------------------------------------------+
420+*}
421+{*common template for compose PDF letters*}
422+{if $form.template.html}
423+<table class="form-layout-compressed">
424+ <tr>
425+ <td class="label-left">{$form.template.label}</td>
426+ <td>{$form.template.html}</td>
427+ </tr>
428+</table>
429+{/if}
430+
431+<div class="crm-accordion-wrapper collapsed">
432+ <div class="crm-accordion-header">
433+ {$form.pdf_format_header.html}
434+ </div>
435+ <div class="crm-accordion-body">
436+ <div class="crm-block crm-form-block crm-pdf-format-form-block">
437+ <table class="form-layout-compressed">
438+ <tr>
439+ <td class="label-left">{$form.format_id.label}</td><td>{$form.format_id.html}{help id="id-pdf-format" file="CRM/Contact/Form/Task/PDFLetterCommon.hlp"}</td>
440+ <td colspan="2">&nbsp;</td>
441+ </tr>
442+ <tr>
443+ <td class="label-left">{$form.paper_size.label}</td><td>{$form.paper_size.html}</td>
444+ <td class="label-left">{$form.orientation.label}</td><td>{$form.orientation.html}</td>
445+ </tr>
446+ <tr>
447+ <td class="label-left">{$form.metric.label}</td><td>{$form.metric.html}</td>
448+ <td colspan="2">&nbsp;</td>
449+ </tr>
450+ <tr>
451+ <td>{$form.paper_dimensions.html}</td><td id="paper_dimensions">&nbsp;</td>
452+ <td colspan="2">&nbsp;</td>
453+ </tr>
454+ <tr>
455+ <td class="label-left">{$form.margin_top.label}</td><td>{$form.margin_top.html}</td>
456+ <td class="label-left">{$form.margin_bottom.label}</td><td>{$form.margin_bottom.html}</td>
457+ </tr>
458+ <tr>
459+ <td class="label-left">{$form.margin_left.label}</td><td>{$form.margin_left.html}</td>
460+ <td class="label-left">{$form.margin_right.label}</td><td>{$form.margin_right.html}</td>
461+ </tr>
462+ </table>
463+ <div id="bindFormat">{$form.bind_format.html}&nbsp;{$form.bind_format.label}</div>
464+ <div id="updateFormat" style="display: none">{$form.update_format.html}&nbsp;{$form.update_format.label}</div>
465+ </div>
466+ </div>
467+</div>
468+
469+<div class="crm-accordion-wrapper crm-html_email-accordion ">
470+<div class="crm-accordion-header">
471+ {$form.html_message.label}
472+</div><!-- /.crm-accordion-header -->
473+ <div class="crm-accordion-body">
474+ {if $action neq 4}
475+ <span class="helpIcon" id="helphtml">
476+ <a href="#" onClick="return showToken('Html', 1);">{$form.token1.label}</a>
477+ {help id="id-token-html" file="CRM/Contact/Form/Task/Email.hlp" tplFile=$tplFile isAdmin=$isAdmin editor=$editor}
478+ <div id="tokenHtml" style="display:none;">
479+ <input style="border:1px solid #999999;" type="text" id="filter1" size="20" name="filter1" onkeyup="filter(this, 1)"/><br />
480+ <span class="description">{ts}Begin typing to filter list of tokens{/ts}</span><br/>
481+ {$form.token1.html}
482+ </div>
483+ </span>
484+ {/if}
485+ <div class="clear"></div>
486+ <div class='html'>
487+ {if $editor EQ 'textarea'}
488+ <div class="help description">{ts}The content of this page should be LaTeX.{/ts}</div>
489+ {/if}
490+ {$form.html_message.html}<br />
491+ </div>
492+
493+<div id="editMessageDetails">
494+ <div id="updateDetails" >
495+ {$form.updateTemplate.html}&nbsp;{$form.updateTemplate.label}
496+ </div>
497+ <div>
498+ {$form.saveTemplate.html}&nbsp;{$form.saveTemplate.label}
499+ </div>
500+</div>
501+
502+<div id="saveDetails" class="section">
503+ <div class="label">{$form.saveTemplateName.label}</div>
504+ <div class="content">{$form.saveTemplateName.html|crmAddClass:huge}</div>
505+</div>
506+
507+ </div><!-- /.crm-accordion-body -->
508+</div><!-- /.crm-accordion-wrapper -->
509+
510+{include file="CRM/Mailing/Form/InsertTokens.tpl"}
511+
512+{literal}
513+<script type="text/javascript">
514+cj(function() {
515+ cj().crmAccordions();
516+});
517+
518+var currentWidth;
519+var currentHeight;
520+var currentMetric = document.getElementById('metric').value;
521+showBindFormatChkBox();
522+selectPaper( document.getElementById('paper_size').value );
523+
524+function tokenReplHtml ( )
525+{
526+ var token1 = cj("#token1").val( )[0];
527+ var editor = {/literal}"{$editor}"{literal};
528+ if ( editor == "tinymce" ) {
529+ var content= tinyMCE.get('html_message').getContent() +token1;
530+ tinyMCE.get('html_message').setContent(content);
531+ } else if ( editor == "joomlaeditor" ) {
532+ tinyMCE.execCommand('mceInsertContent',false, token1);
533+ var msg = document.getElementById(html_message).value;
534+ var cursorlen = document.getElementById(html_message).selectionStart;
535+ var textlen = msg.length;
536+ document.getElementById(html_message).value = msg.substring(0, cursorlen) + token1 + msg.substring(cursorlen, textlen);
537+ var cursorPos = (cursorlen + token1.length);
538+ document.getElementById(html_message).selectionStart = cursorPos;
539+ document.getElementById(html_message).selectionEnd = cursorPos;
540+ document.getElementById(html_message).focus();
541+ } else if ( editor == "ckeditor" ) {
542+ oEditor = CKEDITOR.instances[html_message];
543+ oEditor.insertHtml(token1.toString() );
544+ } else if ( editor == "drupalwysiwyg" ) {
545+ Drupal.wysiwyg.instances[html_message].insert(token1.toString());
546+ } else {
547+ var msg = document.getElementById(html_message).value;
548+ var cursorlen = document.getElementById(html_message).selectionStart;
549+ var textlen = msg.length;
550+ document.getElementById(html_message).value = msg.substring(0, cursorlen) + token1 + msg.substring(cursorlen, textlen);
551+ var cursorPos = (cursorlen + token1.length);
552+ document.getElementById(html_message).selectionStart = cursorPos;
553+ document.getElementById(html_message).selectionEnd = cursorPos;
554+ document.getElementById(html_message).focus();
555+ }
556+ verify();
557+}
558+
559+function showBindFormatChkBox()
560+{
561+ var templateExists = true;
562+ if ( document.getElementById('template') == null || document.getElementById('template').value == '' ) {
563+ templateExists = false;
564+ }
565+ var formatExists = true;
566+ if ( document.getElementById('format_id').value == 0 ) {
567+ formatExists = false;
568+ }
569+ if ( templateExists && formatExists ) {
570+ document.getElementById("bindFormat").style.display = "block";
571+ } else if ( formatExists && document.getElementById("saveTemplate") != null && document.getElementById("saveTemplate").checked ) {
572+ document.getElementById("bindFormat").style.display = "block";
573+ var yes = confirm( '{/literal}{$useThisPageFormat}{literal}' );
574+ if ( yes ) {
575+ document.getElementById("bind_format").checked = true;
576+ }
577+ } else {
578+ document.getElementById("bindFormat").style.display = "none";
579+ document.getElementById("bind_format").checked = false;
580+ }
581+}
582+
583+function showUpdateFormatChkBox()
584+{
585+ if ( document.getElementById('format_id').value != 0 ) {
586+ document.getElementById("updateFormat").style.display = "block";
587+ }
588+}
589+
590+function hideUpdateFormatChkBox()
591+{
592+ document.getElementById("update_format").checked = false;
593+ document.getElementById("updateFormat").style.display = "none";
594+}
595+
596+function selectFormat( val, bind )
597+{
598+ if ( val == null || val == 0 ) {
599+ val = 0;
600+ bind = false;
601+ }
602+ var dataUrl = {/literal}"{crmURL p='civicrm/ajax/pdfFormat' h=0 }"{literal};
603+ cj.post( dataUrl, {formatId: val}, function( data ) {
604+ cj("#format_id").val( data.id );
605+ cj("#paper_size").val( data.paper_size );
606+ cj("#orientation").val( data.orientation );
607+ cj("#metric").val( data.metric );
608+ cj("#margin_top").val( data.margin_top );
609+ cj("#margin_bottom").val( data.margin_bottom );
610+ cj("#margin_left").val( data.margin_left );
611+ cj("#margin_right").val( data.margin_right );
612+ selectPaper( data.paper_size );
613+ hideUpdateFormatChkBox();
614+ document.getElementById('bind_format').checked = bind;
615+ showBindFormatChkBox();
616+ }, 'json');
617+}
618+
619+function selectPaper( val )
620+{
621+ dataUrl = {/literal}"{crmURL p='civicrm/ajax/paperSize' h=0 }"{literal};
622+ cj.post( dataUrl, {paperSizeName: val}, function( data ) {
623+ cj("#paper_size").val( data.name );
624+ metric = document.getElementById('metric').value;
625+ currentWidth = convertMetric( data.width, data.metric, metric );
626+ currentHeight = convertMetric( data.height, data.metric, metric );
627+ updatePaperDimensions( );
628+ }, 'json');
629+}
630+
631+function selectMetric( metric )
632+{
633+ convertField( 'margin_top', currentMetric, metric );
634+ convertField( 'margin_bottom', currentMetric, metric );
635+ convertField( 'margin_left', currentMetric, metric );
636+ convertField( 'margin_right', currentMetric, metric );
637+ currentWidth = convertMetric( currentWidth, currentMetric, metric );
638+ currentHeight = convertMetric( currentHeight, currentMetric, metric );
639+ updatePaperDimensions( );
640+}
641+
642+function updatePaperDimensions( )
643+{
644+ metric = document.getElementById('metric').value;
645+ width = new String( currentWidth.toFixed( 2 ) );
646+ height = new String( currentHeight.toFixed( 2 ) );
647+ if ( document.getElementById('orientation').value == 'landscape' ) {
648+ width = new String( currentHeight.toFixed( 2 ) );
649+ height = new String( currentWidth.toFixed( 2 ) );
650+ }
651+ document.getElementById('paper_dimensions').innerHTML = parseFloat( width ) + ' ' + metric + ' x ' + parseFloat( height ) + ' ' + metric;
652+ currentMetric = metric;
653+}
654+
655+function convertField( id, from, to )
656+{
657+ val = document.getElementById( id ).value;
658+ if ( val == '' || isNaN( val ) ) return;
659+ val = convertMetric( val, from, to );
660+ val = new String( val.toFixed( 3 ) );
661+ document.getElementById( id ).value = parseFloat( val );
662+}
663+
664+function convertMetric( value, from, to ) {
665+ switch( from + to ) {
666+ case 'incm': return value * 2.54;
667+ case 'inmm': return value * 25.4;
668+ case 'inpt': return value * 72;
669+ case 'cmin': return value / 2.54;
670+ case 'cmmm': return value * 10;
671+ case 'cmpt': return value * 72 / 2.54;
672+ case 'mmin': return value / 25.4;
673+ case 'mmcm': return value / 10;
674+ case 'mmpt': return value * 72 / 25.4;
675+ case 'ptin': return value / 72;
676+ case 'ptcm': return value * 2.54 / 72;
677+ case 'ptmm': return value * 25.4 / 72;
678+ }
679+ return value;
680+}
681+
682+function showSaveDetails(chkbox) {
683+ var formatSelected = ( document.getElementById('format_id').value > 0 );
684+ var templateSelected = ( document.getElementById('template') != null && document.getElementById('template').value > 0 );
685+ if (chkbox.checked) {
686+ document.getElementById("saveDetails").style.display = "block";
687+ document.getElementById("saveTemplateName").disabled = false;
688+ if ( formatSelected && ! templateSelected ) {
689+ document.getElementById("bindFormat").style.display = "block";
690+ var yes = confirm( '{/literal}{$useSelectedPageFormat}{literal}' );
691+ if ( yes ) {
692+ document.getElementById("bind_format").checked = true;
693+ }
694+ }
695+ } else {
696+ document.getElementById("saveDetails").style.display = "none";
697+ document.getElementById("saveTemplateName").disabled = true;
698+ if ( ! templateSelected ) {
699+ document.getElementById("bindFormat").style.display = "none";
700+ document.getElementById("bind_format").checked = false;
701+ }
702+ }
703+}
704+
705+</script>
706+{/literal}
707+
708diff --git a/templates/CRM/Contribute/Form/Task/PDFLatex.tpl b/templates/CRM/Contribute/Form/Task/PDFLatex.tpl
709new file mode 100644
710index 0000000..a7fb259
711--- /dev/null
712+++ b/templates/CRM/Contribute/Form/Task/PDFLatex.tpl
713@@ -0,0 +1,48 @@
714+{*
715+ +--------------------------------------------------------------------+
716+ | CiviCRM version 4.4 |
717+ +--------------------------------------------------------------------+
718+ | Copyright CiviCRM LLC (c) 2004-2013 |
719+ +--------------------------------------------------------------------+
720+ | This file is a part of CiviCRM. |
721+ | |
722+ | CiviCRM is free software; you can copy, modify, and distribute it |
723+ | under the terms of the GNU Affero General Public License |
724+ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
725+ | |
726+ | CiviCRM is distributed in the hope that it will be useful, but |
727+ | WITHOUT ANY WARRANTY; without even the implied warranty of |
728+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
729+ | See the GNU Affero General Public License for more details. |
730+ | |
731+ | You should have received a copy of the GNU Affero General Public |
732+ | License and the CiviCRM Licensing Exception along |
733+ | with this program; if not, contact CiviCRM LLC |
734+ | at info[AT]civicrm[DOT]org. If you have questions about the |
735+ | GNU Affero General Public License or the licensing of CiviCRM, |
736+ | see the CiviCRM license FAQ at http://civicrm.org/licensing |
737+ +--------------------------------------------------------------------+
738+*}
739+<div class="crm-form-block crm-block crm-contact-task-pdflatex-form-block">
740+<h3>{ts}Thank-you Letter In Latex for Contributions (PDF){/ts}</h3>
741+{if $single eq false}
742+ <div class="messages status no-popup">{include file="CRM/Contribute/Form/Task.tpl"}</div>
743+{/if}
744+
745+<div class="crm-accordion-wrapper crm-html_email-accordion ">
746+ <div class="crm-accordion-header">
747+ {$form.more_options_header.html}
748+ </div><!-- /.crm-accordion-header -->
749+ <div class="crm-accordion-body">
750+ <table class="form-layout-compressed">
751+ <tr><td class="label-left">{$form.thankyou_update.html} {$form.thankyou_update.label}</td><td></td></tr>
752+ <tr><td class="label-left">{$form.receipt_update.html} {$form.receipt_update.label}</td><td></td></tr>
753+ <!--tr><td class="label-left">{$form.is_group_by.label} (<a href="#" title="unselect" onclick="unselectRadio('is_group_by'); return false;" >{ts}clear{/ts}</a>)</td><td>{$form.is_group_by.html}</td></tr-->
754+ </table>
755+ </div><!-- /.crm-accordion-body -->
756+</div><!-- /.crm-accordion-wrapper -->
757+
758+{include file="CRM/Contact/Form/Task/PDFLatexCommon.tpl"}
759+
760+<div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
761+</div>
762--
7631.8.4
764