Пример #1
0
 /**
  * generate the final result
  *
  * @return array:
  *          'is_error': set if there is a fatal error
  *          'log': array with keys: 'type', 'level', 'timestamp', 'message'
  *          'download_url: URL to download the result
  *          'download_name: suggested file name for the download
  */
 public function wrapUp($snapshot_id, $is_test, $is_bulk)
 {
     $reply = array();
     // create the zip file
     $config = CRM_Core_Config::singleton();
     $preferredFileName = ts("donation_receipts.zip", array('domain' => 'de.systopia.donrec'));
     $archiveFileName = CRM_Donrec_Logic_File::makeFileName(ts("donation_receipts", array('domain' => 'de.systopia.donrec')), ".zip");
     $zip = new ZipArchive();
     $snapshot = CRM_Donrec_Logic_Snapshot::get($snapshot_id);
     $ids = $snapshot->getIds();
     $toRemove = array();
     if ($zip->open($archiveFileName, ZIPARCHIVE::CREATE) === TRUE) {
         foreach ($ids as $id) {
             $proc_info = $snapshot->getProcessInformation($id);
             if (!empty($proc_info)) {
                 $filename = isset($proc_info['PDF']['pdf_file']) ? $proc_info['PDF']['pdf_file'] : FALSE;
                 if ($filename) {
                     $toRemove[$id] = $filename;
                     $opResult = $zip->addFile($filename, basename($filename));
                     CRM_Donrec_Logic_Exporter::addLogEntry($reply, "adding <span title='{$filename}'>created PDF file</span> to <span title='{$archiveFileName}'>ZIP archive</span> ({$opResult})", CRM_Donrec_Logic_Exporter::LOG_TYPE_DEBUG);
                 }
             }
         }
         if (!$zip->close()) {
             CRM_Donrec_Logic_Exporter::addLogEntry($reply, 'zip->close() returned false!', CRM_Donrec_Logic_Exporter::LOG_TYPE_ERROR);
         }
     } else {
         CRM_Donrec_Logic_Exporter::addLogEntry($reply, sprintf('PDF processing failed: Could not open zip file '), CRM_Donrec_Logic_Exporter::LOG_TYPE_FATAL);
         return $reply;
     }
     $file = CRM_Donrec_Logic_File::createTemporaryFile($archiveFileName, $preferredFileName);
     CRM_Core_Error::debug_log_message("de.systopia.donrec: resulting ZIP file URL is '{$file}'.");
     if (!empty($file)) {
         $reply['download_name'] = $preferredFileName;
         $reply['download_url'] = $file;
     }
     // remove loose pdf files or store them
     CRM_Donrec_Logic_Exporter::addLogEntry($reply, 'Removing temporary PDF files.', CRM_Donrec_Logic_Exporter::LOG_TYPE_DEBUG);
     foreach ($toRemove as $file) {
         unlink($file);
     }
     CRM_Donrec_Logic_Exporter::addLogEntry($reply, 'PDF generation process ended.', CRM_Donrec_Logic_Exporter::LOG_TYPE_INFO);
     return $reply;
 }
Пример #2
0
 /**
  * Delete original-file if exists
  * @return TRUE for success, FALSE for failure
  */
 public function deleteOriginalFile()
 {
     $file_id = self::getOriginalFileId();
     if (!$file_id) {
         return FALSE;
     }
     $receipt_fields = self::$_custom_fields;
     $receipt_group_id = self::$_custom_group_id;
     $receipt_id = $this->Id;
     $query = "\n      UPDATE `civicrm_value_donation_receipt_{$receipt_group_id}`\n      SET `{$receipt_fields['original_file']}` = NULL\n      WHERE id = {$receipt_id}\n    ";
     $result = CRM_Core_DAO::executeQuery($query);
     $success = CRM_Donrec_Logic_File::deleteFile($file_id);
     return $success;
 }
