]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/IO/CsvOut.php
a49f410609933ba767ff0fd9b01d2b544197074d
[galette.git] / galette / lib / Galette / IO / CsvOut.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * CSV exports
7 *
8 * PHP version 5
9 *
10 * Copyright © 2009-2014 The Galette Team
11 *
12 * This file is part of Galette (http://galette.tuxfamily.org).
13 *
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
26 *
27 * @category IO
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2009-2014 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @version SVN: $Id$
34 * @link http://galette.tuxfamily.org
35 * @since Disponible depuis la Release 0.7alpha - 2009-02-09
36 */
37
38 namespace Galette\IO;
39
40 use Analog\Analog;
41 use Laminas\Db\Adapter\Adapter;
42
43 /**
44 * CSV exports
45 *
46 * @category IO
47 * @name Csv
48 * @package Galette
49 * @author Johan Cwiklinski <johan@x-tnd.be>
50 * @copyright 2009-2014 The Galette Team
51 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
52 * @link http://galette.tuxfamily.org
53 * @since Disponible depuis la Release 0.7alpha - 2009-02-09
54 */
55
56 class CsvOut extends Csv
57 {
58 const DEFAULT_DIRECTORY = GALETTE_EXPORTS_PATH;
59
60 private $rs;
61 private $parameted_path;
62 private $parameted_file = 'exports.xml';
63
64 /**
65 * Default constructor
66 */
67 public function __construct()
68 {
69 parent::__construct(self::DEFAULT_DIRECTORY);
70 $this->parameted_path = GALETTE_CONFIG_PATH;
71 $this->parameted_file = $this->parameted_path . $this->parameted_file;
72 }
73
74 /**
75 * Export Array result set to CSV
76 *
77 * @param array $rs Results as an array
78 * @param string $separator The CSV separator (either '\t', ';' or ','
79 * are accepted)
80 * @param char $quote how does fields should be quoted
81 * @param bool $titles does export shows column titles or not.
82 * Defaults to false.
83 * @param object $file export to a file on disk. A file pointer
84 * should be passed here. Defaults to false.
85 *
86 * @return string CSV result
87 */
88 public function export($rs, $separator, $quote, $titles = false, $file = false)
89 {
90 if (!$rs) {
91 return '';
92 }
93 //switch back to the default separator if not in accepted_separators array
94 if (!in_array($separator, $this->accepted_separators)) {
95 $separator = self::DEFAULT_SEPARATOR;
96 }
97 //switch back to the default quote if not in accepted_quotes array
98 if (!in_array($quote, $this->accepted_quotes)) {
99 $quote = self::DEFAULT_QUOTE;
100 }
101
102 $this->result = '';
103 $results = [];
104 foreach ($rs as $row) {
105 $results[] = $row;
106 }
107 $this->max = count($results);
108 $this->separator = $separator;
109 $this->quote = $quote;
110 //dubbing quote for escaping
111 $this->escaped = $quote . $quote;
112 $this->file = $file;
113 $this->current_line = 0;
114
115 $fields = array();
116 if ($titles && !is_array($titles)) {
117 $row = $results[0];
118 foreach (array_keys((array)$row) as $field) {
119 $fields[] = $this->quote . str_replace(
120 $this->quote,
121 $this->escaped,
122 $field
123 ) . $this->quote;
124 }
125 $this->result .= implode($this->separator, $fields) . self::NEWLINE;
126 } elseif ($titles && is_array($titles) && count($titles) > 1) {
127 foreach ($titles as $field) {
128 $field = str_replace(
129 array(':', '&nbsp;'),
130 '',
131 $field
132 );
133 $fields[] = $this->quote . str_replace(
134 $this->quote,
135 $this->escaped,
136 $field
137 ) . $this->quote;
138 }
139 $this->result .= implode($this->separator, $fields) . self::NEWLINE;
140 }
141
142 foreach ($results as $row) {
143 $elts = array();
144
145 if (is_array($row) || is_object($row)) {
146 foreach ($row as $v) {
147 $elts[] = $this->quote . str_replace(
148 $this->quote,
149 $this->escaped,
150 $v
151 ) . $this->quote;
152 }
153
154 $this->result .= implode($this->separator, $elts) . self::NEWLINE;
155
156 $this->current_line += 1;
157
158 $this->write();
159 }
160 }
161 $this->write(true);
162 return $this->result;
163 }
164
165 /**
166 * Write export.
167 * If a file is defined, export will be outpoutted into it.
168 * If not, it will be returned
169 *
170 * @param bool $last true if we write the latest line
171 *
172 * @return void
173 */
174 private function write($last = false)
175 {
176 if (
177 $last && $this->file
178 || !$last && $this->file
179 && ($this->current_line % self::BUFLINES) == 0
180 ) {
181 if ($this->file === true) {
182 echo $this->result;
183 } else {
184 fwrite($this->file, $this->result);
185 }
186 $this->result = '';
187 }
188 }
189
190 /**
191 * Retrieve parameted export name
192 *
193 * @param string $id Parameted export identifier
194 *
195 * @return string
196 */
197 public function getParamedtedExportName($id)
198 {
199 $xml = simplexml_load_file($this->parameted_file);
200 $xpath = $xml->xpath(
201 '/exports/export[@id=\'' . $id . '\'][1]/@name'
202 );
203 return (string)$xpath[0];
204 }
205
206 /**
207 * Get al list of all parameted exports
208 *
209 * @return array
210 */
211 public function getParametedExports()
212 {
213 $parameted = array();
214
215 $xml = simplexml_load_file($this->parameted_file);
216
217 foreach ($xml->export as $export) {
218 if (!($export['inactive'] == 'inactive')) {
219 $parameted[] = array(
220 'id' => (string)$export['id'],
221 'name' => (string)$export['name'],
222 'description' => (string)$export['description']
223 );
224 }
225 }
226 return $parameted;
227 }
228
229 /**
230 * Run selected export
231 *
232 * @param string $id export's id to run
233 *
234 * @return string filename used
235 */
236 public function runParametedExport($id)
237 {
238 global $zdb;
239
240 $xml = simplexml_load_file($this->parameted_file);
241
242 $xpath = $xml->xpath(
243 '/exports/export[@id=\'' . $id . '\'][not(@inactive)][1]'
244 );
245 $export = $xpath[0];
246
247 try {
248 $results = $zdb->db->query(
249 str_replace('galette_', PREFIX_DB, $export->query),
250 Adapter::QUERY_MODE_EXECUTE
251 );
252
253 $filename = self::DEFAULT_DIRECTORY . $export['filename'];
254
255 $fp = fopen($filename, 'w');
256 if ($fp) {
257 $separator = ($export->separator)
258 ? $export->separator
259 : self::DEFAULT_SEPARATOR;
260 $quote = ($export->quote) ? $export->quote : self::DEFAULT_QUOTE;
261 if ($export->headers->none) {
262 //No title
263 $title = false;
264 } else {
265 $xpath = $export->xpath('headers/header');
266 if (count($xpath) == 0) {
267 //show titles
268 $title = true;
269 } else {
270 //titles from array
271 foreach ($xpath as $header) {
272 $title[] = (string)$header;
273 }
274 }
275 }
276
277 $this->export($results, $separator, $quote, $title, $fp);
278 fclose($fp);
279 } else {
280 Analog::log(
281 'File ' . $filename . ' is not writeable.',
282 Analog::ERROR
283 );
284 return self::FILE_NOT_WRITABLE;
285 }
286 return $export['filename'];
287 } catch (\Exception $e) {
288 Analog::log(
289 'An error occurred while exporting | ' . $e->getMessage(),
290 Analog::ERROR
291 );
292 return self::DB_ERROR;
293 }
294 }
295 }