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/>.
/**
* This file contains classes used to manage the navigation structures in Moodle
* and was introduced as part of the changes occuring in Moodle 2.0
*
* @ since 2.0
* @ package moodlecore
* @ subpackage navigation
* @ copyright 2009 Sam Hemelryk
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
if ( ! function_exists ( 'get_all_sections' )) {
/** Include course lib for its functions */
require_once ( $CFG -> dirroot . '/course/lib.php' );
}
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 .
*
* @ package moodlecore
2009-10-19 03:29:48 +00:00
* @ subpackage 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 ;
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 ;
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 ;
2010-04-19 06:30:30 +00:00
/** @var navigation_node A reference to the node parent */
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 ;
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 ;
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 )) {
$properties [ 'icon' ] = new pix_icon ( 'i/navigationitem' , 'moodle' );
}
$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
if ( array_key_exists ( 'parent' , $properties )) {
$this -> parent = $properties [ 'parent' ];
}
// 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 ();
}
}
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
// Default the title to the text
2009-08-28 08:47:31 +00:00
$this -> title = $this -> text ;
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-04-19 06:30:30 +00:00
* Overrides the fullmeurl variable providing
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 ) {
self :: $fullmeurl = $url ;
}
/**
* 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
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function add ( $text , $action = null , $type = self :: TYPE_CUSTOM , $shorttext = null , $key = null , pix_icon $icon = null ) {
// First convert the nodetype for this node to a branch as it will now have children
2009-08-28 08:47:31 +00:00
if ( $this -> nodetype !== self :: NODETYPE_BRANCH ) {
$this -> nodetype = self :: NODETYPE_BRANCH ;
}
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
// Default the key to the number of children if not provided
if ( $key === null ) {
$key = $this -> children -> count ();
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
// Set the key
2009-08-28 08:47:31 +00:00
$itemarray [ 'key' ] = $key ;
2010-04-19 06:30:30 +00:00
// Set the parent to this node
$itemarray [ 'parent' ] = $this ;
// Add the child using the navigation_node_collections add method
$node = $this -> children -> add ( new navigation_node ( $itemarray ));
// If the node is a category node or the user is logged in and its a course
// then mark this node as a branch (makes it expandable by AJAX)
2009-09-04 07:41:21 +00:00
if (( $type == self :: TYPE_CATEGORY ) || ( isloggedin () && $type == self :: TYPE_COURSE )) {
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
}
2010-04-19 06:30:30 +00:00
// Return the node (reference returned by $this->children->add()
return $node ;
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 );
}
/**
* Get ths child of this node that has the given key + ( optional ) type .
*
* 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 () {
return ( $this -> nodetype === navigation_node :: NODETYPE_BRANCH || $this -> children -> count () > 0 );
}
/**
* Marks this node as active and forces it open .
*/
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 .
*
* 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 .
*
* @ 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
*
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 ) {
2010-05-13 09:57:43 +00:00
$isloggedin = ( isloggedin () && ! isguestuser ());
if ( ! $isloggedin && $this -> type > self :: TYPE_CATEGORY ) {
2010-04-19 06:30:30 +00:00
return ;
}
foreach ( $this -> children as & $child ) {
2010-05-13 09:57:43 +00:00
if ( ! $isloggedin && $child -> type > self :: TYPE_CATEGORY ) {
continue ;
}
2010-04-21 09:44:16 +00:00
if ( $child -> nodetype == self :: NODETYPE_BRANCH && $child -> children -> count () == 0 && $child -> display ) {
2010-04-19 06:30:30 +00:00
$child -> id = 'expandable_branch_' . ( count ( $expandable ) + 1 );
$this -> add_class ( 'canexpand' );
$expandable [] = array ( 'id' => $child -> id , 'branchid' => $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 )
*
* @ param int $type On of navigation_node :: TYPE_ *
* @ 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 );
}
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 .
*
* @ package moodlecore
* @ subpackage navigation
* @ 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 ;
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
*
2010-04-19 06:30:30 +00:00
* @ param navigation_node $node
* @ return navigation_node
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function add ( navigation_node $node ) {
global $CFG ;
$key = $node -> key ;
$type = $node -> type ;
// 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
}
2010-04-19 06:30:30 +00:00
// Add the node to the appropriate place in the ordered structure.
$this -> orderedcollection [ $type ][ $key ] = $node ;
// Add a reference to the node to the progressive collection.
$this -> collection [ $this -> count ] = & $this -> orderedcollection [ $type ][ $key ];
// Update the last property to a reference to this new node.
$this -> last = & $this -> orderedcollection [ $type ][ $key ];
$this -> count ++ ;
// Return the reference to the now added node
return $this -> last ;
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 ;
}
/**
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 ) {
if ( $node -> key == $key && ( $type == null || $type === $node -> type )) {
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
*
* @ 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 ;
}
/**
* Fetches all nodes of a given type from this collection
*/
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
*
2010-04-19 06:30:30 +00:00
* @ param string | int $key
* @ 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 ) {
if ( $node -> key == $key && $node -> type == $type ) {
unset ( $this -> collection [ $colkey ]);
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
* @ return int
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function count () {
return count ( $this -> collection );
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
* < ul >
* < li >< b > { @ link lib / pagelib . php } </ b > { @ link moodle_page :: initialise_theme_and_output ()} < li >
* < li >< b > { @ link lib / ajax / getnavbranch . php } </ b > Called by ajax < li >
* </ ul >
*
* @ package moodlecore
2009-10-19 03:29:48 +00:00
* @ subpackage 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 {
2010-04-19 06:30:30 +00:00
/**
* The Moodle page this navigation object belongs to .
* @ var moodle_page
*/
protected $page ;
2009-08-28 08:47:31 +00:00
/** @var bool */
protected $initialised = false ;
2010-04-19 06:30:30 +00:00
/** @var array */
protected $mycourses = array ();
/** @var array */
protected $rootnodes = array ();
2009-08-28 08:47:31 +00:00
/** @var bool */
2010-04-19 06:30:30 +00:00
protected $showemptysections = false ;
/** @var array */
2009-12-23 01:22:48 +00:00
protected $extendforuser = array ();
2010-04-19 06:30:30 +00:00
/** @var navigation_cache */
protected $cache ;
/** @var array */
protected $addedcourses = array ();
2010-04-21 09:44:16 +00:00
/** @var int */
protected $expansionlimit = 0 ;
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
// Use the parents consturctor.... 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 );
2010-04-19 06:30:30 +00:00
// Check if we need to clear the cache
2009-08-28 08:47:31 +00:00
$regenerate = optional_param ( 'regenerate' , null , PARAM_TEXT );
2010-04-19 06:30:30 +00:00
if ( $regenerate === 'navigation' ) {
2009-08-28 08:47:31 +00:00
$this -> cache -> clear ();
}
}
/**
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 () {
2010-05-13 09:57:43 +00:00
global $CFG , $SITE , $USER , $DB ;
2010-04-19 06:30:30 +00:00
// Check if it has alread been initialised
2009-08-28 08:47:31 +00:00
if ( $this -> initialised || during_initial_install ()) {
return 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:
// site: Navigation for the front page.
// myprofile: User profile information goes here.
// mycourses: The users courses get added here.
// courses: Additional courses are added here.
// users: Other users information loaded here.
$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
if ( isloggedin ()) { // Makes no sense if you aren't logged in
$this -> rootnodes [ 'home' ] = $this -> add ( get_string ( 'myhome' ), new moodle_url ( '/my/' ), self :: TYPE_SETTING , null , 'home' );
}
2010-05-13 09:57:43 +00:00
} else {
// The home element should be the site because the root node is my moodle
$this -> rootnodes [ 'home' ] = $this -> add ( get_string ( 'sitehome' ), new moodle_url ( '/' ), self :: TYPE_SETTING , null , 'home' );
if ( $CFG -> defaulthomepage == HOMEPAGE_MY ) {
// We need to stop automatic redirection
$this -> rootnodes [ 'home' ] -> action -> param ( 'redirect' , '0' );
}
}
2010-04-19 06:30:30 +00:00
$this -> rootnodes [ 'site' ] = $this -> add_course ( $SITE );
$this -> rootnodes [ 'myprofile' ] = $this -> add ( get_string ( 'myprofile' ), null , self :: TYPE_USER , null , 'myprofile' );
$this -> rootnodes [ 'mycourses' ] = $this -> add ( get_string ( 'mycourses' ), null , self :: TYPE_ROOTNODE , null , 'mycourses' );
$this -> rootnodes [ 'courses' ] = $this -> add ( get_string ( 'courses' ), null , self :: TYPE_ROOTNODE , null , 'courses' );
$this -> rootnodes [ 'users' ] = $this -> add ( get_string ( 'users' ), null , self :: TYPE_ROOTNODE , null , 'users' );
// Fetch all of the users courses.
2010-05-13 09:57:43 +00:00
$limit = 20 ;
if ( ! empty ( $CFG -> navcourselimit )) {
$limit = $CFG -> navcourselimit ;
}
2010-05-18 02:41:27 +00:00
if ( ! empty ( $CFG -> navshowcategories ) && $DB -> count_records ( 'course_categories' ) == 1 ) {
// There is only one category so we don't want to show categories
$CFG -> navshowcategories = false ;
}
2010-05-13 09:57:43 +00:00
$this -> mycourses = get_my_courses ( $USER -> id , 'visible DESC,sortorder ASC' , null , false , $limit );
2010-05-14 06:41:44 +00:00
$showallcourses = ( count ( $this -> mycourses ) == 0 || ! empty ( $CFG -> navshowallcourses ));
$showcategories = ( $showallcourses && ! empty ( $CFG -> navshowcategories ));
2010-04-19 06:30:30 +00:00
// Check if any courses were returned.
if ( count ( $this -> mycourses ) > 0 ) {
// Add all of the users courses to the navigation
foreach ( $this -> mycourses as & $course ) {
2010-05-13 09:57:43 +00:00
$course -> coursenode = $this -> add_course ( $course );
2010-04-19 06:30:30 +00:00
}
2010-05-13 09:57:43 +00:00
}
if ( $showcategories ) {
// Load all categories (ensures we get the base categories)
$this -> load_all_categories ();
2010-05-14 06:41:44 +00:00
} else if ( $showallcourses ) {
// Load all courses
$this -> load_all_courses ();
2010-04-19 06:30:30 +00:00
}
// Next load context specific content into the navigation
switch ( $this -> page -> context -> contextlevel ) {
case CONTEXT_SYSTEM :
case CONTEXT_COURSECAT :
// Load the front page course navigation
2010-05-19 07:57:00 +00:00
$coursenode = $this -> load_course ( $SITE );
$this -> add_front_page_course_essentials ( $coursenode , $SITE );
2009-08-28 08:47:31 +00:00
break ;
2010-04-19 06:30:30 +00:00
case CONTEXT_BLOCK :
case CONTEXT_COURSE :
// Load the course associated with the page into the navigation
$course = $this -> page -> course ;
$coursenode = $this -> load_course ( $course );
// Add the essentials such as reports etc...
$this -> add_course_essentials ( $coursenode , $course );
if ( $this -> format_display_course_content ( $course -> format )) {
// Load the course sections
$sections = $this -> load_course_sections ( $course , $coursenode );
}
2010-05-19 07:57:00 +00:00
if ( ! $coursenode -> contains_active_node () && ! $coursenode -> search_for_active_node ()) {
$coursenode -> make_active ();
}
2009-08-28 08:47:31 +00:00
break ;
2010-04-19 06:30:30 +00:00
case CONTEXT_MODULE :
$course = $this -> page -> course ;
$cm = $this -> page -> cm ;
// Load the course associated with the page into the navigation
$coursenode = $this -> load_course ( $course );
$this -> add_course_essentials ( $coursenode , $course );
// Load the course sections into the page
$sections = $this -> load_course_sections ( $course , $coursenode );
if ( $course -> id !== SITEID ) {
// Find the section for the $CM associated with the page and collect
// its section number.
foreach ( $sections as $section ) {
if ( $section -> id == $cm -> section ) {
$cm -> sectionnumber = $section -> section ;
break ;
}
}
// Load all of the section activities for the section the cm belongs to.
$activities = $this -> load_section_activities ( $sections [ $cm -> sectionnumber ] -> sectionnode , $cm -> sectionnumber , get_fast_modinfo ( $course ));
} else {
$activities = array ();
$activities [ $cm -> id ] = $coursenode -> get ( $cm -> id , navigation_node :: TYPE_ACTIVITY );
}
2010-04-27 03:06:42 +00:00
// Finally load the cm specific navigaton information
2010-04-19 06:30:30 +00:00
$this -> load_activity ( $cm , $course , $activities [ $cm -> id ]);
2010-05-19 07:57:00 +00:00
// Check if we have an active ndoe
if ( ! $activities [ $cm -> id ] -> contains_active_node () && ! $activities [ $cm -> id ] -> search_for_active_node ()) {
// And make the activity node active.
$activities [ $cm -> id ] -> make_active ();
}
2009-08-28 08:47:31 +00:00
break ;
2010-04-19 06:30:30 +00:00
case CONTEXT_USER :
$course = $this -> page -> course ;
if ( $course -> id != SITEID ) {
// Load the course associated with the user into the navigation
$coursenode = $this -> load_course ( $course );
$this -> add_course_essentials ( $coursenode , $course );
$sections = $this -> load_course_sections ( $course , $coursenode );
2009-12-23 01:22:48 +00:00
}
2009-08-28 08:47:31 +00:00
break ;
}
2009-12-23 01:22:48 +00:00
2010-05-14 06:41:44 +00:00
$limit = 20 ;
if ( ! empty ( $CFG -> navcourselimit )) {
$limit = $CFG -> navcourselimit ;
}
if ( $showcategories ) {
$categories = $this -> find_all_of_type ( self :: TYPE_CATEGORY );
foreach ( $categories as & $category ) {
if ( $category -> children -> count () >= $limit ) {
$url = new moodle_url ( '/course/category.php' , array ( 'id' => $category -> key ));
$category -> add ( get_string ( 'viewallcourses' ), $url , self :: TYPE_SETTING );
}
}
} else if ( $this -> rootnodes [ 'courses' ] -> children -> count () >= $limit ) {
$this -> rootnodes [ 'courses' ] -> add ( get_string ( 'viewallcoursescategories' ), new moodle_url ( '/course/index.php' ), self :: TYPE_SETTING );
}
2010-04-19 06:30:30 +00:00
// Load for the current user
$this -> load_for_user ();
2010-05-18 02:03:13 +00:00
if ( $this -> page -> context -> contextlevel >= CONTEXT_COURSE && $this -> page -> context -> instanceid != SITEID ) {
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 ) {
if ( $user -> id !== $USER -> id ) {
$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.
foreach ( get_list_of_plugins ( 'local' ) as $plugin ) {
if ( ! file_exists ( $CFG -> dirroot . '/local/' . $plugin . '/lib.php' )) {
continue ;
}
require_once ( $CFG -> dirroot . '/local/' . $plugin . '/lib.php' );
$function = $plugin . '_extends_navigation' ;
if ( function_exists ( $function )) {
$function ( $this );
}
}
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
// in {@link http://docs.moodle.org/en/Development:Navigation_2.0_structure}
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
$this -> initialised = true ;
return true ;
}
/**
2010-04-19 06:30:30 +00:00
* Checks the course format to see whether it wants the navigation to load
* additional information for the course .
*
* This function utilises a callback that can exist within the course format lib . php file
* The callback should be a function called :
* callback_ { formatname } _display_content ()
* It doesn ' t get any arguments and should return true if additional content is
* desired . If the callback doesn ' t exist we assume additional content is wanted .
*
* @ param string $format The course format
* @ return bool
*/
protected function format_display_course_content ( $format ) {
global $CFG ;
$formatlib = $CFG -> dirroot . '/course/format/' . $format . '/lib.php' ;
if ( file_exists ( $formatlib )) {
require_once ( $formatlib );
$displayfunc = 'callback_' . $format . '_display_content' ;
if ( function_exists ( $displayfunc ) && ! $displayfunc ()) {
return $displayfunc ();
}
}
return true ;
}
/**
* Loads of the the courses in Moodle into the navigation .
*
2010-05-13 09:57:43 +00:00
* @ param string | array $categoryids Either a string or array of category ids to load courses for
2010-04-19 06:30:30 +00:00
* @ return array An array of navigation_node
*/
2010-05-13 09:57:43 +00:00
protected function load_all_courses ( $categoryids = null ) {
global $CFG , $DB , $USER ;
if ( $categoryids !== null ) {
if ( is_array ( $categoryids )) {
list ( $select , $params ) = $DB -> get_in_or_equal ( $categoryids );
} else {
$select = '= ?' ;
$params = array ( $categoryids );
}
array_unshift ( $params , SITEID );
$select = ' AND c.category ' . $select ;
} else {
$params = array ( SITEID );
$select = '' ;
}
2010-04-19 06:30:30 +00: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,cat.path AS categorypath $ccselect
FROM { course } c
$ccjoin
LEFT JOIN { course_categories } cat ON cat . id = c . category
2010-05-13 09:57:43 +00:00
WHERE c . id <> ? $select
2010-04-19 06:30:30 +00:00
ORDER BY c . sortorder ASC " ;
2010-05-13 09:57:43 +00:00
$limit = 20 ;
if ( ! empty ( $CFG -> navcourselimit )) {
$limit = $CFG -> navcourselimit ;
}
$courses = $DB -> get_records_sql ( $sql , $params , 0 , $limit );
2010-04-19 06:30:30 +00:00
$coursenodes = array ();
foreach ( $courses as $course ) {
context_instance_preload ( $course );
$coursenodes [ $course -> id ] = $this -> add_course ( $course );
}
return $coursenodes ;
}
2010-05-13 09:57:43 +00:00
/**
* Loads all categories ( top level or if an id is specified for that category )
*
* @ param int $categoryid
* @ return void
*/
protected function load_all_categories ( $categoryid = null ) {
global $DB ;
if ( $categoryid == null ) {
$categories = $DB -> get_records ( 'course_categories' , array ( 'parent' => '0' ), 'sortorder' );
} else {
$category = $DB -> get_record ( 'course_categories' , array ( 'id' => $categoryid ), '*' , MUST_EXIST );
$wantedids = explode ( '/' , trim ( $category -> path , '/' ));
list ( $select , $params ) = $DB -> get_in_or_equal ( $wantedids );
$select = 'id ' . $select . ' OR parent ' . $select ;
$params = array_merge ( $params , $params );
$categories = $DB -> get_records_select ( 'course_categories' , $select , $params , 'sortorder' );
}
$structured = array ();
$categoriestoload = array ();
foreach ( $categories as $category ) {
if ( $category -> parent == '0' ) {
$structured [ $category -> id ] = array ( 'category' => $category , 'children' => array ());
} else {
if ( $category -> parent == $categoryid ) {
$categoriestoload [] = $category -> id ;
}
$parents = array ();
$id = $category -> parent ;
while ( $id != '0' ) {
$parents [] = $id ;
if ( ! array_key_exists ( $id , $categories )) {
$categories [ $id ] = $DB -> get_record ( 'course_categories' , array ( 'id' => $id ), '*' , MUST_EXIST );
}
$id = $categories [ $id ] -> parent ;
}
$parents = array_reverse ( $parents );
$parentref = & $structured [ array_shift ( $parents )];
foreach ( $parents as $parent ) {
if ( ! array_key_exists ( $parent , $parentref [ 'children' ])) {
$parentref [ 'children' ][ $parent ] = array ( 'category' => $categories [ $parent ], 'children' => array ());
}
$parentref = & $parentref [ 'children' ][ $parent ];
}
if ( ! array_key_exists ( $category -> id , $parentref [ 'children' ])) {
$parentref [ 'children' ][ $category -> id ] = array ( 'category' => $category , 'children' => array ());
}
}
}
foreach ( $structured as $category ) {
$this -> add_category ( $category , $this -> rootnodes [ 'courses' ]);
}
if ( $categoryid !== null && count ( $wantedids )) {
foreach ( $wantedids as $catid ) {
$this -> load_all_courses ( $catid );
}
}
}
/**
* Adds a structured category to the navigation in the correct order / place
*
* @ param object $cat
* @ param navigation_node $parent
*/
protected function add_category ( $cat , navigation_node $parent ) {
$category = $parent -> get ( $cat [ 'category' ] -> id , navigation_node :: TYPE_CATEGORY );
if ( ! $category ) {
$category = $cat [ 'category' ];
$url = new moodle_url ( '/course/category.php' , array ( 'id' => $category -> id ));
$category = $parent -> add ( $category -> name , null , self :: TYPE_CATEGORY , $category -> name , $category -> id );
}
foreach ( $cat [ 'children' ] as $child ) {
$this -> add_category ( $child , $category );
}
}
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 ) {
if ( $course -> id == SITEID ) {
$coursenode = $this -> rootnodes [ 'site' ];
} else if ( array_key_exists ( $course -> id , $this -> mycourses )) {
if ( ! isset ( $this -> mycourses [ $course -> id ] -> coursenode )) {
$this -> mycourses [ $course -> id ] -> coursenode = $this -> add_course ( $course );
}
$coursenode = $this -> mycourses [ $course -> id ] -> coursenode ;
} else {
$coursenode = $this -> add_course ( $course );
}
return $coursenode ;
}
/**
* Loads all of the courses section into the navigation .
*
* This function utilisies a callback that can be implemented within the course
* formats lib . php file to customise the navigation that is generated at this
* point for the course .
*
* By default ( if not defined ) the method { @ see load_generic_course_sections } is
* called instead .
*
* @ param stdClass $course Database record for the course
* @ param navigation_node $coursenode The course node within the navigation
* @ return array Array of navigation nodes for the section with key = section id
*/
protected function load_course_sections ( stdClass $course , navigation_node $coursenode ) {
global $CFG ;
$structurefile = $CFG -> dirroot . '/course/format/' . $course -> format . '/lib.php' ;
$structurefunc = 'callback_' . $course -> format . '_load_content' ;
if ( function_exists ( $structurefunc )) {
return $structurefunc ( $this , $course , $coursenode );
} else if ( file_exists ( $structurefile )) {
require_once $structurefile ;
if ( function_exists ( $structurefunc )) {
return $structurefunc ( $this , $course , $coursenode );
} else {
2010-04-23 07:17:21 +00:00
return $this -> load_generic_course_sections ( $course , $coursenode );
2010-04-19 06:30:30 +00:00
}
} else {
2010-04-23 07:17:21 +00:00
return $this -> load_generic_course_sections ( $course , $coursenode );
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
* @ param string $name The string that identifies each section . e . g Topic , or Week
* @ param string $activeparam The url used to identify the active section
* @ return array An array of course section nodes
*/
2010-04-23 07:17:21 +00:00
public function load_generic_course_sections ( stdClass $course , navigation_node $coursenode , $courseformat = 'unknown' ) {
global $DB , $USER ;
2010-04-19 06:30:30 +00:00
$modinfo = get_fast_modinfo ( $course );
$sections = array_slice ( get_all_sections ( $course -> id ), 0 , $course -> numsections + 1 , true );
$viewhiddensections = has_capability ( 'moodle/course:viewhiddensections' , $this -> page -> context );
2010-04-23 07:17:21 +00:00
if ( isloggedin () && ! isguestuser ()) {
$activesection = $DB -> get_field ( " course_display " , " display " , array ( " userid " => $USER -> id , " course " => $course -> id ));
} else {
$activesection = null ;
}
$namingfunction = 'callback_' . $courseformat . '_get_section_name' ;
$namingfunctionexists = ( function_exists ( $namingfunction ));
$activeparamfunction = 'callback_' . $courseformat . '_request_key' ;
if ( function_exists ( $activeparamfunction )) {
$activeparam = $activeparamfunction ();
} else {
$activeparam = 'section' ;
2010-04-22 01:26:45 +00:00
}
2010-04-23 07:17:21 +00:00
2010-04-19 06:30:30 +00:00
foreach ( $sections as & $section ) {
if ( $course -> id == SITEID ) {
$this -> load_section_activities ( $coursenode , $section -> section , $modinfo );
} else {
if (( ! $viewhiddensections && ! $section -> visible ) || ( ! $this -> showemptysections && ! array_key_exists ( $section -> section , $modinfo -> sections ))) {
continue ;
}
2010-04-23 07:17:21 +00:00
if ( $namingfunctionexists ) {
$sectionname = $namingfunction ( $course , $section , $sections );
2010-04-19 06:30:30 +00:00
} else {
2010-04-23 07:17:21 +00:00
$sectionname = get_string ( 'section' ) . ' ' . $section -> section ;
2010-04-19 06:30:30 +00:00
}
$url = new moodle_url ( '/course/view.php' , array ( 'id' => $course -> id , $activeparam => $section -> section ));
$sectionnode = $coursenode -> add ( $sectionname , $url , navigation_node :: TYPE_SECTION , null , $section -> id );
$sectionnode -> nodetype = navigation_node :: NODETYPE_BRANCH ;
$sectionnode -> hidden = ( ! $section -> visible );
2010-04-27 03:06:42 +00:00
if ( $this -> page -> context -> contextlevel != CONTEXT_MODULE && ( $sectionnode -> isactive || ( $activesection != null && $section -> section == $activesection ))) {
2010-04-23 07:17:21 +00:00
$sectionnode -> force_open ();
2010-04-19 06:30:30 +00:00
$this -> load_section_activities ( $sectionnode , $section -> section , $modinfo );
}
$section -> sectionnode = $sectionnode ;
}
}
return $sections ;
}
/**
* Loads all of the activities for a section into the navigation structure .
*
* @ param navigation_node $sectionnode
* @ param int $sectionnumber
* @ param stdClass $modinfo Object returned from { @ see get_fast_modinfo ()}
* @ return array Array of activity nodes
*/
protected function load_section_activities ( navigation_node $sectionnode , $sectionnumber , $modinfo ) {
if ( ! array_key_exists ( $sectionnumber , $modinfo -> sections )) {
return true ;
}
$viewhiddenactivities = has_capability ( 'moodle/course:viewhiddenactivities' , $this -> page -> context );
$activities = array ();
foreach ( $modinfo -> sections [ $sectionnumber ] as $cmid ) {
$cm = $modinfo -> cms [ $cmid ];
if ( ! $viewhiddenactivities && ! $cm -> visible ) {
continue ;
}
if ( $cm -> icon ) {
$icon = new pix_icon ( $cm -> icon , '' , $cm -> iconcomponent );
} else {
$icon = new pix_icon ( 'icon' , '' , $cm -> modname );
}
$url = new moodle_url ( '/mod/' . $cm -> modname . '/view.php' , array ( 'id' => $cm -> id ));
$activitynode = $sectionnode -> add ( $cm -> name , $url , navigation_node :: TYPE_ACTIVITY , $cm -> name , $cm -> id , $icon );
$activitynode -> title ( get_string ( 'modulename' , $cm -> modname ));
$activitynode -> hidden = ( ! $cm -> visible );
if ( $this -> module_extends_navigation ( $cm -> modname )) {
2010-04-21 09:40:25 +00:00
$activitynode -> nodetype = navigation_node :: NODETYPE_BRANCH ;
2010-04-19 06:30:30 +00:00
}
$activities [ $cmid ] = $activitynode ;
}
return $activities ;
}
/**
* 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 :
* * { @ see forum_extend_navigation ()}
* * { @ see workshop_extend_navigation ()}
*
* @ param stdClass $cm
* @ param stdClass $course
* @ param navigation_node $activity
* @ return bool
*/
protected function load_activity ( stdClass $cm , stdClass $course , navigation_node $activity ) {
global $CFG , $DB ;
$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 );
return true ;
}
}
$activity -> nodetype = navigation_node :: NODETYPE_LEAF ;
return false ;
}
/**
* Loads user specific information into the navigation in the appopriate place .
*
* If no user is provided the current user is assumed .
*
* @ param stdClass $user
* @ 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 ) {
2010-04-19 06:30:30 +00:00
global $DB , $CFG , $USER ;
2010-03-31 07:41:31 +00:00
2009-12-23 01:22:48 +00:00
$iscurrentuser = false ;
if ( $user === null ) {
// We can't require login here but if the user isn't logged in we don't
// want to show anything
if ( ! isloggedin ()) {
return false ;
}
$user = $USER ;
$iscurrentuser = true ;
} else if ( ! is_object ( $user )) {
// If the user is not an object then get them from the database
$user = $DB -> get_record ( 'user' , array ( 'id' => ( int ) $user ), '*' , MUST_EXIST );
}
2010-02-18 05:57:20 +00:00
$usercontext = get_context_instance ( CONTEXT_USER , $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 );
2010-05-17 05:38:59 +00:00
if ( $course -> id !== SITEID && ( ! $iscurrentuser || $forceforcontext )) {
2010-04-19 06:30:30 +00:00
if ( array_key_exists ( $course -> id , $this -> mycourses )) {
$coursenode = $this -> mycourses [ $course -> id ] -> coursenode ;
} else {
$coursenode = $this -> rootnodes [ 'courses' ] -> find ( $course -> id , navigation_node :: TYPE_COURSE );
if ( ! $coursenode ) {
$coursenode = $this -> load_course ( $course );
}
}
2009-12-23 01:22:48 +00:00
$baseargs [ 'course' ] = $course -> id ;
2010-04-19 06:30:30 +00:00
$coursecontext = get_context_instance ( CONTEXT_COURSE , $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
2010-02-18 05:57:20 +00:00
$coursecontext = get_context_instance ( CONTEXT_SYSTEM );
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' ];
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 );
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' ];
$usersnode -> action = new moodle_url ( '/user/index.php' , array ( 'id' => $course -> id ));
2009-12-23 01:22:48 +00:00
}
// Add a branch for the current user
$usernode = $usersnode -> add ( fullname ( $user , true ));
2010-04-19 06:30:30 +00:00
}
if ( $this -> page -> context -> contextlevel == CONTEXT_USER && $user -> id == $this -> page -> context -> instanceid ) {
$usernode -> force_open ();
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
}
// Add nodes for forum posts and discussions if the user can view either or both
2010-02-18 05:57:20 +00:00
$canviewposts = has_capability ( 'moodle/user:readuserposts' , $usercontext );
$canviewdiscussions = has_capability ( 'mod/forum:viewdiscussion' , $coursecontext );
2009-12-23 01:22:48 +00:00
if ( $canviewposts || $canviewdiscussions ) {
$forumtab = $usernode -> add ( get_string ( 'forumposts' , 'forum' ));
if ( $canviewposts ) {
2010-01-16 15:39:56 +00:00
$forumtab -> add ( get_string ( 'posts' , 'forum' ), new moodle_url ( '/mod/forum/user.php' , $baseargs ));
2009-12-23 01:22:48 +00:00
}
if ( $canviewdiscussions ) {
2010-05-04 13:04:35 +00:00
$forumtab -> add ( get_string ( 'discussions' , 'forum' ), new moodle_url ( '/mod/forum/user.php' , array_merge ( $baseargs , array ( 'mode' => 'discussions' , 'course' => $course -> id ))));
2009-12-23 01:22:48 +00:00
}
}
2010-04-23 04:05:16 +00:00
// Add blog nodes
if ( ! empty ( $CFG -> bloglevel )) {
require_once ( $CFG -> dirroot . '/blog/lib.php' );
// Get all options for the user
$options = blog_get_options_for_user ( $user );
if ( count ( $options ) > 0 ) {
$blogs = $usernode -> add ( get_string ( 'blogs' , 'blog' ), null , navigation_node :: TYPE_CONTAINER );
foreach ( $options as $option ) {
$blogs -> add ( $option [ 'string' ], $option [ 'link' ]);
}
}
}
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
}
// Add a reports tab and then add reports the the user has permission to see.
2010-02-18 05:57:20 +00:00
$anyreport = has_capability ( 'moodle/user:viewuseractivitiesreport' , $usercontext );
2009-12-23 01:22:48 +00:00
$viewreports = ( $anyreport || ( $course -> showreports && $iscurrentuser ));
2010-05-04 13:04:35 +00:00
if ( $viewreports ) {
$reporttab = $usernode -> add ( get_string ( 'activityreports' ));
$reportargs = array ( 'user' => $user -> id );
if ( ! empty ( $course -> id )) {
$reportargs [ 'id' ] = $course -> id ;
} else {
$reportargs [ 'id' ] = SITEID ;
}
if ( $viewreports || has_capability ( 'coursereport/outline:view' , $coursecontext )) {
$reporttab -> add ( get_string ( 'outlinereport' ), new moodle_url ( '/course/user.php' , array_merge ( $reportargs , array ( 'mode' => 'outline' ))));
$reporttab -> add ( get_string ( 'completereport' ), new moodle_url ( '/course/user.php' , array_merge ( $reportargs , array ( 'mode' => 'complete' ))));
}
2010-03-31 07:41:31 +00:00
2010-05-04 13:04:35 +00:00
if ( $viewreports || has_capability ( 'coursereport/log:viewtoday' , $coursecontext )) {
$reporttab -> add ( get_string ( 'todaylogs' ), new moodle_url ( '/course/user.php' , array_merge ( $reportargs , array ( 'mode' => 'todaylogs' ))));
}
2009-12-23 01:22:48 +00:00
2010-05-04 13:04:35 +00:00
if ( $viewreports || has_capability ( 'coursereport/log:view' , $coursecontext )) {
$reporttab -> add ( get_string ( 'alllogs' ), new moodle_url ( '/course/user.php' , array_merge ( $reportargs , array ( 'mode' => 'alllogs' ))));
}
2009-12-23 01:22:48 +00:00
2010-05-04 13:04:35 +00:00
if ( ! empty ( $CFG -> enablestats )) {
if ( $viewreports || has_capability ( 'coursereport/stats:view' , $coursecontext )) {
$reporttab -> add ( get_string ( 'stats' ), new moodle_url ( '/course/user.php' , array_merge ( $reportargs , array ( 'mode' => 'stats' ))));
}
2009-12-23 01:22:48 +00:00
}
2010-05-04 13:04:35 +00:00
$gradeaccess = false ;
if ( has_capability ( 'moodle/grade:viewall' , $coursecontext )) {
//ok - can view all course grades
2009-12-23 01:22:48 +00:00
$gradeaccess = true ;
2010-05-04 13:04:35 +00:00
} else if ( $course -> showgrades ) {
if ( $iscurrentuser && has_capability ( 'moodle/grade:view' , $coursecontext )) {
//ok - can view own grades
$gradeaccess = true ;
} else if ( has_capability ( 'moodle/grade:viewall' , $usercontext )) {
// ok - can view grades of this user - parent most probably
$gradeaccess = true ;
} else if ( $anyreport ) {
// ok - 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_merge ( $reportargs , array ( 'mode' => 'grade' ))));
2009-12-23 01:22:48 +00:00
}
2010-05-04 13:04:35 +00:00
// Check the number of nodes in the report node... if there are none remove
// the node
if ( count ( $reporttab -> children ) === 0 ) {
$usernode -> remove_child ( $reporttab );
}
2009-12-23 01:22:48 +00:00
}
2010-05-04 13:04:35 +00:00
2009-12-23 01:22:48 +00:00
// If the user is the current user add the repositories for the current user
if ( $iscurrentuser ) {
require_once ( $CFG -> dirroot . '/repository/lib.php' );
2010-02-18 05:57:20 +00:00
$editabletypes = repository :: get_editable_types ( $usercontext );
2009-12-23 01:22:48 +00:00
if ( ! empty ( $editabletypes )) {
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
}
}
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
*
* @ param string $modname
* @ return bool
*/
protected function module_extends_navigation ( $modname ) {
global $CFG ;
if ( $this -> cache -> cached ( $modname . '_extends_navigation' )) {
return $this -> cache -> { $modname . '_extends_navigation' };
}
$file = $CFG -> dirroot . '/mod/' . $modname . '/lib.php' ;
$function = $modname . '_extend_navigation' ;
if ( function_exists ( $function )) {
$this -> cache -> { $modname . '_extends_navigation' } = true ;
return true ;
} else if ( file_exists ( $file )) {
require_once ( $file );
if ( function_exists ( $function )) {
$this -> cache -> { $modname . '_extends_navigation' } = true ;
return true ;
}
}
$this -> cache -> { $modname . '_extends_navigation' } = false ;
return false ;
}
/**
2010-04-19 06:30:30 +00:00
* Extends the navigation for the given user .
*
* @ 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-05-17 05:38:59 +00:00
$this -> page -> settingsnav -> extend_for_user ( $user -> id );
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
* @ return navigation_node
2009-08-28 08:47:31 +00:00
*/
2010-05-13 09:57:43 +00:00
public function add_course ( stdClass $course , $forcegeneric = false ) {
global $CFG ;
2010-04-19 06:30:30 +00:00
$canviewhidden = has_capability ( 'moodle/course:viewhiddencourses' , $this -> page -> context );
if ( $course -> id !== SITEID && ! $canviewhidden && ( ! $course -> visible || ! course_parent_visible ( $course ))) {
return false ;
2009-08-28 08:47:31 +00:00
}
2010-05-13 09:57:43 +00:00
$issite = ( $course -> id == SITEID );
$ismycourse = ( array_key_exists ( $course -> id , $this -> mycourses ) && ! $forcegeneric );
$displaycategories = ( ! $ismycourse && ! $issite && ! empty ( $CFG -> navshowcategories ));
if ( $issite ) {
2010-04-19 06:30:30 +00:00
$parent = $this ;
2010-05-13 09:57:43 +00:00
$url = null ;
$course -> shortname = get_string ( 'sitepages' );
} else if ( $ismycourse ) {
2010-04-19 06:30:30 +00:00
$parent = $this -> rootnodes [ 'mycourses' ];
$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 ));
2009-08-28 08:47:31 +00:00
}
2010-05-13 09:57:43 +00:00
if ( $displaycategories ) {
// We need to load the category structure for this course
$categoryfound = false ;
if ( ! empty ( $course -> categorypath )) {
$categories = explode ( '/' , trim ( $course -> categorypath , '/' ));
$category = $parent ;
while ( $category && $categoryid = array_shift ( $categories )) {
$category = $category -> get ( $categoryid , self :: TYPE_CATEGORY );
}
if ( $category instanceof navigation_node ) {
$parent = $category ;
$categoryfound = true ;
}
if ( ! $categoryfound && $forcegeneric ) {
$this -> load_all_categories ( $course -> category );
if ( $category = $parent -> find ( $course -> category , self :: TYPE_CATEGORY )) {
$parent = $category ;
$categoryfound = true ;
}
}
} else if ( ! empty ( $course -> category )) {
$this -> load_all_categories ( $course -> category );
if ( $category = $parent -> find ( $course -> category , self :: TYPE_CATEGORY )) {
$parent = $category ;
$categoryfound = true ;
}
if ( ! $categoryfound && ! $forcegeneric ) {
$this -> load_all_categories ( $course -> category );
if ( $category = $parent -> find ( $course -> category , self :: TYPE_CATEGORY )) {
$parent = $category ;
$categoryfound = true ;
}
}
}
}
// We found the course... we can return it now :)
if ( $coursenode = $parent -> get ( $course -> id , self :: TYPE_COURSE )) {
return $coursenode ;
}
2010-05-03 08:40:42 +00:00
$coursenode = $parent -> add ( $course -> shortname , $url , self :: TYPE_COURSE , $course -> shortname , $course -> id );
2010-04-19 06:30:30 +00:00
$coursenode -> nodetype = self :: NODETYPE_BRANCH ;
$coursenode -> hidden = ( ! $course -> visible );
2010-05-13 09:57:43 +00:00
$coursenode -> title ( $course -> fullname );
2010-04-19 06:30:30 +00:00
$this -> addedcourses [ $course -> id ] = & $coursenode ;
2010-05-13 09:57:43 +00:00
if ( $ismycourse && ! empty ( $CFG -> navshowallcourses )) {
// We need to add this course to the general courses node as well as the
// my courses node, rerun the function with the kill param
$genericcourse = $this -> add_course ( $course , true );
if ( $genericcourse -> isactive ) {
$genericcourse -> make_inactive ();
$genericcourse -> collapse = true ;
if ( $genericcourse -> parent && $genericcourse -> parent -> type == self :: TYPE_CATEGORY ) {
$parent = $genericcourse -> parent ;
while ( $parent && $parent -> type == self :: TYPE_CATEGORY ) {
$parent -> collapse = true ;
$parent = $parent -> parent ;
}
}
}
}
2010-04-19 06:30:30 +00:00
return $coursenode ;
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
2009-08-28 08:47:31 +00:00
* @ return bool
*/
2010-04-19 06:30:30 +00:00
public function add_course_essentials ( navigation_node $coursenode , stdClass $course ) {
global $CFG ;
2009-08-28 08:47:31 +00:00
2010-05-13 09:57:43 +00:00
if ( $course -> id == SITEID ) {
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
}
2010-04-19 06:30:30 +00:00
if ( $coursenode == false || $coursenode -> get ( 'participants' , navigation_node :: TYPE_CONTAINER )) {
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 )) {
require_once ( $CFG -> dirroot . '/blog/lib.php' );
$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 );
if ( $course -> id == SITEID ) {
$filterselect = '' ;
} else if ( $course -> id && ! $currentgroup ) {
$filterselect = $course -> id ;
} else {
$filterselect = $currentgroup ;
}
$filterselect = clean_param ( $filterselect , PARAM_INT );
if ( $CFG -> bloglevel >= 3 ) {
$blogsurls = new moodle_url ( '/blog/index.php' , array ( 'courseid' => $filterselect ));
$participants -> add ( get_string ( 'blogs' , 'blog' ), $blogsurls -> out ());
}
if ( ! empty ( $CFG -> enablenotes ) && ( has_capability ( 'moodle/notes:manage' , $this -> page -> context ) || has_capability ( 'moodle/notes:view' , $this -> page -> context ))) {
$participants -> add ( get_string ( 'notes' , 'notes' ), new moodle_url ( '/notes/index.php' , array ( 'filtertype' => 'course' , 'filterselect' => $filterselect )));
}
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' );
}
// View course reports
if ( has_capability ( 'moodle/site:viewreports' , $this -> page -> context )) { // basic capability for listing of reports
$reportnav = $coursenode -> add ( get_string ( 'reports' ), new moodle_url ( '/course/report.php' , array ( 'id' => $course -> id )), 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 , $this -> page -> context );
2009-08-28 08:47:31 +00:00
}
}
}
}
return true ;
}
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-04-19 06:30:30 +00:00
if ( $coursenode == false || $coursenode -> get ( 'participants' , navigation_node :: TYPE_CUSTOM )) {
return true ;
2009-12-23 01:22:48 +00:00
}
2010-04-19 06:30:30 +00:00
//Participants
if ( has_capability ( 'moodle/course:viewparticipants' , $this -> page -> context )) {
$coursenode -> add ( get_string ( 'participants' ), new moodle_url ( '/user/index.php?id=' . $course -> id ), self :: TYPE_CUSTOM , get_string ( 'participants' ), 'participants' );
}
$currentgroup = groups_get_course_group ( $course , true );
if ( $course -> id == SITEID ) {
$filterselect = '' ;
} else if ( $course -> id && ! $currentgroup ) {
$filterselect = $course -> id ;
2009-08-28 08:47:31 +00:00
} else {
2010-04-19 06:30:30 +00:00
$filterselect = $currentgroup ;
2009-08-28 08:47:31 +00:00
}
2010-04-19 06:30:30 +00:00
$filterselect = clean_param ( $filterselect , PARAM_INT );
2010-05-01 14:33:07 +00:00
// Blogs
if ( has_capability ( 'moodle/blog:view' , $this -> page -> context )) {
require_once ( $CFG -> dirroot . '/blog/lib.php' );
if ( blog_is_enabled_for_user ()) {
$blogsurls = new moodle_url ( '/blog/index.php' , array ( 'courseid' => $filterselect ));
$coursenode -> add ( get_string ( 'blogs' , 'blog' ), $blogsurls -> out ());
}
2009-08-28 08:47:31 +00:00
}
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
2010-04-19 06:30:30 +00:00
// View course reports
if ( has_capability ( 'moodle/site:viewreports' , $this -> page -> context )) { // basic capability for listing of reports
$reportnav = $coursenode -> add ( get_string ( 'reports' ), new moodle_url ( '/course/report.php' , array ( 'id' => $course -> id )), 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 , $this -> page -> context );
}
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
public function set_expansion_limit ( $type ) {
$nodes = $this -> find_all_of_type ( $type );
foreach ( $nodes as & $node ) {
foreach ( $node -> children as & $child ) {
$child -> display = false ;
}
}
return true ;
}
2009-08-28 08:47:31 +00:00
}
/**
* The limited global navigation class used for the AJAX extension of the global
* navigation class .
*
* 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 .
*
* @ package moodlecore
2009-10-19 03:29:48 +00:00
* @ subpackage 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
/** @var array */
protected $expandable = array ();
2009-08-28 08:47:31 +00:00
/**
2010-04-19 06:30:30 +00:00
* Constructs the navigation for use in AJAX request
*/
2010-05-13 09:57:43 +00:00
public function __construct ( $page ) {
2010-04-19 06:30:30 +00:00
global $SITE ;
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 ();
$this -> rootnodes = array ();
2010-05-20 06:01:00 +00:00
$this -> rootnodes [ 'site' ] = $this -> add_course ( $SITE );
2010-04-19 06:30:30 +00:00
$this -> rootnodes [ 'courses' ] = $this -> add ( get_string ( 'courses' ), null , self :: TYPE_ROOTNODE , null , 'courses' );
}
/**
* Initialise the navigation given the type and id for the branch to expand .
2009-08-28 08:47:31 +00:00
*
2010-04-19 06:30:30 +00:00
* @ param int $branchtype One of navigation_node :: TYPE_ *
* @ param int $id
* @ return array The expandable nodes
2009-08-28 08:47:31 +00:00
*/
2010-02-18 05:57:20 +00:00
public function initialise ( $branchtype , $id ) {
2010-05-13 09:57:43 +00:00
global $CFG , $DB , $PAGE ;
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-02-18 05:57:20 +00:00
// Branchtype will be one of navigation_node::TYPE_*
switch ( $branchtype ) {
2010-05-13 09:57:43 +00:00
case self :: TYPE_CATEGORY :
$this -> load_all_categories ( $id );
$limit = 20 ;
if ( ! empty ( $CFG -> navcourselimit )) {
$limit = ( int ) $CFG -> navcourselimit ;
}
$courses = $DB -> get_records ( 'course' , array ( 'category' => $id ), 'sortorder' , '*' , 0 , $limit );
foreach ( $courses as $course ) {
$this -> add_course ( $course );
}
break ;
2010-02-18 05:57:20 +00:00
case self :: TYPE_COURSE :
$course = $DB -> get_record ( 'course' , array ( 'id' => $id ), '*' , MUST_EXIST );
require_course_login ( $course );
2010-04-19 06:30:30 +00:00
$this -> page = $PAGE ;
2010-05-17 05:38:59 +00:00
$this -> page -> set_context ( get_context_instance ( CONTEXT_COURSE , $course -> id ));
2010-04-19 06:30:30 +00:00
$coursenode = $this -> add_course ( $course );
$this -> add_course_essentials ( $coursenode , $course );
if ( $this -> format_display_course_content ( $course -> format )) {
$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 = ? ' ;
$course = $DB -> get_record_sql ( $sql , array ( $id ), MUST_EXIST );
require_course_login ( $course );
2010-04-19 06:30:30 +00:00
$this -> page = $PAGE ;
2010-05-17 05:38:59 +00:00
$this -> page -> set_context ( get_context_instance ( CONTEXT_COURSE , $course -> id ));
2010-04-19 06:30:30 +00:00
$coursenode = $this -> add_course ( $course );
$this -> add_course_essentials ( $coursenode , $course );
$sections = $this -> load_course_sections ( $course , $coursenode );
$this -> load_section_activities ( $sections [ $course -> sectionnumber ] -> sectionnode , $course -> sectionnumber , get_fast_modinfo ( $course ));
2009-08-28 08:47:31 +00:00
break ;
2010-02-18 05:57:20 +00:00
case self :: TYPE_ACTIVITY :
$cm = get_coursemodule_from_id ( false , $id , 0 , false , MUST_EXIST );
$course = $DB -> get_record ( 'course' , array ( 'id' => $cm -> course ), '*' , MUST_EXIST );
require_course_login ( $course , true , $cm );
2010-04-19 06:30:30 +00:00
$this -> page = $PAGE ;
2010-05-17 05:38:59 +00:00
$this -> page -> set_context ( get_context_instance ( CONTEXT_MODULE , $cm -> id ));
2010-04-19 06:30:30 +00:00
$coursenode = $this -> load_course ( $course );
$sections = $this -> load_course_sections ( $course , $coursenode );
foreach ( $sections as $section ) {
if ( $section -> id == $cm -> section ) {
$cm -> sectionnumber = $section -> section ;
break ;
}
}
2010-05-20 06:01:00 +00:00
if ( $course -> id == SITEID ) {
$modulenode = $this -> load_activity ( $cm , $course , $coursenode -> find ( $cm -> id , self :: TYPE_ACTIVITY ));
} else {
$activities = $this -> load_section_activities ( $sections [ $cm -> sectionnumber ] -> sectionnode , $cm -> sectionnumber , get_fast_modinfo ( $course ));
$modulenode = $this -> load_activity ( $cm , $course , $activities [ $cm -> id ]);
}
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-02-18 05:57:20 +00:00
$this -> find_expandable ( $this -> 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
*
* @ package moodlecore
2009-10-19 03:29:48 +00:00
* @ subpackage 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 {
/** @var bool */
protected $initialised = false ;
/** @var mixed */
protected $keys = array ();
/** @var null|string */
protected $content = null ;
2010-04-19 06:30:30 +00:00
/** @var moodle_page object */
2009-08-28 08:47:31 +00:00
protected $page ;
/** @var bool */
2009-09-08 08:43:44 +00:00
protected $ignoreactive = false ;
/** @var bool */
2009-08-28 08:47:31 +00:00
protected $duringinstall = false ;
2009-12-23 01:22:48 +00:00
/** @var bool */
protected $hasitems = false ;
2010-04-19 06:30:30 +00:00
/** @var array */
protected $items ;
/** @var array */
public $children = array ();
2010-05-05 03:27:22 +00:00
/** @var bool */
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
}
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 .
*
* @ return array
2009-08-28 08:47:31 +00:00
*/
2010-04-19 06:30:30 +00:00
public function get_items () {
$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-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 ;
}
$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 ;
}
$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
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
* @ param string | moodle_url $action
2009-09-04 08:43:49 +00:00
* @ param int $type
* @ param string | int $key
* @ param string $shorttext
2009-08-28 08:47:31 +00:00
* @ param string $icon
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 );
}
// 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 .
*
* @ package moodlecore
2009-10-19 03:29:48 +00:00
* @ subpackage 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 {
/** @var stdClass */
protected $context ;
2010-04-19 06:30:30 +00:00
/** @var navigation_cache */
2009-08-28 08:47:31 +00:00
protected $cache ;
2010-04-19 06:30:30 +00:00
/** @var moodle_page */
2009-08-28 08:47:31 +00:00
protected $page ;
2010-04-19 06:30:30 +00:00
/** @var string */
2010-02-22 07:57:35 +00:00
protected $adminsection ;
2010-05-13 09:57:43 +00:00
/** @var bool */
protected $initialised = false ;
2010-05-17 05:38:59 +00:00
/** @var array */
protected $userstoextendfor = array ();
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-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 () {
2010-03-22 03:04:00 +00:00
global $DB ;
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 ();
$context = $DB -> get_record_sql ( 'SELECT ctx.* FROM {block_instances} bi LEFT JOIN {context} ctx ON ctx.id=bi.parentcontextid WHERE bi.id=?' , array ( $context -> instanceid ));
}
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 :
2010-03-22 03:04:00 +00:00
if ( $this -> page -> course -> id != SITEID ) {
$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 :
2010-03-22 03:04:00 +00:00
if ( $this -> page -> course -> id != SITEID ) {
$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 );
$admin = $this -> load_administration_settings ();
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
}
// Make sure the first child doesnt have proceed with hr set to true
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
*
* @ param string $text
2009-09-04 03:12:01 +00:00
* @ param sting | moodle_url $url
2009-08-28 08:47:31 +00:00
* @ param string $shorttext
* @ param string | int $key
* @ param int $type
* @ param string $icon
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 , $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
*
* @ param string $text
* @ param sting | moodle_url $url
* @ param string $shorttext
* @ param string | int $key
* @ param int $type
* @ param string $icon
2010-04-19 06:30:30 +00:00
* @ return navigation_node
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 ) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/admin/settings.php' , array ( 'section' => $adminbranch -> name ));
2009-08-28 08:47:31 +00:00
} else if ( $adminbranch instanceof admin_externalpage ) {
$url = $adminbranch -> url ;
}
// 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 .
*
* The array of resources and activities that can be added to a course is then
* stored in the cache so that we can access it for anywhere .
* It saves us generating it all the time
*
* < code php >
* // To get resources:
* $this -> cache -> { 'course' . $courseid . 'resources' }
* // To get activities:
* $this -> cache -> { 'course' . $courseid . 'activities' }
* </ code >
*
* @ param stdClass $course The course to get modules for
*/
protected function get_course_modules ( $course ) {
global $CFG ;
$mods = $modnames = $modnamesplural = $modnamesused = array ();
// This function is included when we include course/lib.php at the top
// of this file
get_all_mods ( $course -> id , $mods , $modnames , $modnamesplural , $modnamesused );
$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 ) {
$resources [ html_entity_decode ( $type -> type )] = $type -> typestr ;
} else {
$activities [ html_entity_decode ( $type -> type )] = $type -> typestr ;
}
}
} 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 ;
}
}
}
$this -> cache -> { 'course' . $course -> id . 'resources' } = $resources ;
$this -> cache -> { 'course' . $course -> id . 'activities' } = $activities ;
}
/**
* 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 ) {
2010-03-31 07:41:31 +00:00
global $CFG , $USER , $SESSION , $OUTPUT ;
2009-08-28 08:47:31 +00:00
$course = $this -> page -> course ;
2010-03-31 07:41:31 +00:00
$coursecontext = get_context_instance ( CONTEXT_COURSE , $course -> id );
2009-08-28 08:47:31 +00:00
if ( ! $this -> cache -> cached ( 'canviewcourse' . $course -> id )) {
2010-03-31 07:41:31 +00:00
$this -> cache -> { 'canviewcourse' . $course -> id } = has_capability ( 'moodle/course:participate' , $coursecontext );
2009-08-28 08:47:31 +00:00
}
if ( $course -> id === SITEID || ! $this -> cache -> { 'canviewcourse' . $course -> id }) {
return false ;
}
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
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/course:update' , $coursecontext )) {
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-14 09:29:44 +00:00
$coursenode -> add ( $editstring , $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/edit' , '' ));
2009-08-28 08:47:31 +00:00
if ( $this -> page -> user_is_editing ()) {
// Add `add` resources|activities branches
$structurefile = $CFG -> dirroot . '/course/format/' . $course -> format . '/lib.php' ;
if ( file_exists ( $structurefile )) {
require_once ( $structurefile );
$formatstring = call_user_func ( 'callback_' . $course -> format . '_definition' );
$formatidentifier = optional_param ( call_user_func ( 'callback_' . $course -> format . '_request_key' ), 0 , PARAM_INT );
} else {
$formatstring = get_string ( 'topic' );
$formatidentifier = optional_param ( 'topic' , 0 , PARAM_INT );
}
if ( ! $this -> cache -> cached ( 'coursesections' . $course -> id )) {
$this -> cache -> { 'coursesections' . $course -> id } = get_all_sections ( $course -> id );
}
$sections = $this -> cache -> { 'coursesections' . $course -> id };
2009-11-01 11:31:16 +00:00
2010-04-19 06:30:30 +00:00
$addresource = $this -> add ( get_string ( 'addresource' ));
$addactivity = $this -> add ( get_string ( 'addactivity' ));
2009-08-28 08:47:31 +00:00
if ( $formatidentifier !== 0 ) {
2010-04-19 06:30:30 +00:00
$addresource -> force_open ();
$addactivity -> force_open ();
2009-08-28 08:47:31 +00:00
}
if ( ! $this -> cache -> cached ( 'course' . $course -> id . 'resources' )) {
2009-08-29 11:15:27 +00:00
$this -> get_course_modules ( $course );
2009-08-28 08:47:31 +00:00
}
$resources = $this -> cache -> { 'course' . $course -> id . 'resources' };
$activities = $this -> cache -> { 'course' . $course -> id . 'activities' };
2009-11-01 11:31:16 +00:00
2010-01-21 08:51:13 +00:00
$textlib = textlib_get_instance ();
2009-08-28 08:47:31 +00:00
foreach ( $sections as $section ) {
if ( $formatidentifier !== 0 && $section -> section != $formatidentifier ) {
continue ;
}
2010-01-16 15:39:56 +00:00
$sectionurl = new moodle_url ( '/course/view.php' , array ( 'id' => $course -> id , $formatstring => $section -> section ));
2009-08-28 08:47:31 +00:00
if ( $section -> section == 0 ) {
2009-09-04 08:43:49 +00:00
$sectionresources = $addresource -> add ( get_string ( 'course' ), $sectionurl , self :: TYPE_SETTING );
$sectionactivities = $addactivity -> add ( get_string ( 'course' ), $sectionurl , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
} else {
2009-09-04 08:43:49 +00:00
$sectionresources = $addresource -> add ( $formatstring . ' ' . $section -> section , $sectionurl , self :: TYPE_SETTING );
$sectionactivities = $addactivity -> add ( $formatstring . ' ' . $section -> section , $sectionurl , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
}
foreach ( $resources as $value => $resource ) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/course/mod.php' , array ( 'id' => $course -> id , 'sesskey' => sesskey (), 'section' => $section -> section ));
2009-08-28 08:47:31 +00:00
$pos = strpos ( $value , '&type=' );
if ( $pos !== false ) {
2010-01-21 08:51:13 +00:00
$url -> param ( 'add' , $textlib -> substr ( $value , 0 , $pos ));
$url -> param ( 'type' , $textlib -> substr ( $value , $pos + 6 ));
2009-08-28 08:47:31 +00:00
} else {
$url -> param ( 'add' , $value );
}
2010-04-19 06:30:30 +00:00
$sectionresources -> add ( $resource , $url , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
}
$subbranch = false ;
foreach ( $activities as $activityname => $activity ) {
if ( $activity === '--' ) {
$subbranch = false ;
continue ;
}
if ( strpos ( $activity , '--' ) === 0 ) {
2010-04-19 06:30:30 +00:00
$subbranch = $sectionresources -> add ( trim ( $activity , '-' ));
2009-08-28 08:47:31 +00:00
continue ;
}
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/course/mod.php' , array ( 'id' => $course -> id , 'sesskey' => sesskey (), 'section' => $section -> section ));
2009-08-28 08:47:31 +00:00
$pos = strpos ( $activityname , '&type=' );
if ( $pos !== false ) {
2010-01-21 08:51:13 +00:00
$url -> param ( 'add' , $textlib -> substr ( $activityname , 0 , $pos ));
$url -> param ( 'type' , $textlib -> substr ( $activityname , $pos + 6 ));
2009-08-28 08:47:31 +00:00
} else {
$url -> param ( 'add' , $activityname );
}
if ( $subbranch !== false ) {
2010-04-19 06:30:30 +00:00
$subbranch -> add ( $activity , $url , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
} else {
2010-04-19 06:30:30 +00:00
$sectionresources -> add ( $activity , $url , self :: TYPE_SETTING );
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 ));
2010-02-14 09:29:44 +00:00
$coursenode -> add ( get_string ( 'settings' ), $url , self :: TYPE_SETTING , null , null , 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 ));
$coursenode -> add ( get_string ( 'completion' , 'completion' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/settings' , '' ));
}
2009-08-28 08:47:31 +00:00
}
2009-11-01 11:31:16 +00:00
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/role:assign' , $coursecontext )) {
2010-03-22 03:04:00 +00:00
// Add assign or override roles if allowed
2010-03-31 07:41:31 +00:00
$url = new moodle_url ( '/' . $CFG -> admin . '/roles/assign.php' , array ( 'contextid' => $coursecontext -> id ));
2010-02-14 09:29:44 +00:00
$coursenode -> add ( get_string ( 'assignroles' , 'role' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/roles' , '' ));
2010-03-22 03:04:00 +00:00
// Override roles
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/role:review' , $coursecontext ) or count ( get_overridable_roles ( $coursecontext )) > 0 ) {
$url = new moodle_url ( '/' . $CFG -> admin . '/roles/permissions.php' , array ( 'contextid' => $coursecontext -> id ));
2010-05-11 06:43:49 +00:00
$coursenode -> add ( get_string ( 'permissions' , 'role' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/permissions' , '' ));
2010-03-22 03:04:00 +00:00
}
// Check role permissions
2010-03-31 07:41:31 +00:00
if ( has_any_capability ( array ( 'moodle/role:assign' , 'moodle/role:safeoverride' , 'moodle/role:override' , 'moodle/role:assign' ), $coursecontext )) {
$url = new moodle_url ( '/' . $CFG -> admin . '/roles/check.php' , array ( 'contextid' => $coursecontext -> id ));
2010-05-11 06:43:49 +00:00
$coursenode -> add ( get_string ( 'checkpermissions' , 'role' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/checkpermissions' , '' ));
2010-03-22 03:04:00 +00:00
}
// Manage filters
2010-03-31 07:41:31 +00:00
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 ));
2010-03-22 03:04:00 +00:00
$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
}
// 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
}
// Add meta course links
if ( $course -> metacourse ) {
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/course:managemetacourse' , $coursecontext )) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/course/importstudents.php' , array ( 'id' => $course -> id ));
2010-02-14 09:29:44 +00:00
$coursenode -> add ( get_string ( 'childcourses' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/course' , '' ));
2010-03-31 07:41:31 +00:00
} else if ( has_capability ( 'moodle/role:assign' , $coursecontext )) {
2010-04-19 06:30:30 +00:00
$roleassign = $coursenode -> add ( get_string ( 'childcourses' ), null , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/course' , '' ));
$roleassign -> hidden = true ;
2009-08-28 08:47:31 +00:00
}
}
// Manage groups in this course
2010-03-31 07:41:31 +00:00
if (( $course -> groupmode || ! $course -> groupmodeforce ) && has_capability ( 'moodle/course:managegroups' , $coursecontext )) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/group/index.php' , array ( 'id' => $course -> id ));
2010-05-20 07:35:44 +00:00
$coursenode -> add ( get_string ( 'groups' ), $url , self :: TYPE_SETTING , null , 'groups' , new pix_icon ( 'i/group' , '' ));
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-01-16 15:39:56 +00:00
$url = new moodle_url ( '/files/index.php' , array ( 'id' => $course -> id , 'wdir' => '/backupdata' ));
2010-05-02 14:52:23 +00:00
$url = null ; // Disabled until restore is implemented. MDL-21432
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-01-16 15:39:56 +00:00
$url = new moodle_url ( '/course/import.php' , array ( 'id' => $course -> id ));
2010-05-02 14:52:23 +00:00
$url = null ; // Disabled until restore is implemented. MDL-21432
2010-05-20 07:35:44 +00:00
$coursenode -> add ( get_string ( 'import' ), $url , self :: TYPE_SETTING , null , 'import' , new pix_icon ( 'i/restore' , '' ));
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
require_once ( $CFG -> dirroot . '/question/editlib.php' );
question_extend_settings_navigation ( $coursenode , $coursecontext ) -> trim_if_empty ();
2009-08-28 08:47:31 +00:00
// Repository Instances
require_once ( $CFG -> dirroot . '/repository/lib.php' );
2010-05-11 05:28:59 +00:00
$editabletypes = repository :: get_editable_types ( $coursecontext );
if ( has_capability ( 'moodle/course:update' , $coursecontext ) && ! empty ( $editabletypes )) {
$url = new moodle_url ( '/repository/manage_instances.php' , array ( 'contextid' => $coursecontext -> id ));
2010-02-14 09:29:44 +00:00
$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-05-22 13:10:05 +00:00
if ( $course -> legacyfiles == 2 and has_capability ( 'moodle/course:managefiles' , $coursecontext )) {
2010-05-11 05:28:59 +00:00
$url = new moodle_url ( '/files/index.php' , array ( 'contextid' => $coursecontext -> id , 'itemid' => 0 , 'filearea' => 'course_content' ));
$coursenode -> add ( get_string ( 'files' ), $url , self :: TYPE_SETTING , null , 'coursefiles' , new pix_icon ( 'i/files' , '' ));
2009-08-28 08:47:31 +00:00
}
// Authorize hooks
if ( $course -> enrol == 'authorize' || ( empty ( $course -> enrol ) && $CFG -> enrol == 'authorize' )) {
require_once ( $CFG -> dirroot . '/enrol/authorize/const.php' );
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/enrol/authorize/index.php' , array ( 'course' => $course -> id ));
2010-02-14 09:29:44 +00:00
$coursenode -> add ( get_string ( 'payments' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/payment' , '' ));
2009-08-28 08:47:31 +00:00
if ( has_capability ( 'enrol/authorize:managepayments' , $this -> page -> context )) {
$cnt = $DB -> count_records ( 'enrol_authorize' , array ( 'status' => AN_STATUS_AUTH , 'courseid' => $course -> id ));
if ( $cnt ) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/enrol/authorize/index.php' , array ( 'course' => $course -> id , 'status' => AN_STATUS_AUTH ));
2010-02-14 09:29:44 +00:00
$coursenode -> add ( get_string ( 'paymentpending' , 'moodle' , $cnt ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/payment' , '' ));
2009-08-28 08:47:31 +00:00
}
}
}
// Unenrol link
2010-03-31 07:41:31 +00:00
if ( empty ( $course -> metacourse ) && ( $course -> id !== SITEID )) {
if ( is_enrolled ( get_context_instance ( CONTEXT_COURSE , $course -> id ))) {
if ( has_capability ( 'moodle/role:unassignself' , $this -> page -> context , NULL , false ) and get_user_roles ( $this -> page -> context , $USER -> id , false )) { // Have some role
$this -> content -> items [] = '<a href="' . $CFG -> wwwroot . '/course/unenrol.php?id=' . $course -> id . '">' . get_string ( 'unenrolme' , '' , format_string ( $course -> shortname )) . '</a>' ;
$this -> content -> icons [] = '<img src="' . $OUTPUT -> pix_url ( 'i/user' ) . '" class="icon" alt="" />' ;
}
} else if ( is_viewing ( get_context_instance ( CONTEXT_COURSE , $course -> id ))) {
// inspector, manager, etc. - do not show anything
} else {
// access because otherwise they would not get into this course at all
$this -> content -> items [] = '<a href="' . $CFG -> wwwroot . '/course/enrol.php?id=' . $course -> id . '">' . get_string ( 'enrolme' , '' , format_string ( $course -> shortname )) . '</a>' ;
$this -> content -> icons [] = '<img src="' . $OUTPUT -> pix_url ( 'i/user' ) . '" class="icon" alt="" />' ;
2009-08-28 08:47:31 +00:00
}
}
// Switch roles
$roles = array ();
$assumedrole = $this -> in_alternative_role ();
if ( $assumedrole !== false ) {
$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 ) {
if ( $key == $CFG -> guestroleid || $assumedrole === ( int ) $key ) {
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
}
$returnurl = $this -> page -> url ;
$returnurl -> param ( 'sesskey' , sesskey ());
$SESSION -> returnurl = serialize ( $returnurl );
foreach ( $roles as $key => $name ) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/course/switchrole.php' , array ( 'id' => $course -> id , 'sesskey' => sesskey (), 'switchrole' => $key , 'returnurl' => '1' ));
2010-04-19 06:30:30 +00:00
$switchroles -> add ( $name , $url , self :: TYPE_SETTING , null , $key , new pix_icon ( 'i/roles' , '' ));
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 .
*
* For examples mod / forum / lib . php ::: forum_extend_settings_navigation ()
*
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-04-19 06:30:30 +00:00
$modulenode = $this -> add ( get_string ( $this -> page -> activityname . 'administration' , $this -> page -> activityname ));
$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 ()));
$modulenode -> add ( get_string ( 'settings' ), $url , navigation_node :: TYPE_SETTING );
}
// 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 ));
$modulenode -> add ( get_string ( 'localroles' , 'role' ), $url , self :: TYPE_SETTING );
}
// 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 ));
$modulenode -> 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 -> page -> cm -> context )) {
$url = new moodle_url ( '/' . $CFG -> admin . '/roles/check.php' , array ( 'contextid' => $this -> page -> cm -> context -> id ));
$modulenode -> add ( get_string ( 'checkpermissions' , 'role' ), $url , self :: TYPE_SETTING );
}
// 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 ));
$modulenode -> add ( get_string ( 'filters' , 'admin' ), $url , self :: TYPE_SETTING );
}
2010-03-31 07:41:31 +00:00
2010-05-10 09:02:09 +00:00
if ( has_capability ( 'coursereport/log:view' , get_context_instance ( CONTEXT_COURSE , $this -> page -> cm -> course ))) {
$url = new moodle_url ( '/course/report/log/index.php' , array ( 'chooselog' => '1' , 'id' => $this -> page -> cm -> course , 'modid' => $this -> page -> cm -> id ));
$modulenode -> add ( get_string ( 'logs' ), $url , self :: TYPE_SETTING );
}
2010-05-04 04:00:03 +00:00
// Add a backup link
$featuresfunc = $this -> page -> activityname . '_supports' ;
if ( $featuresfunc ( FEATURE_BACKUP_MOODLE2 ) && has_capability ( 'moodle/backup:backupactivity' , $this -> page -> cm -> context )) {
$url = new moodle_url ( '/backup/backup.php' , array ( 'id' => $this -> page -> cm -> course , 'cm' => $this -> page -> cm -> id ));
$modulenode -> add ( get_string ( 'backup' ), $url , self :: TYPE_SETTING );
}
2010-02-18 05:57:20 +00:00
$file = $CFG -> dirroot . '/mod/' . $this -> page -> activityname . '/lib.php' ;
$function = $this -> page -> activityname . '_extend_settings_navigation' ;
2009-11-01 11:31:16 +00:00
2009-08-28 08:47:31 +00:00
if ( file_exists ( $file )) {
require_once ( $file );
}
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
*/
protected function load_user_settings ( $courseid = SITEID ) {
2010-03-22 03:04:00 +00:00
global $USER , $FULLME , $CFG ;
2009-08-28 08:47:31 +00:00
if ( isguestuser () || ! isloggedin ()) {
return false ;
}
2010-05-17 05:38:59 +00:00
if ( count ( $this -> userstoextendfor ) > 0 ) {
$usernode = null ;
foreach ( $this -> userstoextendfor as $userid ) {
$node = $this -> generate_user_settings ( $courseid , $userid , '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-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
/**
* This function gets called by { @ link load_user_settings ()} and actually works out
* 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
2010-02-18 05:57:20 +00:00
if ( $courseid != SITEID ) {
if ( ! empty ( $this -> page -> course -> id ) && $this -> page -> course -> id == $courseid ) {
$course = $this -> page -> course ;
} else {
$course = $DB -> get_record ( " course " , array ( " id " => $courseid ), '*' , MUST_EXIST );
}
} else {
$course = $SITE ;
2009-08-28 08:47:31 +00:00
}
$coursecontext = get_context_instance ( CONTEXT_COURSE , $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 ;
$usercontext = get_context_instance ( CONTEXT_USER , $user -> id ); // User context
} else {
2009-12-23 01:22:48 +00:00
if ( ! $user = $DB -> get_record ( 'user' , array ( 'id' => $userid ))) {
2009-08-28 08:47:31 +00:00
return false ;
}
// Check that the user can view the profile
$usercontext = get_context_instance ( CONTEXT_USER , $user -> id ); // User context
if ( $course -> id == SITEID ) {
2010-03-31 07:41:31 +00:00
if ( $CFG -> forceloginforprofiles && !! has_coursemanager_role ( $user -> id ) && ! has_capability ( 'moodle/user:viewdetails' , $usercontext )) { // 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 {
2010-03-31 07:41:31 +00:00
if (( ! has_capability ( 'moodle/user:viewdetails' , $coursecontext ) && ! has_capability ( 'moodle/user:viewdetails' , $usercontext )) || ! has_capability ( 'moodle/course:participate' , $coursecontext , $user -> id , false )) {
2009-08-28 08:47:31 +00:00
return false ;
}
if ( groups_get_course_groupmode ( $course ) == SEPARATEGROUPS && ! has_capability ( 'moodle/site:accessallgroups' , $coursecontext )) {
// 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 ));
// Add a user setting branch
2010-05-05 06:28:47 +00:00
$usersetting = $this -> add ( get_string ( $gstitle , 'moodle' , $fullname ), null , self :: TYPE_CONTAINER , null , $gstitle );
2009-08-28 08:47:31 +00:00
$usersetting -> id = 'usersettings' ;
// 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
2010-05-04 13:04:35 +00:00
if ( $course -> id == SITEID ) {
$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 ;
}
// Add the profile edit link
if ( isloggedin () && ! isguestuser ( $user ) && ! is_mnet_remote_user ( $user )) {
2009-12-23 01:22:48 +00:00
if (( $currentuser || ! is_primary_admin ( $user -> id )) && 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 );
2009-08-28 08:47:31 +00:00
} else if (( has_capability ( 'moodle/user:editprofile' , $usercontext ) && ! is_primary_admin ( $user -> id )) || ( $currentuser && has_capability ( 'moodle/user:editownprofile' , $systemcontext ))) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/user/edit.php' , array ( 'id' => $user -> id , 'course' => $course -> id ));
2009-09-04 08:43:49 +00:00
$usersetting -> add ( get_string ( 'editmyprofile' ), $url , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
}
}
// Change password link
if ( ! empty ( $user -> auth )) {
$userauth = get_auth_plugin ( $user -> auth );
if ( $currentuser && ! session_is_loggedinas () && $userauth -> can_change_password () && ! isguestuser () && has_capability ( 'moodle/user:changeownpassword' , $systemcontext )) {
$passwordchangeurl = $userauth -> change_password_url ();
if ( ! $passwordchangeurl ) {
if ( empty ( $CFG -> loginhttps )) {
$wwwroot = $CFG -> wwwroot ;
} else {
$wwwroot = str_replace ( 'http:' , 'https:' , $CFG -> wwwroot );
}
2010-01-16 15:39:56 +00:00
$passwordchangeurl = new moodle_url ( '/login/change_password.php' );
2009-08-28 08:47:31 +00:00
} else {
$urlbits = explode ( $passwordchangeurl . '?' , 1 );
$passwordchangeurl = new moodle_url ( $urlbits [ 0 ]);
if ( count ( $urlbits ) == 2 && preg_match_all ( '#\&([^\=]*?)\=([^\&]*)#si' , '&' . $urlbits [ 1 ], $matches )) {
foreach ( $matches as $pair ) {
$fullmeurl -> param ( $pair [ 1 ], $pair [ 2 ]);
}
}
}
$passwordchangeurl -> param ( 'id' , $course -> id );
2009-09-04 08:43:49 +00: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 );
$portfolio -> add ( get_string ( 'configure' , 'portfolio' ), new moodle_url ( '/user/portfolio.php' ), self :: TYPE_SETTING );
$portfolio -> add ( get_string ( 'logs' , 'portfolio' ), new moodle_url ( '/user/portfoliologs.php' ), 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
if ( ! $currentuser ) {
require_once ( $CFG -> dirroot . '/repository/lib.php' );
$editabletypes = repository :: get_editable_types ( $usercontext );
if ( $usercontext -> contextlevel == CONTEXT_USER && ! empty ( $editabletypes )) {
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-05-04 13:04:35 +00:00
// TODO this is adding itself to the messaging settings for other people based on one's own setting
2009-12-23 01:22:48 +00:00
if ( has_capability ( 'moodle/user:editownmessageprofile' , $systemcontext )) {
2010-01-16 15:39:56 +00:00
$url = new moodle_url ( '/message/edit.php' , array ( 'id' => $user -> id , 'course' => $course -> id ));
2009-09-04 08:43:49 +00:00
$usersetting -> add ( get_string ( 'editmymessage' , 'message' ), $url , self :: TYPE_SETTING );
2009-08-28 08:47:31 +00:00
}
2010-05-20 08:04:20 +00:00
// Blogs
if ( ! empty ( $CFG -> bloglevel )) {
$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 );
if ( $CFG -> useexternalblogs && $CFG -> maxexternalblogsperuser > 0 && has_capability ( 'moodle/blog:manageexternal' , get_context_instance ( CONTEXT_SYSTEM ))) {
$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 );
}
}
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 ;
2010-04-21 02:43:02 +00:00
$categorynode = $this -> add ( print_context_name ( $this -> context ));
$categorynode -> force_open ();
2010-03-22 03:04:00 +00:00
if ( $this -> page -> user_is_editing () && has_capability ( 'moodle/category:manage' , $this -> context )) {
2010-04-21 02:43:02 +00:00
$categorynode -> add ( get_string ( 'editcategorythis' ), new moodle_url ( '/course/editcategory.php' , array ( 'id' => $this -> context -> instanceid )));
$categorynode -> add ( get_string ( 'addsubcategory' ), new moodle_url ( '/course/editcategory.php' , array ( 'parent' => $this -> context -> instanceid )));
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 ));
2010-04-21 02:43:02 +00:00
$categorynode -> add ( get_string ( 'assignroles' , 'role' ), $assignurl , self :: TYPE_SETTING );
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-04-21 02:43:02 +00:00
$categorynode -> add ( get_string ( 'permissions' , 'role' ), $url , self :: TYPE_SETTING );
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-04-21 02:43:02 +00:00
$categorynode -> add ( get_string ( 'checkpermissions' , 'role' ), $url , self :: TYPE_SETTING );
}
// 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 ));
$categorynode -> add ( get_string ( 'filters' , 'admin' ), $url , self :: TYPE_SETTING );
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
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 );
2010-03-31 07:41:31 +00:00
$coursecontext = get_context_instance ( CONTEXT_COURSE , $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
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/course:update' , $coursecontext )) {
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' , '' ));
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-02-18 05:57:20 +00:00
$frontpage -> add ( get_string ( 'settings' ), $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
//Participants
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/site:viewparticipants' , $coursecontext )) {
$url = new moodle_url ( '/user/index.php' , array ( 'contextid' => $coursecontext -> id ));
2010-02-18 05:57:20 +00:00
$frontpage -> add ( get_string ( 'participants' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/users' , '' ));
2009-09-09 04:21:20 +00:00
}
2009-08-28 08:47:31 +00:00
2010-03-22 03:04:00 +00:00
// Roles
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/role:assign' , $coursecontext )) {
2010-03-22 03:04:00 +00:00
// Add assign or override roles if allowed
2010-03-31 07:41:31 +00:00
$url = new moodle_url ( '/' . $CFG -> admin . '/roles/assign.php' , array ( 'contextid' => $coursecontext -> id ));
2010-03-22 03:04:00 +00:00
$frontpage -> add ( get_string ( 'assignroles' , 'role' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/roles' , '' ));
// Override roles
2010-03-31 07:41:31 +00:00
if ( has_capability ( 'moodle/role:review' , $coursecontext ) or count ( get_overridable_roles ( $coursecontext )) > 0 ) {
$url = new moodle_url ( '/' . $CFG -> admin . '/roles/permissions.php' , array ( 'contextid' => $coursecontext -> id ));
2010-05-11 06:43:49 +00:00
$frontpage -> add ( get_string ( 'permissions' , 'role' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/permissions' , '' ));
2010-03-22 03:04:00 +00:00
}
// Check role permissions
2010-03-31 07:41:31 +00:00
if ( has_any_capability ( array ( 'moodle/role:assign' , 'moodle/role:safeoverride' , 'moodle/role:override' , 'moodle/role:assign' ), $coursecontext )) {
$url = new moodle_url ( '/' . $CFG -> admin . '/roles/check.php' , array ( 'contextid' => $coursecontext -> id ));
2010-05-11 06:43:49 +00:00
$frontpage -> add ( get_string ( 'checkpermissions' , 'role' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/checkpermissions' , '' ));
2010-03-22 03:04:00 +00:00
}
// Manage filters
2010-03-31 07:41:31 +00:00
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 ));
2010-03-22 03:04:00 +00:00
$frontpage -> add ( get_string ( 'filters' , 'admin' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/filter' , '' ));
}
}
// 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-03-22 03:04:00 +00:00
$url = new moodle_url ( '/files/index.php' , array ( 'id' => $course -> id , 'wdir' => '/backupdata' ));
2010-05-03 09:02:26 +00:00
$url = null ; // Disabled until restore is implemented. MDL-21432
2010-03-22 03:04:00 +00:00
$frontpage -> add ( get_string ( 'restore' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/restore' , '' ));
}
// Manage questions
$questioncaps = array ( 'moodle/question:add' ,
'moodle/question:editmine' ,
'moodle/question:editall' ,
'moodle/question:viewmine' ,
'moodle/question:viewall' ,
'moodle/question:movemine' ,
'moodle/question:moveall' );
if ( has_any_capability ( $questioncaps , $this -> context )) {
$questionlink = $CFG -> wwwroot . '/question/edit.php' ;
} else if ( has_capability ( 'moodle/question:managecategory' , $this -> context )) {
$questionlink = $CFG -> wwwroot . '/question/category.php' ;
}
if ( isset ( $questionlink )) {
$url = new moodle_url ( $questionlink , array ( 'courseid' => $course -> id ));
$frontpage -> add ( get_string ( 'questions' , 'quiz' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/questions' , '' ));
}
// Manage files
if ( has_capability ( 'moodle/course:managefiles' , $this -> context )) {
$url = new moodle_url ( '/files/index.php' , array ( 'id' => $course -> id ));
$frontpage -> add ( get_string ( 'files' ), $url , self :: TYPE_SETTING , null , null , new pix_icon ( 'i/files' , '' ));
}
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
/**
* 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
*
* @ package moodlecore
2009-10-19 03:29:48 +00:00
* @ subpackage 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 {
2009-08-28 08:47:31 +00:00
/** @var array */
protected $nodetype = array ( 'node' , 'branch' );
/** @var array */
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-05-13 09:57:43 +00:00
$this -> expandable [ $node [ 'branchid' ] . ':' . $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 ) {
global $OUTPUT ;
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 ) {
$attributes [ 'title' ] = htmlentities ( $child -> title );
}
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 ();
}
$attributes [ 'hidden' ] = ( $child -> hidden );
2010-04-19 06:30:30 +00:00
$attributes [ 'haschildren' ] = ( $child -> children -> count () > 0 || $child -> type == navigation_node :: TYPE_CATEGORY );
2009-08-28 08:47:31 +00:00
if ( count ( $child -> children ) > 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
}
}
/**
* The cache class used by global navigation and settings navigation to cache bits
* and bobs that are used during their generation .
*
* 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 >
*
* @ package moodlecore
2009-10-19 03:29:48 +00:00
* @ subpackage 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 {
/** @var int */
protected $creation ;
/** @var array */
protected $session ;
/** @var string */
protected $area ;
/** @var int */
protected $timeout ;
/** @var stdClass */
protected $currentcontext ;
/** @var int */
const CACHETIME = 0 ;
/** @var int */
const CACHEUSERID = 1 ;
/** @var int */
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
*/
public function __construct ( $area , $timeout = 60 ) {
2010-02-18 05:57:20 +00:00
global $SESSION ;
2009-08-28 08:47:31 +00:00
$this -> creation = time ();
$this -> area = $area ;
if ( ! isset ( $SESSION -> navcache )) {
$SESSION -> navcache = new stdClass ;
}
if ( ! isset ( $SESSION -> navcache -> { $area })) {
$SESSION -> navcache -> { $area } = array ();
}
$this -> session = & $SESSION -> navcache -> { $area };
$this -> timeout = time () - $timeout ;
if ( rand ( 0 , 10 ) === 0 ) {
$this -> garbage_collection ();
}
}
/**
* 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 ;
$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 ;
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
*/
public function compare ( $key , $value , $serialise = true ) {
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 () {
$this -> session = array ();
}
/**
* Checks all cache entries and removes any that have expired , good ole cleanup
*/
protected function garbage_collection () {
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
* { @ link navigation_node :: destroy_volatile_caches ()} which is registered
* 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-05-14 02:55:46 +00:00
}