MDL-40084 mod_data: Refactor exporting data

Functions data_export_csv, data_export_ods, data_get_exportdata have been deprecated.
This commit is contained in:
Philipp Memmel 2023-03-13 22:35:11 +01:00
parent ab09cf2b84
commit bdf02ec088
10 changed files with 731 additions and 159 deletions

View File

@ -0,0 +1,78 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_data\local;
use coding_exception;
use csv_export_writer;
/**
* CSV exporter for mod_data.
*
* @package mod_data
* @copyright 2023 ISB Bayern
* @author Philipp Memmel
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class csv_exporter extends exporter {
/** @var string[] Possible delimiter names. Only used internally to check if a valid delimiter name
* has been specified.
*/
private const POSSIBLE_DELIMITER_NAMES = ['comma', 'tab', 'semicolon', 'colon', 'cfg'];
/**
* @var string name of the delimiter to use for the csv export. Possible values:
* 'comma', 'tab', 'semicolon', 'colon' or 'cfg'.
*/
private string $delimitername = 'comma';
/**
* Returns the csv data exported by the csv_export_writer for further handling.
*
* @see \mod_data\local\exporter::get_data_file_content()
*/
public function get_data_file_content(): string {
return csv_export_writer::print_array($this->exportdata, $this->delimitername, '"', true);
}
/**
* Returns the file extension of this exporter.
*
* @see \mod_data\local\exporter::get_export_data_file_extension()
*/
public function get_export_data_file_extension(): string {
return 'csv';
}
/**
* Setter for the delimiter name which should be used in this csv_exporter object.
*
* Calling this setter is optional, the delimiter name defaults to 'comma'.
*
* @param string $delimitername one of 'comma', 'tab', 'semicolon', 'colon' or 'cfg'
* @return void
* @throws coding_exception if a wrong delimiter name has been specified
*/
public function set_delimiter_name(string $delimitername): void {
if (!in_array($delimitername, self::POSSIBLE_DELIMITER_NAMES)) {
throw new coding_exception('Wrong delimiter type',
'Please choose on of the following delimiters: '
. '\"comma\", \"tab\", \"semicolon\", \"colon\", \"cfg\"');
}
$this->delimitername = $delimitername;
}
}

View File

@ -0,0 +1,149 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_data\local;
use file_serving_exception;
use zip_archive;
/**
* Exporter class for exporting data.
*
* @package mod_data
* @copyright 2023 ISB Bayern
* @author Philipp Memmel
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class exporter {
/** @var int Tracks the currently edited row of the export data file. */
private int $currentrow;
/**
* @var array The data structure containing the data for exporting. It's a 2-dimensional array of
* rows and columns.
*/
protected array $exportdata;
/** @var string Name of the export file name without extension. */
protected string $exportfilename;
/**
* Creates an exporter object.
*
* This object can be used to export data to different formats.
*/
public function __construct() {
$this->currentrow = 0;
$this->exportdata = [];
$this->exportfilename = 'Exportfile';
}
/**
* Adds a row (array of strings) to the export data.
*
* @param array $row the row to add, $row has to be a plain array of strings
* @return void
*/
public function add_row(array $row): void {
$this->exportdata[] = $row;
$this->currentrow++;
}
/**
* Adds a data string (so the content for a "cell") to the current row.
*
* @param string $cellcontent the content to add to the current row
* @return void
*/
public function add_to_current_row(string $cellcontent): void {
$this->exportdata[$this->currentrow][] = $cellcontent;
}
/**
* Signal the exporter to finish the current row and jump to the next row.
*
* @return void
*/
public function next_row(): void {
$this->currentrow++;
}
/**
* Sets the name of the export file.
*
* Only use the basename without path and without extension here.
*
* @param string $exportfilename name of the file without path and extension
* @return void
*/
public function set_export_file_name(string $exportfilename): void {
$this->exportfilename = $exportfilename;
}
/**
* The exporter will prepare a data file from the rows and columns being added.
* Overwrite this method to generate the data file as string.
*
* @return string the data file as a string
*/
abstract protected function get_data_file_content(): string;
/**
* Overwrite the method to return the file extension your data file will have, for example
* <code>return 'csv';</code> for a csv file exporter.
*
* @return string the file extension of the data file your exporter is using
*/
abstract protected function get_export_data_file_extension(): string;
/**
* Returns the count of currently stored records (rows excluding header row).
*
* @return int the count of records/rows
*/
public function get_records_count(): int {
// The attribute $this->exportdata also contains a header. If only one row is present, this
// usually is the header, so record count should be 0.
if (count($this->exportdata) <= 1) {
return 0;
}
return count($this->exportdata) - 1;
}
/**
* Sends the generated export file.
*
* Care: By default this function finishes the current PHP request and directly serves the file to the user as download.
*
* @param bool $sendtouser true if the file should be sent directly to the user, if false the file content will be returned
* as string
* @return string|null file content as string if $sendtouser is true
*/
public function send_file(bool $sendtouser = true): null|string {
if (empty($this->filenamesinzip)) {
if ($sendtouser) {
send_file($this->get_data_file_content(),
$this->exportfilename . '.' . $this->get_export_data_file_extension(),
null, 0, true, true);
return null;
} else {
return $this->get_data_file_content();
}
}
return null;
}
}

