Merge pull request #15748 from eileenmcnaughton/line_item_belt_braces
[civicrm-core.git] / CRM / Financial / BAO / ExportFormat.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2019
32 */
33
34 /**
35 * Base class for Export Formats
36 * Create a subclass for a specific format.
37 * @see http://wiki.civicrm.org/confluence/display/CRM/CiviAccounts+Specifications+-++Batches#CiviAccountsSpecifications-Batches-%C2%A0Overviewofimplementation
38 */
39 abstract class CRM_Financial_BAO_ExportFormat {
40
41 /**
42 * data which the individual export formats will output in the desired format.
43 * @var array
44 */
45 protected $_exportParams;
46
47 /**
48 * smarty template.
49 * @var CRM_Core_Smarty
50 */
51 static protected $_template;
52
53 /**
54 * Download Exported file.
55 * @var bool
56 */
57 public $_isDownloadFile;
58
59 /**
60 * Class constructor.
61 */
62 public function __construct() {
63 if (!isset(self::$_template)) {
64 self::$_template = CRM_Core_Smarty::singleton();
65 }
66 }
67
68 /**
69 * Override to assemble the appropriate subset of financial data for the specific export format.
70 * @param array $exportParams
71 *
72 * @return mixed
73 */
74 public function export($exportParams) {
75 $this->_exportParams = $exportParams;
76 return $exportParams;
77 }
78
79 /**
80 * Exports sbatches in $this->_batchIds, and saves to file.
81 *
82 * @param string $fileName - use this file name (if applicable)
83 */
84 public function output($fileName = NULL) {
85 // Default behaviour, override if needed:
86 self::createActivityExport($this->_batchIds, $fileName);
87 }
88
89 /**
90 * Abstract function that generates exports, and downloads them as zip file.
91 *
92 * @param $exportDaos array with DAO's for queries to be exported.
93 */
94 abstract public function makeExport($exportDaos);
95
96 /**
97 * @return string
98 */
99 public function getMimeType() {
100 return 'text/plain';
101 }
102
103 /**
104 * Returns some kind of identification for your export format.
105 *
106 * This does not really has to be a file extension, you can name your
107 * file as you wish as you override output.
108 *
109 * @return string
110 */
111 abstract public function getFileExtension();
112
113 /**
114 * @return object
115 */
116 public static function &getTemplate() {
117 return self::$_template;
118 }
119
120 /**
121 * @param $var
122 * @param null $value
123 */
124 public function assign($var, $value = NULL) {
125 self::$_template->assign($var, $value);
126 }
127
128 /*
129 * This gets called for every item of data being compiled before being sent to the exporter for output.
130 *
131 * Depending on the output format might want to override this, e.g. for IIF tabs need to be escaped etc,
132 * but for CSV it doesn't make sense because php has built in csv output functions.
133 */
134
135 /**
136 * @param $s
137 * @param string $type
138 *
139 * @return null
140 */
141 public static function format($s, $type = 'string') {
142 if (!empty($s)) {
143 return $s;
144 }
145 else {
146 return NULL;
147 }
148 }
149
150 public function initiateDownload() {
151 if (!$this->_isDownloadFile) {
152 return NULL;
153 }
154 $config = CRM_Core_Config::singleton();
155 // zip files if more than one.
156 if (count($this->_downloadFile) > 1) {
157 $zip = $config->customFileUploadDir . 'Financial_Transactions_' . date('YmdHis') . '.zip';
158 $result = $this->createZip($this->_downloadFile, $zip, TRUE);
159 if ($result) {
160 CRM_Utils_System::setHttpHeader('Content-Type', 'application/zip');
161 CRM_Utils_System::setHttpHeader('Content-Disposition', 'attachment; filename=' . CRM_Utils_File::cleanFileName(basename($zip)));
162 CRM_Utils_System::setHttpHeader('Content-Length', '' . filesize($zip));
163 ob_clean();
164 flush();
165 readfile($config->customFileUploadDir . CRM_Utils_File::cleanFileName(basename($zip)));
166 //delete the zip to avoid clutter.
167 unlink($zip);
168 CRM_Utils_System::civiExit();
169 }
170 }
171 else {
172 CRM_Utils_System::setHttpHeader('Content-Type', 'text/plain');
173 CRM_Utils_System::setHttpHeader('Content-Disposition', 'attachment; filename=' . CRM_Utils_File::cleanFileName(basename($this->_downloadFile[0])));
174 CRM_Utils_System::setHttpHeader('Content-Length', '' . filesize($this->_downloadFile[0]));
175 ob_clean();
176 flush();
177 readfile($config->customFileUploadDir . CRM_Utils_File::cleanFileName(basename($this->_downloadFile[0])));
178 CRM_Utils_System::civiExit();
179 }
180 }
181
182 /**
183 * @param $batchIds
184 * @param string $fileName
185 *
186 * @throws CRM_Core_Exception
187 */
188 public static function createActivityExport($batchIds, $fileName) {
189 $session = CRM_Core_Session::singleton();
190 $values = [];
191 $params = ['id' => $batchIds];
192 CRM_Batch_BAO_Batch::retrieve($params, $values);
193 $createdBy = CRM_Contact_BAO_Contact::displayName($values['created_id']);
194 $modifiedBy = CRM_Contact_BAO_Contact::displayName($values['modified_id']);
195
196 $values['payment_instrument_id'] = '';
197 if (isset($values['payment_instrument_id'])) {
198 $paymentInstrument = array_flip(CRM_Contribute_PseudoConstant::paymentInstrument('label'));
199 $values['payment_instrument_id'] = array_search($values['payment_instrument_id'], $paymentInstrument);
200 }
201 $details = '<p>' . ts('Record:') . ' ' . $values['title'] . '</p><p>' . ts('Description:') . '</p><p>' . ts('Created By:') . " $createdBy" . '</p><p>' . ts('Created Date:') . ' ' . $values['created_date'] . '</p><p>' . ts('Last Modified By:') . ' ' . $modifiedBy . '</p><p>' . ts('Payment Method:') . ' ' . $values['payment_instrument_id'] . '</p>';
202 $subject = '';
203 if (!empty($values['total'])) {
204 $subject .= ts('Total') . '[' . CRM_Utils_Money::format($values['total']) . '],';
205 }
206 if (!empty($values['item_count'])) {
207 $subject .= ' ' . ts('Count') . '[' . $values['item_count'] . '],';
208 }
209
210 // create activity.
211 $subject .= ' ' . ts('Batch') . '[' . $values['title'] . ']';
212 $activityParams = [
213 'activity_type_id' => 'Export Accounting Batch',
214 'subject' => $subject,
215 'status_id' => 'Completed',
216 'activity_date_time' => date('YmdHis'),
217 'source_contact_id' => $session->get('userID'),
218 'source_record_id' => $values['id'],
219 'target_contact_id' => $session->get('userID'),
220 'details' => $details,
221 'attachFile_1' => [
222 'uri' => $fileName,
223 'type' => 'text/csv',
224 'location' => $fileName,
225 'upload_date' => date('YmdHis'),
226 ],
227 ];
228 civicrm_api3('Activity', 'create', $activityParams);
229 }
230
231 /**
232 * @param array $files
233 * @param null $destination
234 * @param bool $overwrite
235 *
236 * @return bool
237 */
238 public function createZip($files = [], $destination = NULL, $overwrite = FALSE) {
239 // if the zip file already exists and overwrite is false, return false
240 if (file_exists($destination) && !$overwrite) {
241 return FALSE;
242 }
243 $valid_files = [];
244 if (is_array($files)) {
245 foreach ($files as $file) {
246 // make sure the file exists
247 if (file_exists($file)) {
248 $validFiles[] = $file;
249 }
250 }
251 }
252 if (count($validFiles)) {
253 $zip = new ZipArchive();
254 if ($zip->open($destination, $overwrite ? ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== TRUE) {
255 return FALSE;
256 }
257 foreach ($validFiles as $file) {
258 $zip->addFile($file, CRM_Utils_File::cleanFileName(basename($file)));
259 }
260 $zip->close();
261 return file_exists($destination);
262 }
263 else {
264 return FALSE;
265 }
266 }
267
268 }