MDL-68500 dataformat: re-factor download/export methods into new class.
[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
21 * @copyright 2020 Moodle Pty Ltd <support@moodle.com>
22 * @author 2020 Paul Holden <paulh@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 * @license Moodle Workplace License, distribution is restricted, contact support@moodle.com
25 */
26
27namespace core;
28
29use coding_exception;
30use core_php_time_limit;
31
32/**
33 * Dataformat utility class
34 *
35 * @package core
36 * @copyright 2020 Moodle Pty Ltd <support@moodle.com>
37 * @author 2020 Paul Holden <paulh@moodle.com>
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 * @license Moodle Workplace License, distribution is restricted, contact support@moodle.com
40 */
41class dataformat {
42
43 /**
44 * Return an instead of a dataformat writer from given dataformat type
45 *
46 * @param string $dataformat
47 * @return dataformat\base
48 * @throws coding_exception
49 */
50 protected static function get_format_instance(string $dataformat): \core\dataformat\base {
51 $classname = 'dataformat_' . $dataformat . '\writer';
52 if (!class_exists($classname)) {
53 throw new coding_exception('Invalid dataformat', $dataformat);
54 }
55
56 return new $classname();
57 }
58
59 /**
60 * Sends a formatted data file to the browser
61 *
62 * @param string $filename
63 * @param string $dataformat
64 * @param array $columns
65 * @param Iterable $iterator
66 * @param callable|null $callback
67 * @throws coding_exception
68 */
69 public static function download_data(string $filename, string $dataformat, array $columns, Iterable $iterator,
70 callable $callback = null): void {
71
72 if (ob_get_length()) {
73 throw new coding_exception('Output can not be buffered before calling download_data()');
74 }
75
76 $format = self::get_format_instance($dataformat);
77
78 // The data format export could take a while to generate.
79 core_php_time_limit::raise();
80
81 // Close the session so that the users other tabs in the same session are not blocked.
82 \core\session\manager::write_close();
83
84 // If this file was requested from a form, then mark download as complete (before sending headers).
85 \core_form\util::form_download_complete();
86
87 $format->set_filename($filename);
88 $format->send_http_headers();
89
90 $format->start_output();
91 $format->start_sheet($columns);
92
93 $rownum = 0;
94 foreach ($iterator as $row) {
95 if (is_callable($callback)) {
96 $row = $callback($row);
97 }
98 if ($row === null) {
99 continue;
100 }
101 $format->write_record($row, $rownum++);
102 }
103
104 $format->close_sheet($columns);
105 $format->close_output();
106 }
107
108 /**
109 * Writes a formatted data file with specified filename
110 *
111 * @param string $filename
112 * @param string $dataformat
113 * @param array $columns
114 * @param Iterable $iterator
115 * @param callable|null $callback
116 * @return string Complete path to the file on disk
117 */
118 public static function write_data(string $filename, string $dataformat, array $columns, Iterable $iterator,
119 callable $callback = null): string {
120
121 $format = self::get_format_instance($dataformat);
122
123 // The data format export could take a while to generate.
124 core_php_time_limit::raise();
125
126 // Close the session so that the users other tabs in the same session are not blocked.
127 \core\session\manager::write_close();
128
129 $filepath = make_request_directory() . '/' . $filename . $format->get_extension();
130 $format->set_filepath($filepath);
131
132 $format->start_output_to_file();
133 $format->start_sheet($columns);
134
135 $rownum = 0;
136 foreach ($iterator as $row) {
137 if (is_callable($callback)) {
138 $row = $callback($row);
139 }
140 if ($row === null) {
141 continue;
142 }
143 $format->write_record($row, $rownum++);
144 }
145
146 $format->close_sheet($columns);
147 $format->close_output_to_file();
148
149 return $filepath;
150 }
151}