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

Enable logs retrieval after course deletion by storing metadata #2

Merged
merged 2 commits into from
Oct 22, 2024
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
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# .github/workflows/ci.yml
name: ci

on: [push, pull_request]

jobs:
ci:
uses: catalyst/catalyst-moodle-workflows/.github/workflows/ci.yml@main
with:
extra_plugin_runners: 'moodle-plugin-ci add-plugin catalyst/moodle-tool_lifecycle'
72 changes: 46 additions & 26 deletions classes/lifecycle/log_table.php
Original file line number Diff line number Diff line change
@@ -14,14 +14,28 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Course backup logs table.
*
* @package tool_lcbackupcourselogstep
* @copyright 2024 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

namespace tool_lcbackupcourselogstep\lifecycle;

defined('MOODLE_INTERNAL') || die;

require_once($CFG->libdir . '/tablelib.php');

class log_table extends \table_sql
{
/**
* Backup log table.
*
* @package tool_lcbackupcourselogstep
* @copyright 2024 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class log_table extends \table_sql {

/**
* @var array "cached" lang strings
@@ -32,44 +46,43 @@ class log_table extends \table_sql
* Constructor for delayed_courses_table.
*
* @throws \coding_exception
* @param array $filterdata Filter data.
*/
public function __construct($filterdata = [])
{
public function __construct($filterdata = []) {
global $DB;

parent::__construct('tool_lcbackupcourselogstep-log');

// Action buttons string
// Action buttons string.
$this->strings = [
'download' => get_string('download')
'download' => get_string('download'),
];

// Build the SQL.
$fields = 'f.id as id,
co.id as courseid, co.shortname as courseshortname, co.fullname as coursefullname,
f.filename as filename, f.timecreated as createdat';

md.oldcourseid as courseid, md.shortname as courseshortname, md.fullname as coursefullname,
f.filename as filename, f.filesize as filesize, f.timecreated as createdat';
$from = '{files} f
JOIN {context} c ON c.id = f.contextid
JOIN {course} co ON co.id = c.instanceid';
LEFT JOIN {tool_lcbackupcourselogstep_metadata} md ON f.id = md.fileid';

$where = ["f.component = :component AND filename <> '.'"];
$params = ['component' => 'tool_lcbackupcourselogstep'];

// Filtering.
if ($filterdata) {
if ($filterdata->shortname) {
$where[] = $DB->sql_like('co.shortname', ':shortname', false, false);
$where[] = $DB->sql_like('md.shortname', ':shortname', false, false);
$params['shortname'] = '%' . $DB->sql_like_escape($filterdata->shortname) . '%';
}

if ($filterdata->fullname) {
$where[] = $DB->sql_like('co.fullname', ':fullname', false, false);
$where[] = $DB->sql_like('md.fullname', ':fullname', false, false);
$params['fullname'] = '%' . $DB->sql_like_escape($filterdata->fullname) . '%';
}

if ($filterdata->courseid) {
$where[] = 'co.id = :courseid';
$where[] = 'md.oldcourseid = :courseid';
$params['courseid'] = $filterdata->courseid;
}
}
@@ -78,13 +91,13 @@ public function __construct($filterdata = [])

$this->set_sql($fields, $from, $where, $params);


// Columns.
$this->define_columns([
'courseid',
'courseshortname',
'coursefullname',
'filename',
'filesize',
'createdat',
'actions',
]);
@@ -94,27 +107,26 @@ public function __construct($filterdata = [])
get_string('course_shortname_header', 'tool_lcbackupcourselogstep'),
get_string('course_fullname_header', 'tool_lcbackupcourselogstep'),
get_string('filename_header', 'tool_lcbackupcourselogstep'),
get_string('filesize_header', 'tool_lcbackupcoursestep'),
get_string('createdat_header', 'tool_lcbackupcourselogstep'),
get_string('actions_header', 'tool_lcbackupcourselogstep'),
]);

// Set default sorting.
$this->sortable(true, 'createdat', SORT_DESC);
$this->sortable(true, 'filesize', SORT_DESC);
$this->collapsible(true);
$this->initialbars(true);
$this->set_attribute('class', 'admintable generaltable');
}

