diff --git a/admin/category.php b/admin/category.php index fb37fa1d7e0..e990383cadb 100644 --- a/admin/category.php +++ b/admin/category.php @@ -131,8 +131,7 @@ if ($savebutton) { $outputhtml .= html_writer::end_tag('div'); } -$visiblepathtosection = array_reverse($settingspage->visiblepath); -$PAGE->set_title("$SITE->shortname: " . implode(": ",$visiblepathtosection)); +$PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $settingspage->visiblepath)); $PAGE->set_heading($SITE->fullname); if ($buttons) { $PAGE->set_button($buttons); diff --git a/admin/index.php b/admin/index.php index 13188c385ec..f1fbb16d470 100644 --- a/admin/index.php +++ b/admin/index.php @@ -224,7 +224,7 @@ if (!core_tables_exist()) { $strlicense = get_string('license'); $PAGE->navbar->add($strlicense); - $PAGE->set_title($strinstallation.' - Moodle '.$CFG->target_release); + $PAGE->set_title($strinstallation . moodle_page::TITLE_SEPARATOR . 'Moodle ' . $CFG->target_release, false); $PAGE->set_heading($strinstallation); $PAGE->set_cacheable(false); @@ -267,7 +267,7 @@ if (!core_tables_exist()) { upgrade_init_javascript(); $PAGE->navbar->add($strdatabasesetup); - $PAGE->set_title($strinstallation.' - Moodle '.$CFG->target_release); + $PAGE->set_title($strinstallation . moodle_page::TITLE_SEPARATOR . $CFG->target_release, false); $PAGE->set_heading($strinstallation); $PAGE->set_cacheable(false); @@ -818,7 +818,7 @@ $context = context_system::instance(); if (!has_capability('moodle/site:config', $context)) { // Do not throw exception display an empty page with administration menu if visible for current user. - $PAGE->set_title($SITE->fullname); + $PAGE->set_title(get_string('home')); $PAGE->set_heading($SITE->fullname); echo $OUTPUT->header(); echo $OUTPUT->footer(); diff --git a/admin/searchreindex.php b/admin/searchreindex.php index c6ed03b3c4e..2886a401f66 100644 --- a/admin/searchreindex.php +++ b/admin/searchreindex.php @@ -44,7 +44,7 @@ $PAGE->set_secondary_active_tab('modules'); // Start page output. $heading = get_string('gradualreindex', 'search', ''); -$PAGE->set_title($PAGE->title . ': ' . $heading); +$PAGE->set_title($areaname . ' - ' . get_string('gradualreindex', 'search', '')); $PAGE->navbar->add($heading); echo $OUTPUT->header(); echo $OUTPUT->heading($heading); diff --git a/admin/settings.php b/admin/settings.php index 30c61121b23..48171745b3a 100644 --- a/admin/settings.php +++ b/admin/settings.php @@ -129,9 +129,7 @@ if (empty($SITE->fullname)) { $PAGE->set_button($buttons); } - $visiblepathtosection = array_reverse($settingspage->visiblepath); - - $PAGE->set_title("$SITE->shortname: " . implode(": ",$visiblepathtosection)); + $PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $settingspage->visiblepath)); $PAGE->set_heading($SITE->fullname); echo $OUTPUT->header(); diff --git a/admin/settings/appearance.php b/admin/settings/appearance.php index c2701e897e9..26f3096ade6 100644 --- a/admin/settings/appearance.php +++ b/admin/settings/appearance.php @@ -242,6 +242,18 @@ reports,core_reportbuilder|/reportbuilder/index.php', // "htmlsettings" settingpage $temp = new admin_settingpage('htmlsettings', new lang_string('htmlsettings', 'admin')); + $sitenameintitleoptions = [ + 'shortname' => new lang_string('shortname'), + 'fullname' => new lang_string('fullname'), + ]; + $sitenameintitleconfig = new admin_setting_configselect( + 'sitenameintitle', + new lang_string('sitenameintitle', 'admin'), + new lang_string('sitenameintitle_help', 'admin'), + 'shortname', + $sitenameintitleoptions + ); + $temp->add($sitenameintitleconfig); $temp->add(new admin_setting_configcheckbox('formatstringstriptags', new lang_string('stripalltitletags', 'admin'), new lang_string('configstripalltitletags', 'admin'), 1)); $temp->add(new admin_setting_emoticons()); $ADMIN->add('appearance', $temp); diff --git a/admin/tool/filetypes/delete.php b/admin/tool/filetypes/delete.php index db8b55f3dc7..ea154b48bbb 100644 --- a/admin/tool/filetypes/delete.php +++ b/admin/tool/filetypes/delete.php @@ -46,7 +46,7 @@ $PAGE->set_url(new \moodle_url('/admin/tool/filetypes/delete.php', array('extens $PAGE->navbar->add($title); $PAGE->set_context($context); $PAGE->set_pagelayout('admin'); -$PAGE->set_title($SITE->fullname. ': ' . $title); +$PAGE->set_title($title); $PAGE->set_primary_active_tab('siteadminnode'); $PAGE->set_secondary_active_tab('server'); diff --git a/admin/tool/filetypes/edit.php b/admin/tool/filetypes/edit.php index b23187eb6e4..9cdd72a5a88 100644 --- a/admin/tool/filetypes/edit.php +++ b/admin/tool/filetypes/edit.php @@ -107,7 +107,7 @@ $PAGE->set_secondary_active_tab('server'); $PAGE->navbar->add($oldextension ? s($oldextension) : $title); $PAGE->set_context($context); $PAGE->set_pagelayout('admin'); -$PAGE->set_title($SITE->fullname. ': ' . $title); +$PAGE->set_title($title); // Display the page. echo $OUTPUT->header(); diff --git a/admin/tool/filetypes/index.php b/admin/tool/filetypes/index.php index 6ac20dcd682..a237731cd7e 100644 --- a/admin/tool/filetypes/index.php +++ b/admin/tool/filetypes/index.php @@ -34,7 +34,7 @@ $context = context_system::instance(); $PAGE->set_url(new \moodle_url('/admin/tool/filetypes/index.php')); $PAGE->set_context($context); $PAGE->set_pagelayout('admin'); -$PAGE->set_title($SITE->fullname. ': ' . $title); +$PAGE->set_title($title); $renderer = $PAGE->get_renderer('tool_filetypes'); diff --git a/admin/tool/filetypes/revert.php b/admin/tool/filetypes/revert.php index c401f93bc1c..b76748d1a18 100644 --- a/admin/tool/filetypes/revert.php +++ b/admin/tool/filetypes/revert.php @@ -46,7 +46,7 @@ $PAGE->set_url(new \moodle_url('/admin/tool/filetypes/revert.php', array('extens $PAGE->navbar->add($title); $PAGE->set_context($context); $PAGE->set_pagelayout('admin'); -$PAGE->set_title($SITE->fullname. ': ' . $title); +$PAGE->set_title($title); // Display the page. echo $OUTPUT->header(); diff --git a/admin/tool/mobile/logout.php b/admin/tool/mobile/logout.php index ebadfec87ed..a1881e3d50f 100644 --- a/admin/tool/mobile/logout.php +++ b/admin/tool/mobile/logout.php @@ -56,7 +56,7 @@ $context = context_system::instance(); $PAGE->set_url(new \moodle_url('/'.$CFG->admin.'/tool/mobile/logout.php')); $PAGE->navbar->add($title); $PAGE->set_context($context); -$PAGE->set_title($SITE->fullname. ': ' . $title); +$PAGE->set_title($title); // Display the page. echo $OUTPUT->header(); diff --git a/auth/ldap/ntlmsso_attempt.php b/auth/ldap/ntlmsso_attempt.php index 6f107caba0f..a7c8749a563 100644 --- a/auth/ldap/ntlmsso_attempt.php +++ b/auth/ldap/ntlmsso_attempt.php @@ -26,7 +26,7 @@ $sesskey = sesskey(); // when we've already left the page that set the timer. $loginsite = get_string("loginsite"); $PAGE->navbar->add($loginsite); -$PAGE->set_title("$site->fullname: $loginsite"); +$PAGE->set_title($loginsite); $PAGE->set_heading($site->fullname); echo $OUTPUT->header(); diff --git a/auth/ldap/ntlmsso_finish.php b/auth/ldap/ntlmsso_finish.php index b0d4d7373b8..9a802ed3bcb 100644 --- a/auth/ldap/ntlmsso_finish.php +++ b/auth/ldap/ntlmsso_finish.php @@ -26,7 +26,7 @@ if (!$authplugin->ntlmsso_finish()) { // here (and not add 3 more secs). $loginsite = get_string("loginsite"); $PAGE->navbar->add($loginsite); - $PAGE->set_title("$site->fullname: $loginsite"); + $PAGE->set_title($loginsite); $PAGE->set_heading($site->fullname); echo $OUTPUT->header(); redirect($CFG->wwwroot . '/login/index.php?authldap_skipntlmsso=1', diff --git a/auth/shibboleth/login.php b/auth/shibboleth/login.php index d4fc639ce5b..df23826ed22 100644 --- a/auth/shibboleth/login.php +++ b/auth/shibboleth/login.php @@ -55,7 +55,7 @@ $PAGE->set_url('/auth/shibboleth/login.php'); $PAGE->set_context(context_system::instance()); $PAGE->navbar->add($loginsite); - $PAGE->set_title("$site->fullname: $loginsite"); + $PAGE->set_title($loginsite); $PAGE->set_heading($site->fullname); $PAGE->set_pagelayout('login'); diff --git a/blog/edit.php b/blog/edit.php index 435445d7487..2c77cbb998d 100644 --- a/blog/edit.php +++ b/blog/edit.php @@ -143,7 +143,7 @@ if ($action === 'delete') { 'sesskey' => sesskey(), 'courseid' => $courseid); $optionsno = array('userid' => $entry->userid, 'courseid' => $courseid); - $PAGE->set_title("$SITE->shortname: $strblogs"); + $PAGE->set_title($strblogs); $PAGE->set_heading($SITE->fullname); echo $OUTPUT->header(); @@ -164,11 +164,11 @@ if ($action === 'delete') { } } else if ($action == 'add') { $editmodetitle = $strblogs . ': ' . get_string('addnewentry', 'blog'); - $PAGE->set_title("$SITE->shortname: $editmodetitle"); + $PAGE->set_title($editmodetitle); $PAGE->set_heading(fullname($USER)); } else if ($action == 'edit') { $editmodetitle = $strblogs . ': ' . get_string('editentry', 'blog'); - $PAGE->set_title("$SITE->shortname: $editmodetitle"); + $PAGE->set_title($editmodetitle); $PAGE->set_heading(fullname($USER)); } diff --git a/blog/external_blog_edit.php b/blog/external_blog_edit.php index 37fb2a5ce52..b8cc1ee0f82 100644 --- a/blog/external_blog_edit.php +++ b/blog/external_blog_edit.php @@ -138,7 +138,7 @@ navigation_node::override_active_url(new moodle_url('/blog/external_blogs.php')) $PAGE->navbar->add(get_string('addnewexternalblog', 'blog')); $PAGE->set_heading(fullname($USER)); -$PAGE->set_title("$SITE->shortname: $strblogs: $strexternalblogs"); +$PAGE->set_title("$strblogs: $strexternalblogs"); echo $OUTPUT->header(); echo $OUTPUT->heading($strformheading, 2); diff --git a/blog/external_blogs.php b/blog/external_blogs.php index 996ee7a3422..667f4b70c1a 100644 --- a/blog/external_blogs.php +++ b/blog/external_blogs.php @@ -67,7 +67,7 @@ if ($delete && confirm_sesskey()) { $blogs = $DB->get_records('blog_external', array('userid' => $USER->id)); $PAGE->set_heading(fullname($USER)); -$PAGE->set_title("$SITE->shortname: $strblogs: $strexternalblogs"); +$PAGE->set_title("$strblogs: $strexternalblogs"); $PAGE->set_pagelayout('standard'); echo $OUTPUT->header(); diff --git a/blog/lib.php b/blog/lib.php index 174b610d0b4..1cd66666f55 100644 --- a/blog/lib.php +++ b/blog/lib.php @@ -716,9 +716,10 @@ function blog_get_headers($courseid=null, $groupid=null, $userid=null, $tagid=nu // Note: if action is set to 'add' or 'edit', we do this at the end. if (empty($entryid) && empty($modid) && empty($courseid) && empty($userid) && !in_array($action, array('edit', 'add'))) { $PAGE->navbar->add($strblogentries, $blogurl); - $PAGE->set_title($site->fullname); + $strsiteblog = get_string('siteblogheading', 'blog'); + $PAGE->set_title($strsiteblog); $PAGE->set_heading($site->fullname); - $headers['heading'] = get_string('siteblogheading', 'blog'); + $headers['heading'] = $strsiteblog; } // Case 2: only entryid is requested, ignore all other filters. courseid is used to give more contextual information. @@ -742,9 +743,10 @@ function blog_get_headers($courseid=null, $groupid=null, $userid=null, $tagid=nu $blogurl->remove_params('userid'); $PAGE->navbar->add($entry->subject, $blogurl); - $PAGE->set_title("$shortname: " . fullname($user) . ": $entry->subject"); + $blogentryby = get_string('blogentrybyuser', 'blog', fullname($user)); + $PAGE->set_title($entry->subject . moodle_page::TITLE_SEPARATOR . $blogentryby); $PAGE->set_heading("$shortname: " . fullname($user) . ": $entry->subject"); - $headers['heading'] = get_string('blogentrybyuser', 'blog', fullname($user)); + $headers['heading'] = $blogentryby; // We ignore tag and search params. if (empty($action) || !$CFG->useblogassociations) { @@ -758,7 +760,7 @@ function blog_get_headers($courseid=null, $groupid=null, $userid=null, $tagid=nu $shortname = format_string($site->shortname, true, array('context' => context_course::instance(SITEID))); $blogurl->param('userid', $userid); - $PAGE->set_title("$shortname: " . fullname($user) . ": " . get_string('blog', 'blog')); + $PAGE->set_title(fullname($user) . ": " . get_string('blog', 'blog')); $PAGE->set_heading("$shortname: " . fullname($user) . ": " . get_string('blog', 'blog')); $headers['heading'] = get_string('userblog', 'blog', fullname($user)); $headers['strview'] = get_string('viewuserentries', 'blog', fullname($user)); @@ -766,9 +768,10 @@ function blog_get_headers($courseid=null, $groupid=null, $userid=null, $tagid=nu } else if (!$CFG->useblogassociations && empty($userid) && !in_array($action, array('edit', 'add'))) { // Case 4: No blog associations, no userid. - $PAGE->set_title($site->fullname); + $strsiteblog = get_string('siteblogheading', 'blog'); + $PAGE->set_title($strsiteblog); $PAGE->set_heading($site->fullname); - $headers['heading'] = get_string('siteblogheading', 'blog'); + $headers['heading'] = $strsiteblog; } else if (!empty($userid) && !empty($modid) && empty($entryid)) { // Case 5: Blog entries associated with an activity by a specific user (courseid ignored). @@ -781,7 +784,7 @@ function blog_get_headers($courseid=null, $groupid=null, $userid=null, $tagid=nu $PAGE->navbar->add(fullname($user), "$CFG->wwwroot/user/view.php?id=$user->id"); $PAGE->navbar->add($strblogentries, $blogurl); - $PAGE->set_title("$shortname: $cm->name: " . fullname($user) . ': ' . get_string('blogentries', 'blog')); + $PAGE->set_title(fullname($user) . ': ' . get_string('blogentries', 'blog') . moodle_page::TITLE_SEPARATOR . $cm->name); $PAGE->set_heading("$shortname: $cm->name: " . fullname($user) . ': ' . get_string('blogentries', 'blog')); $a = new stdClass(); diff --git a/blog/preferences.php b/blog/preferences.php index c950f379255..4c16a56883e 100644 --- a/blog/preferences.php +++ b/blog/preferences.php @@ -95,7 +95,7 @@ $site = get_site(); $strpreferences = get_string('preferences'); $strblogs = get_string('blogs', 'blog'); -$title = "$site->shortname: $strblogs : $strpreferences"; +$title = "$strblogs : $strpreferences"; $PAGE->set_title($title); $PAGE->set_heading(fullname($USER)); diff --git a/calendar/delete.php b/calendar/delete.php index 28af3809c99..b4536e3a542 100644 --- a/calendar/delete.php +++ b/calendar/delete.php @@ -92,7 +92,7 @@ $strcalendar = get_string('calendar', 'calendar'); $PAGE->navbar->add($strcalendar, $viewcalendarurl); $PAGE->navbar->add($title); -$PAGE->set_title($site->shortname.': '.$strcalendar.': '.$title); +$PAGE->set_title($strcalendar.': '.$title); $PAGE->set_heading($COURSE->fullname); if ($course) { $PAGE->set_secondary_navigation(false); diff --git a/course/delete.php b/course/delete.php index 99bc99ace0c..7d283bde3d6 100644 --- a/course/delete.php +++ b/course/delete.php @@ -59,7 +59,7 @@ if ($delete === md5($course->timemodified)) { $strdeletingcourse = get_string("deletingcourse", "", $courseshortname); $PAGE->navbar->add($strdeletingcourse); - $PAGE->set_title("$SITE->shortname: $strdeletingcourse"); + $PAGE->set_title($strdeletingcourse); $PAGE->set_heading($SITE->fullname); echo $OUTPUT->header(); @@ -86,7 +86,7 @@ if ($delete === md5($course->timemodified)) { $strdeletecheck = get_string("deletecheck", "", $courseshortname); $PAGE->navbar->add($strdeletecheck); -$PAGE->set_title("$SITE->shortname: $strdeletecheck"); +$PAGE->set_title($strdeletecheck); $PAGE->set_heading($SITE->fullname); echo $OUTPUT->header(); diff --git a/course/edit.php b/course/edit.php index c3b6b2d04d4..77d2497fae0 100644 --- a/course/edit.php +++ b/course/edit.php @@ -229,7 +229,7 @@ if (!empty($course->id)) { $PAGE->navbar->add(get_string('coursemgmt', 'admin'), $managementurl); $pagedesc = $straddnewcourse; - $title = "$site->shortname: $straddnewcourse"; + $title = $straddnewcourse; $fullname = format_string($category->name); $PAGE->navbar->add($pagedesc); } diff --git a/course/editcategory.php b/course/editcategory.php index af6d13c8f0f..c50adb2339e 100644 --- a/course/editcategory.php +++ b/course/editcategory.php @@ -72,7 +72,7 @@ if ($id) { } else { $context = context_system::instance(); $fullname = $SITE->fullname; - $title = "$SITE->shortname: $strtitle"; + $title = $strtitle; $PAGE->set_secondary_active_tab('courses'); } diff --git a/course/renderer.php b/course/renderer.php index df627474f38..f3404bba12a 100644 --- a/course/renderer.php +++ b/course/renderer.php @@ -1428,13 +1428,13 @@ class core_course_renderer extends plugin_renderer_base { if (core_course_category::is_simple_site()) { // There is only one category in the system, do not display link to it. $strfulllistofcourses = get_string('fulllistofcourses'); - $this->page->set_title("$site->shortname: $strfulllistofcourses"); + $this->page->set_title($strfulllistofcourses); } else if (!$coursecat->id || !$coursecat->is_uservisible()) { $strcategories = get_string('categories'); - $this->page->set_title("$site->shortname: $strcategories"); + $this->page->set_title($strcategories); } else { $strfulllistofcourses = get_string('fulllistofcourses'); - $this->page->set_title("$site->shortname: $strfulllistofcourses"); + $this->page->set_title($strfulllistofcourses); } // Print current category description diff --git a/course/search.php b/course/search.php index ccaf4b302a9..f0d9d625614 100644 --- a/course/search.php +++ b/course/search.php @@ -86,10 +86,10 @@ if (!empty($search)) { if (empty($searchcriteria)) { // no search criteria specified, print page with just search form - $PAGE->set_title("$site->fullname : $strsearch"); + $PAGE->set_title($strsearch); } else { // this is search results page - $PAGE->set_title("$site->fullname : $strsearchresults"); + $PAGE->set_title($strsearchresults); // Link to manage search results should be visible if user have system or category level capability if ((can_edit_in_category() || !empty($usercatlist))) { $aurl = new moodle_url('/course/management.php', $searchcriteria); diff --git a/h5p/libraries.php b/h5p/libraries.php index 40cbc924fe2..bebe0cf1f10 100644 --- a/h5p/libraries.php +++ b/h5p/libraries.php @@ -39,7 +39,7 @@ $url = new \moodle_url("/h5p/libraries.php"); $PAGE->set_context($context); $PAGE->set_url($url); $PAGE->set_pagelayout('admin'); -$PAGE->set_title("$SITE->shortname: " . $pagetitle); +$PAGE->set_title($pagetitle); $PAGE->set_heading($SITE->fullname); $h5pfactory = new \core_h5p\factory(); diff --git a/h5p/overview.php b/h5p/overview.php index 996cb92c70b..45648a3702b 100644 --- a/h5p/overview.php +++ b/h5p/overview.php @@ -35,7 +35,7 @@ $url = new \moodle_url("/h5p/overview.php"); $PAGE->set_context($context); $PAGE->set_url($url); $PAGE->set_pagelayout('admin'); -$PAGE->set_title("$SITE->shortname: " . $pagetitle); +$PAGE->set_title($pagetitle); $PAGE->set_heading($SITE->fullname); echo $OUTPUT->header(); diff --git a/index.php b/index.php index b0ceb50e1af..8e0058c35e5 100644 --- a/index.php +++ b/index.php @@ -101,7 +101,7 @@ course_view(context_course::instance(SITEID)); $PAGE->set_pagetype('site-index'); $PAGE->set_docs_path(''); $editing = $PAGE->user_is_editing(); -$PAGE->set_title($SITE->fullname); +$PAGE->set_title(get_string('home')); $PAGE->set_heading($SITE->fullname); $PAGE->set_secondary_active_tab('coursehome'); diff --git a/lang/en/admin.php b/lang/en/admin.php index 0622309d202..9ea255f0467 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -1300,6 +1300,8 @@ $string['sitemaintenanceon'] = 'Your site is currently in maintenance mode (only $string['sitemaintenanceoncli'] = 'Your site is currently in CLI maintenance mode, no web access is allowed.'; $string['sitemaintenancewarning'] = 'Your site is currently in maintenance mode (only admins can log in). To return this site to normal operation, disable maintenance mode.'; $string['sitemaintenancewarning2'] = 'Your site is currently in maintenance mode (only admins can log in). To return this site to normal operation, disable maintenance mode.'; +$string['sitenameintitle'] = 'Include site name in page title'; +$string['sitenameintitle_help'] = 'This setting will append the site name at the end of the page title. It is encouraged to include the site name in the page title as it will improve the site\'s accessibility by allowing users to quickly identify the page that they are currently in.'; $string['sitepolicies'] = 'Site security settings'; $string['sitepolicy'] = 'Site policy URL'; $string['sitepolicy_help'] = 'The URL of the site policy that all registered users must see and agree to before accessing the site. Note that this setting will only have an effect if the site policy handler is set to default (core).'; diff --git a/lib/adminlib.php b/lib/adminlib.php index 72bb566af67..a4c6ad400c6 100644 --- a/lib/adminlib.php +++ b/lib/adminlib.php @@ -8722,8 +8722,6 @@ function admin_externalpage_setup($section, $extrabutton = '', array $extraurlpa $USER->editing = $adminediting; } - $visiblepathtosection = array_reverse($extpage->visiblepath); - if ($PAGE->user_allowed_editing() && !$PAGE->theme->haseditswitch) { if ($PAGE->user_is_editing()) { $caption = get_string('blockseditoff'); @@ -8735,7 +8733,7 @@ function admin_externalpage_setup($section, $extrabutton = '', array $extraurlpa $PAGE->set_button($OUTPUT->single_button($url, $caption, 'get')); } - $PAGE->set_title("$SITE->shortname: " . implode(": ", $visiblepathtosection)); + $PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $extpage->visiblepath)); $PAGE->set_heading($SITE->fullname); if ($hassiteconfig && empty($options['nosearch'])) { diff --git a/lib/installlib.php b/lib/installlib.php index 6847d9ba437..8e9c5af1ec8 100644 --- a/lib/installlib.php +++ b/lib/installlib.php @@ -344,7 +344,7 @@ function install_print_header($config, $stagename, $heading, $stagetext, $stagec '; echo ' - '.get_string('installation','install').' - Moodle '.$CFG->target_release.' + '.get_string('installation', 'install') . moodle_page::TITLE_SEPARATOR . 'Moodle '.$CFG->target_release.' diff --git a/lib/pagelib.php b/lib/pagelib.php index dafac0a6e7e..0c2069a44eb 100644 --- a/lib/pagelib.php +++ b/lib/pagelib.php @@ -124,6 +124,11 @@ class moodle_page { */ const STATE_DONE = 3; + /** + * The separator used for separating page title elements. + */ + const TITLE_SEPARATOR = ' | '; + /** * @var int The current state of the page. The state a page is within * determines what actions are possible for it. @@ -1367,14 +1372,47 @@ class moodle_page { /** * Sets the title for the page. + * * This is normally used within the title tag in the head of the page. * + * Some tips for providing a meaningful page title: + * - The page title must be accurate and informative. + * - If the page causes a change of context (e.g. a search functionality), it should describe the result or change of context + * to the user. + * - It should be concise. + * - If possible, it should uniquely identify the page. + * - The most identifying information should come first. (e.g. Submit assignment | Assignment | Moodle) + * + * For more information, see + * {@link https://www.w3.org/WAI/WCAG21/Understanding/page-titled Understanding Success Criterion 2.4.2: Page Titled} + * * @param string $title the title that should go in the section of the HTML of this page. + * @param bool $appendsitename Appends site name at the end of the given title. It is encouraged to append the site name as this + * especially helps with accessibility. If it's necessary to override this, please keep in mind + * to ensure that the title provides a concise summary of the page being displayed. */ - public function set_title($title) { + public function set_title($title, bool $appendsitename = true) { + global $CFG; + $title = format_string($title); $title = strip_tags($title); $title = str_replace('"', '"', $title); + + if ($appendsitename) { + // Append the site name at the end of the page title. + $sitenamedisplay = 'shortname'; + if (!empty($CFG->sitenameintitle)) { + $sitenamedisplay = $CFG->sitenameintitle; + } + $site = get_site(); + if (empty(trim($site->{$sitenamedisplay}))) { + // If for some reason the site name is not yet set, fall back to 'Moodle'. + $title .= self::TITLE_SEPARATOR . 'Moodle'; + } else { + $title .= self::TITLE_SEPARATOR . format_string($site->{$sitenamedisplay}); + } + } + $this->_title = $title; } @@ -1778,11 +1816,7 @@ class moodle_page { '/settings.php?section=maintenancemode">' . get_string('maintenancemode', 'admin') . ' ' . $this->button); - $title = $this->title; - if ($title) { - $title .= ' - '; - } - $this->set_title($title . get_string('maintenancemode', 'admin')); + $this->set_title(get_string('maintenancemode', 'admin')); } $this->initialise_standard_body_classes(); diff --git a/lib/tests/behat/behat_general.php b/lib/tests/behat/behat_general.php index 8921a258e4f..ec12005bdf9 100644 --- a/lib/tests/behat/behat_general.php +++ b/lib/tests/behat/behat_general.php @@ -2358,4 +2358,36 @@ EOF; } } + /** + * Check that the page title contains a given string. + * + * @Given the page title should contain ":title" + * @param string $title The string that should be present on the page title. + */ + public function the_page_title_should_contain(string $title): void { + $session = $this->getSession(); + if ($this->running_javascript()) { + // When running on JS, the page title can be changed via JS, so it's more reliable to get the actual page title via JS. + $actualtitle = $session->evaluateScript("return document.title"); + } else { + $titleelement = $session->getPage()->find('css', 'head title'); + if ($titleelement === null) { + // Throw an exception if a page title is not present on the page. + throw new ElementNotFoundException( + $this->getSession(), + ' element', + 'css', + 'head title' + ); + } + $actualtitle = $titleelement->getText(); + } + + if (!str_contains($actualtitle, $title)) { + throw new ExpectationException( + "'$title' was not found from the current page title '$actualtitle'", + $session + ); + } + } } diff --git a/lib/tests/behat/behat_hooks.php b/lib/tests/behat/behat_hooks.php index 81d99f0253d..38822d79d10 100644 --- a/lib/tests/behat/behat_hooks.php +++ b/lib/tests/behat/behat_hooks.php @@ -520,7 +520,7 @@ EOF; 'or that your web server is correctly set up and started.'; $this->find( - "xpath", "//head/child::title[normalize-space(.)='" . behat_util::BEHATSITENAME . "']", + "xpath", "//head/child::title[contains(., '" . behat_util::BEHATSITENAME . "')]", new ExpectationException($message, $session) ); diff --git a/lib/tests/moodle_page_test.php b/lib/tests/moodle_page_test.php index e70bd262805..94b4a88ae06 100644 --- a/lib/tests/moodle_page_test.php +++ b/lib/tests/moodle_page_test.php @@ -325,11 +325,66 @@ class moodle_page_test extends \advanced_testcase { $this->assertSame('a heading <a href="#">edit</a><p></p>', $this->testpage->heading); } - public function test_set_title() { - // Exercise SUT. - $this->testpage->set_title('a title'); + /** + * Data provider for {@see test_set_title}. + * + * @return array + */ + public function set_title_provider(): array { + return [ + 'Do not append the site name' => [ + 'shortname', false, '', false + ], + 'Site not yet installed not configured defaults to site shortname' => [ + null, true, 'shortname' + ], + '$CFG->sitenameintitle not configured defaults to site shortname' => [ + null, true, 'shortname' + ], + '$CFG->sitenameintitle set to shortname' => [ + 'shortname', true, 'shortname' + ], + '$CFG->sitenameintitle set to fullname' => [ + 'fullname', true, 'fullname' + ], + ]; + } + + /** + * Test for set_title + * + * @dataProvider set_title_provider + * @param string|null $config The config value for $CFG->sitenameintitle. + * @param bool $appendsitename The $appendsitename parameter + * @param string $expected The expected site name to be appended to the title. + * @param bool $sitenameset To simulate the absence of the site name being set in the site. + * @return void + * @covers ::set_title + */ + public function test_set_title(?string $config, bool $appendsitename, string $expected, bool $sitenameset = true): void { + global $CFG, $SITE; + + if ($config !== null) { + $CFG->sitenameintitle = $config; + } + + $title = "A title"; + if ($appendsitename) { + if ($sitenameset) { + $expectedtitle = $title . moodle_page::TITLE_SEPARATOR . $SITE->{$expected}; + } else { + // Simulate site fullname and shortname being empty for any reason. + $SITE->fullname = null; + $SITE->shortname = null; + $expectedtitle = $title . moodle_page::TITLE_SEPARATOR . 'Moodle'; + } + } else { + $expectedtitle = $title; + } + + $this->testpage->set_title($title, $appendsitename); // Validated. - $this->assertSame('a title', $this->testpage->title); + $this->assertSame($expectedtitle, $this->testpage->title); } public function test_default_pagelayout() { diff --git a/lib/upgrade.txt b/lib/upgrade.txt index 96daf7fce74..45f33f96f90 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -169,6 +169,14 @@ being forced open in all behat tests. * Added a new method called exceeds_password_length in moodlelib.php to validate the password length. * The core/modal_factory has been deprecated. From Moodle 4.3 onwards please instantiate new modals using the ModalType.create method instead. Please note that this method does not support the `trigger` option. +* \moodle_page::set_title() has been updated to append the site name depending on the value of $CFG->sitenameintitle and whether + the site's fullname/shortname has been set. So there's no need to manually add the site name whenever calling $PAGE->set_title(). + If it's necessary to override this, pass `false` to its new optional parameter `$appendsitename`. +* New page title separator constant `moodle_page:TITLE_SEPARATOR` has been created to help standardise the separators used in page + titles. +* New Behat step \behat_general::the_page_title_should_contain() has been added to allow checking of page titles. You can use this + when writing feature files to check that the page title contains the expected string. + e.g. `And the page title should contain "Some title"` === 4.2 === diff --git a/lib/upgradelib.php b/lib/upgradelib.php index a7b616b1954..e9e2a7778b4 100644 --- a/lib/upgradelib.php +++ b/lib/upgradelib.php @@ -1584,7 +1584,7 @@ function upgrade_started($preinstall=false) { $strupgrade = get_string('upgradingversion', 'admin'); $PAGE->set_pagelayout('maintenance'); upgrade_init_javascript(); - $PAGE->set_title($strupgrade.' - Moodle '.$CFG->target_release); + $PAGE->set_title($strupgrade . moodle_page::TITLE_SEPARATOR . 'Moodle ' . $CFG->target_release); $PAGE->set_heading($strupgrade); $PAGE->navbar->add($strupgrade); $PAGE->set_cacheable(false); diff --git a/lib/weblib.php b/lib/weblib.php index ab4c9031653..840a6c53157 100644 --- a/lib/weblib.php +++ b/lib/weblib.php @@ -3210,7 +3210,6 @@ function print_maintenance_message() { $PAGE->set_pagetype('maintenance-message'); $PAGE->set_pagelayout('maintenance'); - $PAGE->set_title(strip_tags($SITE->fullname)); $PAGE->set_heading($SITE->fullname); echo $OUTPUT->header(); echo $OUTPUT->heading(get_string('sitemaintenance', 'admin')); diff --git a/login/index.php b/login/index.php index e524100d1cc..82c7234362a 100644 --- a/login/index.php +++ b/login/index.php @@ -246,7 +246,7 @@ if ($frm and isset($frm->username)) { // Login WITH $passwordchangeurl = $CFG->wwwroot.'/login/change_password.php'; } $days2expire = $userauth->password_expire($USER->username); - $PAGE->set_title("$site->fullname: $loginsite"); + $PAGE->set_title($loginsite); $PAGE->set_heading("$site->fullname"); if (intval($days2expire) > 0 && intval($days2expire) < intval($userauth->config->expiration_warning)) { echo $OUTPUT->header(); @@ -369,7 +369,7 @@ if (!empty($SESSION->loginerrormsg) || !empty($SESSION->logininfomsg)) { redirect(new moodle_url('/login/index.php')); } -$PAGE->set_title("$site->fullname: $loginsite"); +$PAGE->set_title($loginsite); $PAGE->set_heading("$site->fullname"); echo $OUTPUT->header(); diff --git a/login/logout.php b/login/logout.php index 664b179aa95..e7ebddefd8e 100644 --- a/login/logout.php +++ b/login/logout.php @@ -45,7 +45,7 @@ if (!isloggedin()) { redirect($redirect); } else if (!confirm_sesskey($sesskey)) { - $PAGE->set_title($SITE->fullname); + $PAGE->set_title(get_string('logout')); $PAGE->set_heading($SITE->fullname); echo $OUTPUT->header(); echo $OUTPUT->confirm(get_string('logoutconfirm'), new moodle_url($PAGE->url, array('sesskey'=>sesskey())), $CFG->wwwroot.'/'); @@ -61,4 +61,4 @@ foreach($authsequence as $authname) { require_logout(); -redirect($redirect); \ No newline at end of file +redirect($redirect); diff --git a/message/output/popup/notifications.php b/message/output/popup/notifications.php index 1a2988e140d..c44c0cafdfc 100644 --- a/message/output/popup/notifications.php +++ b/message/output/popup/notifications.php @@ -51,7 +51,7 @@ $PAGE->set_pagelayout('admin'); // Display page header. $title = get_string('notifications', 'message'); -$PAGE->set_title("{$SITE->shortname}: " . $title); +$PAGE->set_title($title); $PAGE->set_heading(fullname($user)); // Grab the renderer. diff --git a/mod/assign/tests/behat/page_titles.feature b/mod/assign/tests/behat/page_titles.feature index 7dce9ffd6bf..299e56ec0f2 100644 --- a/mod/assign/tests/behat/page_titles.feature +++ b/mod/assign/tests/behat/page_titles.feature @@ -21,14 +21,14 @@ Feature: In an assignment, page titles are informative Scenario: I view an assignment as a student and take an action When I am on the "History of ants" Activity page logged in as student1 - Then "title[text() = 'C1: History of ants']" "xpath_element" should exist in the "head" "css_element" + Then the page title should contain "C1: History of ants" And I press "Add submission" - And "title[text() = 'C1: History of ants - Edit submission']" "xpath_element" should exist in the "head" "css_element" + And the page title should contain "C1: History of ants - Edit submission" Scenario: I view an assignment as a teacher and take an action When I am on the "History of ants" Activity page logged in as teacher1 - Then "title[text() = 'C1: History of ants']" "xpath_element" should exist in the "head" "css_element" + Then the page title should contain "C1: History of ants" And I follow "View all submissions" - And "title[text() = 'C1: History of ants - Grading']" "xpath_element" should exist in the "head" "css_element" + And the page title should contain "C1: History of ants - Grading" And I click on "Grade" "link" in the "Student 1" "table_row" - And "title[text() = 'C1: History of ants - Grading']" "xpath_element" should exist in the "head" "css_element" + And the page title should contain "C1: History of ants - Grading" diff --git a/mod/lti/register.php b/mod/lti/register.php index 20a460fae90..6146aa64b0d 100644 --- a/mod/lti/register.php +++ b/mod/lti/register.php @@ -67,7 +67,7 @@ admin_externalpage_setup('ltitoolproxies'); $PAGE->set_heading(get_string('toolproxyregistration', 'lti')); -$PAGE->set_title("{$SITE->shortname}: " . get_string('toolproxyregistration', 'lti')); +$PAGE->set_title(get_string('toolproxyregistration', 'lti')); // Print the page header. echo $OUTPUT->header(); diff --git a/mod/lti/registersettings.php b/mod/lti/registersettings.php index 4ed9dafea0a..0b63dcd2739 100644 --- a/mod/lti/registersettings.php +++ b/mod/lti/registersettings.php @@ -84,7 +84,7 @@ if ($form->is_cancelled()) { $id = lti_add_tool_proxy($data); redirect($redirect); } else { - $PAGE->set_title("{$SITE->shortname}: " . get_string('toolregistration', 'lti')); + $PAGE->set_title(get_string('toolregistration', 'lti')); $PAGE->navbar->add(get_string('lti_administration', 'lti'), $redirect); echo $OUTPUT->header(); diff --git a/mod/lti/toolconfigure.php b/mod/lti/toolconfigure.php index 2b7bc00bc23..5b957271d10 100644 --- a/mod/lti/toolconfigure.php +++ b/mod/lti/toolconfigure.php @@ -45,7 +45,7 @@ if ($cartridgeurl) { $pageurl = new moodle_url('/mod/lti/toolconfigure.php'); $PAGE->set_url($pageurl); -$PAGE->set_title("{$SITE->shortname}: " . get_string('toolregistration', 'mod_lti')); +$PAGE->set_title(get_string('toolregistration', 'mod_lti')); $PAGE->requires->string_for_js('success', 'moodle'); $PAGE->requires->string_for_js('error', 'moodle'); $PAGE->requires->string_for_js('successfullycreatedtooltype', 'mod_lti'); diff --git a/mod/lti/toolproxies.php b/mod/lti/toolproxies.php index 7926ef94ce0..8075ff4e14f 100644 --- a/mod/lti/toolproxies.php +++ b/mod/lti/toolproxies.php @@ -35,7 +35,7 @@ $PAGE->set_url($pageurl); admin_externalpage_setup('ltitoolproxies'); -$PAGE->set_title("{$SITE->shortname}: " . get_string('toolregistration', 'lti')); +$PAGE->set_title(get_string('toolregistration', 'lti')); $configuredtoolproxieshtml = ''; $pendingtoolproxieshtml = ''; diff --git a/mod/lti/toolssettings.php b/mod/lti/toolssettings.php index 693405fd828..edb9a7c2d3f 100644 --- a/mod/lti/toolssettings.php +++ b/mod/lti/toolssettings.php @@ -106,7 +106,7 @@ if ($data = $form->get_data()) { redirect($redirect); } -$PAGE->set_title(format_string($SITE->shortname) . ': ' . get_string('toolsetup', 'lti')); +$PAGE->set_title(get_string('toolsetup', 'lti')); $PAGE->navbar->add(get_string('lti_administration', 'lti'), $CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=modsettinglti'); echo $OUTPUT->header(); diff --git a/mod/lti/typessettings.php b/mod/lti/typessettings.php index 91c2cd82011..ace0b899124 100644 --- a/mod/lti/typessettings.php +++ b/mod/lti/typessettings.php @@ -158,7 +158,7 @@ if ($data = $form->get_data()) { redirect($redirect); } -$PAGE->set_title("$SITE->shortname: " . get_string('toolsetup', 'lti')); +$PAGE->set_title(get_string('toolsetup', 'lti')); $PAGE->set_primary_active_tab('siteadminnode'); $PAGE->set_secondary_active_tab('ltitoolconfigure'); $PAGE->navbar->add(get_string('manage_external_tools', 'lti'), new moodle_url('/mod/lti/toolconfigure.php')); diff --git a/report/insights/done.php b/report/insights/done.php index e11aff98843..15257b91c15 100644 --- a/report/insights/done.php +++ b/report/insights/done.php @@ -37,7 +37,7 @@ if (!\core_analytics\manager::is_analytics_enabled()) { exit(0); } -$PAGE->set_title(get_site()->fullname); +$PAGE->set_title(get_string('insights', 'report_insights')); $PAGE->set_url(new \moodle_url('/report/insights/done.php')); echo $OUTPUT->header(); diff --git a/report/log/index.php b/report/log/index.php index 82df2860a91..41519990296 100644 --- a/report/log/index.php +++ b/report/log/index.php @@ -138,7 +138,7 @@ if ($PAGE->user_allowed_editing() && $adminediting != -1) { if ($course->id == $SITE->id) { admin_externalpage_setup('reportlog', '', null, '', array('pagelayout' => 'report')); - $PAGE->set_title($SITE->shortname .': '. $strlogs); + $PAGE->set_title($strlogs); $PAGE->set_primary_active_tab('siteadminnode'); } else { $PAGE->set_title($course->shortname .': '. $strlogs); diff --git a/user/editadvanced.php b/user/editadvanced.php index 3a45e188d23..3d8795ebfef 100644 --- a/user/editadvanced.php +++ b/user/editadvanced.php @@ -332,7 +332,8 @@ if ($user->id == -1 or ($user->id != $USER->id)) { $streditmyprofile = get_string('editmyprofile'); $userfullname = fullname($user, true); $PAGE->set_heading($userfullname); - $PAGE->set_title("$course->shortname: $streditmyprofile - $userfullname"); + $coursename = $course->id !== SITEID ? "$course->shortname" : ''; + $PAGE->set_title("$streditmyprofile: $userfullname" . moodle_page::TITLE_SEPARATOR . $coursename); echo $OUTPUT->header(); echo $OUTPUT->heading($userfullname); } diff --git a/user/emailupdate.php b/user/emailupdate.php index 0577c68a0a9..6de500eff43 100644 --- a/user/emailupdate.php +++ b/user/emailupdate.php @@ -42,7 +42,7 @@ $a = new stdClass(); $a->fullname = fullname($user, true); $stremailupdate = get_string('emailupdate', 'auth', $a); -$PAGE->set_title(format_string($SITE->fullname) . ": $stremailupdate"); +$PAGE->set_title($stremailupdate); $PAGE->set_heading(format_string($SITE->fullname) . ": $stremailupdate"); if (empty($preferences['newemailattemptsleft'])) { diff --git a/user/profile.php b/user/profile.php index 2de644ed536..553b24f56a7 100644 --- a/user/profile.php +++ b/user/profile.php @@ -83,7 +83,7 @@ if (!user_can_view_profile($user, null, $context)) { // Course managers can be browsed at site level. If not forceloginforprofiles, allow access (bug #4366). $struser = get_string('user'); $PAGE->set_context(context_system::instance()); - $PAGE->set_title("$SITE->shortname: $struser"); // Do not leak the name. + $PAGE->set_title($struser); // Do not leak the name. $PAGE->set_heading($struser); $PAGE->set_pagelayout('mypublic'); $PAGE->add_body_class('limitedwidth');