View File

@ -0,0 +1,137 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_data\local;
use coding_exception;
use context;
use context_system;
use dml_exception;
use moodle_exception;
/**
* Utility class for exporting data from a mod_data instance.
*
* @package mod_data
* @copyright 2023 ISB Bayern
* @author Philipp Memmel
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class exporter_utils {
/**
* Exports the data of the mod_data instance to an exporter object which then can export it to a file format.
*
* @param int $dataid
* @param array $fields
* @param array $selectedfields
* @param exporter $exporter the exporter object used
* @param int $currentgroup group ID of the current group. This is used for
* exporting data while maintaining group divisions.
* @param context|null $context the context in which the operation is performed (for capability checks)
* @param bool $userdetails whether to include the details of the record author
* @param bool $time whether to include time created/modified
* @param bool $approval whether to include approval status
* @param bool $tags whether to include tags
* @return void
* @throws coding_exception
* @throws dml_exception
* @throws moodle_exception
*/
public static function data_exportdata(int $dataid, array $fields, array $selectedfields, exporter $exporter,
int $currentgroup = 0, context $context = null, bool $userdetails = false, bool $time = false, bool $approval = false,
bool $tags = false): void {
global $DB;
if (is_null($context)) {
$context = context_system::instance();
}
// Exporting user data needs special permission.
$userdetails = $userdetails && has_capability('mod/data:exportuserinfo', $context);
// Populate the header in first row of export.
$header = [];
foreach ($fields as $key => $field) {
if (!in_array($field->field->id, $selectedfields)) {
// Ignore values we aren't exporting.
unset($fields[$key]);
} else {
$header[] = $field->field->name;
}
}
if ($tags) {
$header[] = get_string('tags', 'data');
}
if ($userdetails) {
$header[] = get_string('user');
$header[] = get_string('username');
$header[] = get_string('email');
}
if ($time) {
$header[] = get_string('timeadded', 'data');
$header[] = get_string('timemodified', 'data');
}
if ($approval) {
$header[] = get_string('approved', 'data');
}
$exporter->add_row($header);
$datarecords = $DB->get_records('data_records', array('dataid' => $dataid));
ksort($datarecords);
$line = 1;
foreach ($datarecords as $record) {
// Get content indexed by fieldid.
if ($currentgroup) {
$select = 'SELECT c.fieldid, c.content, c.content1, c.content2, c.content3, c.content4 FROM {data_content} c, '
. '{data_records} r WHERE c.recordid = ? AND r.id = c.recordid AND r.groupid = ?';
$where = array($record->id, $currentgroup);
} else {
$select = 'SELECT fieldid, content, content1, content2, content3, content4 FROM {data_content} WHERE recordid = ?';
$where = array($record->id);
}
if ($content = $DB->get_records_sql($select, $where)) {
foreach ($fields as $field) {
$contents = '';
if (isset($content[$field->field->id])) {
$contents = $field->export_text_value($content[$field->field->id]);
}
// Just be double sure.
$contents = !empty($contents) ? $contents : '';
$exporter->add_to_current_row($contents);
}
if ($tags) {
$itemtags = \core_tag_tag::get_item_tags_array('mod_data', 'data_records', $record->id);
$exporter->add_to_current_row(implode(', ', $itemtags));
}
if ($userdetails) { // Add user details to the export data.
$userdata = get_complete_user_data('id', $record->userid);
$exporter->add_to_current_row(fullname($userdata));
$exporter->add_to_current_row($userdata->username);
$exporter->add_to_current_row($userdata->email);
}
if ($time) { // Add time added / modified.
$exporter->add_to_current_row(userdate($record->timecreated));
$exporter->add_to_current_row(userdate($record->timemodified));
}
if ($approval) { // Add approval status.
$exporter->add_to_current_row((int) $record->approved);
}
}
$exporter->next_row();
}
}
}

