Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Main catalyst updated #2

Merged
merged 17 commits into from
Dec 13, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ jobs:

services:
postgres:
image: postgres:10
image: postgres:12
env:
POSTGRES_USER: 'postgres'
POSTGRES_HOST_AUTH_METHOD: 'trust'
4 changes: 2 additions & 2 deletions db/install.xml
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="report/customsql/db" VERSION="20150630" COMMENT="XMLDB file for Moodle report/customsql"
<XMLDB PATH="report/customsql/db" VERSION="20151013" COMMENT="XMLDB file for Moodle report/customsql"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
@@ -43,4 +43,4 @@
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
</XMLDB>
11 changes: 11 additions & 0 deletions edit_form.php
Original file line number Diff line number Diff line change
@@ -150,6 +150,7 @@ public function definition() {
$mform->disabledIf('singlerow', 'runable', 'eq', 'manual');
$mform->disabledIf('at', 'runable', 'ne', 'daily');
$mform->disabledIf('emailto', 'runable', 'eq', 'manual');
$mform->disabledIf('customdir', 'runable', 'eq', 'manual');
$mform->disabledIf('emailwhat', 'runable', 'eq', 'manual');

$this->add_action_buttons();
@@ -301,6 +302,16 @@ public function validation($data, $files) {
}
}

// Check that the custom directory is writable and a directory, if provided.
if (isset($data['customdir']) && !empty($data['customdir'])) {
if (!is_dir($data['customdir'])) {
$errors['customdir'] = get_string('notadirectory', 'report_customsql');
}
else if (!is_writable($data['customdir'])) {
$errors['customdir'] = get_string('directorynotwritable', 'report_customsql');
}
}

return $errors;
}
}
1 change: 1 addition & 0 deletions lang/en/report_customsql.php
Original file line number Diff line number Diff line change
@@ -61,6 +61,7 @@
$string['deletecategoryyesno'] = '<p>Are you really sure you want to delete this category? </p>';
$string['deletereportx'] = 'Delete query \'{$a}\'';
$string['description'] = 'Description';
$string['directorynotwritable'] = 'The directory you provided is not writable.';
$string['displayname'] = 'Query name';
$string['displaynamex'] = 'Query name: {$a}';
$string['displaynamerequired'] = 'You must enter a query name';
2 changes: 1 addition & 1 deletion lib.php
Original file line number Diff line number Diff line change
@@ -89,7 +89,7 @@ function report_customsql_pluginfile($course, $cm, $context, $filearea, $args, $
if ($report->runable !== 'manual') {
$runtime = $report->lastrun;
}
$csvtimestamp = \report_customsql_generate_csv($report, $runtime);
$csvtimestamp = \report_customsql_generate_csv($report, $runtime, true);
}
list($csvfilename) = report_customsql_csv_filename($report, $csvtimestamp);

23 changes: 22 additions & 1 deletion locallib.php
Original file line number Diff line number Diff line change
@@ -96,14 +96,29 @@ function report_customsql_get_element_type($name) {
return 'text';
}

function report_customsql_generate_csv($report, $timenow) {
/**
* Generate customsql csv file.
*
* @param stdclass $report report record from customsql table.
* @param int $timetimenow unix timestamp - usually "now()"
* @param bool $returnheaderwhenempty if true, a CSV file with headers will always be generated, even if there are no results.
*/
function report_customsql_generate_csv($report, $timenow, $returnheaderwhenempty = false) {
global $DB;
$starttime = microtime(true);

$sql = report_customsql_prepare_sql($report, $timenow);

$queryparams = !empty($report->queryparams) ? unserialize($report->queryparams) : array();
$querylimit = $report->querylimit ?? get_config('report_customsql', 'querylimitdefault');
if ($returnheaderwhenempty) {
// We want the export to always generate a CSV file so we modify the query slightly
// to generate an extra "null" values row, so we can get the column names,
// then we ignore rows that contain null records in every row when generating the csv.
$sql = "SELECT subq.*
FROM (SELECT 1) as ignoreme
LEFT JOIN ($sql) as subq on true";
}
// Query one extra row, so we can tell if we hit the limit.
$rs = report_customsql_execute_query($sql, $queryparams, $querylimit + 1);

@@ -124,6 +139,11 @@ function report_customsql_generate_csv($report, $timenow) {
}

$data = get_object_vars($row);

if ($returnheaderwhenempty && array_unique(array_values($data)) === [null]) {
// This is a row with all null values - ignore it.
continue;
}
foreach ($data as $name => $value) {
if (report_customsql_get_element_type($name) == 'date_time_selector' &&
report_customsql_is_integer($value) && $value > 0) {
@@ -146,6 +166,7 @@ function report_customsql_generate_csv($report, $timenow) {
fclose($handle);
}


// Update the execution time in the DB.
$updaterecord = new stdClass();
$updaterecord->id = $report->id;
22 changes: 22 additions & 0 deletions tests/behat/behat_report_customsql.php
Original file line number Diff line number Diff line change
@@ -238,6 +238,28 @@ public function adhoc_database_queries_thinks_the_time_is($time) {
set_config('behat_fixed_time', $value, 'report_customsql');
}

/**
* Simulates downloading an empty report to ensure it shows table headers.
*
* For example:
* When downloading the empty custom sql report "Frog" it contains the headers "frogname,freddy"
*
* @Then /^downloading custom sql report "(?P<REPORT_NAME>[^"]*)" returns a file with headers "([^"]*)"$/
* @param string $reportname the name of the report to go to.
* @param string $headers the headers that shuold be returned.
*/
public function downloading_custom_sql_report_x_returns_a_file_with_headers(string $reportname, string $headers) {
$report = $this->get_report_by_name($reportname);
$url = new \moodle_url('/pluginfile.php/1/'.'report_customsql'. '/'.'download'. '/'. $report->id, ['dataformat' => 'csv']);

$session = $this->getSession()->getCookie('MoodleSession');
$filecontent = trim(download_file_content($url, array('Cookie' => 'MoodleSession=' . $session)));
$filecontent = core_text::trim_utf8_bom($filecontent);
if ($filecontent != $headers) {
throw new \Behat\Mink\Exception\ExpectationException("File headers: $filecontent did not match expected: $headers", $this->getSession());
}
}

/**
* Find a report by name and get all the details.
*
7 changes: 7 additions & 0 deletions tests/behat/report_customsql.feature
Original file line number Diff line number Diff line change
@@ -76,6 +76,13 @@ Feature: Ad-hoc database queries report
And I view the "Test query" custom sql report
Then I should see "This query did not return any data."

Scenario: Download an Ad-hoc database query that returns no data but includes headers
Given the following custom sql report exists:
| name | Test query |
| querysql | SELECT * FROM {config} WHERE name = '-1' |
When I log in as "admin"
Then downloading custom sql report "Test query" returns a file with headers "id,name,value"

Scenario: Create an Ad-hoc database queries category
When I log in as "admin"
And I navigate to "Reports > Ad-hoc database queries" in site administration
2 changes: 1 addition & 1 deletion tests/privacy_test.php
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ public function test_export_user_data(): void {
$subcontext = [
get_string('privacy:metadata:reportcustomsqlqueries', 'report_customsql')
];
$data = $writer->get_data($subcontext);
$data = (array)$writer->get_data($subcontext);
$this->assertEquals('Report of user 1', reset($data)['displayname']);
}