Passed
Push — master ( c75c2f...f693d1 )
by Julito
09:48
created

Export::htmlToOdt()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 50
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 34
nc 6
nop 3
dl 0
loc 50
rs 9.0648
c 0
b 0
f 0
1
<?php
2
/* See license terms in /license.txt */
3
4
use Chamilo\CoreBundle\Component\Editor\Connector;
5
use Chamilo\CoreBundle\Component\Filesystem\Data;
6
use MediaAlchemyst\Alchemyst;
7
use MediaAlchemyst\DriversContainer;
8
use Neutron\TemporaryFilesystem\Manager;
9
use Neutron\TemporaryFilesystem\TemporaryFilesystem;
10
use Sonata\Exporter\Handler;
11
use Sonata\Exporter\Source\ArraySourceIterator;
12
use Sonata\Exporter\Writer\CsvWriter;
13
use Sonata\Exporter\Writer\XlsWriter;
14
use Symfony\Component\Filesystem\Filesystem;
15
16
/**
17
 *  This is the export library for Chamilo.
18
 *  Include/require it in your code to use its functionality.
19
 */
20
class Export
21
{
22
    /**
23
     * Constructor.
24
     */
25
    public function __construct()
26
    {
27
    }
28
29
    /**
30
     * Export tabular data to CSV-file.
31
     *
32
     * @param array  $data
33
     * @param string $filename
34
     * @param bool   $writeOnly Whether to only write on disk or also send for download
35
     * @param string $enclosure
36
     *
37
     * @return mixed csv raw data | false if no data to export | string file path if success in $writeOnly mode
38
     */
39
    public static function arrayToCsv($data, $filename = 'export', $writeOnly = false, $enclosure = '"')
40
    {
41
        if (empty($data)) {
42
            return false;
43
        }
44
45
        $enclosure = !empty($enclosure) ? $enclosure : '"';
46
        $filePath = api_get_path(SYS_ARCHIVE_PATH).uniqid('').'.csv';
47
        $writer = new CsvWriter($filePath, ';', $enclosure, true);
48
49
        $source = new ArraySourceIterator($data);
50
        $handler = Handler::create($source, $writer);
51
        $handler->export();
52
53
        if (!$writeOnly) {
54
            DocumentManager::file_send_for_download($filePath, true, $filename.'.csv');
55
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
56
        }
57
58
        return $filePath;
59
    }
60
61
    /**
62
     * Export tabular data to XLS-file.
63
     *
64
     * @param array  $data
65
     * @param string $filename
66
     */
67
    public static function arrayToXls($data, $filename = 'export')
68
    {
69
        if (empty($data)) {
70
            return false;
71
        }
72
73
        $filePath = api_get_path(SYS_ARCHIVE_PATH).uniqid('').'.xlsx';
74
        $writer = new XlsWriter($filePath);
75
        $source = new ArraySourceIterator($data);
76
        $handler = Handler::create($source, $writer);
77
        $handler->export();
78
79
        DocumentManager::file_send_for_download($filePath, true, $filename.'.xlsx');
80
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
81
    }
82
83
    /**
84
     * Export tabular data to XLS-file (as html table).
85
     *
86
     * @param array  $data
87
     * @param string $filename
88
     */
89
    public static function export_table_xls_html($data, $filename = 'export', $encoding = 'utf-8')
90
    {
91
        $file = api_get_path(SYS_ARCHIVE_PATH).uniqid('').'.xls';
92
        $handle = fopen($file, 'a+');
93
        $systemEncoding = api_get_system_encoding();
94
        fwrite($handle, '<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html" charset="'.$encoding.'" /><body><table>');
0 ignored issues
show
Bug introduced by
It seems like $handle can also be of type false; however, parameter $handle of fwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

94
        fwrite(/** @scrutinizer ignore-type */ $handle, '<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html" charset="'.$encoding.'" /><body><table>');
Loading history...
95
        foreach ($data as $id => $row) {
96
            foreach ($row as $id2 => $row2) {
97
                $data[$id][$id2] = api_htmlentities($row2);
98
            }
99
        }
100
        foreach ($data as $row) {
101
            $string = implode("</td><td>", $row);
102
            $string = '<tr><td>'.$string.'</td></tr>';
103
            if ($encoding != 'utf-8') {
104
                $string = api_convert_encoding($string, $encoding, $systemEncoding);
105
            }
106
            fwrite($handle, $string."\n");
107
        }
108
        fwrite($handle, '</table></body></html>');
109
        fclose($handle);
0 ignored issues
show
Bug introduced by
It seems like $handle can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

109
        fclose(/** @scrutinizer ignore-type */ $handle);
Loading history...
110
        DocumentManager::file_send_for_download($file, true, $filename.'.xls');
111
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
112
    }
113
114
    /**
115
     * Export tabular data to XML-file.
116
     *
117
     * @param array  Simple array of data to put in XML
118
     * @param string Name of file to be given to the user
119
     * @param string Name of common tag to place each line in
120
     * @param string Name of the root element. A root element should always be given.
121
     * @param string Encoding in which the data is provided
122
     */
123
    public static function arrayToXml(
124
        $data,
125
        $filename = 'export',
126
        $item_tagname = 'item',
127
        $wrapper_tagname = null,
128
        $encoding = null
129
    ) {
130
        if (empty($encoding)) {
131
            $encoding = api_get_system_encoding();
132
        }
133
        $file = api_get_path(SYS_ARCHIVE_PATH).'/'.uniqid('').'.xml';
134
        $handle = fopen($file, 'a+');
135
        fwrite($handle, '<?xml version="1.0" encoding="'.$encoding.'"?>'."\n");
0 ignored issues
show
Bug introduced by
It seems like $handle can also be of type false; however, parameter $handle of fwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

135
        fwrite(/** @scrutinizer ignore-type */ $handle, '<?xml version="1.0" encoding="'.$encoding.'"?>'."\n");
Loading history...
136
        if (!is_null($wrapper_tagname)) {
137
            fwrite($handle, "\t".'<'.$wrapper_tagname.'>'."\n");
138
        }
139
        foreach ($data as $row) {
140
            fwrite($handle, '<'.$item_tagname.'>'."\n");
141
            foreach ($row as $key => $value) {
142
                fwrite($handle, "\t\t".'<'.$key.'>'.$value.'</'.$key.'>'."\n");
143
            }
144
            fwrite($handle, "\t".'</'.$item_tagname.'>'."\n");
145
        }
146
        if (!is_null($wrapper_tagname)) {
147
            fwrite($handle, '</'.$wrapper_tagname.'>'."\n");
148
        }
149
        fclose($handle);
0 ignored issues
show
Bug introduced by
It seems like $handle can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

149
        fclose(/** @scrutinizer ignore-type */ $handle);
Loading history...
150
        DocumentManager::file_send_for_download($file, true, $filename.'.xml');
151
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
152
    }
153
154
    /**
155
     * @param array $data table to be read with the HTML_table class
156
     */
157
    public static function export_table_pdf($data, $params = [])
158
    {
159
        $table_html = self::convert_array_to_html($data, $params);
160
        $params['format'] = isset($params['format']) ? $params['format'] : 'A4';
161
        $params['orientation'] = isset($params['orientation']) ? $params['orientation'] : 'P';
162
163
        $pdf = new PDF($params['format'], $params['orientation'], $params);
164
        $pdf->html_to_pdf_with_template($table_html);
165
    }
166
167
    /**
168
     * @param string $html
169
     * @param array  $params
170
     */
171
    public static function export_html_to_pdf($html, $params = [])
172
    {
173
        $params['format'] = isset($params['format']) ? $params['format'] : 'A4';
174
        $params['orientation'] = isset($params['orientation']) ? $params['orientation'] : 'P';
175
176
        $pdf = new PDF($params['format'], $params['orientation'], $params);
177
        $pdf->html_to_pdf_with_template($html);
178
    }
179
180
    /**
181
     * @param array $data
182
     * @param array $params
183
     *
184
     * @return string
185
     */
186
    public static function convert_array_to_html($data, $params = [])
187
    {
188
        $headers = $data[0];
189
        unset($data[0]);
190
191
        $header_attributes = isset($params['header_attributes']) ? $params['header_attributes'] : [];
192
        $table = new HTML_Table(['class' => 'data_table', 'repeat_header' => '1']);
193
        $row = 0;
194
        $column = 0;
195
        foreach ($headers as $header) {
196
            $table->setHeaderContents($row, $column, $header);
197
            $attributes = [];
198
            if (isset($header_attributes) && isset($header_attributes[$column])) {
199
                $attributes = $header_attributes[$column];
200
            }
201
            if (!empty($attributes)) {
202
                $table->updateCellAttributes($row, $column, $attributes);
203
            }
204
            $column++;
205
        }
206
        $row++;
207
        foreach ($data as &$printable_data_row) {
208
            $column = 0;
209
            foreach ($printable_data_row as &$printable_data_cell) {
210
                $table->setCellContents($row, $column, $printable_data_cell);
211
                //$table->updateCellAttributes($row, $column, $atributes);
212
                $column++;
213
            }
214
            $table->updateRowAttributes($row, $row % 2 ? 'class="row_even"' : 'class="row_odd"', true);
215
            $row++;
216
        }
217
        $table_tp_html = $table->toHtml();
218
219
        return $table_tp_html;
220
    }
221
222
    /**
223
     * Export HTML content in a ODF document.
224
     *
225
     * @param string $html
226
     * @param string $name
227
     * @param string $format
228
     *
229
     * @return bool
230
     */
231
    public static function htmlToOdt($html, $name, $format = 'odt')
232
    {
233
        $unoconv = api_get_configuration_value('unoconv.binaries');
234
235
        if (empty($unoconv)) {
236
            return false;
237
        }
238
239
        if (!empty($html)) {
240
            $fs = new Filesystem();
241
            $paths = [
242
                'root_sys' => api_get_path(SYS_PATH),
243
                'path.temp' => api_get_path(SYS_ARCHIVE_PATH),
244
            ];
245
            $connector = new Connector();
0 ignored issues
show
Bug introduced by
The call to Chamilo\CoreBundle\Compo...onnector::__construct() has too few arguments starting with entityManager. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

245
            $connector = /** @scrutinizer ignore-call */ new Connector();

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
246
247
            $drivers = new DriversContainer();
248
            $drivers['configuration'] = [
249
                'unoconv.binaries' => $unoconv,
250
                'unoconv.timeout' => 60,
251
            ];
252
253
            $tempFilesystem = TemporaryFilesystem::create();
254
            $manager = new Manager($tempFilesystem, $fs);
255
            $alchemyst = new Alchemyst($drivers, $manager);
256
257
            $dataFileSystem = new Data($paths, $fs, $connector, $alchemyst);
258
            $content = $dataFileSystem->convertRelativeToAbsoluteUrl($html);
259
            $filePath = $dataFileSystem->putContentInTempFile(
260
                $content,
261
                api_replace_dangerous_char($name),
262
                'html'
263
            );
264
265
            $try = true;
266
267
            while ($try) {
268
                try {
269
                    $convertedFile = $dataFileSystem->transcode(
270
                        $filePath,
271
                        $format
272
                    );
273
274
                    $try = false;
275
                    DocumentManager::file_send_for_download(
276
                        $convertedFile,
277
                        false,
278
                        $name.'.'.$format
279
                    );
280
                } catch (Exception $e) {
281
                    // error_log($e->getMessage());
282
                }
283
            }
284
        }
285
    }
286
}
287