diff --git a/CHANGES.md b/CHANGES.md index 181101e6e32..eea99275a5d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,7 @@ Changes ### Unreleased +* 2023-12-23 - Feature: Add admin option to mark broken links and mailto links, solves #163 #164. * 2023-12-21 - Feature: Add setting to upload touch-images for iOS devices, solves #151. * 2023-12-18 - Improvement: Shrink description_format column size in theme_boost_union_flavours table, solves #321. * 2023-12-11 - Improvement: Configurable sort order in menu items of smart menu, solves #403. diff --git a/README.md b/README.md index d7c703220a8..103114b763c 100644 --- a/README.md +++ b/README.md @@ -385,6 +385,14 @@ In this tab there are the following settings: Adds an "external link" icon after external links (which lead the user to a target outside Moodle). +###### Mark mailto links + +Adds an "envelope" icon in front of mailto links. + +###### Mark broken links + +Adds a "broken chain" icon in front of broken links (which lead to uploaded draft files which have not been properly processed) and marks the link in the bootstrap color for "danger". + #### Tab "Miscellaneous" In this tab there are the following settings: diff --git a/lang/en/theme_boost_union.php b/lang/en/theme_boost_union.php index d12ef0aab5d..f781cdfe4c5 100644 --- a/lang/en/theme_boost_union.php +++ b/lang/en/theme_boost_union.php @@ -453,6 +453,12 @@ // ... ... Setting: Mark external links. $string['markexternallinkssetting'] = 'Mark external links'; $string['markexternallinkssetting_desc'] = 'Adds an "external link" icon after external links (which lead the user to a target outside Moodle).'; +// ... ... Setting: Mark mailto links. +$string['markmailtolinkssetting'] = 'Mark mailto links'; +$string['markmailtolinkssetting_desc'] = 'Adds an "envelope" icon in front of mailto links.'; +// ... ... Setting: Mark broken links. +$string['markbrokenlinkssetting'] = 'Mark broken links'; +$string['markbrokenlinkssetting_desc'] = 'Adds a "broken chain" icon in front of broken links (which lead to uploaded draft files which have not been properly processed) and marks the link in the bootstrap color for "danger".'; // Settings: Misc tab. $string['misctab'] = 'Miscellaneous'; diff --git a/lib.php b/lib.php index c88852d9c52..61fbfaecf1d 100644 --- a/lib.php +++ b/lib.php @@ -298,6 +298,12 @@ function theme_boost_union_get_extra_scss($theme) { // Setting: Mark external links. $content .= theme_boost_union_get_scss_to_mark_external_links($theme); + // Setting: Mark mailto links. + $content .= theme_boost_union_get_scss_to_mark_mailto_links($theme); + + // Setting: Mark broken links. + $content .= theme_boost_union_get_scss_to_mark_broken_links($theme); + // Setting: Course overview block. $content .= theme_boost_union_get_scss_courseoverview_block($theme); diff --git a/locallib.php b/locallib.php index b90377e5754..5bf586129ca 100644 --- a/locallib.php +++ b/locallib.php @@ -1395,6 +1395,71 @@ function theme_boost_union_get_scss_to_mark_external_links($theme) { return $scss; } +/** + * Returns the SCSS to add a broken-chain symbol in front of broken links and make the font red to mark them visually. + * + * @param theme_config $theme The theme config object. + * @return string + */ +function theme_boost_union_get_scss_to_mark_broken_links($theme) { + // Initialize SCSS snippet. + $scss = ''; + + // If the corresponding setting is set to 'yes'. + if ($theme->settings->markbrokenlinks == THEME_BOOST_UNION_SETTING_SELECT_YES) { + // Set font color to the 'danger' color. + $scss .= 'a[href*="/brokenfile.php"] { + color: $danger; + }'; + + // SCSS to add broken-chain icon in front of the link and respect LTR and RTL while doing this. + $scss .= 'body.dir-ltr a[href*="/brokenfile.php"]::before { + font-family: "#{$fa-style-family}"; + content: "\f127" !important; + font-weight: 900; + padding-right: 0.25rem; + }'; + $scss .= 'body.dir-rtl a[href*="/brokenfile.php"]::after { + font-family: "#{$fa-style-family}"; + content: "\f127" !important; + font-weight: 900; + padding-left: 0.25rem; + }'; + } + + return $scss; +} + +/** + * Returns the SCSS to add an envelope symbol in front of mailto links to mark them visually. + * + * @param theme_config $theme The theme config object. + * @return string + */ +function theme_boost_union_get_scss_to_mark_mailto_links($theme) { + // Initialize SCSS snippet. + $scss = ''; + + // If the corresponding setting is set to 'yes'. + if ($theme->settings->markmailtolinks == THEME_BOOST_UNION_SETTING_SELECT_YES) { + // SCSS to add envelope icon in front of the link and respect LTR and RTL while doing this. + $scss .= 'body.dir-ltr a[href^="mailto"]::before { + font-family: "#{$fa-style-family}"; + content: "\f003" !important; + font-weight: 400; + padding-right: 0.25rem; + }'; + $scss .= 'body.dir-rtl a[href^="mailto"]::after { + font-family: "#{$fa-style-family}"; + content: "\f003" !important; + font-weight: 400; + padding-left: 0.25rem; + }'; + } + + return $scss; +} + /** * Returns the SCSS code to hide the course image and/or the course progress in the course overview block, depending * on the theme settings courseoverviewshowcourseimages and courseoverviewshowcourseprogress respectively. diff --git a/settings.php b/settings.php index d2d7cced9a6..bccb0593908 100644 --- a/settings.php +++ b/settings.php @@ -1443,6 +1443,20 @@ $setting->set_updatedcallback('theme_reset_all_caches'); $tab->add($setting); + // Setting: Mark mailto links. + $name = 'theme_boost_union/markmailtolinks'; + $title = get_string('markmailtolinkssetting', 'theme_boost_union', null, true); + $description = get_string('markmailtolinkssetting_desc', 'theme_boost_union', null, true); + $setting = new admin_setting_configselect($name, $title, $description, THEME_BOOST_UNION_SETTING_SELECT_NO, $yesnooption); + $tab->add($setting); + + // Setting: Mark broken links. + $name = 'theme_boost_union/markbrokenlinks'; + $title = get_string('markbrokenlinkssetting', 'theme_boost_union', null, true); + $description = get_string('markbrokenlinkssetting_desc', 'theme_boost_union', null, true); + $setting = new admin_setting_configselect($name, $title, $description, THEME_BOOST_UNION_SETTING_SELECT_NO, $yesnooption); + $tab->add($setting); + // Add tab to settings page. $page->add($tab); diff --git a/tests/behat/behat_theme_boost_union_base_content.php b/tests/behat/behat_theme_boost_union_base_content.php old mode 100644 new mode 100755 diff --git a/tests/behat/behat_theme_boost_union_base_general.php b/tests/behat/behat_theme_boost_union_base_general.php index 4cbf23cf80d..3704f8bc670 100644 --- a/tests/behat/behat_theme_boost_union_base_general.php +++ b/tests/behat/behat_theme_boost_union_base_general.php @@ -25,6 +25,7 @@ require_once(__DIR__.'/../../../../lib/behat/behat_base.php'); use Behat\Mink\Exception\ExpectationException; +use Behat\Mink\Exception\DriverException; /** * Class behat_theme_boost_union_base_general @@ -192,4 +193,58 @@ public function dom_element_is_at_top_of_viewport($selector) { throw new ExpectationException('The DOM element \''.$selector.'\' is not a the top of the page', $this->getSession()); } } + + /** + * Checks if a property of a pseudo-class of an element contains a certain value. + * + * @Then /^element "(?P.*?)" pseudo-class "(?P.*?)" should contain "(?P.*?)": "(?P.*?)"$/ + * @param string $s selector + * @param string $ps pseudo + * @param string $pr property + * @param string $v value + * @throws ExpectationException + * @throws DriverException + */ + public function i_check_for_pseudoclass_content($s, $ps, $pr, $v) { + if (!$this->running_javascript()) { + throw new DriverException("Pseudo-classes can only be evaluated with Javascript enabled."); + } + + $getvalueofpseudoelementjs = "return ( + window.getComputedStyle(document.querySelector(\"". $s ."\"), ':".$ps."').getPropertyValue(\"".$pr."\") + )"; + + $result = Normalizer::normalize($this->evaluate_script($getvalueofpseudoelementjs), Normalizer::FORM_C); + $eq = Normalizer::normalize('"'.$v.'"', Normalizer::FORM_C); + + if (!($result == $eq)) { + throw new ExpectationException("Didn't find ".$v." in ".$s.":".$ps.".", $this->getSession()); + } + } + + /** + * Checks if a property of a pseudo-class of an element contains 'none'. + * + * @Then /^element "(?P(?:[^"]|\\")*)" pseudo-class "(?P(?:[^"]|\\")*)" should contain "(?P(?:[^"]|\\")*)": none$/ + * @param string $s selector + * @param string $ps pseudo + * @param string $pr property + * @throws ExpectationException + * @throws DriverException + */ + public function pseudoclass_should_not_exist($s, $ps, $pr) { + if (!$this->running_javascript()) { + throw new DriverException("Pseudo-classes can only be evaluated with Javascript enabled."); + } + + $pseudoelementcontent = "return ( + window.getComputedStyle(document.querySelector(\"". $s ."\"), ':".$ps."').getPropertyValue(\"".$pr."\") + )"; + + $result = $this->evaluate_script($pseudoelementcontent); + + if ($result != "none") { + throw new ExpectationException($s.":".$ps.".content contains: ".$result, $this->getSession()); + } + } } diff --git a/tests/behat/theme_boost_union_feelsettings_links.feature b/tests/behat/theme_boost_union_feelsettings_links.feature index af3df2e0ee0..dd37a6d400b 100644 --- a/tests/behat/theme_boost_union_feelsettings_links.feature +++ b/tests/behat/theme_boost_union_feelsettings_links.feature @@ -5,19 +5,63 @@ Feature: Configuring the theme_boost_union plugin for the "Links" tab on the "Fe I need to be able to configure the theme Boost Union plugin Background: - Given the following "users" exist: - | username | - | student1 | - | teacher1 | - And the following "courses" exist: + Given the following "courses" exist: | fullname | shortname | | Course 1 | C1 | - And the following "course enrolments" exist: - | user | course | role | - | teacher1 | C1 | editingteacher | - | student1 | C1 | student | + And the following "activities" exist: + | activity | name | intro | course | + | label | Label one | Mail-Link | C1 | + | label | Label two | Broken Link | C1 | + | label | Label three | Extrnal Link | C1 | + | label | Label three | Internal Link | C1 | - # Unfortunately, this can't be tested with Behat yet - # And as this feature file for this tab can't be empty, we just add a dummy step. - Scenario: Setting: Mark external links + @javascript + Scenario Outline: Setting: Mark external links + Given the following config values are set as admin: + | config | value | plugin | + | markexternallinks | | theme_boost_union | When I log in as "admin" + And I navigate to "Development > Purge caches" in site administration + And I press "Purge all caches" + And I am on "Course 1" course homepage + Then element "a[href*='https://www.externallink.com']" pseudo-class "after" should contain "content": + And element "a[href='/my/']" pseudo-class "after" should contain "content": none + + Examples: + | value | content | + | yes | "" | + | no | none | + + @javascript + Scenario Outline: Setting: Mark mailto links + Given the following config values are set as admin: + | config | value | plugin | + | markmailtolinks | | theme_boost_union | + When I log in as "admin" + And I navigate to "Development > Purge caches" in site administration + And I press "Purge all caches" + And I am on "Course 1" course homepage + Then element "a[href^='mailto']" pseudo-class "before" should contain "content": + And element "a[href='/my/']" pseudo-class "after" should contain "content": none + + Examples: + | value | content | + | yes | "" | + | no | none | + + @javascript + Scenario Outline: Setting: Mark broken links + Given the following config values are set as admin: + | config | value | plugin | + | markbrokenlinks | | theme_boost_union | + When I log in as "admin" + And I navigate to "Development > Purge caches" in site administration + And I press "Purge all caches" + And I am on "Course 1" course homepage + Then element "a[href*='/brokenfile.php']" pseudo-class "before" should contain "content": + And element "a[href='/my/']" pseudo-class "after" should contain "content": none + + Examples: + | value | content | + | yes | "" | + | no | none | diff --git a/version.php b/version.php index fc408db3b6e..284f5aaad33 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'theme_boost_union'; -$plugin->version = 2023102010; +$plugin->version = 2023102011; $plugin->release = 'v4.3-r3'; $plugin->requires = 2023100900; $plugin->supported = [403, 403];