Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
CsvExporter
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 3
156
0.00% covered (danger)
0.00%
0 / 1
 export
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
90
 getFileExportResponse
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 prependBomCharSet
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2016 (original work) Open Assessment Technologies SA;
19 *
20 */
21
22namespace oat\tao\model\export\implementation;
23
24use GuzzleHttp\Psr7\Response;
25use oat\tao\model\export\PsrResponseExporter;
26use Psr\Http\Message\ResponseInterface;
27use SPLTempFileObject;
28use Traversable;
29
30/**
31 * Class CsvExporter
32 * @author Aleh Hutnikau <hutnikau@1pt.com>
33 * @package oat\tao\model\export
34 */
35class CsvExporter extends AbstractFileExporter implements PsrResponseExporter
36{
37    public const FILE_NAME = 'export.csv';
38    public const CSV_CONTENT_TYPE = 'text/csv; charset=UTF-8';
39
40    /**
41     * @var string value of `Content-Type` header
42     */
43    protected $contentType = self::CSV_CONTENT_TYPE;
44
45    /**
46     * @param boolean $columnNames array keys will be used in the first line of CSV data as column names.
47     * @param boolean $download Deprecated: use getFileExportResponse() and setResponse() in controller
48     * @param string $delimiter sets the field delimiter (one character only).
49     * @param string $enclosure sets the field enclosure (one character only).
50     * @param bool $withoutBom sets BOM char set in case when need to be compatible with Excel
51     * @return string|null
52     * @throws \common_exception_InvalidArgumentType
53     */
54    public function export(
55        $columnNames = false,
56        $download = false,
57        $delimiter = ',',
58        $enclosure = '"',
59        $withoutBom = true
60    ) {
61        $data = $this->data;
62
63        if (!is_array($data) && !$data instanceof Traversable) {
64            throw new \common_exception_InvalidArgumentType('Entity you trying to export is not Traversable');
65        }
66
67        if ($columnNames && $data) {
68            array_unshift($data, array_keys($data[0]));
69        }
70        $file = new SPLTempFileObject();
71        foreach ($data as $row) {
72            $file->fputcsv($row, $delimiter, $enclosure);
73        }
74
75        $file->rewind();
76        $exportData = '';
77        while (!$file->eof()) {
78            $exportData .= $file->fgets();
79        }
80        $exportData = trim($exportData);
81
82        if ($withoutBom === false) {
83            $exportData = $this->prependBomCharSet($exportData);
84        }
85
86        if ($download) {
87            $this->download($exportData, self::FILE_NAME);
88            return null;
89        }
90
91        return $exportData;
92    }
93
94    /**
95     * Returns Psr Response with exported data and proper headers for file download
96     * You can use obtained response to pass it to $this->setResponse() in controller or
97     * emit directly using ResponseEmitter (for special cases)
98     *
99     * @param ResponseInterface|null $originResponse
100     * @param boolean $columnNames array keys will be used in the first line of CSV data as column names.
101     * @param string $delimiter sets the field delimiter (one character only).
102     * @param string $enclosure sets the field enclosure (one character only).
103     * @return ResponseInterface
104     * @throws \common_exception_InvalidArgumentType
105     */
106    public function getFileExportResponse(
107        ResponseInterface $originResponse = null,
108        $columnNames = false,
109        $delimiter = ',',
110        $enclosure = '"'
111    ) {
112        if ($originResponse === null) {
113            $originResponse = new Response();
114        }
115        $exportedString = $this->export($columnNames, false, $delimiter, $enclosure);
116        return $this->preparePsrResponse($originResponse, $exportedString, self::FILE_NAME);
117    }
118
119    private function prependBomCharSet(string $data): string
120    {
121        return "\xEF\xBB\xBF{$data}";
122    }
123}