/**
* Define download action.
* Download action column.
*
* @param $row
* @return bool|string
* @throws \coding_exception
* @throws \moodle_exception
* @param object $row
* @return string
*/
public function col_actions($row)
{
public function col_actions($row) {
global $OUTPUT;

$actionmenu = new \action_menu();
@@ -130,15 +142,23 @@ public function col_actions($row)
}

/**
* Time when the file is created, displayed in user-friendly format.
* Display time when the file was created.
*
* @param $row
* @param object $row
* @return string
* @throws \coding_exception
*/
public function col_createdat($row)
{
public function col_createdat($row) {
return userdate($row->createdat);
}

/**
* Display size in user friendly format.
*
* @param object $row
* @return string
*/
public function col_filesize($row) {
return display_size($row->filesize);
}

}
91 changes: 71 additions & 20 deletions classes/lifecycle/step.php
Original file line number Diff line number Diff line change
@@ -14,8 +14,18 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Step for backing up a course logs in the lifecycle process.
*
* @package tool_lcbackupcourselogstep
* @copyright 2024 Catalyst
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

namespace tool_lcbackupcourselogstep\lifecycle;

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

global $CFG;
require_once($CFG->dirroot . '/admin/tool/lifecycle/step/lib.php');

@@ -28,32 +38,52 @@
use tool_lifecycle\step\instance_setting;
use tool_lifecycle\step\libbase;

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

/**
* Step class for the Backup Course Log Step plugin.
*
* @package tool_lcbackupcourselogstep
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class step extends libbase {
public function get_subpluginname()
{
/**
* Returns the subplugin name.
*
* @return string
*/
public function get_subpluginname() {
return 'tool_lcbackupcourselogstep';
}

/**
* Get the plugin description.
*
* @return string
*/
public function get_plugin_description() {
return "Backup course log step plugin";
}

public function process_course($processid, $instanceid, $course)
{
/**
* Processes the course.
*
* @param int $processid the process id.
* @param int $instanceid step instance id.
* @param object $course the course object.
* @return step_response
*/
public function process_course($processid, $instanceid, $course) {
global $DB;

// Get all logs for the course with related courses and user details.
$sql = "SELECT log.*, c.shortname as courseshortname, c.fullname as coursefullname,
u1.firstname as userfirstname, u1.lastname as userlastname,
u1.firstname as userfirstname, u1.lastname as userlastname,
u2.firstname as realuserfirstname, u2.lastname as realuserlastname,
u3.firstname as relateduserfirstname, u3.lastname as relateduserlastname
FROM {logstore_standard_log} as log
LEFT JOIN {course} as c ON log.courseid = c.id
LEFT JOIN {user} as u1 ON log.userid = u1.id
LEFT JOIN {user} as u2 ON log.realuserid = u2.id
LEFT JOIN {user} as u3 ON log.relateduserid = u3.id
u3.firstname as relateduserfirstname, u3.lastname as relateduserlastname
FROM {logstore_standard_log} log
LEFT JOIN {course} c ON log.courseid = c.id
LEFT JOIN {user} u1 ON log.userid = u1.id
LEFT JOIN {user} u2 ON log.realuserid = u2.id
LEFT JOIN {user} u3 ON log.relateduserid = u3.id
WHERE courseid = :courseid";

// Get all logs for the course.
@@ -82,7 +112,7 @@ public function process_course($processid, $instanceid, $course)

// Prepare file record.
$filerecord = [
'contextid' => \context_course::instance($course->id)->id,
'contextid' => \context_system::instance()->id,
'component' => 'tool_lcbackupcourselogstep',
'filearea' => 'course_log',
'itemid' => $instanceid,
@@ -99,18 +129,37 @@ public function process_course($processid, $instanceid, $course)
}

// Write data to file.
dataformat::write_data_to_filearea($filerecord, $fileformat, $columns, $logs);
$newfile = dataformat::write_data_to_filearea($filerecord, $fileformat, $columns, $logs);

$DB->insert_record('tool_lcbackupcourselogstep_metadata', [
'shortname' => $course->shortname,
'fullname' => $course->fullname,
'oldcourseid' => $course->id,
'fileid' => $newfile->get_id(),
'timecreated' => time(),
]);

// Proceed.
return step_response::proceed();
}

/**
* Returns instance settings for the plugin.
*
* @return array The instance settings for this step.
*/
public function instance_settings() {
return [
new instance_setting('fileformat', PARAM_TEXT, true),
];
}

/**
* Extend the instance form to add file format options.
*
* @param \MoodleQuickForm $mform The form object.
* @return void
*/
public function extend_add_instance_form_definition($mform) {
$fileformatoptions = [
'csv' => 'CSV',
@@ -119,7 +168,7 @@ public function extend_add_instance_form_definition($mform) {

// Check if XMLWriter is available.
// Available data formats are installed under 'dataformat' folder.
// We need to install https://moodle.org/plugins/dataformat_xml
// We need to install https://moodle.org/plugins/dataformat_xml.
$classname = 'dataformat_xml\writer';
if (class_exists($classname)) {
$fileformatoptions['xml'] = 'XML';
@@ -131,17 +180,19 @@ public function extend_add_instance_form_definition($mform) {
);
$mform->setType('fileformat', PARAM_TEXT);
$mform->setDefault('fileformat', 'csv');

}

public function get_plugin_settings()
{
/**
* Returns the instance settings.
*
* @return void
*/
public function get_plugin_settings() {
global $ADMIN;
// Page to show the logs.
$ADMIN->add('lifecycle_category', new admin_externalpage('tool_lcbackupcourselogstep_logs',
get_string('courselogs', 'tool_lcbackupcourselogstep'),
new moodle_url('/admin/tool/lcbackupcourselogstep/logs.php')));

}

}
7 changes: 4 additions & 3 deletions classes/privacy/provider.php
Original file line number Diff line number Diff line change
@@ -19,9 +19,10 @@
use core_privacy\local\metadata\null_provider;

/**
* Privacy subsystem implementation for tool_samplestep.
* Privacy subsystem implementation for tool_lcbackupcourselogstep.
*
* @package tool_samplestep
* @package tool_lcbackupcourselogstep
* @copyright 2024 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements null_provider {
@@ -32,7 +33,7 @@ class provider implements null_provider {
*
* @return string the reason
*/
public static function get_reason() : string {
public static function get_reason(): string {
return 'privacy:metadata';
}
}
22 changes: 22 additions & 0 deletions db/install.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="admin/tool/lcbackupcourselogstep/db" VERSION="2024102000" COMMENT="XMLDB file for Moodle tool/lcbackupcourselogstep"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<TABLE NAME="tool_lcbackupcourselogstep_metadata" COMMENT="Metadata for course logs.">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="shortname" TYPE="char" LENGTH="255" NOTNULL="true"/>
<FIELD NAME="fullname" TYPE="char" LENGTH="255" NOTNULL="true"/>
<FIELD NAME="oldcourseid" TYPE="int" LENGTH="10" NOTNULL="true"/>
<FIELD NAME="fileid" TYPE="int" LENGTH="10" NOTNULL="true"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" COMMENT="Timestamp when the log file was created"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="fileid_fk" TYPE="foreign" FIELDS="fileid" REFTABLE="files" REFFIELDS="id"/>
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
Loading