View File

@ -0,0 +1,65 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_data\local;
use MoodleODSWorkbook;
use MoodleODSWriter;
/**
* ODS exporter for mod_data.
*
* @package mod_data
* @copyright 2023 ISB Bayern
* @author Philipp Memmel
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class ods_exporter extends exporter {
/**
* Returns the file extension of this exporter.
*
* @see \mod_data\local\exporter::get_export_data_file_extension()
*/
public function get_export_data_file_extension(): string {
return 'ods';
}
/**
* Returns the ods data exported by the ODS library for further handling.
*
* @see \mod_data\local\exporter::get_data_file_content()
*/
public function get_data_file_content(): string {
global $CFG;
require_once("$CFG->libdir/odslib.class.php");
$filearg = '-';
$workbook = new MoodleODSWorkbook($filearg);
$worksheet = [];
$worksheet[0] = $workbook->add_worksheet('');
$rowno = 0;
foreach ($this->exportdata as $row) {
$colno = 0;
foreach ($row as $col) {
$worksheet[0]->write($rowno, $colno, $col);
$colno++;
}
$rowno++;
}
$writer = new MoodleODSWriter($worksheet);
return $writer->get_file_content();
}
}

View File

@ -100,3 +100,170 @@ function data_export_xls($export, $dataname, $count) {
$workbook->close();
return $filename;
}
/**
* @deprecated since Moodle 4.3, exporting is now being done by \mod_data\local\csv_exporter
* @global object
* @param array $export
* @param string $delimiter_name
* @param object $database
* @param int $count
* @param bool $return
* @return string|void
*/
function data_export_csv($export, $delimiter_name, $database, $count, $return=false) {
global $CFG;
debugging('Function data_export_csv has been deprecated. Exporting is now being done by '
. '\mod_data\local\csv_exporter.', DEBUG_DEVELOPER);
require_once($CFG->libdir . '/csvlib.class.php');
$filename = $database . '-' . $count . '-record';
if ($count > 1) {
$filename .= 's';
}
if ($return) {
return csv_export_writer::print_array($export, $delimiter_name, '"', true);
} else {
csv_export_writer::download_array($filename, $export, $delimiter_name);
}
}
/**
* @deprecated since Moodle 4.3, exporting is now being done by \mod_data\local\ods_exporter
* @global object
* @param array $export
* @param string $dataname
* @param int $count
* @param string
*/
function data_export_ods($export, $dataname, $count) {
global $CFG;
debugging('Function data_export_ods has been deprecated. Exporting is now being done by '
. '\mod_data\local\ods_exporter.', DEBUG_DEVELOPER);
require_once("$CFG->libdir/odslib.class.php");
$filename = clean_filename("{$dataname}-{$count}_record");
if ($count > 1) {
$filename .= 's';
}
$filename .= clean_filename('-' . gmdate("Ymd_Hi"));
$filename .= '.ods';
$filearg = '-';
$workbook = new MoodleODSWorkbook($filearg);
$workbook->send($filename);
$worksheet = array();
$worksheet[0] = $workbook->add_worksheet('');
$rowno = 0;
foreach ($export as $row) {
$colno = 0;
foreach($row as $col) {
$worksheet[0]->write($rowno, $colno, $col);
$colno++;
}
$rowno++;
}
$workbook->close();
return $filename;
}
/**
* @deprecated since Moodle 4.3, use \mod_data\local\exporter_utils::data_exportdata with a \mod_data\local\exporter object
* @global object
* @param int $dataid
* @param array $fields
* @param array $selectedfields
* @param int $currentgroup group ID of the current group. This is used for
* exporting data while maintaining group divisions.
* @param object $context the context in which the operation is performed (for capability checks)
* @param bool $userdetails whether to include the details of the record author
* @param bool $time whether to include time created/modified
* @param bool $approval whether to include approval status
* @param bool $tags whether to include tags
* @return array
*/
function data_get_exportdata($dataid, $fields, $selectedfields, $currentgroup=0, $context=null,
$userdetails=false, $time=false, $approval=false, $tags = false) {
global $DB;
debugging('Function data_get_exportdata has been deprecated. Use '
. '\mod_data\local\exporter_utils::data_exportdata with a \mod_data\local\exporter object instead',
DEBUG_DEVELOPER);
if (is_null($context)) {
$context = context_system::instance();
}
// exporting user data needs special permission
$userdetails = $userdetails && has_capability('mod/data:exportuserinfo', $context);
$exportdata = array();
// populate the header in first row of export
foreach($fields as $key => $field) {
if (!in_array($field->field->id, $selectedfields)) {
// ignore values we aren't exporting
unset($fields[$key]);
} else {
$exportdata[0][] = $field->field->name;
}
}
if ($tags) {
$exportdata[0][] = get_string('tags', 'data');
}
if ($userdetails) {
$exportdata[0][] = get_string('user');
$exportdata[0][] = get_string('username');
$exportdata[0][] = get_string('email');
}
if ($time) {
$exportdata[0][] = get_string('timeadded', 'data');
$exportdata[0][] = get_string('timemodified', 'data');
}
if ($approval) {
$exportdata[0][] = get_string('approved', 'data');
}
$datarecords = $DB->get_records('data_records', array('dataid'=>$dataid));
ksort($datarecords);
$line = 1;
foreach($datarecords as $record) {
// get content indexed by fieldid
if ($currentgroup) {
$select = 'SELECT c.fieldid, c.content, c.content1, c.content2, c.content3, c.content4 FROM {data_content} c, {data_records} r WHERE c.recordid = ? AND r.id = c.recordid AND r.groupid = ?';
$where = array($record->id, $currentgroup);
} else {
$select = 'SELECT fieldid, content, content1, content2, content3, content4 FROM {data_content} WHERE recordid = ?';
$where = array($record->id);
}
if( $content = $DB->get_records_sql($select, $where) ) {
foreach($fields as $field) {
$contents = '';
if(isset($content[$field->field->id])) {
$contents = $field->export_text_value($content[$field->field->id]);
}
$exportdata[$line][] = $contents;
}
if ($tags) {
$itemtags = \core_tag_tag::get_item_tags_array('mod_data', 'data_records', $record->id);
$exportdata[$line][] = implode(', ', $itemtags);
}
if ($userdetails) { // Add user details to the export data
$userdata = get_complete_user_data('id', $record->userid);
$exportdata[$line][] = fullname($userdata);
$exportdata[$line][] = $userdata->username;
$exportdata[$line][] = $userdata->email;
}
if ($time) { // Add time added / modified
$exportdata[$line][] = userdate($record->timecreated);
$exportdata[$line][] = userdate($record->timemodified);
}
if ($approval) { // Add approval status
$exportdata[$line][] = (int) $record->approved;
}
}
$line++;
}
$line--;
return $exportdata;
}

