. /** * dataformatlib.php - Contains core dataformat related functions. * * @package core * @subpackage dataformat * @copyright 2016 Brendan Heywood (brendan@catalyst-au.net) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ /** * Sends a formated data file to the browser * * @package core * @subpackage dataformat * * @param string $filename The base filename without an extension * @param string $dataformat A dataformat name * @param array $columns An ordered map of column keys and labels * @param Iterator $iterator An iterator over the records, usually a RecordSet * @param callable $callback An option function applied to each record before writing * @throws coding_exception */ function download_as_dataformat($filename, $dataformat, $columns, $iterator, $callback = null) { if (ob_get_length()) { throw new coding_exception("Output can not be buffered before calling download_as_dataformat"); } $classname = 'dataformat_' . $dataformat . '\writer'; if (!class_exists($classname)) { throw new coding_exception("Unable to locate dataformat/$dataformat/classes/writer.php"); } // The data format export could take a while to generate... core_php_time_limit::raise(); // Close the session so that the users other tabs in the same session are not blocked. \core\session\manager::write_close(); // If this file was requested from a form, then mark download as complete (before sending headers). \core_form\util::form_download_complete(); /** @var \core\dataformat\base $format */ $format = new $classname; $format->set_filename($filename); $format->send_http_headers(); // This exists to support all dataformats - see MDL-56046. if (!method_exists($format, 'start_output') && method_exists($format, 'write_header')) { debugging('The function write_header() does not support multiple sheets. In order to support multiple sheets you ' . 'must implement start_output() and start_sheet() and remove write_header() in your dataformat.', DEBUG_DEVELOPER); $format->write_header($columns); } else { $format->start_output(); $format->start_sheet($columns); } $c = 0; foreach ($iterator as $row) { if ($callback) { $row = $callback($row); } if ($row === null) { continue; } $format->write_record($row, $c++); } // This exists to support all dataformats - see MDL-56046. if (!method_exists($format, 'close_output') && method_exists($format, 'write_footer')) { debugging('The function write_footer() does not support multiple sheets. In order to support multiple sheets you ' . 'must implement close_sheet() and close_output() and remove write_footer() in your dataformat.', DEBUG_DEVELOPER); $format->write_footer($columns); } else { $format->close_sheet($columns); $format->close_output(); } } /** * Writes a formatted data file to specified path * * @package core * @subpackage dataformat * * @param string $filename The base filename without an extension * @param string $dataformat A dataformat name * @param array $columns An ordered map of column keys and labels * @param Iterator $iterator An iterator over the records, usually a RecordSet * @param callable $callback An option function applied to each record before writing * @return string Complete path to written file * @throws coding_exception */ function write_file_as_dataformat(string $filename, string $dataformat, array $columns, $iterator, callable $callback = null): string { $classname = 'dataformat_' . $dataformat . '\writer'; if (!class_exists($classname)) { throw new coding_exception("Unable to locate dataformat/$dataformat/classes/writer.php"); } // The data format export could take a while to generate. core_php_time_limit::raise(); // Close the session so that the users other tabs in the same session are not blocked. \core\session\manager::write_close(); /** @var \core\dataformat\base $format */ $format = new $classname; $filepath = make_request_directory() . '/' . $filename . $format->get_extension(); $format->set_filepath($filepath); // This exists to support all dataformats - see MDL-56046. if (!method_exists($format, 'start_output_to_file') && method_exists($format, 'write_header')) { debugging('The function write_header() does not support multiple sheets. In order to support multiple sheets you must ' . 'implement start_output_to_file() and start_sheet() and remove write_header() in your dataformat.', DEBUG_DEVELOPER); $format->write_header($columns); } else { $format->start_output_to_file(); $format->start_sheet($columns); } $c = 0; foreach ($iterator as $row) { if ($callback) { $row = $callback($row); } if ($row === null) { continue; } $format->write_record($row, $c++); } // This exists to support all dataformats - see MDL-56046. if (!method_exists($format, 'close_output_to_file') && method_exists($format, 'write_footer')) { debugging('The function write_footer() does not support multiple sheets. In order to support multiple sheets you must ' . 'implement close_sheet() and close_output_to_file() and remove write_footer() in your dataformat.', DEBUG_DEVELOPER); $format->write_footer($columns); } else { $format->close_sheet($columns); $format->close_output_to_file(); } return $filepath; }