From 9bb36b6ebd207d9c39e35d36d407f8b1cb1e1e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luca=20B=C3=B6sch?= Date: Sat, 13 May 2023 13:58:33 +0200 Subject: [PATCH] Adding Github workflows. --- .github/workflows/moodle-plugin-ci.yml | 144 +++++++++++++++ classes/event/backend_created.php | 1 - classes/event/backend_deleted.php | 1 - classes/event/backend_disabled.php | 1 - classes/event/backend_enabled.php | 1 - classes/event/backend_updated.php | 1 - classes/event/query_created.php | 1 - classes/event/query_deleted.php | 1 - classes/event/query_disabled.php | 1 - classes/event/query_enabled.php | 1 - classes/event/query_updated.php | 1 - db/access.php | 1 - db/install.php | 1 + db/uninstall.php | 1 - lang/en/report_datawarehouse.php | 1 - locallib.php | 236 ++++++++++++++++++++++++- settings.php | 1 - 17 files changed, 374 insertions(+), 21 deletions(-) create mode 100755 .github/workflows/moodle-plugin-ci.yml diff --git a/.github/workflows/moodle-plugin-ci.yml b/.github/workflows/moodle-plugin-ci.yml new file mode 100755 index 0000000..eac7070 --- /dev/null +++ b/.github/workflows/moodle-plugin-ci.yml @@ -0,0 +1,144 @@ +name: Moodle Plugin CI + +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:13 + env: + POSTGRES_USER: 'postgres' + POSTGRES_HOST_AUTH_METHOD: 'trust' + ports: + - 5432:5432 + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 + mariadb: + image: mariadb:10.6 + env: + MYSQL_USER: 'root' + MYSQL_ALLOW_EMPTY_PASSWORD: "true" + MYSQL_CHARACTER_SET_SERVER: "utf8mb4" + MYSQL_COLLATION_SERVER: "utf8mb4_unicode_ci" + ports: + - 3306:3306 + options: --health-cmd="mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 3 + + strategy: + fail-fast: false + matrix: + include: + - php: 8.1 + moodle-branch: master + database: pgsql + - php: 8.1 + moodle-branch: master + database: mariadb + - php: 8.0 + moodle-branch: master + database: pgsql + - php: 8.0 + moodle-branch: master + database: mariadb + - php: 8.1 + moodle-branch: MOODLE_402_STABLE + database: pgsql + - php: 8.1 + moodle-branch: MOODLE_402_STABLE + database: mariadb + - php: 8.0 + moodle-branch: MOODLE_402_STABLE + database: pgsql + - php: 8.0 + moodle-branch: MOODLE_402_STABLE + database: mariadb + - php: 8.0 + moodle-branch: MOODLE_401_STABLE + database: pgsql + - php: 8.0 + moodle-branch: MOODLE_401_STABLE + database: mariadb + - php: 7.4 + moodle-branch: MOODLE_401_STABLE + database: pgsql + - php: 7.4 + moodle-branch: MOODLE_401_STABLE + database: mariadb + + steps: + - name: Check out repository code + uses: actions/checkout@v3 + with: + path: plugin + + - name: Setup PHP ${{ matrix.php }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: ${{ matrix.extensions }} + ini-values: max_input_vars=5000 + coverage: none + + - name: Initialise moodle-plugin-ci + run: | + composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 + echo $(cd ci/bin; pwd) >> $GITHUB_PATH + echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH + sudo locale-gen en_AU.UTF-8 + echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV + + - name: Install moodle-plugin-ci + run: | + moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 + env: + DB: ${{ matrix.database }} + MOODLE_BRANCH: ${{ matrix.moodle-branch }} + IGNORE_PATHS: moodle/tests/fixtures,moodle/Sniffs + + - name: PHP Lint + if: ${{ always() }} + run: moodle-plugin-ci phplint + + - name: PHP Copy/Paste Detector + continue-on-error: true # This step will show errors but will not fail + if: ${{ always() }} + run: moodle-plugin-ci phpcpd + + - name: PHP Mess Detector + continue-on-error: true # This step will show errors but will not fail + if: ${{ always() }} + run: moodle-plugin-ci phpmd + + - name: Moodle Code Checker + if: ${{ always() }} + run: moodle-plugin-ci codechecker --max-warnings 0 + + - name: Moodle PHPDoc Checker + if: ${{ always() }} + run: moodle-plugin-ci phpdoc + + - name: Validating + if: ${{ always() }} + run: moodle-plugin-ci validate + + - name: Check upgrade savepoints + if: ${{ always() }} + run: moodle-plugin-ci savepoints + + - name: Mustache Lint + if: ${{ always() }} + run: moodle-plugin-ci mustache || true + + - name: Grunt + if: ${{ always() }} + run: moodle-plugin-ci grunt --max-lint-warnings 0 + + - name: PHPUnit tests + if: ${{ always() }} + run: moodle-plugin-ci phpunit --coverage-text + + - name: Behat features + if: ${{ always() }} + run: moodle-plugin-ci behat --profile chrome diff --git a/classes/event/backend_created.php b/classes/event/backend_created.php index 83f429b..9d4f704 100644 --- a/classes/event/backend_created.php +++ b/classes/event/backend_created.php @@ -20,7 +20,6 @@ * The backend_created event class. * * @package report_datawarehouse - * @query_category event * @copyright 2023 Luca Bösch * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/classes/event/backend_deleted.php b/classes/event/backend_deleted.php index 6c6a1ee..c799ec8 100644 --- a/classes/event/backend_deleted.php +++ b/classes/event/backend_deleted.php @@ -20,7 +20,6 @@ * The backend_deleted event class. * * @package report_datawarehouse - * @query_category event * @copyright 2023 Luca Bösch * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/classes/event/backend_disabled.php b/classes/event/backend_disabled.php index 04a177f..221c582 100644 --- a/classes/event/backend_disabled.php +++ b/classes/event/backend_disabled.php @@ -20,7 +20,6 @@ * The backend_disabled event class. * * @package report_datawarehouse - * @query_category event * @copyright 2023 Luca Bösch * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/classes/event/backend_enabled.php b/classes/event/backend_enabled.php index 505cabf..60ae43a 100644 --- a/classes/event/backend_enabled.php +++ b/classes/event/backend_enabled.php @@ -20,7 +20,6 @@ * The backend_enabled event class. * * @package report_datawarehouse - * @query_category event * @copyright 2023 Luca Bösch * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/classes/event/backend_updated.php b/classes/event/backend_updated.php index 3772078..c36d2b6 100644 --- a/classes/event/backend_updated.php +++ b/classes/event/backend_updated.php @@ -20,7 +20,6 @@ * The backend_updated event class. * * @package report_datawarehouse - * @query_category event * @copyright 2023 Luca Bösch * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/classes/event/query_created.php b/classes/event/query_created.php index 21f6176..c8181d8 100644 --- a/classes/event/query_created.php +++ b/classes/event/query_created.php @@ -20,7 +20,6 @@ * The query_created event class. * * @package report_datawarehouse - * @query_category event * @copyright 2023 Luca Bösch * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/classes/event/query_deleted.php b/classes/event/query_deleted.php index 2111d80..cf32729 100644 --- a/classes/event/query_deleted.php +++ b/classes/event/query_deleted.php @@ -20,7 +20,6 @@ * The query_deleted event class. * * @package report_datawarehouse - * @query_category event * @copyright 2023 Luca Bösch * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/classes/event/query_disabled.php b/classes/event/query_disabled.php index 18b4095..c63c6a3 100644 --- a/classes/event/query_disabled.php +++ b/classes/event/query_disabled.php @@ -20,7 +20,6 @@ * The query_disabled event class. * * @package report_datawarehouse - * @query_category event * @copyright 2023 Luca Bösch * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/classes/event/query_enabled.php b/classes/event/query_enabled.php index 9219f89..6e16571 100644 --- a/classes/event/query_enabled.php +++ b/classes/event/query_enabled.php @@ -20,7 +20,6 @@ * The query_enabled event class. * * @package report_datawarehouse - * @query_category event * @copyright 2023 Luca Bösch * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/classes/event/query_updated.php b/classes/event/query_updated.php index 262b7e9..acbadb2 100644 --- a/classes/event/query_updated.php +++ b/classes/event/query_updated.php @@ -20,7 +20,6 @@ * The query_updated event class. * * @package report_datawarehouse - * @query_category event * @copyright 2023 Luca Bösch * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/db/access.php b/db/access.php index 95b541a..179eea3 100644 --- a/db/access.php +++ b/db/access.php @@ -18,7 +18,6 @@ * Plugin capabilities are defined here. * * @package report_datawarehouse - * @query_category access * @copyright 2023 Luca Bösch * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/db/install.php b/db/install.php index 209b6a8..57a03d3 100644 --- a/db/install.php +++ b/db/install.php @@ -16,6 +16,7 @@ /** * Post-install script for the data warehouse report. + * * @package report_datawarehouse * @copyright 2023 Luca Bösch * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later diff --git a/db/uninstall.php b/db/uninstall.php index 01f4810..209651c 100644 --- a/db/uninstall.php +++ b/db/uninstall.php @@ -18,7 +18,6 @@ * Code that is executed before the tables and data are dropped during the plugin uninstallation. * * @package report_datawarehouse - * @query_category upgrade * @copyright 2023 Luca Bösch * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lang/en/report_datawarehouse.php b/lang/en/report_datawarehouse.php index fef74a6..209f58b 100644 --- a/lang/en/report_datawarehouse.php +++ b/lang/en/report_datawarehouse.php @@ -18,7 +18,6 @@ * Plugin strings are defined here. * * @package report_datawarehouse - * @query_category string * @copyright 2023 Luca Bösch * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/locallib.php b/locallib.php index 50c6424..e8366e3 100644 --- a/locallib.php +++ b/locallib.php @@ -27,8 +27,20 @@ global $CFG; require_once($CFG->libdir . '/validateurlsyntax.php'); +/** + * The marker for exceeded row limit. + */ define('REPORT_DATAWAREHOUSE_LIMIT_EXCEEDED_MARKER', '-- ROW LIMIT EXCEEDED --'); +/** + * Execute a query + * + * @param string $sql the sql + * @param array|null $params the params + * @param int|null $limitnum the result limit + * @return moodle_recordset + * @throws dml_exception + */ function report_datawarehouse_execute_query($sql, $params = null, $limitnum = null) { global $CFG, $DB; @@ -48,6 +60,14 @@ function report_datawarehouse_execute_query($sql, $params = null, $limitnum = nu return $DB->get_recordset_sql($sql, $params, 0, $limitnum); } +/** + * Prepare sql for a report + * + * @param stdClass $report the report + * @param int $timenow a time stamp + * @return array|string|string[] + * @throws Exception + */ function report_datawarehouse_prepare_sql($report, $timenow) { global $USER; $sql = $report->querysql; @@ -61,6 +81,7 @@ function report_datawarehouse_prepare_sql($report, $timenow) { /** * Extract all the placeholder names from the SQL. + * * @param string $sql The sql. * @return array placeholder names including the leading colon. */ @@ -85,6 +106,7 @@ function report_datawarehouse_get_query_placeholders_and_field_names(string $que /** * Return the type of form field to use for a placeholder, based on its name. + * * @param string $name the placeholder name. * @return string a formslib element type, for example 'text' or 'date_time_selector'. */ @@ -96,6 +118,14 @@ function report_datawarehouse_get_element_type($name) { return 'text'; } +/** + * Generate the CSV + * + * @param object $report report settings from the database. + * @param int $timenow a timestamp. + * @return mixed|null + * @throws dml_exception + */ function report_datawarehouse_generate_csv($report, $timenow) { global $DB; $starttime = microtime(true); @@ -186,6 +216,14 @@ function report_datawarehouse_is_integer($value) { return (string) (int) $value === (string) $value; } +/** + * Get a report CSV name + * + * @param object $report report settings from the database. + * @param int $timenow a timestamp. + * @return array + * @throws Exception + */ function report_datawarehouse_csv_filename($report, $timenow) { if ($report->runable == 'manual') { return report_datawarehouse_temp_csv_name($report->id, $timenow); @@ -199,6 +237,13 @@ function report_datawarehouse_csv_filename($report, $timenow) { } } +/** + * Get a report CSV name + * + * @param int $reportid The reportid. + * @param int $timestamp a timestamp. + * @return array + */ function report_datawarehouse_temp_csv_name($reportid, $timestamp) { global $CFG; $path = 'admin_report_datawarehouse/temp/'.$reportid; @@ -207,6 +252,13 @@ function report_datawarehouse_temp_csv_name($reportid, $timestamp) { $timestamp); } +/** + * Get the csv location and the time start of a report + * + * @param int $reportid The reportid. + * @param int $timestart a timestamp. + * @return array + */ function report_datawarehouse_scheduled_csv_name($reportid, $timestart) { global $CFG; $path = 'admin_report_datawarehouse/'.$reportid; @@ -215,6 +267,12 @@ function report_datawarehouse_scheduled_csv_name($reportid, $timestart) { $timestart); } +/** + * Get the accumulate.csv file name and 0 of a report + * + * @param int $reportid The reportid. + * @return array + */ function report_datawarehouse_accumulating_csv_name($reportid) { global $CFG; $path = 'admin_report_datawarehouse/'.$reportid; @@ -222,6 +280,12 @@ function report_datawarehouse_accumulating_csv_name($reportid) { return array($CFG->dataroot.'/'.$path.'/accumulate.csv', 0); } +/** + * Get the times the reports were archived. + * + * @param object $report report settings from the database. + * @return array + */ function report_datawarehouse_get_archive_times($report) { global $CFG; if ($report->runable == 'manual' || $report->singlerow) { @@ -239,10 +303,25 @@ function report_datawarehouse_get_archive_times($report) { return $archivetimes; } +/** + * Substitute time tokens + * + * @param string $sql the sql + * @param int $start a timestamp. + * @param int $end a timestamp. + * @return array|string|string[] + */ function report_datawarehouse_substitute_time_tokens($sql, $start, $end) { return str_replace(array('%%STARTTIME%%', '%%ENDTIME%%'), array($start, $end), $sql); } +/** + * Substitute user tokens + * + * @param string $sql the sql + * @param int $userid a user id + * @return array|string|string[] + */ function report_datawarehouse_substitute_user_token($sql, $userid) { return str_replace('%%USERID%%', $userid, $sql); } @@ -282,6 +361,12 @@ function report_datawarehouse_downloadurl($reportid, $params = []) { return $downloadurl; } +/** + * Get the capability options. + * + * @return array + * @throws coding_exception + */ function report_datawarehouse_capability_options() { return array( 'report/datawarehouse:view' => get_string('anyonewhocanveiwthisreport', 'report_datawarehouse'), @@ -290,6 +375,13 @@ function report_datawarehouse_capability_options() { ); } +/** + * Get the available type of reports given a super type. + * + * @param string|null $type the type of report + * @return array + * @throws coding_exception + */ function report_datawarehouse_runable_options($type = null) { if ($type === 'manual') { return array('manual' => get_string('manual', 'report_datawarehouse')); @@ -301,6 +393,11 @@ function report_datawarehouse_runable_options($type = null) { ); } +/** + * Get the options for the time for daily digests. + * + * @return array + */ function report_datawarehouse_daily_at_options() { $time = array(); for ($h = 0; $h < 24; $h++) { @@ -310,33 +407,68 @@ function report_datawarehouse_daily_at_options() { return $time; } +/** + * Get the email options. + * + * @return array + * @throws coding_exception + */ function report_datawarehouse_email_options() { return array('emailnumberofrows' => get_string('emailnumberofrows', 'report_datawarehouse'), 'emailresults' => get_string('emailresults', 'report_datawarehouse'), ); } +/** + * Get the bad words list. + * + * @return string[] + */ function report_datawarehouse_bad_words_list() { return array('ALTER', 'CREATE', 'DELETE', 'DROP', 'GRANT', 'INSERT', 'INTO', 'TRUNCATE', 'UPDATE'); } +/** + * Check if a string contains bad words + * + * @param string $string the string to check + * @return false|int + */ function report_datawarehouse_contains_bad_word($string) { return preg_match('/\b('.implode('|', report_datawarehouse_bad_words_list()).')\b/i', $string); } +/** + * Delete a log + * + * @param int $id The id + * @throws dml_exception + */ function report_datawarehouse_log_delete($id) { $event = \report_datawarehouse\event\query_deleted::create( array('objectid' => $id, 'context' => context_system::instance())); $event->trigger(); } +/** + * Edit a log + * + * @param int $id The id + * @throws dml_exception + */ function report_datawarehouse_log_edit($id) { $event = \report_datawarehouse\event\query_edited::create( array('objectid' => $id, 'context' => context_system::instance())); $event->trigger(); } +/** + * View a log + * + * @param int $id The id + * @throws dml_exception + */ function report_datawarehouse_log_view($id) { $event = \report_datawarehouse\event\query_viewed::create( array('objectid' => $id, 'context' => context_system::instance())); @@ -469,6 +601,14 @@ function report_datawarehouse_display_row($row, $linkcolumns) { return $rowdata; } +/** + * Get the time tag + * + * @param object $report report settings from the database. + * @param string $tag a tag + * @return string + * @throws coding_exception + */ function report_datawarehouse_time_note($report, $tag) { if ($report->lastrun) { $a = new stdClass; @@ -483,8 +623,14 @@ function report_datawarehouse_time_note($report, $tag) { return html_writer::tag($tag, $note, array('class' => 'admin_note')); } - -function report_datawarehouse_pretify_column_names($row, $querysql) { +/** + * Prettify columns name + * + * @param string $row a row + * @param string $querysql the query sql + * @return array + */ +function report_datawarehouse_prettify_column_names($row, $querysql) { $colnames = []; foreach (get_object_vars($row) as $colname => $ignored) { @@ -541,8 +687,16 @@ function report_datawarehouse_read_csv_row($handle) { return fgetcsv($handle, 0, ',', '"', $disablestupidphpescaping); } +/** + * Start CSV output + * + * @param resource $handle the file pointer + * @param string $firstrow the first row + * @param object $report report settings from the database. + * @throws coding_exception + */ function report_datawarehouse_start_csv($handle, $firstrow, $report) { - $colnames = report_datawarehouse_pretify_column_names($firstrow, $report->querysql); + $colnames = report_datawarehouse_prettify_column_names($firstrow, $report->querysql); if ($report->singlerow) { array_unshift($colnames, get_string('queryrundate', 'report_datawarehouse')); } @@ -569,6 +723,14 @@ function report_datawarehouse_get_daily_time_starts($timenow, $at) { ); } +/** + * Get the start of the week. + * + * @param int $timenow a timestamp. + * @return array + * @throws coding_exception + * @throws dml_exception + */ function report_datawarehouse_get_week_starts($timenow) { $dateparts = getdate($timenow); @@ -587,6 +749,12 @@ function report_datawarehouse_get_week_starts($timenow) { ); } +/** + * Get the start of the month. + * + * @param int $timenow a timestamp. + * @return array + */ function report_datawarehouse_get_month_starts($timenow) { $dateparts = getdate($timenow); @@ -596,6 +764,15 @@ function report_datawarehouse_get_month_starts($timenow) { ); } +/** + * Get the start times of the reports. + * + * @param object $report report settings from the database. + * @param int $timenow a timestamp. + * @return array + * @throws coding_exception + * @throws dml_exception + */ function report_datawarehouse_get_starts($report, $timenow) { switch ($report->runable) { case 'daily': @@ -609,6 +786,12 @@ function report_datawarehouse_get_starts($report, $timenow) { } } +/** + * Delete old temp files + * + * @param int $upto a time stamp + * @return int|void + */ function report_datawarehouse_delete_old_temp_files($upto) { global $CFG; @@ -662,6 +845,14 @@ function report_datawarehouse_validate_users($userids, $capability) { return null; } +/** + * Get the 'no data' message + * + * @param object $report report settings from the database. + * @return stdClass + * @throws coding_exception + * @throws moodle_exception + */ function report_datawarehouse_get_message_no_data($report) { // Construct subject. $subject = get_string('emailsubjectnodata', 'report_datawarehouse', @@ -681,6 +872,15 @@ function report_datawarehouse_get_message_no_data($report) { return $message; } +/** + * Get the appropriate message + * + * @param object $report report settings from the database. + * @param string $csvfilename the csv file name + * @return stdClass + * @throws coding_exception + * @throws moodle_exception + */ function report_datawarehouse_get_message($report, $csvfilename) { $handle = fopen($csvfilename, 'r'); $table = new html_table(); @@ -741,6 +941,15 @@ function report_datawarehouse_get_message($report, $csvfilename) { return $message; } +/** + * Send out the email report + * + * @param object $report report settings from the database. + * @param string|null $csvfilename the csv file name + * @throws coding_exception + * @throws dml_exception + * @throws moodle_exception + */ function report_datawarehouse_email_report($report, $csvfilename = null) { global $DB; @@ -766,6 +975,13 @@ function report_datawarehouse_email_report($report, $csvfilename = null) { } } +/** + * Get ready to run daily reports + * + * @param int $timenow a timestamp. + * @return array + * @throws dml_exception + */ function report_datawarehouse_get_ready_to_run_daily_reports($timenow) { global $DB; $reports = $DB->get_records_select('report_datawarehouse_queries', "runable = ?", array('daily'), 'id'); @@ -810,7 +1026,7 @@ function report_datawarehouse_send_email_notification($recipient, $message) { /** * Check if the report is ready to run. * - * @param object $report + * @param object $report report settings from the database. * @param int $timenow * @return boolean */ @@ -828,6 +1044,12 @@ function report_datawarehouse_is_daily_report_ready($report, $timenow) { return false; } +/** + * Get the category options + * + * @return array + * @throws dml_exception + */ function report_datawarehouse_category_options() { global $DB; return $DB->get_records_menu('report_datawarehouse_categories', null, 'name ASC', 'id, name'); @@ -836,9 +1058,9 @@ function report_datawarehouse_category_options() { /** * Copies a csv file to an optional custom directory or file path. * - * @param object $report - * @param integer $timenow - * @param string $csvfilename + * @param object $report report settings from the database. + * @param integer $timenow a time stamp + * @param string|null $csvfilename the csv file name */ function report_datawarehouse_copy_csv_to_customdir($report, $timenow, $csvfilename = null) { diff --git a/settings.php b/settings.php index a5e7265..4d45b4b 100644 --- a/settings.php +++ b/settings.php @@ -18,7 +18,6 @@ * Plugin administration pages are defined here. * * @package report_datawarehouse - * @query_category admin * @copyright 2023 Luca Bösch * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */