Skip to content

Commit e5925dc

Browse files
authored
Feature: Add a type for smart menu item to use mailto links, resolves #702 (#1079)
1 parent 04fb9d8 commit e5925dc

File tree

9 files changed

+104
-2
lines changed

9 files changed

+104
-2
lines changed

CHANGES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ moodle-theme_boost_union
44
Changes
55
-------
66

7+
### Unreleased
8+
9+
* 2025-10-23 - Feature: Add a type for smart menu item to use mailto links, resolves #702
10+
711
### v5.0-r11
812

913
* 2025-10-22 - Bugfix: Solve possible performance issues due to hook override cache being invalidated by CLI scripts, resolves #1076

classes/form/smartmenu_item_edit_form.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ public function definition() {
109109
$mform->hideIf('url', 'type', 'neq', smartmenu_item::TYPESTATIC);
110110
$mform->addHelpButton('url', 'smartmenusmenuitemurl', 'theme_boost_union');
111111

112+
// Add menu item email (for the mailto menu item type) as input element.
113+
$mform->addElement('text', 'email', get_string('smartmenusmenuitememail', 'theme_boost_union'));
114+
$mform->setType('email', PARAM_EMAIL);
115+
$mform->hideIf('email', 'type', 'neq', smartmenu_item::TYPEMAILTO);
116+
$mform->addHelpButton('email', 'smartmenusmenuitememail', 'theme_boost_union');
117+
112118
// Add mode as select element.
113119
$modeoptions = smartmenu_item::get_mode_options();
114120
$mform->addElement('select', 'mode', get_string('smartmenusmenuitemmode', 'theme_boost_union'), $modeoptions);
@@ -704,6 +710,13 @@ public function validation($data, $files) {
704710
}
705711
}
706712

713+
if ($data['type'] == smartmenu_item::TYPEMAILTO) {
714+
// Verify that the email field is not empty.
715+
if (empty($data['email'])) {
716+
$errors['email'] = get_string('smartmenusmenuitememail_required', 'theme_boost_union');
717+
}
718+
}
719+
707720
// Return errors.
708721
return $errors;
709722
}

