From 0f268f5db9055fdff1b13cc001f98d40e6b70741 Mon Sep 17 00:00:00 2001 From: Ryan Wyllie Date: Mon, 19 Jun 2017 05:22:58 +0000 Subject: [PATCH] MDL-59150 admin: build site theme after CLI install or upgrade --- admin/cli/install.php | 6 +++ admin/cli/install_database.php | 7 +++ admin/cli/upgrade.php | 6 +++ .../task/build_installed_themes_task.php | 54 +++++++++++++++++++ lib/classes/task/manager.php | 20 +++++++ lib/tests/adhoc_task_test.php | 40 ++++++++++++++ lib/tests/fixtures/task_fixtures.php | 5 ++ lib/upgradelib.php | 25 +++++++++ 8 files changed, 163 insertions(+) create mode 100644 lib/classes/task/build_installed_themes_task.php diff --git a/admin/cli/install.php b/admin/cli/install.php index 0b6c5cac392..f8876ca0b78 100644 --- a/admin/cli/install.php +++ b/admin/cli/install.php @@ -808,6 +808,12 @@ if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) { if (!$options['skip-database']) { install_cli_database($options, $interactive); + // This needs to happen at the end to ensure it occurs after all caches + // have been purged for the last time. + // This will build a cached version of the current theme for the user + // to immediately start browsing the site. + require_once($CFG->libdir.'/upgradelib.php'); + upgrade_themes(); } else { echo get_string('cliskipdatabase', 'install')."\n"; } diff --git a/admin/cli/install_database.php b/admin/cli/install_database.php index f41263ed9e5..af05fc2a4ac 100644 --- a/admin/cli/install_database.php +++ b/admin/cli/install_database.php @@ -183,5 +183,12 @@ if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) { install_cli_database($options, true); +// This needs to happen at the end to ensure it occurs after all caches +// have been purged for the last time. +// This will build a cached version of the current theme for the user +// to immediately start browsing the site. +require_once($CFG->libdir.'/upgradelib.php'); +upgrade_themes(); + echo get_string('cliinstallfinished', 'install')."\n"; exit(0); // 0 means success diff --git a/admin/cli/upgrade.php b/admin/cli/upgrade.php index 6de2e13ca98..6c10b9a7442 100644 --- a/admin/cli/upgrade.php +++ b/admin/cli/upgrade.php @@ -187,5 +187,11 @@ upgrade_noncore(true); admin_apply_default_settings(NULL, false); admin_apply_default_settings(NULL, false); +// This needs to happen at the end to ensure it occurs after all caches +// have been purged for the last time. +// This will build a cached version of the current theme for the user +// to immediately start browsing the site. +upgrade_themes(); + echo get_string('cliupgradefinished', 'admin')."\n"; exit(0); // 0 means success diff --git a/lib/classes/task/build_installed_themes_task.php b/lib/classes/task/build_installed_themes_task.php new file mode 100644 index 00000000000..a6195f5a590 --- /dev/null +++ b/lib/classes/task/build_installed_themes_task.php @@ -0,0 +1,54 @@ +. + +/** + * Adhoc task that builds and caches all of the site's installed themes. + * + * @package core + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core\task; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Class that builds and caches all of the site's installed themes. + * + * @package core + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class build_installed_themes_task extends adhoc_task { + + /** + * Run the task. + */ + public function execute() { + global $CFG; + require_once("{$CFG->libdir}/outputlib.php"); + + $themenames = array_keys(\core_component::get_plugin_list('theme')); + // Load the theme configs. + $themeconfigs = array_map(function($themename) { + return \theme_config::load($themename); + }, $themenames); + + // Build the list of themes and cache them in local cache. + theme_build_css_for_themes($themeconfigs); + } +} diff --git a/lib/classes/task/manager.php b/lib/classes/task/manager.php index 60a5240baac..106878b8bcf 100644 --- a/lib/classes/task/manager.php +++ b/lib/classes/task/manager.php @@ -353,6 +353,26 @@ class manager { return self::scheduled_task_from_record($record); } + /** + * This function load the adhoc tasks for a given classname. + * + * @param string $classname + * @return \core\task\adhoc_task[] + */ + public static function get_adhoc_tasks($classname) { + global $DB; + + if (strpos($classname, '\\') !== 0) { + $classname = '\\' . $classname; + } + // We are just reading - so no locks required. + $records = $DB->get_records('task_adhoc', array('classname' => $classname)); + + return array_map(function($record) { + return self::adhoc_task_from_record($record); + }, $records); + } + /** * This function load the default scheduled task details for a given classname. * diff --git a/lib/tests/adhoc_task_test.php b/lib/tests/adhoc_task_test.php index 1c4d70a0628..d1ec1d88390 100644 --- a/lib/tests/adhoc_task_test.php +++ b/lib/tests/adhoc_task_test.php @@ -109,4 +109,44 @@ class core_adhoc_task_testcase extends advanced_testcase { $task->execute(); \core\task\manager::adhoc_task_complete($task); } + + /** + * Test empty set of adhoc tasks + */ + public function test_get_adhoc_tasks_empty_set() { + $this->resetAfterTest(true); + + $this->assertEquals([], \core\task\manager::get_adhoc_tasks('\\core\\task\\adhoc_test_task')); + } + + /** + * Test correct set of adhoc tasks is returned for class. + */ + public function test_get_adhoc_tasks_result_set() { + $this->resetAfterTest(true); + + for ($i = 0; $i < 3; $i++) { + $task = new \core\task\adhoc_test_task(); + \core\task\manager::queue_adhoc_task($task); + } + + for ($i = 0; $i < 3; $i++) { + $task = new \core\task\adhoc_test2_task(); + \core\task\manager::queue_adhoc_task($task); + } + + $adhoctests = \core\task\manager::get_adhoc_tasks('\\core\\task\\adhoc_test_task'); + $adhoctest2s = \core\task\manager::get_adhoc_tasks('\\core\\task\\adhoc_test2_task'); + + $this->assertCount(3, $adhoctests); + $this->assertCount(3, $adhoctest2s); + + foreach ($adhoctests as $task) { + $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); + } + + foreach ($adhoctest2s as $task) { + $this->assertInstanceOf('\\core\\task\\adhoc_test2_task', $task); + } + } } diff --git a/lib/tests/fixtures/task_fixtures.php b/lib/tests/fixtures/task_fixtures.php index 6ec619ff0e9..ead50031c3a 100644 --- a/lib/tests/fixtures/task_fixtures.php +++ b/lib/tests/fixtures/task_fixtures.php @@ -31,6 +31,11 @@ class adhoc_test_task extends \core\task\adhoc_task { } } +class adhoc_test2_task extends \core\task\adhoc_task { + public function execute() { + } +} + class scheduled_test_task extends \core\task\scheduled_task { public function get_name() { return "Test task"; diff --git a/lib/upgradelib.php b/lib/upgradelib.php index 0edd3323c8c..cf298f71b62 100644 --- a/lib/upgradelib.php +++ b/lib/upgradelib.php @@ -1664,6 +1664,31 @@ function upgrade_language_pack($lang = null) { print_upgrade_separator(); } +/** + * Build the current theme so that the user doesn't have to wait for it + * to build on the first page load after the install / upgrade. + */ +function upgrade_themes() { + global $CFG; + + require_once("{$CFG->libdir}/outputlib.php"); + + // Build the current theme so that the user can immediately + // browse the site without having to wait for the theme to build. + $themeconfig = theme_config::load($CFG->theme); + $direction = right_to_left() ? 'rtl' : 'ltr'; + theme_build_css_for_themes([$themeconfig], [$direction]); + + // Only queue the task if there isn't already one queued. + if (empty(\core\task\manager::get_adhoc_tasks('\\core\\task\\build_installed_themes_task'))) { + // Queue a task to build all of the site themes at some point + // later. These can happen offline because it doesn't block the + // user unless they quickly change theme. + $adhoctask = new \core\task\build_installed_themes_task(); + \core\task\manager::queue_adhoc_task($adhoctask); + } +} + /** * Install core moodle tables and initialize * @param float $version target version