weekly release 4.0dev
[moodle.git] / lib / classes / dataformat.php
CommitLineData
8844cb82
PH
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/>.
16
17/**
18 * Class containing utility methods for dataformats
19 *
20 * @package core
c1c57e81 21 * @copyright 2020 Paul Holden <paulh@moodle.com>
8844cb82 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
8844cb82
PH
23 */
24
25namespace core;
26
27use coding_exception;
28use core_php_time_limit;
29
30/**
31 * Dataformat utility class
32 *
33 * @package core
c1c57e81 34 * @copyright 2020 Paul Holden <paulh@moodle.com>
8844cb82 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
8844cb82
PH
36 */
37class dataformat {
38
39 /**
c1c57e81 40 * Return an instance of a dataformat writer from given dataformat type
8844cb82
PH
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 }
51
52 return new $classname();
53 }
54
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 {
67
68 if (ob_get_length()) {
69 throw new coding_exception('Output can not be buffered before calling download_data()');
70 }
71
72 $format = self::get_format_instance($dataformat);
73
74 // The data format export could take a while to generate.
75 core_php_time_limit::raise();
76
77 // Close the session so that the users other tabs in the same session are not blocked.
78 \core\session\manager::write_close();
79
80 // If this file was requested from a form, then mark download as complete (before sending headers).
81 \core_form\util::form_download_complete();
82
83 $format->set_filename($filename);
84 $format->send_http_headers();
85
86 $format->start_output();
87 $format->start_sheet($columns);
88
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 }
99
100 $format->close_sheet($columns);
101 $format->close_output();
102 }
103
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 {
116
117 $format = self::get_format_instance($dataformat);
118
119 // The data format export could take a while to generate.
120 core_php_time_limit::raise();
121
122 // Close the session so that the users other tabs in the same session are not blocked.
123 \core\session\manager::write_close();
124
125 $filepath = make_request_directory() . '/' . $filename . $format->get_extension();
126 $format->set_filepath($filepath);
127
128 $format->start_output_to_file();
129 $format->start_sheet($columns);
130
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 }
141
142 $format->close_sheet($columns);
143 $format->close_output_to_file();
144
145 return $filepath;
146 }
147}