diff --git a/.upgradenotes/MDL-82212-2024080916163806.yml b/.upgradenotes/MDL-82212-2024080916163806.yml new file mode 100644 index 00000000000..57d4007f167 --- /dev/null +++ b/.upgradenotes/MDL-82212-2024080916163806.yml @@ -0,0 +1,11 @@ +issueNumber: MDL-82212 +notes: + core: + - message: >- + A new method, get_deprecated_icons(), has been added to the icon_system + class. All deprecated icons should be registered through this method. + Plugins can implement a callback to pluginname_get_deprecated_icons() to + register their deprecated icons too. + When $CFG->debugpageinfo is enabled, a console message will display a + list of the deprecated icons. + type: improved diff --git a/.upgradenotes/MDL-82212-2024081207484596.yml b/.upgradenotes/MDL-82212-2024081207484596.yml new file mode 100644 index 00000000000..838096c78f1 --- /dev/null +++ b/.upgradenotes/MDL-82212-2024081207484596.yml @@ -0,0 +1,7 @@ +issueNumber: MDL-82212 +notes: + tool_behat: + - message: >- + Behat tests are now checking for deprecated icons. This check can be + disabled by using the --no-icon-deprecations option in the behat CLI. + type: improved diff --git a/admin/tool/behat/cli/init.php b/admin/tool/behat/cli/init.php index 87f77742605..26f58a5c270 100644 --- a/admin/tool/behat/cli/init.php +++ b/admin/tool/behat/cli/init.php @@ -54,6 +54,7 @@ list($options, $unrecognized) = cli_get_params( 'composer-upgrade' => true, 'composer-self-update' => true, 'scss-deprecations' => false, + 'no-icon-deprecations' => false, ), array( 'j' => 'parallel', @@ -70,18 +71,20 @@ Behat utilities to initialise behat tests Usage: php init.php [--parallel=value [--maxruns=value] [--fromrun=value --torun=value]] - [--no-axe] [--scss-deprecations] [-o | --optimize-runs] [-a | --add-core-features-to-theme] + [--no-axe] [--scss-deprecations] [--no-icon-deprecations] [-o | --optimize-runs] + [-a | --add-core-features-to-theme] [--no-composer-self-update] [--no-composer-upgrade] [--disable-composer] [--help] Options: --j, --parallel Number of parallel behat run to initialise --m, --maxruns Max parallel processes to be executed at one time ---fromrun Execute run starting from (Used for parallel runs on different vms) ---torun Execute run till (Used for parallel runs on different vms) ---no-axe Disable axe accessibility tests. ---scss-deprecations Enable SCSS deprecation checks. +-j, --parallel Number of parallel behat run to initialise +-m, --maxruns Max parallel processes to be executed at one time +--fromrun Execute run starting from (Used for parallel runs on different vms) +--torun Execute run till (Used for parallel runs on different vms) +--no-axe Disable axe accessibility tests. +--scss-deprecations Enable SCSS deprecation checks. +--no-icon-deprecations Disable icon deprecation checks. -o, --optimize-runs Split features with specified tags in all parallel runs. @@ -134,6 +137,7 @@ if ($options['parallel'] && $options['parallel'] > 1) { 'add-core-features-to-theme', 'axe', 'scss-deprecations', + 'no-icon-deprecations', ]; foreach ($cmdoptionsforsinglerun as $option) { diff --git a/admin/tool/behat/cli/util.php b/admin/tool/behat/cli/util.php index 7d36ffa611c..0a65b4e0a2b 100644 --- a/admin/tool/behat/cli/util.php +++ b/admin/tool/behat/cli/util.php @@ -59,6 +59,7 @@ list($options, $unrecognized) = cli_get_params( 'add-core-features-to-theme' => false, 'axe' => true, 'scss-deprecations' => false, + 'no-icon-deprecations' => false, ), array( 'h' => 'help', @@ -74,18 +75,20 @@ $help = " Behat utilities to manage the test environment Usage: - php util.php [--install|--drop|--enable|--disable|--diag|--updatesteps|--no-axe|--scss-deprecations|--help] + php util.php [--install|--drop|--enable|--disable|--diag|--updatesteps] + [--no-axe|--scss-deprecations|--no-icon-deprecations|--help] [--parallel=value [--maxruns=value]] Options: ---install Installs the test environment for acceptance tests ---drop Drops the database tables and the dataroot contents ---enable Enables test environment and updates tests list ---disable Disables test environment ---diag Get behat test environment status code ---updatesteps Update feature step file. ---no-axe Disable axe accessibility tests. ---scss-deprecations Enable SCSS deprecation checks. +--install Installs the test environment for acceptance tests +--drop Drops the database tables and the dataroot contents +--enable Enables test environment and updates tests list +--disable Disables test environment +--diag Get behat test environment status code +--updatesteps Update feature step file. +--no-axe Disable axe accessibility tests. +--scss-deprecations Enable SCSS deprecation checks. +--no-icon-deprecations Disable icon deprecation checks. -j, --parallel Number of parallel behat run operation -m, --maxruns Max parallel processes to be executed at one time. diff --git a/admin/tool/behat/cli/util_single_run.php b/admin/tool/behat/cli/util_single_run.php index 942a6f834f5..20ef49f1322 100644 --- a/admin/tool/behat/cli/util_single_run.php +++ b/admin/tool/behat/cli/util_single_run.php @@ -54,6 +54,7 @@ list($options, $unrecognized) = cli_get_params( 'add-core-features-to-theme' => false, 'axe' => true, 'scss-deprecations' => false, + 'no-icon-deprecations' => false, ), array( 'h' => 'help', @@ -74,14 +75,15 @@ Usage: php util_single_run.php [--install|--drop|--enable|--disable|--diag|--updatesteps|--help] Options: ---install Installs the test environment for acceptance tests ---drop Drops the database tables and the dataroot contents ---enable Enables test environment and updates tests list ---disable Disables test environment ---diag Get behat test environment status code ---updatesteps Update feature step file. ---no-axe Disable axe accessibility tests. ---scss-deprecations Enable SCSS deprecation checks. +--install Installs the test environment for acceptance tests +--drop Drops the database tables and the dataroot contents +--enable Enables test environment and updates tests list +--disable Disables test environment +--diag Get behat test environment status code +--updatesteps Update feature step file. +--no-axe Disable axe accessibility tests. +--scss-deprecations Enable SCSS deprecation checks. +--no-icon-deprecations Disable icon deprecation checks. -o, --optimize-runs Split features with specified tags in all parallel runs. -a, --add-core-features-to-theme Add all core features to specified theme's @@ -194,6 +196,9 @@ if ($options['install']) { // Define whether to run Behat with SCSS deprecation checks. behat_config_manager::set_behat_run_config_value('scss-deprecations', $options['scss-deprecations']); + // Define whether to run Behat with icon deprecation checks. + behat_config_manager::set_behat_run_config_value('no-icon-deprecations', $options['no-icon-deprecations']); + // Enable test mode. $timestart = microtime(true); mtrace('Creating Behat configuration ...', ''); diff --git a/lib/behat/classes/behat_session_trait.php b/lib/behat/classes/behat_session_trait.php index 6d324ecfb3f..7ec03499b40 100644 --- a/lib/behat/classes/behat_session_trait.php +++ b/lib/behat/classes/behat_session_trait.php @@ -1049,6 +1049,39 @@ EOF; } } + + /** + * Internal step definition to find deprecated icons. + * + * Part of behat_hooks class as is part of the testing framework, is auto-executed + * after each step so no features will splicitly use it. + * + * @throws Exception Unknown type, depending on what we caught in the hook or basic \Exception. + * @see Moodle\BehatExtension\Tester\MoodleStepTester + */ + public function look_for_deprecated_icons() { + if (behat_config_manager::get_behat_run_config_value('no-icon-deprecations')) { + return; + } + + if (!$this->running_javascript()) { + return; + } + + // Look for any DOM element with deprecated icon. + $js = <<<EOF + [...document.querySelectorAll('.icon.deprecated')].some( + deprecatedicon => true + ); + EOF; + if ($this->evaluate_script($js)) { + throw new \Exception(html_entity_decode( + "Deprecated icon in use. Enable \$CFG->debugdisplay for detailed debugging information in the console", + ENT_COMPAT, + )); + } + } + /** * Converts HTML tags to line breaks to display the info in CLI * @@ -1090,6 +1123,9 @@ EOF; // Look for deprecated styles. $this->look_for_deprecated_styles(); + + // Look for deprecated icons. + $this->look_for_deprecated_icons(); } /** diff --git a/lib/behat/classes/util.php b/lib/behat/classes/util.php index 25d9bfb7db6..2ea60f255d9 100644 --- a/lib/behat/classes/util.php +++ b/lib/behat/classes/util.php @@ -519,11 +519,13 @@ class behat_util extends testing_util { $accessibility = empty(behat_config_manager::get_behat_run_config_value('axe')) ? 'No' : 'Yes'; $scssdeprecations = empty(behat_config_manager::get_behat_run_config_value('scss-deprecations')) ? 'No' : 'Yes'; + $icondeprecations = empty(behat_config_manager::get_behat_run_config_value('no-icon-deprecations')) ? 'Yes' : 'No'; $siteinfo .= <<<EOF Run optional tests: - Accessibility: {$accessibility} - SCSS deprecations: {$scssdeprecations} +- Icon deprecations: {$icondeprecations} EOF; diff --git a/lib/classes/output/icon_system.php b/lib/classes/output/icon_system.php index c9f6b5a1488..087e6bbd7c6 100644 --- a/lib/classes/output/icon_system.php +++ b/lib/classes/output/icon_system.php @@ -147,4 +147,26 @@ abstract class icon_system { public static function reset_caches() { self::$instance = null; } + + /** + * Overridable function to get the list of deprecated icons. + * + * @return array with the deprecated key icons (for instance, core:a/download_all). + */ + public function get_deprecated_icons(): array { + $deprecated = []; + // Include deprecated icons in plugins too. + $callback = 'get_deprecated_icons'; + + if ($pluginsfunction = get_plugins_with_function($callback)) { + foreach ($pluginsfunction as $plugintype => $plugins) { + foreach ($plugins as $pluginfunction) { + $plugindeprecated = $pluginfunction(); + $deprecated += $plugindeprecated; + } + } + } + + return $deprecated; + } } diff --git a/lib/classes/output/icon_system_fontawesome.php b/lib/classes/output/icon_system_fontawesome.php index 400102b5929..c59787e04c2 100644 --- a/lib/classes/output/icon_system_fontawesome.php +++ b/lib/classes/output/icon_system_fontawesome.php @@ -488,9 +488,14 @@ class icon_system_fontawesome extends icon_system_font { } } - // Add the solid class by default to all icons that have not specific family. + $deprecated = $this->get_deprecated_icons(); foreach ($this->map as $from => $to) { + // Add the solid class by default to all icons that have not specific family. $this->map[$from] = $this->add_family($to); + // Add the deprecated class to all deprecated icons. + if (in_array($from, $deprecated)) { + $this->map[$from] .= ' deprecated deprecated-'.$from; + } } $cache->set($mapkey, $this->map); @@ -528,6 +533,15 @@ class icon_system_fontawesome extends icon_system_font { if (!$subpix->is_mapped()) { $data['unmappedIcon'] = $icon->export_for_template($output); + // If the icon is not mapped, we need to check if it is deprecated. + $component = $icon->component; + if (empty($component) || $component === 'moodle' || $component === 'core') { + $component = 'core'; + } + $iconname = $component . ':' . $icon->pix; + if (in_array($iconname, $this->get_deprecated_icons())) { + $data['unmappedIcon']['extraclasses'] .= ' deprecated deprecated-'.$iconname; + } } if (isset($icon->attributes['aria-hidden'])) { $data['aria-hidden'] = $icon->attributes['aria-hidden']; diff --git a/lib/pagelib.php b/lib/pagelib.php index 15f81510a16..5b32c4d13e7 100644 --- a/lib/pagelib.php +++ b/lib/pagelib.php @@ -1097,6 +1097,18 @@ class moodle_page { if ($this->subpage) { $summary .= 'Sub-page ' . $this->subpage . '. '; } + + // Display deprecated icons in the console (if any). + $summary .= <<< EOF + <script type="text/javascript"> + //<![CDATA[ + document.querySelectorAll('.icon.deprecated').forEach((icon) => { + window.console.warn("Deprecated icon found: " + icon.className); + }); + //]]> + </script> + EOF; + return $summary; }