be2f9ec66b136df3a9082072977c36842d2fe3cd
[moodle.git] / lib / classes / dataformat.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * Class containing utility methods for dataformats
19  *
20  * @package     core
21  * @copyright   2020 Paul Holden <paulh@moodle.com>
22  * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 namespace core;
27 use coding_exception;
28 use core_php_time_limit;
30 /**
31  * Dataformat utility class
32  *
33  * @package     core
34  * @copyright   2020 Paul Holden <paulh@moodle.com>
35  * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36  */
37 class dataformat {
39     /**
40      * Return an instance of a dataformat writer from given dataformat type
41      *
42      * @param string $dataformat
43      * @return dataformat\base
44      * @throws coding_exception
45      */
46     protected static function get_format_instance(string $dataformat): \core\dataformat\base {
47         $classname = 'dataformat_' . $dataformat . '\writer';
48         if (!class_exists($classname)) {
49             throw new coding_exception('Invalid dataformat', $dataformat);
50         }
52         return new $classname();
53     }
55     /**
56      * Sends a formatted data file to the browser
57      *
58      * @param string $filename
59      * @param string $dataformat
60      * @param array $columns
61      * @param Iterable $iterator
62      * @param callable|null $callback
63      * @throws coding_exception
64      */
65     public static function download_data(string $filename, string $dataformat, array $columns, Iterable $iterator,
66             callable $callback = null): void {
68         if (ob_get_length()) {
69             throw new coding_exception('Output can not be buffered before calling download_data()');
70         }
72         $format = self::get_format_instance($dataformat);
74         // The data format export could take a while to generate.
75         core_php_time_limit::raise();
77         // Close the session so that the users other tabs in the same session are not blocked.
78         \core\session\manager::write_close();
80         // If this file was requested from a form, then mark download as complete (before sending headers).
81         \core_form\util::form_download_complete();
83         $format->set_filename($filename);
84         $format->send_http_headers();
86         $format->start_output();
87         $format->start_sheet($columns);
89         $rownum = 0;
90         foreach ($iterator as $row) {
91             if (is_callable($callback)) {
92                 $row = $callback($row);
93             }
94             if ($row === null) {
95                 continue;
96             }
97             $format->write_record($row, $rownum++);
98         }
100         $format->close_sheet($columns);
101         $format->close_output();
102     }
104     /**
105      * Writes a formatted data file with specified filename
106      *
107      * @param string $filename
108      * @param string $dataformat
109      * @param array $columns
110      * @param Iterable $iterator
111      * @param callable|null $callback
112      * @return string Complete path to the file on disk
113      */
114     public static function write_data(string $filename, string $dataformat, array $columns, Iterable $iterator,
115             callable $callback = null): string {
117         $format = self::get_format_instance($dataformat);
119         // The data format export could take a while to generate.
120         core_php_time_limit::raise();
122         // Close the session so that the users other tabs in the same session are not blocked.
123         \core\session\manager::write_close();
125         $filepath = make_request_directory() . '/' . $filename . $format->get_extension();
126         $format->set_filepath($filepath);
128         $format->start_output_to_file();
129         $format->start_sheet($columns);
131         $rownum = 0;
132         foreach ($iterator as $row) {
133             if (is_callable($callback)) {
134                 $row = $callback($row);
135             }
136             if ($row === null) {
137                 continue;
138             }
139             $format->write_record($row, $rownum++);
140         }
142         $format->close_sheet($columns);
143         $format->close_output_to_file();
145         return $filepath;
146     }