2009-08-28 08:47:31 +00:00
< ? php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
2012-05-07 12:57:42 +12:00
* This file contains classes used to manage the navigation structures within Moodle .
2009-08-28 08:47:31 +00:00
*
2010-07-25 13:35:05 +00:00
* @ since 2.0
* @ package core
* @ copyright 2009 Sam Hemelryk
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
2009-08-28 08:47:31 +00:00
*/
2010-07-25 13:35:05 +00:00
defined ( 'MOODLE_INTERNAL' ) || die ();
2009-10-12 05:39:32 +00:00
/**
2009-10-23 04:23:57 +00:00
* The name that will be used to separate the navigation cache within SESSION
2009-10-12 05:39:32 +00:00
*/
define ( 'NAVIGATION_CACHE_NAME' , 'navigation' );
2009-08-28 08:47:31 +00:00
/**
* This class is used to represent a node in a navigation tree
*
* This class is used to represent a node in a navigation tree within Moodle ,
* the tree could be one of global navigation , settings navigation , or the navbar .
* Each node can be one of two types either a Leaf ( default ) or a branch .
* When a node is first created it is created as a leaf , when / if children are added
* the node then becomes a branch .
*
2012-01-04 15:56:26 +08:00
* @ package core
* @ category navigation
2009-08-28 08:47:31 +00:00
* @ copyright 2009 Sam Hemelryk
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
2010-04-19 06:30:30 +00:00
class navigation_node implements renderable {
/** @var int Used to identify this node a leaf (default) 0 */
2010-02-18 05:57:20 +00:00
const NODETYPE_LEAF = 0 ;
2010-04-19 06:30:30 +00:00
/** @var int Used to identify this node a branch, happens with children 1 */
2009-08-28 08:47:31 +00:00
const NODETYPE_BRANCH = 1 ;
2010-04-19 06:30:30 +00:00
/** @var null Unknown node type null */
2009-08-28 08:47:31 +00:00
const TYPE_UNKNOWN = null ;
2010-04-19 06:30:30 +00:00
/** @var int System node type 0 */
const TYPE_ROOTNODE = 0 ;
/** @var int System node type 1 */
const TYPE_SYSTEM = 1 ;
/** @var int Category node type 10 */
2009-08-28 08:47:31 +00:00
const TYPE_CATEGORY = 10 ;
2013-02-07 11:04:24 +08:00
/** var int Category displayed in MyHome navigation node */
const TYPE_MY_CATEGORY = 11 ;
2010-04-19 06:30:30 +00:00
/** @var int Course node type 20 */
2009-08-28 08:47:31 +00:00
const TYPE_COURSE = 20 ;
2010-04-19 06:30:30 +00:00
/** @var int Course Structure node type 30 */
2010-02-18 05:57:20 +00:00
const TYPE_SECTION = 30 ;
2010-04-19 06:30:30 +00:00
/** @var int Activity node type, e.g. Forum, Quiz 40 */
2009-08-28 08:47:31 +00:00
const TYPE_ACTIVITY = 40 ;
2010-04-19 06:30:30 +00:00
/** @var int Resource node type, e.g. Link to a file, or label 50 */
2009-08-28 08:47:31 +00:00
const TYPE_RESOURCE = 50 ;
2010-04-19 06:30:30 +00:00
/** @var int A custom node type, default when adding without specifing type 60 */
2009-08-28 08:47:31 +00:00
const TYPE_CUSTOM = 60 ;
2010-04-19 06:30:30 +00:00
/** @var int Setting node type, used only within settings nav 70 */
2009-08-28 08:47:31 +00:00
const TYPE_SETTING = 70 ;
2010-04-19 06:30:30 +00:00
/** @var int Setting node type, used only within settings nav 80 */
2010-02-18 05:57:20 +00:00
const TYPE_USER = 80 ;
2010-04-19 06:30:30 +00:00
/** @var int Setting node type, used for containers of no importance 90 */
const TYPE_CONTAINER = 90 ;
2012-07-13 17:05:47 +01:00
/** var int Course the current user is not enrolled in */
const COURSE_OTHER = 0 ;
/** var int Course the current user is enrolled in but not viewing */
const COURSE_MY = 1 ;
/** var int Course the current user is currently viewing */
const COURSE_CURRENT = 2 ;
2009-08-28 08:47:31 +00:00
/** @var int Parameter to aid the coder in tracking [optional] */
public $id = null ;
/** @var string|int The identifier for the node, used to retrieve the node */
public $key = null ;
/** @var string The text to use for the node */
public $text = null ;
/** @var string Short text to use if requested [optional] */
public $shorttext = null ;
/** @var string The title attribute for an action if one is defined */
public $title = null ;
/** @var string A string that can be used to build a help button */
public $helpbutton = null ;
2010-04-19 06:30:30 +00:00
/** @var moodle_url|action_link|null An action for the node (link) */
2009-08-28 08:47:31 +00:00
public $action = null ;
2010-02-14 09:29:44 +00:00
/** @var pix_icon The path to an icon to use for this node */
2009-08-28 08:47:31 +00:00
public $icon = null ;
/** @var int See TYPE_* constants defined for this class */
public $type = self :: TYPE_UNKNOWN ;
/** @var int See NODETYPE_* constants defined for this class */
public $nodetype = self :: NODETYPE_LEAF ;
/** @var bool If set to true the node will be collapsed by default */
public $collapse = false ;
/** @var bool If set to true the node will be expanded by default */
public $forceopen = false ;
2010-04-19 06:30:30 +00:00
/** @var array An array of CSS classes for the node */
2009-08-28 08:47:31 +00:00
public $classes = array ();
2010-04-19 06:30:30 +00:00
/** @var navigation_node_collection An array of child nodes */
2009-08-28 08:47:31 +00:00
public $children = array ();
/** @var bool If set to true the node will be recognised as active */
public $isactive = false ;
2010-04-19 06:30:30 +00:00
/** @var bool If set to true the node will be dimmed */
2009-08-28 08:47:31 +00:00
public $hidden = false ;
/** @var bool If set to false the node will not be displayed */
public $display = true ;
/** @var bool If set to true then an HR will be printed before the node */
public $preceedwithhr = false ;
/** @var bool If set to true the the navigation bar should ignore this node */
public $mainnavonly = false ;
/** @var bool If set to true a title will be added to the action no matter what */
public $forcetitle = false ;
2011-06-23 11:29:26 +08:00
/** @var navigation_node A reference to the node parent, you should never set this directly you should always call set_parent */
2010-04-19 06:30:30 +00:00
public $parent = null ;
2010-04-23 04:21:33 +00:00
/** @var bool Override to not display the icon even if one is provided **/
public $hideicon = false ;
2012-11-04 11:06:49 +13:00
/** @var bool Set to true if we KNOW that this node can be expanded. */
public $isexpandable = false ;
2009-08-28 08:47:31 +00:00
/** @var array */
2009-09-10 03:50:51 +00:00
protected $namedtypes = array ( 0 => 'system' , 10 => 'category' , 20 => 'course' , 30 => 'structure' , 40 => 'activity' , 50 => 'resource' , 60 => 'custom' , 70 => 'setting' , 80 => 'user' );
2009-08-28 08:47:31 +00:00
/** @var moodle_url */
protected static $fullmeurl = null ;
2010-02-22 07:57:35 +00:00
/** @var bool toogles auto matching of active node */
public static $autofindactive = true ;
2012-01-11 16:56:03 +00:00
/** @var mixed If set to an int, that section will be included even if it has no activities */
public $includesectionnum = false ;
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* Constructs a new navigation_node
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ param array | string $properties Either an array of properties or a string to use
* as the text for the node
2009-08-28 08:47:31 +00:00
*/
public function __construct ( $properties ) {
if ( is_array ( $properties )) {
2010-04-19 06:30:30 +00:00
// Check the array for each property that we allow to set at construction.
// text - The main content for the node
// shorttext - A short text if required for the node
// icon - The icon to display for the node
// type - The type of the node
// key - The key to use to identify the node
// parent - A reference to the nodes parent
// action - The action to attribute to this node, usually a URL to link to
2009-08-28 08:47:31 +00:00
if ( array_key_exists ( 'text' , $properties )) {
$this -> text = $properties [ 'text' ];
}
if ( array_key_exists ( 'shorttext' , $properties )) {
$this -> shorttext = $properties [ 'shorttext' ];
}
2010-05-05 05:59:57 +00:00
if ( ! array_key_exists ( 'icon' , $properties )) {
2012-05-28 09:33:49 +08:00
$properties [ 'icon' ] = new pix_icon ( 'i/navigationitem' , '' );
2010-05-05 05:59:57 +00:00
}
$this -> icon = $properties [ 'icon' ];
if ( $this -> icon instanceof pix_icon ) {
if ( empty ( $this -> icon -> attributes [ 'class' ])) {
$this -> icon -> attributes [ 'class' ] = 'navicon' ;
} else {
$this -> icon -> attributes [ 'class' ] .= ' navicon' ;
2010-02-19 02:24:26 +00:00
}
2009-08-28 08:47:31 +00:00
}
if ( array_key_exists ( 'type' , $properties )) {
$this -> type = $properties [ 'type' ];
} else {
$this -> type = self :: TYPE_CUSTOM ;
}
if ( array_key_exists ( 'key' , $properties )) {
$this -> key = $properties [ 'key' ];
}
2010-04-19 06:30:30 +00:00
// This needs to happen last because of the check_if_active call that occurs
if ( array_key_exists ( 'action' , $properties )) {
$this -> action = $properties [ 'action' ];
if ( is_string ( $this -> action )) {
$this -> action = new moodle_url ( $this -> action );
}
if ( self :: $autofindactive ) {
$this -> check_if_active ();
}
}
2011-06-23 11:29:26 +08:00
if ( array_key_exists ( 'parent' , $properties )) {
$this -> set_parent ( $properties [ 'parent' ]);
}
2009-08-28 08:47:31 +00:00
} else if ( is_string ( $properties )) {
$this -> text = $properties ;
}
if ( $this -> text === null ) {
throw new coding_exception ( 'You must set the text for the node when you create it.' );
}
2010-04-19 06:30:30 +00:00
// Instantiate a new navigation node collection for this nodes children
$this -> children = new navigation_node_collection ();
2009-08-28 08:47:31 +00:00
}
2009-09-10 02:19:12 +00:00
/**
2010-04-19 06:30:30 +00:00
* Checks if this node is the active node .
2009-10-19 04:27:10 +00:00
*
2010-04-19 06:30:30 +00:00
* This is determined by comparing the action for the node against the
* defined URL for the page . A match will see this node marked as active .
2009-10-19 04:27:10 +00:00
*
2010-04-19 06:30:30 +00:00
* @ param int $strength One of URL_MATCH_EXACT , URL_MATCH_PARAMS , or URL_MATCH_BASE
* @ return bool
2009-08-28 08:47:31 +00:00
*/
2009-09-23 06:05:36 +00:00
public function check_if_active ( $strength = URL_MATCH_EXACT ) {
global $FULLME , $PAGE ;
2010-04-19 06:30:30 +00:00
// Set fullmeurl if it hasn't already been set
2009-08-28 08:47:31 +00:00
if ( self :: $fullmeurl == null ) {
2009-09-23 06:05:36 +00:00
if ( $PAGE -> has_set_url ()) {
2010-04-19 06:30:30 +00:00
self :: override_active_url ( new moodle_url ( $PAGE -> url ));
2009-09-23 06:05:36 +00:00
} else {
2010-04-19 06:30:30 +00:00
self :: override_active_url ( new moodle_url ( $FULLME ));
2009-08-28 08:47:31 +00:00
}
}
2009-09-23 06:05:36 +00:00
2010-04-19 06:30:30 +00:00
// Compare the action of this node against the fullmeurl
2009-09-23 06:05:36 +00:00
if ( $this -> action instanceof moodle_url && $this -> action -> compare ( self :: $fullmeurl , $strength )) {
2009-08-28 08:47:31 +00:00
$this -> make_active ();
return true ;
}
return false ;
}
2010-04-19 06:30:30 +00:00
2009-08-28 08:47:31 +00:00
/**
2010-08-05 08:17:27 +00:00
* This sets the URL that the URL of new nodes get compared to when locating
* the active node .
*
* The active node is the node that matches the URL set here . By default this
* is either $PAGE -> url or if that hasn ' t been set $FULLME .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ param moodle_url $url The url to use for the fullmeurl .
*/
public static function override_active_url ( moodle_url $url ) {
2010-08-06 16:12:31 +00:00
// Clone the URL, in case the calling script changes their URL later.
self :: $fullmeurl = new moodle_url ( $url );
2010-04-19 06:30:30 +00:00
}
/**
2011-05-23 17:34:17 +01:00
* Creates a navigation node , ready to add it as a child using add_node
* function . ( The created node needs to be added before you can use it . )
2010-04-19 06:30:30 +00:00
* @ param string $text
* @ param moodle_url | action_link $action
* @ param int $type
* @ param string $shorttext
* @ param string | int $key
* @ param pix_icon $icon
* @ return navigation_node
2009-08-28 08:47:31 +00:00
*/
2011-05-23 17:34:17 +01:00
public static function create ( $text , $action = null , $type = self :: TYPE_CUSTOM ,
$shorttext = null , $key = null , pix_icon $icon = null ) {
2010-04-19 06:30:30 +00:00
// Properties array used when creating the new navigation node
$itemarray = array (
'text' => $text ,
'type' => $type
);
// Set the action if one was provided
2009-08-28 08:47:31 +00:00
if ( $action !== null ) {
$itemarray [ 'action' ] = $action ;
}
2010-04-19 06:30:30 +00:00
// Set the shorttext if one was provided
2009-08-28 08:47:31 +00:00
if ( $shorttext !== null ) {
$itemarray [ 'shorttext' ] = $shorttext ;
}
2010-04-19 06:30:30 +00:00
// Set the icon if one was provided
2009-08-28 08:47:31 +00:00
if ( $icon !== null ) {
$itemarray [ 'icon' ] = $icon ;
}
2010-04-19 06:30:30 +00:00
// Set the key
2009-08-28 08:47:31 +00:00
$itemarray [ 'key' ] = $key ;
2011-05-23 17:34:17 +01:00
// Construct and return
return new navigation_node ( $itemarray );
}
/**
* Adds a navigation node as a child of this node .
*
* @ param string $text
* @ param moodle_url | action_link $action
* @ param int $type
* @ param string $shorttext
* @ param string | int $key
* @ param pix_icon $icon
* @ return navigation_node
*/
public function add ( $text , $action = null , $type = self :: TYPE_CUSTOM , $shorttext = null , $key = null , pix_icon $icon = null ) {
// Create child node
$childnode = self :: create ( $text , $action , $type , $shorttext , $key , $icon );
// Add the child to end and return
return $this -> add_node ( $childnode );
}
/**
* Adds a navigation node as a child of this one , given a $node object
* created using the create function .
* @ param navigation_node $childnode Node to add
2012-01-04 15:56:26 +08:00
* @ param string $beforekey
2011-05-23 17:34:17 +01:00
* @ return navigation_node The added node
*/
public function add_node ( navigation_node $childnode , $beforekey = null ) {
// First convert the nodetype for this node to a branch as it will now have children
if ( $this -> nodetype !== self :: NODETYPE_BRANCH ) {
$this -> nodetype = self :: NODETYPE_BRANCH ;
}
2010-04-19 06:30:30 +00:00
// Set the parent to this node
2011-06-23 11:29:26 +08:00
$childnode -> set_parent ( $this );
2011-05-23 17:34:17 +01:00
// Default the key to the number of children if not provided
if ( $childnode -> key === null ) {
$childnode -> key = $this -> children -> count ();
}
2010-04-19 06:30:30 +00:00
// Add the child using the navigation_node_collections add method
2011-05-23 17:34:17 +01:00
$node = $this -> children -> add ( $childnode , $beforekey );
// If added node is a category node or the user is logged in and it's a course
// then mark added node as a branch (makes it expandable by AJAX)
$type = $childnode -> type ;
2013-02-07 11:04:24 +08:00
if (( $type == self :: TYPE_CATEGORY ) || ( isloggedin () && ( $type == self :: TYPE_COURSE )) || ( $type == self :: TYPE_MY_CATEGORY )) {
2010-04-19 06:30:30 +00:00
$node -> nodetype = self :: NODETYPE_BRANCH ;
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
// If this node is hidden mark it's children as hidden also
2009-08-28 08:47:31 +00:00
if ( $this -> hidden ) {
2010-04-19 06:30:30 +00:00
$node -> hidden = true ;
2009-08-28 08:47:31 +00:00
}
2011-05-23 17:34:17 +01:00
// Return added node (reference returned by $this->children->add()
2010-04-19 06:30:30 +00:00
return $node ;
2009-08-28 08:47:31 +00:00
}
2011-06-18 16:23:53 +01:00
/**
* Return a list of all the keys of all the child nodes .
* @ return array the keys .
*/
public function get_children_key_list () {
return $this -> children -> get_key_list ();
}
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* Searches for a node of the given type with the given key .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* This searches this node plus all of its children , and their children ....
* If you know the node you are looking for is a child of this node then please
* use the get method instead .
*
* @ param int | string $key The key of the node we are looking for
* @ param int $type One of navigation_node :: TYPE_ *
* @ return navigation_node | false
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function find ( $key , $type ) {
return $this -> children -> find ( $key , $type );
}
/**
2012-01-04 15:56:26 +08:00
* Get the child of this node that has the given key + ( optional ) type .
2010-04-19 06:30:30 +00:00
*
* If you are looking for a node and want to search all children + thier children
* then please use the find method instead .
*
* @ param int | string $key The key of the node we are looking for
* @ param int $type One of navigation_node :: TYPE_ *
* @ return navigation_node | false
*/
public function get ( $key , $type = null ) {
return $this -> children -> get ( $key , $type );
}
/**
* Removes this node .
*
* @ return bool
*/
public function remove () {
return $this -> parent -> children -> remove ( $this -> key , $this -> type );
}
/**
* Checks if this node has or could have any children
*
* @ return bool Returns true if it has children or could have ( by AJAX expansion )
*/
public function has_children () {
2012-11-04 11:06:49 +13:00
return ( $this -> nodetype === navigation_node :: NODETYPE_BRANCH || $this -> children -> count () > 0 || $this -> isexpandable );
2010-04-19 06:30:30 +00:00
}
/**
* Marks this node as active and forces it open .
2010-08-05 08:17:27 +00:00
*
* Important : If you are here because you need to mark a node active to get
2012-02-29 00:56:41 +01:00
* the navigation to do what you want have you looked at { @ link navigation_node :: override_active_url ()} ?
2010-08-05 08:17:27 +00:00
* You can use it to specify a different URL to match the active navigation node on
* rather than having to locate and manually mark a node active .
2010-04-19 06:30:30 +00:00
*/
public function make_active () {
$this -> isactive = true ;
$this -> add_class ( 'active_tree_node' );
$this -> force_open ();
if ( $this -> parent !== null ) {
$this -> parent -> make_inactive ();
}
}
/**
* Marks a node as inactive and recusised back to the base of the tree
* doing the same to all parents .
*/
public function make_inactive () {
$this -> isactive = false ;
$this -> remove_class ( 'active_tree_node' );
if ( $this -> parent !== null ) {
$this -> parent -> make_inactive ();
2009-08-28 08:47:31 +00:00
}
}
/**
2010-04-19 06:30:30 +00:00
* Forces this node to be open and at the same time forces open all
* parents until the root node .
2009-11-01 11:31:16 +00:00
*
2010-04-19 06:30:30 +00:00
* Recursive .
*/
public function force_open () {
$this -> forceopen = true ;
if ( $this -> parent !== null ) {
$this -> parent -> force_open ();
}
}
/**
* Adds a CSS class to this node .
*
* @ param string $class
* @ return bool
2009-08-28 08:47:31 +00:00
*/
public function add_class ( $class ) {
if ( ! in_array ( $class , $this -> classes )) {
$this -> classes [] = $class ;
}
return true ;
}
/**
2010-04-19 06:30:30 +00:00
* Removes a CSS class from this node .
2009-08-28 08:47:31 +00:00
*
* @ param string $class
2010-04-19 06:30:30 +00:00
* @ return bool True if the class was successfully removed .
2009-08-28 08:47:31 +00:00
*/
public function remove_class ( $class ) {
if ( in_array ( $class , $this -> classes )) {
$key = array_search ( $class , $this -> classes );
if ( $key !== false ) {
unset ( $this -> classes [ $key ]);
return true ;
}
}
return false ;
}
/**
2010-04-19 06:30:30 +00:00
* Sets the title for this node and forces Moodle to utilise it .
* @ param string $title
*/
public function title ( $title ) {
$this -> title = $title ;
$this -> forcetitle = true ;
}
/**
* Resets the page specific information on this node if it is being unserialised .
*/
public function __wakeup (){
$this -> forceopen = false ;
$this -> isactive = false ;
$this -> remove_class ( 'active_tree_node' );
}
/**
* Checks if this node or any of its children contain the active node .
2010-05-30 22:56:29 +00:00
*
2010-04-19 06:30:30 +00:00
* Recursive .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ return bool
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function contains_active_node () {
if ( $this -> isactive ) {
2009-08-28 08:47:31 +00:00
return true ;
} else {
2010-04-19 06:30:30 +00:00
foreach ( $this -> children as $child ) {
if ( $child -> isactive || $child -> contains_active_node ()) {
return true ;
}
}
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
return false ;
2009-08-28 08:47:31 +00:00
}
/**
2010-04-19 06:30:30 +00:00
* Finds the active node .
*
* Searches this nodes children plus all of the children for the active node
* and returns it if found .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* Recursive .
*
* @ return navigation_node | false
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function find_active_node () {
if ( $this -> isactive ) {
return $this ;
} else {
2009-08-28 08:47:31 +00:00
foreach ( $this -> children as & $child ) {
2010-04-19 06:30:30 +00:00
$outcome = $child -> find_active_node ();
if ( $outcome !== false ) {
return $outcome ;
2009-08-28 08:47:31 +00:00
}
}
}
2010-04-19 06:30:30 +00:00
return false ;
2009-08-28 08:47:31 +00:00
}
2010-05-19 07:57:00 +00:00
/**
* Searches all children for the best matching active node
* @ return navigation_node | false
*/
public function search_for_active_node () {
if ( $this -> check_if_active ( URL_MATCH_BASE )) {
return $this ;
} else {
foreach ( $this -> children as & $child ) {
$outcome = $child -> search_for_active_node ();
if ( $outcome !== false ) {
return $outcome ;
}
}
}
return false ;
}
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* Gets the content for this node .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ param bool $shorttext If true shorttext is used rather than the normal text
* @ return string
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function get_content ( $shorttext = false ) {
2009-08-28 08:47:31 +00:00
if ( $shorttext && $this -> shorttext !== null ) {
2010-04-19 06:30:30 +00:00
return format_string ( $this -> shorttext );
2009-08-28 08:47:31 +00:00
} else {
2010-04-19 06:30:30 +00:00
return format_string ( $this -> text );
2009-10-14 09:27:07 +00:00
}
2010-04-19 06:30:30 +00:00
}
2009-10-14 09:27:07 +00:00
2010-04-19 06:30:30 +00:00
/**
* Gets the title to use for this node .
2010-05-30 22:56:29 +00:00
*
2010-04-19 06:30:30 +00:00
* @ return string
*/
public function get_title () {
2010-05-12 08:10:59 +00:00
if ( $this -> forcetitle || $this -> action != null ){
2010-04-19 06:30:30 +00:00
return $this -> title ;
} else {
2010-02-11 18:50:55 +00:00
return '' ;
}
2009-08-28 08:47:31 +00:00
}
2009-11-01 11:31:16 +00:00
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* Gets the CSS class to add to this node to describe its type
2010-05-30 22:56:29 +00:00
*
2009-08-28 08:47:31 +00:00
* @ return string
*/
public function get_css_type () {
if ( array_key_exists ( $this -> type , $this -> namedtypes )) {
return 'type_' . $this -> namedtypes [ $this -> type ];
}
return 'type_unknown' ;
}
/**
2010-04-19 06:30:30 +00:00
* Finds all nodes that are expandable by AJAX
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ param array $expandable An array by reference to populate with expandable nodes .
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function find_expandable ( array & $expandable ) {
foreach ( $this -> children as & $child ) {
2012-11-04 11:06:49 +13:00
if ( $child -> display && $child -> has_children () && $child -> children -> count () == 0 ) {
2010-04-19 06:30:30 +00:00
$child -> id = 'expandable_branch_' . ( count ( $expandable ) + 1 );
$this -> add_class ( 'canexpand' );
2010-12-23 16:55:52 +08:00
$expandable [] = array ( 'id' => $child -> id , 'key' => $child -> key , 'type' => $child -> type );
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
$child -> find_expandable ( $expandable );
2009-08-28 08:47:31 +00:00
}
}
2010-04-21 09:44:16 +00:00
2010-05-13 09:57:43 +00:00
/**
* Finds all nodes of a given type ( recursive )
*
2012-01-04 15:56:26 +08:00
* @ param int $type One of navigation_node :: TYPE_ *
2010-05-13 09:57:43 +00:00
* @ return array
*/
2010-04-21 09:44:16 +00:00
public function find_all_of_type ( $type ) {
$nodes = $this -> children -> type ( $type );
foreach ( $this -> children as & $node ) {
$childnodes = $node -> find_all_of_type ( $type );
$nodes = array_merge ( $nodes , $childnodes );
}
return $nodes ;
}
2010-05-21 03:15:48 +00:00
/**
* Removes this node if it is empty
*/
public function trim_if_empty () {
if ( $this -> children -> count () == 0 ) {
$this -> remove ();
}
}
/**
* Creates a tab representation of this nodes children that can be used
* with print_tabs to produce the tabs on a page .
*
* call_user_func_array ( 'print_tabs' , $node -> get_tabs_array ());
*
* @ param array $inactive
* @ param bool $return
* @ return array Array ( tabs , selected , inactive , activated , return )
*/
public function get_tabs_array ( array $inactive = array (), $return = false ) {
$tabs = array ();
$rows = array ();
$selected = null ;
$activated = array ();
foreach ( $this -> children as $node ) {
$tabs [] = new tabobject ( $node -> key , $node -> action , $node -> get_content (), $node -> get_title ());
if ( $node -> contains_active_node ()) {
if ( $node -> children -> count () > 0 ) {
$activated [] = $node -> key ;
foreach ( $node -> children as $child ) {
if ( $child -> contains_active_node ()) {
$selected = $child -> key ;
}
$rows [] = new tabobject ( $child -> key , $child -> action , $child -> get_content (), $child -> get_title ());
}
} else {
$selected = $node -> key ;
}
}
}
return array ( array ( $tabs , $rows ), $selected , $inactive , $activated , $return );
}
2011-06-23 11:29:26 +08:00
/**
* Sets the parent for this node and if this node is active ensures that the tree is properly
* adjusted as well .
*
* @ param navigation_node $parent
*/
public function set_parent ( navigation_node $parent ) {
// Set the parent (thats the easy part)
$this -> parent = $parent ;
// Check if this node is active (this is checked during construction)
if ( $this -> isactive ) {
// Force all of the parent nodes open so you can see this node
$this -> parent -> force_open ();
// Make all parents inactive so that its clear where we are.
$this -> parent -> make_inactive ();
}
}
2013-02-19 11:38:43 +13:00
/**
* Hides the node and any children it has .
*
* @ since 2.5
2013-04-09 12:06:26 +12:00
* @ param array $typestohide Optional . An array of node types that should be hidden .
* If null all nodes will be hidden .
* If an array is given then nodes will only be hidden if their type mtatches an element in the array .
* e . g . array ( navigation_node :: TYPE_COURSE ) would hide only course nodes .
*/
public function hide ( array $typestohide = null ) {
if ( $typestohide === null || in_array ( $this -> type , $typestohide )) {
$this -> display = false ;
if ( $this -> has_children ()) {
foreach ( $this -> children as $child ) {
$child -> hide ( $typestohide );
}
2013-02-19 11:38:43 +13:00
}
}
}
2010-04-19 06:30:30 +00:00
}
2009-08-28 08:47:31 +00:00
2010-04-19 06:30:30 +00:00
/**
* Navigation node collection
*
* This class is responsible for managing a collection of navigation nodes .
* It is required because a node ' s unique identifier is a combination of both its
* key and its type .
*
* Originally an array was used with a string key that was a combination of the two
* however it was decided that a better solution would be to use a class that
* implements the standard IteratorAggregate interface .
*
2012-01-04 15:56:26 +08:00
* @ package core
* @ category navigation
2010-04-19 06:30:30 +00:00
* @ copyright 2010 Sam Hemelryk
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
class navigation_node_collection implements IteratorAggregate {
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* A multidimensional array to where the first key is the type and the second
* key is the nodes key .
* @ var array
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
protected $collection = array ();
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* An array that contains references to nodes in the same order they were added .
* This is maintained as a progressive array .
* @ var array
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
protected $orderedcollection = array ();
2009-11-04 07:23:19 +00:00
/**
2010-04-19 06:30:30 +00:00
* A reference to the last node that was added to the collection
* @ var navigation_node
2009-11-04 07:23:19 +00:00
*/
2010-04-19 06:30:30 +00:00
protected $last = null ;
2009-10-14 09:08:43 +00:00
/**
2010-04-19 06:30:30 +00:00
* The total number of items added to this array .
* @ var int
2009-10-14 09:08:43 +00:00
*/
2010-04-19 06:30:30 +00:00
protected $count = 0 ;
2011-06-18 16:23:53 +01:00
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* Adds a navigation node to the collection
2009-08-28 08:47:31 +00:00
*
2011-05-23 17:34:17 +01:00
* @ param navigation_node $node Node to add
* @ param string $beforekey If specified , adds before a node with this key ,
* otherwise adds at end
* @ return navigation_node Added node
2009-08-28 08:47:31 +00:00
*/
2011-05-23 17:34:17 +01:00
public function add ( navigation_node $node , $beforekey = null ) {
2010-04-19 06:30:30 +00:00
global $CFG ;
$key = $node -> key ;
$type = $node -> type ;
2011-05-23 17:34:17 +01:00
2010-04-19 06:30:30 +00:00
// First check we have a 2nd dimension for this type
if ( ! array_key_exists ( $type , $this -> orderedcollection )) {
$this -> orderedcollection [ $type ] = array ();
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
// Check for a collision and report if debugging is turned on
if ( $CFG -> debug && array_key_exists ( $key , $this -> orderedcollection [ $type ])) {
debugging ( 'Navigation node intersect: Adding a node that already exists ' . $key , DEBUG_DEVELOPER );
2009-08-28 08:47:31 +00:00
}
2011-05-23 17:34:17 +01:00
// Find the key to add before
$newindex = $this -> count ;
$last = true ;
if ( $beforekey !== null ) {
foreach ( $this -> collection as $index => $othernode ) {
if ( $othernode -> key === $beforekey ) {
$newindex = $index ;
$last = false ;
break ;
}
}
if ( $newindex === $this -> count ) {
debugging ( 'Navigation node add_before: Reference node not found ' . $beforekey .
2011-06-18 16:23:53 +01:00
', options: ' . implode ( ' ' , $this -> get_key_list ()), DEBUG_DEVELOPER );
2011-05-23 17:34:17 +01:00
}
}
// Add the node to the appropriate place in the by-type structure (which
// is not ordered, despite the variable name)
2010-04-19 06:30:30 +00:00
$this -> orderedcollection [ $type ][ $key ] = $node ;
2011-05-23 17:34:17 +01:00
if ( ! $last ) {
// Update existing references in the ordered collection (which is the
// one that isn't called 'ordered') to shuffle them along if required
for ( $oldindex = $this -> count ; $oldindex > $newindex ; $oldindex -- ) {
$this -> collection [ $oldindex ] = $this -> collection [ $oldindex - 1 ];
}
}
2010-04-19 06:30:30 +00:00
// Add a reference to the node to the progressive collection.
2012-05-06 13:31:55 +02:00
$this -> collection [ $newindex ] = $this -> orderedcollection [ $type ][ $key ];
2010-04-19 06:30:30 +00:00
// Update the last property to a reference to this new node.
2012-05-06 13:31:55 +02:00
$this -> last = $this -> orderedcollection [ $type ][ $key ];
2011-05-30 10:05:59 +08:00
2011-05-23 17:34:17 +01:00
// Reorder the array by index if needed
if ( ! $last ) {
ksort ( $this -> collection );
}
2010-04-19 06:30:30 +00:00
$this -> count ++ ;
// Return the reference to the now added node
2011-05-23 17:34:17 +01:00
return $node ;
2009-08-28 08:47:31 +00:00
}
2011-06-18 16:23:53 +01:00
/**
* Return a list of all the keys of all the nodes .
* @ return array the keys .
*/
public function get_key_list () {
$keys = array ();
foreach ( $this -> collection as $node ) {
$keys [] = $node -> key ;
}
return $keys ;
}
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* Fetches a node from this collection .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ param string | int $key The key of the node we want to find .
* @ param int $type One of navigation_node :: TYPE_ *.
* @ return navigation_node | null
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function get ( $key , $type = null ) {
if ( $type !== null ) {
// If the type is known then we can simply check and fetch
if ( ! empty ( $this -> orderedcollection [ $type ][ $key ])) {
return $this -> orderedcollection [ $type ][ $key ];
}
} else {
// Because we don't know the type we look in the progressive array
foreach ( $this -> collection as $node ) {
if ( $node -> key === $key ) {
return $node ;
2009-08-28 08:47:31 +00:00
}
}
}
return false ;
}
2011-06-18 16:23:53 +01:00
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* Searches for a node with matching key and type .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* This function searches both the nodes in this collection and all of
* the nodes in each collection belonging to the nodes in this collection .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* Recursive .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ param string | int $key The key of the node we want to find .
* @ param int $type One of navigation_node :: TYPE_ *.
* @ return navigation_node | null
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function find ( $key , $type = null ) {
if ( $type !== null && array_key_exists ( $type , $this -> orderedcollection ) && array_key_exists ( $key , $this -> orderedcollection [ $type ])) {
return $this -> orderedcollection [ $type ][ $key ];
} else {
$nodes = $this -> getIterator ();
// Search immediate children first
foreach ( $nodes as & $node ) {
2010-07-23 02:59:13 +00:00
if ( $node -> key === $key && ( $type === null || $type === $node -> type )) {
2010-04-19 06:30:30 +00:00
return $node ;
2009-10-13 02:39:05 +00:00
}
2010-04-19 06:30:30 +00:00
}
// Now search each childs children
foreach ( $nodes as & $node ) {
$result = $node -> children -> find ( $key , $type );
if ( $result !== false ) {
return $result ;
2009-10-13 02:39:05 +00:00
}
2009-08-28 08:47:31 +00:00
}
}
return false ;
}
2009-10-13 02:39:05 +00:00
/**
2010-04-19 06:30:30 +00:00
* Fetches the last node that was added to this collection
2010-05-30 22:56:29 +00:00
*
2010-04-19 06:30:30 +00:00
* @ return navigation_node
2009-10-13 02:39:05 +00:00
*/
2010-04-19 06:30:30 +00:00
public function last () {
return $this -> last ;
}
2011-06-18 16:23:53 +01:00
2010-04-19 06:30:30 +00:00
/**
* Fetches all nodes of a given type from this collection
2012-01-04 15:56:26 +08:00
*
* @ param string | int $type node type being searched for .
* @ return array ordered collection
2010-04-19 06:30:30 +00:00
*/
public function type ( $type ) {
if ( ! array_key_exists ( $type , $this -> orderedcollection )) {
$this -> orderedcollection [ $type ] = array ();
2009-10-13 02:39:05 +00:00
}
2010-04-19 06:30:30 +00:00
return $this -> orderedcollection [ $type ];
2009-10-13 02:39:05 +00:00
}
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* Removes the node with the given key and type from the collection
2009-08-28 08:47:31 +00:00
*
2012-01-04 15:56:26 +08:00
* @ param string | int $key The key of the node we want to find .
2010-04-19 06:30:30 +00:00
* @ param int $type
* @ return bool
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function remove ( $key , $type = null ) {
$child = $this -> get ( $key , $type );
if ( $child !== false ) {
foreach ( $this -> collection as $colkey => $node ) {
2013-05-31 11:45:47 +10:00
if ( $node -> key === $key && $node -> type == $type ) {
2010-04-19 06:30:30 +00:00
unset ( $this -> collection [ $colkey ]);
2013-05-31 11:48:32 +10:00
$this -> collection = array_values ( $this -> collection );
2010-04-19 06:30:30 +00:00
break ;
}
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
unset ( $this -> orderedcollection [ $child -> type ][ $child -> key ]);
$this -> count -- ;
return true ;
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
return false ;
2009-08-28 08:47:31 +00:00
}
2009-08-31 03:58:17 +00:00
/**
2010-04-19 06:30:30 +00:00
* Gets the number of nodes in this collection
2011-06-24 16:42:41 +08:00
*
* This option uses an internal count rather than counting the actual options to avoid
* a performance hit through the count function .
*
2010-04-19 06:30:30 +00:00
* @ return int
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function count () {
2011-06-24 16:42:41 +08:00
return $this -> count ;
2009-08-28 08:47:31 +00:00
}
/**
2010-04-19 06:30:30 +00:00
* Gets an array iterator for the collection .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* This is required by the IteratorAggregator interface and is used by routines
* such as the foreach loop .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ return ArrayIterator
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function getIterator () {
return new ArrayIterator ( $this -> collection );
2009-08-28 08:47:31 +00:00
}
}
/**
* The global navigation class used for ... the global navigation
*
* This class is used by PAGE to store the global navigation for the site
* and is then used by the settings nav and navbar to save on processing and DB calls
*
* See
2012-02-29 00:56:41 +01:00
* { @ link lib / pagelib . php } { @ link moodle_page :: initialise_theme_and_output ()}
2012-01-04 15:56:26 +08:00
* { @ link lib / ajax / getnavbranch . php } Called by ajax
2009-08-28 08:47:31 +00:00
*
2012-01-04 15:56:26 +08:00
* @ package core
* @ category navigation
2009-08-28 08:47:31 +00:00
* @ copyright 2009 Sam Hemelryk
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
class global_navigation extends navigation_node {
2012-01-04 15:56:26 +08:00
/** @var moodle_page The Moodle page this navigation object belongs to. */
2010-04-19 06:30:30 +00:00
protected $page ;
2012-01-04 15:56:26 +08:00
/** @var bool switch to let us know if the navigation object is initialised*/
2009-08-28 08:47:31 +00:00
protected $initialised = false ;
2012-01-04 15:56:26 +08:00
/** @var array An array of course information */
2010-04-19 06:30:30 +00:00
protected $mycourses = array ();
2012-01-04 15:56:26 +08:00
/** @var array An array for containing root navigation nodes */
2010-04-19 06:30:30 +00:00
protected $rootnodes = array ();
2012-01-04 15:56:26 +08:00
/** @var bool A switch for whether to show empty sections in the navigation */
2012-04-30 11:46:15 +08:00
protected $showemptysections = true ;
2012-01-04 15:56:26 +08:00
/** @var bool A switch for whether courses should be shown within categories on the navigation. */
2011-08-29 13:45:04 +12:00
protected $showcategories = null ;
2012-11-04 11:06:49 +13:00
/** @var null@var bool A switch for whether or not to show categories in the my courses branch. */
protected $showmycategories = null ;
2012-01-04 15:56:26 +08:00
/** @var array An array of stdClasses for users that the navigation is extended for */
2009-12-23 01:22:48 +00:00
protected $extendforuser = array ();
2010-04-19 06:30:30 +00:00
/** @var navigation_cache */
protected $cache ;
2012-01-04 15:56:26 +08:00
/** @var array An array of course ids that are present in the navigation */
2010-04-19 06:30:30 +00:00
protected $addedcourses = array ();
2011-11-15 17:12:06 +13:00
/** @var bool */
protected $allcategoriesloaded = false ;
2012-01-04 15:56:26 +08:00
/** @var array An array of category ids that are included in the navigation */
2011-06-24 16:42:41 +08:00
protected $addedcategories = array ();
2012-01-04 15:56:26 +08:00
/** @var int expansion limit */
2010-04-21 09:44:16 +00:00
protected $expansionlimit = 0 ;
2012-01-04 15:56:26 +08:00
/** @var int userid to allow parent to see child's profile page navigation */
2011-05-03 15:41:34 +08:00
protected $useridtouseforparentchecks = 0 ;
2010-04-21 09:44:16 +00:00
2011-11-15 17:12:06 +13:00
/** Used when loading categories to load all top level categories [parent = 0] **/
const LOAD_ROOT_CATEGORIES = 0 ;
/** Used when loading categories to load all categories **/
const LOAD_ALL_CATEGORIES = - 1 ;
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* Constructs a new global navigation
*
* @ param moodle_page $page The page this navigation object belongs to
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function __construct ( moodle_page $page ) {
2010-05-13 09:57:43 +00:00
global $CFG , $SITE , $USER ;
2010-04-19 06:30:30 +00:00
2009-08-28 08:47:31 +00:00
if ( during_initial_install ()) {
2010-04-19 06:30:30 +00:00
return ;
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
2010-05-13 09:57:43 +00:00
if ( get_home_page () == HOMEPAGE_SITE ) {
// We are using the site home for the root element
$properties = array (
'key' => 'home' ,
'type' => navigation_node :: TYPE_SYSTEM ,
'text' => get_string ( 'home' ),
'action' => new moodle_url ( '/' )
);
} else {
// We are using the users my moodle for the root element
$properties = array (
'key' => 'myhome' ,
'type' => navigation_node :: TYPE_SYSTEM ,
'text' => get_string ( 'myhome' ),
'action' => new moodle_url ( '/my/' )
);
2010-04-22 07:42:04 +00:00
}
2010-05-13 09:57:43 +00:00
2012-01-04 15:56:26 +08:00
// Use the parents constructor.... good good reuse
2010-04-19 06:30:30 +00:00
parent :: __construct ( $properties );
// Initalise and set defaults
$this -> page = $page ;
2009-08-28 08:47:31 +00:00
$this -> forceopen = true ;
2009-10-12 05:39:32 +00:00
$this -> cache = new navigation_cache ( NAVIGATION_CACHE_NAME );
2009-08-28 08:47:31 +00:00
}
2011-04-15 18:04:45 +08:00
/**
* Mutator to set userid to allow parent to see child ' s profile
* page navigation . See MDL - 25805 for initial issue . Linked to it
* is an issue explaining why this is a REALLY UGLY HACK thats not
* for you to use !
*
2011-07-04 16:42:55 +02:00
* @ param int $userid userid of profile page that parent wants to navigate around .
2011-04-15 18:04:45 +08:00
*/
2011-05-03 15:41:34 +08:00
public function set_userid_for_parent_checks ( $userid ) {
$this -> useridtouseforparentchecks = $userid ;
2011-04-15 18:04:45 +08:00
}
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* Initialises the navigation object .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* This causes the navigation object to look at the current state of the page
* that it is associated with and then load the appropriate content .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* This should only occur the first time that the navigation structure is utilised
* which will normally be either when the navbar is called to be displayed or
* when a block makes use of it .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ return bool
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function initialise () {
2012-11-04 11:06:49 +13:00
global $CFG , $SITE , $USER ;
// Check if it has already been initialised
2009-08-28 08:47:31 +00:00
if ( $this -> initialised || during_initial_install ()) {
return true ;
}
2010-06-10 07:47:59 +00:00
$this -> initialised = true ;
2010-04-19 06:30:30 +00:00
// Set up the five base root nodes. These are nodes where we will put our
// content and are as follows:
2012-11-04 11:06:49 +13:00
// site: Navigation for the front page.
// myprofile: User profile information goes here.
// currentcourse: The course being currently viewed.
// mycourses: The users courses get added here.
// courses: Additional courses are added here.
// users: Other users information loaded here.
2010-04-19 06:30:30 +00:00
$this -> rootnodes = array ();
2010-05-13 09:57:43 +00:00
if ( get_home_page () == HOMEPAGE_SITE ) {
2010-05-14 02:55:46 +00:00
// The home element should be my moodle because the root element is the site
2010-06-03 08:11:46 +00:00
if ( isloggedin () && ! isguestuser ()) { // Makes no sense if you aren't logged in
2011-06-24 16:42:41 +08:00
$this -> rootnodes [ 'home' ] = $this -> add ( get_string ( 'myhome' ), new moodle_url ( '/my/' ), self :: TYPE_SETTING , null , 'home' );
2010-05-14 02:55:46 +00:00
}
2010-05-13 09:57:43 +00:00
} else {
// The home element should be the site because the root node is my moodle
2011-06-24 16:42:41 +08:00
$this -> rootnodes [ 'home' ] = $this -> add ( get_string ( 'sitehome' ), new moodle_url ( '/' ), self :: TYPE_SETTING , null , 'home' );
2012-03-30 12:14:41 +08:00
if ( ! empty ( $CFG -> defaulthomepage ) && ( $CFG -> defaulthomepage == HOMEPAGE_MY )) {
2010-05-13 09:57:43 +00:00
// We need to stop automatic redirection
$this -> rootnodes [ 'home' ] -> action -> param ( 'redirect' , '0' );
}
}
2012-11-04 11:06:49 +13:00
$this -> rootnodes [ 'site' ] = $this -> add_course ( $SITE );
2011-06-24 16:42:41 +08:00
$this -> rootnodes [ 'myprofile' ] = $this -> add ( get_string ( 'myprofile' ), null , self :: TYPE_USER , null , 'myprofile' );
2012-07-13 17:05:47 +01:00
$this -> rootnodes [ 'currentcourse' ] = $this -> add ( get_string ( 'currentcourse' ), null , self :: TYPE_ROOTNODE , null , 'currentcourse' );
2013-02-19 12:12:24 +13:00
$this -> rootnodes [ 'mycourses' ] = $this -> add ( get_string ( 'mycourses' ), new moodle_url ( '/my/' ), self :: TYPE_ROOTNODE , null , 'mycourses' );
2012-11-04 11:06:49 +13:00
$this -> rootnodes [ 'courses' ] = $this -> add ( get_string ( 'courses' ), new moodle_url ( '/course/index.php' ), self :: TYPE_ROOTNODE , null , 'courses' );
$this -> rootnodes [ 'users' ] = $this -> add ( get_string ( 'users' ), null , self :: TYPE_ROOTNODE , null , 'users' );
2010-04-19 06:30:30 +00:00
2012-04-19 10:27:53 +12:00
// We always load the frontpage course to ensure it is available without
// JavaScript enabled.
$this -> add_front_page_course_essentials ( $this -> rootnodes [ 'site' ], $SITE );
$this -> load_course_sections ( $SITE , $this -> rootnodes [ 'site' ]);
2012-11-04 11:06:49 +13:00
$course = $this -> page -> course ;
2011-11-15 17:12:06 +13:00
// $issite gets set to true if the current pages course is the sites frontpage course
2012-05-07 12:57:42 +12:00
$issite = ( $this -> page -> course -> id == $SITE -> id );
2012-11-04 11:06:49 +13:00
// Determine if the user is enrolled in any course.
$enrolledinanycourse = enrol_user_sees_own_courses ();
2010-05-13 09:57:43 +00:00
2012-11-04 11:06:49 +13:00
$this -> rootnodes [ 'currentcourse' ] -> mainnavonly = true ;
if ( $enrolledinanycourse ) {
$this -> rootnodes [ 'mycourses' ] -> isexpandable = true ;
if ( $CFG -> navshowallcourses ) {
// When we show all courses we need to show both the my courses and the regular courses branch.
$this -> rootnodes [ 'courses' ] -> isexpandable = true ;
2011-11-15 17:12:06 +13:00
}
2012-11-04 11:06:49 +13:00
} else {
$this -> rootnodes [ 'courses' ] -> isexpandable = true ;
2010-04-19 06:30:30 +00:00
}
2013-02-19 12:12:24 +13:00
if ( $this -> rootnodes [ 'mycourses' ] -> isactive ) {
$this -> load_courses_enrolled ();
}
2010-08-05 02:22:48 +00:00
$canviewcourseprofile = true ;
2012-02-17 14:36:16 +13:00
// Next load context specific content into the navigation
switch ( $this -> page -> context -> contextlevel ) {
case CONTEXT_SYSTEM :
2012-11-04 11:06:49 +13:00
// Nothing left to do here I feel.
2012-02-17 14:36:16 +13:00
break ;
case CONTEXT_COURSECAT :
2012-11-04 11:06:49 +13:00
// This is essential, we must load categories.
$this -> load_all_categories ( $this -> page -> context -> instanceid , true );
2012-02-17 14:36:16 +13:00
break ;
case CONTEXT_BLOCK :
case CONTEXT_COURSE :
if ( $issite ) {
2012-11-04 11:06:49 +13:00
// Nothing left to do here.
2011-11-29 11:01:50 +13:00
break ;
2012-02-17 14:36:16 +13:00
}
2011-04-15 18:04:45 +08:00
2012-07-13 17:05:47 +01:00
// Load the course associated with the current page into the navigation.
$coursenode = $this -> add_course ( $course , false , self :: COURSE_CURRENT );
2012-02-17 14:36:16 +13:00
// If the course wasn't added then don't try going any further.
if ( ! $coursenode ) {
$canviewcourseprofile = false ;
break ;
}
2011-06-24 16:42:41 +08:00
2012-02-17 14:36:16 +13:00
// If the user is not enrolled then we only want to show the
// course node and not populate it.
// Not enrolled, can't view, and hasn't switched roles
if ( ! can_access_course ( $course )) {
2012-11-04 11:06:49 +13:00
// Very ugly hack - do not force "parents" to enrol into course their child is enrolled in,
2012-02-17 14:36:16 +13:00
// this hack has been propagated from user/view.php to display the navigation node. (MDL-25805)
2012-11-04 11:06:49 +13:00
if ( ! $this -> current_user_is_parent_role ()) {
2011-11-29 11:01:50 +13:00
$coursenode -> make_active ();
2012-02-17 14:36:16 +13:00
$canviewcourseprofile = false ;
break ;
}
}
2012-07-13 17:05:47 +01:00
2012-02-17 14:36:16 +13:00
// Add the essentials such as reports etc...
$this -> add_course_essentials ( $coursenode , $course );
2012-09-18 09:57:37 +08:00
// Extend course navigation with it's sections/activities
$this -> load_course_sections ( $course , $coursenode );
2012-02-17 14:36:16 +13:00
if ( ! $coursenode -> contains_active_node () && ! $coursenode -> search_for_active_node ()) {
$coursenode -> make_active ();
}
2012-07-13 17:05:47 +01:00
2012-02-17 14:36:16 +13:00
break ;
case CONTEXT_MODULE :
if ( $issite ) {
// If this is the site course then most information will have
// already been loaded.
// However we need to check if there is more content that can
// yet be loaded for the specific module instance.
2012-10-31 12:52:32 +08:00
$activitynode = $this -> rootnodes [ 'site' ] -> find ( $this -> page -> cm -> id , navigation_node :: TYPE_ACTIVITY );
2012-02-17 14:36:16 +13:00
if ( $activitynode ) {
$this -> load_activity ( $this -> page -> cm , $this -> page -> course , $activitynode );
2011-11-29 11:01:50 +13:00
}
2011-07-13 13:39:29 +08:00
break ;
2012-02-17 14:36:16 +13:00
}
2011-07-13 13:39:29 +08:00
2012-02-17 14:36:16 +13:00
$course = $this -> page -> course ;
$cm = $this -> page -> cm ;
2010-08-05 02:22:48 +00:00
2012-02-17 14:36:16 +13:00
// Load the course associated with the page into the navigation
2012-11-04 11:06:49 +13:00
$coursenode = $this -> add_course ( $course , false , self :: COURSE_CURRENT );
2011-11-29 11:01:50 +13:00
2012-02-17 14:36:16 +13:00
// If the course wasn't added then don't try going any further.
if ( ! $coursenode ) {
$canviewcourseprofile = false ;
break ;
}
// If the user is not enrolled then we only want to show the
// course node and not populate it.
if ( ! can_access_course ( $course )) {
$coursenode -> make_active ();
$canviewcourseprofile = false ;
break ;
}
2011-11-29 11:01:50 +13:00
2012-02-17 14:36:16 +13:00
$this -> add_course_essentials ( $coursenode , $course );
2011-11-29 11:01:50 +13:00
2012-02-17 14:36:16 +13:00
// Load the course sections into the page
2012-10-31 12:52:32 +08:00
$this -> load_course_sections ( $course , $coursenode , null , $cm );
$activity = $coursenode -> find ( $cm -> id , navigation_node :: TYPE_ACTIVITY );
// Finally load the cm specific navigaton information
$this -> load_activity ( $cm , $course , $activity );
// Check if we have an active ndoe
if ( ! $activity -> contains_active_node () && ! $activity -> search_for_active_node ()) {
// And make the activity node active.
$activity -> make_active ();
2012-02-17 14:36:16 +13:00
}
break ;
case CONTEXT_USER :
if ( $issite ) {
// The users profile information etc is already loaded
// for the front page.
2012-03-19 19:32:15 +13:00
break ;
2012-02-17 14:36:16 +13:00
}
$course = $this -> page -> course ;
// Load the course associated with the user into the navigation
2012-11-04 11:06:49 +13:00
$coursenode = $this -> add_course ( $course , false , self :: COURSE_CURRENT );
2011-07-13 13:39:29 +08:00
2012-02-17 14:36:16 +13:00
// If the course wasn't added then don't try going any further.
if ( ! $coursenode ) {
$canviewcourseprofile = false ;
break ;
}
2011-07-13 13:39:29 +08:00
2012-02-17 14:36:16 +13:00
// If the user is not enrolled then we only want to show the
// course node and not populate it.
if ( ! can_access_course ( $course )) {
$coursenode -> make_active ();
$canviewcourseprofile = false ;
2011-11-29 11:01:50 +13:00
break ;
2011-12-06 13:32:59 +13:00
}
2012-02-17 14:36:16 +13:00
$this -> add_course_essentials ( $coursenode , $course );
2012-09-18 09:57:37 +08:00
$this -> load_course_sections ( $course , $coursenode );
2012-02-17 14:36:16 +13:00
break ;
2009-08-28 08:47:31 +00:00
}
2009-12-23 01:22:48 +00:00
2010-04-19 06:30:30 +00:00
// Load for the current user
$this -> load_for_user ();
2012-05-07 12:57:42 +12:00
if ( $this -> page -> context -> contextlevel >= CONTEXT_COURSE && $this -> page -> context -> instanceid != $SITE -> id && $canviewcourseprofile ) {
2010-05-17 05:38:59 +00:00
$this -> load_for_user ( null , true );
}
2009-12-23 01:22:48 +00:00
// Load each extending user into the navigation.
foreach ( $this -> extendforuser as $user ) {
2011-02-13 16:17:47 +01:00
if ( $user -> id != $USER -> id ) {
2009-12-23 01:22:48 +00:00
$this -> load_for_user ( $user );
}
}
2010-04-27 09:26:42 +00:00
// Give the local plugins a chance to include some navigation if they want.
2012-06-08 09:52:51 +12:00
foreach ( get_plugin_list_with_file ( 'local' , 'lib.php' , true ) as $plugin => $file ) {
$function = " local_ { $plugin } _extends_navigation " ;
$oldfunction = " { $plugin } _extends_navigation " ;
2010-04-27 09:26:42 +00:00
if ( function_exists ( $function )) {
2012-06-08 09:52:51 +12:00
// This is the preferred function name as there is less chance of conflicts
2010-04-27 09:26:42 +00:00
$function ( $this );
2012-06-08 09:52:51 +12:00
} else if ( function_exists ( $oldfunction )) {
2012-11-04 11:06:49 +13:00
// We continue to support the old function name to ensure backwards compatibility
2012-06-27 09:48:02 +12:00
debugging ( " Deprecated local plugin navigation callback: Please rename ' { $oldfunction } ' to ' { $function } '. Support for the old callback will be dropped after the release of 2.4 " , DEBUG_DEVELOPER );
2012-06-08 09:52:51 +12:00
$oldfunction ( $this );
2010-04-27 09:26:42 +00:00
}
}
2010-04-19 06:30:30 +00:00
// Remove any empty root nodes
foreach ( $this -> rootnodes as $node ) {
2010-05-13 09:57:43 +00:00
// Dont remove the home node
if ( $node -> key !== 'home' && ! $node -> has_children ()) {
2010-04-19 06:30:30 +00:00
$node -> remove ();
}
}
2010-05-19 07:57:00 +00:00
if ( ! $this -> contains_active_node ()) {
$this -> search_for_active_node ();
}
2010-04-19 06:30:30 +00:00
// If the user is not logged in modify the navigation structure as detailed
2011-07-04 11:21:48 +08:00
// in {@link http://docs.moodle.org/dev/Navigation_2.0_structure}
2010-04-19 06:30:30 +00:00
if ( ! isloggedin ()) {
$activities = clone ( $this -> rootnodes [ 'site' ] -> children );
$this -> rootnodes [ 'site' ] -> remove ();
$children = clone ( $this -> children );
$this -> children = new navigation_node_collection ();
foreach ( $activities as $child ) {
$this -> children -> add ( $child );
}
foreach ( $children as $child ) {
$this -> children -> add ( $child );
}
}
2009-08-28 08:47:31 +00:00
return true ;
}
2011-08-29 13:45:04 +12:00
2012-11-04 11:06:49 +13:00
/**
* Returns true if the current user is a parent of the user being currently viewed .
*
* If the current user is not viewing another user , or if the current user does not hold any parent roles over the
* other user being viewed this function returns false .
* In order to set the user for whom we are checking against you must call { @ link set_userid_for_parent_checks ()}
*
* @ since 2.4
* @ return bool
*/
protected function current_user_is_parent_role () {
global $USER , $DB ;
if ( $this -> useridtouseforparentchecks && $this -> useridtouseforparentchecks != $USER -> id ) {
$usercontext = context_user :: instance ( $this -> useridtouseforparentchecks , MUST_EXIST );
if ( ! has_capability ( 'moodle/user:viewdetails' , $usercontext )) {
return false ;
}
if ( $DB -> record_exists ( 'role_assignments' , array ( 'userid' => $USER -> id , 'contextid' => $usercontext -> id ))) {
return true ;
}
}
return false ;
}
2011-08-29 13:45:04 +12:00
/**
2012-01-04 15:56:26 +08:00
* Returns true if courses should be shown within categories on the navigation .
2011-08-29 13:45:04 +12:00
*
2012-11-04 11:06:49 +13:00
* @ param bool $ismycourse Set to true if you are calculating this for a course .
2011-08-29 13:45:04 +12:00
* @ return bool
*/
2012-11-04 11:06:49 +13:00
protected function show_categories ( $ismycourse = false ) {
2011-08-29 13:45:04 +12:00
global $CFG , $DB ;
2012-11-04 11:06:49 +13:00
if ( $ismycourse ) {
return $this -> show_my_categories ();
}
2011-08-29 13:45:04 +12:00
if ( $this -> showcategories === null ) {
2012-11-04 11:06:49 +13:00
$show = false ;
if ( $this -> page -> context -> contextlevel == CONTEXT_COURSECAT ) {
$show = true ;
} else if ( ! empty ( $CFG -> navshowcategories ) && $DB -> count_records ( 'course_categories' ) > 1 ) {
$show = true ;
}
2012-02-17 14:36:16 +13:00
$this -> showcategories = $show ;
2011-08-29 13:45:04 +12:00
}
return $this -> showcategories ;
}
2012-11-04 11:06:49 +13:00
/**
* Returns true if we should show categories in the My Courses branch .
* @ return bool
*/
protected function show_my_categories () {
global $CFG , $DB ;
if ( $this -> showmycategories === null ) {
$this -> showmycategories = ! empty ( $CFG -> navshowmycoursecategories ) && $DB -> count_records ( 'course_categories' ) > 1 ;
}
return $this -> showmycategories ;
}
2010-04-19 06:30:30 +00:00
/**
2012-01-04 15:56:26 +08:00
* Loads the courses in Moodle into the navigation .
2010-04-19 06:30:30 +00:00
*
2011-11-15 17:12:06 +13:00
* @ global moodle_database $DB
* @ param string | array $categoryids An array containing categories to load courses
* for , OR null to load courses for all categories .
* @ return array An array of navigation_nodes one for each course
2010-04-19 06:30:30 +00:00
*/
2011-11-15 17:12:06 +13:00
protected function load_all_courses ( $categoryids = null ) {
2012-05-07 12:57:42 +12:00
global $CFG , $DB , $SITE ;
2010-05-13 09:57:43 +00:00
2011-11-15 17:12:06 +13:00
// Work out the limit of courses.
2010-05-13 09:57:43 +00:00
$limit = 20 ;
if ( ! empty ( $CFG -> navcourselimit )) {
$limit = $CFG -> navcourselimit ;
}
2011-11-15 17:12:06 +13:00
$toload = ( empty ( $CFG -> navshowallcourses )) ? self :: LOAD_ROOT_CATEGORIES : self :: LOAD_ALL_CATEGORIES ;
// If we are going to show all courses AND we are showing categories then
// to save us repeated DB calls load all of the categories now
if ( $this -> show_categories ()) {
$this -> load_all_categories ( $toload );
}
// Will be the return of our efforts
2010-04-19 06:30:30 +00:00
$coursenodes = array ();
2011-11-15 17:12:06 +13:00
2012-03-30 13:32:05 +13:00
// Check if we need to show categories.
if ( $this -> show_categories ()) {
// Hmmm we need to show categories... this is going to be painful.
// We now need to fetch up to $limit courses for each category to
// be displayed.
if ( $categoryids !== null ) {
if ( ! is_array ( $categoryids )) {
$categoryids = array ( $categoryids );
2011-11-15 17:12:06 +13:00
}
2012-03-30 13:32:05 +13:00
list ( $categorywhere , $categoryparams ) = $DB -> get_in_or_equal ( $categoryids , SQL_PARAMS_NAMED , 'cc' );
$categorywhere = 'WHERE cc.id ' . $categorywhere ;
} else if ( $toload == self :: LOAD_ROOT_CATEGORIES ) {
$categorywhere = 'WHERE cc.depth = 1 OR cc.depth = 2' ;
$categoryparams = array ();
} else {
$categorywhere = '' ;
$categoryparams = array ();
}
2011-11-15 17:12:06 +13:00
2012-03-30 13:32:05 +13:00
// First up we are going to get the categories that we are going to
// need so that we can determine how best to load the courses from them.
$sql = " SELECT cc.id, COUNT(c.id) AS coursecount
FROM { course_categories } cc
LEFT JOIN { course } c ON c . category = cc . id
{ $categorywhere }
GROUP BY cc . id " ;
$categories = $DB -> get_recordset_sql ( $sql , $categoryparams );
$fullfetch = array ();
$partfetch = array ();
foreach ( $categories as $category ) {
if ( ! $this -> can_add_more_courses_to_category ( $category -> id )) {
continue ;
}
if ( $category -> coursecount > $limit * 5 ) {
$partfetch [] = $category -> id ;
} else if ( $category -> coursecount > 0 ) {
$fullfetch [] = $category -> id ;
}
}
$categories -> close ();
if ( count ( $fullfetch )) {
// First up fetch all of the courses in categories where we know that we are going to
// need the majority of courses.
list ( $ccselect , $ccjoin ) = context_instance_preload_sql ( 'c.id' , CONTEXT_COURSE , 'ctx' );
list ( $categoryids , $categoryparams ) = $DB -> get_in_or_equal ( $fullfetch , SQL_PARAMS_NAMED , 'lcategory' );
$sql = " SELECT c.id, c.sortorder, c.visible, c.fullname, c.shortname, c.category $ccselect
FROM { course } c
$ccjoin
2012-05-12 13:19:22 +02:00
WHERE c . category { $categoryids }
2012-03-30 13:32:05 +13:00
ORDER BY c . sortorder ASC " ;
2012-05-12 13:19:22 +02:00
$coursesrs = $DB -> get_recordset_sql ( $sql , $categoryparams );
2012-03-30 13:32:05 +13:00
foreach ( $coursesrs as $course ) {
2012-05-12 13:19:22 +02:00
if ( $course -> id == $SITE -> id ) {
// This should not be necessary, frontpage is not in any category.
continue ;
}
if ( array_key_exists ( $course -> id , $this -> addedcourses )) {
// It is probably better to not include the already loaded courses
// directly in SQL because inequalities may confuse query optimisers
// and may interfere with query caching.
continue ;
}
2012-03-30 13:32:05 +13:00
if ( ! $this -> can_add_more_courses_to_category ( $course -> category )) {
2011-11-15 17:12:06 +13:00
continue ;
}
2012-03-30 13:32:05 +13:00
context_instance_preload ( $course );
2012-07-25 16:25:55 +08:00
if ( ! $course -> visible && ! is_role_switched ( $course -> id ) && ! has_capability ( 'moodle/course:viewhiddencourses' , context_course :: instance ( $course -> id ))) {
2012-03-30 13:32:05 +13:00
continue ;
2011-11-15 17:12:06 +13:00
}
2012-03-30 13:32:05 +13:00
$coursenodes [ $course -> id ] = $this -> add_course ( $course );
2011-11-15 17:12:06 +13:00
}
2012-03-30 13:32:05 +13:00
$coursesrs -> close ();
}
2011-11-15 17:12:06 +13:00
2012-03-30 13:32:05 +13:00
if ( count ( $partfetch )) {
// Next we will work our way through the categories where we will likely only need a small
// proportion of the courses.
foreach ( $partfetch as $categoryid ) {
2011-11-15 17:12:06 +13:00
list ( $ccselect , $ccjoin ) = context_instance_preload_sql ( 'c.id' , CONTEXT_COURSE , 'ctx' );
$sql = " SELECT c.id, c.sortorder, c.visible, c.fullname, c.shortname, c.category $ccselect
2012-03-30 13:32:05 +13:00
FROM { course } c
$ccjoin
2012-05-12 13:19:22 +02:00
WHERE c . category = : categoryid
2012-03-30 13:32:05 +13:00
ORDER BY c . sortorder ASC " ;
2012-05-12 13:19:22 +02:00
$courseparams = array ( 'categoryid' => $categoryid );
2012-03-30 13:32:05 +13:00
$coursesrs = $DB -> get_recordset_sql ( $sql , $courseparams , 0 , $limit * 5 );
2011-11-15 17:12:06 +13:00
foreach ( $coursesrs as $course ) {
2012-05-12 13:19:22 +02:00
if ( $course -> id == $SITE -> id ) {
// This should not be necessary, frontpage is not in any category.
continue ;
}
if ( array_key_exists ( $course -> id , $this -> addedcourses )) {
// It is probably better to not include the already loaded courses
// directly in SQL because inequalities may confuse query optimisers
// and may interfere with query caching.
// This also helps to respect expected $limit on repeated executions.
continue ;
}
2011-11-15 17:12:06 +13:00
if ( ! $this -> can_add_more_courses_to_category ( $course -> category )) {
2012-03-30 13:32:05 +13:00
break ;
2011-11-15 17:12:06 +13:00
}
context_instance_preload ( $course );
2012-07-25 16:25:55 +08:00
if ( ! $course -> visible && ! is_role_switched ( $course -> id ) && ! has_capability ( 'moodle/course:viewhiddencourses' , context_course :: instance ( $course -> id ))) {
2011-11-15 17:12:06 +13:00
continue ;
}
$coursenodes [ $course -> id ] = $this -> add_course ( $course );
}
$coursesrs -> close ();
}
}
} else {
// Prepare the SQL to load the courses and their contexts
list ( $ccselect , $ccjoin ) = context_instance_preload_sql ( 'c.id' , CONTEXT_COURSE , 'ctx' );
2012-03-30 13:32:05 +13:00
list ( $courseids , $courseparams ) = $DB -> get_in_or_equal ( array_keys ( $this -> addedcourses ), SQL_PARAMS_NAMED , 'lc' , false );
2011-11-15 17:12:06 +13:00
$sql = " SELECT c.id, c.sortorder, c.visible, c.fullname, c.shortname, c.category $ccselect
2012-03-30 13:32:05 +13:00
FROM { course } c
$ccjoin
WHERE c . id { $courseids }
ORDER BY c . sortorder ASC " ;
2011-11-15 17:12:06 +13:00
$coursesrs = $DB -> get_recordset_sql ( $sql , $courseparams );
foreach ( $coursesrs as $course ) {
2012-05-12 13:19:22 +02:00
if ( $course -> id == $SITE -> id ) {
// frotpage is not wanted here
continue ;
}
2012-07-13 17:05:47 +01:00
if ( $this -> page -> course && ( $this -> page -> course -> id == $course -> id )) {
// Don't include the currentcourse in this nodelist - it's displayed in the Current course node
continue ;
}
2011-11-15 17:12:06 +13:00
context_instance_preload ( $course );
2012-07-25 16:25:55 +08:00
if ( ! $course -> visible && ! is_role_switched ( $course -> id ) && ! has_capability ( 'moodle/course:viewhiddencourses' , context_course :: instance ( $course -> id ))) {
2012-03-30 13:32:05 +13:00
continue ;
}
2011-11-15 17:12:06 +13:00
$coursenodes [ $course -> id ] = $this -> add_course ( $course );
2012-03-30 13:32:05 +13:00
if ( count ( $coursenodes ) >= $limit ) {
break ;
}
2011-11-15 17:12:06 +13:00
}
$coursesrs -> close ();
2010-04-19 06:30:30 +00:00
}
2012-03-30 13:32:05 +13:00
2010-04-19 06:30:30 +00:00
return $coursenodes ;
}
2011-11-15 17:12:06 +13:00
/**
* Returns true if more courses can be added to the provided category .
*
2012-05-07 12:57:42 +12:00
* @ param int | navigation_node | stdClass $category
* @ return bool
2011-11-15 17:12:06 +13:00
*/
protected function can_add_more_courses_to_category ( $category ) {
global $CFG ;
$limit = 20 ;
if ( ! empty ( $CFG -> navcourselimit )) {
$limit = ( int ) $CFG -> navcourselimit ;
}
if ( is_numeric ( $category )) {
if ( ! array_key_exists ( $category , $this -> addedcategories )) {
return true ;
}
$coursecount = count ( $this -> addedcategories [ $category ] -> children -> type ( self :: TYPE_COURSE ));
} else if ( $category instanceof navigation_node ) {
2013-02-07 11:04:24 +08:00
if (( $category -> type != self :: TYPE_CATEGORY ) || ( $category -> type != self :: TYPE_MY_CATEGORY )) {
2011-11-15 17:12:06 +13:00
return false ;
}
$coursecount = count ( $category -> children -> type ( self :: TYPE_COURSE ));
} else if ( is_object ( $category ) && property_exists ( $category , 'id' )) {
$coursecount = count ( $this -> addedcategories [ $category -> id ] -> children -> type ( self :: TYPE_COURSE ));
}
2012-03-30 13:27:12 +13:00
return ( $coursecount <= $limit );
2011-11-15 17:12:06 +13:00
}
2010-05-13 09:57:43 +00:00
/**
* Loads all categories ( top level or if an id is specified for that category )
*
2011-06-24 16:42:41 +08:00
* @ param int $categoryid The category id to load or null / 0 to load all base level categories
* @ param bool $showbasecategories If set to true all base level categories will be loaded as well
* as the requested category and any parent categories .
2012-01-04 15:56:26 +08:00
* @ return navigation_node | void returns a navigation node if a category has been loaded .
2010-05-13 09:57:43 +00:00
*/
2011-11-15 17:12:06 +13:00
protected function load_all_categories ( $categoryid = self :: LOAD_ROOT_CATEGORIES , $showbasecategories = false ) {
2012-11-04 11:06:49 +13:00
global $CFG , $DB ;
2011-06-24 16:42:41 +08:00
// Check if this category has already been loaded
2011-11-15 17:12:06 +13:00
if ( $this -> allcategoriesloaded || ( $categoryid < 1 && $this -> is_category_fully_loaded ( $categoryid ))) {
return true ;
2011-06-24 16:42:41 +08:00
}
2012-03-29 12:29:40 +13:00
$catcontextsql = context_helper :: get_preload_record_columns_sql ( 'ctx' );
$sqlselect = " SELECT cc.*, $catcontextsql
FROM { course_categories } cc
JOIN { context } ctx ON cc . id = ctx . instanceid " ;
$sqlwhere = " WHERE ctx.contextlevel = " . CONTEXT_COURSECAT ;
2012-05-18 10:37:44 +12:00
$sqlorder = " ORDER BY cc.depth ASC, cc.sortorder ASC, cc.id ASC " ;
2012-03-29 12:29:40 +13:00
$params = array ();
2011-11-15 17:12:06 +13:00
$categoriestoload = array ();
if ( $categoryid == self :: LOAD_ALL_CATEGORIES ) {
2012-03-29 12:29:40 +13:00
// We are going to load all categories regardless... prepare to fire
// on the database server!
2011-11-15 17:12:06 +13:00
} else if ( $categoryid == self :: LOAD_ROOT_CATEGORIES ) { // can be 0
2011-06-24 16:42:41 +08:00
// We are going to load all of the first level categories (categories without parents)
2012-03-29 12:29:40 +13:00
$sqlwhere .= " AND cc.parent = 0 " ;
2011-06-24 16:42:41 +08:00
} else if ( array_key_exists ( $categoryid , $this -> addedcategories )) {
// The category itself has been loaded already so we just need to ensure its subcategories
// have been loaded
list ( $sql , $params ) = $DB -> get_in_or_equal ( array_keys ( $this -> addedcategories ), SQL_PARAMS_NAMED , 'parent' , false );
if ( $showbasecategories ) {
// We need to include categories with parent = 0 as well
2012-03-30 13:27:12 +13:00
$sqlwhere .= " AND (cc.parent = :categoryid OR cc.parent = 0) AND cc.parent { $sql } " ;
2011-06-24 16:42:41 +08:00
} else {
2012-03-29 12:29:40 +13:00
// All we need is categories that match the parent
2012-03-30 13:27:12 +13:00
$sqlwhere .= " AND cc.parent = :categoryid AND cc.parent { $sql } " ;
2011-06-24 16:42:41 +08:00
}
$params [ 'categoryid' ] = $categoryid ;
2010-05-13 09:57:43 +00:00
} else {
2011-06-24 16:42:41 +08:00
// This category hasn't been loaded yet so we need to fetch it, work out its category path
// and load this category plus all its parents and subcategories
2011-06-27 15:11:28 +08:00
$category = $DB -> get_record ( 'course_categories' , array ( 'id' => $categoryid ), 'path' , MUST_EXIST );
2011-11-15 17:12:06 +13:00
$categoriestoload = explode ( '/' , trim ( $category -> path , '/' ));
list ( $select , $params ) = $DB -> get_in_or_equal ( $categoriestoload );
2012-03-29 12:29:40 +13:00
// We are going to use select twice so double the params
2010-05-13 09:57:43 +00:00
$params = array_merge ( $params , $params );
2012-03-30 13:27:12 +13:00
$basecategorysql = ( $showbasecategories ) ? ' OR cc.depth = 1' : '' ;
$sqlwhere .= " AND (cc.id { $select } OR cc.parent { $select } { $basecategorysql } ) " ;
2012-03-29 12:29:40 +13:00
}
$categoriesrs = $DB -> get_recordset_sql ( " $sqlselect $sqlwhere $sqlorder " , $params );
$categories = array ();
foreach ( $categoriesrs as $category ) {
// Preload the context.. we'll need it when adding the category in order
// to format the category name.
context_helper :: preload_from_record ( $category );
if ( array_key_exists ( $category -> id , $this -> addedcategories )) {
// Do nothing, its already been added.
} else if ( $category -> parent == '0' ) {
// This is a root category lets add it immediately
$this -> add_category ( $category , $this -> rootnodes [ 'courses' ]);
} else if ( array_key_exists ( $category -> parent , $this -> addedcategories )) {
// This categories parent has already been added we can add this immediately
$this -> add_category ( $category , $this -> addedcategories [ $category -> parent ]);
} else {
$categories [] = $category ;
}
2010-05-13 09:57:43 +00:00
}
2012-03-29 12:29:40 +13:00
$categoriesrs -> close ();
2011-06-24 16:42:41 +08:00
// Now we have an array of categories we need to add them to the navigation.
while ( ! empty ( $categories )) {
$category = reset ( $categories );
if ( array_key_exists ( $category -> id , $this -> addedcategories )) {
// Do nothing
} else if ( $category -> parent == '0' ) {
$this -> add_category ( $category , $this -> rootnodes [ 'courses' ]);
} else if ( array_key_exists ( $category -> parent , $this -> addedcategories )) {
$this -> add_category ( $category , $this -> addedcategories [ $category -> parent ]);
2010-05-13 09:57:43 +00:00
} else {
2011-06-24 16:42:41 +08:00
// This category isn't in the navigation and niether is it's parent (yet).
// We need to go through the category path and add all of its components in order.
$path = explode ( '/' , trim ( $category -> path , '/' ));
foreach ( $path as $catid ) {
if ( ! array_key_exists ( $catid , $this -> addedcategories )) {
// This category isn't in the navigation yet so add it.
$subcategory = $categories [ $catid ];
2011-07-13 09:58:42 +08:00
if ( $subcategory -> parent == '0' ) {
// Yay we have a root category - this likely means we will now be able
// to add categories without problems.
$this -> add_category ( $subcategory , $this -> rootnodes [ 'courses' ]);
} else if ( array_key_exists ( $subcategory -> parent , $this -> addedcategories )) {
2011-06-24 16:42:41 +08:00
// The parent is in the category (as we'd expect) so add it now.
$this -> add_category ( $subcategory , $this -> addedcategories [ $subcategory -> parent ]);
// Remove the category from the categories array.
unset ( $categories [ $catid ]);
} else {
// We should never ever arrive here - if we have then there is a bigger
// problem at hand.
2011-07-04 16:42:55 +02:00
throw new coding_exception ( 'Category path order is incorrect and/or there are missing categories' );
2011-06-24 16:42:41 +08:00
}
2010-05-13 09:57:43 +00:00
}
}
}
2011-06-24 16:42:41 +08:00
// Remove the category from the categories array now that we know it has been added.
unset ( $categories [ $category -> id ]);
2010-05-13 09:57:43 +00:00
}
2011-11-15 17:12:06 +13:00
if ( $categoryid === self :: LOAD_ALL_CATEGORIES ) {
$this -> allcategoriesloaded = true ;
}
2011-06-24 16:42:41 +08:00
// Check if there are any categories to load.
2011-11-15 17:12:06 +13:00
if ( count ( $categoriestoload ) > 0 ) {
$readytoloadcourses = array ();
foreach ( $categoriestoload as $category ) {
if ( $this -> can_add_more_courses_to_category ( $category )) {
$readytoloadcourses [] = $category ;
}
}
if ( count ( $readytoloadcourses )) {
$this -> load_all_courses ( $readytoloadcourses );
}
2010-05-13 09:57:43 +00:00
}
2012-11-04 11:06:49 +13:00
// Look for all categories which have been loaded
if ( ! empty ( $this -> addedcategories )) {
$categoryids = array ();
foreach ( $this -> addedcategories as $category ) {
if ( $this -> can_add_more_courses_to_category ( $category )) {
$categoryids [] = $category -> key ;
}
}
2012-12-27 13:52:14 +01:00
if ( $categoryids ) {
list ( $categoriessql , $params ) = $DB -> get_in_or_equal ( $categoryids , SQL_PARAMS_NAMED );
$params [ 'limit' ] = ( ! empty ( $CFG -> navcourselimit )) ? $CFG -> navcourselimit : 20 ;
$sql = " SELECT cc.id, COUNT(c.id) AS coursecount
FROM { course_categories } cc
JOIN { course } c ON c . category = cc . id
WHERE cc . id { $categoriessql }
GROUP BY cc . id
HAVING COUNT ( c . id ) > : limit " ;
$excessivecategories = $DB -> get_records_sql ( $sql , $params );
foreach ( $categories as & $category ) {
if ( array_key_exists ( $category -> key , $excessivecategories ) && ! $this -> can_add_more_courses_to_category ( $category )) {
2013-04-09 12:21:05 +10:00
$url = new moodle_url ( '/course/index.php' , array ( 'categoryid' => $category -> key ));
2012-12-27 13:52:14 +01:00
$category -> add ( get_string ( 'viewallcourses' ), $url , self :: TYPE_SETTING );
}
2012-11-04 11:06:49 +13:00
}
}
}
2010-05-13 09:57:43 +00:00
}
/**
* Adds a structured category to the navigation in the correct order / place
*
2013-02-07 11:04:24 +08:00
* @ param stdClass $category category to be added in navigation .
* @ param navigation_node $parent parent navigation node
* @ param int $nodetype type of node , if category is under MyHome then it ' s TYPE_MY_CATEGORY
* @ return void .
2010-05-13 09:57:43 +00:00
*/
2013-02-07 11:04:24 +08:00
protected function add_category ( stdClass $category , navigation_node $parent , $nodetype = self :: TYPE_CATEGORY ) {
2011-06-24 16:42:41 +08:00
if ( array_key_exists ( $category -> id , $this -> addedcategories )) {
2011-10-29 09:59:49 +02:00
return ;
2011-06-24 16:42:41 +08:00
}
2013-04-09 12:21:05 +10:00
$url = new moodle_url ( '/course/index.php' , array ( 'categoryid' => $category -> id ));
2012-07-25 16:25:55 +08:00
$context = context_coursecat :: instance ( $category -> id );
2011-08-30 17:48:46 +12:00
$categoryname = format_string ( $category -> name , true , array ( 'context' => $context ));
2013-02-07 11:04:24 +08:00
$categorynode = $parent -> add ( $categoryname , $url , $nodetype , $categoryname , $category -> id );
2011-06-24 16:42:41 +08:00
if ( empty ( $category -> visible )) {
if ( has_capability ( 'moodle/category:viewhiddencategories' , get_system_context ())) {
$categorynode -> hidden = true ;
} else {
$categorynode -> display = false ;
2010-09-15 06:02:02 +00:00
}
2010-05-13 09:57:43 +00:00
}
2012-05-06 13:31:55 +02:00
$this -> addedcategories [ $category -> id ] = $categorynode ;
2010-05-13 09:57:43 +00:00
}
2010-04-19 06:30:30 +00:00
/**
* Loads the given course into the navigation
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ param stdClass $course
* @ return navigation_node
*/
protected function load_course ( stdClass $course ) {
2012-05-07 12:57:42 +12:00
global $SITE ;
if ( $course -> id == $SITE -> id ) {
2012-04-19 10:27:53 +12:00
// This is always loaded during initialisation
2011-06-24 16:42:41 +08:00
return $this -> rootnodes [ 'site' ];
} else if ( array_key_exists ( $course -> id , $this -> addedcourses )) {
2012-04-19 10:27:53 +12:00
// The course has already been loaded so return a reference
2011-06-24 16:42:41 +08:00
return $this -> addedcourses [ $course -> id ];
2010-04-19 06:30:30 +00:00
} else {
2012-04-19 10:27:53 +12:00
// Add the course
2011-06-24 16:42:41 +08:00
return $this -> add_course ( $course );
2010-04-19 06:30:30 +00:00
}
}
/**
* Loads all of the courses section into the navigation .
*
2012-10-31 12:52:32 +08:00
* This function calls method from current course format , see
* { @ link format_base :: extend_course_navigation ()}
* If course module ( $cm ) is specified but course format failed to create the node ,
* the activity node is created anyway .
2010-04-19 06:30:30 +00:00
*
2012-10-31 12:52:32 +08:00
* By default course formats call the method { @ link global_navigation :: load_generic_course_sections ()}
2010-04-19 06:30:30 +00:00
*
* @ param stdClass $course Database record for the course
* @ param navigation_node $coursenode The course node within the navigation
2012-10-31 12:52:32 +08:00
* @ param null | int $sectionnum If specified load the contents of section with this relative number
* @ param null | cm_info $cm If specified make sure that activity node is created ( either
* in containg section or by calling load_stealth_activity () )
2010-04-19 06:30:30 +00:00
*/
2012-10-31 12:52:32 +08:00
protected function load_course_sections ( stdClass $course , navigation_node $coursenode , $sectionnum = null , $cm = null ) {
global $CFG , $SITE ;
2012-09-18 09:57:37 +08:00
require_once ( $CFG -> dirroot . '/course/lib.php' );
2012-10-31 12:52:32 +08:00
if ( isset ( $cm -> sectionnum )) {
$sectionnum = $cm -> sectionnum ;
}
if ( $sectionnum !== null ) {
$this -> includesectionnum = $sectionnum ;
}
course_get_format ( $course ) -> extend_course_navigation ( $this , $coursenode , $sectionnum , $cm );
if ( isset ( $cm -> id )) {
$activity = $coursenode -> find ( $cm -> id , self :: TYPE_ACTIVITY );
if ( empty ( $activity )) {
$activity = $this -> load_stealth_activity ( $coursenode , get_fast_modinfo ( $course ));
}
}
}
2010-04-19 06:30:30 +00:00
2011-06-24 16:42:41 +08:00
/**
* Generates an array of sections and an array of activities for the given course .
*
* This method uses the cache to improve performance and avoid the get_fast_modinfo call
*
* @ param stdClass $course
* @ return array Array ( $sections , $activities )
*/
protected function generate_sections_and_activities ( stdClass $course ) {
global $CFG ;
require_once ( $CFG -> dirroot . '/course/lib.php' );
2012-03-27 13:25:24 +13:00
$modinfo = get_fast_modinfo ( $course );
2012-10-11 15:08:17 +08:00
$sections = $modinfo -> get_section_info_all ();
2012-11-02 14:32:17 +08:00
// For course formats using 'numsections' trim the sections list
$courseformatoptions = course_get_format ( $course ) -> get_format_options ();
if ( isset ( $courseformatoptions [ 'numsections' ])) {
$sections = array_slice ( $sections , 0 , $courseformatoptions [ 'numsections' ] + 1 , true );
2012-10-11 15:08:17 +08:00
}
2012-11-02 14:32:17 +08:00
2012-03-27 13:25:24 +13:00
$activities = array ();
2011-06-24 16:42:41 +08:00
2012-03-27 13:25:24 +13:00
foreach ( $sections as $key => $section ) {
2012-07-02 17:29:30 +08:00
// Clone and unset summary to prevent $SESSION bloat (MDL-31802).
2012-02-28 16:28:11 +10:30
$sections [ $key ] = clone ( $section );
unset ( $sections [ $key ] -> summary );
2012-03-27 13:25:24 +13:00
$sections [ $key ] -> hasactivites = false ;
if ( ! array_key_exists ( $section -> section , $modinfo -> sections )) {
continue ;
}
foreach ( $modinfo -> sections [ $section -> section ] as $cmid ) {
$cm = $modinfo -> cms [ $cmid ];
if ( ! $cm -> uservisible ) {
2011-06-24 16:42:41 +08:00
continue ;
}
2012-03-27 13:25:24 +13:00
$activity = new stdClass ;
$activity -> id = $cm -> id ;
$activity -> course = $course -> id ;
$activity -> section = $section -> section ;
$activity -> name = $cm -> name ;
$activity -> icon = $cm -> icon ;
$activity -> iconcomponent = $cm -> iconcomponent ;
$activity -> hidden = ( ! $cm -> visible );
$activity -> modname = $cm -> modname ;
$activity -> nodetype = navigation_node :: NODETYPE_LEAF ;
$activity -> onclick = $cm -> get_on_click ();
$url = $cm -> get_url ();
if ( ! $url ) {
$activity -> url = null ;
$activity -> display = false ;
} else {
$activity -> url = $cm -> get_url () -> out ();
$activity -> display = true ;
if ( self :: module_extends_navigation ( $cm -> modname )) {
$activity -> nodetype = navigation_node :: NODETYPE_BRANCH ;
2012-01-11 16:56:03 +00:00
}
2011-06-24 16:42:41 +08:00
}
2012-03-27 13:25:24 +13:00
$activities [ $cmid ] = $activity ;
if ( $activity -> display ) {
$sections [ $key ] -> hasactivites = true ;
}
2011-06-24 16:42:41 +08:00
}
}
2012-03-27 13:25:24 +13:00
2011-06-24 16:42:41 +08:00
return array ( $sections , $activities );
}
2010-04-19 06:30:30 +00:00
/**
* Generically loads the course sections into the course ' s navigation .
*
* @ param stdClass $course
* @ param navigation_node $coursenode
* @ return array An array of course section nodes
*/
2012-09-18 09:57:37 +08:00
public function load_generic_course_sections ( stdClass $course , navigation_node $coursenode ) {
2012-05-07 12:57:42 +12:00
global $CFG , $DB , $USER , $SITE ;
MDL-21782 reworked enrolment framework, the core infrastructure is in place, the basic plugins are all implemented; see the tracker issue for list of unfinished bits, expect more changes and improvements during the next week
AMOS START
MOV [sendcoursewelcomemessage,core_admin],[sendcoursewelcomemessage,enrol_self]
MOV [configsendcoursewelcomemessage,core_admin],[sendcoursewelcomemessage_desc,enrol_self]
MOV [enrolstartdate,core],[enrolstartdate,enrol_self]
MOV [enrolenddate,core],[enrolenddate,enrol_self]
CPY [welcometocourse,core],[welcometocourse,enrol_self]
CPY [welcometocoursetext,core],[welcometocoursetext,enrol_self]
MOV [notenrollable,core],[notenrollable,core_enrol]
MOV [enrolenddaterror,core],[enrolenddaterror,enrol_self]
MOV [enrolmentkeyhint,core],[passwordinvalidhint,enrol_self]
MOV [coursemanager,core_admin],[coursecontact,core_admin]
MOV [configcoursemanager,core_admin],[coursecontact_desc,core_admin]
MOV [enrolledincourserole,core],[enrolledincourserole,enrol_manual]
MOV [enrolme,core],[enrolme,core_enrol]
MOV [unenrol,core],[unenrol,core_enrol]
MOV [unenrolme,core],[unenrolme,core_enrol]
MOV [enrolmentnew,core],[enrolmentnew,core_enrol]
MOV [enrolmentnewuser,core],[enrolmentnewuser,core_enrol]
MOV [enrolments,core],[enrolments,core_enrol]
MOV [enrolperiod,core],[enrolperiod,core_enrol]
MOV [unenrolroleusers,core],[unenrolroleusers,core_enrol]
AMOS END
2010-06-21 15:30:49 +00:00
require_once ( $CFG -> dirroot . '/course/lib.php' );
2010-05-30 22:56:29 +00:00
2011-06-24 16:42:41 +08:00
list ( $sections , $activities ) = $this -> generate_sections_and_activities ( $course );
2010-04-23 07:17:21 +00:00
2010-06-08 06:21:25 +00:00
$navigationsections = array ();
2011-06-24 16:42:41 +08:00
foreach ( $sections as $sectionid => $section ) {
2010-06-08 06:21:25 +00:00
$section = clone ( $section );
2012-05-07 12:57:42 +12:00
if ( $course -> id == $SITE -> id ) {
2011-06-24 16:42:41 +08:00
$this -> load_section_activities ( $coursenode , $section -> section , $activities );
2010-04-19 06:30:30 +00:00
} else {
2012-04-02 12:16:13 +01:00
if ( ! $section -> uservisible || ( ! $this -> showemptysections &&
2012-01-11 16:56:03 +00:00
! $section -> hasactivites && $this -> includesectionnum !== $section -> section )) {
2010-04-19 06:30:30 +00:00
continue ;
}
2012-04-02 12:16:13 +01:00
2012-09-18 09:57:37 +08:00
$sectionname = get_section_name ( $course , $section );
$url = course_get_url ( $course , $section -> section , array ( 'navigation' => true ));
2011-07-28 15:20:01 +08:00
2010-04-19 06:30:30 +00:00
$sectionnode = $coursenode -> add ( $sectionname , $url , navigation_node :: TYPE_SECTION , null , $section -> id );
$sectionnode -> nodetype = navigation_node :: NODETYPE_BRANCH ;
2012-04-02 12:16:13 +01:00
$sectionnode -> hidden = ( ! $section -> visible || ! $section -> available );
2012-10-31 12:52:32 +08:00
if ( $this -> includesectionnum !== false && $this -> includesectionnum == $section -> section ) {
2011-06-24 16:42:41 +08:00
$this -> load_section_activities ( $sectionnode , $section -> section , $activities );
2010-04-19 06:30:30 +00:00
}
$section -> sectionnode = $sectionnode ;
2010-06-08 06:21:25 +00:00
$navigationsections [ $sectionid ] = $section ;
2010-04-19 06:30:30 +00:00
}
}
2010-06-08 06:21:25 +00:00
return $navigationsections ;
2010-04-19 06:30:30 +00:00
}
2012-10-31 12:52:32 +08:00
2010-04-19 06:30:30 +00:00
/**
* Loads all of the activities for a section into the navigation structure .
*
* @ param navigation_node $sectionnode
* @ param int $sectionnumber
2012-02-29 00:56:41 +01:00
* @ param array $activities An array of activites as returned by { @ link global_navigation :: generate_sections_and_activities ()}
2012-01-05 14:29:44 +13:00
* @ param stdClass $course The course object the section and activities relate to .
2010-04-19 06:30:30 +00:00
* @ return array Array of activity nodes
*/
2012-01-05 14:29:44 +13:00
protected function load_section_activities ( navigation_node $sectionnode , $sectionnumber , array $activities , $course = null ) {
2012-05-07 12:57:42 +12:00
global $CFG , $SITE ;
2011-10-06 19:32:27 +13:00
// A static counter for JS function naming
static $legacyonclickcounter = 0 ;
2010-04-19 06:30:30 +00:00
2011-06-24 16:42:41 +08:00
$activitynodes = array ();
2011-12-06 13:04:12 +13:00
if ( empty ( $activities )) {
return $activitynodes ;
}
if ( ! is_object ( $course )) {
$activity = reset ( $activities );
$courseid = $activity -> course ;
} else {
$courseid = $course -> id ;
}
2012-05-07 12:57:42 +12:00
$showactivities = ( $courseid != $SITE -> id || ! empty ( $CFG -> navshowfrontpagemods ));
2011-12-06 13:04:12 +13:00
2011-06-24 16:42:41 +08:00
foreach ( $activities as $activity ) {
if ( $activity -> section != $sectionnumber ) {
2010-04-19 06:30:30 +00:00
continue ;
}
2011-06-24 16:42:41 +08:00
if ( $activity -> icon ) {
$icon = new pix_icon ( $activity -> icon , get_string ( 'modulename' , $activity -> modname ), $activity -> iconcomponent );
2010-04-19 06:30:30 +00:00
} else {
2011-06-24 16:42:41 +08:00
$icon = new pix_icon ( 'icon' , get_string ( 'modulename' , $activity -> modname ), $activity -> modname );
2010-04-19 06:30:30 +00:00
}
2011-10-06 19:32:27 +13:00
// Prepare the default name and url for the node
2012-07-25 16:25:55 +08:00
$activityname = format_string ( $activity -> name , true , array ( 'context' => context_module :: instance ( $activity -> id )));
2011-10-06 19:32:27 +13:00
$action = new moodle_url ( $activity -> url );
// Check if the onclick property is set (puke!)
if ( ! empty ( $activity -> onclick )) {
// Increment the counter so that we have a unique number.
$legacyonclickcounter ++ ;
// Generate the function name we will use
$functionname = 'legacy_activity_onclick_handler_' . $legacyonclickcounter ;
$propogrationhandler = '' ;
// Check if we need to cancel propogation. Remember inline onclick
// events would return false if they wanted to prevent propogation and the
// default action.
if ( strpos ( $activity -> onclick , 'return false' )) {
$propogrationhandler = 'e.halt();' ;
}
// Decode the onclick - it has already been encoded for display (puke)
2012-12-11 16:50:30 +08:00
$onclick = htmlspecialchars_decode ( $activity -> onclick , ENT_QUOTES );
2011-10-06 19:32:27 +13:00
// Build the JS function the click event will call
$jscode = " function { $functionname } (e) { $propogrationhandler $onclick } " ;
$this -> page -> requires -> js_init_code ( $jscode );
// Override the default url with the new action link
$action = new action_link ( $action , $activityname , new component_action ( 'click' , $functionname ));
}
$activitynode = $sectionnode -> add ( $activityname , $action , navigation_node :: TYPE_ACTIVITY , null , $activity -> id , $icon );
2011-06-24 16:42:41 +08:00
$activitynode -> title ( get_string ( 'modulename' , $activity -> modname ));
$activitynode -> hidden = $activity -> hidden ;
2011-12-06 13:04:12 +13:00
$activitynode -> display = $showactivities && $activity -> display ;
2011-06-24 16:42:41 +08:00
$activitynode -> nodetype = $activity -> nodetype ;
$activitynodes [ $activity -> id ] = $activitynode ;
2010-04-19 06:30:30 +00:00
}
2011-06-24 16:42:41 +08:00
return $activitynodes ;
2010-04-19 06:30:30 +00:00
}
2010-10-13 18:51:37 +00:00
/**
* Loads a stealth module from unavailable section
* @ param navigation_node $coursenode
* @ param stdClass $modinfo
* @ return navigation_node or null if not accessible
*/
protected function load_stealth_activity ( navigation_node $coursenode , $modinfo ) {
if ( empty ( $modinfo -> cms [ $this -> page -> cm -> id ])) {
return null ;
}
$cm = $modinfo -> cms [ $this -> page -> cm -> id ];
if ( ! $cm -> uservisible ) {
return null ;
}
if ( $cm -> icon ) {
$icon = new pix_icon ( $cm -> icon , get_string ( 'modulename' , $cm -> modname ), $cm -> iconcomponent );
} else {
$icon = new pix_icon ( 'icon' , get_string ( 'modulename' , $cm -> modname ), $cm -> modname );
}
2011-01-26 10:29:16 +00:00
$url = $cm -> get_url ();
2010-10-13 18:51:37 +00:00
$activitynode = $coursenode -> add ( format_string ( $cm -> name ), $url , navigation_node :: TYPE_ACTIVITY , null , $cm -> id , $icon );
$activitynode -> title ( get_string ( 'modulename' , $cm -> modname ));
$activitynode -> hidden = ( ! $cm -> visible );
2011-01-26 10:29:16 +00:00
if ( ! $url ) {
// Don't show activities that don't have links!
2010-10-13 18:51:37 +00:00
$activitynode -> display = false ;
2011-06-24 16:42:41 +08:00
} else if ( self :: module_extends_navigation ( $cm -> modname )) {
2010-10-13 18:51:37 +00:00
$activitynode -> nodetype = navigation_node :: NODETYPE_BRANCH ;
}
return $activitynode ;
}
2010-04-19 06:30:30 +00:00
/**
* Loads the navigation structure for the given activity into the activities node .
*
* This method utilises a callback within the modules lib . php file to load the
* content specific to activity given .
*
* The callback is a method : { modulename } _extend_navigation ()
* Examples :
2012-02-29 00:56:41 +01:00
* * { @ link forum_extend_navigation ()}
* * { @ link workshop_extend_navigation ()}
2010-04-19 06:30:30 +00:00
*
2011-02-07 12:16:13 +08:00
* @ param cm_info | stdClass $cm
2010-04-19 06:30:30 +00:00
* @ param stdClass $course
* @ param navigation_node $activity
* @ return bool
*/
2011-01-26 10:29:16 +00:00
protected function load_activity ( $cm , stdClass $course , navigation_node $activity ) {
2010-04-19 06:30:30 +00:00
global $CFG , $DB ;
2011-02-13 16:17:47 +01:00
2011-02-07 12:16:13 +08:00
// make sure we have a $cm from get_fast_modinfo as this contains activity access details
if ( ! ( $cm instanceof cm_info )) {
$modinfo = get_fast_modinfo ( $course );
$cm = $modinfo -> get_cm ( $cm -> id );
}
2012-02-10 13:03:55 +08:00
$activity -> nodetype = navigation_node :: NODETYPE_LEAF ;
2010-04-19 06:30:30 +00:00
$activity -> make_active ();
$file = $CFG -> dirroot . '/mod/' . $cm -> modname . '/lib.php' ;
$function = $cm -> modname . '_extend_navigation' ;
if ( file_exists ( $file )) {
require_once ( $file );
if ( function_exists ( $function )) {
$activtyrecord = $DB -> get_record ( $cm -> modname , array ( 'id' => $cm -> instance ), '*' , MUST_EXIST );
$function ( $activity , $course , $activtyrecord , $cm );
}
}
2012-02-10 13:03:55 +08:00
// Allow the active advanced grading method plugin to append module navigation
$featuresfunc = $cm -> modname . '_supports' ;
if ( function_exists ( $featuresfunc ) && $featuresfunc ( FEATURE_ADVANCED_GRADING )) {
require_once ( $CFG -> dirroot . '/grade/grading/lib.php' );
$gradingman = get_grading_manager ( $cm -> context , $cm -> modname );
$gradingman -> extend_navigation ( $this , $activity );
}
return $activity -> has_children ();
2010-04-19 06:30:30 +00:00
}
/**
2011-11-03 18:48:20 +01:00
* Loads user specific information into the navigation in the appropriate place .
2010-04-19 06:30:30 +00:00
*
* If no user is provided the current user is assumed .
*
* @ param stdClass $user
2011-11-03 18:48:20 +01:00
* @ param bool $forceforcontext probably force something to be loaded somewhere ( ask SamH if not sure what this means )
2010-04-19 06:30:30 +00:00
* @ return bool
2009-12-23 01:22:48 +00:00
*/
2010-05-17 05:38:59 +00:00
protected function load_for_user ( $user = null , $forceforcontext = false ) {
2012-05-07 12:57:42 +12:00
global $DB , $CFG , $USER , $SITE ;
2010-03-31 07:41:31 +00:00
2009-12-23 01:22:48 +00:00
if ( $user === null ) {
// We can't require login here but if the user isn't logged in we don't
// want to show anything
2010-06-03 08:11:46 +00:00
if ( ! isloggedin () || isguestuser ()) {
2009-12-23 01:22:48 +00:00
return false ;
}
$user = $USER ;
} else if ( ! is_object ( $user )) {
// If the user is not an object then get them from the database
2012-03-07 11:37:21 +13:00
$select = context_helper :: get_preload_record_columns_sql ( 'ctx' );
$sql = " SELECT u.*, $select
FROM { user } u
JOIN { context } ctx ON u . id = ctx . instanceid
WHERE u . id = : userid AND
ctx . contextlevel = : contextlevel " ;
$user = $DB -> get_record_sql ( $sql , array ( 'userid' => ( int ) $user , 'contextlevel' => CONTEXT_USER ), MUST_EXIST );
context_helper :: preload_from_record ( $user );
2009-12-23 01:22:48 +00:00
}
2010-08-26 06:23:14 +00:00
$iscurrentuser = ( $user -> id == $USER -> id );
2012-07-25 16:25:55 +08:00
$usercontext = context_user :: instance ( $user -> id );
2009-12-23 01:22:48 +00:00
// Get the course set against the page, by default this will be the site
2010-04-19 06:30:30 +00:00
$course = $this -> page -> course ;
$baseargs = array ( 'id' => $user -> id );
2012-05-07 12:57:42 +12:00
if ( $course -> id != $SITE -> id && ( ! $iscurrentuser || $forceforcontext )) {
2012-11-04 11:06:49 +13:00
$coursenode = $this -> add_course ( $course , false , self :: COURSE_CURRENT );
2009-12-23 01:22:48 +00:00
$baseargs [ 'course' ] = $course -> id ;
2012-07-25 16:25:55 +08:00
$coursecontext = context_course :: instance ( $course -> id );
2009-12-23 01:22:48 +00:00
$issitecourse = false ;
2009-08-28 08:47:31 +00:00
} else {
2009-12-23 01:22:48 +00:00
// Load all categories and get the context for the system
2012-07-25 16:25:55 +08:00
$coursecontext = context_system :: instance ();
2009-12-23 01:22:48 +00:00
$issitecourse = true ;
}
// Create a node to add user information under.
2010-05-17 05:38:59 +00:00
if ( $iscurrentuser && ! $forceforcontext ) {
2010-04-19 06:30:30 +00:00
// If it's the current user the information will go under the profile root node
$usernode = $this -> rootnodes [ 'myprofile' ];
2011-07-27 10:16:48 +08:00
$course = get_site ();
2012-07-25 16:25:55 +08:00
$coursecontext = context_course :: instance ( $course -> id );
2011-07-27 10:16:48 +08:00
$issitecourse = true ;
2009-12-23 01:22:48 +00:00
} else {
if ( ! $issitecourse ) {
// Not the current user so add it to the participants node for the current course
2010-04-19 06:30:30 +00:00
$usersnode = $coursenode -> get ( 'participants' , navigation_node :: TYPE_CONTAINER );
2010-08-17 02:07:30 +00:00
$userviewurl = new moodle_url ( '/user/view.php' , $baseargs );
2009-12-23 01:22:48 +00:00
} else {
// This is the site so add a users node to the root branch
2010-04-19 06:30:30 +00:00
$usersnode = $this -> rootnodes [ 'users' ];
2011-07-03 10:52:32 +01:00
if ( has_capability ( 'moodle/course:viewparticipants' , $coursecontext )) {
$usersnode -> action = new moodle_url ( '/user/index.php' , array ( 'id' => $course -> id ));
}
2010-08-17 02:07:30 +00:00
$userviewurl = new moodle_url ( '/user/profile.php' , $baseargs );
2009-12-23 01:22:48 +00:00
}
2010-08-27 01:44:25 +00:00
if ( ! $usersnode ) {
// We should NEVER get here, if the course hasn't been populated
// with a participants node then the navigaiton either wasn't generated
// for it (you are missing a require_login or set_context call) or
// you don't have access.... in the interests of no leaking informatin
// we simply quit...
return false ;
}
2009-12-23 01:22:48 +00:00
// Add a branch for the current user
2012-02-03 11:38:50 +08:00
$canseefullname = has_capability ( 'moodle/site:viewfullnames' , $coursecontext );
$usernode = $usersnode -> add ( fullname ( $user , $canseefullname ), $userviewurl , self :: TYPE_USER , null , $user -> id );
2010-04-19 06:30:30 +00:00
2010-07-13 02:35:31 +00:00
if ( $this -> page -> context -> contextlevel == CONTEXT_USER && $user -> id == $this -> page -> context -> instanceid ) {
$usernode -> make_active ();
}
2009-12-23 01:22:48 +00:00
}
// If the user is the current user or has permission to view the details of the requested
// user than add a view profile link.
2010-02-18 05:57:20 +00:00
if ( $iscurrentuser || has_capability ( 'moodle/user:viewdetails' , $coursecontext ) || has_capability ( 'moodle/user:viewdetails' , $usercontext )) {
2010-05-17 05:38:59 +00:00
if ( $issitecourse || ( $iscurrentuser && ! $forceforcontext )) {
2010-05-04 13:04:35 +00:00
$usernode -> add ( get_string ( 'viewprofile' ), new moodle_url ( '/user/profile.php' , $baseargs ));
} else {
$usernode -> add ( get_string ( 'viewprofile' ), new moodle_url ( '/user/view.php' , $baseargs ));
}
2009-12-23 01:22:48 +00:00
}
2011-10-06 14:00:13 +13:00
if ( ! empty ( $CFG -> navadduserpostslinks )) {
// Add nodes for forum posts and discussions if the user can view either or both
// There are no capability checks here as the content of the page is based
// purely on the forums the current user has access too.
$forumtab = $usernode -> add ( get_string ( 'forumposts' , 'forum' ));
$forumtab -> add ( get_string ( 'posts' , 'forum' ), new moodle_url ( '/mod/forum/user.php' , $baseargs ));
$forumtab -> add ( get_string ( 'discussions' , 'forum' ), new moodle_url ( '/mod/forum/user.php' , array_merge ( $baseargs , array ( 'mode' => 'discussions' ))));
}
2009-12-23 01:22:48 +00:00
2010-04-23 04:05:16 +00:00
// Add blog nodes
2012-07-19 11:30:05 +08:00
if ( ! empty ( $CFG -> enableblogs )) {
2011-06-24 16:42:41 +08:00
if ( ! $this -> cache -> cached ( 'userblogoptions' . $user -> id )) {
require_once ( $CFG -> dirroot . '/blog/lib.php' );
// Get all options for the user
$options = blog_get_options_for_user ( $user );
$this -> cache -> set ( 'userblogoptions' . $user -> id , $options );
} else {
$options = $this -> cache -> { 'userblogoptions' . $user -> id };
}
2010-04-23 04:05:16 +00:00
if ( count ( $options ) > 0 ) {
$blogs = $usernode -> add ( get_string ( 'blogs' , 'blog' ), null , navigation_node :: TYPE_CONTAINER );
2011-11-30 11:22:13 +08:00
foreach ( $options as $type => $option ) {
if ( $type == " rss " ) {
$blogs -> add ( $option [ 'string' ], $option [ 'link' ], settings_navigation :: TYPE_SETTING , null , null , new pix_icon ( 'i/rss' , '' ));
} else {
$blogs -> add ( $option [ 'string' ], $option [ 'link' ]);
}
2010-04-23 04:05:16 +00:00
}
}
}
2010-07-13 02:35:31 +00:00
if ( ! empty ( $CFG -> messaging )) {
$messageargs = null ;
2012-11-12 15:25:49 +08:00
if ( $USER -> id != $user -> id ) {
$messageargs = array ( 'user1' => $user -> id );
2010-07-13 02:35:31 +00:00
}
$url = new moodle_url ( '/message/index.php' , $messageargs );
$usernode -> add ( get_string ( 'messages' , 'message' ), $url , self :: TYPE_SETTING , null , 'messages' );
2010-06-25 08:20:16 +00:00
}
2013-01-31 12:24:37 +08:00
if ( $iscurrentuser && has_capability ( 'moodle/user:manageownfiles' , context_user :: instance ( $USER -> id ))) {
2012-05-24 16:05:30 +08:00
$url = new moodle_url ( '/user/files.php' );
2010-07-19 13:21:16 +00:00
$usernode -> add ( get_string ( 'myfiles' ), $url , self :: TYPE_SETTING );
2010-07-12 09:39:47 +00:00
}
2013-04-02 15:40:15 +08:00
if ( ! empty ( $CFG -> enablebadges ) && $iscurrentuser &&
2013-04-02 13:57:39 +13:00
has_capability ( 'moodle/badges:manageownbadges' , context_user :: instance ( $USER -> id ))) {
$url = new moodle_url ( '/badges/mybadges.php' );
$usernode -> add ( get_string ( 'mybadges' , 'badges' ), $url , self :: TYPE_SETTING );
}
2009-12-23 01:22:48 +00:00
// Add a node to view the users notes if permitted
2010-02-18 05:57:20 +00:00
if ( ! empty ( $CFG -> enablenotes ) && has_any_capability ( array ( 'moodle/notes:manage' , 'moodle/notes:view' ), $coursecontext )) {
2010-04-19 06:30:30 +00:00
$url = new moodle_url ( '/notes/index.php' , array ( 'user' => $user -> id ));
if ( $coursecontext -> instanceid ) {
$url -> param ( 'course' , $coursecontext -> instanceid );
}
$usernode -> add ( get_string ( 'notes' , 'notes' ), $url );
2009-12-23 01:22:48 +00:00
}
// If the user is the current user add the repositories for the current user
2010-07-30 09:32:51 +00:00
$hiddenfields = array_flip ( explode ( ',' , $CFG -> hiddenuserfields ));
2009-12-23 01:22:48 +00:00
if ( $iscurrentuser ) {
2011-06-24 16:42:41 +08:00
if ( ! $this -> cache -> cached ( 'contexthasrepos' . $usercontext -> id )) {
require_once ( $CFG -> dirroot . '/repository/lib.php' );
$editabletypes = repository :: get_editable_types ( $usercontext );
$haseditabletypes = ! empty ( $editabletypes );
unset ( $editabletypes );
$this -> cache -> set ( 'contexthasrepos' . $usercontext -> id , $haseditabletypes );
} else {
$haseditabletypes = $this -> cache -> { 'contexthasrepos' . $usercontext -> id };
}
if ( $haseditabletypes ) {
2010-03-20 15:02:15 +00:00
$usernode -> add ( get_string ( 'repositories' , 'repository' ), new moodle_url ( '/repository/manage_instances.php' , array ( 'contextid' => $usercontext -> id )));
2009-12-23 01:22:48 +00:00
}
2012-05-07 12:57:42 +12:00
} else if ( $course -> id == $SITE -> id && has_capability ( 'moodle/user:viewdetails' , $usercontext ) && ( ! in_array ( 'mycourses' , $hiddenfields ) || has_capability ( 'moodle/user:viewhiddendetails' , $coursecontext ))) {
2010-07-30 09:32:51 +00:00
// Add view grade report is permitted
$reports = get_plugin_list ( 'gradereport' );
arsort ( $reports ); // user is last, we want to test it first
$userscourses = enrol_get_users_courses ( $user -> id );
$userscoursesnode = $usernode -> add ( get_string ( 'courses' ));
2010-08-02 13:33:19 +00:00
2010-07-30 09:32:51 +00:00
foreach ( $userscourses as $usercourse ) {
2012-07-25 16:25:55 +08:00
$usercoursecontext = context_course :: instance ( $usercourse -> id );
2011-09-07 11:46:28 +12:00
$usercourseshortname = format_string ( $usercourse -> shortname , true , array ( 'context' => $usercoursecontext ));
$usercoursenode = $userscoursesnode -> add ( $usercourseshortname , new moodle_url ( '/user/view.php' , array ( 'id' => $user -> id , 'course' => $usercourse -> id )), self :: TYPE_CONTAINER );
2010-07-30 09:32:51 +00:00
$gradeavailable = has_capability ( 'moodle/grade:viewall' , $usercoursecontext );
if ( ! $gradeavailable && ! empty ( $usercourse -> showgrades ) && is_array ( $reports ) && ! empty ( $reports )) {
foreach ( $reports as $plugin => $plugindir ) {
if ( has_capability ( 'gradereport/' . $plugin . ':view' , $usercoursecontext )) {
//stop when the first visible plugin is found
$gradeavailable = true ;
break ;
2010-08-05 02:44:03 +00:00
}
2010-07-30 09:32:51 +00:00
}
}
if ( $gradeavailable ) {
$url = new moodle_url ( '/grade/report/index.php' , array ( 'id' => $usercourse -> id ));
$usercoursenode -> add ( get_string ( 'grades' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/grades' , '' ));
}
// Add a node to view the users notes if permitted
if ( ! empty ( $CFG -> enablenotes ) && has_any_capability ( array ( 'moodle/notes:manage' , 'moodle/notes:view' ), $usercoursecontext )) {
$url = new moodle_url ( '/notes/index.php' , array ( 'user' => $user -> id , 'course' => $usercourse -> id ));
$usercoursenode -> add ( get_string ( 'notes' , 'notes' ), $url , self :: TYPE_SETTING );
}
2011-10-29 09:45:54 +02:00
if ( can_access_course ( $usercourse , $user -> id )) {
2010-07-30 09:32:51 +00:00
$usercoursenode -> add ( get_string ( 'entercourse' ), new moodle_url ( '/course/view.php' , array ( 'id' => $usercourse -> id )), self :: TYPE_SETTING , null , null , new pix_icon ( 'i/course' , '' ));
}
2011-11-03 18:48:20 +01:00
$reporttab = $usercoursenode -> add ( get_string ( 'activityreports' ));
$reports = get_plugin_list_with_function ( 'report' , 'extend_navigation_user' , 'lib.php' );
foreach ( $reports as $reportfunction ) {
$reportfunction ( $reporttab , $user , $usercourse );
}
$reporttab -> trim_if_empty ();
2010-07-30 09:32:51 +00:00
}
2009-12-23 01:22:48 +00:00
}
return true ;
}
/**
2010-04-19 06:30:30 +00:00
* This method simply checks to see if a given module can extend the navigation .
2009-08-28 08:47:31 +00:00
*
2012-01-04 15:56:26 +08:00
* @ todo ( MDL - 25290 ) A shared caching solution should be used to save details on what extends navigation .
2011-06-24 16:42:41 +08:00
*
2009-08-28 08:47:31 +00:00
* @ param string $modname
* @ return bool
*/
2012-10-31 12:52:32 +08:00
public static function module_extends_navigation ( $modname ) {
2009-08-28 08:47:31 +00:00
global $CFG ;
2011-06-24 16:42:41 +08:00
static $extendingmodules = array ();
if ( ! array_key_exists ( $modname , $extendingmodules )) {
$extendingmodules [ $modname ] = false ;
$file = $CFG -> dirroot . '/mod/' . $modname . '/lib.php' ;
if ( file_exists ( $file )) {
$function = $modname . '_extend_navigation' ;
require_once ( $file );
$extendingmodules [ $modname ] = ( function_exists ( $function ));
2009-08-28 08:47:31 +00:00
}
}
2011-06-24 16:42:41 +08:00
return $extendingmodules [ $modname ];
2009-08-28 08:47:31 +00:00
}
/**
2010-04-19 06:30:30 +00:00
* Extends the navigation for the given user .
2010-05-30 22:56:29 +00:00
*
2010-04-19 06:30:30 +00:00
* @ param stdClass $user A user from the database
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function extend_for_user ( $user ) {
$this -> extendforuser [] = $user ;
2010-06-10 07:29:02 +00:00
}
/**
* Returns all of the users the navigation is being extended for
*
2012-01-04 15:56:26 +08:00
* @ return array An array of extending users .
2010-06-10 07:29:02 +00:00
*/
public function get_extending_users () {
return $this -> extendforuser ;
2009-08-28 08:47:31 +00:00
}
/**
2010-04-19 06:30:30 +00:00
* Adds the given course to the navigation structure .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ param stdClass $course
2011-11-15 17:12:06 +13:00
* @ param bool $forcegeneric
* @ param bool $ismycourse
2010-04-19 06:30:30 +00:00
* @ return navigation_node
2009-08-28 08:47:31 +00:00
*/
2012-07-13 17:05:47 +01:00
public function add_course ( stdClass $course , $forcegeneric = false , $coursetype = self :: COURSE_OTHER ) {
2012-05-07 12:57:42 +12:00
global $CFG , $SITE ;
2011-02-13 16:17:47 +01:00
2011-06-24 16:42:41 +08:00
// We found the course... we can return it now :)
if ( ! $forcegeneric && array_key_exists ( $course -> id , $this -> addedcourses )) {
return $this -> addedcourses [ $course -> id ];
}
2012-07-25 16:25:55 +08:00
$coursecontext = context_course :: instance ( $course -> id );
2011-09-07 11:46:28 +12:00
2012-05-07 12:57:42 +12:00
if ( $course -> id != $SITE -> id && ! $course -> visible ) {
2011-06-24 16:42:41 +08:00
if ( is_role_switched ( $course -> id )) {
// user has to be able to access course in order to switch, let's skip the visibility test here
2011-09-07 11:46:28 +12:00
} else if ( ! has_capability ( 'moodle/course:viewhiddencourses' , $coursecontext )) {
2011-06-24 16:42:41 +08:00
return false ;
2011-02-13 16:17:47 +01:00
}
2009-08-28 08:47:31 +00:00
}
2012-05-07 12:57:42 +12:00
$issite = ( $course -> id == $SITE -> id );
2011-09-07 11:46:28 +12:00
$shortname = format_string ( $course -> shortname , true , array ( 'context' => $coursecontext ));
2013-01-24 09:29:25 +13:00
$fullname = format_string ( $course -> fullname , true , array ( 'context' => $coursecontext ));
// This is the name that will be shown for the course.
$coursename = empty ( $CFG -> navshowfullcoursenames ) ? $shortname : $fullname ;
2010-05-13 09:57:43 +00:00
if ( $issite ) {
2010-04-19 06:30:30 +00:00
$parent = $this ;
2010-05-13 09:57:43 +00:00
$url = null ;
2011-07-27 13:22:34 +08:00
if ( empty ( $CFG -> usesitenameforsitepages )) {
2013-01-24 09:29:25 +13:00
$coursename = get_string ( 'sitepages' );
2011-07-27 13:22:34 +08:00
}
2012-07-13 17:05:47 +01:00
} else if ( $coursetype == self :: COURSE_CURRENT ) {
$parent = $this -> rootnodes [ 'currentcourse' ];
$url = new moodle_url ( '/course/view.php' , array ( 'id' => $course -> id ));
} else if ( $coursetype == self :: COURSE_MY && ! $forcegeneric ) {
2013-02-07 11:04:24 +08:00
if ( ! empty ( $CFG -> navshowmycoursecategories ) && ( $parent = $this -> rootnodes [ 'mycourses' ] -> find ( $course -> category , self :: TYPE_MY_CATEGORY ))) {
2012-02-22 15:30:13 +13:00
// Nothing to do here the above statement set $parent to the category within mycourses.
} else {
$parent = $this -> rootnodes [ 'mycourses' ];
}
2010-04-19 06:30:30 +00:00
$url = new moodle_url ( '/course/view.php' , array ( 'id' => $course -> id ));
2009-12-23 01:22:48 +00:00
} else {
2010-04-19 06:30:30 +00:00
$parent = $this -> rootnodes [ 'courses' ];
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/course/view.php' , array ( 'id' => $course -> id ));
2012-11-04 11:06:49 +13:00
if ( ! empty ( $course -> category ) && $this -> show_categories ( $coursetype == self :: COURSE_MY )) {
if ( ! $this -> is_category_fully_loaded ( $course -> category )) {
2011-11-15 17:12:06 +13:00
// We need to load the category structure for this course
2012-04-19 10:27:53 +12:00
$this -> load_all_categories ( $course -> category , false );
2011-11-15 17:12:06 +13:00
}
if ( array_key_exists ( $course -> category , $this -> addedcategories )) {
$parent = $this -> addedcategories [ $course -> category ];
// This could lead to the course being created so we should check whether it is the case again
if ( ! $forcegeneric && array_key_exists ( $course -> id , $this -> addedcourses )) {
return $this -> addedcourses [ $course -> id ];
}
2011-06-27 15:11:28 +08:00
}
2010-05-13 09:57:43 +00:00
}
}
2013-01-24 09:29:25 +13:00
$coursenode = $parent -> add ( $coursename , $url , self :: TYPE_COURSE , $shortname , $course -> id );
2010-04-19 06:30:30 +00:00
$coursenode -> nodetype = self :: NODETYPE_BRANCH ;
$coursenode -> hidden = ( ! $course -> visible );
2013-03-20 17:27:08 +13:00
// We need to decode &'s here as they will have been added by format_string above and attributes will be encoded again
// later.
$coursenode -> title ( str_replace ( '&' , '&' , $fullname ));
2011-06-24 16:42:41 +08:00
if ( ! $forcegeneric ) {
2012-05-06 13:31:55 +02:00
$this -> addedcourses [ $course -> id ] = $coursenode ;
2011-06-24 16:42:41 +08:00
}
2010-04-19 06:30:30 +00:00
return $coursenode ;
2009-08-28 08:47:31 +00:00
}
2011-11-15 17:12:06 +13:00
/**
* Returns true if the category has already been loaded as have any child categories
*
* @ param int $categoryid
* @ return bool
*/
protected function is_category_fully_loaded ( $categoryid ) {
return ( array_key_exists ( $categoryid , $this -> addedcategories ) && ( $this -> allcategoriesloaded || $this -> addedcategories [ $categoryid ] -> children -> count () > 0 ));
}
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* Adds essential course nodes to the navigation for the given course .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* This method adds nodes such as reports , blogs and participants
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ param navigation_node $coursenode
* @ param stdClass $course
2012-01-04 15:56:26 +08:00
* @ return bool returns true on successful addition of a node .
2009-08-28 08:47:31 +00:00
*/
2011-07-13 13:39:29 +08:00
public function add_course_essentials ( $coursenode , stdClass $course ) {
2012-05-07 12:57:42 +12:00
global $CFG , $SITE ;
2009-08-28 08:47:31 +00:00
2012-05-07 12:57:42 +12:00
if ( $course -> id == $SITE -> id ) {
2010-04-19 06:30:30 +00:00
return $this -> add_front_page_course_essentials ( $coursenode , $course );
2009-08-28 08:47:31 +00:00
}
2011-07-13 13:39:29 +08:00
if ( $coursenode == false || ! ( $coursenode instanceof navigation_node ) || $coursenode -> get ( 'participants' , navigation_node :: TYPE_CONTAINER )) {
2010-04-19 06:30:30 +00:00
return true ;
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
//Participants
if ( has_capability ( 'moodle/course:viewparticipants' , $this -> page -> context )) {
$participants = $coursenode -> add ( get_string ( 'participants' ), new moodle_url ( '/user/index.php?id=' . $course -> id ), self :: TYPE_CONTAINER , get_string ( 'participants' ), 'participants' );
$currentgroup = groups_get_course_group ( $course , true );
2012-05-07 12:57:42 +12:00
if ( $course -> id == $SITE -> id ) {
2013-02-19 10:46:51 +13:00
$filtervar = 'courseid' ;
2010-04-19 06:30:30 +00:00
$filterselect = '' ;
} else if ( $course -> id && ! $currentgroup ) {
2013-02-19 10:46:51 +13:00
$filtervar = 'courseid' ;
2010-04-19 06:30:30 +00:00
$filterselect = $course -> id ;
} else {
2013-02-19 10:46:51 +13:00
$filtervar = 'groupid' ;
2010-04-19 06:30:30 +00:00
$filterselect = $currentgroup ;
}
$filterselect = clean_param ( $filterselect , PARAM_INT );
2011-03-20 13:34:51 +01:00
if (( $CFG -> bloglevel == BLOG_GLOBAL_LEVEL or ( $CFG -> bloglevel == BLOG_SITE_LEVEL and ( isloggedin () and ! isguestuser ())))
2012-07-25 16:25:55 +08:00
and has_capability ( 'moodle/blog:view' , context_system :: instance ())) {
2013-02-19 10:46:51 +13:00
$blogsurls = new moodle_url ( '/blog/index.php' , array ( $filtervar => $filterselect ));
2012-03-09 15:08:25 +08:00
$participants -> add ( get_string ( 'blogscourse' , 'blog' ), $blogsurls -> out ());
2010-04-19 06:30:30 +00:00
}
if ( ! empty ( $CFG -> enablenotes ) && ( has_capability ( 'moodle/notes:manage' , $this -> page -> context ) || has_capability ( 'moodle/notes:view' , $this -> page -> context ))) {
2011-10-18 22:56:38 +01:00
$participants -> add ( get_string ( 'notes' , 'notes' ), new moodle_url ( '/notes/index.php' , array ( 'filtertype' => 'course' , 'filterselect' => $course -> id )));
2010-04-19 06:30:30 +00:00
}
2010-05-25 03:34:08 +00:00
} else if ( count ( $this -> extendforuser ) > 0 || $this -> page -> course -> id == $course -> id ) {
2010-04-19 06:30:30 +00:00
$participants = $coursenode -> add ( get_string ( 'participants' ), null , self :: TYPE_CONTAINER , get_string ( 'participants' ), 'participants' );
}
2013-04-02 13:57:39 +13:00
// Badges.
2013-04-06 14:24:48 +13:00
if ( ! empty ( $CFG -> enablebadges ) && has_capability ( 'moodle/badges:viewbadges' , $this -> page -> context )) {
2013-04-02 13:57:39 +13:00
$url = new moodle_url ( $CFG -> wwwroot . '/badges/view.php' ,
array ( 'type' => 2 , 'id' => $course -> id ));
$coursenode -> add ( get_string ( 'coursebadges' , 'badges' ), null ,
navigation_node :: TYPE_CONTAINER , null , 'coursebadges' );
$coursenode -> get ( 'coursebadges' ) -> add ( get_string ( 'badgesview' , 'badges' ), $url ,
navigation_node :: TYPE_SETTING , null , 'badgesview' ,
new pix_icon ( 'i/badge' , get_string ( 'badgesview' , 'badges' )));
}
2009-08-28 08:47:31 +00:00
return true ;
}
2010-08-05 02:44:03 +00:00
/**
2012-01-04 15:56:26 +08:00
* This generates the structure of the course that won ' t be generated when
2010-08-05 02:44:03 +00:00
* the modules and sections are added .
*
* Things such as the reports branch , the participants branch , blogs ... get
* added to the course node by this method .
*
* @ param navigation_node $coursenode
* @ param stdClass $course
* @ return bool True for successfull generation
*/
2010-04-19 06:30:30 +00:00
public function add_front_page_course_essentials ( navigation_node $coursenode , stdClass $course ) {
global $CFG ;
2009-08-28 08:47:31 +00:00
2010-09-10 03:13:45 +00:00
if ( $coursenode == false || $coursenode -> get ( 'frontpageloaded' , navigation_node :: TYPE_CUSTOM )) {
2010-04-19 06:30:30 +00:00
return true ;
2009-12-23 01:22:48 +00:00
}
2010-09-10 03:13:45 +00:00
// Hidden node that we use to determine if the front page navigation is loaded.
// This required as there are not other guaranteed nodes that may be loaded.
$coursenode -> add ( 'frontpageloaded' , null , self :: TYPE_CUSTOM , null , 'frontpageloaded' ) -> display = false ;
2010-04-19 06:30:30 +00:00
//Participants
2010-10-06 06:50:36 +00:00
if ( has_capability ( 'moodle/course:viewparticipants' , get_system_context ())) {
2010-04-19 06:30:30 +00:00
$coursenode -> add ( get_string ( 'participants' ), new moodle_url ( '/user/index.php?id=' . $course -> id ), self :: TYPE_CUSTOM , get_string ( 'participants' ), 'participants' );
}
2010-05-30 22:56:29 +00:00
2010-10-05 02:38:40 +00:00
$filterselect = 0 ;
2010-05-01 14:33:07 +00:00
// Blogs
2012-07-19 11:30:05 +08:00
if ( ! empty ( $CFG -> enableblogs )
2011-03-20 13:34:51 +01:00
and ( $CFG -> bloglevel == BLOG_GLOBAL_LEVEL or ( $CFG -> bloglevel == BLOG_SITE_LEVEL and ( isloggedin () and ! isguestuser ())))
2012-07-25 16:25:55 +08:00
and has_capability ( 'moodle/blog:view' , context_system :: instance ())) {
2011-03-20 13:34:51 +01:00
$blogsurls = new moodle_url ( '/blog/index.php' , array ( 'courseid' => $filterselect ));
2012-03-09 15:08:25 +08:00
$coursenode -> add ( get_string ( 'blogssite' , 'blog' ), $blogsurls -> out ());
2009-08-28 08:47:31 +00:00
}
2010-05-01 14:33:07 +00:00
2013-04-02 13:57:39 +13:00
//Badges
2013-04-29 14:36:14 +12:00
if ( ! empty ( $CFG -> enablebadges ) && ! empty ( $CFG -> badges_allowcoursebadges ) && has_capability ( 'moodle/badges:viewbadges' , $this -> page -> context )) {
2013-04-02 13:57:39 +13:00
$url = new moodle_url ( $CFG -> wwwroot . '/badges/view.php' , array ( 'type' => 1 ));
$coursenode -> add ( get_string ( 'sitebadges' , 'badges' ), $url , navigation_node :: TYPE_CUSTOM );
}
2010-05-01 14:33:07 +00:00
// Notes
2010-04-19 06:30:30 +00:00
if ( ! empty ( $CFG -> enablenotes ) && ( has_capability ( 'moodle/notes:manage' , $this -> page -> context ) || has_capability ( 'moodle/notes:view' , $this -> page -> context ))) {
$coursenode -> add ( get_string ( 'notes' , 'notes' ), new moodle_url ( '/notes/index.php' , array ( 'filtertype' => 'course' , 'filterselect' => $filterselect )));
}
2010-05-01 14:33:07 +00:00
// Tags
if ( ! empty ( $CFG -> usetags ) && isloggedin ()) {
2010-04-19 06:30:30 +00:00
$coursenode -> add ( get_string ( 'tags' , 'tag' ), new moodle_url ( '/tag/search.php' ));
2009-08-28 08:47:31 +00:00
}
2009-10-14 09:08:43 +00:00
2011-10-06 12:13:13 +13:00
if ( isloggedin ()) {
// Calendar
$calendarurl = new moodle_url ( '/calendar/view.php' , array ( 'view' => 'month' ));
$coursenode -> add ( get_string ( 'calendar' , 'calendar' ), $calendarurl , self :: TYPE_CUSTOM , null , 'calendar' );
}
2009-10-14 09:08:43 +00:00
2010-04-19 06:30:30 +00:00
return true ;
2009-10-14 09:08:43 +00:00
}
2009-11-04 07:23:19 +00:00
2010-04-19 06:30:30 +00:00
/**
* Clears the navigation cache
*/
public function clear_cache () {
$this -> cache -> clear ();
2009-11-04 07:23:19 +00:00
}
2010-04-21 09:44:16 +00:00
2010-08-05 02:44:03 +00:00
/**
* Sets an expansion limit for the navigation
*
* The expansion limit is used to prevent the display of content that has a type
* greater than the provided $type .
*
* Can be used to ensure things such as activities or activity content don ' t get
* shown on the navigation .
* They are still generated in order to ensure the navbar still makes sense .
*
* @ param int $type One of navigation_node :: TYPE_ *
2012-01-04 15:56:26 +08:00
* @ return bool true when complete .
2010-08-05 02:44:03 +00:00
*/
2010-04-21 09:44:16 +00:00
public function set_expansion_limit ( $type ) {
2012-05-07 12:57:42 +12:00
global $SITE ;
2010-04-21 09:44:16 +00:00
$nodes = $this -> find_all_of_type ( $type );
2013-04-09 12:06:26 +12:00
// We only want to hide specific types of nodes.
// Only nodes that represent "structure" in the navigation tree should be hidden.
// If we hide all nodes then we risk hiding vital information.
$typestohide = array (
self :: TYPE_CATEGORY ,
self :: TYPE_COURSE ,
self :: TYPE_SECTION ,
self :: TYPE_ACTIVITY
);
2013-02-19 11:38:43 +13:00
foreach ( $nodes as $node ) {
2010-07-01 03:33:16 +00:00
// We need to generate the full site node
2012-05-07 12:57:42 +12:00
if ( $type == self :: TYPE_COURSE && $node -> key == $SITE -> id ) {
2010-07-01 03:33:16 +00:00
continue ;
}
2013-02-19 11:38:43 +13:00
foreach ( $node -> children as $child ) {
2013-04-09 12:06:26 +12:00
$child -> hide ( $typestohide );
2010-04-21 09:44:16 +00:00
}
}
return true ;
}
2010-08-05 02:44:03 +00:00
/**
* Attempts to get the navigation with the given key from this nodes children .
*
* This function only looks at this nodes children , it does NOT look recursivily .
* If the node can ' t be found then false is returned .
*
2012-02-29 00:56:41 +01:00
* If you need to search recursivily then use the { @ link global_navigation :: find ()} method .
2010-08-05 02:44:03 +00:00
*
2012-02-29 00:56:41 +01:00
* Note : If you are trying to set the active node { @ link navigation_node :: override_active_url ()}
2010-08-05 02:44:03 +00:00
* may be of more use to you .
*
* @ param string | int $key The key of the node you wish to receive .
* @ param int $type One of navigation_node :: TYPE_ *
* @ return navigation_node | false
*/
2010-06-10 07:47:59 +00:00
public function get ( $key , $type = null ) {
2010-06-11 04:25:22 +00:00
if ( ! $this -> initialised ) {
$this -> initialise ();
}
2010-06-10 07:55:38 +00:00
return parent :: get ( $key , $type );
2010-06-10 07:47:59 +00:00
}
2010-08-05 02:44:03 +00:00
/**
2012-01-04 15:56:26 +08:00
* Searches this nodes children and their children to find a navigation node
2010-08-05 02:44:03 +00:00
* with the matching key and type .
*
* This method is recursive and searches children so until either a node is
2012-01-04 15:56:26 +08:00
* found or there are no more nodes to search .
2010-08-05 02:44:03 +00:00
*
* If you know that the node being searched for is a child of this node
2012-02-29 00:56:41 +01:00
* then use the { @ link global_navigation :: get ()} method instead .
2010-08-05 02:44:03 +00:00
*
2012-02-29 00:56:41 +01:00
* Note : If you are trying to set the active node { @ link navigation_node :: override_active_url ()}
2010-08-05 02:44:03 +00:00
* may be of more use to you .
*
* @ param string | int $key The key of the node you wish to receive .
* @ param int $type One of navigation_node :: TYPE_ *
* @ return navigation_node | false
*/
2010-06-10 07:47:59 +00:00
public function find ( $key , $type ) {
2010-06-11 04:25:22 +00:00
if ( ! $this -> initialised ) {
$this -> initialise ();
}
2012-11-04 11:06:49 +13:00
if ( $type == self :: TYPE_ROOTNODE && array_key_exists ( $key , $this -> rootnodes )) {
return $this -> rootnodes [ $key ];
}
2010-06-10 07:55:38 +00:00
return parent :: find ( $key , $type );
2010-06-10 07:47:59 +00:00
}
2013-02-19 12:12:24 +13:00
/**
* They 've expanded the ' my courses ' branch .
*/
protected function load_courses_enrolled () {
global $CFG , $DB ;
$sortorder = 'visible DESC' ;
2013-03-07 10:21:03 +01:00
// Prevent undefined $CFG->navsortmycoursessort errors.
if ( empty ( $CFG -> navsortmycoursessort )) {
$CFG -> navsortmycoursessort = 'sortorder' ;
}
2013-02-19 12:12:24 +13:00
// Append the chosen sortorder.
$sortorder = $sortorder . ',' . $CFG -> navsortmycoursessort . ' ASC' ;
$courses = enrol_get_my_courses ( null , $sortorder );
2013-03-06 14:35:19 +13:00
if ( count ( $courses ) && $this -> show_my_categories ()) {
2013-02-19 12:12:24 +13:00
// OK Actually we are loading categories. We only want to load categories that have a parent of 0.
// In order to make sure we load everything required we must first find the categories that are not
// base categories and work out the bottom category in thier path.
$categoryids = array ();
foreach ( $courses as $course ) {
$categoryids [] = $course -> category ;
}
$categoryids = array_unique ( $categoryids );
list ( $sql , $params ) = $DB -> get_in_or_equal ( $categoryids );
$categories = $DB -> get_recordset_select ( 'course_categories' , 'id ' . $sql . ' AND parent <> 0' , $params , 'sortorder, id' , 'id, path' );
foreach ( $categories as $category ) {
$bits = explode ( '/' , trim ( $category -> path , '/' ));
$categoryids [] = array_shift ( $bits );
}
$categoryids = array_unique ( $categoryids );
$categories -> close ();
// Now we load the base categories.
list ( $sql , $params ) = $DB -> get_in_or_equal ( $categoryids );
$categories = $DB -> get_recordset_select ( 'course_categories' , 'id ' . $sql . ' AND parent = 0' , $params , 'sortorder, id' );
foreach ( $categories as $category ) {
$this -> add_category ( $category , $this -> rootnodes [ 'mycourses' ]);
}
$categories -> close ();
} else {
foreach ( $courses as $course ) {
$this -> add_course ( $course , false , self :: COURSE_MY );
}
}
}
2009-08-28 08:47:31 +00:00
}
/**
2012-05-07 12:57:42 +12:00
* The global navigation class used especially for AJAX requests .
2009-08-28 08:47:31 +00:00
*
* The primary methods that are used in the global navigation class have been overriden
* to ensure that only the relevant branch is generated at the root of the tree .
* This can be done because AJAX is only used when the backwards structure for the
* requested branch exists .
* This has been done only because it shortens the amounts of information that is generated
* which of course will speed up the response time .. because no one likes laggy AJAX .
*
2012-01-04 15:56:26 +08:00
* @ package core
* @ category navigation
2009-08-28 08:47:31 +00:00
* @ copyright 2009 Sam Hemelryk
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
2010-02-18 05:57:20 +00:00
class global_navigation_for_ajax extends global_navigation {
2010-04-19 06:30:30 +00:00
2012-01-04 15:56:26 +08:00
/** @var int used for determining what type of navigation_node::TYPE_* is being used */
2010-08-27 02:09:07 +00:00
protected $branchtype ;
2012-01-04 15:56:26 +08:00
/** @var int the instance id */
2010-08-27 02:09:07 +00:00
protected $instanceid ;
2012-01-04 15:56:26 +08:00
/** @var array Holds an array of expandable nodes */
2010-04-19 06:30:30 +00:00
protected $expandable = array ();
2009-08-28 08:47:31 +00:00
/**
2012-01-04 15:56:26 +08:00
* Constructs the navigation for use in an AJAX request
*
* @ param moodle_page $page moodle_page object
* @ param int $branchtype
* @ param int $id
2010-04-19 06:30:30 +00:00
*/
2010-06-11 04:25:22 +00:00
public function __construct ( $page , $branchtype , $id ) {
2010-05-13 09:57:43 +00:00
$this -> page = $page ;
2010-04-19 06:30:30 +00:00
$this -> cache = new navigation_cache ( NAVIGATION_CACHE_NAME );
$this -> children = new navigation_node_collection ();
2010-08-27 02:09:07 +00:00
$this -> branchtype = $branchtype ;
$this -> instanceid = $id ;
$this -> initialise ();
2010-04-19 06:30:30 +00:00
}
/**
* Initialise the navigation given the type and id for the branch to expand .
2009-08-28 08:47:31 +00:00
*
2012-01-04 15:56:26 +08:00
* @ return array An array of the expandable nodes
2009-08-28 08:47:31 +00:00
*/
2010-08-27 02:09:07 +00:00
public function initialise () {
2012-11-04 11:06:49 +13:00
global $DB , $SITE ;
2010-02-18 05:57:20 +00:00
2009-08-28 08:47:31 +00:00
if ( $this -> initialised || during_initial_install ()) {
2009-09-10 02:19:12 +00:00
return $this -> expandable ;
2009-08-28 08:47:31 +00:00
}
2010-06-11 04:25:22 +00:00
$this -> initialised = true ;
$this -> rootnodes = array ();
2011-06-24 16:42:41 +08:00
$this -> rootnodes [ 'site' ] = $this -> add_course ( $SITE );
2012-11-04 11:06:49 +13:00
$this -> rootnodes [ 'mycourses' ] = $this -> add ( get_string ( 'mycourses' ), new moodle_url ( '/my' ), self :: TYPE_ROOTNODE , null , 'mycourses' );
2010-06-11 04:25:22 +00:00
$this -> rootnodes [ 'courses' ] = $this -> add ( get_string ( 'courses' ), null , self :: TYPE_ROOTNODE , null , 'courses' );
2010-02-18 05:57:20 +00:00
// Branchtype will be one of navigation_node::TYPE_*
2010-08-27 02:09:07 +00:00
switch ( $this -> branchtype ) {
2012-11-04 11:06:49 +13:00
case 0 :
if ( $this -> instanceid === 'mycourses' ) {
$this -> load_courses_enrolled ();
} else if ( $this -> instanceid === 'courses' ) {
$this -> load_courses_other ();
}
break ;
2010-05-13 09:57:43 +00:00
case self :: TYPE_CATEGORY :
2012-03-30 13:27:12 +13:00
$this -> load_category ( $this -> instanceid );
2010-05-13 09:57:43 +00:00
break ;
2013-02-07 11:04:24 +08:00
case self :: TYPE_MY_CATEGORY :
$this -> load_category ( $this -> instanceid , self :: TYPE_MY_CATEGORY );
break ;
2010-02-18 05:57:20 +00:00
case self :: TYPE_COURSE :
2010-08-27 02:09:07 +00:00
$course = $DB -> get_record ( 'course' , array ( 'id' => $this -> instanceid ), '*' , MUST_EXIST );
2012-03-27 11:32:09 +13:00
require_course_login ( $course , true , null , false , true );
2012-07-25 16:25:55 +08:00
$this -> page -> set_context ( context_course :: instance ( $course -> id ));
2010-04-19 06:30:30 +00:00
$coursenode = $this -> add_course ( $course );
$this -> add_course_essentials ( $coursenode , $course );
2012-09-18 09:57:37 +08:00
$this -> load_course_sections ( $course , $coursenode );
2009-08-28 08:47:31 +00:00
break ;
2010-02-18 05:57:20 +00:00
case self :: TYPE_SECTION :
2010-04-19 06:30:30 +00:00
$sql = ' SELECT c .* , cs . section AS sectionnumber
2010-02-18 05:57:20 +00:00
FROM { course } c
LEFT JOIN { course_sections } cs ON cs . course = c . id
WHERE cs . id = ? ' ;
2010-08-27 02:09:07 +00:00
$course = $DB -> get_record_sql ( $sql , array ( $this -> instanceid ), MUST_EXIST );
2012-03-27 11:32:09 +13:00
require_course_login ( $course , true , null , false , true );
2012-07-25 16:25:55 +08:00
$this -> page -> set_context ( context_course :: instance ( $course -> id ));
2010-04-19 06:30:30 +00:00
$coursenode = $this -> add_course ( $course );
$this -> add_course_essentials ( $coursenode , $course );
2012-10-31 12:52:32 +08:00
$this -> load_course_sections ( $course , $coursenode , $course -> sectionnumber );
2009-08-28 08:47:31 +00:00
break ;
2010-02-18 05:57:20 +00:00
case self :: TYPE_ACTIVITY :
2011-03-21 10:22:28 +08:00
$sql = " SELECT c.*
FROM { course } c
JOIN { course_modules } cm ON cm . course = c . id
WHERE cm . id = : cmid " ;
$params = array ( 'cmid' => $this -> instanceid );
$course = $DB -> get_record_sql ( $sql , $params , MUST_EXIST );
2011-02-07 12:16:13 +08:00
$modinfo = get_fast_modinfo ( $course );
$cm = $modinfo -> get_cm ( $this -> instanceid );
2012-03-27 11:32:09 +13:00
require_course_login ( $course , true , $cm , false , true );
2012-07-25 16:25:55 +08:00
$this -> page -> set_context ( context_module :: instance ( $cm -> id ));
2010-04-19 06:30:30 +00:00
$coursenode = $this -> load_course ( $course );
2012-10-31 12:52:32 +08:00
if ( $course -> id != $SITE -> id ) {
$this -> load_course_sections ( $course , $coursenode , null , $cm );
2010-05-20 06:01:00 +00:00
}
2012-10-31 12:52:32 +08:00
$modulenode = $this -> load_activity ( $cm , $course , $coursenode -> find ( $cm -> id , self :: TYPE_ACTIVITY ));
2009-08-28 08:47:31 +00:00
break ;
2010-02-18 05:57:20 +00:00
default :
2010-04-19 06:30:30 +00:00
throw new Exception ( 'Unknown type' );
2010-02-18 05:57:20 +00:00
return $this -> expandable ;
2009-08-28 08:47:31 +00:00
}
2010-07-28 05:34:09 +00:00
2012-05-07 12:57:42 +12:00
if ( $this -> page -> context -> contextlevel == CONTEXT_COURSE && $this -> page -> context -> instanceid != $SITE -> id ) {
2010-07-28 05:34:09 +00:00
$this -> load_for_user ( null , true );
}
2010-02-18 05:57:20 +00:00
$this -> find_expandable ( $this -> expandable );
return $this -> expandable ;
2010-06-11 04:25:22 +00:00
}
2012-11-04 11:06:49 +13:00
/**
* They 've expanded the general ' courses ' branch .
*/
protected function load_courses_other () {
$this -> load_all_courses ();
}
2012-03-30 13:27:12 +13:00
/**
* Loads a single category into the AJAX navigation .
*
* This function is special in that it doesn ' t concern itself with the parent of
* the requested category or its siblings .
* This is because with the AJAX navigation we know exactly what is wanted and only need to
* request that .
*
* @ global moodle_database $DB
2013-02-07 11:04:24 +08:00
* @ param int $categoryid id of category to load in navigation .
* @ param int $nodetype type of node , if category is under MyHome then it ' s TYPE_MY_CATEGORY
* @ return void .
2012-03-30 13:27:12 +13:00
*/
2013-02-07 11:04:24 +08:00
protected function load_category ( $categoryid , $nodetype = self :: TYPE_CATEGORY ) {
2012-03-30 13:27:12 +13:00
global $CFG , $DB ;
$limit = 20 ;
if ( ! empty ( $CFG -> navcourselimit )) {
$limit = ( int ) $CFG -> navcourselimit ;
}
$catcontextsql = context_helper :: get_preload_record_columns_sql ( 'ctx' );
$sql = " SELECT cc.*, $catcontextsql
FROM { course_categories } cc
JOIN { context } ctx ON cc . id = ctx . instanceid
WHERE ctx . contextlevel = " .CONTEXT_COURSECAT. " AND
( cc . id = : categoryid1 OR cc . parent = : categoryid2 )
2012-05-18 10:37:44 +12:00
ORDER BY cc . depth ASC , cc . sortorder ASC , cc . id ASC " ;
2012-03-30 13:27:12 +13:00
$params = array ( 'categoryid1' => $categoryid , 'categoryid2' => $categoryid );
$categories = $DB -> get_recordset_sql ( $sql , $params , 0 , $limit );
2013-02-20 11:12:11 +08:00
$categorylist = array ();
2012-03-30 13:27:12 +13:00
$subcategories = array ();
$basecategory = null ;
foreach ( $categories as $category ) {
2013-02-20 11:12:11 +08:00
$categorylist [] = $category -> id ;
2012-03-30 13:27:12 +13:00
context_helper :: preload_from_record ( $category );
if ( $category -> id == $categoryid ) {
2013-02-07 11:04:24 +08:00
$this -> add_category ( $category , $this , $nodetype );
2012-03-30 13:27:12 +13:00
$basecategory = $this -> addedcategories [ $category -> id ];
} else {
$subcategories [] = $category ;
}
}
$categories -> close ();
if ( ! is_null ( $basecategory )) {
foreach ( $subcategories as $category ) {
2013-02-07 11:04:24 +08:00
$this -> add_category ( $category , $basecategory , $nodetype );
2012-03-30 13:27:12 +13:00
}
}
2013-02-07 11:04:24 +08:00
// If category is shown in MyHome then only show enrolled courses, else show all courses.
if ( $nodetype === self :: TYPE_MY_CATEGORY ) {
$courses = enrol_get_my_courses ();
foreach ( $courses as $course ) {
2013-02-20 11:12:11 +08:00
// Add course if it's in category.
if ( in_array ( $course -> category , $categorylist )) {
$this -> add_course ( $course , true , self :: COURSE_MY );
}
2013-02-07 11:04:24 +08:00
}
} else {
$courses = $DB -> get_recordset ( 'course' , array ( 'category' => $categoryid ), 'sortorder' , '*' , 0 , $limit );
foreach ( $courses as $course ) {
$this -> add_course ( $course );
}
$courses -> close ();
2012-03-30 13:27:12 +13:00
}
}
2010-08-05 02:44:03 +00:00
/**
* Returns an array of expandable nodes
* @ return array
*/
2010-06-11 04:25:22 +00:00
public function get_expandable () {
return $this -> expandable ;
2009-08-28 08:47:31 +00:00
}
}
/**
* Navbar class
*
* This class is used to manage the navbar , which is initialised from the navigation
* object held by PAGE
*
2012-01-04 15:56:26 +08:00
* @ package core
* @ category navigation
2009-08-28 08:47:31 +00:00
* @ copyright 2009 Sam Hemelryk
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
class navbar extends navigation_node {
2012-01-04 15:56:26 +08:00
/** @var bool A switch for whether the navbar is initialised or not */
2009-08-28 08:47:31 +00:00
protected $initialised = false ;
2012-01-04 15:56:26 +08:00
/** @var mixed keys used to reference the nodes on the navbar */
2009-08-28 08:47:31 +00:00
protected $keys = array ();
2012-01-04 15:56:26 +08:00
/** @var null|string content of the navbar */
2009-08-28 08:47:31 +00:00
protected $content = null ;
2012-01-04 15:56:26 +08:00
/** @var moodle_page object the moodle page that this navbar belongs to */
2009-08-28 08:47:31 +00:00
protected $page ;
2012-01-04 15:56:26 +08:00
/** @var bool A switch for whether to ignore the active navigation information */
2009-09-08 08:43:44 +00:00
protected $ignoreactive = false ;
2012-01-04 15:56:26 +08:00
/** @var bool A switch to let us know if we are in the middle of an install */
2009-08-28 08:47:31 +00:00
protected $duringinstall = false ;
2012-01-04 15:56:26 +08:00
/** @var bool A switch for whether the navbar has items */
2009-12-23 01:22:48 +00:00
protected $hasitems = false ;
2012-01-04 15:56:26 +08:00
/** @var array An array of navigation nodes for the navbar */
2010-04-19 06:30:30 +00:00
protected $items ;
2012-01-04 15:56:26 +08:00
/** @var array An array of child node objects */
2010-04-19 06:30:30 +00:00
public $children = array ();
2012-01-04 15:56:26 +08:00
/** @var bool A switch for whether we want to include the root node in the navbar */
2010-05-05 03:27:22 +00:00
public $includesettingsbase = false ;
2009-08-28 08:47:31 +00:00
/**
* The almighty constructor
2010-04-19 06:30:30 +00:00
*
* @ param moodle_page $page
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function __construct ( moodle_page $page ) {
2010-02-18 05:57:20 +00:00
global $CFG ;
2009-08-28 08:47:31 +00:00
if ( during_initial_install ()) {
$this -> duringinstall = true ;
return false ;
}
$this -> page = $page ;
$this -> text = get_string ( 'home' );
$this -> shorttext = get_string ( 'home' );
$this -> action = new moodle_url ( $CFG -> wwwroot );
$this -> nodetype = self :: NODETYPE_BRANCH ;
$this -> type = self :: TYPE_SYSTEM ;
}
/**
* Quick check to see if the navbar will have items in .
*
* @ return bool Returns true if the navbar will have items , false otherwise
*/
public function has_items () {
if ( $this -> duringinstall ) {
return false ;
2009-12-23 01:22:48 +00:00
} else if ( $this -> hasitems !== false ) {
return true ;
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
$this -> page -> navigation -> initialise ( $this -> page );
2009-09-23 06:05:36 +00:00
2009-12-23 01:22:48 +00:00
$activenodefound = ( $this -> page -> navigation -> contains_active_node () ||
2010-04-19 06:30:30 +00:00
$this -> page -> settingsnav -> contains_active_node ());
2009-09-23 06:05:36 +00:00
2010-04-19 06:30:30 +00:00
$outcome = ( count ( $this -> children ) > 0 || ( ! $this -> ignoreactive && $activenodefound ));
2009-12-23 01:22:48 +00:00
$this -> hasitems = $outcome ;
2009-09-23 06:05:36 +00:00
return $outcome ;
2009-09-08 08:43:44 +00:00
}
2010-04-19 06:30:30 +00:00
/**
* Turn on / off ignore active
*
* @ param bool $setting
*/
2009-09-08 08:43:44 +00:00
public function ignore_active ( $setting = true ) {
$this -> ignoreactive = ( $setting );
2009-08-28 08:47:31 +00:00
}
2012-01-04 15:56:26 +08:00
/**
* Gets a navigation node
*
* @ param string | int $key for referencing the navbar nodes
* @ param int $type navigation_node :: TYPE_ *
* @ return navigation_node | bool
*/
2010-04-19 06:30:30 +00:00
public function get ( $key , $type = null ) {
foreach ( $this -> children as & $child ) {
if ( $child -> key === $key && ( $type == null || $type == $child -> type )) {
return $child ;
}
}
return false ;
}
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* Returns an array of navigation_node ' s that make up the navbar .
2010-05-30 22:56:29 +00:00
*
2010-04-19 06:30:30 +00:00
* @ return array
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function get_items () {
2013-04-15 11:25:53 +12:00
global $CFG ;
2010-04-19 06:30:30 +00:00
$items = array ();
2009-08-28 08:47:31 +00:00
// Make sure that navigation is initialised
2009-12-23 01:22:48 +00:00
if ( ! $this -> has_items ()) {
2010-04-19 06:30:30 +00:00
return $items ;
2009-12-23 01:22:48 +00:00
}
2010-04-19 06:30:30 +00:00
if ( $this -> items !== null ) {
return $this -> items ;
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
if ( count ( $this -> children ) > 0 ) {
// Add the custom children
$items = array_reverse ( $this -> children );
}
2009-11-01 11:31:16 +00:00
2010-04-19 06:30:30 +00:00
$navigationactivenode = $this -> page -> navigation -> find_active_node ();
$settingsactivenode = $this -> page -> settingsnav -> find_active_node ();
2010-03-22 03:04:00 +00:00
2009-08-28 08:47:31 +00:00
// Check if navigation contains the active node
2010-03-22 03:04:00 +00:00
if ( ! $this -> ignoreactive ) {
2010-05-30 22:56:29 +00:00
2010-04-19 06:30:30 +00:00
if ( $navigationactivenode && $settingsactivenode ) {
2010-03-22 03:04:00 +00:00
// Parse a combined navigation tree
2010-04-19 06:30:30 +00:00
while ( $settingsactivenode && $settingsactivenode -> parent !== null ) {
if ( ! $settingsactivenode -> mainnavonly ) {
$items [] = $settingsactivenode ;
}
$settingsactivenode = $settingsactivenode -> parent ;
}
2010-05-05 03:27:22 +00:00
if ( ! $this -> includesettingsbase ) {
// Removes the first node from the settings (root node) from the list
array_pop ( $items );
}
2010-04-19 06:30:30 +00:00
while ( $navigationactivenode && $navigationactivenode -> parent !== null ) {
if ( ! $navigationactivenode -> mainnavonly ) {
$items [] = $navigationactivenode ;
}
2013-04-15 13:32:07 +08:00
if ( ! empty ( $CFG -> navshowcategories ) &&
$navigationactivenode -> type === self :: TYPE_COURSE &&
$navigationactivenode -> parent -> key === 'currentcourse' ) {
2013-04-15 11:25:53 +12:00
$items = array_merge ( $items , $this -> get_course_categories ());
2013-04-12 16:40:12 +12:00
}
2010-04-19 06:30:30 +00:00
$navigationactivenode = $navigationactivenode -> parent ;
2010-03-22 03:04:00 +00:00
}
2010-04-19 06:30:30 +00:00
} else if ( $navigationactivenode ) {
2010-03-22 03:04:00 +00:00
// Parse the navigation tree to get the active node
2010-04-19 06:30:30 +00:00
while ( $navigationactivenode && $navigationactivenode -> parent !== null ) {
if ( ! $navigationactivenode -> mainnavonly ) {
$items [] = $navigationactivenode ;
}
2013-04-15 13:32:07 +08:00
if ( ! empty ( $CFG -> navshowcategories ) &&
$navigationactivenode -> type === self :: TYPE_COURSE &&
$navigationactivenode -> parent -> key === 'currentcourse' ) {
2013-04-15 11:25:53 +12:00
$items = array_merge ( $items , $this -> get_course_categories ());
2013-04-12 16:40:12 +12:00
}
2010-04-19 06:30:30 +00:00
$navigationactivenode = $navigationactivenode -> parent ;
}
} else if ( $settingsactivenode ) {
2010-03-22 03:04:00 +00:00
// Parse the settings navigation to get the active node
2010-04-19 06:30:30 +00:00
while ( $settingsactivenode && $settingsactivenode -> parent !== null ) {
if ( ! $settingsactivenode -> mainnavonly ) {
$items [] = $settingsactivenode ;
}
$settingsactivenode = $settingsactivenode -> parent ;
}
2010-03-22 03:04:00 +00:00
}
2009-08-28 08:47:31 +00:00
}
2010-02-18 06:42:29 +00:00
2010-04-19 06:30:30 +00:00
$items [] = new navigation_node ( array (
'text' => $this -> page -> navigation -> text ,
'shorttext' => $this -> page -> navigation -> shorttext ,
'key' => $this -> page -> navigation -> key ,
'action' => $this -> page -> navigation -> action
));
2010-02-18 06:42:29 +00:00
2010-04-19 06:30:30 +00:00
$this -> items = array_reverse ( $items );
return $this -> items ;
2009-08-28 08:47:31 +00:00
}
2010-02-18 05:57:20 +00:00
2013-04-12 16:40:12 +12:00
/**
* Get the list of categories leading to this course .
*
* This function is used by { @ link navbar :: get_items ()} to add back the " courses "
* node and category chain leading to the current course . Note that this is only ever
* called for the current course , so we don ' t need to bother taking in any parameters .
*
* @ return array
*/
private function get_course_categories () {
$categories = array ();
2013-04-16 11:02:06 +12:00
foreach ( $this -> page -> categories as $category ) {
$url = new moodle_url ( '/course/index.php' , array ( 'categoryid' => $category -> id ));
$name = format_string ( $category -> name , true , array ( 'context' => context_coursecat :: instance ( $category -> id )));
$categories [] = navigation_node :: create ( $name , $url , self :: TYPE_CATEGORY , null , $category -> id );
2013-04-12 16:40:12 +12:00
$id = $category -> parent ;
}
2013-04-16 11:02:06 +12:00
if ( is_enrolled ( context_course :: instance ( $this -> page -> course -> id ))) {
$courses = $this -> page -> navigation -> get ( 'mycourses' );
} else {
$courses = $this -> page -> navigation -> get ( 'courses' );
}
if ( ! $courses ) {
// Courses node may not be present.
$courses = navigation_node :: create (
get_string ( 'courses' ),
new moodle_url ( '/course/index.php' ),
self :: TYPE_CONTAINER
);
}
$categories [] = $courses ;
2013-04-12 16:40:12 +12:00
return $categories ;
}
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* Add a new navigation_node to the navbar , overrides parent :: add
2009-08-28 08:47:31 +00:00
*
* This function overrides { @ link navigation_node :: add ()} so that we can change
* the way nodes get added to allow us to simply call add and have the node added to the
* end of the navbar
*
* @ param string $text
2012-05-07 12:57:42 +12:00
* @ param string | moodle_url | action_link $action An action to associate with this node .
* @ param int $type One of navigation_node :: TYPE_ *
2009-09-04 08:43:49 +00:00
* @ param string $shorttext
2012-05-07 12:57:42 +12:00
* @ param string | int $key A key to identify this node with . Key + type is unique to a parent .
* @ param pix_icon $icon An optional icon to use for this node .
2010-04-19 06:30:30 +00:00
* @ return navigation_node
2009-08-28 08:47:31 +00:00
*/
2010-02-14 09:29:44 +00:00
public function add ( $text , $action = null , $type = self :: TYPE_CUSTOM , $shorttext = null , $key = null , pix_icon $icon = null ) {
2010-04-19 06:30:30 +00:00
if ( $this -> content !== null ) {
debugging ( 'Nav bar items must be printed before $OUTPUT->header() has been called' , DEBUG_DEVELOPER );
}
2010-05-30 22:56:29 +00:00
2010-04-19 06:30:30 +00:00
// Properties array used when creating the new navigation node
$itemarray = array (
'text' => $text ,
'type' => $type
);
// Set the action if one was provided
if ( $action !== null ) {
$itemarray [ 'action' ] = $action ;
}
// Set the shorttext if one was provided
if ( $shorttext !== null ) {
$itemarray [ 'shorttext' ] = $shorttext ;
}
// Set the icon if one was provided
if ( $icon !== null ) {
$itemarray [ 'icon' ] = $icon ;
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
// Default the key to the number of children if not provided
if ( $key === null ) {
$key = count ( $this -> children );
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
// Set the key
$itemarray [ 'key' ] = $key ;
// Set the parent to this node
$itemarray [ 'parent' ] = $this ;
// Add the child using the navigation_node_collections add method
$this -> children [] = new navigation_node ( $itemarray );
return $this ;
2009-08-28 08:47:31 +00:00
}
}
/**
* Class used to manage the settings option for the current page
*
* This class is used to manage the settings options in a tree format ( recursively )
* and was created initially for use with the settings blocks .
*
2012-01-04 15:56:26 +08:00
* @ package core
* @ category navigation
2009-08-28 08:47:31 +00:00
* @ copyright 2009 Sam Hemelryk
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
class settings_navigation extends navigation_node {
2012-01-04 15:56:26 +08:00
/** @var stdClass the current context */
2009-08-28 08:47:31 +00:00
protected $context ;
2012-01-04 15:56:26 +08:00
/** @var moodle_page the moodle page that the navigation belongs to */
2009-08-28 08:47:31 +00:00
protected $page ;
2012-01-04 15:56:26 +08:00
/** @var string contains administration section navigation_nodes */
2010-02-22 07:57:35 +00:00
protected $adminsection ;
2012-01-04 15:56:26 +08:00
/** @var bool A switch to see if the navigation node is initialised */
2010-05-13 09:57:43 +00:00
protected $initialised = false ;
2012-01-04 15:56:26 +08:00
/** @var array An array of users that the nodes can extend for. */
2010-05-17 05:38:59 +00:00
protected $userstoextendfor = array ();
2011-06-24 16:42:41 +08:00
/** @var navigation_cache **/
protected $cache ;
2010-05-13 09:57:43 +00:00
2009-08-28 08:47:31 +00:00
/**
* Sets up the object with basic settings and preparse it for use
2010-05-30 22:56:29 +00:00
*
2010-04-19 06:30:30 +00:00
* @ param moodle_page $page
2009-08-28 08:47:31 +00:00
*/
2010-02-18 05:57:20 +00:00
public function __construct ( moodle_page & $page ) {
2009-08-28 08:47:31 +00:00
if ( during_initial_install ()) {
return false ;
}
$this -> page = $page ;
// Initialise the main navigation. It is most important that this is done
// before we try anything
$this -> page -> navigation -> initialise ();
// Initialise the navigation cache
2009-10-12 05:39:32 +00:00
$this -> cache = new navigation_cache ( NAVIGATION_CACHE_NAME );
2010-04-19 06:30:30 +00:00
$this -> children = new navigation_node_collection ();
2009-08-28 08:47:31 +00:00
}
/**
* Initialise the settings navigation based on the current context
*
* This function initialises the settings navigation tree for a given context
* by calling supporting functions to generate major parts of the tree .
2010-04-19 06:30:30 +00:00
*
2009-08-28 08:47:31 +00:00
*/
public function initialise () {
2012-05-07 12:57:42 +12:00
global $DB , $SESSION , $SITE ;
2010-03-31 07:41:31 +00:00
2009-08-28 08:47:31 +00:00
if ( during_initial_install ()) {
return false ;
2010-05-13 09:57:43 +00:00
} else if ( $this -> initialised ) {
return true ;
2009-08-28 08:47:31 +00:00
}
$this -> id = 'settingsnav' ;
$this -> context = $this -> page -> context ;
2010-03-22 03:04:00 +00:00
$context = $this -> context ;
if ( $context -> contextlevel == CONTEXT_BLOCK ) {
$this -> load_block_settings ();
2011-10-14 12:48:00 +02:00
$context = $context -> get_parent_context ();
2010-03-22 03:04:00 +00:00
}
switch ( $context -> contextlevel ) {
2009-08-28 08:47:31 +00:00
case CONTEXT_SYSTEM :
2010-03-22 03:04:00 +00:00
if ( $this -> page -> url -> compare ( new moodle_url ( '/admin/settings.php' , array ( 'section' => 'frontpagesettings' )))) {
$this -> load_front_page_settings (( $context -> id == $this -> context -> id ));
}
2009-08-28 08:47:31 +00:00
break ;
case CONTEXT_COURSECAT :
2010-03-22 03:04:00 +00:00
$this -> load_category_settings ();
2009-08-28 08:47:31 +00:00
break ;
case CONTEXT_COURSE :
2012-05-07 12:57:42 +12:00
if ( $this -> page -> course -> id != $SITE -> id ) {
2010-03-22 03:04:00 +00:00
$this -> load_course_settings (( $context -> id == $this -> context -> id ));
2009-08-28 08:47:31 +00:00
} else {
2010-03-22 03:04:00 +00:00
$this -> load_front_page_settings (( $context -> id == $this -> context -> id ));
2009-08-28 08:47:31 +00:00
}
break ;
case CONTEXT_MODULE :
2010-03-22 03:04:00 +00:00
$this -> load_module_settings ();
$this -> load_course_settings ();
2009-08-28 08:47:31 +00:00
break ;
case CONTEXT_USER :
2012-05-07 12:57:42 +12:00
if ( $this -> page -> course -> id != $SITE -> id ) {
2010-03-22 03:04:00 +00:00
$this -> load_course_settings ();
2009-08-28 08:47:31 +00:00
}
break ;
}
2010-04-19 06:30:30 +00:00
$settings = $this -> load_user_settings ( $this -> page -> course -> id );
2011-01-27 15:54:11 +08:00
if ( isloggedin () && ! isguestuser () && ( ! property_exists ( $SESSION , 'load_navigation_admin' ) || $SESSION -> load_navigation_admin )) {
$admin = $this -> load_administration_settings ();
$SESSION -> load_navigation_admin = ( $admin -> has_children ());
} else {
$admin = false ;
}
2010-03-22 03:04:00 +00:00
2010-04-19 06:30:30 +00:00
if ( $context -> contextlevel == CONTEXT_SYSTEM && $admin ) {
$admin -> force_open ();
} else if ( $context -> contextlevel == CONTEXT_USER && $settings ) {
$settings -> force_open ();
2010-03-22 03:04:00 +00:00
}
2009-08-28 08:47:31 +00:00
// Check if the user is currently logged in as another user
if ( session_is_loggedinas ()) {
// Get the actual user, we need this so we can display an informative return link
$realuser = session_get_realuser ();
// Add the informative return to original user link
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/course/loginas.php' , array ( 'id' => $this -> page -> course -> id , 'return' => 1 , 'sesskey' => sesskey ()));
2010-02-14 09:29:44 +00:00
$this -> add ( get_string ( 'returntooriginaluser' , 'moodle' , fullname ( $realuser , true )), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 't/left' , '' ));
2009-08-28 08:47:31 +00:00
}
2011-11-30 10:30:46 +10:00
// At this point we give any local plugins the ability to extend/tinker with the navigation settings.
$this -> load_local_plugin_settings ();
2010-04-19 06:30:30 +00:00
foreach ( $this -> children as $key => $node ) {
if ( $node -> nodetype != self :: NODETYPE_BRANCH || $node -> children -> count () === 0 ) {
$node -> remove ();
}
}
2010-05-13 09:57:43 +00:00
$this -> initialised = true ;
2009-08-28 08:47:31 +00:00
}
/**
* Override the parent function so that we can add preceeding hr ' s and set a
* root node class against all first level element
*
* It does this by first calling the parent ' s add method { @ link navigation_node :: add ()}
2009-11-01 11:31:16 +00:00
* and then proceeds to use the key to set class and hr
2009-08-28 08:47:31 +00:00
*
2012-01-04 15:56:26 +08:00
* @ param string $text text to be used for the link .
* @ param string | moodle_url $url url for the new node
* @ param int $type the type of node navigation_node :: TYPE_ *
2009-08-28 08:47:31 +00:00
* @ param string $shorttext
2012-01-04 15:56:26 +08:00
* @ param string | int $key a key to access the node by .
* @ param pix_icon $icon An icon that appears next to the node .
* @ return navigation_node with the new node added to it .
2009-08-28 08:47:31 +00:00
*/
2010-02-14 09:29:44 +00:00
public function add ( $text , $url = null , $type = null , $shorttext = null , $key = null , pix_icon $icon = null ) {
2010-04-19 06:30:30 +00:00
$node = parent :: add ( $text , $url , $type , $shorttext , $key , $icon );
$node -> add_class ( 'root_node' );
return $node ;
2009-08-28 08:47:31 +00:00
}
2009-09-16 07:52:36 +00:00
/**
* This function allows the user to add something to the start of the settings
* navigation , which means it will be at the top of the settings navigation block
*
2012-01-04 15:56:26 +08:00
* @ param string $text text to be used for the link .
* @ param string | moodle_url $url url for the new node
* @ param int $type the type of node navigation_node :: TYPE_ *
2009-09-16 07:52:36 +00:00
* @ param string $shorttext
2012-01-04 15:56:26 +08:00
* @ param string | int $key a key to access the node by .
* @ param pix_icon $icon An icon that appears next to the node .
* @ return navigation_node $node with the new node added to it .
2009-09-16 07:52:36 +00:00
*/
2010-02-14 09:29:44 +00:00
public function prepend ( $text , $url = null , $type = null , $shorttext = null , $key = null , pix_icon $icon = null ) {
2009-09-16 07:52:36 +00:00
$children = $this -> children ;
2010-05-03 07:11:17 +00:00
$childrenclass = get_class ( $children );
$this -> children = new $childrenclass ;
2010-04-19 06:30:30 +00:00
$node = $this -> add ( $text , $url , $type , $shorttext , $key , $icon );
foreach ( $children as $child ) {
$this -> children -> add ( $child );
2009-09-16 07:52:36 +00:00
}
2010-04-19 06:30:30 +00:00
return $node ;
2009-09-16 07:52:36 +00:00
}
2009-08-28 08:47:31 +00:00
/**
* Load the site administration tree
*
* This function loads the site administration tree by using the lib / adminlib library functions
*
2010-04-19 06:30:30 +00:00
* @ param navigation_node $referencebranch A reference to a branch in the settings
2009-08-28 08:47:31 +00:00
* navigation tree
2010-04-19 06:30:30 +00:00
* @ param part_of_admin_tree $adminbranch The branch to add , if null generate the admin
2009-08-28 08:47:31 +00:00
* tree and start at the beginning
* @ return mixed A key to access the admin tree by
*/
2010-02-10 01:12:59 +00:00
protected function load_administration_settings ( navigation_node $referencebranch = null , part_of_admin_tree $adminbranch = null ) {
2010-02-18 05:57:20 +00:00
global $CFG ;
2010-02-10 01:12:59 +00:00
2009-08-28 08:47:31 +00:00
// Check if we are just starting to generate this navigation.
if ( $referencebranch === null ) {
2010-02-10 01:12:59 +00:00
2010-02-22 07:57:35 +00:00
// Require the admin lib then get an admin structure
2010-02-10 01:12:59 +00:00
if ( ! function_exists ( 'admin_get_root' )) {
require_once ( $CFG -> dirroot . '/lib/adminlib.php' );
}
$adminroot = admin_get_root ( false , false );
2010-02-22 07:57:35 +00:00
// This is the active section identifier
$this -> adminsection = $this -> page -> url -> param ( 'section' );
2010-03-31 07:41:31 +00:00
2010-02-22 07:57:35 +00:00
// Disable the navigation from automatically finding the active node
navigation_node :: $autofindactive = false ;
2010-04-19 06:30:30 +00:00
$referencebranch = $this -> add ( get_string ( 'administrationsite' ), null , self :: TYPE_SETTING , null , 'root' );
2010-02-10 01:12:59 +00:00
foreach ( $adminroot -> children as $adminbranch ) {
$this -> load_administration_settings ( $referencebranch , $adminbranch );
}
2010-02-22 07:57:35 +00:00
navigation_node :: $autofindactive = true ;
2010-02-10 01:12:59 +00:00
2010-02-22 07:57:35 +00:00
// Use the admin structure to locate the active page
2010-04-19 06:30:30 +00:00
if ( ! $this -> contains_active_node () && $current = $adminroot -> locate ( $this -> adminsection , true )) {
$currentnode = $this ;
while (( $pathkey = array_pop ( $current -> path )) !== null && $currentnode ) {
$currentnode = $currentnode -> get ( $pathkey );
}
if ( $currentnode ) {
$currentnode -> make_active ();
2009-08-28 08:47:31 +00:00
}
2010-05-05 06:28:47 +00:00
} else {
$this -> scan_for_active_node ( $referencebranch );
2010-02-10 01:12:59 +00:00
}
2010-04-19 06:30:30 +00:00
return $referencebranch ;
2009-10-20 03:31:19 +00:00
} else if ( $adminbranch -> check_access ()) {
2009-08-28 08:47:31 +00:00
// We have a reference branch that we can access and is not hidden `hurrah`
// Now we need to display it and any children it may have
$url = null ;
$icon = null ;
if ( $adminbranch instanceof admin_settingpage ) {
2011-10-06 11:58:22 +13:00
$url = new moodle_url ( '/' . $CFG -> admin . '/settings.php' , array ( 'section' => $adminbranch -> name ));
2009-08-28 08:47:31 +00:00
} else if ( $adminbranch instanceof admin_externalpage ) {
$url = $adminbranch -> url ;
2011-10-06 11:58:22 +13:00
} else if ( ! empty ( $CFG -> linkadmincategories ) && $adminbranch instanceof admin_category ) {
$url = new moodle_url ( '/' . $CFG -> admin . '/category.php' , array ( 'category' => $adminbranch -> name ));
2009-08-28 08:47:31 +00:00
}
// Add the branch
2010-04-19 06:30:30 +00:00
$reference = $referencebranch -> add ( $adminbranch -> visiblename , $url , self :: TYPE_SETTING , null , $adminbranch -> name , $icon );
2009-10-20 03:31:19 +00:00
if ( $adminbranch -> is_hidden ()) {
2010-02-22 07:57:35 +00:00
if (( $adminbranch instanceof admin_externalpage || $adminbranch instanceof admin_settingpage ) && $adminbranch -> name == $this -> adminsection ) {
$reference -> add_class ( 'hidden' );
} else {
$reference -> display = false ;
}
2009-10-20 03:31:19 +00:00
}
2009-08-28 08:47:31 +00:00
// Check if we are generating the admin notifications and whether notificiations exist
if ( $adminbranch -> name === 'adminnotifications' && admin_critical_warnings_present ()) {
$reference -> add_class ( 'criticalnotification' );
}
// Check if this branch has children
if ( $reference && isset ( $adminbranch -> children ) && is_array ( $adminbranch -> children ) && count ( $adminbranch -> children ) > 0 ) {
foreach ( $adminbranch -> children as $branch ) {
// Generate the child branches as well now using this branch as the reference
2009-08-29 11:15:27 +00:00
$this -> load_administration_settings ( $reference , $branch );
2009-08-28 08:47:31 +00:00
}
} else {
2010-02-14 09:29:44 +00:00
$reference -> icon = new pix_icon ( 'i/settings' , '' );
2009-08-28 08:47:31 +00:00
}
}
}
2010-05-05 06:28:47 +00:00
/**
* This function recursivily scans nodes until it finds the active node or there
* are no more nodes .
* @ param navigation_node $node
*/
protected function scan_for_active_node ( navigation_node $node ) {
if ( ! $node -> check_if_active () && $node -> children -> count () > 0 ) {
foreach ( $node -> children as & $child ) {
$this -> scan_for_active_node ( $child );
}
}
}
2010-04-19 06:30:30 +00:00
/**
* Gets a navigation node given an array of keys that represent the path to
* the desired node .
*
* @ param array $path
* @ return navigation_node | false
*/
protected function get_by_path ( array $path ) {
$node = $this -> get ( array_shift ( $path ));
foreach ( $path as $key ) {
$node -> get ( $key );
}
return $node ;
}
2009-08-28 08:47:31 +00:00
/**
* Generate the list of modules for the given course .
*
* @ param stdClass $course The course to get modules for
*/
protected function get_course_modules ( $course ) {
global $CFG ;
// This function is included when we include course/lib.php at the top
// of this file
2012-09-25 10:34:18 +08:00
$modnames = get_module_types_names ();
2009-08-28 08:47:31 +00:00
$resources = array ();
$activities = array ();
foreach ( $modnames as $modname => $modnamestr ) {
if ( ! course_allowed_module ( $course , $modname )) {
continue ;
}
$libfile = " $CFG->dirroot /mod/ $modname /lib.php " ;
if ( ! file_exists ( $libfile )) {
continue ;
}
include_once ( $libfile );
$gettypesfunc = $modname . '_get_types' ;
if ( function_exists ( $gettypesfunc )) {
$types = $gettypesfunc ();
foreach ( $types as $type ) {
if ( ! isset ( $type -> modclass ) || ! isset ( $type -> typestr )) {
debugging ( 'Incorrect activity type in ' . $modname );
continue ;
}
if ( $type -> modclass == MOD_CLASS_RESOURCE ) {
2012-12-09 18:21:38 +01:00
$resources [ html_entity_decode ( $type -> type , ENT_QUOTES , 'UTF-8' )] = $type -> typestr ;
2009-08-28 08:47:31 +00:00
} else {
2012-12-09 18:21:38 +01:00
$activities [ html_entity_decode ( $type -> type , ENT_QUOTES , 'UTF-8' )] = $type -> typestr ;
2009-08-28 08:47:31 +00:00
}
}
} else {
$archetype = plugin_supports ( 'mod' , $modname , FEATURE_MOD_ARCHETYPE , MOD_ARCHETYPE_OTHER );
if ( $archetype == MOD_ARCHETYPE_RESOURCE ) {
$resources [ $modname ] = $modnamestr ;
} else {
// all other archetypes are considered activity
$activities [ $modname ] = $modnamestr ;
}
}
}
2011-06-24 16:42:41 +08:00
return array ( $resources , $activities );
2009-08-28 08:47:31 +00:00
}
/**
* This function loads the course settings that are available for the user
*
2010-03-22 03:04:00 +00:00
* @ param bool $forceopen If set to true the course node will be forced open
2010-04-19 06:30:30 +00:00
* @ return navigation_node | false
2009-08-28 08:47:31 +00:00
*/
2010-03-22 03:04:00 +00:00
protected function load_course_settings ( $forceopen = false ) {
2011-06-24 16:42:41 +08:00
global $CFG ;
2009-08-28 08:47:31 +00:00
$course = $this -> page -> course ;
2012-07-25 16:25:55 +08:00
$coursecontext = context_course :: instance ( $course -> id );
MDL-21782 reworked enrolment framework, the core infrastructure is in place, the basic plugins are all implemented; see the tracker issue for list of unfinished bits, expect more changes and improvements during the next week
AMOS START
MOV [sendcoursewelcomemessage,core_admin],[sendcoursewelcomemessage,enrol_self]
MOV [configsendcoursewelcomemessage,core_admin],[sendcoursewelcomemessage_desc,enrol_self]
MOV [enrolstartdate,core],[enrolstartdate,enrol_self]
MOV [enrolenddate,core],[enrolenddate,enrol_self]
CPY [welcometocourse,core],[welcometocourse,enrol_self]
CPY [welcometocoursetext,core],[welcometocoursetext,enrol_self]
MOV [notenrollable,core],[notenrollable,core_enrol]
MOV [enrolenddaterror,core],[enrolenddaterror,enrol_self]
MOV [enrolmentkeyhint,core],[passwordinvalidhint,enrol_self]
MOV [coursemanager,core_admin],[coursecontact,core_admin]
MOV [configcoursemanager,core_admin],[coursecontact_desc,core_admin]
MOV [enrolledincourserole,core],[enrolledincourserole,enrol_manual]
MOV [enrolme,core],[enrolme,core_enrol]
MOV [unenrol,core],[unenrol,core_enrol]
MOV [unenrolme,core],[unenrolme,core_enrol]
MOV [enrolmentnew,core],[enrolmentnew,core_enrol]
MOV [enrolmentnewuser,core],[enrolmentnewuser,core_enrol]
MOV [enrolments,core],[enrolments,core_enrol]
MOV [enrolperiod,core],[enrolperiod,core_enrol]
MOV [unenrolroleusers,core],[unenrolroleusers,core_enrol]
AMOS END
2010-06-21 15:30:49 +00:00
// note: do not test if enrolled or viewing here because we need the enrol link in Course administration section
2009-08-28 08:47:31 +00:00
2010-04-19 06:30:30 +00:00
$coursenode = $this -> add ( get_string ( 'courseadministration' ), null , self :: TYPE_COURSE , null , 'courseadmin' );
if ( $forceopen ) {
$coursenode -> force_open ();
}
2009-11-01 11:31:16 +00:00
2013-05-30 10:18:00 +10:00
if ( $this -> page -> user_allowed_editing ()) {
2009-08-28 08:47:31 +00:00
// Add the turn on/off settings
2012-04-30 11:23:37 +08:00
if ( $this -> page -> url -> compare ( new moodle_url ( '/course/view.php' ), URL_MATCH_BASE )) {
// We are on the course page, retain the current page params e.g. section.
2011-11-25 10:20:34 +00:00
$baseurl = clone ( $this -> page -> url );
$baseurl -> param ( 'sesskey' , sesskey ());
2012-04-30 11:23:37 +08:00
} else {
// Edit on the main course page.
2012-09-13 12:30:32 +08:00
$baseurl = new moodle_url ( '/course/view.php' , array ( 'id' => $course -> id , 'return' => $this -> page -> url -> out_as_local_url ( false ), 'sesskey' => sesskey ()));
2012-04-30 11:23:37 +08:00
}
2011-11-25 10:20:34 +00:00
$editurl = clone ( $baseurl );
2009-08-28 08:47:31 +00:00
if ( $this -> page -> user_is_editing ()) {
2011-11-25 10:20:34 +00:00
$editurl -> param ( 'edit' , 'off' );
2009-08-28 08:47:31 +00:00
$editstring = get_string ( 'turneditingoff' );
} else {
2011-11-25 10:20:34 +00:00
$editurl -> param ( 'edit' , 'on' );
2009-08-28 08:47:31 +00:00
$editstring = get_string ( 'turneditingon' );
}
2013-05-30 10:18:00 +10:00
$coursenode -> add ( $editstring , $editurl , self :: TYPE_SETTING , null , 'turneditingonoff' , new pix_icon ( 'i/edit' , '' ));
}
2011-11-25 10:20:34 +00:00
2013-05-30 10:18:00 +10:00
if ( has_capability ( 'moodle/course:update' , $coursecontext )) {
2009-08-28 08:47:31 +00:00
// Add the course settings link
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/course/edit.php' , array ( 'id' => $course -> id ));
2012-12-12 15:35:18 +08:00
$coursenode -> add ( get_string ( 'editsettings' ), $url , self :: TYPE_SETTING , null , 'editsettings' , new pix_icon ( 'i/settings' , '' ));
2010-04-30 03:06:22 +00:00
// Add the course completion settings link
if ( $CFG -> enablecompletion && $course -> enablecompletion ) {
$url = new moodle_url ( '/course/completion.php' , array ( 'id' => $course -> id ));
2013-05-06 21:58:17 +02:00
$coursenode -> add ( get_string ( 'coursecompletion' , 'completion' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/settings' , '' ));
2010-04-30 03:06:22 +00:00
}
2009-08-28 08:47:31 +00:00
}
2009-11-01 11:31:16 +00:00
MDL-21782 reworked enrolment framework, the core infrastructure is in place, the basic plugins are all implemented; see the tracker issue for list of unfinished bits, expect more changes and improvements during the next week
AMOS START
MOV [sendcoursewelcomemessage,core_admin],[sendcoursewelcomemessage,enrol_self]
MOV [configsendcoursewelcomemessage,core_admin],[sendcoursewelcomemessage_desc,enrol_self]
MOV [enrolstartdate,core],[enrolstartdate,enrol_self]
MOV [enrolenddate,core],[enrolenddate,enrol_self]
CPY [welcometocourse,core],[welcometocourse,enrol_self]
CPY [welcometocoursetext,core],[welcometocoursetext,enrol_self]
MOV [notenrollable,core],[notenrollable,core_enrol]
MOV [enrolenddaterror,core],[enrolenddaterror,enrol_self]
MOV [enrolmentkeyhint,core],[passwordinvalidhint,enrol_self]
MOV [coursemanager,core_admin],[coursecontact,core_admin]
MOV [configcoursemanager,core_admin],[coursecontact_desc,core_admin]
MOV [enrolledincourserole,core],[enrolledincourserole,enrol_manual]
MOV [enrolme,core],[enrolme,core_enrol]
MOV [unenrol,core],[unenrol,core_enrol]
MOV [unenrolme,core],[unenrolme,core_enrol]
MOV [enrolmentnew,core],[enrolmentnew,core_enrol]
MOV [enrolmentnewuser,core],[enrolmentnewuser,core_enrol]
MOV [enrolments,core],[enrolments,core_enrol]
MOV [enrolperiod,core],[enrolperiod,core_enrol]
MOV [unenrolroleusers,core],[unenrolroleusers,core_enrol]
AMOS END
2010-06-21 15:30:49 +00:00
// add enrol nodes
enrol_add_course_navigation ( $coursenode , $course );
// Manage filters
if ( has_capability ( 'moodle/filter:manage' , $coursecontext ) && count ( filter_get_available_in_context ( $coursecontext )) > 0 ) {
$url = new moodle_url ( '/filter/manage.php' , array ( 'contextid' => $coursecontext -> id ));
$coursenode -> add ( get_string ( 'filters' , 'admin' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/filter' , '' ));
2009-08-28 08:47:31 +00:00
}
2013-02-15 13:06:26 +08:00
// View course reports.
if ( has_capability ( 'moodle/site:viewreports' , $coursecontext )) { // Basic capability for listing of reports.
$reportnav = $coursenode -> add ( get_string ( 'reports' ), null , self :: TYPE_CONTAINER , null , null ,
new pix_icon ( 'i/stats' , '' ));
$coursereports = get_plugin_list ( 'coursereport' );
foreach ( $coursereports as $report => $dir ) {
$libfile = $CFG -> dirroot . '/course/report/' . $report . '/lib.php' ;
if ( file_exists ( $libfile )) {
require_once ( $libfile );
$reportfunction = $report . '_report_extend_navigation' ;
if ( function_exists ( $report . '_report_extend_navigation' )) {
$reportfunction ( $reportnav , $course , $coursecontext );
}
}
}
$reports = get_plugin_list_with_function ( 'report' , 'extend_navigation_course' , 'lib.php' );
foreach ( $reports as $reportfunction ) {
$reportfunction ( $reportnav , $course , $coursecontext );
}
}
2009-08-28 08:47:31 +00:00
// Add view grade report is permitted
$reportavailable = false ;
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/grade:viewall' , $coursecontext )) {
2009-08-28 08:47:31 +00:00
$reportavailable = true ;
} else if ( ! empty ( $course -> showgrades )) {
$reports = get_plugin_list ( 'gradereport' );
if ( is_array ( $reports ) && count ( $reports ) > 0 ) { // Get all installed reports
arsort ( $reports ); // user is last, we want to test it first
foreach ( $reports as $plugin => $plugindir ) {
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'gradereport/' . $plugin . ':view' , $coursecontext )) {
2009-08-28 08:47:31 +00:00
//stop when the first visible plugin is found
$reportavailable = true ;
break ;
}
}
}
}
if ( $reportavailable ) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/grade/report/index.php' , array ( 'id' => $course -> id ));
2010-05-03 07:11:17 +00:00
$gradenode = $coursenode -> add ( get_string ( 'grades' ), $url , self :: TYPE_SETTING , null , 'grades' , new pix_icon ( 'i/grades' , '' ));
2009-08-28 08:47:31 +00:00
}
// Add outcome if permitted
2010-03-31 07:41:31 +00:00
if ( ! empty ( $CFG -> enableoutcomes ) && has_capability ( 'moodle/course:update' , $coursecontext )) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/grade/edit/outcome/course.php' , array ( 'id' => $course -> id ));
2010-05-20 07:35:44 +00:00
$coursenode -> add ( get_string ( 'outcomes' , 'grades' ), $url , self :: TYPE_SETTING , null , 'outcomes' , new pix_icon ( 'i/outcomes' , '' ));
2009-08-28 08:47:31 +00:00
}
2013-04-02 13:57:39 +13:00
//Add badges navigation
require_once ( $CFG -> libdir . '/badgeslib.php' );
badges_add_course_navigation ( $coursenode , $course );
2009-08-28 08:47:31 +00:00
// Backup this course
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/backup:backupcourse' , $coursecontext )) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/backup/backup.php' , array ( 'id' => $course -> id ));
2010-05-20 07:35:44 +00:00
$coursenode -> add ( get_string ( 'backup' ), $url , self :: TYPE_SETTING , null , 'backup' , new pix_icon ( 'i/backup' , '' ));
2009-08-28 08:47:31 +00:00
}
// Restore to this course
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/restore:restorecourse' , $coursecontext )) {
2010-07-22 07:48:02 +00:00
$url = new moodle_url ( '/backup/restorefile.php' , array ( 'contextid' => $coursecontext -> id ));
2010-05-20 07:35:44 +00:00
$coursenode -> add ( get_string ( 'restore' ), $url , self :: TYPE_SETTING , null , 'restore' , new pix_icon ( 'i/restore' , '' ));
2009-08-28 08:47:31 +00:00
}
// Import data from other courses
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/restore:restoretargetimport' , $coursecontext )) {
2010-08-17 02:07:30 +00:00
$url = new moodle_url ( '/backup/import.php' , array ( 'id' => $course -> id ));
2012-11-09 15:43:22 +08:00
$coursenode -> add ( get_string ( 'import' ), $url , self :: TYPE_SETTING , null , 'import' , new pix_icon ( 'i/import' , '' ));
2009-08-28 08:47:31 +00:00
}
2010-05-01 05:05:55 +00:00
// Publish course on a hub
if ( has_capability ( 'moodle/course:publish' , $coursecontext )) {
$url = new moodle_url ( '/course/publish/index.php' , array ( 'id' => $course -> id ));
2010-05-20 07:35:44 +00:00
$coursenode -> add ( get_string ( 'publish' ), $url , self :: TYPE_SETTING , null , 'publish' , new pix_icon ( 'i/publish' , '' ));
2010-05-01 05:05:55 +00:00
}
2009-08-28 08:47:31 +00:00
// Reset this course
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/course:reset' , $coursecontext )) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/course/reset.php' , array ( 'id' => $course -> id ));
2010-02-14 09:29:44 +00:00
$coursenode -> add ( get_string ( 'reset' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/return' , '' ));
2009-08-28 08:47:31 +00:00
}
2010-05-21 03:15:48 +00:00
// Questions
2011-12-22 17:37:41 +00:00
require_once ( $CFG -> libdir . '/questionlib.php' );
2010-05-21 03:15:48 +00:00
question_extend_settings_navigation ( $coursenode , $coursecontext ) -> trim_if_empty ();
2009-08-28 08:47:31 +00:00
2011-06-24 16:42:41 +08:00
if ( has_capability ( 'moodle/course:update' , $coursecontext )) {
// Repository Instances
if ( ! $this -> cache -> cached ( 'contexthasrepos' . $coursecontext -> id )) {
require_once ( $CFG -> dirroot . '/repository/lib.php' );
$editabletypes = repository :: get_editable_types ( $coursecontext );
$haseditabletypes = ! empty ( $editabletypes );
unset ( $editabletypes );
$this -> cache -> set ( 'contexthasrepos' . $coursecontext -> id , $haseditabletypes );
} else {
$haseditabletypes = $this -> cache -> { 'contexthasrepos' . $coursecontext -> id };
}
if ( $haseditabletypes ) {
$url = new moodle_url ( '/repository/manage_instances.php' , array ( 'contextid' => $coursecontext -> id ));
$coursenode -> add ( get_string ( 'repositories' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/repository' , '' ));
}
2009-08-28 08:47:31 +00:00
}
// Manage files
2010-09-03 19:14:33 +00:00
if ( $course -> legacyfiles == 2 and has_capability ( 'moodle/course:managefiles' , $coursecontext )) {
2010-08-02 13:33:19 +00:00
// hidden in new courses and courses where legacy files were turned off
2010-08-30 08:22:14 +00:00
$url = new moodle_url ( '/files/index.php' , array ( 'contextid' => $coursecontext -> id ));
2012-11-22 17:08:10 +08:00
$coursenode -> add ( get_string ( 'courselegacyfiles' ), $url , self :: TYPE_SETTING , null , 'coursefiles' , new pix_icon ( 'i/folder' , '' ));
2012-02-22 15:30:13 +13:00
2009-08-28 08:47:31 +00:00
}
// Switch roles
$roles = array ();
$assumedrole = $this -> in_alternative_role ();
2011-06-24 16:42:41 +08:00
if ( $assumedrole !== false ) {
2009-08-28 08:47:31 +00:00
$roles [ 0 ] = get_string ( 'switchrolereturn' );
}
2010-05-11 05:28:59 +00:00
if ( has_capability ( 'moodle/role:switchroles' , $coursecontext )) {
$availableroles = get_switchable_roles ( $coursecontext );
2009-08-28 08:47:31 +00:00
if ( is_array ( $availableroles )) {
foreach ( $availableroles as $key => $role ) {
2011-02-13 16:17:47 +01:00
if ( $assumedrole == ( int ) $key ) {
2009-08-28 08:47:31 +00:00
continue ;
}
$roles [ $key ] = $role ;
}
}
}
if ( is_array ( $roles ) && count ( $roles ) > 0 ) {
2010-04-19 06:30:30 +00:00
$switchroles = $this -> add ( get_string ( 'switchroleto' ));
2009-08-28 08:47:31 +00:00
if (( count ( $roles ) == 1 && array_key_exists ( 0 , $roles )) || $assumedrole !== false ) {
2010-04-19 06:30:30 +00:00
$switchroles -> force_open ();
2009-08-28 08:47:31 +00:00
}
2011-06-24 16:42:41 +08:00
foreach ( $roles as $key => $name ) {
2012-12-07 18:13:22 +01:00
$url = new moodle_url ( '/course/switchrole.php' , array ( 'id' => $course -> id , 'sesskey' => sesskey (), 'switchrole' => $key , 'returnurl' => $this -> page -> url -> out_as_local_url ( false )));
2012-11-13 16:48:50 +08:00
$switchroles -> add ( $name , $url , self :: TYPE_SETTING , null , $key , new pix_icon ( 'i/switchrole' , '' ));
2009-08-28 08:47:31 +00:00
}
}
// Return we are done
2010-04-19 06:30:30 +00:00
return $coursenode ;
2009-08-28 08:47:31 +00:00
}
/**
* This function calls the module function to inject module settings into the
* settings navigation tree .
*
* This only gets called if there is a corrosponding function in the modules
* lib file .
*
2012-02-29 00:56:41 +01:00
* For examples mod / forum / lib . php { @ link forum_extend_settings_navigation ()}
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ return navigation_node | false
2009-08-28 08:47:31 +00:00
*/
protected function load_module_settings () {
2010-02-18 05:57:20 +00:00
global $CFG ;
2009-10-15 06:37:45 +00:00
if ( ! $this -> page -> cm && $this -> context -> contextlevel == CONTEXT_MODULE && $this -> context -> instanceid ) {
2010-03-22 03:04:00 +00:00
$cm = get_coursemodule_from_id ( false , $this -> context -> instanceid , 0 , false , MUST_EXIST );
2010-02-18 05:57:20 +00:00
$this -> page -> set_cm ( $cm , $this -> page -> course );
2009-10-15 06:37:45 +00:00
}
2010-07-21 02:53:52 +00:00
$file = $CFG -> dirroot . '/mod/' . $this -> page -> activityname . '/lib.php' ;
if ( file_exists ( $file )) {
require_once ( $file );
}
MDL-23318 Consistent usage of 'pluginadministration' string for the Settings block
AMOS BEGIN
MOV [assignmentadministration,mod_assignment],[pluginadministration,mod_assignment]
MOV [dataadministration,mod_data],[pluginadministration,mod_data]
MOV [feedbackadministration,mod_feedback],[pluginadministration,mod_feedback]
MOV [folderadministration,mod_folder],[pluginadministration,mod_folder]
MOV [forumadministration,mod_forum],[pluginadministration,mod_forum]
MOV [glossaryadministration,mod_glossary],[pluginadministration,mod_glossary]
MOV [chatadministration,mod_chat],[pluginadministration,mod_chat]
MOV [choiceadministration,mod_choice],[pluginadministration,mod_choice]
MOV [imscpadministration,mod_imscp],[pluginadministration,mod_imscp]
MOV [labeladministration,mod_label],[pluginadministration,mod_label]
MOV [lessonadministration,mod_lesson],[pluginadministration,mod_lesson]
MOV [pageadministration,mod_page],[pluginadministration,mod_page]
MOV [quizadministration,mod_quiz],[pluginadministration,mod_quiz]
MOV [resourceadministration,mod_resource],[pluginadministration,mod_resource]
MOV [scormadministration,mod_scorm],[pluginadministration,mod_scorm]
MOV [surveyadministration,mod_survey],[pluginadministration,mod_survey]
MOV [urladministration,mod_url],[pluginadministration,mod_url]
MOV [wikiadministration,mod_wiki],[pluginadministration,mod_wiki]
MOV [workshopadministration,mod_workshop],[pluginadministration,mod_workshop]
AMOS END
2010-08-17 17:35:12 +00:00
$modulenode = $this -> add ( get_string ( 'pluginadministration' , $this -> page -> activityname ));
2010-04-19 06:30:30 +00:00
$modulenode -> force_open ();
2010-03-31 07:41:31 +00:00
2010-03-22 03:04:00 +00:00
// Settings for the module
if ( has_capability ( 'moodle/course:manageactivities' , $this -> page -> cm -> context )) {
$url = new moodle_url ( '/course/modedit.php' , array ( 'update' => $this -> page -> cm -> id , 'return' => true , 'sesskey' => sesskey ()));
2011-06-18 16:24:31 +01:00
$modulenode -> add ( get_string ( 'editsettings' ), $url , navigation_node :: TYPE_SETTING , null , 'modedit' );
2010-03-22 03:04:00 +00:00
}
// Assign local roles
if ( count ( get_assignable_roles ( $this -> page -> cm -> context )) > 0 ) {
$url = new moodle_url ( '/' . $CFG -> admin . '/roles/assign.php' , array ( 'contextid' => $this -> page -> cm -> context -> id ));
2011-06-18 16:24:31 +01:00
$modulenode -> add ( get_string ( 'localroles' , 'role' ), $url , self :: TYPE_SETTING , null , 'roleassign' );
2010-03-22 03:04:00 +00:00
}
// Override roles
if ( has_capability ( 'moodle/role:review' , $this -> page -> cm -> context ) or count ( get_overridable_roles ( $this -> page -> cm -> context )) > 0 ) {
$url = new moodle_url ( '/' . $CFG -> admin . '/roles/permissions.php' , array ( 'contextid' => $this -> page -> cm -> context -> id ));
2011-06-18 16:24:31 +01:00
$modulenode -> add ( get_string ( 'permissions' , 'role' ), $url , self :: TYPE_SETTING , null , 'roleoverride' );
2010-03-22 03:04:00 +00:00
}
// Check role permissions
if ( has_any_capability ( array ( 'moodle/role:assign' , 'moodle/role:safeoverride' , 'moodle/role:override' , 'moodle/role:assign' ), $this -> page -> cm -> context )) {
$url = new moodle_url ( '/' . $CFG -> admin . '/roles/check.php' , array ( 'contextid' => $this -> page -> cm -> context -> id ));
2011-06-18 16:24:31 +01:00
$modulenode -> add ( get_string ( 'checkpermissions' , 'role' ), $url , self :: TYPE_SETTING , null , 'rolecheck' );
2010-03-22 03:04:00 +00:00
}
// Manage filters
if ( has_capability ( 'moodle/filter:manage' , $this -> page -> cm -> context ) && count ( filter_get_available_in_context ( $this -> page -> cm -> context )) > 0 ) {
$url = new moodle_url ( '/filter/manage.php' , array ( 'contextid' => $this -> page -> cm -> context -> id ));
2011-06-18 16:24:31 +01:00
$modulenode -> add ( get_string ( 'filters' , 'admin' ), $url , self :: TYPE_SETTING , null , 'filtermanage' );
2010-03-22 03:04:00 +00:00
}
2011-11-03 20:52:00 +01:00
// Add reports
$reports = get_plugin_list_with_function ( 'report' , 'extend_navigation_module' , 'lib.php' );
foreach ( $reports as $reportfunction ) {
$reportfunction ( $modulenode , $this -> page -> cm );
2010-05-10 09:02:09 +00:00
}
2010-05-04 04:00:03 +00:00
// Add a backup link
$featuresfunc = $this -> page -> activityname . '_supports' ;
2010-10-01 06:22:08 +00:00
if ( function_exists ( $featuresfunc ) && $featuresfunc ( FEATURE_BACKUP_MOODLE2 ) && has_capability ( 'moodle/backup:backupactivity' , $this -> page -> cm -> context )) {
2010-05-04 04:00:03 +00:00
$url = new moodle_url ( '/backup/backup.php' , array ( 'id' => $this -> page -> cm -> course , 'cm' => $this -> page -> cm -> id ));
2011-06-18 16:24:31 +01:00
$modulenode -> add ( get_string ( 'backup' ), $url , self :: TYPE_SETTING , null , 'backup' );
2010-05-04 04:00:03 +00:00
}
2010-11-02 02:29:21 +00:00
// Restore this activity
$featuresfunc = $this -> page -> activityname . '_supports' ;
if ( function_exists ( $featuresfunc ) && $featuresfunc ( FEATURE_BACKUP_MOODLE2 ) && has_capability ( 'moodle/restore:restoreactivity' , $this -> page -> cm -> context )) {
$url = new moodle_url ( '/backup/restorefile.php' , array ( 'contextid' => $this -> page -> cm -> context -> id ));
2011-06-18 16:24:31 +01:00
$modulenode -> add ( get_string ( 'restore' ), $url , self :: TYPE_SETTING , null , 'restore' );
2010-11-02 02:29:21 +00:00
}
2011-10-03 21:57:16 +02:00
// Allow the active advanced grading method plugin to append its settings
$featuresfunc = $this -> page -> activityname . '_supports' ;
if ( function_exists ( $featuresfunc ) && $featuresfunc ( FEATURE_ADVANCED_GRADING ) && has_capability ( 'moodle/grade:managegradingforms' , $this -> page -> cm -> context )) {
require_once ( $CFG -> dirroot . '/grade/grading/lib.php' );
$gradingman = get_grading_manager ( $this -> page -> cm -> context , $this -> page -> activityname );
$gradingman -> extend_settings_navigation ( $this , $modulenode );
}
2010-02-18 05:57:20 +00:00
$function = $this -> page -> activityname . '_extend_settings_navigation' ;
2009-08-28 08:47:31 +00:00
if ( ! function_exists ( $function )) {
2010-04-19 06:30:30 +00:00
return $modulenode ;
2009-08-28 08:47:31 +00:00
}
2010-03-22 03:04:00 +00:00
$function ( $this , $modulenode );
// Remove the module node if there are no children
if ( empty ( $modulenode -> children )) {
2010-04-19 06:30:30 +00:00
$modulenode -> remove ();
2010-03-22 03:04:00 +00:00
}
2010-04-19 06:30:30 +00:00
return $modulenode ;
2009-08-28 08:47:31 +00:00
}
/**
* Loads the user settings block of the settings nav
2009-11-01 11:31:16 +00:00
*
2009-08-28 08:47:31 +00:00
* This function is simply works out the userid and whether we need to load
2009-11-01 11:31:16 +00:00
* just the current users profile settings , or the current user and the user the
2009-08-28 08:47:31 +00:00
* current user is viewing .
2009-11-01 11:31:16 +00:00
*
2009-08-28 08:47:31 +00:00
* This function has some very ugly code to work out the user , if anyone has
* any bright ideas please feel free to intervene .
*
* @ param int $courseid The course id of the current course
2010-04-19 06:30:30 +00:00
* @ return navigation_node | false
2009-08-28 08:47:31 +00:00
*/
2012-05-07 12:57:42 +12:00
protected function load_user_settings ( $courseid = SITEID ) {
2012-04-22 17:17:27 +02:00
global $USER , $CFG ;
2009-08-28 08:47:31 +00:00
if ( isguestuser () || ! isloggedin ()) {
return false ;
}
2010-05-30 22:56:29 +00:00
2010-06-10 07:29:02 +00:00
$navusers = $this -> page -> navigation -> get_extending_users ();
if ( count ( $this -> userstoextendfor ) > 0 || count ( $navusers ) > 0 ) {
2010-05-17 05:38:59 +00:00
$usernode = null ;
foreach ( $this -> userstoextendfor as $userid ) {
2010-06-10 08:18:18 +00:00
if ( $userid == $USER -> id ) {
continue ;
}
2010-05-17 05:38:59 +00:00
$node = $this -> generate_user_settings ( $courseid , $userid , 'userviewingsettings' );
if ( is_null ( $usernode )) {
$usernode = $node ;
}
}
2010-06-10 07:29:02 +00:00
foreach ( $navusers as $user ) {
2010-06-10 08:18:18 +00:00
if ( $user -> id == $USER -> id ) {
continue ;
}
2010-06-10 07:29:02 +00:00
$node = $this -> generate_user_settings ( $courseid , $user -> id , 'userviewingsettings' );
if ( is_null ( $usernode )) {
$usernode = $node ;
}
}
2010-03-22 03:04:00 +00:00
$this -> generate_user_settings ( $courseid , $USER -> id );
2009-08-28 08:47:31 +00:00
} else {
2010-04-19 06:30:30 +00:00
$usernode = $this -> generate_user_settings ( $courseid , $USER -> id );
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
return $usernode ;
2009-08-28 08:47:31 +00:00
}
2010-08-05 02:44:03 +00:00
/**
* Extends the settings navigation for the given user .
*
* Note : This method gets called automatically if you call
* $PAGE -> navigation -> extend_for_user ( $userid )
*
* @ param int $userid
*/
2010-05-17 05:38:59 +00:00
public function extend_for_user ( $userid ) {
global $CFG ;
if ( ! in_array ( $userid , $this -> userstoextendfor )) {
$this -> userstoextendfor [] = $userid ;
if ( $this -> initialised ) {
$this -> generate_user_settings ( $this -> page -> course -> id , $userid , 'userviewingsettings' );
$children = array ();
foreach ( $this -> children as $child ) {
$children [] = $child ;
}
array_unshift ( $children , array_pop ( $children ));
$this -> children = new navigation_node_collection ();
foreach ( $children as $child ) {
$this -> children -> add ( $child );
}
}
}
}
2009-08-28 08:47:31 +00:00
/**
2012-02-29 00:56:41 +01:00
* This function gets called by { @ link settings_navigation :: load_user_settings ()} and actually works out
2009-08-28 08:47:31 +00:00
* what can be shown / done
*
* @ param int $courseid The current course ' id
* @ param int $userid The user id to load for
* @ param string $gstitle The string to pass to get_string for the branch title
2010-04-19 06:30:30 +00:00
* @ return navigation_node | false
2009-08-28 08:47:31 +00:00
*/
protected function generate_user_settings ( $courseid , $userid , $gstitle = 'usercurrentsettings' ) {
2010-02-18 05:57:20 +00:00
global $DB , $CFG , $USER , $SITE ;
2009-08-28 08:47:31 +00:00
2012-05-07 12:57:42 +12:00
if ( $courseid != $SITE -> id ) {
2010-02-18 05:57:20 +00:00
if ( ! empty ( $this -> page -> course -> id ) && $this -> page -> course -> id == $courseid ) {
$course = $this -> page -> course ;
} else {
2012-03-07 11:37:21 +13:00
$select = context_helper :: get_preload_record_columns_sql ( 'ctx' );
$sql = " SELECT c.*, $select
FROM { course } c
JOIN { context } ctx ON c . id = ctx . instanceid
WHERE c . id = : courseid AND ctx . contextlevel = : contextlevel " ;
$params = array ( 'courseid' => $courseid , 'contextlevel' => CONTEXT_COURSE );
$course = $DB -> get_record_sql ( $sql , $params , MUST_EXIST );
context_helper :: preload_from_record ( $course );
2010-02-18 05:57:20 +00:00
}
} else {
$course = $SITE ;
2009-08-28 08:47:31 +00:00
}
2012-07-25 16:25:55 +08:00
$coursecontext = context_course :: instance ( $course -> id ); // Course context
2010-02-18 05:57:20 +00:00
$systemcontext = get_system_context ();
2009-08-28 08:47:31 +00:00
$currentuser = ( $USER -> id == $userid );
2010-03-31 07:41:31 +00:00
2009-08-28 08:47:31 +00:00
if ( $currentuser ) {
$user = $USER ;
2012-07-25 16:25:55 +08:00
$usercontext = context_user :: instance ( $user -> id ); // User context
2009-08-28 08:47:31 +00:00
} else {
2012-03-07 11:37:21 +13:00
$select = context_helper :: get_preload_record_columns_sql ( 'ctx' );
$sql = " SELECT u.*, $select
FROM { user } u
JOIN { context } ctx ON u . id = ctx . instanceid
WHERE u . id = : userid AND ctx . contextlevel = : contextlevel " ;
$params = array ( 'userid' => $userid , 'contextlevel' => CONTEXT_USER );
$user = $DB -> get_record_sql ( $sql , $params , IGNORE_MISSING );
2011-06-24 16:42:41 +08:00
if ( ! $user ) {
2009-08-28 08:47:31 +00:00
return false ;
}
2012-03-07 11:37:21 +13:00
context_helper :: preload_from_record ( $user );
2011-06-24 16:42:41 +08:00
2009-08-28 08:47:31 +00:00
// Check that the user can view the profile
2012-07-25 16:25:55 +08:00
$usercontext = context_user :: instance ( $user -> id ); // User context
2011-06-24 16:42:41 +08:00
$canviewuser = has_capability ( 'moodle/user:viewdetails' , $usercontext );
2012-05-07 12:57:42 +12:00
if ( $course -> id == $SITE -> id ) {
2011-06-24 16:42:41 +08:00
if ( $CFG -> forceloginforprofiles && ! has_coursecontact_role ( $user -> id ) && ! $canviewuser ) { // Reduce possibility of "browsing" userbase at site level
2009-08-28 08:47:31 +00:00
// Teachers can browse and be browsed at site level. If not forceloginforprofiles, allow access (bug #4366)
return false ;
}
} else {
2011-06-24 16:42:41 +08:00
$canviewusercourse = has_capability ( 'moodle/user:viewdetails' , $coursecontext );
$canaccessallgroups = has_capability ( 'moodle/site:accessallgroups' , $coursecontext );
2011-10-29 09:45:54 +02:00
if (( ! $canviewusercourse && ! $canviewuser ) || ! can_access_course ( $course , $user -> id )) {
2009-08-28 08:47:31 +00:00
return false ;
}
2011-06-24 16:42:41 +08:00
if ( ! $canaccessallgroups && groups_get_course_groupmode ( $course ) == SEPARATEGROUPS ) {
2009-08-28 08:47:31 +00:00
// If groups are in use, make sure we can see that group
return false ;
}
}
}
$fullname = fullname ( $user , has_capability ( 'moodle/site:viewfullnames' , $this -> page -> context ));
2010-06-10 07:29:02 +00:00
$key = $gstitle ;
if ( $gstitle != 'usercurrentsettings' ) {
$key .= $userid ;
}
2009-08-28 08:47:31 +00:00
// Add a user setting branch
2010-06-10 07:29:02 +00:00
$usersetting = $this -> add ( get_string ( $gstitle , 'moodle' , $fullname ), null , self :: TYPE_CONTAINER , null , $key );
2009-08-28 08:47:31 +00:00
$usersetting -> id = 'usersettings' ;
2010-07-13 02:35:31 +00:00
if ( $this -> page -> context -> contextlevel == CONTEXT_USER && $this -> page -> context -> instanceid == $user -> id ) {
// Automatically start by making it active
$usersetting -> make_active ();
}
2009-08-28 08:47:31 +00:00
// Check if the user has been deleted
if ( $user -> deleted ) {
if ( ! has_capability ( 'moodle/user:update' , $coursecontext )) {
// We can't edit the user so just show the user deleted message
2009-09-04 08:43:49 +00:00
$usersetting -> add ( get_string ( 'userdeleted' ), null , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
} else {
// We can edit the user so show the user deleted message and link it to the profile
2012-05-07 12:57:42 +12:00
if ( $course -> id == $SITE -> id ) {
2010-05-04 13:04:35 +00:00
$profileurl = new moodle_url ( '/user/profile.php' , array ( 'id' => $user -> id ));
} else {
$profileurl = new moodle_url ( '/user/view.php' , array ( 'id' => $user -> id , 'course' => $course -> id ));
}
2009-09-04 08:43:49 +00:00
$usersetting -> add ( get_string ( 'userdeleted' ), $profileurl , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
}
return true ;
}
2011-06-24 16:42:41 +08:00
$userauthplugin = false ;
if ( ! empty ( $user -> auth )) {
$userauthplugin = get_auth_plugin ( $user -> auth );
}
2009-08-28 08:47:31 +00:00
// Add the profile edit link
if ( isloggedin () && ! isguestuser ( $user ) && ! is_mnet_remote_user ( $user )) {
2010-08-12 09:44:28 +00:00
if (( $currentuser || is_siteadmin ( $USER ) || ! is_siteadmin ( $user )) && has_capability ( 'moodle/user:update' , $systemcontext )) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/user/editadvanced.php' , array ( 'id' => $user -> id , 'course' => $course -> id ));
2009-12-23 01:22:48 +00:00
$usersetting -> add ( get_string ( 'editmyprofile' ), $url , self :: TYPE_SETTING );
2010-08-12 09:44:28 +00:00
} else if (( has_capability ( 'moodle/user:editprofile' , $usercontext ) && ! is_siteadmin ( $user )) || ( $currentuser && has_capability ( 'moodle/user:editownprofile' , $systemcontext ))) {
2011-06-24 16:42:41 +08:00
if ( $userauthplugin && $userauthplugin -> can_edit_profile ()) {
$url = $userauthplugin -> edit_profile_url ();
if ( empty ( $url )) {
$url = new moodle_url ( '/user/edit.php' , array ( 'id' => $user -> id , 'course' => $course -> id ));
2010-09-03 19:14:33 +00:00
}
2011-06-24 16:42:41 +08:00
$usersetting -> add ( get_string ( 'editmyprofile' ), $url , self :: TYPE_SETTING );
2010-09-03 19:14:33 +00:00
}
2009-08-28 08:47:31 +00:00
}
}
// Change password link
2011-06-24 16:42:41 +08:00
if ( $userauthplugin && $currentuser && ! session_is_loggedinas () && ! isguestuser () && has_capability ( 'moodle/user:changeownpassword' , $systemcontext ) && $userauthplugin -> can_change_password ()) {
$passwordchangeurl = $userauthplugin -> change_password_url ();
if ( empty ( $passwordchangeurl )) {
$passwordchangeurl = new moodle_url ( '/login/change_password.php' , array ( 'id' => $course -> id ));
2009-08-28 08:47:31 +00:00
}
2011-06-24 16:42:41 +08:00
$usersetting -> add ( get_string ( " changepassword " ), $passwordchangeurl , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
}
// View the roles settings
if ( has_any_capability ( array ( 'moodle/role:assign' , 'moodle/role:safeoverride' , 'moodle/role:override' , 'moodle/role:manage' ), $usercontext )) {
2010-04-19 06:30:30 +00:00
$roles = $usersetting -> add ( get_string ( 'roles' ), null , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/admin/roles/usersroles.php' , array ( 'userid' => $user -> id , 'courseid' => $course -> id ));
2010-04-19 06:30:30 +00:00
$roles -> add ( get_string ( 'thisusersroles' , 'role' ), $url , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
$assignableroles = get_assignable_roles ( $usercontext , ROLENAME_BOTH );
if ( ! empty ( $assignableroles )) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/admin/roles/assign.php' , array ( 'contextid' => $usercontext -> id , 'userid' => $user -> id , 'courseid' => $course -> id ));
2010-04-19 06:30:30 +00:00
$roles -> add ( get_string ( 'assignrolesrelativetothisuser' , 'role' ), $url , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
}
2010-03-22 03:04:00 +00:00
if ( has_capability ( 'moodle/role:review' , $usercontext ) || count ( get_overridable_roles ( $usercontext , ROLENAME_BOTH )) > 0 ) {
$url = new moodle_url ( '/admin/roles/permissions.php' , array ( 'contextid' => $usercontext -> id , 'userid' => $user -> id , 'courseid' => $course -> id ));
2010-04-19 06:30:30 +00:00
$roles -> add ( get_string ( 'permissions' , 'role' ), $url , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
}
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/admin/roles/check.php' , array ( 'contextid' => $usercontext -> id , 'userid' => $user -> id , 'courseid' => $course -> id ));
2010-04-19 06:30:30 +00:00
$roles -> add ( get_string ( 'checkpermissions' , 'role' ), $url , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
}
// Portfolio
2009-12-23 01:22:48 +00:00
if ( $currentuser && ! empty ( $CFG -> enableportfolios ) && has_capability ( 'moodle/portfolio:export' , $systemcontext )) {
2009-12-12 11:27:07 +00:00
require_once ( $CFG -> libdir . '/portfoliolib.php' );
if ( portfolio_instances ( true , false )) {
2010-04-19 06:30:30 +00:00
$portfolio = $usersetting -> add ( get_string ( 'portfolios' , 'portfolio' ), null , self :: TYPE_SETTING );
2010-07-12 20:04:38 +00:00
$url = new moodle_url ( '/user/portfolio.php' , array ( 'courseid' => $course -> id ));
$portfolio -> add ( get_string ( 'configure' , 'portfolio' ), $url , self :: TYPE_SETTING );
$url = new moodle_url ( '/user/portfoliologs.php' , array ( 'courseid' => $course -> id ));
$portfolio -> add ( get_string ( 'logs' , 'portfolio' ), $url , self :: TYPE_SETTING );
2009-12-12 11:27:07 +00:00
}
2009-08-28 08:47:31 +00:00
}
2010-05-13 02:13:06 +00:00
$enablemanagetokens = false ;
if ( ! empty ( $CFG -> enablerssfeeds )) {
$enablemanagetokens = true ;
} else if ( ! is_siteadmin ( $USER -> id )
&& ! empty ( $CFG -> enablewebservices )
&& has_capability ( 'moodle/webservice:createtoken' , get_system_context ()) ) {
$enablemanagetokens = true ;
}
2010-01-19 08:16:57 +00:00
// Security keys
2010-05-13 02:13:06 +00:00
if ( $currentuser && $enablemanagetokens ) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/user/managetoken.php' , array ( 'sesskey' => sesskey ()));
2010-01-19 08:16:57 +00:00
$usersetting -> add ( get_string ( 'securitykeys' , 'webservice' ), $url , self :: TYPE_SETTING );
2010-01-12 10:34:52 +00:00
}
2009-08-28 08:47:31 +00:00
// Repository
2011-06-24 16:42:41 +08:00
if ( ! $currentuser && $usercontext -> contextlevel == CONTEXT_USER ) {
if ( ! $this -> cache -> cached ( 'contexthasrepos' . $usercontext -> id )) {
require_once ( $CFG -> dirroot . '/repository/lib.php' );
$editabletypes = repository :: get_editable_types ( $usercontext );
$haseditabletypes = ! empty ( $editabletypes );
unset ( $editabletypes );
$this -> cache -> set ( 'contexthasrepos' . $usercontext -> id , $haseditabletypes );
} else {
$haseditabletypes = $this -> cache -> { 'contexthasrepos' . $usercontext -> id };
}
if ( $haseditabletypes ) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/repository/manage_instances.php' , array ( 'contextid' => $usercontext -> id ));
2009-09-04 08:43:49 +00:00
$usersetting -> add ( get_string ( 'repositories' , 'repository' ), $url , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
}
}
// Messaging
2010-07-13 02:35:31 +00:00
if (( $currentuser && has_capability ( 'moodle/user:editownmessageprofile' , $systemcontext )) || ( ! isguestuser ( $user ) && has_capability ( 'moodle/user:editmessageprofile' , $usercontext ) && ! is_primary_admin ( $user -> id ))) {
2012-10-22 16:46:39 +08:00
$url = new moodle_url ( '/message/edit.php' , array ( 'id' => $user -> id ));
2012-11-01 09:42:11 +08:00
$usersetting -> add ( get_string ( 'messaging' , 'message' ), $url , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
}
2010-05-20 08:04:20 +00:00
// Blogs
2012-07-19 11:30:05 +08:00
if ( $currentuser && ! empty ( $CFG -> enableblogs )) {
2010-05-20 08:04:20 +00:00
$blog = $usersetting -> add ( get_string ( 'blogs' , 'blog' ), null , navigation_node :: TYPE_CONTAINER , null , 'blogs' );
$blog -> add ( get_string ( 'preferences' , 'blog' ), new moodle_url ( '/blog/preferences.php' ), navigation_node :: TYPE_SETTING );
2012-07-25 16:25:55 +08:00
if ( ! empty ( $CFG -> useexternalblogs ) && $CFG -> maxexternalblogsperuser > 0 && has_capability ( 'moodle/blog:manageexternal' , context_system :: instance ())) {
2010-05-20 08:04:20 +00:00
$blog -> add ( get_string ( 'externalblogs' , 'blog' ), new moodle_url ( '/blog/external_blogs.php' ), navigation_node :: TYPE_SETTING );
$blog -> add ( get_string ( 'addnewexternalblog' , 'blog' ), new moodle_url ( '/blog/external_blog_edit.php' ), navigation_node :: TYPE_SETTING );
}
}
2013-04-16 10:47:40 +12:00
// Badges.
if ( $currentuser && ! empty ( $CFG -> enablebadges )) {
$badges = $usersetting -> add ( get_string ( 'badges' ), null , navigation_node :: TYPE_CONTAINER , null , 'badges' );
$badges -> add ( get_string ( 'preferences' ), new moodle_url ( '/badges/preferences.php' ), navigation_node :: TYPE_SETTING );
if ( ! empty ( $CFG -> badges_allowexternalbackpack )) {
$badges -> add ( get_string ( 'backpackdetails' , 'badges' ), new moodle_url ( '/badges/mybackpack.php' ), navigation_node :: TYPE_SETTING );
}
}
2013-02-15 13:06:26 +08:00
// Add reports node.
$reporttab = $usersetting -> add ( get_string ( 'activityreports' ));
$reports = get_plugin_list_with_function ( 'report' , 'extend_navigation_user' , 'lib.php' );
foreach ( $reports as $reportfunction ) {
$reportfunction ( $reporttab , $user , $course );
}
$anyreport = has_capability ( 'moodle/user:viewuseractivitiesreport' , $usercontext );
2013-03-05 09:24:19 +13:00
if ( $anyreport || ( $course -> showreports && $currentuser && $forceforcontext )) {
2013-02-15 13:06:26 +08:00
// Add grade hardcoded grade report if necessary.
$gradeaccess = false ;
if ( has_capability ( 'moodle/grade:viewall' , $coursecontext )) {
// Can view all course grades.
$gradeaccess = true ;
} else if ( $course -> showgrades ) {
2013-03-05 09:24:19 +13:00
if ( $currentuser && has_capability ( 'moodle/grade:view' , $coursecontext )) {
2013-02-15 13:06:26 +08:00
// Can view own grades.
$gradeaccess = true ;
} else if ( has_capability ( 'moodle/grade:viewall' , $usercontext )) {
// Can view grades of this user - parent most probably.
$gradeaccess = true ;
} else if ( $anyreport ) {
// Can view grades of this user - parent most probably.
$gradeaccess = true ;
}
}
if ( $gradeaccess ) {
$reporttab -> add ( get_string ( 'grade' ), new moodle_url ( '/course/user.php' , array ( 'mode' => 'grade' , 'id' => $course -> id ,
'user' => $usercontext -> instanceid )));
}
}
// Check the number of nodes in the report node... if there are none remove the node
$reporttab -> trim_if_empty ();
2010-05-04 13:04:35 +00:00
// Login as ...
if ( ! $user -> deleted and ! $currentuser && ! session_is_loggedinas () && has_capability ( 'moodle/user:loginas' , $coursecontext ) && ! is_siteadmin ( $user -> id )) {
$url = new moodle_url ( '/course/loginas.php' , array ( 'id' => $course -> id , 'user' => $user -> id , 'sesskey' => sesskey ()));
$usersetting -> add ( get_string ( 'loginas' ), $url , self :: TYPE_SETTING );
}
2010-04-19 06:30:30 +00:00
return $usersetting ;
2009-08-28 08:47:31 +00:00
}
2010-03-22 03:04:00 +00:00
/**
* Loads block specific settings in the navigation
2010-03-31 07:41:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ return navigation_node
2010-03-22 03:04:00 +00:00
*/
protected function load_block_settings () {
global $CFG ;
2010-04-19 06:30:30 +00:00
$blocknode = $this -> add ( print_context_name ( $this -> context ));
$blocknode -> force_open ();
2010-03-22 03:04:00 +00:00
// Assign local roles
$assignurl = new moodle_url ( '/' . $CFG -> admin . '/roles/assign.php' , array ( 'contextid' => $this -> context -> id ));
$blocknode -> add ( get_string ( 'assignroles' , 'role' ), $assignurl , self :: TYPE_SETTING );
// Override roles
if ( has_capability ( 'moodle/role:review' , $this -> context ) or count ( get_overridable_roles ( $this -> context )) > 0 ) {
$url = new moodle_url ( '/' . $CFG -> admin . '/roles/permissions.php' , array ( 'contextid' => $this -> context -> id ));
$blocknode -> add ( get_string ( 'permissions' , 'role' ), $url , self :: TYPE_SETTING );
}
// Check role permissions
if ( has_any_capability ( array ( 'moodle/role:assign' , 'moodle/role:safeoverride' , 'moodle/role:override' , 'moodle/role:assign' ), $this -> context )) {
$url = new moodle_url ( '/' . $CFG -> admin . '/roles/check.php' , array ( 'contextid' => $this -> context -> id ));
$blocknode -> add ( get_string ( 'checkpermissions' , 'role' ), $url , self :: TYPE_SETTING );
}
2010-04-19 06:30:30 +00:00
return $blocknode ;
2010-03-22 03:04:00 +00:00
}
/**
* Loads category specific settings in the navigation
*
2010-04-19 06:30:30 +00:00
* @ return navigation_node
2010-03-22 03:04:00 +00:00
*/
protected function load_category_settings () {
global $CFG ;
2012-12-06 14:08:25 +00:00
$categorynode = $this -> add ( print_context_name ( $this -> context ), null , null , null , 'categorysettings' );
2010-04-21 02:43:02 +00:00
$categorynode -> force_open ();
2013-01-29 15:06:37 +11:00
$onmanagepage = $this -> page -> url -> compare ( new moodle_url ( '/course/manage.php' ), URL_MATCH_BASE );
2010-03-22 03:04:00 +00:00
2013-01-29 15:06:37 +11:00
if ( can_edit_in_category ( $this -> context -> instanceid ) && ! $onmanagepage ) {
2013-04-09 12:55:50 +10:00
$url = new moodle_url ( '/course/manage.php' , array ( 'categoryid' => $this -> context -> instanceid ));
2013-01-29 15:06:37 +11:00
$editstring = get_string ( 'managecategorythis' );
2010-11-22 05:31:46 +00:00
$categorynode -> add ( $editstring , $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/edit' , '' ));
}
2013-02-07 12:49:56 +11:00
if ( has_capability ( 'moodle/category:manage' , $this -> context )) {
2010-11-22 05:31:46 +00:00
$editurl = new moodle_url ( '/course/editcategory.php' , array ( 'id' => $this -> context -> instanceid ));
$categorynode -> add ( get_string ( 'editcategorythis' ), $editurl , self :: TYPE_SETTING , null , 'edit' , new pix_icon ( 'i/edit' , '' ));
$addsubcaturl = new moodle_url ( '/course/editcategory.php' , array ( 'parent' => $this -> context -> instanceid ));
$categorynode -> add ( get_string ( 'addsubcategory' ), $addsubcaturl , self :: TYPE_SETTING , null , 'addsubcat' , new pix_icon ( 'i/withsubcat' , '' ));
2010-03-22 03:04:00 +00:00
}
// Assign local roles
2010-11-11 08:58:46 +00:00
if ( has_capability ( 'moodle/role:assign' , $this -> context )) {
$assignurl = new moodle_url ( '/' . $CFG -> admin . '/roles/assign.php' , array ( 'contextid' => $this -> context -> id ));
2012-11-13 16:48:50 +08:00
$categorynode -> add ( get_string ( 'assignroles' , 'role' ), $assignurl , self :: TYPE_SETTING , null , 'roles' , new pix_icon ( 'i/assignroles' , '' ));
2010-11-11 08:58:46 +00:00
}
2010-03-22 03:04:00 +00:00
// Override roles
if ( has_capability ( 'moodle/role:review' , $this -> context ) or count ( get_overridable_roles ( $this -> context )) > 0 ) {
$url = new moodle_url ( '/' . $CFG -> admin . '/roles/permissions.php' , array ( 'contextid' => $this -> context -> id ));
2010-11-22 05:31:46 +00:00
$categorynode -> add ( get_string ( 'permissions' , 'role' ), $url , self :: TYPE_SETTING , null , 'permissions' , new pix_icon ( 'i/permissions' , '' ));
2010-03-22 03:04:00 +00:00
}
// Check role permissions
if ( has_any_capability ( array ( 'moodle/role:assign' , 'moodle/role:safeoverride' , 'moodle/role:override' , 'moodle/role:assign' ), $this -> context )) {
$url = new moodle_url ( '/' . $CFG -> admin . '/roles/check.php' , array ( 'contextid' => $this -> context -> id ));
2010-11-22 05:31:46 +00:00
$categorynode -> add ( get_string ( 'checkpermissions' , 'role' ), $url , self :: TYPE_SETTING , null , 'checkpermissions' , new pix_icon ( 'i/checkpermissions' , '' ));
2010-04-21 02:43:02 +00:00
}
2010-08-17 13:05:33 +00:00
// Cohorts
if ( has_capability ( 'moodle/cohort:manage' , $this -> context ) or has_capability ( 'moodle/cohort:view' , $this -> context )) {
2010-11-22 05:31:46 +00:00
$categorynode -> add ( get_string ( 'cohorts' , 'cohort' ), new moodle_url ( '/cohort/index.php' , array ( 'contextid' => $this -> context -> id )), self :: TYPE_SETTING , null , 'cohort' , new pix_icon ( 'i/cohort' , '' ));
2010-08-17 13:05:33 +00:00
}
2010-04-21 02:43:02 +00:00
// Manage filters
if ( has_capability ( 'moodle/filter:manage' , $this -> context ) && count ( filter_get_available_in_context ( $this -> context )) > 0 ) {
$url = new moodle_url ( '/filter/manage.php' , array ( 'contextid' => $this -> context -> id ));
2010-11-22 05:31:46 +00:00
$categorynode -> add ( get_string ( 'filters' , 'admin' ), $url , self :: TYPE_SETTING , null , 'filters' , new pix_icon ( 'i/filter' , '' ));
2010-03-22 03:04:00 +00:00
}
2010-04-21 02:43:02 +00:00
return $categorynode ;
2010-03-22 03:04:00 +00:00
}
2009-08-28 08:47:31 +00:00
/**
* Determine whether the user is assuming another role
*
* This function checks to see if the user is assuming another role by means of
* role switching . In doing this we compare each RSW key ( context path ) against
* the current context path . This ensures that we can provide the switching
* options against both the course and any page shown under the course .
*
* @ return bool | int The role ( int ) if the user is in another role , false otherwise
*/
protected function in_alternative_role () {
global $USER ;
if ( ! empty ( $USER -> access [ 'rsw' ]) && is_array ( $USER -> access [ 'rsw' ])) {
if ( ! empty ( $this -> page -> context ) && ! empty ( $USER -> access [ 'rsw' ][ $this -> page -> context -> path ])) {
return $USER -> access [ 'rsw' ][ $this -> page -> context -> path ];
}
foreach ( $USER -> access [ 'rsw' ] as $key => $role ) {
if ( strpos ( $this -> context -> path , $key ) === 0 ) {
return $role ;
}
}
}
return false ;
}
/**
2009-09-09 04:21:20 +00:00
* This function loads all of the front page settings into the settings navigation .
* This function is called when the user is on the front page , or $COURSE == $SITE
2012-01-04 15:56:26 +08:00
* @ param bool $forceopen ( optional )
2010-04-19 06:30:30 +00:00
* @ return navigation_node
2009-08-28 08:47:31 +00:00
*/
2010-03-22 03:04:00 +00:00
protected function load_front_page_settings ( $forceopen = false ) {
global $SITE , $CFG ;
2009-08-28 08:47:31 +00:00
2010-03-22 03:04:00 +00:00
$course = clone ( $SITE );
2012-07-25 16:25:55 +08:00
$coursecontext = context_course :: instance ( $course -> id ); // Course context
2009-08-28 08:47:31 +00:00
2010-04-19 06:30:30 +00:00
$frontpage = $this -> add ( get_string ( 'frontpagesettings' ), null , self :: TYPE_SETTING , null , 'frontpage' );
if ( $forceopen ) {
$frontpage -> force_open ();
}
2010-03-22 03:04:00 +00:00
$frontpage -> id = 'frontpagesettings' ;
2010-02-18 05:57:20 +00:00
2013-05-30 10:18:00 +10:00
if ( $this -> page -> user_allowed_editing ()) {
2009-08-28 08:47:31 +00:00
// Add the turn on/off settings
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/course/view.php' , array ( 'id' => $course -> id , 'sesskey' => sesskey ()));
2009-08-28 08:47:31 +00:00
if ( $this -> page -> user_is_editing ()) {
$url -> param ( 'edit' , 'off' );
$editstring = get_string ( 'turneditingoff' );
} else {
$url -> param ( 'edit' , 'on' );
$editstring = get_string ( 'turneditingon' );
}
2010-02-18 05:57:20 +00:00
$frontpage -> add ( $editstring , $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/edit' , '' ));
2013-05-30 10:18:00 +10:00
}
2009-08-28 08:47:31 +00:00
2013-05-30 10:18:00 +10:00
if ( has_capability ( 'moodle/course:update' , $coursecontext )) {
2009-08-28 08:47:31 +00:00
// Add the course settings link
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/admin/settings.php' , array ( 'section' => 'frontpagesettings' ));
2010-07-09 08:20:39 +00:00
$frontpage -> add ( get_string ( 'editsettings' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/settings' , '' ));
2009-08-28 08:47:31 +00:00
}
2009-09-09 04:21:20 +00:00
MDL-21782 reworked enrolment framework, the core infrastructure is in place, the basic plugins are all implemented; see the tracker issue for list of unfinished bits, expect more changes and improvements during the next week
AMOS START
MOV [sendcoursewelcomemessage,core_admin],[sendcoursewelcomemessage,enrol_self]
MOV [configsendcoursewelcomemessage,core_admin],[sendcoursewelcomemessage_desc,enrol_self]
MOV [enrolstartdate,core],[enrolstartdate,enrol_self]
MOV [enrolenddate,core],[enrolenddate,enrol_self]
CPY [welcometocourse,core],[welcometocourse,enrol_self]
CPY [welcometocoursetext,core],[welcometocoursetext,enrol_self]
MOV [notenrollable,core],[notenrollable,core_enrol]
MOV [enrolenddaterror,core],[enrolenddaterror,enrol_self]
MOV [enrolmentkeyhint,core],[passwordinvalidhint,enrol_self]
MOV [coursemanager,core_admin],[coursecontact,core_admin]
MOV [configcoursemanager,core_admin],[coursecontact_desc,core_admin]
MOV [enrolledincourserole,core],[enrolledincourserole,enrol_manual]
MOV [enrolme,core],[enrolme,core_enrol]
MOV [unenrol,core],[unenrol,core_enrol]
MOV [unenrolme,core],[unenrolme,core_enrol]
MOV [enrolmentnew,core],[enrolmentnew,core_enrol]
MOV [enrolmentnewuser,core],[enrolmentnewuser,core_enrol]
MOV [enrolments,core],[enrolments,core_enrol]
MOV [enrolperiod,core],[enrolperiod,core_enrol]
MOV [unenrolroleusers,core],[unenrolroleusers,core_enrol]
AMOS END
2010-06-21 15:30:49 +00:00
// add enrol nodes
enrol_add_course_navigation ( $frontpage , $course );
// Manage filters
if ( has_capability ( 'moodle/filter:manage' , $coursecontext ) && count ( filter_get_available_in_context ( $coursecontext )) > 0 ) {
$url = new moodle_url ( '/filter/manage.php' , array ( 'contextid' => $coursecontext -> id ));
$frontpage -> add ( get_string ( 'filters' , 'admin' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/filter' , '' ));
2010-03-22 03:04:00 +00:00
}
2013-02-15 13:06:26 +08:00
// View course reports.
if ( has_capability ( 'moodle/site:viewreports' , $coursecontext )) { // Basic capability for listing of reports.
$frontpagenav = $frontpage -> add ( get_string ( 'reports' ), null , self :: TYPE_CONTAINER , null , null ,
new pix_icon ( 'i/stats' , '' ));
$coursereports = get_plugin_list ( 'coursereport' );
foreach ( $coursereports as $report => $dir ) {
$libfile = $CFG -> dirroot . '/course/report/' . $report . '/lib.php' ;
if ( file_exists ( $libfile )) {
require_once ( $libfile );
$reportfunction = $report . '_report_extend_navigation' ;
if ( function_exists ( $report . '_report_extend_navigation' )) {
$reportfunction ( $frontpagenav , $course , $coursecontext );
}
}
}
$reports = get_plugin_list_with_function ( 'report' , 'extend_navigation_course' , 'lib.php' );
foreach ( $reports as $reportfunction ) {
$reportfunction ( $frontpagenav , $course , $coursecontext );
}
}
2010-03-22 03:04:00 +00:00
// Backup this course
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/backup:backupcourse' , $coursecontext )) {
2010-03-22 03:04:00 +00:00
$url = new moodle_url ( '/backup/backup.php' , array ( 'id' => $course -> id ));
$frontpage -> add ( get_string ( 'backup' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/backup' , '' ));
}
// Restore to this course
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/restore:restorecourse' , $coursecontext )) {
2010-08-24 03:52:52 +00:00
$url = new moodle_url ( '/backup/restorefile.php' , array ( 'contextid' => $coursecontext -> id ));
2010-03-22 03:04:00 +00:00
$frontpage -> add ( get_string ( 'restore' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/restore' , '' ));
}
2011-12-22 17:37:41 +00:00
// Questions
require_once ( $CFG -> libdir . '/questionlib.php' );
question_extend_settings_navigation ( $frontpage , $coursecontext ) -> trim_if_empty ();
2010-03-22 03:04:00 +00:00
// Manage files
2010-09-03 19:14:33 +00:00
if ( $course -> legacyfiles == 2 and has_capability ( 'moodle/course:managefiles' , $this -> context )) {
2010-08-02 13:33:19 +00:00
//hiden in new installs
2010-09-03 19:14:33 +00:00
$url = new moodle_url ( '/files/index.php' , array ( 'contextid' => $coursecontext -> id , 'itemid' => 0 , 'component' => 'course' , 'filearea' => 'legacy' ));
2012-11-22 17:08:10 +08:00
$frontpage -> add ( get_string ( 'sitelegacyfiles' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/folder' , '' ));
2010-03-22 03:04:00 +00:00
}
2010-04-19 06:30:30 +00:00
return $frontpage ;
2009-08-28 08:47:31 +00:00
}
2009-10-12 05:39:32 +00:00
2011-11-30 10:30:46 +10:00
/**
* This function gives local plugins an opportunity to modify the settings navigation .
*/
protected function load_local_plugin_settings () {
// Get all local plugins with an extend_settings_navigation function in their lib.php file
2012-06-08 09:34:19 +12:00
foreach ( get_plugin_list_with_function ( 'local' , 'extends_settings_navigation' ) as $function ) {
2011-11-30 10:30:46 +10:00
// Call each function providing this (the settings navigation) and the current context.
2012-06-08 09:34:19 +12:00
$function ( $this , $this -> context );
2011-11-30 10:30:46 +10:00
}
}
2009-10-12 05:39:32 +00:00
/**
* This function marks the cache as volatile so it is cleared during shutdown
*/
public function clear_cache () {
$this -> cache -> volatile ();
}
2009-08-28 08:47:31 +00:00
}
/**
* Simple class used to output a navigation branch in XML
*
2012-01-04 15:56:26 +08:00
* @ package core
* @ category navigation
2009-08-28 08:47:31 +00:00
* @ copyright 2009 Sam Hemelryk
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
2010-02-18 05:57:20 +00:00
class navigation_json {
2012-01-04 15:56:26 +08:00
/** @var array An array of different node types */
2009-08-28 08:47:31 +00:00
protected $nodetype = array ( 'node' , 'branch' );
2012-01-04 15:56:26 +08:00
/** @var array An array of node keys and types */
2009-08-28 08:47:31 +00:00
protected $expandable = array ();
/**
* Turns a branch and all of its children into XML
*
* @ param navigation_node $branch
* @ return string XML string
*/
public function convert ( $branch ) {
$xml = $this -> convert_child ( $branch );
return $xml ;
}
/**
* Set the expandable items in the array so that we have enough information
* to attach AJAX events
2010-04-19 06:30:30 +00:00
* @ param array $expandable
2009-08-28 08:47:31 +00:00
*/
public function set_expandable ( $expandable ) {
foreach ( $expandable as $node ) {
2010-12-23 11:21:07 +08:00
$this -> expandable [ $node [ 'key' ] . ':' . $node [ 'type' ]] = $node ;
2009-08-28 08:47:31 +00:00
}
}
/**
* Recusively converts a child node and its children to XML for output
*
* @ param navigation_node $child The child to convert
* @ param int $depth Pointlessly used to track the depth of the XML structure
2010-04-19 06:30:30 +00:00
* @ return string JSON
2009-08-28 08:47:31 +00:00
*/
protected function convert_child ( $child , $depth = 1 ) {
if ( ! $child -> display ) {
return '' ;
}
$attributes = array ();
$attributes [ 'id' ] = $child -> id ;
2010-02-18 05:57:20 +00:00
$attributes [ 'name' ] = $child -> text ;
2009-08-28 08:47:31 +00:00
$attributes [ 'type' ] = $child -> type ;
$attributes [ 'key' ] = $child -> key ;
$attributes [ 'class' ] = $child -> get_css_type ();
2010-02-19 02:24:26 +00:00
if ( $child -> icon instanceof pix_icon ) {
$attributes [ 'icon' ] = array (
'component' => $child -> icon -> component ,
'pix' => $child -> icon -> pix ,
);
foreach ( $child -> icon -> attributes as $key => $value ) {
if ( $key == 'class' ) {
$attributes [ 'icon' ][ 'classes' ] = explode ( ' ' , $value );
} else if ( ! array_key_exists ( $key , $attributes [ 'icon' ])) {
$attributes [ 'icon' ][ $key ] = $value ;
}
}
} else if ( ! empty ( $child -> icon )) {
$attributes [ 'icon' ] = ( string ) $child -> icon ;
}
2009-08-28 08:47:31 +00:00
if ( $child -> forcetitle || $child -> title !== $child -> text ) {
2012-12-09 18:21:38 +01:00
$attributes [ 'title' ] = htmlentities ( $child -> title , ENT_QUOTES , 'UTF-8' );
2009-08-28 08:47:31 +00:00
}
2010-05-13 09:57:43 +00:00
if ( array_key_exists ( $child -> key . ':' . $child -> type , $this -> expandable )) {
2009-08-28 08:47:31 +00:00
$attributes [ 'expandable' ] = $child -> key ;
2010-05-13 09:57:43 +00:00
$child -> add_class ( $this -> expandable [ $child -> key . ':' . $child -> type ][ 'id' ]);
2009-08-28 08:47:31 +00:00
}
2009-10-14 09:08:43 +00:00
2009-08-28 08:47:31 +00:00
if ( count ( $child -> classes ) > 0 ) {
$attributes [ 'class' ] .= ' ' . join ( ' ' , $child -> classes );
}
if ( is_string ( $child -> action )) {
$attributes [ 'link' ] = $child -> action ;
} else if ( $child -> action instanceof moodle_url ) {
$attributes [ 'link' ] = $child -> action -> out ();
2011-10-24 12:46:07 +01:00
} else if ( $child -> action instanceof action_link ) {
$attributes [ 'link' ] = $child -> action -> url -> out ();
2009-08-28 08:47:31 +00:00
}
$attributes [ 'hidden' ] = ( $child -> hidden );
2010-04-19 06:30:30 +00:00
$attributes [ 'haschildren' ] = ( $child -> children -> count () > 0 || $child -> type == navigation_node :: TYPE_CATEGORY );
2013-02-07 11:04:24 +08:00
$attributes [ 'haschildren' ] = $attributes [ 'haschildren' ] || $child -> type == navigation_node :: TYPE_MY_CATEGORY ;
2009-08-28 08:47:31 +00:00
2011-06-27 15:11:28 +08:00
if ( $child -> children -> count () > 0 ) {
2010-02-18 05:57:20 +00:00
$attributes [ 'children' ] = array ();
2009-08-28 08:47:31 +00:00
foreach ( $child -> children as $subchild ) {
2010-02-18 05:57:20 +00:00
$attributes [ 'children' ][] = $this -> convert_child ( $subchild , $depth + 1 );
2009-08-28 08:47:31 +00:00
}
}
2010-02-18 05:57:20 +00:00
if ( $depth > 1 ) {
return $attributes ;
} else {
return json_encode ( $attributes );
}
2009-08-28 08:47:31 +00:00
}
}
/**
2012-05-07 12:57:42 +12:00
* The cache class used by global navigation and settings navigation .
2009-08-28 08:47:31 +00:00
*
* It is basically an easy access point to session with a bit of smarts to make
* sure that the information that is cached is valid still .
*
* Example use :
* < code php >
* if ( ! $cache -> viewdiscussion ()) {
* // Code to do stuff and produce cachable content
* $cache -> viewdiscussion = has_capability ( 'mod/forum:viewdiscussion' , $coursecontext );
* }
* $content = $cache -> viewdiscussion ;
* </ code >
*
2012-01-04 15:56:26 +08:00
* @ package core
* @ category navigation
2009-08-28 08:47:31 +00:00
* @ copyright 2009 Sam Hemelryk
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
class navigation_cache {
2012-01-04 15:56:26 +08:00
/** @var int represents the time created */
2009-08-28 08:47:31 +00:00
protected $creation ;
2012-01-04 15:56:26 +08:00
/** @var array An array of session keys */
2009-08-28 08:47:31 +00:00
protected $session ;
2012-01-04 15:56:26 +08:00
/**
* The string to use to segregate this particular cache . It can either be
* unique to start a fresh cache or if you want to share a cache then make
* it the string used in the original cache .
* @ var string
*/
2009-08-28 08:47:31 +00:00
protected $area ;
2012-01-04 15:56:26 +08:00
/** @var int a time that the information will time out */
2009-08-28 08:47:31 +00:00
protected $timeout ;
2012-01-04 15:56:26 +08:00
/** @var stdClass The current context */
2009-08-28 08:47:31 +00:00
protected $currentcontext ;
2012-01-04 15:56:26 +08:00
/** @var int cache time information */
2009-08-28 08:47:31 +00:00
const CACHETIME = 0 ;
2012-01-04 15:56:26 +08:00
/** @var int cache user id */
2009-08-28 08:47:31 +00:00
const CACHEUSERID = 1 ;
2012-01-04 15:56:26 +08:00
/** @var int cache value */
2009-08-28 08:47:31 +00:00
const CACHEVALUE = 2 ;
2009-10-12 05:39:32 +00:00
/** @var null|array An array of navigation cache areas to expire on shutdown */
public static $volatilecaches ;
2009-11-01 11:31:16 +00:00
2009-08-28 08:47:31 +00:00
/**
* Contructor for the cache . Requires two arguments
*
* @ param string $area The string to use to segregate this particular cache
* it can either be unique to start a fresh cache or if you want
* to share a cache then make it the string used in the original
* cache
* @ param int $timeout The number of seconds to time the information out after
*/
2011-06-24 16:42:41 +08:00
public function __construct ( $area , $timeout = 1800 ) {
2009-08-28 08:47:31 +00:00
$this -> creation = time ();
$this -> area = $area ;
2011-06-24 16:42:41 +08:00
$this -> timeout = time () - $timeout ;
if ( rand ( 0 , 100 ) === 0 ) {
$this -> garbage_collection ();
2009-08-28 08:47:31 +00:00
}
2011-06-24 16:42:41 +08:00
}
2009-08-28 08:47:31 +00:00
2011-06-24 16:42:41 +08:00
/**
* Used to set up the cache within the SESSION .
*
* This is called for each access and ensure that we don ' t put anything into the session before
* it is required .
*/
protected function ensure_session_cache_initialised () {
global $SESSION ;
if ( empty ( $this -> session )) {
if ( ! isset ( $SESSION -> navcache )) {
$SESSION -> navcache = new stdClass ;
}
if ( ! isset ( $SESSION -> navcache -> { $this -> area })) {
$SESSION -> navcache -> { $this -> area } = array ();
}
2012-05-06 13:31:55 +02:00
$this -> session = & $SESSION -> navcache -> { $this -> area }; // pointer to array, =& is correct here
2009-08-28 08:47:31 +00:00
}
}
/**
* Magic Method to retrieve something by simply calling using = cache -> key
*
* @ param mixed $key The identifier for the information you want out again
* @ return void | mixed Either void or what ever was put in
*/
public function __get ( $key ) {
if ( ! $this -> cached ( $key )) {
return ;
}
$information = $this -> session [ $key ][ self :: CACHEVALUE ];
return unserialize ( $information );
}
/**
* Magic method that simply uses { @ link set ();} to store something in the cache
*
* @ param string | int $key
* @ param mixed $information
*/
public function __set ( $key , $information ) {
$this -> set ( $key , $information );
}
2009-10-12 05:39:32 +00:00
2009-08-28 08:47:31 +00:00
/**
* Sets some information against the cache ( session ) for later retrieval
*
* @ param string | int $key
* @ param mixed $information
*/
public function set ( $key , $information ) {
global $USER ;
2011-06-24 16:42:41 +08:00
$this -> ensure_session_cache_initialised ();
2009-08-28 08:47:31 +00:00
$information = serialize ( $information );
$this -> session [ $key ] = array ( self :: CACHETIME => time (), self :: CACHEUSERID => $USER -> id , self :: CACHEVALUE => $information );
}
/**
* Check the existence of the identifier in the cache
*
* @ param string | int $key
* @ return bool
*/
public function cached ( $key ) {
global $USER ;
2011-06-24 16:42:41 +08:00
$this -> ensure_session_cache_initialised ();
2009-08-28 08:47:31 +00:00
if ( ! array_key_exists ( $key , $this -> session ) || ! is_array ( $this -> session [ $key ]) || $this -> session [ $key ][ self :: CACHEUSERID ] != $USER -> id || $this -> session [ $key ][ self :: CACHETIME ] < $this -> timeout ) {
return false ;
}
return true ;
}
2009-09-08 08:49:12 +00:00
/**
* Compare something to it ' s equivilant in the cache
*
* @ param string $key
* @ param mixed $value
* @ param bool $serialise Whether to serialise the value before comparison
* this should only be set to false if the value is already
* serialised
* @ return bool If the value is the same false if it is not set or doesn ' t match
*/
2011-06-24 16:42:41 +08:00
public function compare ( $key , $value , $serialise = true ) {
2009-09-08 08:49:12 +00:00
if ( $this -> cached ( $key )) {
if ( $serialise ) {
$value = serialize ( $value );
}
if ( $this -> session [ $key ][ self :: CACHEVALUE ] === $value ) {
return true ;
}
}
return false ;
}
2009-08-28 08:47:31 +00:00
/**
2009-10-19 03:29:48 +00:00
* Wipes the entire cache , good to force regeneration
2009-08-28 08:47:31 +00:00
*/
public function clear () {
2011-06-24 16:42:41 +08:00
global $SESSION ;
unset ( $SESSION -> navcache );
$this -> session = null ;
2009-08-28 08:47:31 +00:00
}
/**
* Checks all cache entries and removes any that have expired , good ole cleanup
*/
protected function garbage_collection () {
2011-06-24 16:42:41 +08:00
if ( empty ( $this -> session )) {
return true ;
}
2009-08-28 08:47:31 +00:00
foreach ( $this -> session as $key => $cachedinfo ) {
if ( is_array ( $cachedinfo ) && $cachedinfo [ self :: CACHETIME ] < $this -> timeout ) {
unset ( $this -> session [ $key ]);
}
}
}
2009-10-12 05:39:32 +00:00
/**
* Marks the cache as being volatile ( likely to change )
*
* Any caches marked as volatile will be destroyed at the on shutdown by
2012-02-29 00:56:41 +01:00
* { @ link navigation_node :: destroy_volatile_caches ()} which is registered
2009-10-12 05:39:32 +00:00
* as a shutdown function if any caches are marked as volatile .
*
* @ param bool $setting True to destroy the cache false not too
*/
public function volatile ( $setting = true ) {
if ( self :: $volatilecaches === null ) {
self :: $volatilecaches = array ();
register_shutdown_function ( array ( 'navigation_cache' , 'destroy_volatile_caches' ));
}
if ( $setting ) {
self :: $volatilecaches [ $this -> area ] = $this -> area ;
} else if ( array_key_exists ( $this -> area , self :: $volatilecaches )) {
unset ( self :: $volatilecaches [ $this -> area ]);
}
}
/**
* Destroys all caches marked as volatile
*
* This function is static and works in conjunction with the static volatilecaches
* property of navigation cache .
* Because this function is static it manually resets the cached areas back to an
* empty array .
*/
public static function destroy_volatile_caches () {
global $SESSION ;
if ( is_array ( self :: $volatilecaches ) && count ( self :: $volatilecaches ) > 0 ) {
foreach ( self :: $volatilecaches as $area ) {
$SESSION -> navcache -> { $area } = array ();
}
2010-09-15 08:32:15 +00:00
} else {
$SESSION -> navcache = new stdClass ;
2009-10-12 05:39:32 +00:00
}
}
2010-05-14 02:55:46 +00:00
}