classes/smartmenu_item.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ class smartmenu_item {
7676
*/
7777
const TYPEDIVIDER = 4;
7878

79+
/**
80+
* Represents the type of a mailto element.
81+
* @var int
82+
*/
83+
const TYPEMAILTO = 5;
84+
7985
/**
8086
* Represents the completion status of an item where the status is 'enrolled'.
8187
* @var int
@@ -691,6 +697,24 @@ protected function generate_static_item() {
691697
);
692698
}
693699

700+
/**
701+
* Generate the item as mailto menu item.
702+
*
703+
* @return string
704+
*/
705+
protected function generate_mailto_item() {
706+
707+
$mailto = 'mailto:' . $this->item->email;
708+
709+
return $this->generate_node_data(
710+
$this->item->title, // Title.
711+
$mailto, // Mailto link.
712+
null, // Default key.
713+
$this->item->tooltip,
714+
// Tooltip.
715+
);
716+
}
717+
694718
/**
695719
* Generate the dynamic courses based on the conditions of categories, enrollmentrole,
696720
* daterange (Past, Present, Future), and customfields.
@@ -1220,6 +1244,7 @@ public function build() {
12201244
$types = [
12211245
self::TYPESTATIC => 'static',
12221246
self::TYPEDYNAMIC => 'dynamic',
1247+
self::TYPEMAILTO => 'mailto',
12231248
self::TYPEHEADING => 'heading',
12241249
self::TYPEDOCS => 'docs',
12251250
self::TYPEDIVIDER => 'divider',
@@ -1244,6 +1269,13 @@ public function build() {
12441269
$cacheable = true;
12451270
break;
12461271

1272+
case self::TYPEMAILTO:
1273+
$mailto = $this->generate_mailto_item();
1274+
$result = [$mailto];
1275+
$type = 'mailto';
1276+
$cacheable = true;
1277+
break;
1278+
12471279
case self::TYPEDOCS:
12481280
$docs = $this->generate_docs_item();
12491281

@@ -1553,6 +1585,7 @@ public static function load_custom_field_config(&$mform) {
15531585
public static function get_types(?int $type = null) {
15541586
$types = [
15551587
self::TYPESTATIC => get_string('smartmenusmenuitemtypestatic', 'theme_boost_union'),
1588+
self::TYPEMAILTO => get_string('smartmenusmenuitemtypemailto', 'theme_boost_union'),
15561589
self::TYPEHEADING => get_string('smartmenusmenuitemtypeheading', 'theme_boost_union'),
15571590
self::TYPEDOCS => get_string('smartmenusmenuitemtypedocs', 'theme_boost_union'),
15581591
self::TYPEDYNAMIC => get_string('smartmenusmenuitemtypedynamiccourses', 'theme_boost_union'),

db/install.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
<FIELD NAME="type" TYPE="int" LENGTH="9" NOTNULL="false" DEFAULT="1" SEQUENCE="false"/>
8080
<FIELD NAME="sortorder" TYPE="int" LENGTH="18" NOTNULL="false" SEQUENCE="false"/>
8181
<FIELD NAME="url" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
82+
<FIELD NAME="email" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
8283
<FIELD NAME="category" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
8384
<FIELD NAME="category_subcats" TYPE="int" LENGTH="1" NOTNULL="false" SEQUENCE="false"/>
8485
<FIELD NAME="enrolmentrole" TYPE="text" NOTNULL="false" SEQUENCE="false"/>

db/upgrade.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,22 @@ function xmldb_theme_boost_union_upgrade($oldversion) {
684684
upgrade_plugin_savepoint(true, 2025041419, 'theme', 'boost_union');
685685
}
686686

687+
if ($oldversion < 2025041428) {
688+
// Define table theme_boost_union_menuitems to be altered.
689+
$table = new xmldb_table('theme_boost_union_menuitems');
690+
691+
// Define field to be added to theme_boost_union_menuitems.
692+
$field = new xmldb_field('email', XMLDB_TYPE_TEXT, null, null, null, null, null, 'url');
693+
694+
// Conditionally launch adding field.
695+
if (!$dbman->field_exists($table, $field)) {
696+
$dbman->add_field($table, $field);
697+
}
698+
699+
// Savepoint reached.
700+
upgrade_plugin_savepoint(true, 2025041428, 'theme', 'boost_union');
701+
}
702+
687703
// Load the builtin SCSS snippets into the database.
688704
// This is done with every plugin update, regardless of the plugin version.
689705
snippets::add_builtin_snippets();

lang/en/theme_boost_union.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,9 @@
14891489
$string['smartmenusmenuitemdeleteconfirm'] = 'Are you sure you want to delete this menu item from the smart menu?';
14901490
$string['smartmenusmenuitemdeletesuccess'] = 'Smart menu item deleted successfully';
14911491
$string['smartmenusmenuitemdisplayallcourses'] = 'Show hidden courses';
1492+
$string['smartmenusmenuitememail'] = 'Recipient\'s email address';
1493+
$string['smartmenusmenuitememail_help'] = 'The recipient\'s email address for the menu item. This will be used to build a mailto link that opens when the menu item is clicked.';
1494+
$string['smartmenusmenuitememail_required'] = 'Required – Please enter a valid email address without the \'mailto:\' prefix.';
14921495
$string['smartmenusmenuitemhidehiddencourses'] = 'Hide hidden courses';
14931496
$string['smartmenusmenuitemhiddencoursessorting_help'] = 'Choose how hidden courses should be sorted in the course list of the dynamic courses menu items.';
14941497
$string['smartmenusmenuitemhiddencoursessorting'] = 'Hidden courses sorting';
@@ -1558,11 +1561,12 @@
15581561
$string['smartmenusmenuitemtooltip'] = 'Tooltip';
15591562
$string['smartmenusmenuitemtooltip_help'] = 'The tooltip which will be displayed when the user hovers over the menu item.';
15601563
$string['smartmenusmenuitemtype'] = 'Menu item type';
1561-
$string['smartmenusmenuitemtype_help'] = '<p>Select the type of menu item you want to create, choosing between static, heading, moodle documentation, dynamic courses, and divider.</p><ul><li>Static: A static menu item is simply a link to a fixed URL that does not change.</li><li>Heading: A heading menu item is used to group related menu items together under a common heading. It does not have a link and is not clickable.</li><li>Separator: A dividerenu item displays a horizontal line in the menu to visually separate groups of menu items.</li><li>Moodle documentation: A moodle documenation menu item is used to link to the corresponding MoodleDocs article, similar to the MoodleDocs link which is located in the Moodle footer (questionmark icon).</li><li>Dynamic courses: A dynamic courses menu item is used to display a list of courses based on certain criteria, such as course category, course enrolment role, course completion status or date range. The content displayed in a dynamic courses menu item will update automatically as the criteria changes.</li></ul>';
1564+
$string['smartmenusmenuitemtype_help'] = '<p>Select the type of menu item you want to create, choosing between static, mailto, heading, moodle documentation, dynamic courses, and divider.</p><ul><li>Static: A static menu item is simply a link to a fixed URL that does not change.</li><li>Mailto: A mailto menu item opens the user\'s default email client to compose a message to the specified email address.</li><li>Heading: A heading menu item is used to group related menu items together under a common heading. It does not have a link and is not clickable.</li><li>Separator: A dividerenu item displays a horizontal line in the menu to visually separate groups of menu items.</li><li>Moodle documentation: A moodle documenation menu item is used to link to the corresponding MoodleDocs article, similar to the MoodleDocs link which is located in the Moodle footer (questionmark icon).</li><li>Dynamic courses: A dynamic courses menu item is used to display a list of courses based on certain criteria, such as course category, course enrolment role, course completion status or date range. The content displayed in a dynamic courses menu item will update automatically as the criteria changes.</li></ul>';
15621565
$string['smartmenusmenuitemtypedocs'] = 'Moodle documentation';
15631566
$string['smartmenusmenuitemtypedynamiccourses'] = 'Dynamic courses';
15641567
$string['smartmenusmenuitemtypeheading'] = 'Heading';
15651568
$string['smartmenusmenuitemtypedivider'] = 'Divider';
1569+
$string['smartmenusmenuitemtypemailto'] = 'Mailto';
15661570
$string['smartmenusmenuitemtypestatic'] = 'Static';
15671571
$string['smartmenusmenuitemurl'] = 'Menu item URL';
15681572
$string['smartmenusmenuitemurl_help'] = 'The static URL for the menu item. This is the link that will be followed when the menu item is clicked.';
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
@theme @theme_boost_union @theme_boost_union_smartmenusettings @theme_boost_union_smartmenusettings_menuitems @theme_boost_union_smartmenusettings_menuitems_mailto
2+
Feature: Configuring the theme_boost_union plugin on the "Smart menus" page, using a mailto item
3+
In order to use the features
4+
As admin
5+
I need to be able to configure the theme Boost Union plugin
6+
7+
Background:
8+
Given the following "theme_boost_union > smart menu" exists:
9+
| title | Quick links |
10+
| location | Main navigation, Menu bar, User menu, Bottom bar |
11+
And the following "theme_boost_union > smart menu item" exists:
12+
| menu | Quick links |
13+
| title | Mail |
14+
| itemtype | Mailto |
15+
| email | test@test.com |
16+
17+
@javascript
18+
Scenario: Smartmenus: Menu items: Mailto - Add a smart menu documentation link item in a smart menu
19+
When I log in as "admin"
20+
And I navigate to "Appearance > Boost Union > Smart menus" in site administration
21+
Then I should see smart menu "Quick links" item "Mail" in location "Main, Menu, User, Bottom"
22+
And the "href" attribute of "//div[@class='primary-navigation']//a[contains(normalize-space(.), 'Mail')]" "xpath_element" should contain "mailto:[email protected]"

tests/generator/lib.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,14 @@ public function create_smartmenu_item(array $data): \stdClass {
157157
$url = $data['url'];
158158
}
159159

160+
$email = null;
161+
if ($type === smartmenu_item::TYPEMAILTO) {
162+
if (empty($data['email'])) {
163+
throw new Exception('Email is required when type is mailto.');
164+
}
165+
$email = $data['email'];
166+
}
167+
160168
$category = json_encode($data['category'] ?? []);
161169
$categorysubcats = $data['category_subcats'] ?? false;
162170
$enrolmentrole = json_encode($data['enrolmentrole'] ?? []);
@@ -224,6 +232,7 @@ public function create_smartmenu_item(array $data): \stdClass {
224232
'type' => $type,
225233
'sortorder' => $sortorder,
226234
'url' => $url,
235+
'email' => $email,
227236
'category' => $category,
228237
'category_subcats' => $categorysubcats,
229238
'enrolmentrole' => $enrolmentrole,

version.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
defined('MOODLE_INTERNAL') || die();
2626

2727
$plugin->component = 'theme_boost_union';
28-
$plugin->version = 2025041427;
28+
$plugin->version = 2025041428;
2929
$plugin->release = 'v5.0-r11';
3030
$plugin->requires = 2025041401;
3131
$plugin->supported = [500, 500];

0 commit comments

Comments
 (0)