View File

@ -95,20 +95,30 @@ if ($mform->is_cancelled()) {
$currentgroup = groups_get_activity_group($cm);
$exportdata = data_get_exportdata($data->id, $fields, $selectedfields, $currentgroup, $context,
$exportuser, $exporttime, $exportapproval, $tags);
$count = count($exportdata);
$exporter = null;
switch ($formdata['exporttype']) {
case 'csv':
data_export_csv($exportdata, $formdata['delimiter_name'], $data->name, $count);
$exporter = new \mod_data\local\csv_exporter();
$exporter->set_delimiter_name($formdata['delimiter_name']);
break;
case 'ods':
data_export_ods($exportdata, $data->name, $count);
$exporter = new \mod_data\local\ods_exporter();
break;
default:
throw new coding_exception('Invalid export format has been specified. '
. 'Only "csv" and "ods" are currently supported.');
}
\mod_data\local\exporter_utils::data_exportdata($data->id, $fields, $selectedfields, $exporter, $currentgroup, $context,
$exportuser, $exporttime, $exportapproval, $tags);
$count = $exporter->get_records_count();
$filename = clean_filename("{$data->name}-{$count}_record");
if ($count > 1) {
$filename .= 's';
}
$filename .= clean_filename('-' . gmdate("Ymd_Hi"));
$exporter->set_export_file_name($filename);
$exporter->send_file();
}
// Build header to match the rest of the UI.

