mirror of
https://github.com/moodle/moodle.git
synced 2025-01-16 21:18:33 +01:00
MDL-78427 core_theme: Add theme usage report and icon
In addition to adding in theme usage reports, there is also the addition of an icon on the theme cards which takes you to the report. This icon only appears for that theme if it has been used in any overriding context.
This commit is contained in:
parent
f30110b5eb
commit
40d397ab5f
@ -293,14 +293,27 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) { // sp
|
||||
new lang_string('configthemedesignermode', 'admin'), 0);
|
||||
$setting->set_updatedcallback('theme_reset_all_caches');
|
||||
$temp->add($setting);
|
||||
$temp->add(new admin_setting_configcheckbox('allowuserthemes', new lang_string('allowuserthemes', 'admin'),
|
||||
new lang_string('configallowuserthemes', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('allowcoursethemes', new lang_string('allowcoursethemes', 'admin'),
|
||||
new lang_string('configallowcoursethemes', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('allowcategorythemes', new lang_string('allowcategorythemes', 'admin'),
|
||||
new lang_string('configallowcategorythemes', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('allowcohortthemes', new lang_string('allowcohortthemes', 'admin'),
|
||||
new lang_string('configallowcohortthemes', 'admin'), 0));
|
||||
|
||||
$setting = new admin_setting_configcheckbox('allowuserthemes', new lang_string('allowuserthemes', 'admin'),
|
||||
new lang_string('configallowuserthemes', 'admin'), 0);
|
||||
$setting->set_updatedcallback('theme_purge_used_in_context_caches');
|
||||
$temp->add($setting);
|
||||
|
||||
$setting = new admin_setting_configcheckbox('allowcoursethemes', new lang_string('allowcoursethemes', 'admin'),
|
||||
new lang_string('configallowcoursethemes', 'admin'), 0);
|
||||
$setting->set_updatedcallback('theme_purge_used_in_context_caches');
|
||||
$temp->add($setting);
|
||||
|
||||
$setting = new admin_setting_configcheckbox('allowcategorythemes', new lang_string('allowcategorythemes', 'admin'),
|
||||
new lang_string('configallowcategorythemes', 'admin'), 0);
|
||||
$setting->set_updatedcallback('theme_purge_used_in_context_caches');
|
||||
$temp->add($setting);
|
||||
|
||||
$setting = new admin_setting_configcheckbox('allowcohortthemes', new lang_string('allowcohortthemes', 'admin'),
|
||||
new lang_string('configallowcohortthemes', 'admin'), 0);
|
||||
$setting->set_updatedcallback('theme_purge_used_in_context_caches');
|
||||
$temp->add($setting);
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('allowthemechangeonurl', new lang_string('allowthemechangeonurl', 'admin'),
|
||||
new lang_string('configallowthemechangeonurl', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('allowuserblockhiding', new lang_string('allowuserblockhiding', 'admin'),
|
||||
|
@ -27,7 +27,8 @@
|
||||
"current": true,
|
||||
"actionurl": "http://moodlesite/admin/themeselector.php",
|
||||
"sesskey": "123XYZ",
|
||||
"settingsurl": "http://moodlesite/admin/settings.php?section=themesettingboost"
|
||||
"settingsurl": "http://moodlesite/admin/settings.php?section=themesettingboost",
|
||||
"reporturl": "http://moodlesite/report/themeusage/index.php?themechoice=boost"
|
||||
}
|
||||
}}
|
||||
<div class="card dashboard-card" role="listitem" id="theme-card-{{choose}}" aria-labelledby="theme-name-{{choose}} {{#current}}current-theme-{{choose}}{{/current}}">
|
||||
@ -53,6 +54,16 @@
|
||||
<i class="icon fa fa-info-circle m-0" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{#str}}previewthemename, moodle, {{name}}{{/str}}</span>
|
||||
</button>
|
||||
{{#reporturl}}
|
||||
<a
|
||||
href="{{reporturl}}"
|
||||
id="theme-usage-report-{{choose}}"
|
||||
class="btn btn-link p-0 ml-2"
|
||||
title="{{#str}}themeusagereportname, admin, {{name}}{{/str}}">
|
||||
<i class="icon fa fa-area-chart m-0" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{#str}}themeusagereportname, admin, {{name}}{{/str}}</span>
|
||||
</a>
|
||||
{{/reporturl}}
|
||||
{{#settingsurl}}
|
||||
<a
|
||||
href="{{settingsurl}}"
|
||||
|
@ -127,6 +127,13 @@ foreach ($themes as $themename => $themedir) {
|
||||
$themedata['settingsurl'] = $settingsurl;
|
||||
}
|
||||
|
||||
// Link to the theme usage report if override enabled and it is being used in at least one context.
|
||||
if (\core\output\theme_usage::is_theme_used_in_any_context($themename) === \core\output\theme_usage::THEME_IS_USED) {
|
||||
$reporturl = new moodle_url($CFG->wwwroot . '/report/themeusage/index.php');
|
||||
$reporturl->params(['themechoice' => $themename]);
|
||||
$themedata['reporturl'] = $reporturl->out(false);
|
||||
}
|
||||
|
||||
$data[$index] = $themedata;
|
||||
$index++;
|
||||
}
|
||||
|
@ -101,6 +101,15 @@ function cohort_update_cohort($cohort) {
|
||||
if (empty($CFG->allowcohortthemes) && isset($cohort->theme)) {
|
||||
unset($cohort->theme);
|
||||
}
|
||||
|
||||
// Delete theme usage cache if the theme has been changed.
|
||||
if (isset($cohort->theme)) {
|
||||
$oldcohort = $DB->get_record('cohort', ['id' => $cohort->id]);
|
||||
if ($cohort->theme != $oldcohort->theme) {
|
||||
theme_delete_used_in_context_cache($cohort->theme, $oldcohort->theme);
|
||||
}
|
||||
}
|
||||
|
||||
$cohort->timemodified = time();
|
||||
|
||||
// Update custom fields if there are any of them in the form.
|
||||
|
@ -628,6 +628,14 @@ class core_course_category implements renderable, cacheable_object, IteratorAggr
|
||||
fix_course_sortorder();
|
||||
}
|
||||
|
||||
// Delete theme usage cache if the theme has been changed.
|
||||
if (isset($data->theme)) {
|
||||
$oldcategory = $DB->get_record('course_categories', ['id' => $data->id]);
|
||||
if ($data->theme != $oldcategory->theme) {
|
||||
theme_delete_used_in_context_cache($data->theme, (string)$oldcategory->theme);
|
||||
}
|
||||
}
|
||||
|
||||
$newcategory->timemodified = time();
|
||||
|
||||
$categorycontext = $this->get_context();
|
||||
|
@ -488,7 +488,6 @@ class course_edit_form extends moodleform {
|
||||
// Tweak the form with values provided by custom fields in use.
|
||||
$handler = core_course\customfield\course_handler::create();
|
||||
$handler->instance_form_definition_after_data($mform, empty($courseid) ? 0 : $courseid);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2485,6 +2485,11 @@ function update_course($data, $editoroptions = NULL) {
|
||||
$DB->delete_records('course_format_options',
|
||||
array('courseid' => $course->id, 'format' => $oldcourse->format));
|
||||
}
|
||||
|
||||
// Delete theme usage cache if the theme has been changed.
|
||||
if (isset($data->theme) && ($data->theme != $oldcourse->theme)) {
|
||||
theme_delete_used_in_context_cache($data->theme, $oldcourse->theme);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1463,6 +1463,8 @@ $string['themeselect'] = 'Change theme';
|
||||
$string['themeselector'] = 'Themes';
|
||||
$string['themesettingsadvanced'] = 'Advanced theme settings';
|
||||
$string['themeeditsettingsname'] = 'Edit theme settings \'{$a}\'';
|
||||
$string['themesettingsname'] = 'Theme settings \'{$a}\'';
|
||||
$string['themeusagereportname'] = 'Theme usage report \'{$a}\'';
|
||||
$string['therewereerrors'] = 'There were errors in your data';
|
||||
$string['thirdpartylibrary'] = 'Library';
|
||||
$string['thirdpartylibrarylocation'] = 'Location';
|
||||
|
@ -96,6 +96,7 @@ $string['cachedef_grade_letters'] = 'Grade letter queries';
|
||||
$string['cachedef_string'] = 'Language string cache';
|
||||
$string['cachedef_tags'] = 'Tags collections and areas';
|
||||
$string['cachedef_temp_tables'] = 'Temporary tables cache';
|
||||
$string['cachedef_theme_usedincontext'] = 'A theme has been used in context to override the default theme';
|
||||
$string['cachedef_userselections'] = 'Data used to persist user selections throughout Moodle';
|
||||
$string['cachedef_user_favourite_course_content_items'] = 'User\'s starred items';
|
||||
$string['cachedef_user_group_groupings'] = 'User\'s groupings and groups per course';
|
||||
|
127
lib/classes/output/theme_usage.php
Normal file
127
lib/classes/output/theme_usage.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core\output;
|
||||
|
||||
/**
|
||||
* This class houses methods for checking theme usage in a given context.
|
||||
*
|
||||
* @package core
|
||||
* @category output
|
||||
* @copyright 2024 David Woloszyn <david.woloszyn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class theme_usage {
|
||||
|
||||
/** @var string The theme usage type for users. */
|
||||
public const THEME_USAGE_TYPE_USER = 'user';
|
||||
|
||||
/** @var string The theme usage type for courses. */
|
||||
public const THEME_USAGE_TYPE_COURSE = 'course';
|
||||
|
||||
/** @var string The theme usage type for cohorts. */
|
||||
public const THEME_USAGE_TYPE_COHORT = 'cohort';
|
||||
|
||||
/** @var string The theme usage type for categories. */
|
||||
public const THEME_USAGE_TYPE_CATEGORY = 'category';
|
||||
|
||||
/** @var string The theme usage type for all. */
|
||||
public const THEME_USAGE_TYPE_ALL = 'all';
|
||||
|
||||
/** @var int The theme is used in context. */
|
||||
public const THEME_IS_USED = 1;
|
||||
|
||||
/** @var int The theme is not used in context. */
|
||||
public const THEME_IS_NOT_USED = 0;
|
||||
|
||||
/**
|
||||
* Check if the theme is used in any context (e.g. user, course, cohort, category).
|
||||
*
|
||||
* This query is cached.
|
||||
*
|
||||
* @param string $themename The theme to check.
|
||||
* @return int Return 1 if at least one record was found, 0 if none.
|
||||
*/
|
||||
public static function is_theme_used_in_any_context(string $themename): int {
|
||||
global $DB;
|
||||
$cache = \cache::make('core', 'theme_usedincontext');
|
||||
$isused = $cache->get($themename);
|
||||
|
||||
if ($isused === false) {
|
||||
|
||||
$sqlunions = [];
|
||||
|
||||
// For each context, check if the config is enabled and there is at least one use.
|
||||
if (get_config('core', 'allowuserthemes')) {
|
||||
$sqlunions[self::THEME_USAGE_TYPE_USER] = "
|
||||
SELECT u.id
|
||||
FROM {user} u
|
||||
WHERE u.theme = :usertheme
|
||||
";
|
||||
}
|
||||
|
||||
if (get_config('core', 'allowcoursethemes')) {
|
||||
$sqlunions[self::THEME_USAGE_TYPE_COURSE] = "
|
||||
SELECT c.id
|
||||
FROM {course} c
|
||||
WHERE c.theme = :coursetheme
|
||||
";
|
||||
}
|
||||
|
||||
if (get_config('core', 'allowcohortthemes')) {
|
||||
$sqlunions[self::THEME_USAGE_TYPE_COHORT] = "
|
||||
SELECT co.id
|
||||
FROM {cohort} co
|
||||
WHERE co.theme = :cohorttheme
|
||||
";
|
||||
}
|
||||
|
||||
if (get_config('core', 'allowcategorythemes')) {
|
||||
$sqlunions[self::THEME_USAGE_TYPE_CATEGORY] = "
|
||||
SELECT cat.id
|
||||
FROM {course_categories} cat
|
||||
WHERE cat.theme = :categorytheme
|
||||
";
|
||||
}
|
||||
|
||||
// Union the sql statements from the different tables.
|
||||
if (!empty($sqlunions)) {
|
||||
$sql = implode(' UNION ', $sqlunions);
|
||||
|
||||
// Prepare params.
|
||||
$params = [];
|
||||
foreach ($sqlunions as $type => $val) {
|
||||
$params[$type . 'theme'] = $themename;
|
||||
}
|
||||
|
||||
$result = $DB->record_exists_sql($sql, $params);
|
||||
}
|
||||
|
||||
if (!empty($result)) {
|
||||
$isused = self::THEME_IS_USED;
|
||||
} else {
|
||||
$isused = self::THEME_IS_NOT_USED;
|
||||
}
|
||||
|
||||
// Cache the result so we don't have to keep checking for this theme.
|
||||
$cache->set($themename, $isused);
|
||||
return $isused;
|
||||
|
||||
} else {
|
||||
return $isused;
|
||||
}
|
||||
}
|
||||
}
|
@ -609,4 +609,13 @@ $definitions = array(
|
||||
'changesincourse',
|
||||
],
|
||||
],
|
||||
|
||||
// A theme has been used in context to override the default theme.
|
||||
// Applies to user, cohort, category and course.
|
||||
'theme_usedincontext' => [
|
||||
'mode' => cache_store::MODE_APPLICATION,
|
||||
'simplekeys' => true,
|
||||
'simpledata' => true,
|
||||
'staticacceleration' => true,
|
||||
],
|
||||
);
|
||||
|
@ -300,6 +300,33 @@ function theme_set_designer_mod($state) {
|
||||
theme_reset_all_caches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Purge theme used in context caches.
|
||||
*/
|
||||
function theme_purge_used_in_context_caches() {
|
||||
\cache::make('core', 'theme_usedincontext')->purge();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete theme used in context cache for a particular theme.
|
||||
*
|
||||
* When switching themes, both old and new theme caches are deleted.
|
||||
* This gives the query the opportunity to recache accurate results for both themes.
|
||||
*
|
||||
* @param string $newtheme The incoming new theme.
|
||||
* @param string $oldtheme The theme that was already set.
|
||||
*/
|
||||
function theme_delete_used_in_context_cache(string $newtheme, string $oldtheme): void {
|
||||
if ((strlen($newtheme) > 0) && (strlen($oldtheme) > 0)) {
|
||||
// Theme -> theme.
|
||||
\cache::make('core', 'theme_usedincontext')->delete($oldtheme);
|
||||
\cache::make('core', 'theme_usedincontext')->delete($newtheme);
|
||||
} else {
|
||||
// No theme -> theme, or theme -> no theme.
|
||||
\cache::make('core', 'theme_usedincontext')->delete($newtheme . $oldtheme);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class represents the configuration variables of a Moodle theme.
|
||||
*
|
||||
|
98
report/themeusage/classes/form/theme_usage_form.php
Normal file
98
report/themeusage/classes/form/theme_usage_form.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace report_themeusage\form;
|
||||
|
||||
use moodleform;
|
||||
use core\output\theme_usage;
|
||||
|
||||
/**
|
||||
* Defines the form for generating theme usage report data.
|
||||
*
|
||||
* @package report_themeusage
|
||||
* @copyright 2023 David Woloszyn <david.woloszyn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL Juv3 or later
|
||||
*/
|
||||
class theme_usage_form extends moodleform {
|
||||
|
||||
/**
|
||||
* Build the form definition.
|
||||
*/
|
||||
protected function definition() {
|
||||
$mform = $this->_form;
|
||||
|
||||
// Theme choices (e.g. boost, classic).
|
||||
$themechoice = $this->_customdata['themechoice'];
|
||||
$themechoices = array_merge(['' => get_string('select') . '...'], self::get_theme_choices());
|
||||
$mform->addElement('select', 'themechoice', get_string('themename', 'report_themeusage'), $themechoices);
|
||||
$mform->setType('themechoice', PARAM_TEXT);
|
||||
$mform->addRule('themechoice', get_string('required'), 'required', null, 'client');
|
||||
if (!empty($themechoice)) {
|
||||
$mform->setDefault('themechoice', $themechoice);
|
||||
}
|
||||
|
||||
// Theme usage types (e.g. user, course, cohort, category).
|
||||
$typechoices = self::get_type_choices();
|
||||
$mform->addElement('select', 'typechoice', get_string('usagetype', 'report_themeusage'), $typechoices);
|
||||
$mform->setType('typechoice', PARAM_TEXT);
|
||||
$mform->addRule('typechoice', get_string('required'), 'required', null, 'client');
|
||||
$mform->setDefault(theme_usage::THEME_USAGE_TYPE_ALL, $themechoice);
|
||||
|
||||
// Submit button.
|
||||
$mform->addElement('submit', 'submit', get_string('getreport', 'report_themeusage'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of available theme usage types.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_type_choices(): array {
|
||||
return [
|
||||
theme_usage::THEME_USAGE_TYPE_ALL => get_string('all'),
|
||||
theme_usage::THEME_USAGE_TYPE_USER => get_string('user'),
|
||||
theme_usage::THEME_USAGE_TYPE_COURSE => get_string('course'),
|
||||
theme_usage::THEME_USAGE_TYPE_COHORT => get_string('cohort', 'cohort'),
|
||||
theme_usage::THEME_USAGE_TYPE_CATEGORY => get_string('category'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of available themes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_theme_choices(): array {
|
||||
$themes = \core_component::get_plugin_list('theme');
|
||||
foreach ($themes as $themename => $themedir) {
|
||||
$themechoices[$themename] = get_string('pluginname', 'theme_'.$themename);
|
||||
}
|
||||
return $themechoices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the requested theme is in a list of available themes.
|
||||
*
|
||||
* @param string $themechoice The theme name.
|
||||
* @return bool
|
||||
*/
|
||||
public static function validate_theme_choice_param(string $themechoice): bool {
|
||||
if (!empty($themechoice) && !array_key_exists($themechoice, self::get_theme_choices())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
45
report/themeusage/classes/privacy/provider.php
Normal file
45
report/themeusage/classes/privacy/provider.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for report_themeusage.
|
||||
*
|
||||
* @package report_themeusage
|
||||
* @copyright 2023 David Woloszyn <david.woloszyn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace report_themeusage\privacy;
|
||||
|
||||
/**
|
||||
* Privacy Subsystem for report_themeusage implementing null_provider.
|
||||
*
|
||||
* @package report_themeusage
|
||||
* @copyright 2023 David Woloszyn <david.woloszyn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider {
|
||||
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason(): string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
134
report/themeusage/classes/reportbuilder/local/entities/theme.php
Normal file
134
report/themeusage/classes/reportbuilder/local/entities/theme.php
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace report_themeusage\reportbuilder\local\entities;
|
||||
|
||||
use core_reportbuilder\local\entities\base;
|
||||
use core_reportbuilder\local\report\column;
|
||||
use lang_string;
|
||||
|
||||
/**
|
||||
* Theme entity.
|
||||
*
|
||||
* Defines all the columns and filters that can be added to reports that use this entity.
|
||||
*
|
||||
* @package report_themeusage
|
||||
* @copyright 2023 David Woloszyn <david.woloszyn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class theme extends base {
|
||||
|
||||
/**
|
||||
* Database tables that this entity uses.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_default_tables(): array {
|
||||
return [
|
||||
'config_plugins',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The default title for this entity.
|
||||
*
|
||||
* @return lang_string
|
||||
*/
|
||||
protected function get_default_entity_title(): lang_string {
|
||||
return new lang_string('theme');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the entity.
|
||||
*
|
||||
* @return base
|
||||
*/
|
||||
public function initialise(): base {
|
||||
$columns = $this->get_all_columns();
|
||||
foreach ($columns as $column) {
|
||||
$this->add_column($column);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of all available columns.
|
||||
*
|
||||
* @return column[]
|
||||
*/
|
||||
protected function get_all_columns(): array {
|
||||
global $DB;
|
||||
$themealias = $this->get_table_alias('config_plugins');
|
||||
$sqlsubstring = $DB->sql_substr("{$themealias}.plugin", 7);
|
||||
|
||||
$courselabel = get_string('course');
|
||||
$cohortlabel = get_string('cohort', 'cohort');
|
||||
$userlabel = get_string('user');
|
||||
$categorylabel = get_string('category');
|
||||
|
||||
// Force theme column.
|
||||
$columns[] = (new column(
|
||||
'forcetheme',
|
||||
new lang_string('forcetheme'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_fields("{$themealias}.plugin")
|
||||
->add_callback(static function(?string $theme): string {
|
||||
$theme = get_string('pluginname', $theme);
|
||||
return format_text($theme, FORMAT_PLAIN);
|
||||
});
|
||||
|
||||
// Usage type column.
|
||||
$columns[] = (new column(
|
||||
'usagetype',
|
||||
new lang_string('usagetype', 'report_themeusage'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_join("LEFT JOIN (
|
||||
SELECT '{$courselabel}' AS usagetype, theme, COUNT(theme) AS themecount
|
||||
FROM {course}
|
||||
WHERE " . $DB->sql_isnotempty('course', 'theme', false, false) . "
|
||||
GROUP BY theme
|
||||
UNION
|
||||
SELECT '{$userlabel}' AS usagetype, theme, COUNT(theme) AS themecount
|
||||
FROM {user}
|
||||
WHERE " . $DB->sql_isnotempty('user', 'theme', false, false) . "
|
||||
GROUP BY theme
|
||||
UNION
|
||||
SELECT '{$cohortlabel}' AS usagetype, theme, COUNT(theme) AS themecount
|
||||
FROM {cohort}
|
||||
WHERE " . $DB->sql_isnotempty('cohort', 'theme', false, false) . "
|
||||
GROUP BY theme
|
||||
UNION
|
||||
SELECT '{$categorylabel}' AS usagetype, theme, COUNT(theme) AS themecount
|
||||
FROM {course_categories}
|
||||
WHERE " . $DB->sql_isnotempty('course_categories', 'theme', false, false) . "
|
||||
GROUP BY theme
|
||||
) tuse ON tuse.theme={$sqlsubstring}")
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_fields("tuse.usagetype, tuse.themecount")
|
||||
->add_callback(static function(?string $usagetype, \stdClass $row): string {
|
||||
$count = $row->themecount ?? 0;
|
||||
return format_text($usagetype . ' ('. $count . ')', FORMAT_PLAIN);
|
||||
});
|
||||
|
||||
return $columns;
|
||||
}
|
||||
}
|
@ -0,0 +1,256 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace report_themeusage\reportbuilder\local\systemreports;
|
||||
|
||||
use context_system;
|
||||
use core_reportbuilder\local\entities\{course, user};
|
||||
use core_cohort\reportbuilder\local\entities\cohort;
|
||||
use core_course\reportbuilder\local\entities\course_category;
|
||||
use core_reportbuilder\local\helpers\database;
|
||||
use core_reportbuilder\system_report;
|
||||
use core\output\theme_usage;
|
||||
use report_themeusage\reportbuilder\local\entities\theme;
|
||||
|
||||
/**
|
||||
* Config changes system report class implementation
|
||||
*
|
||||
* @package report_themeusage
|
||||
* @copyright 2023 David Woloszyn <david.woloszyn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class theme_usage_report extends system_report {
|
||||
|
||||
/**
|
||||
* Initialise report, we need to set the main table, load our entities and set columns/filters.
|
||||
*/
|
||||
protected function initialise(): void {
|
||||
// Show results depending on the theme and type chosen.
|
||||
$themechoice = $this->get_parameter('themechoice', '', PARAM_TEXT);
|
||||
$typechoice = $this->get_parameter('typechoice', '', PARAM_TEXT);
|
||||
|
||||
$themename = get_string('pluginname', 'theme_'.$themechoice);
|
||||
|
||||
$themeentity = new theme();
|
||||
$themealias = $themeentity->get_table_alias('config_plugins');
|
||||
$this->set_main_table('config_plugins', $themealias);
|
||||
$this->add_entity($themeentity);
|
||||
|
||||
$param1 = database::generate_param_name();
|
||||
$param2 = database::generate_param_name();
|
||||
$params = [$param1 => 'theme_' . $themechoice, $param2 => 'version'];
|
||||
|
||||
$this->add_base_condition_sql("{$themealias}.plugin = :{$param1} AND {$themealias}.name = :{$param2}", $params);
|
||||
|
||||
switch ($typechoice) {
|
||||
|
||||
case theme_usage::THEME_USAGE_TYPE_ALL:
|
||||
|
||||
$this->add_columns_theme();
|
||||
$this->set_downloadable(true, get_string('themeusagereportall', 'report_themeusage', $themename));
|
||||
|
||||
break;
|
||||
|
||||
case theme_usage::THEME_USAGE_TYPE_USER:
|
||||
|
||||
$userentity = new user();
|
||||
$useralias = $userentity->get_table_alias('user');
|
||||
|
||||
$this->add_entity($userentity->add_join(
|
||||
"JOIN {user} {$useralias}
|
||||
ON $useralias.theme = '{$themechoice}'
|
||||
AND {$themealias}.plugin = 'theme_{$themechoice}'"));
|
||||
|
||||
$this->add_columns_user();
|
||||
$this->add_filters_user();
|
||||
$this->set_downloadable(true, get_string('themeusagereportuser', 'report_themeusage', $themename));
|
||||
break;
|
||||
|
||||
case theme_usage::THEME_USAGE_TYPE_COURSE:
|
||||
|
||||
$courseentity = new course();
|
||||
$coursealias = $courseentity->get_table_alias('course');
|
||||
|
||||
$this->add_entity($courseentity->add_join(
|
||||
"JOIN {course} {$coursealias}
|
||||
ON $coursealias.theme = '{$themechoice}'
|
||||
AND {$themealias}.plugin = 'theme_{$themechoice}'"));
|
||||
|
||||
$this->add_columns_course();
|
||||
$this->add_filters_course();
|
||||
$this->set_downloadable(true, get_string('themeusagereportcourse', 'report_themeusage', $themename));
|
||||
break;
|
||||
|
||||
case theme_usage::THEME_USAGE_TYPE_COHORT:
|
||||
|
||||
$cohortentity = new cohort();
|
||||
$cohortalias = $cohortentity->get_table_alias('cohort');
|
||||
|
||||
$this->add_entity($cohortentity->add_join(
|
||||
"JOIN {cohort} {$cohortalias}
|
||||
ON $cohortalias.theme = '{$themechoice}'
|
||||
AND {$themealias}.plugin = 'theme_{$themechoice}'"));
|
||||
|
||||
$this->add_columns_cohort();
|
||||
$this->add_filters_cohort();
|
||||
$this->set_downloadable(true, get_string('themeusagereportcohort', 'report_themeusage', $themename));
|
||||
break;
|
||||
|
||||
case theme_usage::THEME_USAGE_TYPE_CATEGORY:
|
||||
|
||||
$categoryentity = new course_category();
|
||||
$categoryalias = $categoryentity->get_table_alias('course_categories');
|
||||
|
||||
$this->add_entity($categoryentity->add_join(
|
||||
"JOIN {course_categories} {$categoryalias}
|
||||
ON $categoryalias.theme = '{$themechoice}'
|
||||
AND {$themealias}.plugin = 'theme_{$themechoice}'"));
|
||||
|
||||
$this->add_columns_category();
|
||||
$this->add_filters_category();
|
||||
$this->set_downloadable(true, get_string('themeusagereportcategory', 'report_themeusage', $themename));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates access to view this report.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function can_view(): bool {
|
||||
return has_capability('moodle/site:config', context_system::instance());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the columns we want to display in the report for 'theme'.
|
||||
*/
|
||||
protected function add_columns_theme(): void {
|
||||
$columns = [
|
||||
'theme:usagetype',
|
||||
'theme:forcetheme',
|
||||
];
|
||||
|
||||
$this->add_columns_from_entities($columns);
|
||||
$this->set_initial_sort_column('theme:forcetheme', SORT_ASC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the columns we want to display in the report for 'user'.
|
||||
*/
|
||||
protected function add_columns_user(): void {
|
||||
$columns = [
|
||||
'user:firstname',
|
||||
'user:lastname',
|
||||
'theme:forcetheme',
|
||||
];
|
||||
|
||||
$this->add_columns_from_entities($columns);
|
||||
$this->set_initial_sort_column('user:firstname', SORT_ASC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the filters we want to display in the report for 'user'.
|
||||
*/
|
||||
protected function add_filters_user(): void {
|
||||
$filters = [
|
||||
'user:firstname',
|
||||
'user:lastname',
|
||||
];
|
||||
|
||||
$this->add_filters_from_entities($filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the columns we want to display in the report for 'course'.
|
||||
*/
|
||||
protected function add_columns_course(): void {
|
||||
$columns = [
|
||||
'course:fullname',
|
||||
'course:shortname',
|
||||
'theme:forcetheme',
|
||||
];
|
||||
|
||||
$this->add_columns_from_entities($columns);
|
||||
$this->set_initial_sort_column('course:fullname', SORT_ASC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the filters we want to display in the report for 'course'.
|
||||
*/
|
||||
protected function add_filters_course(): void {
|
||||
$filters = [
|
||||
'course:fullname',
|
||||
'course:shortname',
|
||||
];
|
||||
|
||||
$this->add_filters_from_entities($filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the columns we want to display in the report for 'cohort'.
|
||||
*/
|
||||
protected function add_columns_cohort(): void {
|
||||
$columns = [
|
||||
'cohort:name',
|
||||
'cohort:context',
|
||||
'theme:forcetheme',
|
||||
];
|
||||
|
||||
$this->add_columns_from_entities($columns);
|
||||
$this->set_initial_sort_column('cohort:name', SORT_ASC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the filters we want to display in the report for 'cohort'.
|
||||
*/
|
||||
protected function add_filters_cohort(): void {
|
||||
$filters = [
|
||||
'cohort:name',
|
||||
'cohort:context',
|
||||
];
|
||||
|
||||
$this->add_filters_from_entities($filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the columns we want to display in the report for 'category'.
|
||||
*/
|
||||
protected function add_columns_category(): void {
|
||||
$columns = [
|
||||
'course_category:name',
|
||||
'course_category:coursecount',
|
||||
'theme:forcetheme',
|
||||
];
|
||||
|
||||
$this->add_columns_from_entities($columns);
|
||||
$this->set_initial_sort_column('course_category:name', SORT_ASC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the filters we want to display in the report for 'category'.
|
||||
*/
|
||||
protected function add_filters_category(): void {
|
||||
$filters = [
|
||||
'course_category:name',
|
||||
];
|
||||
|
||||
$this->add_filters_from_entities($filters);
|
||||
}
|
||||
}
|
83
report/themeusage/index.php
Normal file
83
report/themeusage/index.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Display usage information about themes.
|
||||
*
|
||||
* @package report_themeusage
|
||||
* @copyright 2023 David Woloszyn <david.woloszyn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use core_reportbuilder\system_report_factory;
|
||||
use report_themeusage\form\theme_usage_form;
|
||||
use report_themeusage\reportbuilder\local\systemreports\theme_usage_report;
|
||||
|
||||
require(__DIR__.'/../../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
|
||||
require_login();
|
||||
admin_externalpage_setup('reportthemeusage');
|
||||
|
||||
// Get URL parameters.
|
||||
$themechoice = optional_param('themechoice', '', PARAM_TEXT);
|
||||
|
||||
// Check the requested theme is a valid one.
|
||||
if (!theme_usage_form::validate_theme_choice_param($themechoice)) {
|
||||
throw new \moodle_exception(get_string('invalidparametertheme', 'report_themeusage'));
|
||||
}
|
||||
|
||||
// Set up the page.
|
||||
$pageurl = new moodle_url($CFG->wwwroot . '/report/themeusage/index.php');
|
||||
$PAGE->set_url($pageurl);
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_pagelayout('report');
|
||||
$PAGE->set_primary_active_tab('siteadminnode');
|
||||
echo $OUTPUT->header();
|
||||
|
||||
// Show heading.
|
||||
$heading = get_string('themeusage', 'report_themeusage');
|
||||
echo $OUTPUT->heading($heading);
|
||||
|
||||
// Build form with prepared data.
|
||||
$cutomdata['themechoice'] = $themechoice;
|
||||
$form = new theme_usage_form($pageurl, $cutomdata);
|
||||
$form->display();
|
||||
|
||||
if ($data = $form->get_data()) {
|
||||
// Build report using submitted form data.
|
||||
$themechoice = $data->themechoice;
|
||||
$typechoice = $data->typechoice;
|
||||
|
||||
} else if (!empty($themechoice)) {
|
||||
// Build report with incoming theme choice and set the type to 'all'.
|
||||
$typechoice = 'all';
|
||||
}
|
||||
|
||||
if (!empty($themechoice) && !empty($typechoice)) {
|
||||
// Show a heading that explains what the report is showing.
|
||||
$themename = get_string('pluginname', 'theme_' . $themechoice);
|
||||
$reportheading = get_string('themeusagereport' . $typechoice, 'report_themeusage', $themename);
|
||||
echo $OUTPUT->heading($reportheading, 3, 'mt-4');
|
||||
|
||||
// Build the report.
|
||||
$reportparams = ['themechoice' => $themechoice, 'typechoice' => $typechoice];
|
||||
$report = system_report_factory::create(theme_usage_report::class, context_system::instance(), '', '', 0, $reportparams);
|
||||
echo $report->output();
|
||||
}
|
||||
|
||||
// Show footer.
|
||||
echo $OUTPUT->footer();
|
37
report/themeusage/lang/en/report_themeusage.php
Normal file
37
report/themeusage/lang/en/report_themeusage.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Lang strings for theme usage report.
|
||||
*
|
||||
* @package report_themeusage
|
||||
* @copyright 2023 David Woloszyn <david.woloszyn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['getreport'] = 'Get report';
|
||||
$string['invalidparametertheme'] = 'Invalid paramater set for theme';
|
||||
$string['pluginname'] = 'Theme usage';
|
||||
$string['privacy:metadata'] = 'The theme report plugin does not store any personal data.';
|
||||
$string['themename'] = 'Theme name';
|
||||
$string['themeusage'] = 'Theme usage';
|
||||
$string['themeusagereport'] = 'Theme usage report';
|
||||
$string['themeusagereportall'] = 'All uses of {$a}';
|
||||
$string['themeusagereportcategory'] = 'Categories using {$a}';
|
||||
$string['themeusagereportcohort'] = 'Cohorts using {$a}';
|
||||
$string['themeusagereportcourse'] = 'Courses using {$a}';
|
||||
$string['themeusagereportuser'] = 'Users using {$a}';
|
||||
$string['usagetype'] = 'Usage type';
|
37
report/themeusage/settings.php
Normal file
37
report/themeusage/settings.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Settings and links.
|
||||
*
|
||||
* @package report_themeusage
|
||||
* @copyright 2023 David Woloszyn <david.woloszyn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
$ADMIN->add('reports',
|
||||
new admin_externalpage(
|
||||
'reportthemeusage',
|
||||
get_string('pluginname', 'report_themeusage'),
|
||||
"$CFG->wwwroot/report/themeusage/index.php",
|
||||
'moodle/site:config',
|
||||
),
|
||||
);
|
||||
|
||||
// No report settings.
|
||||
$settings = null;
|
92
report/themeusage/tests/behat/theme_usage.feature
Normal file
92
report/themeusage/tests/behat/theme_usage.feature
Normal file
@ -0,0 +1,92 @@
|
||||
@report @report_themeusage
|
||||
Feature: Navigate to a theme usage report
|
||||
In order to see a theme usage report
|
||||
As an admin
|
||||
I need to set a theme for user/course/category/cohort and view the report
|
||||
|
||||
Background:
|
||||
Given the following config values are set as admin:
|
||||
| allowuserthemes | 1 |
|
||||
| allowcoursethemes | 1 |
|
||||
| allowcategorythemes | 1 |
|
||||
| allowcohortthemes | 1 |
|
||||
And I log in as "admin"
|
||||
|
||||
Scenario: I am able to see theme usage report for all contexts overriding the default theme
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | theme |
|
||||
| Course 1 | course1 | boost |
|
||||
| Course 2 | course2 | boost |
|
||||
And the following "user" exists:
|
||||
| username | student1 |
|
||||
| firstname | Student |
|
||||
| lastname | One |
|
||||
| theme | boost |
|
||||
And I navigate to "Reports > Theme usage" in site administration
|
||||
And I set the field "Theme name" to "boost"
|
||||
And I set the field "Usage type" to "all"
|
||||
When I press "Get report"
|
||||
Then the following should exist in the "reportbuilder-table" table:
|
||||
| Usage type | Force theme |
|
||||
| Course (2) | Boost |
|
||||
| User (1) | Boost |
|
||||
|
||||
Scenario: I am able to see theme usage report for courses overriding the default theme
|
||||
Given the following "course" exists:
|
||||
| fullname | Course 1 |
|
||||
| shortname | course1 |
|
||||
| theme | boost |
|
||||
And I navigate to "Reports > Theme usage" in site administration
|
||||
And I set the field "Theme name" to "boost"
|
||||
And I set the field "Usage type" to "course"
|
||||
When I press "Get report"
|
||||
Then the following should exist in the "reportbuilder-table" table:
|
||||
| Course full name | Course short name | Force theme |
|
||||
| Course 1 | course1 | Boost |
|
||||
|
||||
Scenario: I am able to see theme usage report for users overriding the default theme
|
||||
Given the following "user" exists:
|
||||
| username | student1 |
|
||||
| firstname | Student |
|
||||
| lastname | One |
|
||||
| theme | boost |
|
||||
And I navigate to "Reports > Theme usage" in site administration
|
||||
And I set the field "Theme name" to "boost"
|
||||
And I set the field "Usage type" to "user"
|
||||
When I press "Get report"
|
||||
Then the following should exist in the "reportbuilder-table" table:
|
||||
| First name | Last name | Force theme |
|
||||
| Student | One | Boost |
|
||||
|
||||
Scenario: I am able to see theme usage report for cohorts overriding the default theme
|
||||
Given the following "cohort" exists:
|
||||
| name | Cohort 1 |
|
||||
| idnumber | cohort1 |
|
||||
| context | system |
|
||||
And I navigate to "Users > Accounts > Cohorts" in site administration
|
||||
And I press "Edit" action in the "cohort1" report row
|
||||
And I set the field "theme" to "boost"
|
||||
And I press "Save changes"
|
||||
And I navigate to "Reports > Theme usage" in site administration
|
||||
And I set the field "Theme name" to "boost"
|
||||
And I set the field "Usage type" to "cohort"
|
||||
When I press "Get report"
|
||||
Then the following should exist in the "reportbuilder-table" table:
|
||||
| Name | Category | Force theme |
|
||||
| Cohort 1 | System | Boost |
|
||||
|
||||
Scenario: I am able to see theme usage report for categories overriding the default theme
|
||||
Given the following "categories" exist:
|
||||
| name | category | idnumber |
|
||||
| Category 1 | 0 | category1 |
|
||||
And I navigate to "Courses > Manage courses and categories" in site administration
|
||||
And I click on "edit" action for "Category 1" in management category listing
|
||||
And I set the field "theme" to "boost"
|
||||
And I press "Save changes"
|
||||
And I navigate to "Reports > Theme usage" in site administration
|
||||
And I set the field "Theme name" to "boost"
|
||||
And I set the field "Usage type" to "category"
|
||||
When I press "Get report"
|
||||
Then the following should exist in the "reportbuilder-table" table:
|
||||
| Category name | Course count | Force theme |
|
||||
| Category 1 | 0 | Boost |
|
101
report/themeusage/tests/theme_usage_test.php
Normal file
101
report/themeusage/tests/theme_usage_test.php
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace report_themeusage;
|
||||
|
||||
use testing_data_generator;
|
||||
use core\output\theme_usage;
|
||||
|
||||
/**
|
||||
* Unit tests for theme usage.
|
||||
*
|
||||
* @package report_themeusage
|
||||
* @copyright 2023 David Woloszyn <david.woloszyn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class theme_usage_test extends \advanced_testcase {
|
||||
|
||||
/** @var testing_data_generator Data generator. */
|
||||
private testing_data_generator $generator;
|
||||
|
||||
/**
|
||||
* Set up function for tests.
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->generator = $this->getDataGenerator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test is_theme_used_in_any_context method.
|
||||
*
|
||||
* @covers ::is_theme_used_in_any_context
|
||||
* @covers ::theme_purge_used_in_context_caches
|
||||
*/
|
||||
public function test_is_theme_used_in_any_context(): void {
|
||||
// Enable theme overrides.
|
||||
set_config('allowuserthemes', 1);
|
||||
set_config('allowcoursethemes', 1);
|
||||
set_config('allowcohortthemes', 1);
|
||||
set_config('allowcategorythemes', 1);
|
||||
|
||||
$theme = 'boost';
|
||||
|
||||
// Check there are no contexts using 'boost' as their preferred theme yet.
|
||||
$usedinanycontext = theme_usage::is_theme_used_in_any_context($theme);
|
||||
$this->assertEquals(theme_usage::THEME_IS_NOT_USED, $usedinanycontext);
|
||||
|
||||
// Create a user and set its theme preference to 'boost'.
|
||||
// The outcome of this test should be the same if we use a cohort/course/category.
|
||||
$this->generator->create_user(['theme' => $theme]);
|
||||
|
||||
// Because we have already checked and cached a response, purge this cache.
|
||||
theme_purge_used_in_context_caches();
|
||||
|
||||
$usedinanycontext = theme_usage::is_theme_used_in_any_context($theme);
|
||||
$this->assertEquals(theme_usage::THEME_IS_USED, $usedinanycontext);
|
||||
|
||||
// Double-check the the cache is set for the theme.
|
||||
$cache = \cache::make('core', 'theme_usedincontext')->get($theme);
|
||||
$this->assertEquals(theme_usage::THEME_IS_USED, $cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the deleting of cache using theme_delete_used_in_context_cache.
|
||||
*
|
||||
* @covers ::theme_delete_used_in_context_cache
|
||||
*/
|
||||
public function test_theme_delete_used_in_context_cache(): void {
|
||||
// Enable theme override.
|
||||
set_config('allowuserthemes', 1);
|
||||
|
||||
// Create a user and set its theme preference to 'boost'.
|
||||
$theme = 'boost';
|
||||
$user = $this->generator->create_user(['theme' => $theme]);
|
||||
|
||||
// Check for theme usage. This will create a cached result.
|
||||
theme_usage::is_theme_used_in_any_context($theme);
|
||||
$cache = \cache::make('core', 'theme_usedincontext')->get($theme);
|
||||
$this->assertEquals(theme_usage::THEME_IS_USED, $cache);
|
||||
|
||||
// Delete the cache by switching themes.
|
||||
theme_delete_used_in_context_cache('classic', $user->theme);
|
||||
$cache = \cache::make('core', 'theme_usedincontext')->get($theme);
|
||||
$this->assertFalse($cache);
|
||||
}
|
||||
}
|
29
report/themeusage/version.php
Normal file
29
report/themeusage/version.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Version info.
|
||||
*
|
||||
* @package report_themeusage
|
||||
* @copyright 2023 David Woloszyn <david.woloszyn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
$plugin->version = 2023110900; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2023100900; // Requires this Moodle version.
|
||||
$plugin->component = 'report_themeusage'; // Full name of the plugin (used for diagnostics).
|
@ -241,6 +241,14 @@ class user_editadvanced_form extends moodleform {
|
||||
}
|
||||
}
|
||||
|
||||
// User changing their preferred theme will delete the cache for this theme.
|
||||
if ($mform->elementExists('theme') && $mform->isSubmitted()) {
|
||||
$theme = $mform->getSubmitValue('theme');
|
||||
if (!empty($user) && ($theme != $user->theme)) {
|
||||
theme_delete_used_in_context_cache($theme, $user->theme);
|
||||
}
|
||||
}
|
||||
|
||||
// Next the customisable profile fields.
|
||||
profile_definition_after_data($mform, $userid);
|
||||
}
|
||||
|
@ -209,6 +209,15 @@ function user_update_user($user, $updatepassword = true, $triggerevent = true) {
|
||||
unset($user->calendartype);
|
||||
}
|
||||
|
||||
// Delete theme usage cache if the theme has been changed.
|
||||
if (isset($user->theme)) {
|
||||
if ($user->theme != $currentrecord->theme) {
|
||||
theme_delete_used_in_context_cache($user->theme, $currentrecord->theme);
|
||||
}
|
||||
}
|
||||
|
||||
$user->timemodified = time();
|
||||
|
||||
// Validate user data object.
|
||||
$uservalidation = core_user::validate($user);
|
||||
if ($uservalidation !== true) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user