MDL-78741 files: context report entity data for path and parent.

Allows for better aggregation/grouping of file data by context tree.
This commit is contained in:
Paul Holden 2023-07-20 17:53:35 +01:00
parent 5a44292a05
commit ce1db1499d
No known key found for this signature in database
GPG Key ID: A81A96D6045F6164
3 changed files with 90 additions and 13 deletions

View File

@ -18,8 +18,7 @@ declare(strict_types=1);
namespace core_files\reportbuilder\datasource;
use context_course;
use context_user;
use core\context\{course, coursecat, user};
use core_reportbuilder_generator;
use core_reportbuilder_testcase;
use core_reportbuilder\local\filters\{boolean_select, date, number, select, text};
@ -46,10 +45,10 @@ class files_test extends core_reportbuilder_testcase {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$coursecontext = context_course::instance($course->id);
$coursecontext = course::instance($course->id);
$user = $this->getDataGenerator()->create_user();
$usercontext = context_user::instance($user->id);
$usercontext = user::instance($user->id);
$this->setUser($user);
@ -91,11 +90,14 @@ class files_test extends core_reportbuilder_testcase {
$this->resetAfterTest();
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$coursecontext = context_course::instance($course->id);
$category = $this->getDataGenerator()->create_category();
$categorycontext = coursecat::instance($category->id);
$course = $this->getDataGenerator()->create_course(['category' => $category->id]);
$coursecontext = course::instance($course->id);
$user = $this->getDataGenerator()->create_user();
$usercontext = context_user::instance($user->id);
$usercontext = user::instance($user->id);
$this->setUser($user);
@ -110,6 +112,9 @@ class files_test extends core_reportbuilder_testcase {
'sortenabled' => 1, 'sortorder' => 1]);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'context:name']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'context:level']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'context:path']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'context:parent']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'file:path']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'file:author']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'file:license']);
@ -130,6 +135,8 @@ class files_test extends core_reportbuilder_testcase {
"<a href=\"{$coursecontext->get_url()}\">{$coursecontext->get_context_name()}</a>",
$coursecontext->get_context_name(),
'Course',
$coursecontext->path,
$categorycontext->get_context_name(),
'/',
null,
'',
@ -142,6 +149,8 @@ class files_test extends core_reportbuilder_testcase {
"<a href=\"{$coursecontext->get_url()}\">{$coursecontext->get_context_name()}</a>",
$coursecontext->get_context_name(),
'Course',
$coursecontext->path,
$categorycontext->get_context_name(),
'/',
null,
'',
@ -154,6 +163,8 @@ class files_test extends core_reportbuilder_testcase {
"<a href=\"{$usercontext->get_url()}\">{$usercontext->get_context_name()}</a>",
$usercontext->get_context_name(),
'User',
$usercontext->path,
'System',
'/',
null,
'',
@ -166,6 +177,8 @@ class files_test extends core_reportbuilder_testcase {
"<a href=\"{$usercontext->get_url()}\">{$usercontext->get_context_name()}</a>",
$usercontext->get_context_name(),
'User',
$usercontext->path,
'System',
'/',
null,
'',
@ -233,6 +246,14 @@ class files_test extends core_reportbuilder_testcase {
'context:level_operator' => select::EQUAL_TO,
'context:level_value' => CONTEXT_BLOCK,
], 0],
'Context path' => ['context:path', [
'context:path_operator' => text::STARTS_WITH,
'context:path_value' => '/1/',
], 4],
'Context path (no match)' => ['context:path', [
'context:path_operator' => text::STARTS_WITH,
'context:path_value' => '/1/2/3/',
], 0],
// User.
'Filter user' => ['user:username', [
@ -267,7 +288,7 @@ class files_test extends core_reportbuilder_testcase {
$this->setUser($user);
$course = $this->getDataGenerator()->create_course();
$coursecontext = context_course::instance($course->id);
$coursecontext = course::instance($course->id);
$this->generate_test_files($coursecontext);
@ -302,7 +323,7 @@ class files_test extends core_reportbuilder_testcase {
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$coursecontext = context_course::instance($course->id);
$coursecontext = course::instance($course->id);
$this->generate_test_files($coursecontext);
@ -326,17 +347,17 @@ class files_test extends core_reportbuilder_testcase {
/**
* Helper method to generate some test files (a user draft and course summary file) for reporting on
*
* @param context_course $context
* @param course $context
* @return int Draft item ID
*/
protected function generate_test_files(context_course $context): int {
protected function generate_test_files(course $context): int {
global $USER;
$draftitemid = file_get_unused_draft_itemid();
// Populate user draft.
get_file_storage()->create_file_from_string([
'contextid' => context_user::instance($USER->id)->id,
'contextid' => user::instance($USER->id)->id,
'userid' => $USER->id,
'component' => 'user',
'filearea' => 'draft',

View File

@ -301,6 +301,7 @@ $string['contentbank'] = 'Content bank';
$string['context'] = 'Context';
$string['contextlevel'] = 'Context level';
$string['contextname'] = 'Context name';
$string['contextparent'] = 'Parent';
$string['contexturl'] = 'Context URL';
$string['continue'] = 'Continue';
$string['continuetocourse'] = 'Click here to enter your course';

View File

@ -20,7 +20,7 @@ namespace core\reportbuilder\local\entities;
use core\context_helper;
use core_reportbuilder\local\entities\base;
use core_reportbuilder\local\filters\select;
use core_reportbuilder\local\filters\{select, text};
use core_reportbuilder\local\report\{column, filter};
use html_writer;
use lang_string;
@ -81,6 +81,8 @@ class context extends base {
* @return column[]
*/
protected function get_all_columns(): array {
global $DB;
$contextalias = $this->get_table_alias('context');
// Name.
@ -145,6 +147,49 @@ class context extends base {
return context_helper::get_level_name($level);
});
// Path.
$columns[] = (new column(
'path',
new lang_string('path'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TEXT)
->add_field("{$contextalias}.path")
->set_is_sortable(true);
// Parent (note we select the parent path in SQL, so that aggregation/grouping is on the parent data itself).
$columns[] = (new column(
'parent',
new lang_string('contextparent'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TEXT)
// The "path" column looks like "/1/2/3", for context ID 3. In order to select/group by the parent context, we
// concatenate a trailing slash (to prevent partial matches, e.g. "/1/2/31"), then replace "/3/" with empty string.
->add_field("
REPLACE(
" . $DB->sql_concat("{$contextalias}.path", "'/'") . ",
" . $DB->sql_concat("'/'", $DB->sql_cast_to_char("{$contextalias}.id"), "'/'") . ",
''
)", 'parent'
)
// Sorting may not order alphabetically, but will at least group contexts together.
->set_is_sortable(true)
->add_callback(static function (?string $parent): string {
// System level (no parent) or null.
if ($parent === '' || $parent === null) {
return '';
}
$contextids = explode('/', $parent);
$contextid = (int) array_pop($contextids);
return context_helper::instance_by_id($contextid)->get_context_name();
});
return $columns;
}
@ -173,6 +218,16 @@ class context extends base {
}, $levels);
});
// Path.
$filters[] = (new filter(
text::class,
'path',
new lang_string('path'),
$this->get_entity_name(),
"{$contextalias}.path"
))
->add_joins($this->get_joins());
return $filters;
}
}