Пример #3
0
 /**
  * generate the final result
  *
  * @return array:
  *          'is_error': set if there is a fatal error
  *          'log': array with keys: 'type', 'level', 'timestamp', 'message'
  *          'download_url: URL to download the result
  *          'download_name: suggested file name for the download
  */
 public function wrapUp($snapshot_id, $is_test, $is_bulk)
 {
     $reply = array();
     // create the zip file
     $config = CRM_Core_Config::singleton();
     $preferredFileName = ts("donation_receipts", array('domain' => 'de.systopia.donrec'));
     $preferredSuffix = ts('.zip', array('domain' => 'de.systopia.donrec'));
     $archiveFileName = CRM_Donrec_Logic_File::makeFileName($preferredFileName, $preferredSuffix);
     $fileURL = $archiveFileName;
     $outerArchive = new ZipArchive();
     $snapshot = CRM_Donrec_Logic_Snapshot::get($snapshot_id);
     $ids = $snapshot->getIds();
     $toRemove = array();
     // Sort array by page count
     $pageCountArr = array();
     foreach ($ids as $id) {
         $proc_info = $snapshot->getProcessInformation($id);
         if (!empty($proc_info)) {
             $pageCount = isset($proc_info['PDF']['pdf_pagecount']) ? $proc_info['PDF']['pdf_pagecount'] : FALSE;
             $filename = isset($proc_info['PDF']['pdf_file']) ? $proc_info['PDF']['pdf_file'] : FALSE;
             if ($pageCount) {
                 $pageCountArr[$pageCount][] = array($pageCount, $id, $filename);
             }
         }
     }
     // add files to sub-archives
     // open main archive and add sub-archives
     if ($outerArchive->open($fileURL, ZIPARCHIVE::CREATE) === TRUE) {
         foreach ($pageCountArr as $entry) {
             foreach ($entry as $item) {
                 if ($item[0] && $item[2]) {
                     // if page count and file name exists
                     $folder = sprintf(ts('%d-page', array('domain' => 'de.systopia.donrec')), $item[0]) . DIRECTORY_SEPARATOR;
                     $opResult = $outerArchive->addFile($item[2], $folder . basename($item[2]));
                     CRM_Donrec_Logic_Exporter::addLogEntry($reply, "adding <span title='{$item[2]}'>created {$item[0]}-page PDF file</span> ({$opResult})", CRM_Donrec_Logic_Exporter::LOG_TYPE_DEBUG);
                 }
             }
         }
         if (!$outerArchive->close()) {
             CRM_Donrec_Logic_Exporter::addLogEntry($reply, 'zip->close() returned false!', CRM_Donrec_Logic_Exporter::LOG_TYPE_ERROR);
         }
     } else {
         CRM_Donrec_Logic_Exporter::addLogEntry($reply, sprintf('PDF processing failed: Could not open zip file '), CRM_Donrec_Logic_Exporter::FATAL);
         return $reply;
     }
     $file = CRM_Donrec_Logic_File::createTemporaryFile($fileURL, $preferredFileName . $preferredSuffix);
     CRM_Core_Error::debug_log_message("de.systopia.donrec: resulting ZIP file URL is '{$file}'.");
     if (!empty($file)) {
         $reply['download_name'] = $preferredFileName . $preferredSuffix;
         $reply['download_url'] = $file;
     }
     // remove loose pdf files or store them
     CRM_Donrec_Logic_Exporter::addLogEntry($reply, 'Removing temporary files.', CRM_Donrec_Logic_Exporter::LOG_TYPE_DEBUG);
     foreach ($toRemove as $file) {
         unlink($file);
     }
     CRM_Donrec_Logic_Exporter::addLogEntry($reply, 'PDF generation process ended.', CRM_Donrec_Logic_Exporter::LOG_TYPE_INFO);
     return $reply;
 }
/**
 * View Receipts
 */
function civicrm_api3_donation_receipt_view($params)
{
    // check for missing receipt id parameter
    if (empty($params['rid'])) {
        return civicrm_api3_create_error(ts("No 'rid' parameter given.", array('domain' => 'de.systopia.donrec')));
    }
    $receipt = CRM_Donrec_Logic_Receipt::get($params['rid']);
    if (empty($receipt)) {
        return civicrm_api3_create_error(sprintf(ts("Receipt with id %d does not exist.", array('domain' => 'de.systopia.donrec')), $params['rid']));
    }
    if (empty($params['name'])) {
        $name = 'View.pdf';
    } else {
        $name = $params['name'];
    }
    $values = $receipt->getAllProperties();
    $profile = $receipt->getProfile();
    // mark this as DRAFT id ORIGINAL
    if (empty($values['watermark'])) {
        $values['status'] = 'DRAFT';
        $values['watermark'] = $profile->get('draft_text');
    }
    $pdf = $profile->getTemplate()->generatePDF($values, $parameter);
    $url = CRM_Donrec_Logic_File::createTemporaryFile($pdf, $name);
    // and return the result
    return civicrm_api3_create_success($url);
}
Пример #5
0
 /**
  * generate the final result
  *
  * @return array:
  *          'is_error': set if there is a fatal error
  *          'log': array with keys: 'type', 'level', 'timestamp', 'message'
  *          'download_url: URL to download the result
  *          'download_name: suggested file name for the download
  */
 public function wrapUp($snapshot_id, $is_test, $is_bulk)
 {
     $snapshot = CRM_Donrec_Logic_Snapshot::get($snapshot_id);
     $reply = array();
     // open file
     $preferredFileName = ts('donation_receipts');
     $preferredFileSuffix = ts('.csv', array('domain' => 'de.systopia.donrec'));
     $temp_file = CRM_Donrec_Logic_File::makeFileName($preferredFileName, $preferredFileSuffix);
     $handle = fopen($temp_file, 'w');
     // get headers
     $headers = CRM_Donrec_Logic_ReceiptTokens::getFullTokenList();
     $headers = $this->flattenTokenData($headers);
     $headers = array_keys($headers);
     $header_written = false;
     // write them all into the file
     $ids = $snapshot->getIds();
     foreach ($ids as $id) {
         $proc_info = $snapshot->getProcessInformation($id);
         $csv_data = $proc_info['CSV']['csv_data'];
         if (!empty($csv_data)) {
             if (!$header_written) {
                 // extend header by extra fields
                 $headers = array_merge($headers, array_keys($csv_data));
                 $headers = array_unique($headers);
                 // write header
                 fputcsv($handle, $headers, ';', '"');
                 $header_written = true;
             }
             // create and write a line
             $line = array();
             foreach ($headers as $field) {
                 if (isset($csv_data[$field])) {
                     $line[$field] = $csv_data[$field];
                 } else {
                     $line[$field] = '';
                 }
             }
             fputcsv($handle, $line, ';', '"');
         }
     }
     // get process info iterator
     fclose($handle);
     // create the file
     $file = CRM_Donrec_Logic_File::createTemporaryFile($temp_file, $preferredFileName . $preferredFileSuffix);
     CRM_Core_Error::debug_log_message("de.systopia.donrec: resulting CSV file URL is '{$file}'.");
     if (!empty($file)) {
         $reply['download_name'] = $preferredFileName;
         $reply['download_url'] = $file;
     }
     CRM_Donrec_Logic_Exporter::addLogEntry($reply, 'CSV process ended.', CRM_Donrec_Logic_Exporter::LOG_TYPE_INFO);
     return $reply;
 }