View File

@ -3111,160 +3111,6 @@ function data_import_csv($cm, $data, &$csvdata, $encoding, $fielddelimiter) {
return 0;
}
/**
* @global object
* @param array $export
* @param string $delimiter_name
* @param object $database
* @param int $count
* @param bool $return
* @return string|void
*/
function data_export_csv($export, $delimiter_name, $database, $count, $return=false) {
global $CFG;
require_once($CFG->libdir . '/csvlib.class.php');
$filename = $database . '-' . $count . '-record';
if ($count > 1) {
$filename .= 's';
}
if ($return) {
return csv_export_writer::print_array($export, $delimiter_name, '"', true);
} else {
csv_export_writer::download_array($filename, $export, $delimiter_name);
}
}
/**
* @global object
* @param array $export
* @param string $dataname
* @param int $count
* @param string
*/
function data_export_ods($export, $dataname, $count) {
global $CFG;
require_once("$CFG->libdir/odslib.class.php");
$filename = clean_filename("{$dataname}-{$count}_record");
if ($count > 1) {
$filename .= 's';
}
$filename .= clean_filename('-' . gmdate("Ymd_Hi"));
$filename .= '.ods';
$filearg = '-';
$workbook = new MoodleODSWorkbook($filearg);
$workbook->send($filename);
$worksheet = array();
$worksheet[0] = $workbook->add_worksheet('');
$rowno = 0;
foreach ($export as $row) {
$colno = 0;
foreach($row as $col) {
$worksheet[0]->write($rowno, $colno, $col);
$colno++;
}
$rowno++;
}
$workbook->close();
return $filename;
}
/**
* @global object
* @param int $dataid
* @param array $fields
* @param array $selectedfields
* @param int $currentgroup group ID of the current group. This is used for
* exporting data while maintaining group divisions.
* @param object $context the context in which the operation is performed (for capability checks)
* @param bool $userdetails whether to include the details of the record author
* @param bool $time whether to include time created/modified
* @param bool $approval whether to include approval status
* @param bool $tags whether to include tags
* @return array
*/
function data_get_exportdata($dataid, $fields, $selectedfields, $currentgroup=0, $context=null,
$userdetails=false, $time=false, $approval=false, $tags = false) {
global $DB;
if (is_null($context)) {
$context = context_system::instance();
}
// exporting user data needs special permission
$userdetails = $userdetails && has_capability('mod/data:exportuserinfo', $context);
$exportdata = array();
// populate the header in first row of export
foreach($fields as $key => $field) {
if (!in_array($field->field->id, $selectedfields)) {
// ignore values we aren't exporting
unset($fields[$key]);
} else {
$exportdata[0][] = $field->field->name;
}
}
if ($tags) {
$exportdata[0][] = get_string('tags', 'data');
}
if ($userdetails) {
$exportdata[0][] = get_string('user');
$exportdata[0][] = get_string('username');
$exportdata[0][] = get_string('email');
}
if ($time) {
$exportdata[0][] = get_string('timeadded', 'data');
$exportdata[0][] = get_string('timemodified', 'data');
}
if ($approval) {
$exportdata[0][] = get_string('approved', 'data');
}
$datarecords = $DB->get_records('data_records', array('dataid'=>$dataid));
ksort($datarecords);
$line = 1;
foreach($datarecords as $record) {
// get content indexed by fieldid
if ($currentgroup) {
$select = 'SELECT c.fieldid, c.content, c.content1, c.content2, c.content3, c.content4 FROM {data_content} c, {data_records} r WHERE c.recordid = ? AND r.id = c.recordid AND r.groupid = ?';
$where = array($record->id, $currentgroup);
} else {
$select = 'SELECT fieldid, content, content1, content2, content3, content4 FROM {data_content} WHERE recordid = ?';
$where = array($record->id);
}
if( $content = $DB->get_records_sql($select, $where) ) {
foreach($fields as $field) {
$contents = '';
if(isset($content[$field->field->id])) {
$contents = $field->export_text_value($content[$field->field->id]);
}
$exportdata[$line][] = $contents;
}
if ($tags) {
$itemtags = \core_tag_tag::get_item_tags_array('mod_data', 'data_records', $record->id);
$exportdata[$line][] = implode(', ', $itemtags);
}
if ($userdetails) { // Add user details to the export data
$userdata = get_complete_user_data('id', $record->userid);
$exportdata[$line][] = fullname($userdata);
$exportdata[$line][] = $userdata->username;
$exportdata[$line][] = $userdata->email;
}
if ($time) { // Add time added / modified
$exportdata[$line][] = userdate($record->timecreated);
$exportdata[$line][] = userdate($record->timemodified);
}
if ($approval) { // Add approval status
$exportdata[$line][] = (int) $record->approved;
}
}
$line++;
}
$line--;
return $exportdata;
}
////////////////////////////////////////////////////////////////////////////////
// File API //
////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,114 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_data;
use coding_exception;
use context_module;
use dml_exception;
use mod_data\local\csv_exporter;
use mod_data\local\exporter_utils;
use mod_data\local\mod_data_csv_importer;
/**
* Unit tests for import.php.
*
* @package mod_data
* @category test
* @copyright 2019 Tobias Reischmann
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class export_test extends \advanced_testcase {
/**
* Get the test data.
*
* In this instance we are setting up database records to be used in the unit tests.
*
* @return array of test instances
* @throws coding_exception
*/
protected function get_test_data(): array {
$this->resetAfterTest(true);
$generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
$course = $this->getDataGenerator()->create_course();
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
$this->setUser($teacher);
$student = $this->getDataGenerator()->create_and_enrol($course, 'student', ['username' => 'student']);
$data = $generator->create_instance(['course' => $course->id]);
$cm = get_coursemodule_from_instance('data', $data->id);
// Add fields.
$fieldrecord = new \stdClass();
$fieldrecord->name = 'numberfield'; // Identifier of the records for testing.
$fieldrecord->type = 'number';
$numberfield = $generator->create_field($fieldrecord, $data);
$fieldrecord->name = 'textfield';
$fieldrecord->type = 'text';
$textfield = $generator->create_field($fieldrecord, $data);
$contents[$numberfield->field->id] = '3';
$contents[$textfield->field->id] = 'a simple text';
$generator->create_entry($data, $contents);
return [
'teacher' => $teacher,
'student' => $student,
'data' => $data,
'cm' => $cm,
];
}
/**
* Tests the exporting of the content of a mod_data instance.
*
* @covers \mod_data\local\exporter
* @covers \mod_data\local\exporter_utils::data_exportdata
*/
public function test_export(): void {
global $DB;
[
'data' => $data,
'cm' => $cm,
] = $this->get_test_data();
$exporter = new csv_exporter();
$exporter->set_export_file_name('testexportfile');
$fieldrecords = $DB->get_records('data_fields', ['dataid' => $data->id], 'id');
$fields = [];
foreach ($fieldrecords as $fieldrecord) {
$fields[] = data_get_field($fieldrecord, $data);
}
// We select all fields.
$selectedfields = array_map(fn($field) => $field->field->id, $fields);
$currentgroup = groups_get_activity_group($cm);
$context = context_module::instance($cm->id);
$exportuser = false;
$exporttime = false;
$exportapproval = false;
$tags = false;
exporter_utils::data_exportdata($data->id, $fields, $selectedfields, $exporter, $currentgroup, $context,
$exportuser, $exporttime, $exportapproval, $tags);
$this->assertEquals(file_get_contents(__DIR__ . '/fixtures/test_data_export.csv'),
$exporter->send_file(false));
}
}

View File

@ -0,0 +1,2 @@
numberfield,textfield
3,"a simple text"
1 numberfield textfield
2 3 a simple text

View File

@ -3,6 +3,10 @@ information provided here is intended especially for developers.
== 4.3 ==
* Function data_export_xls() has been deprecated and moved to deprecatedlib, because xls support has already been dropped.
* Functions data_export_csv(), data_export_ods() and data_get_exportdata() have been deprecated due to a bigger
refactoring of the way data is being exported. This is now being done by new exporter classes
\mod_data\local\csv_exporter and \mod_data\local\ods_exporter (inheriting from exporter base class
\mod_data\local\exporter) as well as \mod_data\local\exporter_utils::data_exportdata().
== 4.2 ==
* The field base class now has a method validate(). Overwrite it in the field type to provide validation of field type's