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

Issue #123: Fix schema issues in report_customsql_categories #125

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d7a6737
Add new custom directory option to store copy of report on filesystem
Oct 13, 2015
40e8fe7
Refactoring update to address Tim's feedback
Oct 13, 2015
af78630
Allow no directory to be set
Oct 14, 2015
d98bbe5
Check file exists before attempting copy
Oct 15, 2015
1148946
Fixing file exists checks, allow to work if no records returned
Oct 19, 2015
83aeb3e
Revert "Check file exists before attempting copy"
Oct 20, 2015
da69d58
Merge branch 'master' into originmaster
Oct 20, 2015
cdc9032
Fix #114 - return empty csv file (with headers) when no results.
danmarsden Dec 4, 2022
485a8e7
Bump pg version in github action config.
danmarsden Dec 5, 2022
b2447dd
Fix phpdocs and simplify check for empty row.
danmarsden Dec 7, 2022
4862f67
Try a simple behat test
danmarsden Dec 12, 2022
882afea
Fix #123: Fix schema issues in report_customsql_categories
jnlar Dec 21, 2022
7b44f4a
Merge pull request #1 from catalyst/issue123-categories-schema
keevan Dec 22, 2022
5ef87f9
WR410672 Merge with the github project
gbarat87 Aug 8, 2023
50e1d5d
Merge branch 'fix114' of github.com:danmarsden/moodle-report_customsq…
gbarat87 Aug 8, 2023
00986e2
Merge branch 'WR410672-fix-report-sql' into 'catalyst-main'
brendanheywood Aug 9, 2023
8a226de
Merge branch 'WR410672-add-dan-fix' into 'main-catalyst'
brendanheywood Sep 7, 2023
40c30ec
WR-416501 fix privacy test
jay-oswald Dec 12, 2023
626efc3
Merge branch 'WR-416501-fix-privacy-test' into 'main-catalyst'
jay-oswald Dec 13, 2023
98fe1d7
Merge pull request #2 from catalyst/main-catalyst-updated
jay-oswald Dec 13, 2023
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
Expand Up @@ -23,7 +23,7 @@ jobs:

services:
postgres:
image: postgres:10
image: postgres:12
env:
POSTGRES_USER: 'postgres'
POSTGRES_HOST_AUTH_METHOD: 'trust'
Expand Down
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"
>
Expand Down Expand Up @@ -43,4 +43,4 @@
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
</XMLDB>
16 changes: 16 additions & 0 deletions db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -269,5 +269,21 @@ function xmldb_report_customsql_upgrade($oldversion) {
upgrade_plugin_savepoint(true, 2021111600, 'report', 'customsql');
}

if ($oldversion < 2022031801) {

// Changing nullability of field name on table report_customsql_categories to not null.
// Changing the default of field name on table report_customsql_categories to drop it.
$table = new xmldb_table('report_customsql_categories');
$field = new xmldb_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'id');

// Launch change of nullability for field name.
$dbman->change_field_notnull($table, $field);
// Launch change of default for field name.
$dbman->change_field_default($table, $field);

// Report savepoint reached.
upgrade_plugin_savepoint(true, 2022031801, 'report', 'customsql');
}

return true;
}
11 changes: 11 additions & 0 deletions edit_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Up @@ -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';
Expand Down
2 changes: 1 addition & 1 deletion lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
23 changes: 22 additions & 1 deletion locallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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) {
Expand All @@ -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;
Expand Down
22 changes: 22 additions & 0 deletions tests/behat/behat_report_customsql.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
7 changes: 7 additions & 0 deletions tests/behat/report_customsql.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion tests/local/category_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* @copyright 2021 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class _category_test extends \advanced_testcase {
class category_test extends \advanced_testcase {
/**
* Test create category.
*/
Expand Down
2 changes: 1 addition & 1 deletion tests/privacy_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -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']);
}

Expand Down
2 changes: 1 addition & 1 deletion version.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

defined('MOODLE_INTERNAL') || die();

$plugin->version = 2022031800;
$plugin->version = 2022031801;
$plugin->requires = 2020061500;
$plugin->component = 'report_customsql';
$plugin->maturity = MATURITY_STABLE;
Expand Down