Пример #6
0
 public static function addDynamicTokens(&$values)
 {
     if (!empty($values['issued_by'])) {
         // add created_by_display_name
         try {
             $creator = civicrm_api3('Contact', 'getsingle', array('id' => $values['issued_by']));
             $values['issued_by_display_name'] = $creator['display_name'];
         } catch (Exception $e) {
             CRM_Core_Error::debug_log_message('de.systopia.donrec - ' . print_r($e, 1));
         }
     }
     // add the legacy 'today' token
     if (!empty($values['issued_on'])) {
         $values['today'] = $values['issued_on'];
     }
     // add the monetary tokens: 'total', 'totaltext', 'totalmoney'
     if (isset($values['total_amount'])) {
         // format total_amount
         $values['total_amount'] = number_format((double) $values['total_amount'], 2, '.', '');
         $values['total'] = $values['total_amount'];
         $values['totaltext'] = CRM_Utils_DonrecHelper::convert_number_to_words($values['total_amount']);
         $values['totalmoney'] = CRM_Utils_Money::format($values['total_amount'], '');
     }
     // add financial type name
     $financialTypes = CRM_Contribute_PseudoConstant::financialType();
     if (is_array($values['lines'])) {
         foreach ($values['lines'] as $key => $line) {
             if (!empty($line['financial_type_id'])) {
                 $values['lines'][$key]['financial_type'] = $financialTypes[$line['financial_type_id']];
             }
         }
     }
     // sort contribution lines by receive date (#1497)
     $receive_dates = array();
     $sorted_lines = $values['lines'];
     foreach ($sorted_lines as $key => $line) {
         $sorted_lines[$key]['id'] = $key;
         $receive_dates[$key] = $line['receive_date'];
     }
     array_multisort($receive_dates, SORT_ASC, $sorted_lines);
     $values['lines'] = array();
     foreach ($sorted_lines as $key => $line) {
         $values['lines'][$line['id']] = $line;
     }
     // add legacy 'items'
     if (count($values['lines']) > 1) {
         $values['items'] = $values['lines'];
     }
     // add organisation address
     if (empty($values['organisation'])) {
         $domain = CRM_Core_BAO_Domain::getDomain();
         $values['organisation'] = self::lookupAddressTokens($domain->contact_id, 0, 0);
     }
     // ADD watermarks
     $profile = CRM_Donrec_Logic_Profile::getProfile($values['profile']);
     if ($values['status'] == 'ORIGINAL') {
         // nothing to to in this case..
     } elseif ($values['status'] == 'COPY') {
         $values['watermark'] = $profile->get('copy_text');
     } else {
         // in all other cases, it's INVALID/DRAFT:
         $values['watermark'] = $profile->get('draft_text');
     }
     // copy contributor values to addressee, if not set separately
     if (!isset($values['addressee']['display_name'])) {
         $values['addressee']['display_name'] = $values['contributor']['display_name'];
     }
     if (!isset($values['addressee']['addressee_display'])) {
         $values['addressee']['addressee_display'] = $values['contributor']['addressee_display'];
     }
     // add URL to view original file, if it exists
     if (!empty($values['original_file'])) {
         $values['view_url'] = CRM_Donrec_Logic_File::getPermanentURL($values['original_file'], $values['contributor']['id']);
     }
     // TODO: call Token hooks? Currently done by PDF generator
 }
