Merge branch 'MDL-45893-master-v3' of git://github.com/jethac/moodle

Conflicts:
	theme/bootstrapbase/style/moodle.css
This commit is contained in:
Dan Poltawski
2014-10-07 16:52:07 +01:00
17 changed files with 684 additions and 16 deletions
+7 -4
View File
@@ -91,10 +91,13 @@ class behat_auth extends behat_base {
return $steps;
}
// If it is needed, it expands the navigation bar with the 'Log out' link.
if ($clicknavbar = $this->get_expand_navbar_step()) {
array_unshift($steps, $clicknavbar);
}
// There is no longer any need to worry about whether the navigation
// bar needs to be expanded; user_menu now lives outside the
// hamburger.
// However, the user menu *always* needs to be expanded.
$xpath ="//div[@class='usermenu']//a[contains(concat(' ', @class, ' '), ' toggle-display ')]";
array_unshift($steps, new When('I click on "'.$xpath.'" "xpath_element"'));
return $steps;
}
+1
View File
@@ -1899,6 +1899,7 @@ $string['userdescription_help'] = 'This box enables you to enter some text about
$string['userdetails'] = 'User details';
$string['userfiles'] = 'User files';
$string['userlist'] = 'User list';
$string['usermenu'] = 'User menu';
$string['username'] = 'Username';
$string['usernameemail'] = 'Username / email';
$string['usernameemailmatch'] = 'The username and email address do not relate to the same user';
+177
View File
@@ -2904,6 +2904,183 @@ EOD;
return html_writer::tag('ul', implode("\n", $lis), $attrs);
}
/**
* Construct a user menu, returning HTML that can be echoed out by a
* layout file.
*
* @param stdClass $user A user object, usually $USER.
* @param bool $withlinks true if a dropdown should be built.
* @return string HTML fragment.
*/
public function user_menu($user = null, $withlinks = null) {
global $USER, $CFG;
require_once($CFG->dirroot . '/user/lib.php');
if (is_null($user)) {
$user = $USER;
}
// Note: this behaviour is intended to match that of core_renderer::login_info,
// but should not be considered to be good practice; layout options are
// intended to be theme-specific. Please don't copy this snippet anywhere else.
if (is_null($withlinks)) {
$withlinks = empty($this->page->layout_options['nologinlinks']);
}
// Add a class for when $withlinks is false.
$usermenuclasses = 'usermenu';
if (!$withlinks) {
$usermenuclasses .= ' withoutlinks';
}
$returnstr = "";
// If during initial install, return the empty return string.
if (during_initial_install()) {
return $returnstr;
}
$loginpage = ((string)$this->page->url === get_login_url());
$loginurl = get_login_url();
// If not logged in, show the typical not-logged-in string.
if (!isloggedin()) {
$returnstr = get_string('loggedinnot', 'moodle');
if (!$loginpage) {
$returnstr .= " (<a href=\"$loginurl\">" . get_string('login') . '</a>)';
}
return html_writer::div(
html_writer::span(
$returnstr,
'login'
),
$usermenuclasses
);
}
// If logged in as a guest user, show a string to that effect.
if (isguestuser()) {
$returnstr = get_string('loggedinasguest');
if (!$loginpage && $withlinks) {
$returnstr .= " (<a href=\"$loginurl\">".get_string('login').'</a>)';
}
return html_writer::div(
html_writer::span(
$returnstr,
'login'
),
$usermenuclasses
);
}
// Get some navigation opts.
$opts = user_get_user_navigation_info($user, $this->page, $this->page->course);
$avatarclasses = "avatars";
$avatarcontents = html_writer::span($opts->metadata['useravatar'], 'avatar current');
$usertextcontents = $opts->metadata['userfullname'];
// Other user.
if (!empty($opts->metadata['asotheruser'])) {
$avatarcontents .= html_writer::span(
$opts->metadata['realuseravatar'],
'avatar realuser'
);
$usertextcontents = $opts->metadata['realuserfullname'];
$usertextcontents .= html_writer::tag(
'span',
get_string(
'loggedinas',
'moodle',
html_writer::span(
$opts->metadata['userfullname'],
'value'
)
),
array('class' => 'meta viewingas')
);
}
// Role.
if (!empty($opts->metadata['asotherrole'])) {
$role = core_text::strtolower(preg_replace('#[ ]+#', '-', trim($opts->metadata['rolename'])));
$usertextcontents .= html_writer::span(
$opts->metadata['rolename'],
'meta role role-' . $role
);
}
// User login failures.
if (!empty($opts->metadata['userloginfail'])) {
$usertextcontents .= html_writer::span(
$opts->metadata['userloginfail'],
'meta loginfailures'
);
}
// MNet.
if (!empty($opts->metadata['asmnetuser'])) {
$mnet = strtolower(preg_replace('#[ ]+#', '-', trim($opts->metadata['mnetidprovidername'])));
$usertextcontents .= html_writer::span(
$opts->metadata['mnetidprovidername'],
'meta mnet mnet-' . $mnet
);
}
$returnstr .= html_writer::span(
html_writer::span($usertextcontents, 'usertext') .
html_writer::span($avatarcontents, $avatarclasses),
'userbutton'
);
// Create a divider (well, a filler).
$divider = new action_menu_filler();
$divider->primary = false;
$am = new action_menu();
$am->initialise_js($this->page);
$am->set_menu_trigger(html_writer::span(
get_string('usermenu', 'moodle'),
"accesshide"
));
$am->set_alignment(action_menu::TR, action_menu::BR);
if ($withlinks) {
$navitemcount = count($opts->navitems);
$idx = 0;
foreach ($opts->navitems as $key => $value) {
$pix = null;
if (isset($value->pix)) {
$pix = new pix_icon($value->pix, $value->title, null, array('class' => 'iconsmall'));
}
$al = new action_menu_link_secondary(
$value->url,
$pix,
$value->title,
array('class' => 'icon')
);
$am->add($al);
// Add dividers after the first item and before the
// last item.
if ($idx == 0 || $idx == $navitemcount - 2) {
$am->add($divider);
}
$idx++;
}
}
return html_writer::div(
html_writer::div(
$returnstr,
'userinfo'
) .
$this->render($am),
$usermenuclasses
);
}
/**
* Return the navbar content so that it can be echoed out by the layout
*
+1 -1
View File
@@ -66,7 +66,7 @@ echo $OUTPUT->doctype() ?>
<div id="page-header" class="clearfix">
<h1 class="headermain"><?php echo $PAGE->heading ?></h1>
<div class="headermenu"><?php
echo $OUTPUT->login_info();
echo $OUTPUT->user_menu();
echo $OUTPUT->lang_menu();
echo $PAGE->headingmenu;
?></div>
+1 -3
View File
@@ -80,9 +80,7 @@ echo $OUTPUT->doctype() ?>
<?php if ($hasheading) { ?>
<h1 class="headermain"><?php echo $PAGE->heading ?></h1>
<div class="headermenu"><?php
if ($haslogininfo) {
echo $OUTPUT->login_info();
}
echo $OUTPUT->user_menu();
if (!empty($PAGE->layout_options['langmenu'])) {
echo $OUTPUT->lang_menu();
}
+100
View File
@@ -192,6 +192,106 @@ a.skip:active {position: static;display: block;}
.headermenu {float:right;margin:10px;font-size:0.8em;text-align:right;}
#course-header {clear:both;}
/**
* User menu
*/
.usermenu {
border: 1px solid #333;
padding: 4px 6px;
margin: 0.5em 0em;
font-size: 14px;
}
.jsenabled .usermenu.withoutlinks .moodle-actionmenu[data-enhance]
{
display: none;
}
.usermenu .menu .filler {
width: auto;
height: 1px;
margin: 9px 0px;
display: block;
background: #e5e5e5;
}
.usermenu .toggle-display {
outline: none;
}
.usermenu .userbutton {
background: #fff;
color: #000;
display: inline-block;
font-size: 15px;
}
.usermenu .userbutton > * {
display: inline-block;
vertical-align: middle;
}
.usermenu .userbutton .avatars {
display: inline-block;
vertical-align: middle;
}
.usermenu .userbutton .usertext {
display: inline-block;
text-align: left;
}
.usermenu .userbutton .usertext .meta{
display: block;
font-size: 12px;
}
.usermenu .userbutton .usertext .meta .value {
font-weight: bold;
}
.usermenu .moodle-actionmenu .toggle-display.textmenu .caret {
display: none;
}
.jsenabled .usermenu .moodle-actionmenu[data-enhanced] .toggle-display.textmenu {
margin-left: 0;
padding-left: 0;
}
.jsenabled.dir-rtl .usermenu .moodle-actionmenu[data-enhanced] .toggle-display.textmenu {
margin-right: 0;
margin-left: 4px;
}
.jsenabled .usermenu .moodle-actionmenu[data-enhanced] .toggle-display.textmenu .caret {
display: inline-block;
margin-top: 0;
vertical-align: middle;
}
.userloggedinas .usermenu .userbutton .avatars .avatar {
display: inline-block;
vertical-align:middle;
overflow: hidden;
}
.userloggedinas .usermenu .userbutton .avatars .avatar img {
width: inherit;
height: inherit;
}
.userloggedinas .usermenu .userbutton .avatars .avatar.current {
position: relative;
top: 4px;
left: 4px;
width: 20px;
height: 20px;
margin-top: 11px;
border: 1px solid #ddd;
border-radius: 10px;
box-shadow: -2px -2px 16px rgba(0,0,0,0.25);
}
.dir-ltr .usermenu .userbutton .avatars {
margin-right: 6px;
}
.dir-rtl .usermenu .userbutton {
margin-right: -4px;
}
.dir-rtl .usermenu .userbutton .avatars {
margin-left: 6px;
}
.dir-ltr.userloggedinas .usermenu .userbutton .avatars .avatar.current {
margin-right: -34px;
}
.dir-rtl.userloggedinas .usermenu .userbutton .avatars .avatar.current {
margin-left: -42px;
}
/**
* Navbar
*/
+1 -1
View File
@@ -46,11 +46,11 @@ echo $OUTPUT->doctype() ?>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<?php echo $OUTPUT->user_menu(); ?>
<div class="nav-collapse collapse">
<?php echo $OUTPUT->custom_menu(); ?>
<ul class="nav pull-right">
<li><?php echo $OUTPUT->page_heading_menu(); ?></li>
<li class="navbar-text"><?php echo $OUTPUT->login_info() ?></li>
</ul>
</div>
</div>
+1 -1
View File
@@ -47,11 +47,11 @@ echo $OUTPUT->doctype() ?>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<?php echo $OUTPUT->user_menu(); ?>
<div class="nav-collapse collapse">
<?php echo $OUTPUT->custom_menu(); ?>
<ul class="nav pull-right">
<li><?php echo $OUTPUT->page_heading_menu(); ?></li>
<li class="navbar-text"><?php echo $OUTPUT->login_info() ?></li>
</ul>
</div>
</div>
+1 -1
View File
@@ -52,11 +52,11 @@ echo $OUTPUT->doctype() ?>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<?php echo $OUTPUT->user_menu(); ?>
<div class="nav-collapse collapse">
<?php echo $OUTPUT->custom_menu(); ?>
<ul class="nav pull-right">
<li><?php echo $OUTPUT->page_heading_menu(); ?></li>
<li class="navbar-text"><?php echo $OUTPUT->login_info() ?></li>
</ul>
</div>
</div>
+2 -1
View File
@@ -60,7 +60,7 @@ echo $OUTPUT->doctype() ?>
<?php echo $OUTPUT->custom_menu(); ?>
<ul class="nav pull-right">
<li><?php echo $OUTPUT->page_heading_menu(); ?></li>
<li class="navbar-text"><?php echo $OUTPUT->login_info() ?></li>
<li class="navbar-text"><?php echo $OUTPUT->user_menu(); ?></li>
</ul>
</div>
</div>
@@ -75,6 +75,7 @@ echo $OUTPUT->doctype() ?>
<div class="breadcrumb-button"><?php echo $OUTPUT->page_heading_button(); ?></div>
</div>
<?php echo $OUTPUT->page_heading(); ?>
<?php echo $OUTPUT->user_menu(); ?>
<div id="course-header">
<?php echo $OUTPUT->course_header(); ?>
</div>
@@ -340,3 +340,195 @@ div#dock {
border-right: 0px none;
}
}
// Usermenu
.usermenu {
font-size: 14px;
&.withoutlinks {
.withoutlinks {
display: none;
}
}
.login {
color: @navbarText;
line-height: 40px;
a {
color: @navbarLinkColor;
}
}
> .moodle-actionmenu > .menubar {
display: block;
margin: -40px 0px 2px 0px;
li {
display: block;
a {
line-height: 40px;
}
}
}
> div {
height: 40px;
}
.toggle-display {
color: @navbarLinkColor;
outline: none;
}
.userbutton {
height: 40px;
line-height: 40px;
.avatars{
display: inline-block;
height: 36px;
vertical-align: middle;
margin-right: 6px;
.avatar,
img {
display: block;
}
}
.usertext {
display: inline-block;
vertical-align: middle;
line-height: 1em;
.meta,
.role {
display: block;
font-size: 12px;
.value {
font-weight: bold;
}
}
.role {
font-weight: bold;
}
}
}
.moodle-actionmenu[data-enhanced].show .menu a {
white-space: nowrap;
}
.menu .filler {
width: auto;
height: 1px;
margin: 4px 0px;
display: block;
background: #e5e5e5;
}
}
.userloggedinas .usermenu .userbutton .avatars {
.avatar {
&.current {
position: relative;
top: 4px;
left: 4px;
width: 20px;
height: 20px;
margin-top: 11px;
border: 1px solid #fff;
border-radius: 50%;
box-shadow: -2px -2px 16px rgba(0,0,0,0.25);
}
img {
width: inherit;
height: inherit;
}
display: inline-block;
overflow: hidden;
}
}
.jsenabled .usermenu .moodle-actionmenu[data-enhanced] .toggle-display.textmenu {
position: relative;
.caret {
margin-top: 0;
vertical-align: middle;
}
}
.jsenabled .navbar-inverse {
.usermenu {
.login {
color: @navbarInverseText;
a {
color: @navbarInverseLinkColor;
&:hover {
color: @navbarInverseLinkColorHover;
}
}
}
.toggle-display {
color: @navbarInverseLinkColor;
}
.userinfo .usertext {
color: @navbarInverseLinkColor;
.meta {
color: @navbarInverseText;
.value {
color: @navbarInverseLinkColor;
}
}
}
&:hover {
.userinfo .usertext {
color: @navbarInverseLinkColorHover;
.meta {
color: @navbarInverseText;
.value {
color: @navbarInverseLinkColorHover;
}
}
}
.moodle-actionmenu[data-enhanced] .toggle-display.textmenu {
.caret {
border-top-color: @navbarInverseLinkColorHover;
}
}
}
}
}
.dir-ltr {
.usermenu {
float: right;
.userinfo {
padding-left: 20px;
}
.userbutton {
margin-right: 4px;
padding-right: 8px;
.avatars{
margin-left: 6px;
}
}
> .moodle-actionmenu > .menubar li a {
text-align: right;
}
}
&.userloggedinas .usermenu .userbutton .avatars {
.avatar {
&.current {
margin-right: -34px;
}
}
}
}
.dir-rtl {
.usermenu {
float: left;
.userbutton {
margin-left: 4px;
padding-left: 8px;
.avatars{
margin-right: 6px;
}
}
> .moodle-actionmenu > .menubar li a {
text-align: left;
}
}
&.userloggedinas .usermenu .userbutton .avatars {
.avatar {
&.current {
margin-left: -42px;
}
}
}
}
@@ -440,6 +440,18 @@
}
.nav-collapse.active {
height: auto;
.usermenu .moodle-actionmenu[data-enhanced] {
.toggle-display {
display: none;
}
.menu {
display: block;
li {
margin: 0 0.5em;
}
}
}
}
.path-mod-data .box > table > tbody > tr > td {
display: block;
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -49,11 +49,11 @@ echo $OUTPUT->doctype() ?>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<?php echo $OUTPUT->user_menu(); ?>
<div class="nav-collapse collapse">
<?php echo $OUTPUT->custom_menu(); ?>
<ul class="nav pull-right">
<li><?php echo $OUTPUT->page_heading_menu(); ?></li>
<li class="navbar-text"><?php echo $OUTPUT->login_info() ?></li>
</ul>
</div>
</div>
+1 -1
View File
@@ -50,11 +50,11 @@ echo $OUTPUT->doctype() ?>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<?php echo $OUTPUT->user_menu(); ?>
<div class="nav-collapse collapse">
<?php echo $OUTPUT->custom_menu(); ?>
<ul class="nav pull-right">
<li><?php echo $OUTPUT->page_heading_menu(); ?></li>
<li class="navbar-text"><?php echo $OUTPUT->login_info() ?></li>
</ul>
</div>
</div>
+1 -1
View File
@@ -61,11 +61,11 @@ echo $OUTPUT->doctype() ?>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<?php echo $OUTPUT->user_menu(); ?>
<div class="nav-collapse collapse">
<?php echo $OUTPUT->custom_menu(); ?>
<ul class="nav pull-right">
<li><?php echo $OUTPUT->page_heading_menu(); ?></li>
<li class="navbar-text"><?php echo $OUTPUT->login_info() ?></li>
</ul>
</div>
</div>
+184
View File
@@ -614,3 +614,187 @@ function user_count_login_failures($user, $reset = true) {
return $count;
}
/**
* Get a list of essential user navigation items.
*
* @param stdclass $user user object.
* @param moodle_page $page page object.
* @return stdClass $returnobj navigation information object, where:
*
* $returnobj->navitems array array of links where each link is a
* stdClass with fields url, title, and
* pix
* $returnobj->metadata array array of useful user metadata to be
* used when constructing navigation;
* fields include:
*
* ROLE FIELDS
* asotherrole bool whether viewing as another role
* rolename string name of the role
*
* USER FIELDS
* These fields are for the currently-logged in user, or for
* the user that the real user is currently logged in as.
*
* userid int the id of the user in question
* userfullname string the user's full name
* userprofileurl moodle_url the url of the user's profile
* useravatar string a HTML fragment - the rendered
* user_picture for this user
* userloginfail string an error string denoting the number
* of login failures since last login
*
* "REAL USER" FIELDS
* These fields are for when asotheruser is true, and
* correspond to the underlying "real user".
*
* asotheruser bool whether viewing as another user
* realuserid int the id of the user in question
* realuserfullname string the user's full name
* realuserprofileurl moodle_url the url of the user's profile
* realuseravatar string a HTML fragment - the rendered
* user_picture for this user
*
* MNET PROVIDER FIELDS
* asmnetuser bool whether viewing as a user from an
* MNet provider
* mnetidprovidername string name of the MNet provider
* mnetidproviderwwwroot string URL of the MNet provider
*/
function user_get_user_navigation_info($user, $page) {
global $OUTPUT, $DB, $SESSION, $CFG;
$returnobject = new stdClass();
$returnobject->navitems = array();
$returnobject->metadata = array();
$course = $page->course;
// Query the environment.
$context = context_course::instance($course->id);
// Get basic user metadata.
$returnobject->metadata['userid'] = $user->id;
$returnobject->metadata['userfullname'] = fullname($user, true);
$returnobject->metadata['userprofileurl'] = new moodle_url('/user/profile.php', array(
'id' => $user->id
));
$returnobject->metadata['useravatar'] = $OUTPUT->user_picture (
$user,
array(
'link' => false,
'visibletoscreenreaders' => false
)
);
// Build a list of items for a regular user.
// Query MNet status.
if ($returnobject->metadata['asmnetuser'] = is_mnet_remote_user($user)) {
$mnetidprovider = $DB->get_record('mnet_host', array('id' => $user->mnethostid));
$returnobject->metadata['mnetidprovidername'] = $mnetidprovider->name;
$returnobject->metadata['mnetidproviderwwwroot'] = $mnetidprovider->wwwroot;
}
// Did the user just log in?
if (isset($SESSION->justloggedin)) {
// Don't unset this flag as login_info still needs it.
if (!empty($CFG->displayloginfailures)) {
// We're already in /user/lib.php, so we don't need to include.
if ($count = user_count_login_failures($user)) {
// Get login failures string.
$a = new stdClass();
$a->attempts = html_writer::tag('span', $count, array('class' => 'value'));
$returnobject->metadata['userloginfail'] =
get_string('failedloginattempts', '', $a);
}
}
}
// Links: My Home.
$myhome = new stdClass();
$myhome->url = new moodle_url('/my/');
$myhome->title = get_string('mymoodle', 'admin');
$myhome->pix = "i/course";
$returnobject->navitems[] = $myhome;
// Links: My Profile.
$myprofile = new stdClass();
$myprofile->url = new moodle_url('/user/profile.php', array('id' => $user->id));
$myprofile->title = get_string('myprofile');
$myprofile->pix = "i/user";
$returnobject->navitems[] = $myprofile;
// Links: Role-return or logout link.
$lastobj = null;
$buildlogout = true;
$returnobject->metadata['asotherrole'] = false;
if (is_role_switched($course->id)) {
if ($role = $DB->get_record('role', array('id' => $user->access['rsw'][$context->path]))) {
// Build role-return link instead of logout link.
$rolereturn = new stdClass();
$rolereturn->url = new moodle_url('/course/switchrole.php', array(
'id' => $course->id,
'sesskey' => sesskey(),
'switchrole' => 0,
'returnurl' => $page->url->out_as_local_url(false)
));
$rolereturn->pix = "a/logout";
$rolereturn->title = get_string('switchrolereturn');
$lastobj = $rolereturn;
$returnobject->metadata['asotherrole'] = true;
$returnobject->metadata['rolename'] = role_get_name($role, $context);
$buildlogout = false;
}
}
if ($returnobject->metadata['asotheruser'] = \core\session\manager::is_loggedinas()) {
$realuser = \core\session\manager::get_realuser();
// Save values for the real user, as $user will be full of data for the
// user the user is disguised as.
$returnobject->metadata['realuserid'] = $realuser->id;
$returnobject->metadata['realuserfullname'] = fullname($realuser, true);
$returnobject->metadata['realuserprofileurl'] = new moodle_url('/user/profile.php', array(
'id' => $realuser->id
));
$returnobject->metadata['realuseravatar'] = $OUTPUT->user_picture (
$realuser,
array(
'link' => false,
'visibletoscreenreaders' => false
)
);
// Build a user-revert link.
$userrevert = new stdClass();
$userrevert->url = new moodle_url('/course/loginas.php', array(
'id' => $course->id,
'sesskey' => sesskey()
));
$userrevert->pix = "a/logout";
$userrevert->title = get_string('logout');
$lastobj = $userrevert;
$buildlogout = false;
}
if ($buildlogout) {
// Build a logout link.
$logout = new stdClass();
$logout->url = new moodle_url('/login/logout.php', array('sesskey' => sesskey()));
$logout->pix = "a/logout";
$logout->title = get_string('logout');
$lastobj = $logout;
}
// Add the last item to the list.
if (!is_null($lastobj)) {
$returnobject->navitems[] = $lastobj;
}
return $returnobject;
}