Пример #7
0
    /**
     * Creates a PDF file from the specified values
     *
     * @param array associative array of values that will be
     *        assigned to the template
     * @param array of configuration parameters
     * @return filename or False
     */
    public function generatePDF($values, &$parameters)
    {
        $smarty = CRM_Core_Smarty::singleton();
        $config = CRM_Core_Config::singleton();
        // assign all values
        foreach ($values as $token => $value) {
            $smarty->assign($token, $value);
        }
        // callback for custom variables
        CRM_Utils_DonrecCustomisationHooks::pdf_unique_token($smarty, $values);
        // get template
        $html = $this->_template->msg_html;
        // --- watermark injection ---
        // identify pdf engine
        $pdf_engine = $config->wkhtmltopdfPath;
        if (!empty($pdf_engine)) {
            $wk_is_enabled = TRUE;
            $watermark_css = '<style>
                        {literal}
                        .watermark {
                          position: fixed;
                          z-index: 999;
                          color: rgba(128, 128, 128, 0.20);
                          -ms-transform: rotate(-45deg); /* IE 9 */
                          -webkit-transform: rotate(-45deg); /* Chrome, Safari, Opera */
                          transform: rotate(-45deg);
                          font-size: 100pt!important;
                        }

                        .watermark-center {
                          left: 10px;
                          top: 400px;
                        }

                        {/literal}
                        </style>
                        ';
        } else {
            $wk_is_enabled = FALSE;
            $watermark_css = '<style>
                        {literal}
                        .watermark {
                          position: fixed;
                          z-index: 999;
                          opacity: 0.10;
                          -ms-transform: rotate(-45deg); /* IE 9 */
                          -webkit-transform: rotate(-45deg); /* Chrome, Safari, Opera */
                          transform: rotate(-45deg);
                          font-size: 100pt!important;
                        }

                        .watermark-center {
                          left: 30px;
                          top: 650px;
                        }

                        {/literal}
                        </style>
                        ';
        }
        $smarty->assign('wk_enabled', $wk_is_enabled);
        // prepare watermark
        $watermark_site = '<div class="watermark watermark-center">{if $watermark}{$watermark}{/if}</div>';
        // find </style> element
        $matches = array();
        preg_match('/<\\/style>/', $html, $matches, PREG_OFFSET_CAPTURE);
        if (count($matches) == 1) {
            $head_offset = $matches[0][1];
            $html = substr_replace($html, $watermark_css, $head_offset + strlen($matches[0][0]), 0);
        } else {
            if (count($matches) < 1) {
                CRM_Core_Error::debug_log_message('de.systopia.donrec: watermark css could not be created (</style> not found). falling back to <body>.');
                $matches = array();
                preg_match('/<body>/', $html, $matches, PREG_OFFSET_CAPTURE);
                if (count($matches) == 1) {
                    $head_offset = $matches[0][1];
                    $html = substr_replace($html, $watermark_css, $head_offset, 0);
                } else {
                    CRM_Core_Error::debug_log_message('de.systopia.donrec: watermark could not be created. pdf rendering cancelled.');
                    return FALSE;
                }
            }
        }
        // find <body> element
        $matches = array();
        preg_match('/<body[^>]*>/', $html, $matches, PREG_OFFSET_CAPTURE);
        if (count($matches) == 1) {
            $body_offset = $matches[0][1];
            $html = substr_replace($html, $watermark_site, $body_offset + strlen($matches[0][0]), 0);
        } else {
            if (count($matches) < 1) {
                CRM_Core_Error::debug_log_message('de.systopia.donrec: watermark could not be created for site one (<body> not found). pdf rendering cancelled.');
                return FALSE;
            }
        }
        // --- watermark injection end ---
        // compile template
        $html = $smarty->fetch("string:{$html}");
        // reset template variables
        $smarty->clearTemplateVars();
        // set up file names
        $filename_export = CRM_Donrec_Logic_File::makeFileName(ts("donationreceipt-", array('domain' => 'de.systopia.donrec')) . "{$values['contributor']['id']}-" . date('YmdHis'), ".pdf");
        // render PDF receipt
        $result = file_put_contents($filename_export, CRM_Utils_PDF_Utils::html2pdf($html, null, true, $this->_template->pdf_format_id));
        if ($result) {
            return $filename_export;
        } else {
            $parameters['error'] = "Could not write file {$filename_export}";
            return FALSE;
        }
    }
Пример #8
0
 /**
  * execute the next step of a donation receipt run
  *
  * @return array of stats:
  */
 public function nextStep()
 {
     // some containers
     $exporter_results = array();
     $files = array();
     $profile = $this->snapshot->getProfile();
     // Synchronize this step
     $lock = CRM_Utils_DonrecHelper::getLock('CRM_Donrec_Logic_Engine', 'nextStep');
     if (!$lock->isAcquired()) {
         // lock timed out
         CRM_Core_Error::debug_log_message("de.systopia.donrec - couldn't acquire lock. Timeout is " . $lock->_timeout);
         // compile and return "state of affairs" report
         $stats = $this->createStats();
         $stats['log'] = array();
         $stats['files'] = $files;
         $stats['chunk_size'] = 0;
         CRM_Donrec_Logic_Exporter::addLogEntry($stats, "Couldn't acquire lock. Parallel processing denied. Lock timeout is {$lock->_timeout}s.");
         return $stats;
     }
     // check status
     $is_bulk = !empty($this->parameters['bulk']);
     $is_test = !empty($this->parameters['test']);
     // initialize stuff
     $chunk = $this->snapshot->getNextChunk($is_bulk, $is_test);
     $exporters = $this->getExporters();
     // loop over receipts
     foreach ($chunk as $chunk_id => $chunk_items) {
         // Setup some parameters
         //**********************************
         // Prepare chunk_items:
         // #FIXME: It is more convenient to have a simalar array-structure for bulk-
         // and single-processing. In future the getNextChunk-method might be
         // refactored and build up the arrays correspondingly.
         $chunk_items = $is_bulk ? $chunk_items : array($chunk_items);
         $contact_id = $chunk_items[0]['contact_id'];
         $line_ids = array();
         foreach ($chunk_items as $chunk_item) {
             $line_ids[] = $chunk_item['id'];
         }
         // create a SnapshotReceipt
         $snapshot_receipt = $this->snapshot->getSnapshotReceipt($line_ids, $is_test);
         // call exporters
         //**********************************
         foreach ($exporters as $exporter) {
             $exporter_id = $exporter->getID();
             if ($is_bulk) {
                 $result = $exporter->exportBulk($snapshot_receipt, $is_test);
             } else {
                 $result = $exporter->exportSingle($snapshot_receipt, $is_test);
             }
             if (!isset($exporter_results[$exporter_id])) {
                 $exporter_results[$exporter_id] = array();
                 $exporter_results[$exporter_id]['success'] = 0;
                 $exporter_results[$exporter_id]['failure'] = 0;
             }
             if ($result) {
                 $exporter_results[$exporter_id]['success']++;
             } else {
                 $exporter_results[$exporter_id]['failure']++;
             }
         }
         // save original pdfs and create receipt for non-test-runs
         //**********************************
         if (!$is_test) {
             $receipt_params = array();
             $receipt_params['type'] = $is_bulk ? 'BULK' : 'SINGLE';
             if ($profile->saveOriginalPDF()) {
                 $pdf_file = $this->getPDF($line_ids);
                 $file = CRM_Donrec_Logic_File::createPermanentFile($pdf_file, basename($pdf_file), $contact_id);
                 if (!empty($file)) {
                     $receipt_params['original_file'] = $file['id'];
                 }
             }
             CRM_Donrec_Logic_Receipt::createFromSnapshotReceipt($snapshot_receipt, $receipt_params);
         }
     }
     // The last chunk is empty.
     // If it is the last do some wrap-up.
     // Otherwise mark the chunk as processed.
     //**********************************
     if (!$chunk) {
         foreach ($exporters as $exporter) {
             $result = $exporter->wrapUp($this->snapshot->getId(), $is_test, $is_bulk);
             if (!empty($result['download_name']) && !empty($result['download_url'])) {
                 $files[$exporter->getID()] = array($result['download_name'], $result['download_url']);
             }
         }
     } else {
         $this->snapshot->markChunkProcessed($chunk, $is_test, $is_bulk);
     }
     // compile stats
     //**********************************
     $stats = $this->createStats();
     // create log-messages
     foreach ($exporter_results as $exporter_id => $result) {
         $msg = sprintf('%s processed %d items - %d succeeded, %d failed', $exporter_id, count($chunk), $result['success'], $result['failure']);
         $type = $result['failure'] ? 'ERROR' : 'INFO';
         CRM_Donrec_Logic_Exporter::addLogEntry($stats, $msg, $type);
     }
     $stats['files'] = $files;
     if ($chunk == NULL) {
         $stats['progress'] = 100.0;
     } else {
         $stats['chunk_size'] = count($chunk);
     }
     // release our lock
     $lock->release();
     return $stats;
 }