2009-08-10 06:22:04 +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/>.
/**
* Classes for rendering HTML output for Moodle .
*
2012-01-05 13:28:08 +13:00
* Please see { @ link http :// docs . moodle . org / en / Developement : How_Moodle_outputs_HTML }
2009-08-10 06:22:04 +00:00
* for an overview .
*
2012-01-05 13:28:08 +13:00
* Included in this file are the primary renderer classes :
* - renderer_base : The renderer outline class that all renderers
* should inherit from .
* - core_renderer : The standard HTML renderer .
* - core_renderer_cli : An adaption of the standard renderer for CLI scripts .
* - core_renderer_ajax : An adaption of the standard renderer for AJAX scripts .
* - plugin_renderer_base : A renderer class that should be extended by all
* plugin renderers .
*
2012-02-14 18:24:09 +13:00
* @ package core
2012-01-11 10:40:55 +13:00
* @ category output
2010-07-25 13:35:05 +00:00
* @ copyright 2009 Tim Hunt
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
2009-08-10 06:22:04 +00:00
*/
2010-07-25 13:35:05 +00:00
defined ( 'MOODLE_INTERNAL' ) || die ();
2009-08-10 06:22:04 +00:00
/**
* Simple base class for Moodle renderers .
*
* Tracks the xhtml_container_stack to use , which is passed in in the constructor .
*
* Also has methods to facilitate generating HTML output .
*
* @ copyright 2009 Tim Hunt
2012-01-05 13:28:08 +13:00
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
* @ since Moodle 2.0
2012-02-14 18:24:09 +13:00
* @ package core
2012-01-11 10:40:55 +13:00
* @ category output
2009-08-10 06:22:04 +00:00
*/
2009-12-16 18:00:58 +00:00
class renderer_base {
2012-01-05 13:28:08 +13:00
/**
2012-01-11 10:40:55 +13:00
* @ var xhtml_container_stack The xhtml_container_stack to use .
2012-01-05 13:28:08 +13:00
*/
2009-08-10 06:22:04 +00:00
protected $opencontainers ;
2012-01-05 13:28:08 +13:00
/**
2012-01-11 10:40:55 +13:00
* @ var moodle_page The Moodle page the renderer has been created to assist with .
2012-01-05 13:28:08 +13:00
*/
2009-08-10 06:22:04 +00:00
protected $page ;
2012-01-05 13:28:08 +13:00
/**
2012-01-11 10:40:55 +13:00
* @ var string The requested rendering target .
2012-01-05 13:28:08 +13:00
*/
2009-12-17 22:43:27 +00:00
protected $target ;
2009-08-10 06:22:04 +00:00
2015-02-22 15:24:44 +08:00
/**
* @ var Mustache_Engine $mustache The mustache template compiler
*/
private $mustache ;
/**
* Return an instance of the mustache class .
*
* @ since 2.9
* @ return Mustache_Engine
*/
protected function get_mustache () {
global $CFG ;
if ( $this -> mustache === null ) {
$themename = $this -> page -> theme -> name ;
$themerev = theme_get_revision ();
2015-05-01 16:43:21 +08:00
$cachedir = make_localcache_directory ( " mustache/ $themerev / $themename " );
$loader = new \core\output\mustache_filesystem_loader ();
2015-02-22 15:24:44 +08:00
$stringhelper = new \core\output\mustache_string_helper ();
MDL-52136 core: Add support for quoting variables in mustache helpers
This is required for when helpers include json-encoded variables as arguments.
As an example, imagine a template with content:
{{# str }} somekey, someidentifier, { "fullname": "{{ fullname }}" } {{/ str }}
If the fullname variable were to include the double-quote character (e.g.
John "Trevor" Doe) because of the way in which mustache renders content, it
would become:
{{# str }} somekey, someidentifier, { "fullname": "John "Trevor" Doe" } {{/ str }}
This results in an invalid JSON structure.
To work around this issue, the quote characters in the passed variable
must be escaped:
{{# str }} somekey, someidentifier, { "fullname": "John \"Trevor\" Doe" } {{/ str }}
Unfortunately, Mustache provides no way of doing so natively.
With this function, we can quote the text as appropriate:
{{# str }} somekey, someidentifier, { "fullname": {{# quote }}{{ fullname }}{{/ quote }} } {{/ str }}
This also handles the case where the quoted content includes the Mustache
delimeter ({{ or }}).
For example:
fullname = 'John "}}Trevor{{" Doe'
Ordinarily this would be rendered as:
{{# str }} somekey, someidentifier, { "fullname": "John "}}Trevor{{" Doe" } {{/ str }}
This rendering is both a JSON error, and also a mustache syntax error because of the mustache delimeters.
The quote helper also escapes these by wrapping them in change delimeter
tags:
{{# str }} somekey, someidentifier, { "fullname": "John "{{=<% %>=}}}}<%={{ }}=%>Trevor{{=<% %>=}}{{{{=<% %>=}}" Doe" } {{/ str }}
2016-02-12 12:42:41 +08:00
$quotehelper = new \core\output\mustache_quote_helper ();
2015-02-22 15:24:44 +08:00
$jshelper = new \core\output\mustache_javascript_helper ( $this -> page -> requires );
$pixhelper = new \core\output\mustache_pix_helper ( $this );
// We only expose the variables that are exposed to JS templates.
$safeconfig = $this -> page -> requires -> get_config_for_javascript ( $this -> page , $this );
$helpers = array ( 'config' => $safeconfig ,
'str' => array ( $stringhelper , 'str' ),
MDL-52136 core: Add support for quoting variables in mustache helpers
This is required for when helpers include json-encoded variables as arguments.
As an example, imagine a template with content:
{{# str }} somekey, someidentifier, { "fullname": "{{ fullname }}" } {{/ str }}
If the fullname variable were to include the double-quote character (e.g.
John "Trevor" Doe) because of the way in which mustache renders content, it
would become:
{{# str }} somekey, someidentifier, { "fullname": "John "Trevor" Doe" } {{/ str }}
This results in an invalid JSON structure.
To work around this issue, the quote characters in the passed variable
must be escaped:
{{# str }} somekey, someidentifier, { "fullname": "John \"Trevor\" Doe" } {{/ str }}
Unfortunately, Mustache provides no way of doing so natively.
With this function, we can quote the text as appropriate:
{{# str }} somekey, someidentifier, { "fullname": {{# quote }}{{ fullname }}{{/ quote }} } {{/ str }}
This also handles the case where the quoted content includes the Mustache
delimeter ({{ or }}).
For example:
fullname = 'John "}}Trevor{{" Doe'
Ordinarily this would be rendered as:
{{# str }} somekey, someidentifier, { "fullname": "John "}}Trevor{{" Doe" } {{/ str }}
This rendering is both a JSON error, and also a mustache syntax error because of the mustache delimeters.
The quote helper also escapes these by wrapping them in change delimeter
tags:
{{# str }} somekey, someidentifier, { "fullname": "John "{{=<% %>=}}}}<%={{ }}=%>Trevor{{=<% %>=}}{{{{=<% %>=}}" Doe" } {{/ str }}
2016-02-12 12:42:41 +08:00
'quote' => array ( $quotehelper , 'quote' ),
2015-02-22 15:24:44 +08:00
'js' => array ( $jshelper , 'help' ),
'pix' => array ( $pixhelper , 'pix' ));
$this -> mustache = new Mustache_Engine ( array (
'cache' => $cachedir ,
'escape' => 's' ,
'loader' => $loader ,
2015-07-22 13:02:01 +08:00
'helpers' => $helpers ,
'pragmas' => [ Mustache_Engine :: PRAGMA_BLOCKS ]));
2015-02-22 15:24:44 +08:00
}
return $this -> mustache ;
}
2009-08-10 06:22:04 +00:00
/**
* Constructor
2012-01-05 13:28:08 +13:00
*
2012-01-12 12:55:50 +13:00
* The constructor takes two arguments . The first is the page that the renderer
2012-01-05 13:28:08 +13:00
* has been created to assist with , and the second is the target .
* The target is an additional identifier that can be used to load different
* renderers for different options .
*
2009-08-10 06:22:04 +00:00
* @ param moodle_page $page the page we are doing output for .
2009-12-17 22:43:27 +00:00
* @ param string $target one of rendering target constants
2009-08-10 06:22:04 +00:00
*/
2009-12-17 22:43:27 +00:00
public function __construct ( moodle_page $page , $target ) {
2009-08-10 06:22:04 +00:00
$this -> opencontainers = $page -> opencontainers ;
$this -> page = $page ;
2009-12-17 22:43:27 +00:00
$this -> target = $target ;
2009-08-10 06:22:04 +00:00
}
2015-02-22 15:24:44 +08:00
/**
* Renders a template by name with the given context .
*
* The provided data needs to be array / stdClass made up of only simple types .
* Simple types are array , stdClass , bool , int , float , string
*
* @ since 2.9
* @ param array | stdClass $context Context containing data for the template .
* @ return string | boolean
*/
public function render_from_template ( $templatename , $context ) {
static $templatecache = array ();
$mustache = $this -> get_mustache ();
2016-06-16 07:47:53 +00:00
try {
// Grab a copy of the existing helper to be restored later.
2016-09-20 17:23:22 +08:00
$uniqidhelper = $mustache -> getHelper ( 'uniqid' );
2016-06-16 07:47:53 +00:00
} catch ( Mustache_Exception_UnknownHelperException $e ) {
// Helper doesn't exist.
2016-09-20 17:23:22 +08:00
$uniqidhelper = null ;
2016-06-16 07:47:53 +00:00
}
2015-02-22 15:24:44 +08:00
// Provide 1 random value that will not change within a template
// but will be different from template to template. This is useful for
// e.g. aria attributes that only work with id attributes and must be
// unique in a page.
$mustache -> addHelper ( 'uniqid' , new \core\output\mustache_uniqid_helper ());
if ( isset ( $templatecache [ $templatename ])) {
$template = $templatecache [ $templatename ];
} else {
try {
$template = $mustache -> loadTemplate ( $templatename );
$templatecache [ $templatename ] = $template ;
} catch ( Mustache_Exception_UnknownTemplateException $e ) {
throw new moodle_exception ( 'Unknown template: ' . $templatename );
}
}
2016-06-16 07:41:02 +00:00
2016-09-20 17:23:22 +08:00
$renderedtemplate = trim ( $template -> render ( $context ));
2016-06-16 07:41:02 +00:00
// If we had an existing uniqid helper then we need to restore it to allow
// handle nested calls of render_from_template.
2016-09-20 17:23:22 +08:00
if ( $uniqidhelper ) {
$mustache -> addHelper ( 'uniqid' , $uniqidhelper );
2016-06-16 07:41:02 +00:00
}
2016-09-20 17:23:22 +08:00
return $renderedtemplate ;
2015-02-22 15:24:44 +08:00
}
2009-08-10 06:22:04 +00:00
/**
2010-01-13 17:13:52 +00:00
* Returns rendered widget .
2012-01-05 13:28:08 +13:00
*
* The provided widget needs to be an object that extends the renderable
* interface .
2012-01-12 12:55:50 +13:00
* If will then be rendered by a method based upon the classname for the widget .
2012-01-05 13:28:08 +13:00
* For instance a widget of class ` crazywidget ` will be rendered by a protected
* render_crazywidget method of this renderer .
*
2010-05-22 14:43:46 +00:00
* @ param renderable $widget instance with renderable interface
2010-01-13 17:13:52 +00:00
* @ return string
2009-08-10 06:22:04 +00:00
*/
2010-01-13 17:13:52 +00:00
public function render ( renderable $widget ) {
2014-05-12 12:16:26 +08:00
$classname = get_class ( $widget );
// Strip namespaces.
$classname = preg_replace ( '/^.*\\\/' , '' , $classname );
// Remove _renderable suffixes
$classname = preg_replace ( '/_renderable$/' , '' , $classname );
$rendermethod = 'render_' . $classname ;
2010-01-13 17:13:52 +00:00
if ( method_exists ( $this , $rendermethod )) {
return $this -> $rendermethod ( $widget );
}
throw new coding_exception ( 'Can not render widget, renderer method (' . $rendermethod . ') not found.' );
2009-08-10 06:22:04 +00:00
}
/**
2012-01-05 13:28:08 +13:00
* Adds a JS action for the element with the provided id .
*
* This method adds a JS event for the provided component action to the page
* and then returns the id that the event has been attached to .
2012-02-14 18:24:09 +13:00
* If no id has been provided then a new ID is generated by { @ link html_writer :: random_id ()}
2012-01-05 13:28:08 +13:00
*
2012-02-14 18:24:09 +13:00
* @ param component_action $action
2010-02-11 15:44:06 +00:00
* @ param string $id
* @ return string id of element , either original submitted or random new if not supplied
2009-08-10 06:22:04 +00:00
*/
2012-01-05 13:28:08 +13:00
public function add_action_handler ( component_action $action , $id = null ) {
2010-02-11 15:44:06 +00:00
if ( ! $id ) {
$id = html_writer :: random_id ( $action -> event );
}
2010-01-19 22:01:12 +00:00
$this -> page -> requires -> event_handler ( " # $id " , $action -> event , $action -> jsfunction , $action -> jsfunctionargs );
2010-02-11 15:44:06 +00:00
return $id ;
2009-08-10 06:22:04 +00:00
}
/**
2012-01-05 13:28:08 +13:00
* Returns true is output has already started , and false if not .
*
2010-01-13 17:13:52 +00:00
* @ return boolean true if the header has been printed .
2009-08-10 06:22:04 +00:00
*/
2010-01-13 17:13:52 +00:00
public function has_started () {
return $this -> page -> state >= moodle_page :: STATE_IN_BODY ;
2009-08-10 06:22:04 +00:00
}
/**
* Given an array or space - separated list of classes , prepares and returns the HTML class attribute value
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param mixed $classes Space - separated string or array of classes
* @ return string HTML class attribute value
*/
public static function prepare_classes ( $classes ) {
if ( is_array ( $classes )) {
return implode ( ' ' , array_unique ( $classes ));
}
return $classes ;
}
/**
2010-01-04 14:40:34 +00:00
* Return the moodle_url for an image .
2012-01-05 13:28:08 +13:00
*
2010-01-04 14:40:34 +00:00
* The exact image location and extension is determined
* automatically by searching for gif | png | jpg | jpeg , please
* note there can not be diferent images with the different
* extension . The imagename is for historical reasons
* a relative path name , it may be changed later for core
* images . It is recommended to not use subdirectories
* in plugin and theme pix directories .
2009-08-10 06:22:04 +00:00
*
2010-01-04 14:40:34 +00:00
* There are three types of images :
* 1 / theme images - stored in theme / mytheme / pix / ,
* use component 'theme'
* 2 / core images - stored in / pix / ,
* overridden via theme / mytheme / pix_core /
* 3 / plugin images - stored in mod / mymodule / pix ,
* overridden via theme / mytheme / pix_plugins / mod / mymodule / ,
* example : pix_url ( 'comment' , 'mod_glossary' )
*
* @ param string $imagename the pathname of the image
* @ param string $component full plugin name ( aka component ) or 'theme'
2009-12-16 18:00:58 +00:00
* @ return moodle_url
2009-08-10 06:22:04 +00:00
*/
2009-12-17 22:43:27 +00:00
public function pix_url ( $imagename , $component = 'moodle' ) {
2009-12-16 20:33:37 +00:00
return $this -> page -> theme -> pix_url ( $imagename , $component );
2009-08-10 06:22:04 +00:00
}
2016-08-03 17:43:23 +08:00
/**
* Return the site ' s logo URL , if any .
*
* @ param int $maxwidth The maximum width , or null when the maximum width does not matter .
* @ param int $maxheight The maximum height , or null when the maximum height does not matter .
* @ return moodle_url | false
*/
public function get_logo_url ( $maxwidth = null , $maxheight = 100 ) {
global $CFG ;
$logo = get_config ( 'core_admin' , 'logo' );
if ( empty ( $logo )) {
return false ;
}
// Hide the requested size in the file path.
$filepath = (( int ) $maxwidth . 'x' . ( int ) $maxheight ) . '/' ;
// Use $CFG->themerev to prevent browser caching when the file changes.
return moodle_url :: make_pluginfile_url ( context_system :: instance () -> id , 'core_admin' , 'logo' , $filepath ,
theme_get_revision (), $logo );
}
/**
* Return the site ' s compact logo URL , if any .
*
* @ param int $maxwidth The maximum width , or null when the maximum width does not matter .
* @ param int $maxheight The maximum height , or null when the maximum height does not matter .
* @ return moodle_url | false
*/
public function get_compact_logo_url ( $maxwidth = 100 , $maxheight = 100 ) {
global $CFG ;
$logo = get_config ( 'core_admin' , 'logocompact' );
if ( empty ( $logo )) {
return false ;
}
// Hide the requested size in the file path.
$filepath = (( int ) $maxwidth . 'x' . ( int ) $maxheight ) . '/' ;
// Use $CFG->themerev to prevent browser caching when the file changes.
return moodle_url :: make_pluginfile_url ( context_system :: instance () -> id , 'core_admin' , 'logocompact' , $filepath ,
theme_get_revision (), $logo );
}
2009-08-10 06:22:04 +00:00
}
2009-12-17 22:43:27 +00:00
2009-12-17 14:51:36 +00:00
/**
* Basis for all plugin renderers .
*
2012-02-14 18:24:09 +13:00
* @ copyright Petr Skoda ( skodak )
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
* @ since Moodle 2.0
* @ package core
2012-01-11 10:40:55 +13:00
* @ category output
2009-12-17 14:51:36 +00:00
*/
class plugin_renderer_base extends renderer_base {
2012-01-05 13:28:08 +13:00
2009-12-17 14:51:36 +00:00
/**
2012-01-12 12:55:50 +13:00
* @ var renderer_base | core_renderer A reference to the current renderer .
* The renderer provided here will be determined by the page but will in 90 %
2012-02-14 18:24:09 +13:00
* of cases by the { @ link core_renderer }
2009-12-17 14:51:36 +00:00
*/
protected $output ;
/**
2010-05-22 14:43:46 +00:00
* Constructor method , calls the parent constructor
2012-01-05 13:28:08 +13:00
*
2009-12-17 14:51:36 +00:00
* @ param moodle_page $page
2009-12-17 22:43:27 +00:00
* @ param string $target one of rendering target constants
2009-12-17 14:51:36 +00:00
*/
2009-12-17 22:43:27 +00:00
public function __construct ( moodle_page $page , $target ) {
2013-09-12 09:51:58 +12:00
if ( empty ( $target ) && $page -> pagelayout === 'maintenance' ) {
// If the page is using the maintenance layout then we're going to force the target to maintenance.
// This way we'll get a special maintenance renderer that is designed to block access to API's that are likely
// unavailable for this page layout.
$target = RENDERER_TARGET_MAINTENANCE ;
}
2009-12-17 22:43:27 +00:00
$this -> output = $page -> get_renderer ( 'core' , null , $target );
parent :: __construct ( $page , $target );
2009-12-17 14:51:36 +00:00
}
2009-12-17 14:54:04 +00:00
2010-01-13 17:13:52 +00:00
/**
2012-01-05 13:28:08 +13:00
* Renders the provided widget and returns the HTML to display it .
*
2010-05-22 20:16:12 +00:00
* @ param renderable $widget instance with renderable interface
2010-01-13 17:13:52 +00:00
* @ return string
*/
public function render ( renderable $widget ) {
2014-05-12 12:16:26 +08:00
$classname = get_class ( $widget );
// Strip namespaces.
$classname = preg_replace ( '/^.*\\\/' , '' , $classname );
2014-07-02 13:51:45 +12:00
// Keep a copy at this point, we may need to look for a deprecated method.
$deprecatedmethod = 'render_' . $classname ;
2014-05-12 12:16:26 +08:00
// Remove _renderable suffixes
2014-07-02 13:51:45 +12:00
$classname = preg_replace ( '/_renderable$/' , '' , $classname );
2014-05-12 12:16:26 +08:00
$rendermethod = 'render_' . $classname ;
2010-01-13 17:13:52 +00:00
if ( method_exists ( $this , $rendermethod )) {
return $this -> $rendermethod ( $widget );
}
2014-07-02 13:51:45 +12:00
if ( $rendermethod !== $deprecatedmethod && method_exists ( $this , $deprecatedmethod )) {
// This is exactly where we don't want to be.
// If you have arrived here you have a renderable component within your plugin that has the name
// blah_renderable, and you have a render method render_blah_renderable on your plugin.
// In 2.8 we revamped output, as part of this change we changed slightly how renderables got rendered
// and the _renderable suffix now gets removed when looking for a render method.
// You need to change your renderers render_blah_renderable to render_blah.
// Until you do this it will not be possible for a theme to override the renderer to override your method.
// Please do it ASAP.
static $debugged = array ();
if ( ! isset ( $debugged [ $deprecatedmethod ])) {
debugging ( sprintf ( 'Deprecated call. Please rename your renderables render method from %s to %s.' ,
$deprecatedmethod , $rendermethod ), DEBUG_DEVELOPER );
$debugged [ $deprecatedmethod ] = true ;
}
return $this -> $deprecatedmethod ( $widget );
}
2010-01-13 17:13:52 +00:00
// pass to core renderer if method not found here
2010-07-08 16:32:19 +00:00
return $this -> output -> render ( $widget );
2010-01-13 17:13:52 +00:00
}
2009-12-17 14:54:04 +00:00
/**
* Magic method used to pass calls otherwise meant for the standard renderer
2010-05-22 14:43:46 +00:00
* to it to ensure we don ' t go causing unnecessary grief .
2009-12-17 14:54:04 +00:00
*
* @ param string $method
* @ param array $arguments
* @ return mixed
*/
public function __call ( $method , $arguments ) {
2009-12-20 16:34:18 +00:00
if ( method_exists ( 'renderer_base' , $method )) {
2012-06-27 15:27:50 +01:00
throw new coding_exception ( 'Protected method called against ' . get_class ( $this ) . ' :: ' . $method );
2009-12-20 16:34:18 +00:00
}
2009-12-17 14:54:04 +00:00
if ( method_exists ( $this -> output , $method )) {
return call_user_func_array ( array ( $this -> output , $method ), $arguments );
} else {
2012-06-27 15:27:50 +01:00
throw new coding_exception ( 'Unknown method called against ' . get_class ( $this ) . ' :: ' . $method );
2009-12-17 14:54:04 +00:00
}
}
2009-12-17 14:51:36 +00:00
}
2009-08-10 06:22:04 +00:00
2009-12-17 22:43:27 +00:00
2009-08-10 06:22:04 +00:00
/**
2009-12-16 18:00:58 +00:00
* The standard implementation of the core_renderer interface .
2009-08-10 06:22:04 +00:00
*
* @ copyright 2009 Tim Hunt
2012-01-05 13:28:08 +13:00
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
* @ since Moodle 2.0
2012-02-14 18:24:09 +13:00
* @ package core
2012-01-11 10:40:55 +13:00
* @ category output
2009-08-10 06:22:04 +00:00
*/
2009-12-16 18:00:58 +00:00
class core_renderer extends renderer_base {
2011-08-21 21:01:31 +02:00
/**
* Do NOT use , please use < ? php echo $OUTPUT -> main_content () ?>
* in layout files instead .
* @ deprecated
2012-02-14 18:24:09 +13:00
* @ var string used in { @ link core_renderer :: header ()} .
2011-08-21 21:01:31 +02:00
*/
2009-08-10 06:22:04 +00:00
const MAIN_CONTENT_TOKEN = '[MAIN CONTENT GOES HERE]' ;
2012-01-05 13:28:08 +13:00
/**
2012-02-14 18:24:09 +13:00
* @ var string Used to pass information from { @ link core_renderer :: doctype ()} to
* { @ link core_renderer :: standard_head_html ()} .
2012-01-05 13:28:08 +13:00
*/
2009-08-10 06:22:04 +00:00
protected $contenttype ;
2012-01-05 13:28:08 +13:00
/**
2012-02-14 18:24:09 +13:00
* @ var string Used by { @ link core_renderer :: redirect_message ()} method to communicate
* with { @ link core_renderer :: header ()} .
2012-01-05 13:28:08 +13:00
*/
2009-08-10 06:22:04 +00:00
protected $metarefreshtag = '' ;
2012-01-05 13:28:08 +13:00
/**
2012-01-11 10:40:55 +13:00
* @ var string Unique token for the closing HTML
2012-01-05 13:28:08 +13:00
*/
2011-08-21 21:01:31 +02:00
protected $unique_end_html_token ;
2012-01-05 13:28:08 +13:00
/**
2012-01-11 10:40:55 +13:00
* @ var string Unique token for performance information
2012-01-05 13:28:08 +13:00
*/
2011-08-21 21:01:31 +02:00
protected $unique_performance_info_token ;
2012-01-05 13:28:08 +13:00
/**
2012-01-11 10:40:55 +13:00
* @ var string Unique token for the main content .
2012-01-05 13:28:08 +13:00
*/
2011-08-21 21:01:31 +02:00
protected $unique_main_content_token ;
/**
* Constructor
2012-01-05 13:28:08 +13:00
*
2011-08-21 21:01:31 +02:00
* @ param moodle_page $page the page we are doing output for .
* @ param string $target one of rendering target constants
*/
public function __construct ( moodle_page $page , $target ) {
$this -> opencontainers = $page -> opencontainers ;
$this -> page = $page ;
$this -> target = $target ;
$this -> unique_end_html_token = '%%ENDHTML-' . sesskey () . '%%' ;
$this -> unique_performance_info_token = '%%PERFORMANCEINFO-' . sesskey () . '%%' ;
$this -> unique_main_content_token = '[MAIN CONTENT GOES HERE - ' . sesskey () . ']' ;
}
2009-08-10 06:22:04 +00:00
/**
* Get the DOCTYPE declaration that should be used with this page . Designed to
* be called in theme layout . php files .
2012-01-05 13:28:08 +13:00
*
2012-07-21 19:23:44 +02:00
* @ return string the DOCTYPE declaration that should be used .
2009-08-10 06:22:04 +00:00
*/
public function doctype () {
2012-07-21 19:23:44 +02:00
if ( $this -> page -> theme -> doctype === 'html5' ) {
$this -> contenttype = 'text/html; charset=utf-8' ;
return " <!DOCTYPE html> \n " ;
2009-08-10 06:22:04 +00:00
2012-07-21 19:23:44 +02:00
} else if ( $this -> page -> theme -> doctype === 'xhtml5' ) {
2009-08-10 06:22:04 +00:00
$this -> contenttype = 'application/xhtml+xml; charset=utf-8' ;
2012-07-21 19:23:44 +02:00
return " <!DOCTYPE html> \n " ;
2009-08-10 06:22:04 +00:00
} else {
2012-07-21 19:23:44 +02:00
// legacy xhtml 1.0
$this -> contenttype = 'text/html; charset=utf-8' ;
return ( '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' . " \n " );
2009-08-10 06:22:04 +00:00
}
}
/**
* The attributes that should be added to the < html > tag . Designed to
* be called in theme layout . php files .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ return string HTML fragment .
*/
public function htmlattributes () {
2012-07-21 19:23:44 +02:00
$return = get_html_lang ( true );
if ( $this -> page -> theme -> doctype !== 'html5' ) {
$return .= ' xmlns="http://www.w3.org/1999/xhtml"' ;
}
return $return ;
2009-08-10 06:22:04 +00:00
}
/**
* The standard tags ( meta tags , links to stylesheets and JavaScript , etc . )
* that should be included in the < head > tag . Designed to be called in theme
* layout . php files .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ return string HTML fragment .
*/
public function standard_head_html () {
2009-12-02 06:38:16 +00:00
global $CFG , $SESSION ;
2013-09-01 23:52:58 +01:00
// Before we output any content, we need to ensure that certain
// page components are set up.
// Blocks must be set up early as they may require javascript which
// has to be included in the page header before output is created.
foreach ( $this -> page -> blocks -> get_regions () as $region ) {
$this -> page -> blocks -> ensure_content_created ( $region , $this );
}
2009-08-10 06:22:04 +00:00
$output = '' ;
2016-02-05 19:45:00 +11:00
// Allow a url_rewrite plugin to setup any dynamic head content.
if ( isset ( $CFG -> urlrewriteclass ) && ! isset ( $CFG -> upgraderunning )) {
$class = $CFG -> urlrewriteclass ;
$output .= $class :: html_head_setup ();
}
2009-08-10 06:22:04 +00:00
$output .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />' . " \n " ;
$output .= '<meta name="keywords" content="moodle, ' . $this -> page -> title . '" />' . " \n " ;
2012-02-14 18:24:09 +13:00
// This is only set by the {@link redirect()} method
2009-08-10 06:22:04 +00:00
$output .= $this -> metarefreshtag ;
// Check if a periodic refresh delay has been set and make sure we arn't
// already meta refreshing
if ( $this -> metarefreshtag == '' && $this -> page -> periodicrefreshdelay !== null ) {
$output .= '<meta http-equiv="refresh" content="' . $this -> page -> periodicrefreshdelay . ';url=' . $this -> page -> url -> out () . '" />' ;
}
2016-08-01 11:25:16 +02:00
// Smart App Banners meta tag is only displayed if mobile services are enabled and configured.
2016-10-04 15:07:57 +01:00
if ( ! empty ( $CFG -> enablemobilewebservice )) {
2016-08-01 11:25:16 +02:00
$mobilesettings = get_config ( 'tool_mobile' );
2016-10-04 15:07:57 +01:00
if ( ! empty ( $mobilesettings -> enablesmartappbanners ) and ! empty ( $mobilesettings -> iosappid )) {
2016-08-01 11:25:16 +02:00
$output .= '<meta name="apple-itunes-app" content="app-id=' . s ( $mobilesettings -> iosappid ) . ', ' ;
$output .= 'app-argument=' . $this -> page -> url -> out () . '"/>' ;
}
}
2012-10-10 11:03:00 +01:00
// Set up help link popups for all links with the helptooltip class
2012-10-07 09:55:08 +01:00
$this -> page -> requires -> js_init_call ( 'M.util.help_popups.setup' );
2012-10-10 11:03:00 +01:00
// Setup help icon overlays.
$this -> page -> requires -> yui_module ( 'moodle-core-popuphelp' , 'M.core.init_popuphelp' );
$this -> page -> requires -> strings_for_js ( array (
'morehelp' ,
'loadinghelp' ,
), 'moodle' );
2009-08-28 08:47:31 +00:00
$this -> page -> requires -> js_function_call ( 'setTimeout' , array ( 'fix_column_widths()' , 20 ));
2009-08-10 06:22:04 +00:00
$focus = $this -> page -> focuscontrol ;
if ( ! empty ( $focus )) {
if ( preg_match ( " #forms \ ['([a-zA-Z0-9]+)' \ ].elements \ ['([a-zA-Z0-9]+)' \ ]# " , $focus , $matches )) {
// This is a horrifically bad way to handle focus but it is passed in
// through messy formslib::moodleform
2009-08-28 08:47:31 +00:00
$this -> page -> requires -> js_function_call ( 'old_onload_focus' , array ( $matches [ 1 ], $matches [ 2 ]));
2009-08-10 06:22:04 +00:00
} else if ( strpos ( $focus , '.' ) !== false ) {
// Old style of focus, bad way to do it
debugging ( 'This code is using the old style focus event, Please update this code to focus on an element id or the moodleform focus method.' , DEBUG_DEVELOPER );
$this -> page -> requires -> js_function_call ( 'old_onload_focus' , explode ( '.' , $focus , 2 ));
} else {
// Focus element with given id
2009-08-28 08:47:31 +00:00
$this -> page -> requires -> js_function_call ( 'focuscontrol' , array ( $focus ));
2009-08-10 06:22:04 +00:00
}
}
2009-12-16 18:00:58 +00:00
// Get the theme stylesheet - this has to be always first CSS, this loads also styles.css from all plugins;
// any other custom CSS can not be overridden via themes and is highly discouraged
2010-01-05 00:33:15 +00:00
$urls = $this -> page -> theme -> css_urls ( $this -> page );
2009-12-16 18:00:58 +00:00
foreach ( $urls as $url ) {
2010-01-18 20:02:13 +00:00
$this -> page -> requires -> css_theme ( $url );
2009-12-16 18:00:58 +00:00
}
2010-01-05 23:22:16 +00:00
// Get the theme javascript head and footer
2012-11-05 14:03:04 +00:00
if ( $jsurl = $this -> page -> theme -> javascript_url ( true )) {
$this -> page -> requires -> js ( $jsurl , true );
}
if ( $jsurl = $this -> page -> theme -> javascript_url ( false )) {
$this -> page -> requires -> js ( $jsurl );
}
2010-01-13 17:13:52 +00:00
2009-08-10 06:22:04 +00:00
// Get any HTML from the page_requirements_manager.
2009-12-28 23:08:55 +00:00
$output .= $this -> page -> requires -> get_head_code ( $this -> page , $this );
2009-08-10 06:22:04 +00:00
// List alternate versions.
foreach ( $this -> page -> alternateversions as $type => $alt ) {
2010-01-13 17:13:52 +00:00
$output .= html_writer :: empty_tag ( 'link' , array ( 'rel' => 'alternate' ,
2009-08-10 06:22:04 +00:00
'type' => $type , 'title' => $alt -> title , 'href' => $alt -> url ));
}
2011-01-14 09:32:17 +01:00
2010-12-07 08:48:38 +00:00
if ( ! empty ( $CFG -> additionalhtmlhead )) {
$output .= " \n " . $CFG -> additionalhtmlhead ;
}
2009-08-10 06:22:04 +00:00
return $output ;
}
/**
* The standard tags ( typically skip links ) that should be output just inside
* the start of the < body > tag . Designed to be called in theme layout . php files .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ return string HTML fragment .
*/
public function standard_top_of_body_html () {
2010-12-07 08:48:38 +00:00
global $CFG ;
2016-07-15 17:02:22 +08:00
$output = $this -> page -> requires -> get_top_of_body_code ( $this );
2016-06-08 13:16:07 +08:00
if ( $this -> page -> pagelayout !== 'embedded' && ! empty ( $CFG -> additionalhtmltopofbody )) {
2010-12-07 08:48:38 +00:00
$output .= " \n " . $CFG -> additionalhtmltopofbody ;
}
2013-01-21 16:51:28 +01:00
$output .= $this -> maintenance_warning ();
return $output ;
}
/**
* Scheduled maintenance warning message .
*
* Note : This is a nasty hack to display maintenance notice , this should be moved
* to some general notification area once we have it .
*
* @ return string
*/
public function maintenance_warning () {
global $CFG ;
$output = '' ;
if ( isset ( $CFG -> maintenance_later ) and $CFG -> maintenance_later > time ()) {
2013-11-20 09:05:01 +08:00
$timeleft = $CFG -> maintenance_later - time ();
// If timeleft less than 30 sec, set the class on block to error to highlight.
2016-10-27 10:22:36 +08:00
$errorclass = ( $timeleft < 30 ) ? 'alert-error alert-danger' : 'alert-warning' ;
$output .= $this -> box_start ( $errorclass . ' moodle-has-zindex maintenancewarning m-a-1 alert' );
2013-11-20 09:05:01 +08:00
$a = new stdClass ();
2016-10-13 14:50:07 -04:00
$a -> hour = ( int )( $timeleft / 3600 );
$a -> min = ( int )(( $timeleft / 60 ) % 60 );
2013-11-20 09:05:01 +08:00
$a -> sec = ( int )( $timeleft % 60 );
2016-10-13 14:50:07 -04:00
if ( $a -> hour > 0 ) {
$output .= get_string ( 'maintenancemodeisscheduledlong' , 'admin' , $a );
} else {
$output .= get_string ( 'maintenancemodeisscheduled' , 'admin' , $a );
}
2013-01-21 16:51:28 +01:00
$output .= $this -> box_end ();
2013-11-20 09:05:01 +08:00
$this -> page -> requires -> yui_module ( 'moodle-core-maintenancemodetimer' , 'M.core.maintenancemodetimer' ,
array ( array ( 'timeleftinsec' => $timeleft )));
$this -> page -> requires -> strings_for_js (
2016-10-13 14:50:07 -04:00
array ( 'maintenancemodeisscheduled' , 'maintenancemodeisscheduledlong' , 'sitemaintenance' ),
2013-11-20 09:05:01 +08:00
'admin' );
2013-01-21 16:51:28 +01:00
}
2010-12-07 08:48:38 +00:00
return $output ;
2009-08-10 06:22:04 +00:00
}
/**
* The standard tags ( typically performance information and validation links ,
* if we are in developer debug mode ) that should be output in the footer area
* of the page . Designed to be called in theme layout . php files .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ return string HTML fragment .
*/
public function standard_footer_html () {
2010-11-20 13:22:27 +01:00
global $CFG , $SCRIPT ;
2009-08-10 06:22:04 +00:00
2013-04-24 12:50:45 +02:00
if ( during_initial_install ()) {
// Debugging info can not work before install is finished,
// in any case we do not want any links during installation!
return '' ;
}
2012-02-14 18:24:09 +13:00
// This function is normally called from a layout.php file in {@link core_renderer::header()}
2009-08-10 06:22:04 +00:00
// but some of the content won't be known until later, so we return a placeholder
2012-02-14 18:24:09 +13:00
// for now. This will be replaced with the real content in {@link core_renderer::footer()}.
2011-08-21 21:01:31 +02:00
$output = $this -> unique_performance_info_token ;
2011-05-31 14:28:03 +08:00
if ( $this -> page -> devicetypeinuse == 'legacy' ) {
2010-04-21 04:21:53 +00:00
// The legacy theme is in use print the notification
$output .= html_writer :: tag ( 'div' , get_string ( 'legacythemeinuse' ), array ( 'class' => 'legacythemeinuse' ));
}
2011-05-31 14:25:52 +08:00
2011-05-31 14:28:03 +08:00
// Get links to switch device types (only shown for users not on a default device)
2011-05-31 14:25:52 +08:00
$output .= $this -> theme_switch_links ();
2009-08-10 06:22:04 +00:00
if ( ! empty ( $CFG -> debugpageinfo )) {
2010-08-20 07:37:59 +00:00
$output .= '<div class="performanceinfo pageinfo">This page is: ' . $this -> page -> debug_summary () . '</div>' ;
2009-08-10 06:22:04 +00:00
}
2012-07-25 16:25:55 +08:00
if ( debugging ( null , DEBUG_DEVELOPER ) and has_capability ( 'moodle/site:config' , context_system :: instance ())) { // Only in developer mode
2010-11-20 13:22:27 +01:00
// Add link to profiling report if necessary
if ( function_exists ( 'profiling_is_running' ) && profiling_is_running ()) {
$txt = get_string ( 'profiledscript' , 'admin' );
$title = get_string ( 'profiledscriptview' , 'admin' );
2011-09-19 18:54:30 +02:00
$url = $CFG -> wwwroot . '/admin/tool/profiling/index.php?script=' . urlencode ( $SCRIPT );
2010-11-20 13:22:27 +01:00
$link = '<a title="' . $title . '" href="' . $url . '">' . $txt . '</a>' ;
$output .= '<div class="profilingfooter">' . $link . '</div>' ;
}
2013-07-29 16:03:58 +01:00
$purgeurl = new moodle_url ( '/admin/purgecaches.php' , array ( 'confirm' => 1 ,
'sesskey' => sesskey (), 'returnurl' => $this -> page -> url -> out_as_local_url ( false )));
$output .= '<div class="purgecaches">' .
html_writer :: link ( $purgeurl , get_string ( 'purgecaches' , 'admin' )) . '</div>' ;
2010-07-18 07:17:01 +00:00
}
2009-08-10 06:22:04 +00:00
if ( ! empty ( $CFG -> debugvalidators )) {
2012-04-22 17:17:27 +02:00
// NOTE: this is not a nice hack, $PAGE->url is not always accurate and $FULLME neither, it is not a bug if it fails. --skodak
2009-08-10 06:22:04 +00:00
$output .= ' < div class = " validators " >< ul >
< li >< a href = " http://validator.w3.org/check?verbose=1&ss=1&uri=' . urlencode(qualified_me()) . ' " > Validate HTML </ a ></ li >
< li >< a href = " http://www.contentquality.com/mynewtester/cynthia.exe?rptmode=-1&url1=' . urlencode(qualified_me()) . ' " > Section 508 Check </ a ></ li >
< li >< a href = " http://www.contentquality.com/mynewtester/cynthia.exe?rptmode=0&warnp2n3e=1&url1=' . urlencode(qualified_me()) . ' " > WCAG 1 ( 2 , 3 ) Check </ a ></ li >
</ ul ></ div > ' ;
}
return $output ;
}
2011-08-21 21:01:31 +02:00
/**
* Returns standard main content placeholder .
* Designed to be called in theme layout . php files .
2012-01-05 13:28:08 +13:00
*
2011-08-21 21:01:31 +02:00
* @ return string HTML fragment .
*/
public function main_content () {
2012-10-19 11:17:48 +08:00
// This is here because it is the only place we can inject the "main" role over the entire main content area
// without requiring all theme's to manually do it, and without creating yet another thing people need to
// remember in the theme.
// This is an unfortunate hack. DO NO EVER add anything more here.
// DO NOT add classes.
// DO NOT add an id.
return '<div role="main">' . $this -> unique_main_content_token . '</div>' ;
2011-08-21 21:01:31 +02:00
}
2009-08-10 06:22:04 +00:00
/**
* The standard tags ( typically script tags that are not needed earlier ) that
2014-01-23 15:35:53 +00:00
* should be output after everything else . Designed to be called in theme layout . php files .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ return string HTML fragment .
*/
public function standard_end_of_body_html () {
2014-01-23 15:35:53 +00:00
global $CFG ;
2012-02-14 18:24:09 +13:00
// This function is normally called from a layout.php file in {@link core_renderer::header()}
2009-08-10 06:22:04 +00:00
// but some of the content won't be known until later, so we return a placeholder
2012-02-14 18:24:09 +13:00
// for now. This will be replaced with the real content in {@link core_renderer::footer()}.
2014-01-23 15:35:53 +00:00
$output = '' ;
2016-06-08 13:16:07 +08:00
if ( $this -> page -> pagelayout !== 'embedded' && ! empty ( $CFG -> additionalhtmlfooter )) {
2014-01-23 15:35:53 +00:00
$output .= " \n " . $CFG -> additionalhtmlfooter ;
}
$output .= $this -> unique_end_html_token ;
return $output ;
2009-08-10 06:22:04 +00:00
}
/**
* Return the standard string that says whether you are logged in ( and switched
* roles / logged in as another user ) .
2012-09-03 07:25:30 +02:00
* @ param bool $withlinks if false , then don ' t include any links in the HTML produced .
* If not set , the default is the nologinlinks option from the theme config . php file ,
* and if that is not set , then links are included .
2009-08-10 06:22:04 +00:00
* @ return string HTML fragment .
*/
2012-09-03 07:25:30 +02:00
public function login_info ( $withlinks = null ) {
2010-09-17 08:00:29 +00:00
global $USER , $CFG , $DB , $SESSION ;
2009-12-30 15:19:55 +00:00
2009-12-29 17:26:29 +00:00
if ( during_initial_install ()) {
return '' ;
}
2009-12-30 15:19:55 +00:00
2012-09-03 07:25:30 +02:00
if ( is_null ( $withlinks )) {
$withlinks = empty ( $this -> page -> layout_options [ 'nologinlinks' ]);
}
2009-12-29 17:26:29 +00:00
$course = $this -> page -> course ;
2013-09-08 08:38:52 +02:00
if ( \core\session\manager :: is_loggedinas ()) {
$realuser = \core\session\manager :: get_realuser ();
2009-12-29 17:26:29 +00:00
$fullname = fullname ( $realuser , true );
2012-09-03 07:25:30 +02:00
if ( $withlinks ) {
2013-04-02 15:51:41 +08:00
$loginastitle = get_string ( 'loginas' );
$realuserinfo = " [<a href= \" $CFG->wwwroot /course/loginas.php?id= $course->id &sesskey= " . sesskey () . " \" " ;
$realuserinfo .= " title = \" " . $loginastitle . " \" > $fullname </a>] " ;
2012-09-03 07:25:30 +02:00
} else {
$realuserinfo = " [ $fullname ] " ;
}
2009-12-29 17:26:29 +00:00
} else {
$realuserinfo = '' ;
}
2009-12-30 15:19:55 +00:00
2014-12-18 08:40:57 +08:00
$loginpage = $this -> is_login_page ();
2009-12-29 17:26:29 +00:00
$loginurl = get_login_url ();
2009-12-30 15:19:55 +00:00
2009-12-29 17:26:29 +00:00
if ( empty ( $course -> id )) {
// $course->id is not defined during installation
return '' ;
2010-03-31 07:41:31 +00:00
} else if ( isloggedin ()) {
2012-07-25 16:25:55 +08:00
$context = context_course :: instance ( $course -> id );
2009-12-30 15:19:55 +00:00
2009-12-29 17:26:29 +00:00
$fullname = fullname ( $USER , true );
2010-05-04 13:04:35 +00:00
// Since Moodle 2.0 this link always goes to the public profile page (not the course profile page)
2012-09-03 07:25:30 +02:00
if ( $withlinks ) {
2013-04-02 15:32:38 +08:00
$linktitle = get_string ( 'viewprofile' );
$username = " <a href= \" $CFG->wwwroot /user/profile.php?id= $USER->id\ " title = \ " $linktitle\ " > $fullname </ a > " ;
2012-09-03 07:25:30 +02:00
} else {
$username = $fullname ;
}
2009-12-29 17:26:29 +00:00
if ( is_mnet_remote_user ( $USER ) and $idprovider = $DB -> get_record ( 'mnet_host' , array ( 'id' => $USER -> mnethostid ))) {
2012-09-03 07:25:30 +02:00
if ( $withlinks ) {
$username .= " from <a href= \" { $idprovider -> wwwroot } \" > { $idprovider -> name } </a> " ;
} else {
$username .= " from { $idprovider -> name } " ;
}
2009-12-29 17:26:29 +00:00
}
2010-08-25 08:56:07 +00:00
if ( isguestuser ()) {
2010-10-16 17:43:04 +00:00
$loggedinas = $realuserinfo . get_string ( 'loggedinasguest' );
2012-09-03 07:25:30 +02:00
if ( ! $loginpage && $withlinks ) {
2010-10-16 17:43:04 +00:00
$loggedinas .= " (<a href= \" $loginurl\ " > " .get_string('login').'</a>)';
}
2010-08-27 01:44:25 +00:00
} else if ( is_role_switched ( $course -> id )) { // Has switched roles
2009-12-29 17:26:29 +00:00
$rolename = '' ;
if ( $role = $DB -> get_record ( 'role' , array ( 'id' => $USER -> access [ 'rsw' ][ $context -> path ]))) {
2013-03-17 21:13:28 +01:00
$rolename = ': ' . role_get_name ( $role , $context );
2009-12-29 17:26:29 +00:00
}
2012-09-03 07:25:30 +02:00
$loggedinas = get_string ( 'loggedinas' , 'moodle' , $username ) . $rolename ;
if ( $withlinks ) {
2012-12-07 18:13:22 +01:00
$url = new moodle_url ( '/course/switchrole.php' , array ( 'id' => $course -> id , 'sesskey' => sesskey (), 'switchrole' => 0 , 'returnurl' => $this -> page -> url -> out_as_local_url ( false )));
2014-05-09 16:19:14 +01:00
$loggedinas .= ' (' . html_writer :: tag ( 'a' , get_string ( 'switchrolereturn' ), array ( 'href' => $url )) . ')' ;
2012-09-03 07:25:30 +02:00
}
2009-12-29 17:26:29 +00:00
} else {
2012-09-03 07:25:30 +02:00
$loggedinas = $realuserinfo . get_string ( 'loggedinas' , 'moodle' , $username );
if ( $withlinks ) {
$loggedinas .= " (<a href= \" $CFG->wwwroot /login/logout.php?sesskey= " . sesskey () . " \" > " . get_string ( 'logout' ) . '</a>)' ;
}
2009-12-29 17:26:29 +00:00
}
} else {
2010-10-16 17:43:04 +00:00
$loggedinas = get_string ( 'loggedinnot' , 'moodle' );
2012-09-03 07:25:30 +02:00
if ( ! $loginpage && $withlinks ) {
2010-10-16 17:43:04 +00:00
$loggedinas .= " (<a href= \" $loginurl\ " > " .get_string('login').'</a>)';
}
2009-12-29 17:26:29 +00:00
}
2009-12-30 15:19:55 +00:00
2009-12-29 17:26:29 +00:00
$loggedinas = '<div class="logininfo">' . $loggedinas . '</div>' ;
2009-12-30 15:19:55 +00:00
2009-12-29 17:26:29 +00:00
if ( isset ( $SESSION -> justloggedin )) {
unset ( $SESSION -> justloggedin );
if ( ! empty ( $CFG -> displayloginfailures )) {
2010-08-25 08:56:07 +00:00
if ( ! isguestuser ()) {
2014-02-21 16:25:09 +08:00
// Include this file only when required.
require_once ( $CFG -> dirroot . '/user/lib.php' );
if ( $count = user_count_login_failures ( $USER )) {
2014-04-02 14:18:25 +08:00
$loggedinas .= '<div class="loginfailures">' ;
2014-02-21 16:25:09 +08:00
$a = new stdClass ();
$a -> attempts = $count ;
$loggedinas .= get_string ( 'failedloginattempts' , '' , $a );
2012-07-25 16:25:55 +08:00
if ( file_exists ( " $CFG->dirroot /report/log/index.php " ) and has_capability ( 'report/log:view' , context_system :: instance ())) {
2014-07-04 14:48:10 +01:00
$loggedinas .= ' (' . html_writer :: link ( new moodle_url ( '/report/log/index.php' , array ( 'chooselog' => 1 ,
'id' => 0 , 'modid' => 'site_errors' )), get_string ( 'logs' )) . ')' ;
2009-12-29 17:26:29 +00:00
}
$loggedinas .= '</div>' ;
}
}
}
}
2009-12-30 15:19:55 +00:00
2009-12-29 17:26:29 +00:00
return $loggedinas ;
2009-08-10 06:22:04 +00:00
}
2014-12-18 08:40:57 +08:00
/**
* Check whether the current page is a login page .
*
* @ since Moodle 2.9
* @ return bool
*/
protected function is_login_page () {
// This is a real bit of a hack, but its a rarety that we need to do something like this.
// In fact the login pages should be only these two pages and as exposing this as an option for all pages
// could lead to abuse (or at least unneedingly complex code) the hack is the way to go.
return in_array (
$this -> page -> url -> out_as_local_url ( false , array ()),
array (
'/login/index.php' ,
'/login/forgot_password.php' ,
)
);
}
2009-08-10 06:22:04 +00:00
/**
* Return the 'back' link that normally appears in the footer .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ return string HTML fragment .
*/
public function home_link () {
global $CFG , $SITE ;
if ( $this -> page -> pagetype == 'site-index' ) {
// Special case for site home page - please do not remove
return '<div class="sitelink">' .
2009-11-17 03:06:39 +00:00
'<a title="Moodle" href="http://moodle.org/">' .
2015-10-30 16:51:51 +00:00
'<img src="' . $this -> pix_url ( 'moodlelogo' ) . '" alt="' . get_string ( 'moodlelogo' ) . '" /></a></div>' ;
2009-08-10 06:22:04 +00:00
} else if ( ! empty ( $CFG -> target_release ) && $CFG -> target_release != $CFG -> release ) {
// Special case for during install/upgrade.
return '<div class="sitelink">' .
2009-11-17 03:06:39 +00:00
'<a title="Moodle" href="http://docs.moodle.org/en/Administrator_documentation" onclick="this.target=\'_blank\'">' .
2015-10-30 16:51:51 +00:00
'<img src="' . $this -> pix_url ( 'moodlelogo' ) . '" alt="' . get_string ( 'moodlelogo' ) . '" /></a></div>' ;
2009-08-10 06:22:04 +00:00
} else if ( $this -> page -> course -> id == $SITE -> id || strpos ( $this -> page -> pagetype , 'course-view' ) === 0 ) {
return '<div class="homelink"><a href="' . $CFG -> wwwroot . '/">' .
get_string ( 'home' ) . '</a></div>' ;
} else {
return '<div class="homelink"><a href="' . $CFG -> wwwroot . '/course/view.php?id=' . $this -> page -> course -> id . '">' .
2011-09-07 11:46:28 +12:00
format_string ( $this -> page -> course -> shortname , true , array ( 'context' => $this -> page -> context )) . '</a></div>' ;
2009-08-10 06:22:04 +00:00
}
}
/**
* Redirects the user by any means possible given the current state
*
* This function should not be called directly , it should always be called using
* the redirect function in lib / weblib . php
*
* The redirect function should really only be called before page output has started
* however it will allow itself to be called during the state STATE_IN_BODY
*
* @ param string $encodedurl The URL to send to encoded if required
* @ param string $message The message to display to the user if any
* @ param int $delay The delay before redirecting a user , if $message has been
* set this is a requirement and defaults to 3 , set to 0 no delay
* @ param boolean $debugdisableredirect this redirect has been disabled for
* debugging purposes . Display a message that explains , and don ' t
* trigger the redirect .
2016-02-16 08:49:42 +08:00
* @ param string $messagetype The type of notification to show the message in .
* See constants on \core\output\notification .
2009-08-10 06:22:04 +00:00
* @ return string The HTML to display to the user before dying , may contain
* meta refresh , javascript refresh , and may have set header redirects
*/
2016-02-16 08:49:42 +08:00
public function redirect_message ( $encodedurl , $message , $delay , $debugdisableredirect ,
$messagetype = \core\output\notification :: NOTIFY_INFO ) {
2009-08-10 06:22:04 +00:00
global $CFG ;
$url = str_replace ( '&' , '&' , $encodedurl );
switch ( $this -> page -> state ) {
case moodle_page :: STATE_BEFORE_HEADER :
// No output yet it is safe to delivery the full arsenal of redirect methods
if ( ! $debugdisableredirect ) {
// Don't use exactly the same time here, it can cause problems when both redirects fire at the same time.
$this -> metarefreshtag = '<meta http-equiv="refresh" content="' . $delay . '; url=' . $encodedurl . '" />' . " \n " ;
2010-02-06 14:45:17 +00:00
$this -> page -> requires -> js_function_call ( 'document.location.replace' , array ( $url ), false , ( $delay + 3 ));
2009-08-10 06:22:04 +00:00
}
$output = $this -> header ();
break ;
case moodle_page :: STATE_PRINTING_HEADER :
// We should hopefully never get here
throw new coding_exception ( 'You cannot redirect while printing the page header' );
break ;
case moodle_page :: STATE_IN_BODY :
// We really shouldn't be here but we can deal with this
debugging ( " You should really redirect before you start page output " );
if ( ! $debugdisableredirect ) {
2010-02-06 14:45:17 +00:00
$this -> page -> requires -> js_function_call ( 'document.location.replace' , array ( $url ), false , $delay );
2009-08-10 06:22:04 +00:00
}
$output = $this -> opencontainers -> pop_all_but_last ();
break ;
case moodle_page :: STATE_DONE :
// Too late to be calling redirect now
throw new coding_exception ( 'You cannot redirect after the entire page has been generated' );
break ;
}
2016-02-16 08:49:42 +08:00
$output .= $this -> notification ( $message , $messagetype );
2010-06-14 05:16:56 +00:00
$output .= '<div class="continuebutton">(<a href="' . $encodedurl . '">' . get_string ( 'continue' ) . '</a>)</div>' ;
2009-08-10 06:22:04 +00:00
if ( $debugdisableredirect ) {
2015-02-06 23:02:45 +02:00
$output .= '<p><strong>' . get_string ( 'erroroutput' , 'error' ) . '</strong></p>' ;
2009-08-10 06:22:04 +00:00
}
$output .= $this -> footer ();
return $output ;
}
/**
* Start output by sending the HTTP headers , and printing the HTML < head >
* and the start of the < body >.
*
* To control what is printed , you should set properties on $PAGE . If you
2012-02-14 18:24:09 +13:00
* are familiar with the old { @ link print_header ()} function from Moodle 1.9
2009-08-10 06:22:04 +00:00
* you will find that there are properties on $PAGE that correspond to most
* of the old parameters to could be passed to print_header .
*
* Not that , in due course , the remaining $navigation , $menu parameters here
* will be replaced by more properties of $PAGE , but that is still to do .
*
* @ return string HTML that you must output this , preferably immediately .
*/
2009-09-01 03:47:07 +00:00
public function header () {
2009-08-10 06:22:04 +00:00
global $USER , $CFG ;
2013-09-08 08:38:52 +02:00
if ( \core\session\manager :: is_loggedinas ()) {
2010-08-24 08:50:53 +00:00
$this -> page -> add_body_class ( 'userloggedinas' );
}
2014-09-16 13:41:41 +08:00
// If the user is logged in, and we're not in initial install,
// check to see if the user is role-switched and add the appropriate
// CSS class to the body element.
if ( ! during_initial_install () && isloggedin () && is_role_switched ( $this -> page -> course -> id )) {
$this -> page -> add_body_class ( 'userswitchedrole' );
}
2013-03-19 11:47:31 +01:00
// Give themes a chance to init/alter the page object.
$this -> page -> theme -> init_page ( $this -> page );
2009-08-10 06:22:04 +00:00
$this -> page -> set_state ( moodle_page :: STATE_PRINTING_HEADER );
2009-12-16 18:00:58 +00:00
// Find the appropriate page layout file, based on $this->page->pagelayout.
$layoutfile = $this -> page -> theme -> layout_file ( $this -> page -> pagelayout );
// Render the layout using the layout file.
$rendered = $this -> render_page_layout ( $layoutfile );
2009-10-03 08:54:30 +00:00
2009-12-16 18:00:58 +00:00
// Slice the rendered output into header and footer.
2011-08-21 21:01:31 +02:00
$cutpos = strpos ( $rendered , $this -> unique_main_content_token );
if ( $cutpos === false ) {
$cutpos = strpos ( $rendered , self :: MAIN_CONTENT_TOKEN );
$token = self :: MAIN_CONTENT_TOKEN ;
} else {
$token = $this -> unique_main_content_token ;
}
2009-08-10 06:22:04 +00:00
if ( $cutpos === false ) {
2011-08-21 21:01:31 +02:00
throw new coding_exception ( 'page layout file ' . $layoutfile . ' does not contain the main content placeholder, please include "<?php echo $OUTPUT->main_content() ?>" in theme layout file.' );
2009-08-10 06:22:04 +00:00
}
2009-12-16 18:00:58 +00:00
$header = substr ( $rendered , 0 , $cutpos );
2011-08-21 21:01:31 +02:00
$footer = substr ( $rendered , $cutpos + strlen ( $token ));
2009-08-10 06:22:04 +00:00
if ( empty ( $this -> contenttype )) {
2009-12-16 18:00:58 +00:00
debugging ( 'The page layout file did not call $OUTPUT->doctype()' );
2009-10-03 08:54:30 +00:00
$header = $this -> doctype () . $header ;
2009-08-10 06:22:04 +00:00
}
2012-10-18 09:38:36 +08:00
// If this theme version is below 2.4 release and this is a course view page
if (( ! isset ( $this -> page -> theme -> settings -> version ) || $this -> page -> theme -> settings -> version < 2012101500 ) &&
$this -> page -> pagelayout === 'course' && $this -> page -> url -> compare ( new moodle_url ( '/course/view.php' ), URL_MATCH_BASE )) {
// check if course content header/footer have not been output during render of theme layout
$coursecontentheader = $this -> course_content_header ( true );
$coursecontentfooter = $this -> course_content_footer ( true );
if ( ! empty ( $coursecontentheader )) {
// display debug message and add header and footer right above and below main content
// Please note that course header and footer (to be displayed above and below the whole page)
// are not displayed in this case at all.
// Besides the content header and footer are not displayed on any other course page
debugging ( 'The current theme is not optimised for 2.4, the course-specific header and footer defined in course format will not be output' , DEBUG_DEVELOPER );
$header .= $coursecontentheader ;
$footer = $coursecontentfooter . $footer ;
}
}
2009-08-10 06:22:04 +00:00
send_headers ( $this -> contenttype , $this -> page -> cacheable );
2009-10-03 08:54:30 +00:00
2009-08-10 06:22:04 +00:00
$this -> opencontainers -> push ( 'header/footer' , $footer );
$this -> page -> set_state ( moodle_page :: STATE_IN_BODY );
2009-10-03 08:54:30 +00:00
2010-06-23 09:10:53 +00:00
return $header . $this -> skip_link_target ( 'maincontent' );
2009-08-10 06:22:04 +00:00
}
/**
2009-12-16 18:00:58 +00:00
* Renders and outputs the page layout file .
2012-01-05 13:28:08 +13:00
*
* This is done by preparing the normal globals available to a script , and
* then including the layout file provided by the current theme for the
* requested layout .
*
2009-12-16 18:00:58 +00:00
* @ param string $layoutfile The name of the layout file
2009-08-10 06:22:04 +00:00
* @ return string HTML code
*/
2009-12-16 18:00:58 +00:00
protected function render_page_layout ( $layoutfile ) {
2009-12-23 17:44:17 +00:00
global $CFG , $SITE , $USER ;
2009-08-10 06:22:04 +00:00
// The next lines are a bit tricky. The point is, here we are in a method
// of a renderer class, and this object may, or may not, be the same as
2009-12-16 18:00:58 +00:00
// the global $OUTPUT object. When rendering the page layout file, we want to use
2009-08-10 06:22:04 +00:00
// this object. However, people writing Moodle code expect the current
// renderer to be called $OUTPUT, not $this, so define a variable called
// $OUTPUT pointing at $this. The same comment applies to $PAGE and $COURSE.
$OUTPUT = $this ;
$PAGE = $this -> page ;
$COURSE = $this -> page -> course ;
ob_start ();
2009-12-16 18:00:58 +00:00
include ( $layoutfile );
$rendered = ob_get_contents ();
2009-08-10 06:22:04 +00:00
ob_end_clean ();
2009-12-16 18:00:58 +00:00
return $rendered ;
2009-08-10 06:22:04 +00:00
}
/**
* Outputs the page ' s footer
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ return string HTML fragment
*/
public function footer () {
2016-02-16 08:48:39 +08:00
global $CFG , $DB , $PAGE ;
2009-11-03 11:02:07 +00:00
2009-12-23 18:05:58 +00:00
$output = $this -> container_end_all ( true );
2010-05-19 08:05:36 +00:00
2009-08-10 06:22:04 +00:00
$footer = $this -> opencontainers -> pop ( 'header/footer' );
2009-11-07 08:52:56 +00:00
if ( debugging () and $DB and $DB -> is_transaction_started ()) {
2009-11-09 11:33:14 +00:00
// TODO: MDL-20625 print warning - transaction will be rolled back
2009-11-07 08:52:56 +00:00
}
2009-08-10 06:22:04 +00:00
// Provide some performance info if required
$performanceinfo = '' ;
if ( defined ( 'MDL_PERF' ) || ( ! empty ( $CFG -> perfdebug ) and $CFG -> perfdebug > 7 )) {
$perf = get_performance_info ();
if ( defined ( 'MDL_PERFTOFOOT' ) || debugging () || $CFG -> perfdebug > 7 ) {
$performanceinfo = $perf [ 'html' ];
}
}
2013-11-14 11:55:03 +08:00
// We always want performance data when running a performance test, even if the user is redirected to another page.
if ( MDL_PERF_TEST && strpos ( $footer , $this -> unique_performance_info_token ) === false ) {
$footer = $this -> unique_performance_info_token . $footer ;
}
2011-08-21 21:01:31 +02:00
$footer = str_replace ( $this -> unique_performance_info_token , $performanceinfo , $footer );
2009-08-10 06:22:04 +00:00
2016-04-18 16:38:36 +08:00
// Only show notifications when we have a $PAGE context id.
if ( ! empty ( $PAGE -> context -> id )) {
$this -> page -> requires -> js_call_amd ( 'core/notification' , 'init' , array (
$PAGE -> context -> id ,
\core\notification :: fetch_as_array ( $this )
));
}
2011-08-21 21:01:31 +02:00
$footer = str_replace ( $this -> unique_end_html_token , $this -> page -> requires -> get_end_code (), $footer );
2009-08-10 06:22:04 +00:00
$this -> page -> set_state ( moodle_page :: STATE_DONE );
return $output . $footer ;
}
2009-12-23 18:05:58 +00:00
/**
* Close all but the last open container . This is useful in places like error
* handling , where you want to close all the open containers ( apart from < body > )
* before outputting the error message .
2012-01-05 13:28:08 +13:00
*
2009-12-23 18:05:58 +00:00
* @ param bool $shouldbenone assert that the stack should be empty now - causes a
* developer debug warning if it isn ' t .
* @ return string the HTML required to close any open containers inside < body >.
*/
public function container_end_all ( $shouldbenone = false ) {
return $this -> opencontainers -> pop_all_but_last ( $shouldbenone );
}
2012-10-18 09:38:36 +08:00
/**
* Returns course - specific information to be output immediately above content on any course page
* ( for the current course )
*
* @ param bool $onlyifnotcalledbefore output content only if it has not been output before
* @ return string
*/
public function course_content_header ( $onlyifnotcalledbefore = false ) {
global $CFG ;
static $functioncalled = false ;
if ( $functioncalled && $onlyifnotcalledbefore ) {
// we have already output the content header
return '' ;
}
2016-02-16 08:48:39 +08:00
// Output any session notification.
$notifications = \core\notification :: fetch ();
$bodynotifications = '' ;
foreach ( $notifications as $notification ) {
$bodynotifications .= $this -> render_from_template (
$notification -> get_template_name (),
$notification -> export_for_template ( $this )
);
}
$output = html_writer :: span ( $bodynotifications , 'notifications' , array ( 'id' => 'user-notifications' ));
if ( $this -> page -> course -> id == SITEID ) {
// return immediately and do not include /course/lib.php if not necessary
return $output ;
}
2012-10-18 09:38:36 +08:00
require_once ( $CFG -> dirroot . '/course/lib.php' );
$functioncalled = true ;
$courseformat = course_get_format ( $this -> page -> course );
if (( $obj = $courseformat -> course_content_header ()) !== null ) {
2016-02-16 08:48:39 +08:00
$output .= html_writer :: div ( $courseformat -> get_renderer ( $this -> page ) -> render ( $obj ), 'course-content-header' );
2012-10-18 09:38:36 +08:00
}
2016-02-16 08:48:39 +08:00
return $output ;
2012-10-18 09:38:36 +08:00
}
/**
* Returns course - specific information to be output immediately below content on any course page
* ( for the current course )
*
* @ param bool $onlyifnotcalledbefore output content only if it has not been output before
* @ return string
*/
public function course_content_footer ( $onlyifnotcalledbefore = false ) {
global $CFG ;
if ( $this -> page -> course -> id == SITEID ) {
// return immediately and do not include /course/lib.php if not necessary
return '' ;
}
static $functioncalled = false ;
if ( $functioncalled && $onlyifnotcalledbefore ) {
// we have already output the content footer
return '' ;
}
$functioncalled = true ;
require_once ( $CFG -> dirroot . '/course/lib.php' );
$courseformat = course_get_format ( $this -> page -> course );
if (( $obj = $courseformat -> course_content_footer ()) !== null ) {
2013-06-07 10:38:39 +12:00
return html_writer :: div ( $courseformat -> get_renderer ( $this -> page ) -> render ( $obj ), 'course-content-footer' );
2012-10-18 09:38:36 +08:00
}
return '' ;
}
/**
* Returns course - specific information to be output on any course page in the header area
* ( for the current course )
*
* @ return string
*/
public function course_header () {
global $CFG ;
if ( $this -> page -> course -> id == SITEID ) {
// return immediately and do not include /course/lib.php if not necessary
return '' ;
}
require_once ( $CFG -> dirroot . '/course/lib.php' );
$courseformat = course_get_format ( $this -> page -> course );
if (( $obj = $courseformat -> course_header ()) !== null ) {
return $courseformat -> get_renderer ( $this -> page ) -> render ( $obj );
}
return '' ;
}
/**
* Returns course - specific information to be output on any course page in the footer area
* ( for the current course )
*
* @ return string
*/
public function course_footer () {
global $CFG ;
if ( $this -> page -> course -> id == SITEID ) {
// return immediately and do not include /course/lib.php if not necessary
return '' ;
}
require_once ( $CFG -> dirroot . '/course/lib.php' );
$courseformat = course_get_format ( $this -> page -> course );
if (( $obj = $courseformat -> course_footer ()) !== null ) {
return $courseformat -> get_renderer ( $this -> page ) -> render ( $obj );
}
return '' ;
}
2009-12-29 17:26:29 +00:00
/**
* Returns lang menu or '' , this method also checks forcing of languages in courses .
2012-01-05 13:28:08 +13:00
*
2013-04-15 11:05:46 +10:00
* This function calls { @ link core_renderer :: render_single_select ()} to actually display the language menu .
*
2012-01-05 13:28:08 +13:00
* @ return string The lang menu HTML or empty string
2009-12-29 17:26:29 +00:00
*/
public function lang_menu () {
global $CFG ;
if ( empty ( $CFG -> langmenu )) {
return '' ;
}
if ( $this -> page -> course != SITEID and ! empty ( $this -> page -> course -> lang )) {
// do not show lang menu if language forced
return '' ;
}
$currlang = current_language ();
2010-04-14 09:45:49 +00:00
$langs = get_string_manager () -> get_list_of_translations ();
2009-12-30 15:19:55 +00:00
2009-12-29 17:26:29 +00:00
if ( count ( $langs ) < 2 ) {
return '' ;
}
2010-02-09 17:39:13 +00:00
$s = new single_select ( $this -> page -> url , 'lang' , $langs , $currlang , null );
$s -> label = get_accesshide ( get_string ( 'language' ));
$s -> class = 'langmenu' ;
return $this -> render ( $s );
2009-12-29 17:26:29 +00:00
}
2009-08-10 06:22:04 +00:00
/**
* Output the row of editing icons for a block , as defined by the controls array .
2012-01-05 13:28:08 +13:00
*
2012-02-14 18:24:09 +13:00
* @ param array $controls an array like { @ link block_contents :: $controls } .
2013-07-03 13:46:01 +12:00
* @ param string $blockid The ID given to the block .
2012-01-05 13:28:08 +13:00
* @ return string HTML fragment .
2009-08-10 06:22:04 +00:00
*/
2013-07-03 13:46:01 +12:00
public function block_controls ( $actions , $blockid = null ) {
2013-07-18 15:09:12 +12:00
global $CFG ;
2013-07-03 13:46:01 +12:00
if ( empty ( $actions )) {
return '' ;
}
2013-07-08 11:44:32 +12:00
$menu = new action_menu ( $actions );
2013-07-03 13:46:01 +12:00
if ( $blockid !== null ) {
$menu -> set_owner_selector ( '#' . $blockid );
}
2013-10-31 15:54:16 +08:00
$menu -> set_constraint ( '.block-region' );
2013-07-03 13:46:01 +12:00
$menu -> attributes [ 'class' ] .= ' block-control-actions commands' ;
return $this -> render ( $menu );
}
/**
* Renders an action menu component .
*
2013-07-18 10:42:11 +12:00
* ARIA references :
* - http :// www . w3 . org / WAI / GL / wiki / Using_ARIA_menus
* - http :// stackoverflow . com / questions / 12279113 / recommended - wai - aria - implementation - for - navigation - bar - menu
*
2013-07-03 13:46:01 +12:00
* @ param action_menu $menu
* @ return string HTML
*/
public function render_action_menu ( action_menu $menu ) {
2016-09-06 20:28:41 +08:00
$context = $menu -> export_for_template ( $this );
return $this -> render_from_template ( 'core/action_menu' , $context );
2009-08-10 06:22:04 +00:00
}
2013-07-08 11:44:32 +12:00
/**
2013-07-18 10:42:11 +12:00
* Renders an action_menu_link item .
2013-07-08 11:44:32 +12:00
*
2013-07-18 10:42:11 +12:00
* @ param action_menu_link $action
2013-07-08 11:44:32 +12:00
* @ return string HTML fragment
*/
2013-07-18 10:42:11 +12:00
protected function render_action_menu_link ( action_menu_link $action ) {
2016-09-06 20:28:41 +08:00
return $this -> render_from_template ( 'core/action_menu_link' , $action -> export_for_template ( $this ));
2013-07-08 11:44:32 +12:00
}
2013-10-30 16:29:56 +08:00
/**
* Renders a primary action_menu_filler item .
*
* @ param action_menu_link_filler $action
* @ return string HTML fragment
*/
protected function render_action_menu_filler ( action_menu_filler $action ) {
return html_writer :: span ( ' ' , 'filler' );
}
2013-07-08 11:44:32 +12:00
/**
2013-07-18 10:42:11 +12:00
* Renders a primary action_menu_link item .
2013-07-08 11:44:32 +12:00
*
2013-07-18 10:42:11 +12:00
* @ param action_menu_link_primary $action
2013-07-08 11:44:32 +12:00
* @ return string HTML fragment
*/
2013-07-18 10:42:11 +12:00
protected function render_action_menu_link_primary ( action_menu_link_primary $action ) {
return $this -> render_action_menu_link ( $action );
2013-07-08 11:44:32 +12:00
}
/**
2013-07-18 10:42:11 +12:00
* Renders a secondary action_menu_link item .
2013-07-08 11:44:32 +12:00
*
2013-07-18 10:42:11 +12:00
* @ param action_menu_link_secondary $action
2013-07-08 11:44:32 +12:00
* @ return string HTML fragment
*/
2013-07-18 10:42:11 +12:00
protected function render_action_menu_link_secondary ( action_menu_link_secondary $action ) {
return $this -> render_action_menu_link ( $action );
2013-07-08 11:44:32 +12:00
}
2009-08-10 06:22:04 +00:00
/**
* Prints a nice side block with an optional header .
*
* The content is described
2012-02-14 18:24:09 +13:00
* by a { @ link core_renderer :: block_contents } object .
2009-08-10 06:22:04 +00:00
*
2010-08-17 08:31:20 +00:00
* < div id = " inst { $instanceid } " class = " block_ { $blockname } block " >
* < div class = " header " ></ div >
* < div class = " content " >
* ... CONTENT ...
* < div class = " footer " >
* </ div >
* </ div >
* < div class = " annotation " >
* </ div >
* </ div >
*
2009-08-10 06:22:04 +00:00
* @ param block_contents $bc HTML for the content
* @ param string $region the region the block is appearing in .
* @ return string the HTML to be output .
*/
2012-01-05 13:28:08 +13:00
public function block ( block_contents $bc , $region ) {
2009-08-10 06:22:04 +00:00
$bc = clone ( $bc ); // Avoid messing up the object passed in.
2010-02-17 18:36:26 +00:00
if ( empty ( $bc -> blockinstanceid ) || ! strip_tags ( $bc -> title )) {
$bc -> collapsible = block_contents :: NOT_HIDEABLE ;
}
2013-06-20 18:12:28 +12:00
if ( ! empty ( $bc -> blockinstanceid )) {
$bc -> attributes [ 'data-instanceid' ] = $bc -> blockinstanceid ;
}
2012-10-11 10:41:05 +08:00
$skiptitle = strip_tags ( $bc -> title );
if ( $bc -> blockinstanceid && ! empty ( $skiptitle )) {
$bc -> attributes [ 'aria-labelledby' ] = 'instance-' . $bc -> blockinstanceid . '-header' ;
} else if ( ! empty ( $bc -> arialabel )) {
$bc -> attributes [ 'aria-label' ] = $bc -> arialabel ;
}
2013-06-20 18:12:28 +12:00
if ( $bc -> dockable ) {
$bc -> attributes [ 'data-dockable' ] = 1 ;
}
2010-02-17 18:36:26 +00:00
if ( $bc -> collapsible == block_contents :: HIDDEN ) {
$bc -> add_class ( 'hidden' );
}
if ( ! empty ( $bc -> controls )) {
$bc -> add_class ( 'block_with_controls' );
}
2009-08-10 06:22:04 +00:00
2012-10-11 10:41:05 +08:00
2009-08-10 06:22:04 +00:00
if ( empty ( $skiptitle )) {
$output = '' ;
$skipdest = '' ;
} else {
2015-11-05 16:49:24 +08:00
$output = html_writer :: link ( '#sb-' . $bc -> skipid , get_string ( 'skipa' , 'access' , $skiptitle ),
array ( 'class' => 'skip skip-block' , 'id' => 'fsb-' . $bc -> skipid ));
2015-08-19 11:05:07 -05:00
$skipdest = html_writer :: span ( '' , 'skip-block-to' ,
2015-11-05 16:49:24 +08:00
array ( 'id' => 'sb-' . $bc -> skipid ));
2009-08-10 06:22:04 +00:00
}
2010-05-19 08:05:36 +00:00
2010-01-13 17:13:52 +00:00
$output .= html_writer :: start_tag ( 'div' , $bc -> attributes );
2009-08-10 06:22:04 +00:00
2010-08-30 06:57:05 +00:00
$output .= $this -> block_header ( $bc );
$output .= $this -> block_content ( $bc );
$output .= html_writer :: end_tag ( 'div' );
$output .= $this -> block_annotation ( $bc );
$output .= $skipdest ;
$this -> init_block_hider_js ( $bc );
return $output ;
}
/**
* Produces a header for a block
2010-09-07 10:06:57 +00:00
*
2010-08-30 06:57:05 +00:00
* @ param block_contents $bc
* @ return string
*/
protected function block_header ( block_contents $bc ) {
2009-08-10 06:22:04 +00:00
$title = '' ;
if ( $bc -> title ) {
2012-10-11 10:41:05 +08:00
$attributes = array ();
if ( $bc -> blockinstanceid ) {
$attributes [ 'id' ] = 'instance-' . $bc -> blockinstanceid . '-header' ;
}
$title = html_writer :: tag ( 'h2' , $bc -> title , $attributes );
2009-08-10 06:22:04 +00:00
}
2013-07-03 13:46:01 +12:00
$blockid = null ;
if ( isset ( $bc -> attributes [ 'id' ])) {
$blockid = $bc -> attributes [ 'id' ];
}
$controlshtml = $this -> block_controls ( $bc -> controls , $blockid );
2010-08-30 06:57:05 +00:00
$output = '' ;
2009-08-10 06:22:04 +00:00
if ( $title || $controlshtml ) {
2010-02-24 08:12:17 +00:00
$output .= html_writer :: tag ( 'div' , html_writer :: tag ( 'div' , html_writer :: tag ( 'div' , '' , array ( 'class' => 'block_action' )) . $title . $controlshtml , array ( 'class' => 'title' )), array ( 'class' => 'header' ));
2009-08-10 06:22:04 +00:00
}
2010-08-30 06:57:05 +00:00
return $output ;
}
2009-08-10 06:22:04 +00:00
2010-08-30 06:57:05 +00:00
/**
* Produces the content area for a block
*
* @ param block_contents $bc
* @ return string
*/
protected function block_content ( block_contents $bc ) {
$output = html_writer :: start_tag ( 'div' , array ( 'class' => 'content' ));
if ( ! $bc -> title && ! $this -> block_controls ( $bc -> controls )) {
2010-02-24 08:12:17 +00:00
$output .= html_writer :: tag ( 'div' , '' , array ( 'class' => 'block_action notitle' ));
}
2009-08-10 06:22:04 +00:00
$output .= $bc -> content ;
2010-08-30 06:57:05 +00:00
$output .= $this -> block_footer ( $bc );
$output .= html_writer :: end_tag ( 'div' );
2010-09-07 10:06:57 +00:00
2010-08-30 06:57:05 +00:00
return $output ;
}
2009-08-10 06:22:04 +00:00
2010-08-30 06:57:05 +00:00
/**
* Produces the footer for a block
*
* @ param block_contents $bc
* @ return string
*/
protected function block_footer ( block_contents $bc ) {
$output = '' ;
2009-08-10 06:22:04 +00:00
if ( $bc -> footer ) {
2010-02-18 18:15:56 +00:00
$output .= html_writer :: tag ( 'div' , $bc -> footer , array ( 'class' => 'footer' ));
2009-08-10 06:22:04 +00:00
}
2010-08-30 06:57:05 +00:00
return $output ;
}
2009-08-10 06:22:04 +00:00
2010-08-30 06:57:05 +00:00
/**
* Produces the annotation for a block
*
* @ param block_contents $bc
* @ return string
*/
protected function block_annotation ( block_contents $bc ) {
$output = '' ;
2009-08-10 06:22:04 +00:00
if ( $bc -> annotation ) {
2010-02-18 18:15:56 +00:00
$output .= html_writer :: tag ( 'div' , $bc -> annotation , array ( 'class' => 'blockannotation' ));
2009-08-10 06:22:04 +00:00
}
return $output ;
}
/**
* Calls the JS require function to hide a block .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param block_contents $bc A block_contents object
*/
2010-02-17 18:36:26 +00:00
protected function init_block_hider_js ( block_contents $bc ) {
if ( ! empty ( $bc -> attributes [ 'id' ]) and $bc -> collapsible != block_contents :: NOT_HIDEABLE ) {
2010-08-17 08:31:20 +00:00
$config = new stdClass ;
$config -> id = $bc -> attributes [ 'id' ];
$config -> title = strip_tags ( $bc -> title );
$config -> preference = 'block' . $bc -> blockinstanceid . 'hidden' ;
$config -> tooltipVisible = get_string ( 'hideblocka' , 'access' , $config -> title );
$config -> tooltipHidden = get_string ( 'showblocka' , 'access' , $config -> title );
$this -> page -> requires -> js_init_call ( 'M.util.init_block_hider' , array ( $config ));
user_preference_allow_ajax_update ( $config -> preference , PARAM_BOOL );
2009-08-10 06:22:04 +00:00
}
}
/**
* Render the contents of a block_list .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param array $icons the icon for each item .
* @ param array $items the content of each item .
* @ return string HTML
*/
public function list_block_contents ( $icons , $items ) {
$row = 0 ;
$lis = array ();
foreach ( $items as $key => $string ) {
2010-01-13 17:13:52 +00:00
$item = html_writer :: start_tag ( 'li' , array ( 'class' => 'r' . $row ));
2009-08-25 19:09:04 +00:00
if ( ! empty ( $icons [ $key ])) { //test if the content has an assigned icon
2010-02-18 18:15:56 +00:00
$item .= html_writer :: tag ( 'div' , $icons [ $key ], array ( 'class' => 'icon column c0' ));
2009-08-10 06:22:04 +00:00
}
2010-02-18 18:15:56 +00:00
$item .= html_writer :: tag ( 'div' , $string , array ( 'class' => 'column c1' ));
2010-01-13 17:13:52 +00:00
$item .= html_writer :: end_tag ( 'li' );
2009-08-10 06:22:04 +00:00
$lis [] = $item ;
$row = 1 - $row ; // Flip even/odd.
}
2010-10-25 07:32:51 +00:00
return html_writer :: tag ( 'ul' , implode ( " \n " , $lis ), array ( 'class' => 'unlist' ));
2009-08-10 06:22:04 +00:00
}
/**
* Output all the blocks in a particular region .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param string $region the name of a region on this page .
* @ return string the HTML to be output .
*/
public function blocks_for_region ( $region ) {
$blockcontents = $this -> page -> blocks -> get_content_for_region ( $region , $this );
2013-03-11 14:56:35 +08:00
$blocks = $this -> page -> blocks -> get_blocks_for_region ( $region );
$lastblock = null ;
$zones = array ();
foreach ( $blocks as $block ) {
$zones [] = $block -> title ;
}
2009-08-10 06:22:04 +00:00
$output = '' ;
2013-03-11 14:56:35 +08:00
2009-08-10 06:22:04 +00:00
foreach ( $blockcontents as $bc ) {
if ( $bc instanceof block_contents ) {
$output .= $this -> block ( $bc , $region );
2013-03-11 14:56:35 +08:00
$lastblock = $bc -> title ;
2009-08-10 06:22:04 +00:00
} else if ( $bc instanceof block_move_target ) {
2014-01-06 12:36:50 +01:00
$output .= $this -> block_move_target ( $bc , $zones , $lastblock , $region );
2009-08-10 06:22:04 +00:00
} else {
throw new coding_exception ( 'Unexpected type of thing (' . get_class ( $bc ) . ') found in list of block contents.' );
}
}
return $output ;
}
/**
* Output a place where the block that is currently being moved can be dropped .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param block_move_target $target with the necessary details .
2013-03-11 14:56:35 +08:00
* @ param array $zones array of areas where the block can be moved to
* @ param string $previous the block located before the area currently being rendered .
2014-01-06 12:36:50 +01:00
* @ param string $region the name of the region
2009-08-10 06:22:04 +00:00
* @ return string the HTML to be output .
*/
2014-01-06 12:36:50 +01:00
public function block_move_target ( $target , $zones , $previous , $region ) {
2013-03-27 10:16:09 +08:00
if ( $previous == null ) {
2014-01-06 12:36:50 +01:00
if ( empty ( $zones )) {
// There are no zones, probably because there are no blocks.
$regions = $this -> page -> theme -> get_all_block_regions ();
$position = get_string ( 'moveblockinregion' , 'block' , $regions [ $region ]);
} else {
$position = get_string ( 'moveblockbefore' , 'block' , $zones [ 0 ]);
}
2013-03-11 14:56:35 +08:00
} else {
$position = get_string ( 'moveblockafter' , 'block' , $previous );
}
return html_writer :: tag ( 'a' , html_writer :: tag ( 'span' , $position , array ( 'class' => 'accesshide' )), array ( 'href' => $target -> url , 'class' => 'blockmovetarget' ));
2009-08-10 06:22:04 +00:00
}
2010-01-14 22:40:33 +00:00
/**
2010-05-22 14:43:46 +00:00
* Renders a special html link with attached action
2010-01-14 22:40:33 +00:00
*
2013-04-15 11:05:46 +10:00
* Theme developers : DO NOT OVERRIDE ! Please override function
* { @ link core_renderer :: render_action_link ()} instead .
*
2010-01-14 22:40:33 +00:00
* @ param string | moodle_url $url
* @ param string $text HTML fragment
* @ param component_action $action
2010-01-14 22:51:10 +00:00
* @ param array $attributes associative array of html link attributes + disabled
2013-07-05 10:45:05 +12:00
* @ param pix_icon optional pix icon to render with the link
2012-01-05 13:28:08 +13:00
* @ return string HTML fragment
2010-01-14 22:40:33 +00:00
*/
2013-07-05 10:45:05 +12:00
public function action_link ( $url , $text , component_action $action = null , array $attributes = null , $icon = null ) {
2010-01-14 22:40:33 +00:00
if ( ! ( $url instanceof moodle_url )) {
$url = new moodle_url ( $url );
}
2013-07-05 10:45:05 +12:00
$link = new action_link ( $url , $text , $action , $attributes , $icon );
2010-01-14 22:40:33 +00:00
2010-01-15 09:01:59 +00:00
return $this -> render ( $link );
2010-01-14 22:40:33 +00:00
}
/**
2012-01-05 13:28:08 +13:00
* Renders an action_link object .
*
* The provided link is renderer and the HTML returned . At the same time the
2012-02-14 18:24:09 +13:00
* associated actions are setup in JS by { @ link core_renderer :: add_action_handler ()}
2012-01-05 13:28:08 +13:00
*
2010-01-14 22:40:33 +00:00
* @ param action_link $link
* @ return string HTML fragment
*/
protected function render_action_link ( action_link $link ) {
2016-09-06 20:20:35 +08:00
return $this -> render_from_template ( 'core/action_link' , $link -> export_for_template ( $this ));
2010-01-14 22:40:33 +00:00
}
2010-02-16 16:24:49 +00:00
/**
2012-01-05 13:28:08 +13:00
* Renders an action_icon .
*
2012-02-14 18:24:09 +13:00
* This function uses the { @ link core_renderer :: action_link ()} method for the
2012-01-05 13:28:08 +13:00
* most part . What it does different is prepare the icon as HTML and use it
* as the link text .
2010-02-16 16:24:49 +00:00
*
2013-04-15 11:05:46 +10:00
* Theme developers : If you want to change how action links and / or icons are rendered ,
* consider overriding function { @ link core_renderer :: render_action_link ()} and
* { @ link core_renderer :: render_pix_icon ()} .
*
2010-02-16 16:24:49 +00:00
* @ param string | moodle_url $url A string URL or moodel_url
* @ param pix_icon $pixicon
* @ param component_action $action
* @ param array $attributes associative array of html link attributes + disabled
* @ param bool $linktext show title next to image in link
* @ return string HTML fragment
*/
public function action_icon ( $url , pix_icon $pixicon , component_action $action = null , array $attributes = null , $linktext = false ) {
if ( ! ( $url instanceof moodle_url )) {
$url = new moodle_url ( $url );
}
$attributes = ( array ) $attributes ;
2010-02-24 06:08:52 +00:00
if ( empty ( $attributes [ 'class' ])) {
2010-02-16 16:24:49 +00:00
// let ppl override the class via $options
$attributes [ 'class' ] = 'action-icon' ;
}
$icon = $this -> render ( $pixicon );
if ( $linktext ) {
$text = $pixicon -> attributes [ 'alt' ];
} else {
$text = '' ;
}
return $this -> action_link ( $url , $text . $icon , $action , $attributes );
}
2009-08-10 06:22:04 +00:00
/**
2009-09-01 14:15:49 +00:00
* Print a message along with button choices for Continue / Cancel
*
2010-02-11 10:32:39 +00:00
* If a string or moodle_url is given instead of a single_button , method defaults to post .
2009-09-01 14:15:49 +00:00
*
2009-08-10 06:22:04 +00:00
* @ param string $message The question to ask the user
2010-01-14 19:18:04 +00:00
* @ param single_button | moodle_url | string $continue The single_button component representing the Continue answer . Can also be a moodle_url or string URL
* @ param single_button | moodle_url | string $cancel The single_button component representing the Cancel answer . Can also be a moodle_url or string URL
2009-08-10 06:22:04 +00:00
* @ return string HTML fragment
*/
public function confirm ( $message , $continue , $cancel ) {
2010-01-14 22:44:24 +00:00
if ( $continue instanceof single_button ) {
2010-01-14 22:51:10 +00:00
// ok
2010-01-14 22:44:24 +00:00
} else if ( is_string ( $continue )) {
$continue = new single_button ( new moodle_url ( $continue ), get_string ( 'continue' ), 'post' );
} else if ( $continue instanceof moodle_url ) {
2010-01-03 17:20:49 +00:00
$continue = new single_button ( $continue , get_string ( 'continue' ), 'post' );
2009-08-10 06:22:04 +00:00
} else {
2010-02-11 10:32:39 +00:00
throw new coding_exception ( 'The continue param to $OUTPUT->confirm() must be either a URL (string/moodle_url) or a single_button instance.' );
2009-08-10 06:22:04 +00:00
}
2010-01-14 22:44:24 +00:00
if ( $cancel instanceof single_button ) {
2010-01-14 22:51:10 +00:00
// ok
2010-01-14 22:44:24 +00:00
} else if ( is_string ( $cancel )) {
$cancel = new single_button ( new moodle_url ( $cancel ), get_string ( 'cancel' ), 'get' );
} else if ( $cancel instanceof moodle_url ) {
2010-01-03 17:20:49 +00:00
$cancel = new single_button ( $cancel , get_string ( 'cancel' ), 'get' );
2009-08-10 06:22:04 +00:00
} else {
2010-02-11 10:32:39 +00:00
throw new coding_exception ( 'The cancel param to $OUTPUT->confirm() must be either a URL (string/moodle_url) or a single_button instance.' );
2009-08-10 06:22:04 +00:00
}
$output = $this -> box_start ( 'generalbox' , 'notice' );
2010-02-18 18:15:56 +00:00
$output .= html_writer :: tag ( 'p' , $message );
$output .= html_writer :: tag ( 'div' , $this -> render ( $continue ) . $this -> render ( $cancel ), array ( 'class' => 'buttons' ));
2009-08-10 06:22:04 +00:00
$output .= $this -> box_end ();
return $output ;
}
2010-01-03 10:28:29 +00:00
/**
2010-01-14 19:18:04 +00:00
* Returns a form with a single button .
2010-01-03 10:28:29 +00:00
*
2013-04-15 11:05:46 +10:00
* Theme developers : DO NOT OVERRIDE ! Please override function
* { @ link core_renderer :: render_single_button ()} instead .
*
2010-01-14 19:18:04 +00:00
* @ param string | moodle_url $url
2010-01-03 10:28:29 +00:00
* @ param string $label button text
* @ param string $method get or post submit method
2010-01-14 19:18:04 +00:00
* @ param array $options associative array { disabled , title , etc . }
2010-01-03 10:28:29 +00:00
* @ return string HTML fragment
*/
2010-01-14 19:18:04 +00:00
public function single_button ( $url , $label , $method = 'post' , array $options = null ) {
2010-01-14 22:40:33 +00:00
if ( ! ( $url instanceof moodle_url )) {
$url = new moodle_url ( $url );
2010-01-14 19:18:04 +00:00
}
2010-01-14 22:40:33 +00:00
$button = new single_button ( $url , $label , $method );
2010-01-14 19:18:04 +00:00
foreach (( array ) $options as $key => $value ) {
if ( array_key_exists ( $key , $button )) {
$button -> $key = $value ;
}
2010-01-03 10:28:29 +00:00
}
2010-01-14 19:18:04 +00:00
return $this -> render ( $button );
2010-01-03 10:28:29 +00:00
}
2009-08-10 06:22:04 +00:00
/**
2012-01-05 13:28:08 +13:00
* Renders a single button widget .
*
* This will return HTML to display a form containing a single button .
*
2010-01-14 19:18:04 +00:00
* @ param single_button $button
2009-08-10 06:22:04 +00:00
* @ return string HTML fragment
*/
2010-01-14 19:18:04 +00:00
protected function render_single_button ( single_button $button ) {
$attributes = array ( 'type' => 'submit' ,
'value' => $button -> label ,
2010-02-03 17:20:01 +00:00
'disabled' => $button -> disabled ? 'disabled' : null ,
2010-01-14 19:18:04 +00:00
'title' => $button -> tooltip );
if ( $button -> actions ) {
$id = html_writer :: random_id ( 'single_button' );
$attributes [ 'id' ] = $id ;
foreach ( $button -> actions as $action ) {
2010-02-11 15:44:06 +00:00
$this -> add_action_handler ( $action , $id );
2010-01-14 19:18:04 +00:00
}
2009-08-10 06:22:04 +00:00
}
2010-01-14 19:18:04 +00:00
// first the input element
$output = html_writer :: empty_tag ( 'input' , $attributes );
2009-08-10 06:22:04 +00:00
2010-01-14 19:18:04 +00:00
// then hidden fields
$params = $button -> url -> params ();
if ( $button -> method === 'post' ) {
$params [ 'sesskey' ] = sesskey ();
}
foreach ( $params as $var => $val ) {
$output .= html_writer :: empty_tag ( 'input' , array ( 'type' => 'hidden' , 'name' => $var , 'value' => $val ));
}
2009-08-10 06:22:04 +00:00
2010-01-14 19:18:04 +00:00
// then div wrapper for xhtml strictness
2010-02-18 18:15:56 +00:00
$output = html_writer :: tag ( 'div' , $output );
2009-08-10 06:22:04 +00:00
2010-01-14 19:18:04 +00:00
// now the form itself around it
2011-03-24 14:25:40 +01:00
if ( $button -> method === 'get' ) {
$url = $button -> url -> out_omit_querystring ( true ); // url without params, the anchor part allowed
} else {
$url = $button -> url -> out_omit_querystring (); // url without params, the anchor part not allowed
}
2010-01-16 15:39:56 +00:00
if ( $url === '' ) {
$url = '#' ; // there has to be always some action
}
2010-01-14 19:18:04 +00:00
$attributes = array ( 'method' => $button -> method ,
2010-01-16 15:39:56 +00:00
'action' => $url ,
2010-01-14 19:18:04 +00:00
'id' => $button -> formid );
2010-02-18 18:15:56 +00:00
$output = html_writer :: tag ( 'form' , $output , $attributes );
2009-08-10 06:22:04 +00:00
2010-01-14 19:18:04 +00:00
// and finally one more wrapper with class
2010-02-18 18:15:56 +00:00
return html_writer :: tag ( 'div' , $output , array ( 'class' => $button -> class ));
2009-08-10 06:22:04 +00:00
}
2010-02-09 17:39:13 +00:00
/**
2010-02-10 10:23:09 +00:00
* Returns a form with a single select widget .
2012-01-05 13:28:08 +13:00
*
2013-04-15 11:05:46 +10:00
* Theme developers : DO NOT OVERRIDE ! Please override function
* { @ link core_renderer :: render_single_select ()} instead .
*
2010-02-09 17:39:13 +00:00
* @ param moodle_url $url form action target , includes hidden fields
* @ param string $name name of selection field - the changing parameter in url
* @ param array $options list of options
* @ param string $selected selected element
* @ param array $nothing
2010-02-10 09:37:50 +00:00
* @ param string $formid
2015-04-09 11:12:16 +12:00
* @ param array $attributes other attributes for the single select
2010-02-09 17:39:13 +00:00
* @ return string HTML fragment
*/
2015-04-09 11:12:16 +12:00
public function single_select ( $url , $name , array $options , $selected = '' ,
$nothing = array ( '' => 'choosedots' ), $formid = null , $attributes = array ()) {
2010-02-09 17:39:13 +00:00
if ( ! ( $url instanceof moodle_url )) {
$url = new moodle_url ( $url );
}
2010-02-10 09:37:50 +00:00
$select = new single_select ( $url , $name , $options , $selected , $nothing , $formid );
2010-02-09 17:39:13 +00:00
2015-04-09 11:12:16 +12:00
if ( array_key_exists ( 'label' , $attributes )) {
$select -> set_label ( $attributes [ 'label' ]);
unset ( $attributes [ 'label' ]);
}
$select -> attributes = $attributes ;
2010-02-09 17:39:13 +00:00
return $this -> render ( $select );
}
2016-04-02 16:10:29 +11:00
/**
* Returns a dataformat selection and download form
*
* @ param string $label A text label
* @ param moodle_url | string $base The download page url
* @ param string $name The query param which will hold the type of the download
* @ param array $params Extra params sent to the download page
* @ return string HTML fragment
*/
public function download_dataformat_selector ( $label , $base , $name = 'dataformat' , $params = array ()) {
$formats = core_plugin_manager :: instance () -> get_plugins_of_type ( 'dataformat' );
$options = array ();
foreach ( $formats as $format ) {
if ( $format -> is_enabled ()) {
$options [] = array (
'value' => $format -> name ,
2016-04-21 14:48:01 +08:00
'label' => get_string ( 'dataformat' , $format -> component ),
2016-04-02 16:10:29 +11:00
);
}
}
$hiddenparams = array ();
foreach ( $params as $key => $value ) {
$hiddenparams [] = array (
'name' => $key ,
'value' => $value ,
);
}
$data = array (
'label' => $label ,
'base' => $base ,
'name' => $name ,
'params' => $hiddenparams ,
'options' => $options ,
'sesskey' => sesskey (),
'submit' => get_string ( 'download' ),
);
return $this -> render_from_template ( 'core/dataformat_selector' , $data );
}
2010-02-09 17:39:13 +00:00
/**
* Internal implementation of single_select rendering
2012-01-05 13:28:08 +13:00
*
2010-02-09 17:39:13 +00:00
* @ param single_select $select
* @ return string HTML fragment
*/
protected function render_single_select ( single_select $select ) {
$select = clone ( $select );
if ( empty ( $select -> formid )) {
$select -> formid = html_writer :: random_id ( 'single_select_f' );
}
$output = '' ;
$params = $select -> url -> params ();
if ( $select -> method === 'post' ) {
$params [ 'sesskey' ] = sesskey ();
}
foreach ( $params as $name => $value ) {
$output .= html_writer :: empty_tag ( 'input' , array ( 'type' => 'hidden' , 'name' => $name , 'value' => $value ));
}
if ( empty ( $select -> attributes [ 'id' ])) {
$select -> attributes [ 'id' ] = html_writer :: random_id ( 'single_select' );
}
2010-02-10 09:46:44 +00:00
if ( $select -> disabled ) {
$select -> attributes [ 'disabled' ] = 'disabled' ;
}
2010-02-10 10:22:25 +00:00
2010-02-09 17:39:13 +00:00
if ( $select -> tooltip ) {
$select -> attributes [ 'title' ] = $select -> tooltip ;
}
2012-09-21 15:17:22 +01:00
$select -> attributes [ 'class' ] = 'autosubmit' ;
if ( $select -> class ) {
$select -> attributes [ 'class' ] .= ' ' . $select -> class ;
}
2010-02-09 17:39:13 +00:00
if ( $select -> label ) {
2012-07-31 12:07:16 +08:00
$output .= html_writer :: label ( $select -> label , $select -> attributes [ 'id' ], false , $select -> labelattributes );
2010-02-09 17:39:13 +00:00
}
if ( $select -> helpicon instanceof help_icon ) {
$output .= $this -> render ( $select -> helpicon );
}
$output .= html_writer :: select ( $select -> options , $select -> name , $select -> selected , $select -> nothing , $select -> attributes );
$go = html_writer :: empty_tag ( 'input' , array ( 'type' => 'submit' , 'value' => get_string ( 'go' )));
2012-11-19 20:23:42 +08:00
$output .= html_writer :: tag ( 'noscript' , html_writer :: tag ( 'div' , $go ), array ( 'class' => 'inline' ));
2010-02-09 17:39:13 +00:00
$nothing = empty ( $select -> nothing ) ? false : key ( $select -> nothing );
2012-09-21 15:17:22 +01:00
$this -> page -> requires -> yui_module ( 'moodle-core-formautosubmit' ,
'M.core.init_formautosubmit' ,
array ( array ( 'selectid' => $select -> attributes [ 'id' ], 'nothing' => $nothing ))
);
2010-02-09 17:39:13 +00:00
// then div wrapper for xhtml strictness
2010-02-18 18:15:56 +00:00
$output = html_writer :: tag ( 'div' , $output );
2010-02-09 17:39:13 +00:00
// now the form itself around it
2011-03-24 14:25:40 +01:00
if ( $select -> method === 'get' ) {
$url = $select -> url -> out_omit_querystring ( true ); // url without params, the anchor part allowed
} else {
$url = $select -> url -> out_omit_querystring (); // url without params, the anchor part not allowed
}
2010-02-09 17:39:13 +00:00
$formattributes = array ( 'method' => $select -> method ,
2011-03-24 14:25:40 +01:00
'action' => $url ,
2010-02-09 17:39:13 +00:00
'id' => $select -> formid );
2010-02-18 18:15:56 +00:00
$output = html_writer :: tag ( 'form' , $output , $formattributes );
2010-02-10 10:22:25 +00:00
// and finally one more wrapper with class
2010-02-18 18:15:56 +00:00
return html_writer :: tag ( 'div' , $output , array ( 'class' => $select -> class ));
2010-02-10 10:22:25 +00:00
}
/**
2010-02-10 10:23:09 +00:00
* Returns a form with a url select widget .
2012-01-05 13:28:08 +13:00
*
2013-04-15 11:05:46 +10:00
* Theme developers : DO NOT OVERRIDE ! Please override function
* { @ link core_renderer :: render_url_select ()} instead .
*
2010-02-10 10:22:25 +00:00
* @ param array $urls list of urls - array ( '/course/view.php?id=1' => 'Frontpage' , .... )
* @ param string $selected selected element
* @ param array $nothing
* @ param string $formid
* @ return string HTML fragment
*/
2012-01-05 13:28:08 +13:00
public function url_select ( array $urls , $selected , $nothing = array ( '' => 'choosedots' ), $formid = null ) {
2010-02-10 10:22:25 +00:00
$select = new url_select ( $urls , $selected , $nothing , $formid );
return $this -> render ( $select );
}
/**
2010-02-10 10:23:09 +00:00
* Internal implementation of url_select rendering
2012-01-05 13:28:08 +13:00
*
* @ param url_select $select
2010-02-10 10:22:25 +00:00
* @ return string HTML fragment
*/
protected function render_url_select ( url_select $select ) {
2010-05-28 15:47:26 +00:00
global $CFG ;
2010-02-10 10:22:25 +00:00
$select = clone ( $select );
if ( empty ( $select -> formid )) {
$select -> formid = html_writer :: random_id ( 'url_select_f' );
}
if ( empty ( $select -> attributes [ 'id' ])) {
$select -> attributes [ 'id' ] = html_writer :: random_id ( 'url_select' );
}
if ( $select -> disabled ) {
$select -> attributes [ 'disabled' ] = 'disabled' ;
}
if ( $select -> tooltip ) {
$select -> attributes [ 'title' ] = $select -> tooltip ;
}
$output = '' ;
if ( $select -> label ) {
2012-07-31 12:07:16 +08:00
$output .= html_writer :: label ( $select -> label , $select -> attributes [ 'id' ], false , $select -> labelattributes );
2010-02-10 10:22:25 +00:00
}
2012-11-30 09:54:37 +00:00
$classes = array ();
if ( ! $select -> showbutton ) {
$classes [] = 'autosubmit' ;
}
2012-09-21 15:17:22 +01:00
if ( $select -> class ) {
2012-11-30 09:54:37 +00:00
$classes [] = $select -> class ;
}
if ( count ( $classes )) {
$select -> attributes [ 'class' ] = implode ( ' ' , $classes );
2012-09-21 15:17:22 +01:00
}
2010-02-10 10:22:25 +00:00
if ( $select -> helpicon instanceof help_icon ) {
$output .= $this -> render ( $select -> helpicon );
}
2010-05-31 15:30:45 +00:00
// For security reasons, the script course/jumpto.php requires URL starting with '/'. To keep
// backward compatibility, we are removing heading $CFG->wwwroot from URLs here.
2010-05-28 15:47:26 +00:00
$urls = array ();
foreach ( $select -> urls as $k => $v ) {
2010-05-31 15:30:45 +00:00
if ( is_array ( $v )) {
// optgroup structure
foreach ( $v as $optgrouptitle => $optgroupoptions ) {
foreach ( $optgroupoptions as $optionurl => $optiontitle ) {
if ( empty ( $optionurl )) {
$safeoptionurl = '' ;
} else if ( strpos ( $optionurl , $CFG -> wwwroot . '/' ) === 0 ) {
// debugging('URLs passed to url_select should be in local relative form - please fix the code.', DEBUG_DEVELOPER);
$safeoptionurl = str_replace ( $CFG -> wwwroot , '' , $optionurl );
} else if ( strpos ( $optionurl , '/' ) !== 0 ) {
debugging ( " Invalid url_select urls parameter inside optgroup: url ' $optionurl ' is not local relative url! " );
continue ;
} else {
$safeoptionurl = $optionurl ;
}
$urls [ $k ][ $optgrouptitle ][ $safeoptionurl ] = $optiontitle ;
}
}
} else {
// plain list structure
if ( empty ( $k )) {
// nothing selected option
} else if ( strpos ( $k , $CFG -> wwwroot . '/' ) === 0 ) {
$k = str_replace ( $CFG -> wwwroot , '' , $k );
} else if ( strpos ( $k , '/' ) !== 0 ) {
debugging ( " Invalid url_select urls parameter: url ' $k ' is not local relative url! " );
continue ;
}
$urls [ $k ] = $v ;
}
}
$selected = $select -> selected ;
if ( ! empty ( $selected )) {
if ( strpos ( $select -> selected , $CFG -> wwwroot . '/' ) === 0 ) {
$selected = str_replace ( $CFG -> wwwroot , '' , $selected );
} else if ( strpos ( $selected , '/' ) !== 0 ) {
debugging ( " Invalid value of parameter 'selected': url ' $selected ' is not local relative url! " );
2010-05-28 15:47:26 +00:00
}
}
2010-02-10 10:22:25 +00:00
$output .= html_writer :: empty_tag ( 'input' , array ( 'type' => 'hidden' , 'name' => 'sesskey' , 'value' => sesskey ()));
2010-05-31 15:30:45 +00:00
$output .= html_writer :: select ( $urls , 'jump' , $selected , $select -> nothing , $select -> attributes );
2010-02-10 10:22:25 +00:00
2010-11-15 10:41:26 +00:00
if ( ! $select -> showbutton ) {
$go = html_writer :: empty_tag ( 'input' , array ( 'type' => 'submit' , 'value' => get_string ( 'go' )));
2012-11-19 20:23:42 +08:00
$output .= html_writer :: tag ( 'noscript' , html_writer :: tag ( 'div' , $go ), array ( 'class' => 'inline' ));
2010-11-15 10:41:26 +00:00
$nothing = empty ( $select -> nothing ) ? false : key ( $select -> nothing );
2012-09-21 15:17:22 +01:00
$this -> page -> requires -> yui_module ( 'moodle-core-formautosubmit' ,
'M.core.init_formautosubmit' ,
array ( array ( 'selectid' => $select -> attributes [ 'id' ], 'nothing' => $nothing ))
);
2010-11-15 10:41:26 +00:00
} else {
$output .= html_writer :: empty_tag ( 'input' , array ( 'type' => 'submit' , 'value' => $select -> showbutton ));
}
2010-02-10 10:22:25 +00:00
// then div wrapper for xhtml strictness
2010-02-18 18:15:56 +00:00
$output = html_writer :: tag ( 'div' , $output );
2010-02-10 10:22:25 +00:00
// now the form itself around it
$formattributes = array ( 'method' => 'post' ,
'action' => new moodle_url ( '/course/jumpto.php' ),
'id' => $select -> formid );
2010-02-18 18:15:56 +00:00
$output = html_writer :: tag ( 'form' , $output , $formattributes );
2010-02-09 17:39:13 +00:00
// and finally one more wrapper with class
2010-02-18 18:15:56 +00:00
return html_writer :: tag ( 'div' , $output , array ( 'class' => $select -> class ));
2010-02-09 17:39:13 +00:00
}
2009-08-10 06:22:04 +00:00
/**
* Returns a string containing a link to the user documentation .
* Also contains an icon by default . Shown to teachers and admin only .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param string $path The page link after doc root and language , no leading slash .
* @ param string $text The text to be displayed for the link
2012-10-07 09:55:08 +01:00
* @ param boolean $forcepopup Whether to force a popup regardless of the value of $CFG -> doctonewwindow
2010-05-22 14:43:46 +00:00
* @ return string
2009-08-10 06:22:04 +00:00
*/
2012-10-07 09:55:08 +01:00
public function doc_link ( $path , $text = '' , $forcepopup = false ) {
2010-01-02 13:17:54 +00:00
global $CFG ;
2014-07-21 08:19:08 +08:00
$icon = $this -> pix_icon ( 'docs' , '' , 'moodle' , array ( 'class' => 'iconhelp icon-pre' , 'role' => 'presentation' ));
2010-01-02 13:17:54 +00:00
2010-02-11 14:59:00 +00:00
$url = new moodle_url ( get_docs_url ( $path ));
2010-01-02 13:17:54 +00:00
2010-02-11 15:44:06 +00:00
$attributes = array ( 'href' => $url );
2012-10-07 09:55:08 +01:00
if ( ! empty ( $CFG -> doctonewwindow ) || $forcepopup ) {
$attributes [ 'class' ] = 'helplinkpopup' ;
2009-08-10 06:22:04 +00:00
}
2010-03-28 09:05:47 +00:00
2010-02-18 18:15:56 +00:00
return html_writer :: tag ( 'a' , $icon . $text , $attributes );
2009-08-10 06:22:04 +00:00
}
2010-02-11 14:59:00 +00:00
/**
2012-01-05 13:28:08 +13:00
* Return HTML for a pix_icon .
*
2013-04-15 11:05:46 +10:00
* Theme developers : DO NOT OVERRIDE ! Please override function
* { @ link core_renderer :: render_pix_icon ()} instead .
*
2010-02-11 14:59:00 +00:00
* @ param string $pix short pix name
* @ param string $alt mandatory alt attribute
2010-09-19 19:09:48 +00:00
* @ param string $component standard compoennt name like 'moodle' , 'mod_forum' , etc .
2010-02-11 14:59:00 +00:00
* @ param array $attributes htm lattributes
* @ return string HTML fragment
*/
public function pix_icon ( $pix , $alt , $component = 'moodle' , array $attributes = null ) {
$icon = new pix_icon ( $pix , $alt , $component , $attributes );
return $this -> render ( $icon );
}
/**
2012-01-05 13:28:08 +13:00
* Renders a pix_icon widget and returns the HTML to display it .
*
2010-02-11 14:59:00 +00:00
* @ param pix_icon $icon
* @ return string HTML fragment
*/
2010-02-16 17:33:13 +00:00
protected function render_pix_icon ( pix_icon $icon ) {
2015-05-04 14:38:16 +08:00
$data = $icon -> export_for_template ( $this );
return $this -> render_from_template ( 'core/pix_icon' , $data );
2010-02-11 14:59:00 +00:00
}
2010-10-23 18:39:23 +00:00
/**
2012-01-05 13:28:08 +13:00
* Return HTML to display an emoticon icon .
*
2010-10-23 18:39:23 +00:00
* @ param pix_emoticon $emoticon
* @ return string HTML fragment
*/
protected function render_pix_emoticon ( pix_emoticon $emoticon ) {
$attributes = $emoticon -> attributes ;
$attributes [ 'src' ] = $this -> pix_url ( $emoticon -> pix , $emoticon -> component );
return html_writer :: empty_tag ( 'img' , $attributes );
}
2010-03-16 05:57:51 +00:00
/**
2012-01-05 13:28:08 +13:00
* Produces the html that represents this rating in the UI
*
* @ param rating $rating the page object on which this rating will appear
* @ return string
*/
2010-03-16 05:57:51 +00:00
function render_rating ( rating $rating ) {
2010-03-17 09:12:13 +00:00
global $CFG , $USER ;
2010-03-16 05:57:51 +00:00
2011-05-11 13:32:36 +08:00
if ( $rating -> settings -> aggregationmethod == RATING_AGGREGATE_NONE ) {
2010-04-22 05:15:23 +00:00
return null ; //ratings are turned off
}
2011-05-11 13:32:36 +08:00
$ratingmanager = new rating_manager ();
// Initialise the JavaScript so ratings can be done by AJAX.
$ratingmanager -> initialise_rating_javascript ( $this -> page );
2010-03-16 05:57:51 +00:00
2010-04-22 05:15:23 +00:00
$strrate = get_string ( " rate " , " rating " );
$ratinghtml = '' ; //the string we'll return
2011-05-11 13:32:36 +08:00
// permissions check - can they view the aggregate?
if ( $rating -> user_can_view_aggregate ()) {
2010-03-16 05:57:51 +00:00
2011-05-11 13:32:36 +08:00
$aggregatelabel = $ratingmanager -> get_aggregate_label ( $rating -> settings -> aggregationmethod );
$aggregatestr = $rating -> get_aggregate_string ();
2010-03-16 05:57:51 +00:00
2011-12-05 14:57:36 +08:00
$aggregatehtml = html_writer :: tag ( 'span' , $aggregatestr , array ( 'id' => 'ratingaggregate' . $rating -> itemid , 'class' => 'ratingaggregate' )) . ' ' ;
2011-05-11 13:32:36 +08:00
if ( $rating -> count > 0 ) {
2011-12-05 14:57:36 +08:00
$countstr = " ( { $rating -> count } ) " ;
2010-04-23 09:44:19 +00:00
} else {
2011-12-05 14:57:36 +08:00
$countstr = '-' ;
2010-04-23 09:44:19 +00:00
}
2011-12-05 14:57:36 +08:00
$aggregatehtml .= html_writer :: tag ( 'span' , $countstr , array ( 'id' => " ratingcount { $rating -> itemid } " , 'class' => 'ratingcount' )) . ' ' ;
2010-04-22 05:15:23 +00:00
2010-10-06 05:50:45 +00:00
$ratinghtml .= html_writer :: tag ( 'span' , $aggregatelabel , array ( 'class' => 'rating-aggregate-label' ));
2010-04-23 09:44:19 +00:00
if ( $rating -> settings -> permissions -> viewall && $rating -> settings -> pluginpermissions -> viewall ) {
2011-05-11 13:32:36 +08:00
$nonpopuplink = $rating -> get_view_ratings_url ();
$popuplink = $rating -> get_view_ratings_url ( true );
2010-03-16 05:57:51 +00:00
2010-04-23 09:44:19 +00:00
$action = new popup_action ( 'click' , $popuplink , 'ratings' , array ( 'height' => 400 , 'width' => 600 ));
2010-10-06 05:50:45 +00:00
$ratinghtml .= $this -> action_link ( $nonpopuplink , $aggregatehtml , $action );
2010-04-23 09:44:19 +00:00
} else {
2010-10-06 05:50:45 +00:00
$ratinghtml .= $aggregatehtml ;
2010-03-16 05:57:51 +00:00
}
2010-04-23 09:44:19 +00:00
}
2010-03-16 05:57:51 +00:00
2010-04-23 09:44:19 +00:00
$formstart = null ;
2011-05-11 13:32:36 +08:00
// if the item doesn't belong to the current user, the user has permission to rate
// and we're within the assessable period
if ( $rating -> user_can_rate ()) {
2010-05-17 07:31:22 +00:00
2011-05-11 13:32:36 +08:00
$rateurl = $rating -> get_rate_url ();
$inputs = $rateurl -> params ();
2010-05-17 07:31:22 +00:00
2011-05-11 13:32:36 +08:00
//start the rating form
$formattrs = array (
'id' => " postrating { $rating -> itemid } " ,
'class' => 'postratingform' ,
'method' => 'post' ,
'action' => $rateurl -> out_omit_querystring ()
);
$formstart = html_writer :: start_tag ( 'form' , $formattrs );
$formstart .= html_writer :: start_tag ( 'div' , array ( 'class' => 'ratingform' ));
// add the hidden inputs
foreach ( $inputs as $name => $value ) {
$attributes = array ( 'type' => 'hidden' , 'class' => 'ratinginput' , 'name' => $name , 'value' => $value );
$formstart .= html_writer :: empty_tag ( 'input' , $attributes );
}
2010-05-21 03:43:45 +00:00
2010-04-23 09:44:19 +00:00
if ( empty ( $ratinghtml )) {
$ratinghtml .= $strrate . ': ' ;
}
$ratinghtml = $formstart . $ratinghtml ;
2010-04-22 05:15:23 +00:00
2011-05-11 13:32:36 +08:00
$scalearray = array ( RATING_UNSET_RATING => $strrate . '...' ) + $rating -> settings -> scale -> scaleitems ;
$scaleattrs = array ( 'class' => 'postratingmenu ratinginput' , 'id' => 'menurating' . $rating -> itemid );
2012-07-31 12:07:16 +08:00
$ratinghtml .= html_writer :: label ( $rating -> rating , 'menurating' . $rating -> itemid , false , array ( 'class' => 'accesshide' ));
2011-05-11 13:32:36 +08:00
$ratinghtml .= html_writer :: select ( $scalearray , 'rating' , $rating -> rating , false , $scaleattrs );
2010-03-16 05:57:51 +00:00
2010-04-23 09:44:19 +00:00
//output submit button
2010-05-17 07:31:22 +00:00
$ratinghtml .= html_writer :: start_tag ( 'span' , array ( 'class' => " ratingsubmit " ));
2011-05-11 13:32:36 +08:00
$attributes = array ( 'type' => 'submit' , 'class' => 'postratingmenusubmit' , 'id' => 'postratingsubmit' . $rating -> itemid , 'value' => s ( get_string ( 'rate' , 'rating' )));
2010-05-17 07:31:22 +00:00
$ratinghtml .= html_writer :: empty_tag ( 'input' , $attributes );
2010-03-16 05:57:51 +00:00
2011-05-11 13:32:36 +08:00
if ( ! $rating -> settings -> scale -> isnumeric ) {
2012-10-15 16:48:21 +08:00
// If a global scale, try to find current course ID from the context
if ( empty ( $rating -> settings -> scale -> courseid ) and $coursecontext = $rating -> context -> get_course_context ( false )) {
$courseid = $coursecontext -> instanceid ;
} else {
$courseid = $rating -> settings -> scale -> courseid ;
}
$ratinghtml .= $this -> help_icon_scale ( $courseid , $rating -> settings -> scale );
2010-03-16 05:57:51 +00:00
}
2010-05-17 07:31:22 +00:00
$ratinghtml .= html_writer :: end_tag ( 'span' );
$ratinghtml .= html_writer :: end_tag ( 'div' );
$ratinghtml .= html_writer :: end_tag ( 'form' );
2010-03-16 05:57:51 +00:00
}
2010-04-22 05:15:23 +00:00
return $ratinghtml ;
2010-03-16 05:57:51 +00:00
}
2012-01-05 13:28:08 +13:00
/**
2009-08-10 06:22:04 +00:00
* Centered heading with attached help button ( same title text )
2012-01-05 13:28:08 +13:00
* and optional icon attached .
*
2009-12-30 15:19:55 +00:00
* @ param string $text A heading text
2010-04-10 09:10:08 +00:00
* @ param string $helpidentifier The keyword that defines a help page
2009-12-30 15:19:55 +00:00
* @ param string $component component name
* @ param string | moodle_url $icon
* @ param string $iconalt icon alt text
2013-08-29 10:30:02 +08:00
* @ param int $level The level of importance of the heading . Defaulting to 2
* @ param string $classnames A space - separated list of CSS classes . Defaulting to null
2009-08-10 06:22:04 +00:00
* @ return string HTML fragment
*/
2013-08-29 10:30:02 +08:00
public function heading_with_help ( $text , $helpidentifier , $component = 'moodle' , $icon = '' , $iconalt = '' , $level = 2 , $classnames = null ) {
2009-12-30 15:19:55 +00:00
$image = '' ;
if ( $icon ) {
2013-10-27 09:42:00 +08:00
$image = $this -> pix_icon ( $icon , $iconalt , $component , array ( 'class' => 'icon iconlarge' ));
2009-08-10 06:22:04 +00:00
}
2009-12-30 15:19:55 +00:00
2010-04-13 21:51:49 +00:00
$help = '' ;
if ( $helpidentifier ) {
$help = $this -> help_icon ( $helpidentifier , $component );
}
2009-12-30 15:19:55 +00:00
2013-08-29 10:30:02 +08:00
return $this -> heading ( $image . $text . $help , $level , $classnames );
2009-08-10 06:22:04 +00:00
}
/**
2012-01-05 13:28:08 +13:00
* Returns HTML to display a help icon .
2009-08-10 06:22:04 +00:00
*
2010-08-16 15:29:46 +00:00
* @ deprecated since Moodle 2.0
2010-01-13 18:50:28 +00:00
*/
2010-04-13 20:34:27 +00:00
public function old_help_icon ( $helpidentifier , $title , $component = 'moodle' , $linktext = '' ) {
2013-02-05 09:25:29 +00:00
throw new coding_exception ( 'old_help_icon() can not be used any more, please see help_icon().' );
2009-08-10 06:22:04 +00:00
}
2010-04-13 21:51:49 +00:00
/**
2012-01-05 13:28:08 +13:00
* Returns HTML to display a help icon .
2010-04-13 21:51:49 +00:00
*
2013-04-15 11:05:46 +10:00
* Theme developers : DO NOT OVERRIDE ! Please override function
* { @ link core_renderer :: render_help_icon ()} instead .
*
2010-04-13 21:51:49 +00:00
* @ param string $identifier The keyword that defines a help page
* @ param string $component component name
* @ param string | bool $linktext true means use $title as link text , string means link text value
* @ return string HTML fragment
*/
public function help_icon ( $identifier , $component = 'moodle' , $linktext = '' ) {
2010-05-04 08:29:05 +00:00
$icon = new help_icon ( $identifier , $component );
2010-04-13 21:51:49 +00:00
$icon -> diag_strings ();
if ( $linktext === true ) {
$icon -> linktext = get_string ( $icon -> identifier , $icon -> component );
} else if ( ! empty ( $linktext )) {
$icon -> linktext = $linktext ;
}
return $this -> render ( $icon );
}
/**
* Implementation of user image rendering .
2012-01-05 13:28:08 +13:00
*
2012-01-12 12:55:50 +13:00
* @ param help_icon $helpicon A help icon instance
2010-04-13 21:51:49 +00:00
* @ return string HTML fragment
*/
protected function render_help_icon ( help_icon $helpicon ) {
2016-08-17 15:36:02 +08:00
return $this -> render_from_template ( 'core/help_icon' , $helpicon -> export_for_template ( $this ));
2010-04-13 21:51:49 +00:00
}
2009-08-10 06:22:04 +00:00
/**
2012-01-05 13:28:08 +13:00
* Returns HTML to display a scale help icon .
2009-08-10 06:22:04 +00:00
*
2009-12-30 15:19:55 +00:00
* @ param int $courseid
2012-01-05 13:28:08 +13:00
* @ param stdClass $scale instance
* @ return string HTML fragment
2009-08-10 06:22:04 +00:00
*/
2009-12-30 15:19:55 +00:00
public function help_icon_scale ( $courseid , stdClass $scale ) {
global $CFG ;
2009-10-23 18:49:00 +00:00
2009-12-30 15:19:55 +00:00
$title = get_string ( 'helpprefix2' , '' , $scale -> name ) . ' (' . get_string ( 'newwindow' ) . ')' ;
2009-10-23 18:49:00 +00:00
2010-02-16 17:31:35 +00:00
$icon = $this -> pix_icon ( 'help' , get_string ( 'scales' ), 'moodle' , array ( 'class' => 'iconhelp' ));
2009-10-23 18:49:00 +00:00
2010-10-11 06:23:03 +00:00
$scaleid = abs ( $scale -> id );
$link = new moodle_url ( '/course/scales.php' , array ( 'id' => $courseid , 'list' => true , 'scaleid' => $scaleid ));
2010-03-24 02:35:16 +00:00
$action = new popup_action ( 'click' , $link , 'ratingscale' );
2009-10-23 18:49:00 +00:00
2010-02-18 18:15:56 +00:00
return html_writer :: tag ( 'span' , $this -> action_link ( $link , $icon , $action ), array ( 'class' => 'helplink' ));
2009-08-10 06:22:04 +00:00
}
/**
* Creates and returns a spacer image with optional line break .
*
2012-01-12 12:55:50 +13:00
* @ param array $attributes Any HTML attributes to add to the spaced .
* @ param bool $br Include a BR after the spacer .... DON 'T USE THIS. Don' t be
* laxy do it with CSS which is a much better solution .
2009-08-10 06:22:04 +00:00
* @ return string HTML fragment
*/
2010-02-16 17:31:35 +00:00
public function spacer ( array $attributes = null , $br = false ) {
$attributes = ( array ) $attributes ;
if ( empty ( $attributes [ 'width' ])) {
$attributes [ 'width' ] = 1 ;
2009-12-27 23:31:46 +00:00
}
2010-09-17 08:01:16 +00:00
if ( empty ( $attributes [ 'height' ])) {
2010-02-16 17:31:35 +00:00
$attributes [ 'height' ] = 1 ;
2009-08-10 06:22:04 +00:00
}
2010-02-16 17:31:35 +00:00
$attributes [ 'class' ] = 'spacer' ;
2009-08-10 06:22:04 +00:00
2010-02-16 17:31:35 +00:00
$output = $this -> pix_icon ( 'spacer' , '' , 'moodle' , $attributes );
2009-08-14 03:16:23 +00:00
2010-02-16 17:31:35 +00:00
if ( ! empty ( $br )) {
2009-12-27 23:31:46 +00:00
$output .= '<br />' ;
}
2009-08-10 06:22:04 +00:00
return $output ;
}
/**
2012-01-05 13:28:08 +13:00
* Returns HTML to display the specified user ' s avatar .
2009-08-10 06:22:04 +00:00
*
2010-01-13 17:13:52 +00:00
* User avatar may be obtained in two ways :
2009-08-10 06:22:04 +00:00
* < pre >
2009-12-27 19:47:21 +00:00
* // Option 1: (shortcut for simple cases, preferred way)
* // $user has come from the DB and has fields id, picture, imagealt, firstname and lastname
* $OUTPUT -> user_picture ( $user , array ( 'popup' => true ));
*
2010-01-13 17:13:52 +00:00
* // Option 2:
* $userpic = new user_picture ( $user );
2009-08-10 06:22:04 +00:00
* // Set properties of $userpic
2009-12-27 19:47:21 +00:00
* $userpic -> popup = true ;
2010-01-13 17:13:52 +00:00
* $OUTPUT -> render ( $userpic );
2009-08-10 06:22:04 +00:00
* </ pre >
*
2013-04-15 11:05:46 +10:00
* Theme developers : DO NOT OVERRIDE ! Please override function
* { @ link core_renderer :: render_user_picture ()} instead .
*
2012-01-05 13:28:08 +13:00
* @ param stdClass $user Object with at least fields id , picture , imagealt , firstname , lastname
2009-12-27 19:47:21 +00:00
* If any of these are missing , the database is queried . Avoid this
2009-08-10 06:22:04 +00:00
* if at all possible , particularly for reports . It is very bad for performance .
2009-12-27 19:47:21 +00:00
* @ param array $options associative array with user picture options , used only if not a user_picture object ,
* options are :
* - courseid = $this -> page -> course -> id ( course id of user profile in link )
* - size = 35 ( size of image )
* - link = true ( make image clickable - the link leads to user profile )
* - popup = false ( open in popup )
* - alttext = true ( add image alt attribute )
2010-01-13 17:13:52 +00:00
* - class = image class attribute ( default 'userpicture' )
2014-07-08 15:17:26 +08:00
* - visibletoscreenreaders = true ( whether to be visible to screen readers )
2009-08-10 06:22:04 +00:00
* @ return string HTML fragment
*/
2010-01-13 17:13:52 +00:00
public function user_picture ( stdClass $user , array $options = null ) {
$userpicture = new user_picture ( $user );
foreach (( array ) $options as $key => $value ) {
if ( array_key_exists ( $key , $userpicture )) {
$userpicture -> $key = $value ;
}
}
return $this -> render ( $userpicture );
}
/**
* Internal implementation of user image rendering .
2012-01-05 13:28:08 +13:00
*
2010-01-13 17:13:52 +00:00
* @ param user_picture $userpicture
* @ return string
*/
protected function render_user_picture ( user_picture $userpicture ) {
global $CFG , $DB ;
2009-12-27 19:47:21 +00:00
2010-01-13 17:13:52 +00:00
$user = $userpicture -> user ;
if ( $userpicture -> alttext ) {
if ( ! empty ( $user -> imagealt )) {
$alt = $user -> imagealt ;
} else {
$alt = get_string ( 'pictureof' , '' , fullname ( $user ));
}
2009-08-10 06:22:04 +00:00
} else {
2010-02-03 16:27:52 +00:00
$alt = '' ;
2010-01-13 17:13:52 +00:00
}
if ( empty ( $userpicture -> size )) {
$size = 35 ;
} else if ( $userpicture -> size === true or $userpicture -> size == 1 ) {
$size = 100 ;
} else {
$size = $userpicture -> size ;
2009-08-10 06:22:04 +00:00
}
2010-01-13 17:13:52 +00:00
$class = $userpicture -> class ;
2009-08-10 06:22:04 +00:00
2012-04-30 23:36:47 +02:00
if ( $user -> picture == 0 ) {
2010-01-13 17:13:52 +00:00
$class .= ' defaultuserpic' ;
}
2009-08-10 06:22:04 +00:00
2011-09-06 11:29:05 +12:00
$src = $userpicture -> get_url ( $this -> page , $this );
2010-10-11 05:46:58 +00:00
$attributes = array ( 'src' => $src , 'alt' => $alt , 'title' => $alt , 'class' => $class , 'width' => $size , 'height' => $size );
2014-07-08 15:17:26 +08:00
if ( ! $userpicture -> visibletoscreenreaders ) {
$attributes [ 'role' ] = 'presentation' ;
}
2010-01-13 17:13:52 +00:00
// get the image html output fisrt
2012-11-15 09:51:26 +08:00
$output = html_writer :: empty_tag ( 'img' , $attributes );
2010-01-13 17:13:52 +00:00
// then wrap it in link if needed
if ( ! $userpicture -> link ) {
return $output ;
2009-08-10 06:22:04 +00:00
}
2010-01-13 17:13:52 +00:00
if ( empty ( $userpicture -> courseid )) {
$courseid = $this -> page -> course -> id ;
} else {
$courseid = $userpicture -> courseid ;
}
2010-05-04 13:04:35 +00:00
if ( $courseid == SITEID ) {
$url = new moodle_url ( '/user/profile.php' , array ( 'id' => $user -> id ));
} else {
$url = new moodle_url ( '/user/view.php' , array ( 'id' => $user -> id , 'course' => $courseid ));
}
2010-01-13 17:13:52 +00:00
$attributes = array ( 'href' => $url );
2014-07-08 15:17:26 +08:00
if ( ! $userpicture -> visibletoscreenreaders ) {
$attributes [ 'tabindex' ] = '-1' ;
$attributes [ 'aria-hidden' ] = 'true' ;
}
2010-01-13 17:13:52 +00:00
if ( $userpicture -> popup ) {
$id = html_writer :: random_id ( 'userpicture' );
$attributes [ 'id' ] = $id ;
2010-02-11 15:44:06 +00:00
$this -> add_action_handler ( new popup_action ( 'click' , $url ), $id );
2010-01-13 17:13:52 +00:00
}
2010-02-18 18:15:56 +00:00
return html_writer :: tag ( 'a' , $output , $attributes );
2009-08-10 06:22:04 +00:00
}
2010-05-26 08:32:31 +00:00
/**
* Internal implementation of file tree viewer items rendering .
2012-01-05 13:28:08 +13:00
*
2010-05-26 08:32:31 +00:00
* @ param array $dir
* @ return string
*/
public function htmllize_file_tree ( $dir ) {
if ( empty ( $dir [ 'subdirs' ]) and empty ( $dir [ 'files' ])) {
return '' ;
}
$result = '<ul>' ;
foreach ( $dir [ 'subdirs' ] as $subdir ) {
$result .= '<li>' . s ( $subdir [ 'dirname' ]) . ' ' . $this -> htmllize_file_tree ( $subdir ) . '</li>' ;
}
foreach ( $dir [ 'files' ] as $file ) {
$filename = $file -> get_filename ();
$result .= '<li><span>' . html_writer :: link ( $file -> fileurl , $filename ) . '</span></li>' ;
}
$result .= '</ul>' ;
return $result ;
}
2012-01-05 13:28:08 +13:00
2010-05-24 07:55:57 +00:00
/**
2012-01-05 13:28:08 +13:00
* Returns HTML to display the file picker
2010-05-24 07:55:57 +00:00
*
* < pre >
* $OUTPUT -> file_picker ( $options );
* </ pre >
*
2013-04-15 11:05:46 +10:00
* Theme developers : DO NOT OVERRIDE ! Please override function
* { @ link core_renderer :: render_file_picker ()} instead .
*
2010-05-24 07:55:57 +00:00
* @ param array $options associative array with file manager options
* options are :
* maxbytes =>- 1 ,
* itemid => 0 ,
* client_id => uniqid (),
* acepted_types => '*' ,
* return_types => FILE_INTERNAL ,
* context => $PAGE -> context
* @ return string HTML fragment
*/
public function file_picker ( $options ) {
$fp = new file_picker ( $options );
return $this -> render ( $fp );
}
2012-01-05 13:28:08 +13:00
2010-05-26 08:32:31 +00:00
/**
* Internal implementation of file picker rendering .
2012-01-05 13:28:08 +13:00
*
2010-05-26 08:32:31 +00:00
* @ param file_picker $fp
* @ return string
*/
2010-05-24 07:55:57 +00:00
public function render_file_picker ( file_picker $fp ) {
global $CFG , $OUTPUT , $USER ;
$options = $fp -> options ;
$client_id = $options -> client_id ;
$strsaved = get_string ( 'filesaved' , 'repository' );
$straddfile = get_string ( 'openpicker' , 'repository' );
$strloading = get_string ( 'loading' , 'repository' );
2012-02-23 19:34:59 +00:00
$strdndenabled = get_string ( 'dndenabled_inbox' , 'moodle' );
2012-04-26 11:53:52 +08:00
$strdroptoupload = get_string ( 'droptoupload' , 'moodle' );
2010-05-24 07:55:57 +00:00
$icon_progress = $OUTPUT -> pix_icon ( 'i/loading_small' , $strloading ) . '' ;
$currentfile = $options -> currentfile ;
if ( empty ( $currentfile )) {
2012-05-30 10:05:10 +08:00
$currentfile = '' ;
} else {
$currentfile .= ' - ' ;
2010-05-24 07:55:57 +00:00
}
2010-09-30 03:36:38 +00:00
if ( $options -> maxbytes ) {
$size = $options -> maxbytes ;
} else {
$size = get_max_upload_file_size ();
}
2010-10-04 03:09:58 +00:00
if ( $size == - 1 ) {
2010-10-04 10:03:52 +00:00
$maxsize = '' ;
2010-10-04 03:09:58 +00:00
} else {
$maxsize = get_string ( 'maxfilesize' , 'moodle' , display_size ( $size ));
}
2011-04-18 11:42:27 +02:00
if ( $options -> buttonname ) {
2011-04-12 14:30:13 +12:00
$buttonname = ' name="' . $options -> buttonname . '"' ;
} else {
$buttonname = '' ;
}
2010-05-24 07:55:57 +00:00
$html = <<< EOD
< div class = " filemanager-loading mdl-align " id = 'filepicker-loading-{$client_id}' >
$icon_progress
</ div >
< div id = " filepicker-wrapper- { $client_id } " class = " mdl-left " style = " display:none " >
< div >
2012-07-13 16:02:21 +08:00
< input type = " button " class = " fp-btn-choose " id = " filepicker-button- { $client_id } " value = " { $straddfile } " { $buttonname } />
2010-09-07 10:06:57 +00:00
< span > $maxsize </ span >
2010-05-24 07:55:57 +00:00
</ div >
EOD ;
if ( $options -> env != 'url' ) {
$html .= <<< EOD
2012-05-24 16:12:15 +08:00
< div id = " file_info_ { $client_id } " class = " mdl-left filepicker-filelist " style = " position: relative " >
2012-05-24 15:02:52 +08:00
< div class = " filepicker-filename " >
2012-11-27 15:58:30 +08:00
< div class = " filepicker-container " > $currentfile < div class = " dndupload-message " > $strdndenabled < br />< div class = " dndupload-arrow " ></ div ></ div ></ div >
2013-01-16 11:18:18 +08:00
< div class = " dndupload-progressbars " ></ div >
2012-05-24 15:02:52 +08:00
</ div >
2012-11-27 15:58:30 +08:00
< div >< div class = " dndupload-target " > { $strdroptoupload } < br />< div class = " dndupload-arrow " ></ div ></ div ></ div >
2011-11-08 20:05:19 +00:00
</ div >
2010-05-24 07:55:57 +00:00
EOD ;
}
$html .= '</div>' ;
return $html ;
}
2009-08-10 06:22:04 +00:00
/**
2012-01-05 13:28:08 +13:00
* Returns HTML to display the 'Update this Modulename' button that appears on module pages .
2009-08-10 06:22:04 +00:00
*
2016-07-27 14:13:25 +08:00
* @ deprecated since Moodle 3.2
*
2009-08-10 06:22:04 +00:00
* @ param string $cmid the course_module id .
* @ param string $modulename the module name , eg . " forum " , " quiz " or " workshop "
* @ return string the HTML for the button , if this user has permission to edit it , else an empty string .
*/
public function update_module_button ( $cmid , $modulename ) {
global $CFG ;
2016-07-27 14:13:25 +08:00
debugging ( 'core_renderer::update_module_button() has been deprecated and should not be used anymore. Activity modules ' .
'should not add the edit module button, the link is already available in the Administration block. Themes can choose ' .
'to display the link in the buttons row consistently for all module types.' , DEBUG_DEVELOPER );
2012-07-25 16:25:55 +08:00
if ( has_capability ( 'moodle/course:manageactivities' , context_module :: instance ( $cmid ))) {
2009-08-10 06:22:04 +00:00
$modulename = get_string ( 'modulename' , $modulename );
$string = get_string ( 'updatethis' , '' , $modulename );
2010-01-14 19:18:04 +00:00
$url = new moodle_url ( " $CFG->wwwroot /course/mod.php " , array ( 'update' => $cmid , 'return' => true , 'sesskey' => sesskey ()));
return $this -> single_button ( $url , $string );
2009-08-10 06:22:04 +00:00
} else {
return '' ;
}
}
/**
2012-01-05 13:28:08 +13:00
* Returns HTML to display a " Turn editing on/off " button in a form .
*
2009-08-10 06:22:04 +00:00
* @ param moodle_url $url The URL + params to send through when clicking the button
* @ return string HTML the button
*/
public function edit_button ( moodle_url $url ) {
2010-08-03 10:56:35 +00:00
$url -> param ( 'sesskey' , sesskey ());
if ( $this -> page -> user_is_editing ()) {
$url -> param ( 'edit' , 'off' );
$editstring = get_string ( 'turneditingoff' );
2009-08-10 06:22:04 +00:00
} else {
2010-08-03 10:56:35 +00:00
$url -> param ( 'edit' , 'on' );
$editstring = get_string ( 'turneditingon' );
2009-08-10 06:22:04 +00:00
}
2010-08-03 10:56:35 +00:00
return $this -> single_button ( $url , $editstring );
2009-08-10 06:22:04 +00:00
}
/**
2012-01-05 13:28:08 +13:00
* Returns HTML to display a simple button to close a window
2009-08-10 06:22:04 +00:00
*
* @ param string $text The lang string for the button ' s label ( already output from get_string ())
2010-01-14 19:18:04 +00:00
* @ return string html fragment
2009-08-10 06:22:04 +00:00
*/
2009-08-13 01:15:58 +00:00
public function close_window_button ( $text = '' ) {
2009-08-10 06:22:04 +00:00
if ( empty ( $text )) {
$text = get_string ( 'closewindow' );
}
2010-01-16 15:39:56 +00:00
$button = new single_button ( new moodle_url ( '#' ), $text , 'get' );
$button -> add_action ( new component_action ( 'click' , 'close_window' ));
2010-01-14 19:18:04 +00:00
return $this -> container ( $this -> render ( $button ), 'closewindow' );
2009-08-10 06:22:04 +00:00
}
/**
* Output an error message . By default wraps the error message in < span class = " error " >.
* If the error message is blank , nothing is output .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param string $message the error message .
* @ return string the HTML to output .
*/
public function error_text ( $message ) {
if ( empty ( $message )) {
return '' ;
}
2013-01-31 11:02:49 +08:00
$message = $this -> pix_icon ( 'i/warning' , get_string ( 'error' ), '' , array ( 'class' => 'icon icon-pre' , 'title' => '' )) . $message ;
2010-02-18 18:15:56 +00:00
return html_writer :: tag ( 'span' , $message , array ( 'class' => 'error' ));
2009-08-10 06:22:04 +00:00
}
/**
* Do not call this function directly .
*
2012-02-14 18:24:09 +13:00
* To terminate the current script with a fatal error , call the { @ link print_error }
2009-08-10 06:22:04 +00:00
* function , or throw an exception . Doing either of those things will then call this
* function to display the error , before terminating the execution .
*
* @ param string $message The message to output
* @ param string $moreinfourl URL where more info can be found about the error
* @ param string $link Link for the Continue button
* @ param array $backtrace The execution backtrace
* @ param string $debuginfo Debugging information
* @ return string the HTML to output .
*/
2016-09-13 14:23:21 +02:00
public function fatal_error ( $message , $moreinfourl , $link , $backtrace , $debuginfo = null , $errorcode = " " ) {
2010-11-05 08:44:51 +00:00
global $CFG ;
2009-08-10 06:22:04 +00:00
$output = '' ;
2009-10-31 14:12:16 +00:00
$obbuffer = '' ;
2009-08-13 03:38:30 +00:00
2009-08-10 06:22:04 +00:00
if ( $this -> has_started ()) {
2009-10-30 13:44:07 +00:00
// we can not always recover properly here, we have problems with output buffering,
// html tables, etc.
2009-08-10 06:22:04 +00:00
$output .= $this -> opencontainers -> pop_all_but_last ();
2009-10-30 13:44:07 +00:00
2009-08-10 06:22:04 +00:00
} else {
2009-10-30 13:44:07 +00:00
// It is really bad if library code throws exception when output buffering is on,
// because the buffered text would be printed before our start of page.
// NOTE: this hack might be behave unexpectedly in case output buffering is enabled in PHP.ini
2010-11-05 08:44:51 +00:00
error_reporting ( 0 ); // disable notices from gzip compression, etc.
2009-10-30 13:44:07 +00:00
while ( ob_get_level () > 0 ) {
2010-11-05 08:32:36 +00:00
$buff = ob_get_clean ();
if ( $buff === false ) {
break ;
}
$obbuffer .= $buff ;
2009-10-30 13:44:07 +00:00
}
2010-11-05 08:44:51 +00:00
error_reporting ( $CFG -> debug );
2009-10-31 14:12:16 +00:00
2013-03-25 16:06:02 +01:00
// Output not yet started.
$protocol = ( isset ( $_SERVER [ 'SERVER_PROTOCOL' ]) ? $_SERVER [ 'SERVER_PROTOCOL' ] : 'HTTP/1.0' );
if ( empty ( $_SERVER [ 'HTTP_RANGE' ])) {
@ header ( $protocol . ' 404 Not Found' );
2016-11-07 09:55:11 +08:00
} else if ( core_useragent :: check_safari_ios_version ( 602 ) && ! empty ( $_SERVER [ 'HTTP_X_PLAYBACK_SESSION_ID' ])) {
// Coax iOS 10 into sending the session cookie.
@ header ( $protocol . ' 403 Forbidden' );
2013-03-25 16:06:02 +01:00
} else {
// Must stop byteserving attempts somehow,
// this is weird but Chrome PDF viewer can be stopped only with 407!
@ header ( $protocol . ' 407 Proxy Authentication Required' );
2009-10-30 12:46:16 +00:00
}
2013-03-25 16:06:02 +01:00
2010-08-16 19:11:21 +00:00
$this -> page -> set_context ( null ); // ugly hack - make sure page context is set to something, we do not want bogus warnings here
2010-01-18 09:40:14 +00:00
$this -> page -> set_url ( '/' ); // no url
2009-12-27 12:02:04 +00:00
//$this->page->set_pagelayout('base'); //TODO: MDL-20676 blocks on error pages are weird, unfortunately it somehow detect the pagelayout from URL :-(
2010-06-23 09:13:23 +00:00
$this -> page -> set_title ( get_string ( 'error' ));
2010-06-23 09:16:53 +00:00
$this -> page -> set_heading ( $this -> page -> course -> fullname );
2009-08-10 06:22:04 +00:00
$output .= $this -> header ();
}
$message = '<p class="errormessage">' . $message . '</p>' .
'<p class="errorcode"><a href="' . $moreinfourl . '">' .
get_string ( 'moreinformation' ) . '</a></p>' ;
2011-09-11 00:07:28 +02:00
if ( empty ( $CFG -> rolesactive )) {
$message .= '<p class="errormessage">' . get_string ( 'installproblem' , 'error' ) . '</p>' ;
//It is usually not possible to recover from errors triggered during installation, you may need to create a new database or use a different database prefix for new installation.
}
2013-08-01 16:52:18 +12:00
$output .= $this -> box ( $message , 'errorbox' , null , array ( 'data-rel' => 'fatalerror' ));
2009-08-10 06:22:04 +00:00
2013-08-10 22:46:49 +02:00
if ( $CFG -> debugdeveloper ) {
2009-10-31 14:12:16 +00:00
if ( ! empty ( $debuginfo )) {
2010-03-20 13:46:15 +00:00
$debuginfo = s ( $debuginfo ); // removes all nasty JS
$debuginfo = str_replace ( " \n " , '<br />' , $debuginfo ); // keep newlines
$output .= $this -> notification ( '<strong>Debug info:</strong> ' . $debuginfo , 'notifytiny' );
2009-10-31 14:12:16 +00:00
}
if ( ! empty ( $backtrace )) {
$output .= $this -> notification ( '<strong>Stack trace:</strong> ' . format_backtrace ( $backtrace ), 'notifytiny' );
}
if ( $obbuffer !== '' ) {
$output .= $this -> notification ( '<strong>Output buffer:</strong> ' . s ( $obbuffer ), 'notifytiny' );
}
2009-08-10 06:22:04 +00:00
}
2011-09-09 10:19:27 +02:00
if ( empty ( $CFG -> rolesactive )) {
// continue does not make much sense if moodle is not installed yet because error is most probably not recoverable
} else if ( ! empty ( $link )) {
2009-08-10 06:22:04 +00:00
$output .= $this -> continue_button ( $link );
}
$output .= $this -> footer ();
// Padding to encourage IE to display our error page, rather than its own.
$output .= str_repeat ( ' ' , 512 );
return $output ;
}
/**
2016-02-16 08:45:29 +08:00
* Output a notification ( that is , a status message about something that has just happened ) .
2009-08-10 06:22:04 +00:00
*
2016-02-16 08:48:39 +08:00
* Note : \core\notification :: add () may be more suitable for your usage .
*
2016-02-16 08:45:29 +08:00
* @ param string $message The message to print out .
* @ param string $type The type of notification . See constants on \core\output\notification .
2009-08-10 06:22:04 +00:00
* @ return string the HTML to output .
*/
2016-02-16 08:45:29 +08:00
public function notification ( $message , $type = null ) {
$typemappings = [
// Valid types.
'success' => \core\output\notification :: NOTIFY_SUCCESS ,
'info' => \core\output\notification :: NOTIFY_INFO ,
'warning' => \core\output\notification :: NOTIFY_WARNING ,
'error' => \core\output\notification :: NOTIFY_ERROR ,
// Legacy types mapped to current types.
'notifyproblem' => \core\output\notification :: NOTIFY_ERROR ,
'notifytiny' => \core\output\notification :: NOTIFY_ERROR ,
'notifyerror' => \core\output\notification :: NOTIFY_ERROR ,
'notifysuccess' => \core\output\notification :: NOTIFY_SUCCESS ,
'notifymessage' => \core\output\notification :: NOTIFY_INFO ,
'notifyredirect' => \core\output\notification :: NOTIFY_INFO ,
'redirectmessage' => \core\output\notification :: NOTIFY_INFO ,
];
$extraclasses = [];
if ( $type ) {
if ( strpos ( $type , ' ' ) === false ) {
// No spaces in the list of classes, therefore no need to loop over and determine the class.
if ( isset ( $typemappings [ $type ])) {
$type = $typemappings [ $type ];
} else {
// The value provided did not match a known type. It must be an extra class.
$extraclasses = [ $type ];
}
} else {
// Identify what type of notification this is.
$classarray = explode ( ' ' , self :: prepare_classes ( $type ));
// Separate out the type of notification from the extra classes.
foreach ( $classarray as $class ) {
if ( isset ( $typemappings [ $class ])) {
$type = $typemappings [ $class ];
} else {
$extraclasses [] = $class ;
}
2015-03-23 14:27:16 +08:00
}
}
}
2016-02-16 08:45:29 +08:00
$notification = new \core\output\notification ( $message , $type );
if ( count ( $extraclasses )) {
$notification -> set_extra_classes ( $extraclasses );
}
2015-03-23 14:27:16 +08:00
2016-02-16 08:45:29 +08:00
// Return the rendered template.
return $this -> render_from_template ( $notification -> get_template_name (), $notification -> export_for_template ( $this ));
2015-03-23 14:27:16 +08:00
}
/**
* Output a notification at a particular level - in this case , NOTIFY_PROBLEM .
*
* @ param string $message the message to print out
* @ return string HTML fragment .
2016-02-16 08:45:29 +08:00
* @ deprecated since Moodle 3.1 MDL - 30811 - please do not use this function any more .
* @ todo MDL - 53113 This will be removed in Moodle 3.5 .
* @ see \core\output\notification
2015-03-23 14:27:16 +08:00
*/
public function notify_problem ( $message ) {
2016-02-16 08:45:29 +08:00
debugging ( __FUNCTION__ . ' is deprecated.' .
2016-02-16 08:48:39 +08:00
'Please use \core\notification::add, or \core\output\notification as required' ,
2016-02-16 08:45:29 +08:00
DEBUG_DEVELOPER );
$n = new \core\output\notification ( $message , \core\output\notification :: NOTIFY_ERROR );
2015-03-23 14:27:16 +08:00
return $this -> render ( $n );
}
/**
* Output a notification at a particular level - in this case , NOTIFY_SUCCESS .
*
* @ param string $message the message to print out
* @ return string HTML fragment .
2016-02-16 08:45:29 +08:00
* @ deprecated since Moodle 3.1 MDL - 30811 - please do not use this function any more .
* @ todo MDL - 53113 This will be removed in Moodle 3.5 .
* @ see \core\output\notification
2015-03-23 14:27:16 +08:00
*/
public function notify_success ( $message ) {
2016-02-16 08:45:29 +08:00
debugging ( __FUNCTION__ . ' is deprecated.' .
2016-02-16 08:48:39 +08:00
'Please use \core\notification::add, or \core\output\notification as required' ,
2016-02-16 08:45:29 +08:00
DEBUG_DEVELOPER );
2015-03-23 14:27:16 +08:00
$n = new \core\output\notification ( $message , \core\output\notification :: NOTIFY_SUCCESS );
return $this -> render ( $n );
}
/**
* Output a notification at a particular level - in this case , NOTIFY_MESSAGE .
*
* @ param string $message the message to print out
* @ return string HTML fragment .
2016-02-16 08:45:29 +08:00
* @ deprecated since Moodle 3.1 MDL - 30811 - please do not use this function any more .
* @ todo MDL - 53113 This will be removed in Moodle 3.5 .
* @ see \core\output\notification
2015-03-23 14:27:16 +08:00
*/
public function notify_message ( $message ) {
2016-02-16 08:45:29 +08:00
debugging ( __FUNCTION__ . ' is deprecated.' .
2016-02-16 08:48:39 +08:00
'Please use \core\notification::add, or \core\output\notification as required' ,
2016-02-16 08:45:29 +08:00
DEBUG_DEVELOPER );
$n = new \core\output\notification ( $message , \core\output\notification :: NOTIFY_INFO );
2015-03-23 14:27:16 +08:00
return $this -> render ( $n );
}
/**
* Output a notification at a particular level - in this case , NOTIFY_REDIRECT .
*
* @ param string $message the message to print out
* @ return string HTML fragment .
2016-02-16 08:45:29 +08:00
* @ deprecated since Moodle 3.1 MDL - 30811 - please do not use this function any more .
* @ todo MDL - 53113 This will be removed in Moodle 3.5 .
* @ see \core\output\notification
2015-03-23 14:27:16 +08:00
*/
public function notify_redirect ( $message ) {
2016-02-16 08:45:29 +08:00
debugging ( __FUNCTION__ . ' is deprecated.' .
2016-02-16 08:48:39 +08:00
'Please use \core\notification::add, or \core\output\notification as required' ,
2016-02-16 08:45:29 +08:00
DEBUG_DEVELOPER );
$n = new \core\output\notification ( $message , \core\output\notification :: NOTIFY_INFO );
2015-03-23 14:27:16 +08:00
return $this -> render ( $n );
}
/**
* Render a notification ( that is , a status message about something that has
* just happened ) .
*
* @ param \core\output\notification $notification the notification to print out
* @ return string the HTML to output .
*/
protected function render_notification ( \core\output\notification $notification ) {
2016-02-16 08:45:29 +08:00
return $this -> render_from_template ( $notification -> get_template_name (), $notification -> export_for_template ( $this ));
2009-08-10 06:22:04 +00:00
}
/**
2012-01-05 13:28:08 +13:00
* Returns HTML to display a continue button that goes to a particular URL .
2009-08-10 06:22:04 +00:00
*
2010-01-14 19:18:04 +00:00
* @ param string | moodle_url $url The url the button goes to .
2009-08-10 06:22:04 +00:00
* @ return string the HTML to output .
*/
2010-01-14 19:18:04 +00:00
public function continue_button ( $url ) {
if ( ! ( $url instanceof moodle_url )) {
$url = new moodle_url ( $url );
2009-08-10 06:22:04 +00:00
}
2010-01-14 19:18:04 +00:00
$button = new single_button ( $url , get_string ( 'continue' ), 'get' );
$button -> class = 'continuebutton' ;
2009-08-10 06:22:04 +00:00
2010-01-14 19:18:04 +00:00
return $this -> render ( $button );
2009-08-10 06:22:04 +00:00
}
/**
2012-01-05 13:28:08 +13:00
* Returns HTML to display a single paging bar to provide access to other pages ( usually in a search )
2009-08-10 06:22:04 +00:00
*
2013-04-15 11:05:46 +10:00
* Theme developers : DO NOT OVERRIDE ! Please override function
* { @ link core_renderer :: render_paging_bar ()} instead .
*
2010-05-22 20:16:12 +00:00
* @ param int $totalcount The total number of entries available to be paged through
2010-02-17 16:59:41 +00:00
* @ param int $page The page you are currently viewing
* @ param int $perpage The number of entries that should be shown per page
* @ param string | moodle_url $baseurl url of the current page , the $pagevar parameter is added
* @ param string $pagevar name of page parameter that holds the page number
2009-08-10 06:22:04 +00:00
* @ return string the HTML to output .
*/
2010-02-17 16:59:41 +00:00
public function paging_bar ( $totalcount , $page , $perpage , $baseurl , $pagevar = 'page' ) {
$pb = new paging_bar ( $totalcount , $page , $perpage , $baseurl , $pagevar );
return $this -> render ( $pb );
}
/**
* Internal implementation of paging bar rendering .
2012-01-05 13:28:08 +13:00
*
2010-02-17 16:59:41 +00:00
* @ param paging_bar $pagingbar
* @ return string
*/
protected function render_paging_bar ( paging_bar $pagingbar ) {
2009-08-10 06:22:04 +00:00
$output = '' ;
$pagingbar = clone ( $pagingbar );
2009-12-27 12:58:29 +00:00
$pagingbar -> prepare ( $this , $this -> page , $this -> target );
2009-08-10 06:22:04 +00:00
if ( $pagingbar -> totalcount > $pagingbar -> perpage ) {
$output .= get_string ( 'page' ) . ':' ;
if ( ! empty ( $pagingbar -> previouslink )) {
2015-05-26 12:13:14 +08:00
$output .= ' (' . $pagingbar -> previouslink . ') ' ;
2009-08-10 06:22:04 +00:00
}
if ( ! empty ( $pagingbar -> firstlink )) {
2015-05-26 12:13:14 +08:00
$output .= ' ' . $pagingbar -> firstlink . ' ...' ;
2009-08-10 06:22:04 +00:00
}
foreach ( $pagingbar -> pagelinks as $link ) {
2015-05-26 12:13:14 +08:00
$output .= " $link " ;
2009-08-10 06:22:04 +00:00
}
if ( ! empty ( $pagingbar -> lastlink )) {
2016-03-29 23:28:25 +02:00
$output .= ' ... ' . $pagingbar -> lastlink . ' ' ;
2009-08-10 06:22:04 +00:00
}
if ( ! empty ( $pagingbar -> nextlink )) {
2015-05-26 12:13:14 +08:00
$output .= ' (' . $pagingbar -> nextlink . ')' ;
2009-08-10 06:22:04 +00:00
}
}
2010-02-18 18:15:56 +00:00
return html_writer :: tag ( 'div' , $output , array ( 'class' => 'paging' ));
2009-08-10 06:22:04 +00:00
}
/**
* Output the place a skip link goes to .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param string $id The target name from the corresponding $PAGE -> requires -> skip_link_to ( $target ) call .
* @ return string the HTML to output .
*/
2010-02-16 08:26:21 +00:00
public function skip_link_target ( $id = null ) {
2015-11-05 16:49:24 +08:00
return html_writer :: span ( '' , '' , array ( 'id' => $id ));
2009-08-10 06:22:04 +00:00
}
/**
* Outputs a heading
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param string $text The text of the heading
* @ param int $level The level of importance of the heading . Defaulting to 2
2013-08-29 10:30:02 +08:00
* @ param string $classes A space - separated list of CSS classes . Defaulting to null
2009-08-10 06:22:04 +00:00
* @ param string $id An optional ID
* @ return string the HTML to output .
*/
2013-08-29 10:30:02 +08:00
public function heading ( $text , $level = 2 , $classes = null , $id = null ) {
2009-08-10 06:22:04 +00:00
$level = ( integer ) $level ;
if ( $level < 1 or $level > 6 ) {
throw new coding_exception ( 'Heading level must be an integer between 1 and 6.' );
}
2010-02-18 18:15:56 +00:00
return html_writer :: tag ( 'h' . $level , $text , array ( 'id' => $id , 'class' => renderer_base :: prepare_classes ( $classes )));
2009-08-10 06:22:04 +00:00
}
/**
* Outputs a box .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param string $contents The contents of the box
* @ param string $classes A space - separated list of CSS classes
* @ param string $id An optional ID
2013-07-24 11:18:19 +12:00
* @ param array $attributes An array of other attributes to give the box .
2009-08-10 06:22:04 +00:00
* @ return string the HTML to output .
*/
2013-07-24 11:18:19 +12:00
public function box ( $contents , $classes = 'generalbox' , $id = null , $attributes = array ()) {
return $this -> box_start ( $classes , $id , $attributes ) . $contents . $this -> box_end ();
2009-08-10 06:22:04 +00:00
}
/**
2012-01-12 12:55:50 +13:00
* Outputs the opening section of a box .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param string $classes A space - separated list of CSS classes
* @ param string $id An optional ID
2013-07-24 11:18:19 +12:00
* @ param array $attributes An array of other attributes to give the box .
2009-08-10 06:22:04 +00:00
* @ return string the HTML to output .
*/
2013-07-24 11:18:19 +12:00
public function box_start ( $classes = 'generalbox' , $id = null , $attributes = array ()) {
2010-01-13 17:13:52 +00:00
$this -> opencontainers -> push ( 'box' , html_writer :: end_tag ( 'div' ));
2013-07-24 11:18:19 +12:00
$attributes [ 'id' ] = $id ;
$attributes [ 'class' ] = 'box ' . renderer_base :: prepare_classes ( $classes );
return html_writer :: start_tag ( 'div' , $attributes );
2009-08-10 06:22:04 +00:00
}
/**
* Outputs the closing section of a box .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ return string the HTML to output .
*/
public function box_end () {
return $this -> opencontainers -> pop ( 'box' );
}
/**
* Outputs a container .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param string $contents The contents of the box
* @ param string $classes A space - separated list of CSS classes
* @ param string $id An optional ID
* @ return string the HTML to output .
*/
2010-02-16 08:26:21 +00:00
public function container ( $contents , $classes = null , $id = null ) {
2009-08-10 06:22:04 +00:00
return $this -> container_start ( $classes , $id ) . $contents . $this -> container_end ();
}
/**
* Outputs the opening section of a container .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param string $classes A space - separated list of CSS classes
* @ param string $id An optional ID
* @ return string the HTML to output .
*/
2010-02-16 08:26:21 +00:00
public function container_start ( $classes = null , $id = null ) {
2010-01-13 17:13:52 +00:00
$this -> opencontainers -> push ( 'container' , html_writer :: end_tag ( 'div' ));
return html_writer :: start_tag ( 'div' , array ( 'id' => $id ,
2009-12-16 18:00:58 +00:00
'class' => renderer_base :: prepare_classes ( $classes )));
2009-08-10 06:22:04 +00:00
}
/**
* Outputs the closing section of a container .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ return string the HTML to output .
*/
public function container_end () {
return $this -> opencontainers -> pop ( 'container' );
}
2009-08-28 08:47:31 +00:00
2010-04-19 06:30:30 +00:00
/**
2009-08-28 08:47:31 +00:00
* Make nested HTML lists out of the items
*
* The resulting list will look something like this :
*
* < pre >
* << ul >>
* << li >>< div class = 'tree_item parent' > ( item contents ) </ div >
* << ul >
* << li >>< div class = 'tree_item' > ( item contents ) </ div ><</ li >>
* <</ ul >>
* <</ li >>
* <</ ul >>
* </ pre >
*
2012-01-05 13:28:08 +13:00
* @ param array $items
* @ param array $attrs html attributes passed to the top ofs the list
2009-08-28 08:47:31 +00:00
* @ return string HTML
*/
2012-01-05 13:28:08 +13:00
public function tree_block_contents ( $items , $attrs = array ()) {
2009-08-28 08:47:31 +00:00
// exit if empty, we don't want an empty ul element
if ( empty ( $items )) {
return '' ;
}
// array of nested li elements
$lis = array ();
foreach ( $items as $item ) {
// this applies to the li item which contains all child lists too
$content = $item -> content ( $this );
$liclasses = array ( $item -> get_css_type ());
2010-04-19 06:30:30 +00:00
if ( ! $item -> forceopen || ( ! $item -> forceopen && $item -> collapse ) || ( $item -> children -> count () == 0 && $item -> nodetype == navigation_node :: NODETYPE_BRANCH )) {
2009-08-28 08:47:31 +00:00
$liclasses [] = 'collapsed' ;
}
if ( $item -> isactive === true ) {
$liclasses [] = 'current_branch' ;
}
$liattr = array ( 'class' => join ( ' ' , $liclasses ));
// class attribute on the div item which only contains the item content
$divclasses = array ( 'tree_item' );
2010-04-19 06:30:30 +00:00
if ( $item -> children -> count () > 0 || $item -> nodetype == navigation_node :: NODETYPE_BRANCH ) {
2009-08-28 08:47:31 +00:00
$divclasses [] = 'branch' ;
} else {
$divclasses [] = 'leaf' ;
}
if ( ! empty ( $item -> classes ) && count ( $item -> classes ) > 0 ) {
$divclasses [] = join ( ' ' , $item -> classes );
}
$divattr = array ( 'class' => join ( ' ' , $divclasses ));
if ( ! empty ( $item -> id )) {
$divattr [ 'id' ] = $item -> id ;
}
2010-02-18 18:15:56 +00:00
$content = html_writer :: tag ( 'p' , $content , $divattr ) . $this -> tree_block_contents ( $item -> children );
2009-08-28 08:47:31 +00:00
if ( ! empty ( $item -> preceedwithhr ) && $item -> preceedwithhr === true ) {
2010-02-18 18:15:56 +00:00
$content = html_writer :: empty_tag ( 'hr' ) . $content ;
2009-08-28 08:47:31 +00:00
}
2010-02-18 18:15:56 +00:00
$content = html_writer :: tag ( 'li' , $content , $liattr );
2009-08-28 08:47:31 +00:00
$lis [] = $content ;
}
2010-02-18 18:15:56 +00:00
return html_writer :: tag ( 'ul' , implode ( " \n " , $lis ), $attrs );
2009-08-28 08:47:31 +00:00
}
2016-02-19 14:46:37 +08:00
/**
* Returns a search box .
*
* @ param string $id The search box wrapper div id , defaults to an autogenerated one .
* @ return string HTML with the search form hidden by default .
*/
public function search_box ( $id = false ) {
global $CFG ;
// Accessing $CFG directly as using \core_search::is_global_search_enabled would
// result in an extra included file for each site, even the ones where global search
// is disabled.
2016-02-23 10:44:20 +08:00
if ( empty ( $CFG -> enableglobalsearch ) || ! has_capability ( 'moodle/search:query' , context_system :: instance ())) {
2016-02-19 14:46:37 +08:00
return '' ;
}
if ( $id == false ) {
$id = uniqid ();
} else {
// Needs to be cleaned, we use it for the input id.
$id = clean_param ( $id , PARAM_ALPHANUMEXT );
}
// JS to animate the form.
$this -> page -> requires -> js_call_amd ( 'core/search-input' , 'init' , array ( $id ));
$searchicon = html_writer :: tag ( 'div' , $this -> pix_icon ( 'a/search' , get_string ( 'search' , 'search' ), 'moodle' ),
array ( 'role' => 'button' , 'tabindex' => 0 ));
$formattrs = array ( 'class' => 'search-input-form' , 'action' => $CFG -> wwwroot . '/search/index.php' );
$inputattrs = array ( 'type' => 'text' , 'name' => 'q' , 'placeholder' => get_string ( 'search' , 'search' ),
'size' => 13 , 'tabindex' => - 1 , 'id' => 'id_q_' . $id );
2016-02-23 10:44:20 +08:00
$contents = html_writer :: tag ( 'label' , get_string ( 'enteryoursearchquery' , 'search' ),
2016-02-19 14:46:37 +08:00
array ( 'for' => 'id_q_' . $id , 'class' => 'accesshide' )) . html_writer :: tag ( 'input' , '' , $inputattrs );
$searchinput = html_writer :: tag ( 'form' , $contents , $formattrs );
2016-10-31 10:34:12 +08:00
return html_writer :: tag ( 'div' , $searchicon . $searchinput , array ( 'class' => 'search-input-wrapper nav-link' , 'id' => $id ));
2016-02-19 14:46:37 +08:00
}
2016-06-16 07:47:53 +00:00
/**
2016-09-30 07:41:32 +00:00
* Allow plugins to provide some content to be rendered in the navbar .
* The plugin must define a PLUGIN_render_navbar_output function that returns
* the HTML they wish to add to the navbar .
2016-06-16 07:47:53 +00:00
*
2016-09-30 07:41:32 +00:00
* @ return string HTML for the navbar
2016-06-16 07:47:53 +00:00
*/
2016-09-30 07:41:32 +00:00
public function navbar_plugin_output () {
$output = '' ;
2016-07-07 05:12:41 +00:00
2016-09-30 07:41:32 +00:00
if ( $pluginsfunction = get_plugins_with_function ( 'render_navbar_output' )) {
foreach ( $pluginsfunction as $plugintype => $plugins ) {
foreach ( $plugins as $pluginfunction ) {
$output .= $pluginfunction ( $this );
}
}
2016-06-16 07:47:53 +00:00
}
2016-07-08 07:45:04 +00:00
2016-09-30 07:41:32 +00:00
return $output ;
2016-07-08 07:45:04 +00:00
}
2014-10-03 15:12:37 +08:00
/**
* Construct a user menu , returning HTML that can be echoed out by a
* layout file .
*
* @ param stdClass $user A user object , usually $USER .
* @ param bool $withlinks true if a dropdown should be built .
* @ return string HTML fragment .
*/
2014-10-03 17:02:02 +08:00
public function user_menu ( $user = null , $withlinks = null ) {
2014-10-03 15:12:37 +08:00
global $USER , $CFG ;
2014-10-03 17:02:02 +08:00
require_once ( $CFG -> dirroot . '/user/lib.php' );
2014-10-03 15:12:37 +08:00
if ( is_null ( $user )) {
$user = $USER ;
}
// Note: this behaviour is intended to match that of core_renderer::login_info,
// but should not be considered to be good practice; layout options are
// intended to be theme-specific. Please don't copy this snippet anywhere else.
if ( is_null ( $withlinks )) {
$withlinks = empty ( $this -> page -> layout_options [ 'nologinlinks' ]);
}
2014-10-03 17:02:02 +08:00
// Add a class for when $withlinks is false.
$usermenuclasses = 'usermenu' ;
if ( ! $withlinks ) {
$usermenuclasses .= ' withoutlinks' ;
}
2014-10-03 15:12:37 +08:00
$returnstr = " " ;
// If during initial install, return the empty return string.
if ( during_initial_install ()) {
return $returnstr ;
}
2014-12-18 08:40:57 +08:00
$loginpage = $this -> is_login_page ();
2014-10-03 15:12:37 +08:00
$loginurl = get_login_url ();
// If not logged in, show the typical not-logged-in string.
if ( ! isloggedin ()) {
$returnstr = get_string ( 'loggedinnot' , 'moodle' );
if ( ! $loginpage ) {
$returnstr .= " (<a href= \" $loginurl\ " > " . get_string('login') . '</a>)';
}
2014-10-03 17:02:02 +08:00
return html_writer :: div (
html_writer :: span (
$returnstr ,
'login'
),
$usermenuclasses
2014-10-03 15:12:37 +08:00
);
2014-10-03 17:02:02 +08:00
2014-10-03 15:12:37 +08:00
}
// If logged in as a guest user, show a string to that effect.
if ( isguestuser ()) {
$returnstr = get_string ( 'loggedinasguest' );
if ( ! $loginpage && $withlinks ) {
$returnstr .= " (<a href= \" $loginurl\ " > " .get_string('login').'</a>)';
}
2014-10-03 17:02:02 +08:00
return html_writer :: div (
html_writer :: span (
$returnstr ,
'login'
),
$usermenuclasses
2014-10-03 15:12:37 +08:00
);
}
// Get some navigation opts.
2015-07-15 11:48:43 +01:00
$opts = user_get_user_navigation_info ( $user , $this -> page );
2014-10-03 15:12:37 +08:00
$avatarclasses = " avatars " ;
$avatarcontents = html_writer :: span ( $opts -> metadata [ 'useravatar' ], 'avatar current' );
$usertextcontents = $opts -> metadata [ 'userfullname' ];
// Other user.
if ( ! empty ( $opts -> metadata [ 'asotheruser' ])) {
$avatarcontents .= html_writer :: span (
$opts -> metadata [ 'realuseravatar' ],
'avatar realuser'
);
$usertextcontents = $opts -> metadata [ 'realuserfullname' ];
$usertextcontents .= html_writer :: tag (
'span' ,
get_string (
'loggedinas' ,
'moodle' ,
html_writer :: span (
$opts -> metadata [ 'userfullname' ],
'value'
)
),
array ( 'class' => 'meta viewingas' )
);
}
// Role.
if ( ! empty ( $opts -> metadata [ 'asotherrole' ])) {
$role = core_text :: strtolower ( preg_replace ( '#[ ]+#' , '-' , trim ( $opts -> metadata [ 'rolename' ])));
$usertextcontents .= html_writer :: span (
$opts -> metadata [ 'rolename' ],
'meta role role-' . $role
);
}
// User login failures.
if ( ! empty ( $opts -> metadata [ 'userloginfail' ])) {
$usertextcontents .= html_writer :: span (
$opts -> metadata [ 'userloginfail' ],
'meta loginfailures'
);
}
// MNet.
if ( ! empty ( $opts -> metadata [ 'asmnetuser' ])) {
$mnet = strtolower ( preg_replace ( '#[ ]+#' , '-' , trim ( $opts -> metadata [ 'mnetidprovidername' ])));
$usertextcontents .= html_writer :: span (
$opts -> metadata [ 'mnetidprovidername' ],
'meta mnet mnet-' . $mnet
);
}
$returnstr .= html_writer :: span (
2014-10-03 17:02:02 +08:00
html_writer :: span ( $usertextcontents , 'usertext' ) .
html_writer :: span ( $avatarcontents , $avatarclasses ),
2014-10-03 15:12:37 +08:00
'userbutton'
);
// Create a divider (well, a filler).
$divider = new action_menu_filler ();
$divider -> primary = false ;
$am = new action_menu ();
2014-10-10 17:17:54 +08:00
$am -> set_menu_trigger (
$returnstr
);
2014-10-03 15:12:37 +08:00
$am -> set_alignment ( action_menu :: TR , action_menu :: BR );
2014-11-03 13:44:58 +13:00
$am -> set_nowrap_on_items ();
2014-10-03 15:12:37 +08:00
if ( $withlinks ) {
$navitemcount = count ( $opts -> navitems );
$idx = 0 ;
foreach ( $opts -> navitems as $key => $value ) {
2014-12-15 09:05:35 +08:00
switch ( $value -> itemtype ) {
case 'divider' :
// If the nav item is a divider, add one and skip link processing.
$am -> add ( $divider );
break ;
case 'invalid' :
// Silently skip invalid entries (should we post a notification?).
break ;
case 'link' :
// Process this as a link item.
$pix = null ;
if ( isset ( $value -> pix ) && ! empty ( $value -> pix )) {
$pix = new pix_icon ( $value -> pix , $value -> title , null , array ( 'class' => 'iconsmall' ));
} else if ( isset ( $value -> imgsrc ) && ! empty ( $value -> imgsrc )) {
$value -> title = html_writer :: img (
$value -> imgsrc ,
$value -> title ,
array ( 'class' => 'iconsmall' )
) . $value -> title ;
}
2016-03-22 08:26:59 +08:00
2014-12-15 09:05:35 +08:00
$al = new action_menu_link_secondary (
$value -> url ,
$pix ,
$value -> title ,
array ( 'class' => 'icon' )
);
2016-03-22 08:26:59 +08:00
if ( ! empty ( $value -> titleidentifier )) {
$al -> attributes [ 'data-title' ] = $value -> titleidentifier ;
}
2014-12-15 09:05:35 +08:00
$am -> add ( $al );
break ;
2014-10-03 15:12:37 +08:00
}
$idx ++ ;
2015-01-28 12:00:11 +08:00
// Add dividers after the first item and before the last item.
if ( $idx == 1 || $idx == $navitemcount - 1 ) {
$am -> add ( $divider );
}
2014-10-03 15:12:37 +08:00
}
}
return html_writer :: div (
$this -> render ( $am ),
$usermenuclasses
);
}
2009-08-28 08:47:31 +00:00
/**
* Return the navbar content so that it can be echoed out by the layout
2012-01-05 13:28:08 +13:00
*
2009-08-28 08:47:31 +00:00
* @ return string XHTML navbar
*/
public function navbar () {
2010-04-19 06:30:30 +00:00
$items = $this -> page -> navbar -> get_items ();
2013-06-07 10:38:39 +12:00
$itemcount = count ( $items );
if ( $itemcount === 0 ) {
return '' ;
}
2010-04-19 06:30:30 +00:00
$htmlblocks = array ();
// Iterate the navarray and display each node
2010-04-27 05:19:32 +00:00
$separator = get_separator ();
for ( $i = 0 ; $i < $itemcount ; $i ++ ) {
$item = $items [ $i ];
2010-04-23 04:21:33 +00:00
$item -> hideicon = true ;
2010-04-27 05:19:32 +00:00
if ( $i === 0 ) {
$content = html_writer :: tag ( 'li' , $this -> render ( $item ));
} else {
$content = html_writer :: tag ( 'li' , $separator . $this -> render ( $item ));
}
$htmlblocks [] = $content ;
2010-04-19 06:30:30 +00:00
}
2010-06-23 09:13:23 +00:00
//accessibility: heading for navbar list (MDL-20446)
2016-04-18 16:56:34 +01:00
$navbarcontent = html_writer :: tag ( 'span' , get_string ( 'pagepath' ),
array ( 'class' => 'accesshide' , 'id' => 'navbar-label' ));
$navbarcontent .= html_writer :: tag ( 'nav' ,
html_writer :: tag ( 'ul' , join ( '' , $htmlblocks )),
array ( 'aria-labelledby' => 'navbar-label' ));
2010-04-19 06:30:30 +00:00
// XHTML
2010-06-23 09:13:23 +00:00
return $navbarcontent ;
2010-04-19 06:30:30 +00:00
}
2015-10-12 17:11:28 +11:00
/**
* Renders a breadcrumb navigation node object .
*
* @ param breadcrumb_navigation_node $item The navigation node to render .
* @ return string HTML fragment
*/
protected function render_breadcrumb_navigation_node ( breadcrumb_navigation_node $item ) {
if ( $item -> action instanceof moodle_url ) {
$content = $item -> get_content ();
$title = $item -> get_title ();
$attributes = array ();
$attributes [ 'itemprop' ] = 'url' ;
if ( $title !== '' ) {
$attributes [ 'title' ] = $title ;
}
if ( $item -> hidden ) {
$attributes [ 'class' ] = 'dimmed_text' ;
}
$content = html_writer :: tag ( 'span' , $content , array ( 'itemprop' => 'title' ));
$content = html_writer :: link ( $item -> action , $content , $attributes );
$attributes = array ();
$attributes [ 'itemscope' ] = '' ;
$attributes [ 'itemtype' ] = 'http://data-vocabulary.org/Breadcrumb' ;
$content = html_writer :: tag ( 'span' , $content , $attributes );
} else {
$content = $this -> render_navigation_node ( $item );
}
return $content ;
}
2012-01-05 13:28:08 +13:00
/**
* Renders a navigation node object .
*
* @ param navigation_node $item The navigation node to render .
* @ return string HTML fragment
*/
2010-04-19 06:30:30 +00:00
protected function render_navigation_node ( navigation_node $item ) {
$content = $item -> get_content ();
$title = $item -> get_title ();
2010-04-23 04:21:33 +00:00
if ( $item -> icon instanceof renderable && ! $item -> hideicon ) {
2010-04-19 06:30:30 +00:00
$icon = $this -> render ( $item -> icon );
2010-06-03 08:27:03 +00:00
$content = $icon . $content ; // use CSS for spacing of icons
2010-04-19 06:30:30 +00:00
}
if ( $item -> helpbutton !== null ) {
2011-05-10 16:44:18 +08:00
$content = trim ( $item -> helpbutton ) . html_writer :: tag ( 'span' , $content , array ( 'class' => 'clearhelpbutton' , 'tabindex' => '0' ));
2010-04-19 06:30:30 +00:00
}
if ( $content === '' ) {
2010-05-11 15:47:12 +00:00
return '' ;
2010-04-19 06:30:30 +00:00
}
if ( $item -> action instanceof action_link ) {
$link = $item -> action ;
if ( $item -> hidden ) {
$link -> add_class ( 'dimmed' );
}
2012-04-11 10:56:49 +12:00
if ( ! empty ( $content )) {
// Providing there is content we will use that for the link content.
$link -> text = $content ;
}
2011-02-11 16:26:20 +08:00
$content = $this -> render ( $link );
2010-04-19 06:30:30 +00:00
} else if ( $item -> action instanceof moodle_url ) {
$attributes = array ();
if ( $title !== '' ) {
$attributes [ 'title' ] = $title ;
}
if ( $item -> hidden ) {
$attributes [ 'class' ] = 'dimmed_text' ;
}
$content = html_writer :: link ( $item -> action , $content , $attributes );
} else if ( is_string ( $item -> action ) || empty ( $item -> action )) {
2011-05-10 16:44:18 +08:00
$attributes = array ( 'tabindex' => '0' ); //add tab support to span but still maintain character stream sequence.
2010-04-19 06:30:30 +00:00
if ( $title !== '' ) {
$attributes [ 'title' ] = $title ;
}
if ( $item -> hidden ) {
$attributes [ 'class' ] = 'dimmed_text' ;
}
$content = html_writer :: tag ( 'span' , $content , $attributes );
}
return $content ;
2009-08-28 08:47:31 +00:00
}
2009-12-23 17:44:17 +00:00
/**
* Accessibility : Right arrow - like character is
* used in the breadcrumb trail , course navigation menu
* ( previous / next activity ), calendar , and search forum block .
* If the theme does not set characters , appropriate defaults
* are set automatically . Please DO NOT
* use & lt ; & gt ; & raquo ; - these are confusing for blind users .
2012-01-05 13:28:08 +13:00
*
2009-12-23 17:44:17 +00:00
* @ return string
*/
public function rarrow () {
return $this -> page -> theme -> rarrow ;
}
/**
2012-09-12 16:13:43 +02:00
* Accessibility : Left arrow - like character is
2009-12-23 17:44:17 +00:00
* used in the breadcrumb trail , course navigation menu
* ( previous / next activity ), calendar , and search forum block .
* If the theme does not set characters , appropriate defaults
* are set automatically . Please DO NOT
* use & lt ; & gt ; & raquo ; - these are confusing for blind users .
2012-01-05 13:28:08 +13:00
*
2009-12-23 17:44:17 +00:00
* @ return string
*/
public function larrow () {
return $this -> page -> theme -> larrow ;
}
2009-12-23 17:51:41 +00:00
2014-10-28 09:29:28 +00:00
/**
* Accessibility : Up arrow - like character is used in
* the book heirarchical navigation .
* If the theme does not set characters , appropriate defaults
* are set automatically . Please DO NOT
* use ^ - this is confusing for blind users .
*
* @ return string
*/
public function uarrow () {
return $this -> page -> theme -> uarrow ;
}
2016-07-19 15:06:00 +08:00
/**
* Accessibility : Down arrow - like character .
* If the theme does not set characters , appropriate defaults
* are set automatically .
*
* @ return string
*/
public function darrow () {
return $this -> page -> theme -> darrow ;
}
2010-05-10 05:24:00 +00:00
/**
* Returns the custom menu if one has been set
*
2010-05-22 20:16:12 +00:00
* A custom menu can be configured by browsing to
2010-05-10 05:24:00 +00:00
* Settings : Administration > Appearance > Themes > Theme settings
* and then configuring the custommenu config setting as described .
2010-05-19 08:05:36 +00:00
*
2013-04-15 11:05:46 +10:00
* Theme developers : DO NOT OVERRIDE ! Please override function
* { @ link core_renderer :: render_custom_menu ()} instead .
*
2012-01-06 12:48:01 +13:00
* @ param string $custommenuitems - custom menuitems set by theme instead of global theme settings
2010-05-10 05:24:00 +00:00
* @ return string
*/
2012-01-06 12:48:01 +13:00
public function custom_menu ( $custommenuitems = '' ) {
2010-05-11 07:30:04 +00:00
global $CFG ;
2012-01-06 12:48:01 +13:00
if ( empty ( $custommenuitems ) && ! empty ( $CFG -> custommenuitems )) {
$custommenuitems = $CFG -> custommenuitems ;
}
if ( empty ( $custommenuitems )) {
2010-05-11 07:30:04 +00:00
return '' ;
}
2012-01-06 12:48:01 +13:00
$custommenu = new custom_menu ( $custommenuitems , current_language ());
2013-04-15 11:05:46 +10:00
return $this -> render ( $custommenu );
2010-05-10 05:24:00 +00:00
}
/**
* Renders a custom menu object ( located in outputcomponents . php )
*
* The custom menu this method produces makes use of the YUI3 menunav widget
* and requires very specific html elements and classes .
*
* @ staticvar int $menucount
* @ param custom_menu $menu
* @ return string
*/
protected function render_custom_menu ( custom_menu $menu ) {
static $menucount = 0 ;
// If the menu has no children return an empty string
if ( ! $menu -> has_children ()) {
return '' ;
}
// Increment the menu count. This is used for ID's that get worked with
// in JavaScript as is essential
$menucount ++ ;
2011-07-27 16:35:07 +08:00
// Initialise this custom menu (the custom menu object is contained in javascript-static
$jscode = js_writer :: function_call_with_Y ( 'M.core_custom_menu.init' , array ( 'custom_menu_' . $menucount ));
$jscode = " (function() { { $jscode } }) " ;
$this -> page -> requires -> yui_module ( 'node-menunav' , $jscode );
2010-05-10 05:24:00 +00:00
// Build the root nodes as required by YUI
2013-06-07 10:38:39 +12:00
$content = html_writer :: start_tag ( 'div' , array ( 'id' => 'custom_menu_' . $menucount , 'class' => 'yui3-menu yui3-menu-horizontal javascript-disabled custom-menu' ));
2010-05-10 05:24:00 +00:00
$content .= html_writer :: start_tag ( 'div' , array ( 'class' => 'yui3-menu-content' ));
$content .= html_writer :: start_tag ( 'ul' );
// Render each child
foreach ( $menu -> get_children () as $item ) {
$content .= $this -> render_custom_menu_item ( $item );
}
// Close the open tags
$content .= html_writer :: end_tag ( 'ul' );
$content .= html_writer :: end_tag ( 'div' );
$content .= html_writer :: end_tag ( 'div' );
// Return the custom menu
return $content ;
}
/**
* Renders a custom menu node as part of a submenu
*
* The custom menu this method produces makes use of the YUI3 menunav widget
* and requires very specific html elements and classes .
*
2012-01-05 13:28:08 +13:00
* @ see core : renderer :: render_custom_menu ()
2010-05-10 05:24:00 +00:00
*
* @ staticvar int $submenucount
* @ param custom_menu_item $menunode
* @ return string
*/
protected function render_custom_menu_item ( custom_menu_item $menunode ) {
// Required to ensure we get unique trackable id's
static $submenucount = 0 ;
if ( $menunode -> has_children ()) {
// If the child has menus render it as a sub menu
$submenucount ++ ;
$content = html_writer :: start_tag ( 'li' );
if ( $menunode -> get_url () !== null ) {
$url = $menunode -> get_url ();
} else {
$url = '#cm_submenu_' . $submenucount ;
}
$content .= html_writer :: link ( $url , $menunode -> get_text (), array ( 'class' => 'yui3-menu-label' , 'title' => $menunode -> get_title ()));
$content .= html_writer :: start_tag ( 'div' , array ( 'id' => 'cm_submenu_' . $submenucount , 'class' => 'yui3-menu custom_menu_submenu' ));
$content .= html_writer :: start_tag ( 'div' , array ( 'class' => 'yui3-menu-content' ));
$content .= html_writer :: start_tag ( 'ul' );
foreach ( $menunode -> get_children () as $menunode ) {
$content .= $this -> render_custom_menu_item ( $menunode );
}
$content .= html_writer :: end_tag ( 'ul' );
$content .= html_writer :: end_tag ( 'div' );
$content .= html_writer :: end_tag ( 'div' );
$content .= html_writer :: end_tag ( 'li' );
} else {
2014-06-18 15:45:40 +08:00
// The node doesn't have children so produce a final menuitem.
// Also, if the node's text matches '####', add a class so we can treat it as a divider.
$content = '' ;
if ( preg_match ( " /^#+ $ / " , $menunode -> get_text ())) {
// This is a divider.
$content = html_writer :: start_tag ( 'li' , array ( 'class' => 'yui3-menuitem divider' ));
2010-05-10 05:24:00 +00:00
} else {
2014-06-18 15:45:40 +08:00
$content = html_writer :: start_tag (
'li' ,
array (
'class' => 'yui3-menuitem'
)
);
if ( $menunode -> get_url () !== null ) {
$url = $menunode -> get_url ();
} else {
$url = '#' ;
}
$content .= html_writer :: link (
$url ,
$menunode -> get_text (),
array ( 'class' => 'yui3-menuitem-content' , 'title' => $menunode -> get_title ())
);
2010-05-10 05:24:00 +00:00
}
$content .= html_writer :: end_tag ( 'li' );
}
// Return the sub menu
return $content ;
}
2011-05-31 14:25:52 +08:00
2011-05-31 14:28:03 +08:00
/**
2011-05-31 14:25:52 +08:00
* Renders theme links for switching between default and other themes .
2011-05-31 14:28:03 +08:00
*
* @ return string
2011-05-31 14:25:52 +08:00
*/
protected function theme_switch_links () {
2013-07-30 17:00:54 +12:00
$actualdevice = core_useragent :: get_device_type ();
2011-05-31 14:28:03 +08:00
$currentdevice = $this -> page -> devicetypeinuse ;
$switched = ( $actualdevice != $currentdevice );
2011-05-31 14:25:52 +08:00
2011-05-31 14:28:03 +08:00
if ( ! $switched && $currentdevice == 'default' && $actualdevice == 'default' ) {
// The user is using the a default device and hasn't switched so don't shown the switch
// device links.
2011-05-31 14:25:52 +08:00
return '' ;
}
if ( $switched ) {
$linktext = get_string ( 'switchdevicerecommended' );
2011-05-31 14:28:03 +08:00
$devicetype = $actualdevice ;
2011-05-31 14:25:52 +08:00
} else {
$linktext = get_string ( 'switchdevicedefault' );
2011-05-31 14:28:03 +08:00
$devicetype = 'default' ;
2011-05-31 14:25:52 +08:00
}
2011-05-31 14:28:03 +08:00
$linkurl = new moodle_url ( '/theme/switchdevice.php' , array ( 'url' => $this -> page -> url , 'device' => $devicetype , 'sesskey' => sesskey ()));
2011-05-31 14:25:52 +08:00
2011-05-31 14:28:03 +08:00
$content = html_writer :: start_tag ( 'div' , array ( 'id' => 'theme_switch_link' ));
2015-01-23 16:02:49 +00:00
$content .= html_writer :: link ( $linkurl , $linktext , array ( 'rel' => 'nofollow' ));
2011-05-31 14:25:52 +08:00
$content .= html_writer :: end_tag ( 'div' );
return $content ;
}
2013-04-11 19:06:52 +10:00
/**
* Renders tabs
*
* This function replaces print_tabs () used before Moodle 2.5 but with slightly different arguments
*
2013-04-15 11:05:46 +10:00
* Theme developers : In order to change how tabs are displayed please override functions
* { @ link core_renderer :: render_tabtree ()} and / or { @ link core_renderer :: render_tabobject ()}
*
2013-04-11 19:06:52 +10:00
* @ param array $tabs array of tabs , each of them may have it ' s own -> subtree
* @ param string | null $selected which tab to mark as selected , all parent tabs will
* automatically be marked as activated
* @ param array | string | null $inactive list of ids of inactive tabs , regardless of
* their level . Note that you can as weel specify tabobject :: $inactive for separate instances
* @ return string
*/
2013-04-15 11:05:46 +10:00
public final function tabtree ( $tabs , $selected = null , $inactive = null ) {
2013-04-11 19:06:52 +10:00
return $this -> render ( new tabtree ( $tabs , $selected , $inactive ));
}
/**
* Renders tabtree
*
* @ param tabtree $tabtree
* @ return string
*/
protected function render_tabtree ( tabtree $tabtree ) {
if ( empty ( $tabtree -> subtree )) {
return '' ;
}
$str = '' ;
$str .= html_writer :: start_tag ( 'div' , array ( 'class' => 'tabtree' ));
$str .= $this -> render_tabobject ( $tabtree );
$str .= html_writer :: end_tag ( 'div' ) .
html_writer :: tag ( 'div' , ' ' , array ( 'class' => 'clearer' ));
2013-04-15 10:26:53 +01:00
return $str ;
2013-04-11 19:06:52 +10:00
}
/**
* Renders tabobject ( part of tabtree )
*
* This function is called from { @ link core_renderer :: render_tabtree ()}
* and also it calls itself when printing the $tabobject subtree recursively .
*
* Property $tabobject -> level indicates the number of row of tabs .
*
* @ param tabobject $tabobject
* @ return string HTML fragment
*/
protected function render_tabobject ( tabobject $tabobject ) {
$str = '' ;
// Print name of the current tab.
if ( $tabobject instanceof tabtree ) {
// No name for tabtree root.
} else if ( $tabobject -> inactive || $tabobject -> activated || ( $tabobject -> selected && ! $tabobject -> linkedwhenselected )) {
// Tab name without a link. The <a> tag is used for styling.
2013-11-06 10:11:31 +08:00
$str .= html_writer :: tag ( 'a' , html_writer :: span ( $tabobject -> text ), array ( 'class' => 'nolink moodle-has-zindex' ));
2013-04-11 19:06:52 +10:00
} else {
// Tab name with a link.
if ( ! ( $tabobject -> link instanceof moodle_url )) {
// backward compartibility when link was passed as quoted string
$str .= " <a href= \" $tabobject->link\ " title = \ " $tabobject->title\ " >< span > $tabobject -> text </ span ></ a > " ;
} else {
$str .= html_writer :: link ( $tabobject -> link , html_writer :: span ( $tabobject -> text ), array ( 'title' => $tabobject -> title ));
}
}
if ( empty ( $tabobject -> subtree )) {
if ( $tabobject -> selected ) {
$str .= html_writer :: tag ( 'div' , ' ' , array ( 'class' => 'tabrow' . ( $tabobject -> level + 1 ) . ' empty' ));
}
return $str ;
}
2015-11-09 23:22:53 +00:00
// Print subtree.
if ( $tabobject -> level == 0 || $tabobject -> selected || $tabobject -> activated ) {
$str .= html_writer :: start_tag ( 'ul' , array ( 'class' => 'tabrow' . $tabobject -> level ));
$cnt = 0 ;
foreach ( $tabobject -> subtree as $tab ) {
$liclass = '' ;
if ( ! $cnt ) {
$liclass .= ' first' ;
}
if ( $cnt == count ( $tabobject -> subtree ) - 1 ) {
$liclass .= ' last' ;
}
if (( empty ( $tab -> subtree )) && ( ! empty ( $tab -> selected ))) {
$liclass .= ' onerow' ;
}
2013-04-11 19:06:52 +10:00
2015-11-09 23:22:53 +00:00
if ( $tab -> selected ) {
$liclass .= ' here selected' ;
} else if ( $tab -> activated ) {
$liclass .= ' here active' ;
}
2013-04-11 19:06:52 +10:00
2015-11-09 23:22:53 +00:00
// This will recursively call function render_tabobject() for each item in subtree.
$str .= html_writer :: tag ( 'li' , $this -> render ( $tab ), array ( 'class' => trim ( $liclass )));
$cnt ++ ;
}
$str .= html_writer :: end_tag ( 'ul' );
2013-04-11 19:06:52 +10:00
}
return $str ;
}
2013-06-07 10:32:52 +12:00
/**
* Get the HTML for blocks in the given region .
*
2014-05-19 17:03:04 +01:00
* @ since Moodle 2.5 . 1 2.6
2013-06-07 10:32:52 +12:00
* @ param string $region The region to get HTML for .
* @ return string HTML .
*/
public function blocks ( $region , $classes = array (), $tag = 'aside' ) {
2013-06-10 09:10:06 +12:00
$displayregion = $this -> page -> apply_theme_region_manipulations ( $region );
2013-06-07 10:32:52 +12:00
$classes = ( array ) $classes ;
$classes [] = 'block-region' ;
$attributes = array (
2013-06-10 09:10:06 +12:00
'id' => 'block-region-' . preg_replace ( '#[^a-zA-Z0-9_\-]+#' , '-' , $displayregion ),
2013-06-07 10:32:52 +12:00
'class' => join ( ' ' , $classes ),
2013-06-10 09:10:06 +12:00
'data-blockregion' => $displayregion ,
2013-06-07 10:32:52 +12:00
'data-droptarget' => '1'
);
2013-11-17 13:33:30 +00:00
if ( $this -> page -> blocks -> region_has_content ( $displayregion , $this )) {
$content = $this -> blocks_for_region ( $displayregion );
2013-11-02 00:43:48 +00:00
} else {
$content = '' ;
}
return html_writer :: tag ( $tag , $content , $attributes );
2013-06-07 10:32:52 +12:00
}
2013-06-07 10:34:02 +12:00
2014-02-24 10:38:17 +13:00
/**
* Renders a custom block region .
*
* Use this method if you want to add an additional block region to the content of the page .
* Please note this should only be used in special situations .
* We want to leave the theme is control where ever possible !
*
* This method must use the same method that the theme uses within its layout file .
* As such it asks the theme what method it is using .
* It can be one of two values , blocks or blocks_for_region ( deprecated ) .
*
* @ param string $regionname The name of the custom region to add .
* @ return string HTML for the block region .
*/
public function custom_block_region ( $regionname ) {
if ( $this -> page -> theme -> get_block_render_method () === 'blocks' ) {
return $this -> blocks ( $regionname );
} else {
return $this -> blocks_for_region ( $regionname );
}
}
2013-06-07 10:34:02 +12:00
/**
* Returns the CSS classes to apply to the body tag .
*
2014-05-19 17:03:04 +01:00
* @ since Moodle 2.5 . 1 2.6
2013-06-07 10:34:02 +12:00
* @ param array $additionalclasses Any additional classes to apply .
* @ return string
*/
public function body_css_classes ( array $additionalclasses = array ()) {
// Add a class for each block region on the page.
// We use the block manager here because the theme object makes get_string calls.
2015-02-05 12:04:41 +08:00
$usedregions = array ();
2013-06-07 10:34:02 +12:00
foreach ( $this -> page -> blocks -> get_regions () as $region ) {
$additionalclasses [] = 'has-region-' . $region ;
if ( $this -> page -> blocks -> region_has_content ( $region , $this )) {
$additionalclasses [] = 'used-region-' . $region ;
2015-02-05 12:04:41 +08:00
$usedregions [] = $region ;
2013-06-07 10:34:02 +12:00
} else {
$additionalclasses [] = 'empty-region-' . $region ;
}
2014-01-09 11:50:50 +13:00
if ( $this -> page -> blocks -> region_completely_docked ( $region , $this )) {
$additionalclasses [] = 'docked-region-' . $region ;
}
2013-06-07 10:34:02 +12:00
}
2015-08-26 09:32:07 +08:00
if ( ! $usedregions ) {
// No regions means there is only content, add 'content-only' class.
$additionalclasses [] = 'content-only' ;
} else if ( count ( $usedregions ) === 1 ) {
2015-02-05 12:04:41 +08:00
// Add the -only class for the only used region.
$region = array_shift ( $usedregions );
$additionalclasses [] = $region . '-only' ;
}
2013-06-07 10:34:02 +12:00
foreach ( $this -> page -> layout_options as $option => $value ) {
if ( $value ) {
$additionalclasses [] = 'layout-option-' . $option ;
}
}
$css = $this -> page -> bodyclasses . ' ' . join ( ' ' , $additionalclasses );
return $css ;
}
/**
* The ID attribute to apply to the body tag .
*
2014-05-19 17:03:04 +01:00
* @ since Moodle 2.5 . 1 2.6
2013-06-07 10:34:02 +12:00
* @ return string
*/
public function body_id () {
return $this -> page -> bodyid ;
}
/**
* Returns HTML attributes to use within the body tag . This includes an ID and classes .
*
2014-05-19 17:03:04 +01:00
* @ since Moodle 2.5 . 1 2.6
2013-06-07 10:34:02 +12:00
* @ param string | array $additionalclasses Any additional classes to give the body tag ,
* @ return string
*/
public function body_attributes ( $additionalclasses = array ()) {
if ( ! is_array ( $additionalclasses )) {
$additionalclasses = explode ( ' ' , $additionalclasses );
}
return ' id="' . $this -> body_id () . '" class="' . $this -> body_css_classes ( $additionalclasses ) . '"' ;
}
2013-06-07 10:35:38 +12:00
/**
* Gets HTML for the page heading .
*
2014-05-19 17:03:04 +01:00
* @ since Moodle 2.5 . 1 2.6
2013-06-07 10:35:38 +12:00
* @ param string $tag The tag to encase the heading in . h1 by default .
* @ return string HTML .
*/
public function page_heading ( $tag = 'h1' ) {
return html_writer :: tag ( $tag , $this -> page -> heading );
}
/**
* Gets the HTML for the page heading button .
*
2014-05-19 17:03:04 +01:00
* @ since Moodle 2.5 . 1 2.6
2013-06-07 10:35:38 +12:00
* @ return string HTML .
*/
public function page_heading_button () {
return $this -> page -> button ;
}
/**
* Returns the Moodle docs link to use for this page .
*
2014-05-19 17:03:04 +01:00
* @ since Moodle 2.5 . 1 2.6
2013-06-07 10:35:38 +12:00
* @ param string $text
* @ return string
*/
public function page_doc_link ( $text = null ) {
if ( $text === null ) {
$text = get_string ( 'moodledocslink' );
}
$path = page_get_doc_link_path ( $this -> page );
if ( ! $path ) {
return '' ;
}
return $this -> doc_link ( $path , $text );
}
/**
* Returns the page heading menu .
*
2014-05-19 17:03:04 +01:00
* @ since Moodle 2.5 . 1 2.6
2013-06-07 10:35:38 +12:00
* @ return string HTML .
*/
public function page_heading_menu () {
return $this -> page -> headingmenu ;
}
/**
* Returns the title to use on the page .
*
2014-05-19 17:03:04 +01:00
* @ since Moodle 2.5 . 1 2.6
2013-06-07 10:35:38 +12:00
* @ return string
*/
public function page_title () {
return $this -> page -> title ;
}
/**
* Returns the URL for the favicon .
*
2014-05-19 17:03:04 +01:00
* @ since Moodle 2.5 . 1 2.6
2013-06-07 10:35:38 +12:00
* @ return string The favicon URL
*/
public function favicon () {
return $this -> pix_url ( 'favicon' , 'theme' );
}
2015-01-30 18:24:18 +08:00
/**
* Renders preferences groups .
*
* @ param preferences_groups $renderable The renderable
* @ return string The output .
*/
public function render_preferences_groups ( preferences_groups $renderable ) {
$html = '' ;
2015-03-27 16:17:30 +08:00
$html .= html_writer :: start_div ( 'row-fluid' );
2015-01-30 18:24:18 +08:00
$html .= html_writer :: start_tag ( 'div' , array ( 'class' => 'span12 preferences-groups' ));
$i = 0 ;
$open = false ;
foreach ( $renderable -> groups as $group ) {
if ( $i == 0 || $i % 3 == 0 ) {
if ( $open ) {
$html .= html_writer :: end_tag ( 'div' );
}
2015-03-27 16:17:30 +08:00
$html .= html_writer :: start_tag ( 'div' , array ( 'class' => 'row-fluid' ));
2015-01-30 18:24:18 +08:00
$open = true ;
}
$html .= $this -> render ( $group );
$i ++ ;
}
$html .= html_writer :: end_tag ( 'div' );
$html .= html_writer :: end_tag ( 'ul' );
$html .= html_writer :: end_tag ( 'div' );
2015-03-27 16:17:30 +08:00
$html .= html_writer :: end_div ();
2015-01-30 18:24:18 +08:00
return $html ;
}
/**
* Renders preferences group .
*
* @ param preferences_group $renderable The renderable
* @ return string The output .
*/
public function render_preferences_group ( preferences_group $renderable ) {
$html = '' ;
$html .= html_writer :: start_tag ( 'div' , array ( 'class' => 'span4 preferences-group' ));
$html .= $this -> heading ( $renderable -> title , 3 );
$html .= html_writer :: start_tag ( 'ul' );
foreach ( $renderable -> nodes as $node ) {
if ( $node -> has_children ()) {
debugging ( 'Preferences nodes do not support children' , DEBUG_DEVELOPER );
}
$html .= html_writer :: tag ( 'li' , $this -> render ( $node ));
}
$html .= html_writer :: end_tag ( 'ul' );
$html .= html_writer :: end_tag ( 'div' );
return $html ;
}
2015-02-17 13:35:02 +08:00
2015-04-08 12:45:46 +08:00
public function context_header ( $headerinfo = null , $headinglevel = 1 ) {
2015-09-08 12:10:07 +08:00
global $DB , $USER , $CFG ;
2015-02-17 13:35:02 +08:00
$context = $this -> page -> context ;
2015-04-08 12:45:46 +08:00
// Make sure to use the heading if it has been set.
if ( isset ( $headerinfo [ 'heading' ])) {
$heading = $headerinfo [ 'heading' ];
} else {
$heading = null ;
}
2015-02-17 13:35:02 +08:00
$imagedata = null ;
$subheader = null ;
$userbuttons = null ;
2015-04-08 12:45:46 +08:00
// The user context currently has images and buttons. Other contexts may follow.
if ( isset ( $headerinfo [ 'user' ]) || $context -> contextlevel == CONTEXT_USER ) {
if ( isset ( $headerinfo [ 'user' ])) {
$user = $headerinfo [ 'user' ];
} else {
// Look up the user information if it is not supplied.
$user = $DB -> get_record ( 'user' , array ( 'id' => $context -> instanceid ));
}
// If the user context is set, then use that for capability checks.
if ( isset ( $headerinfo [ 'usercontext' ])) {
$context = $headerinfo [ 'usercontext' ];
}
// Use the user's full name if the heading isn't set.
if ( ! isset ( $heading )) {
$heading = fullname ( $user );
}
$imagedata = $this -> user_picture ( $user , array ( 'size' => 100 ));
// Check to see if we should be displaying a message button.
2015-09-08 12:10:07 +08:00
if ( ! empty ( $CFG -> messaging ) && $USER -> id != $user -> id && has_capability ( 'moodle/site:sendmessage' , $context )) {
2016-06-21 03:32:06 +00:00
$iscontact = ! empty ( message_get_contact ( $user -> id ));
$contacttitle = $iscontact ? 'removefromyourcontacts' : 'addtoyourcontacts' ;
$contacturlaction = $iscontact ? 'removecontact' : 'addcontact' ;
$contactimage = $iscontact ? 'removecontact' : 'addcontact' ;
2015-04-08 12:45:46 +08:00
$userbuttons = array (
'messages' => array (
2015-03-17 13:50:38 +08:00
'buttontype' => 'message' ,
2015-04-08 12:45:46 +08:00
'title' => get_string ( 'message' , 'message' ),
'url' => new moodle_url ( '/message/index.php' , array ( 'id' => $user -> id )),
'image' => 'message' ,
2016-09-02 17:36:42 +08:00
'linkattributes' => array ( 'role' => 'button' ),
2015-04-08 12:45:46 +08:00
'page' => $this -> page
2016-06-21 03:32:06 +00:00
),
'togglecontact' => array (
'buttontype' => 'togglecontact' ,
'title' => get_string ( $contacttitle , 'message' ),
'url' => new moodle_url ( '/message/index.php' , array (
'user1' => $USER -> id ,
'user2' => $user -> id ,
$contacturlaction => $user -> id ,
'sesskey' => sesskey ())
),
'image' => $contactimage ,
2016-09-22 12:30:28 +08:00
'linkattributes' => \core_message\helper :: togglecontact_link_params ( $user , $iscontact ),
2016-06-21 03:32:06 +00:00
'page' => $this -> page
),
2015-04-08 12:45:46 +08:00
);
2016-06-21 03:32:06 +00:00
2015-09-24 12:35:20 +08:00
$this -> page -> requires -> string_for_js ( 'changesmadereallygoaway' , 'moodle' );
2015-04-08 12:45:46 +08:00
}
}
$contextheader = new context_header ( $heading , $headinglevel , $imagedata , $userbuttons );
2015-02-17 13:35:02 +08:00
return $this -> render_context_header ( $contextheader );
2015-04-08 12:45:46 +08:00
}
2015-02-17 13:35:02 +08:00
2016-07-15 17:02:22 +08:00
/**
* Renders the skip links for the page .
*
* @ param array $links List of skip links .
* @ return string HTML for the skip links .
*/
public function render_skip_links ( $links ) {
$context = [ 'links' => []];
foreach ( $links as $url => $text ) {
$context [ 'links' ][] = [ 'url' => $url , 'text' => $text ];
}
return $this -> render_from_template ( 'core/skip_links' , $context );
}
2015-02-17 13:35:02 +08:00
/**
* Renders the header bar .
*
* @ param context_header $contextheader Header bar object .
* @ return string HTML for the header bar .
*/
protected function render_context_header ( context_header $contextheader ) {
// All the html stuff goes here.
2015-04-08 12:45:46 +08:00
$html = html_writer :: start_div ( 'page-context-header' );
2015-02-17 13:35:02 +08:00
// Image data.
if ( isset ( $contextheader -> imagedata )) {
2015-04-08 12:45:46 +08:00
// Header specific image.
$html .= html_writer :: div ( $contextheader -> imagedata , 'page-header-image' );
2015-02-17 13:35:02 +08:00
}
// Headings.
2015-04-08 12:45:46 +08:00
if ( ! isset ( $contextheader -> heading )) {
$headings = $this -> heading ( $this -> page -> heading , $contextheader -> headinglevel );
} else {
$headings = $this -> heading ( $contextheader -> heading , $contextheader -> headinglevel );
2015-02-17 13:35:02 +08:00
}
2015-04-08 12:45:46 +08:00
2015-02-17 13:35:02 +08:00
$html .= html_writer :: tag ( 'div' , $headings , array ( 'class' => 'page-header-headings' ));
// Buttons.
if ( isset ( $contextheader -> additionalbuttons )) {
$html .= html_writer :: start_div ( 'btn-group header-button-group' );
2015-04-08 12:45:46 +08:00
foreach ( $contextheader -> additionalbuttons as $button ) {
if ( ! isset ( $button -> page )) {
2015-03-17 13:50:38 +08:00
// Include js for messaging.
2016-09-02 17:36:42 +08:00
if ( $button [ 'buttontype' ] === 'togglecontact' ) {
2016-09-22 12:30:28 +08:00
\core_message\helper :: togglecontact_requirejs ();
2015-03-17 13:50:38 +08:00
}
2015-04-08 12:45:46 +08:00
$image = $this -> pix_icon ( $button [ 'formattedimage' ], $button [ 'title' ], 'moodle' , array (
2015-02-17 13:35:02 +08:00
'class' => 'iconsmall' ,
'role' => 'presentation'
));
2015-04-08 12:45:46 +08:00
$image .= html_writer :: span ( $button [ 'title' ], 'header-button-title' );
2015-02-17 13:35:02 +08:00
} else {
$image = html_writer :: empty_tag ( 'img' , array (
2015-04-08 12:45:46 +08:00
'src' => $button [ 'formattedimage' ],
2015-02-17 13:35:02 +08:00
'role' => 'presentation'
));
}
2015-04-08 12:45:46 +08:00
$html .= html_writer :: link ( $button [ 'url' ], html_writer :: tag ( 'span' , $image ), $button [ 'linkattributes' ]);
2015-02-17 13:35:02 +08:00
}
$html .= html_writer :: end_div ();
}
$html .= html_writer :: end_div ();
return $html ;
}
2015-04-08 12:45:46 +08:00
/**
* Wrapper for header elements .
2015-03-27 16:17:30 +08:00
*
* @ return string HTML to display the main header .
2015-04-08 12:45:46 +08:00
*/
2015-05-04 17:02:33 +08:00
public function full_header () {
2015-02-17 13:35:02 +08:00
$html = html_writer :: start_tag ( 'header' , array ( 'id' => 'page-header' , 'class' => 'clearfix' ));
2015-05-04 17:02:33 +08:00
$html .= $this -> context_header ();
2015-04-08 12:45:46 +08:00
$html .= html_writer :: start_div ( 'clearfix' , array ( 'id' => 'page-navbar' ));
2016-04-18 16:56:34 +01:00
$html .= html_writer :: tag ( 'div' , $this -> navbar (), array ( 'class' => 'breadcrumb-nav' ));
2015-02-17 13:35:02 +08:00
$html .= html_writer :: div ( $this -> page_heading_button (), 'breadcrumb-button' );
2015-04-08 12:45:46 +08:00
$html .= html_writer :: end_div ();
2015-03-27 16:17:30 +08:00
$html .= html_writer :: tag ( 'div' , $this -> course_header (), array ( 'id' => 'course-header' ));
2015-02-17 13:35:02 +08:00
$html .= html_writer :: end_tag ( 'header' );
return $html ;
}
2015-10-02 23:13:44 +08:00
/**
* Displays the list of tags associated with an entry
*
* @ param array $tags list of instances of core_tag or stdClass
* @ param string $label label to display in front , by default 'Tags' ( get_string ( 'tags' )), set to null
* to use default , set to '' ( empty string ) to omit the label completely
* @ param string $classes additional classes for the enclosing div element
* @ param int $limit limit the number of tags to display , if size of $tags is more than this limit the " more " link
* will be appended to the end , JS will toggle the rest of the tags
* @ param context $pagecontext specify if needed to overwrite the current page context for the view tag link
* @ return string
*/
public function tag_list ( $tags , $label = null , $classes = '' , $limit = 10 , $pagecontext = null ) {
$list = new \core_tag\output\taglist ( $tags , $label , $classes , $limit , $pagecontext );
return $this -> render_from_template ( 'core_tag/taglist' , $list -> export_for_template ( $this ));
2016-01-18 15:18:14 +08:00
}
/**
* Renders element for inline editing of any value
*
* @ param \core\output\inplace_editable $element
* @ return string
*/
public function render_inplace_editable ( \core\output\inplace_editable $element ) {
return $this -> render_from_template ( 'core/inplace_editable' , $element -> export_for_template ( $this ));
2015-10-02 23:13:44 +08:00
}
2016-06-20 19:12:43 +08:00
/**
* Renders a bar chart .
*
* @ param \core\chart_bar $chart The chart .
* @ return string .
*/
public function render_chart_bar ( \core\chart_bar $chart ) {
return $this -> render_chart ( $chart );
}
/**
* Renders a line chart .
*
* @ param \core\chart_line $chart The chart .
* @ return string .
*/
public function render_chart_line ( \core\chart_line $chart ) {
return $this -> render_chart ( $chart );
}
/**
* Renders a pie chart .
*
* @ param \core\chart_pie $chart The chart .
* @ return string .
*/
public function render_chart_pie ( \core\chart_pie $chart ) {
return $this -> render_chart ( $chart );
}
/**
* Renders a chart .
*
* @ param \core\chart_base $chart The chart .
2016-07-04 18:38:05 +08:00
* @ param bool $withtable Whether to include a data table with the chart .
2016-06-20 19:12:43 +08:00
* @ return string .
*/
2016-07-04 18:38:05 +08:00
public function render_chart ( \core\chart_base $chart , $withtable = true ) {
$chartdata = json_encode ( $chart );
return $this -> render_from_template ( 'core/chart' , ( object ) [
'chartdata' => $chartdata ,
'withtable' => $withtable
]);
2016-06-20 19:12:43 +08:00
}
2016-08-11 19:42:28 +08:00
/**
* Renders the login form .
*
2016-09-21 13:20:03 +08:00
* @ param \core_auth\output\login $form The renderable .
2016-08-11 19:42:28 +08:00
* @ return string
*/
2016-09-21 13:20:03 +08:00
public function render_login ( \core_auth\output\login $form ) {
2016-08-11 19:42:28 +08:00
$context = $form -> export_for_template ( $this );
// Override because rendering is not supported in template yet.
$context -> cookieshelpiconformatted = $this -> help_icon ( 'cookiesenabled' );
$context -> errorformatted = $this -> error_text ( $context -> error );
2016-08-12 13:40:09 +08:00
return $this -> render_from_template ( 'core/login' , $context );
2016-08-11 19:42:28 +08:00
}
MDL-55417 forms: Render form elements with a template
This change allows form elements to be overridden with a mustache template.
The template can even listen for form validation errors and supply the JS to
change the look of the form element when there is/isn't a validation error.
Initial support is for all core form elements including:
text, select, selectyesno and checkboxes, groups, dateselector, datetimeselector,
autocomplete, modvisible, advcheckbox, button, duration, filemanager, filepicker, editor, static, grading,
warning, textarea, password, url, submit, questioncategory, recaptcha.
Part of MDL-55071
2016-08-04 22:29:32 +08:00
/**
* Renders an mform element from a template .
*
* @ param HTML_QuickForm_element $element element
* @ param bool $required if input is required field
2016-08-22 12:22:21 +08:00
* @ param bool $advanced if input is an advanced field
MDL-55417 forms: Render form elements with a template
This change allows form elements to be overridden with a mustache template.
The template can even listen for form validation errors and supply the JS to
change the look of the form element when there is/isn't a validation error.
Initial support is for all core form elements including:
text, select, selectyesno and checkboxes, groups, dateselector, datetimeselector,
autocomplete, modvisible, advcheckbox, button, duration, filemanager, filepicker, editor, static, grading,
warning, textarea, password, url, submit, questioncategory, recaptcha.
Part of MDL-55071
2016-08-04 22:29:32 +08:00
* @ param string $error error message to display
* @ param bool $ingroup True if this element is rendered as part of a group
* @ return mixed string | bool
*/
2016-08-22 12:22:21 +08:00
public function mform_element ( $element , $required , $advanced , $error , $ingroup ) {
MDL-55417 forms: Render form elements with a template
This change allows form elements to be overridden with a mustache template.
The template can even listen for form validation errors and supply the JS to
change the look of the form element when there is/isn't a validation error.
Initial support is for all core form elements including:
text, select, selectyesno and checkboxes, groups, dateselector, datetimeselector,
autocomplete, modvisible, advcheckbox, button, duration, filemanager, filepicker, editor, static, grading,
warning, textarea, password, url, submit, questioncategory, recaptcha.
Part of MDL-55071
2016-08-04 22:29:32 +08:00
$templatename = 'core_form/element-' . $element -> getType ();
if ( $ingroup ) {
$templatename .= " -inline " ;
}
try {
// We call this to generate a file not found exception if there is no template.
// We don't want to call export_for_template if there is no template.
core\output\mustache_template_finder :: get_template_filepath ( $templatename );
if ( $element instanceof templatable ) {
$elementcontext = $element -> export_for_template ( $this );
$helpbutton = '' ;
if ( method_exists ( $element , 'getHelpButton' )) {
$helpbutton = $element -> getHelpButton ();
}
$label = $element -> getLabel ();
if ( method_exists ( $element , 'getText' )) {
$label .= ' ' . $element -> getText ();
}
$context = array (
'element' => $elementcontext ,
'label' => $label ,
'required' => $required ,
2016-08-22 12:22:21 +08:00
'advanced' => $advanced ,
MDL-55417 forms: Render form elements with a template
This change allows form elements to be overridden with a mustache template.
The template can even listen for form validation errors and supply the JS to
change the look of the form element when there is/isn't a validation error.
Initial support is for all core form elements including:
text, select, selectyesno and checkboxes, groups, dateselector, datetimeselector,
autocomplete, modvisible, advcheckbox, button, duration, filemanager, filepicker, editor, static, grading,
warning, textarea, password, url, submit, questioncategory, recaptcha.
Part of MDL-55071
2016-08-04 22:29:32 +08:00
'helpbutton' => $helpbutton ,
'error' => $error
);
return $this -> render_from_template ( $templatename , $context );
}
} catch ( Exception $e ) {
// No template for this element.
return false ;
}
}
2016-09-23 12:40:48 +02:00
2016-10-06 14:10:14 +08:00
/**
* Render the login signup form into a nice template for the theme .
*
* @ param mform $form
* @ return string
*/
public function render_login_signup_form ( $form ) {
$context = $form -> export_for_template ( $this );
return $this -> render_from_template ( 'core/signup_form_layout' , $context );
}
2016-09-23 12:40:48 +02:00
/**
* Renders a progress bar .
*
* Do not use $OUTPUT -> render ( $bar ), instead use progress_bar :: create () .
*
* @ param progress_bar $bar The bar .
* @ return string HTML fragment
*/
public function render_progress_bar ( progress_bar $bar ) {
global $PAGE ;
$data = $bar -> export_for_template ( $this );
return $this -> render_from_template ( 'core/progress_bar' , $data );
}
2009-12-16 18:00:58 +00:00
}
2009-08-10 06:22:04 +00:00
/**
* A renderer that generates output for command - line scripts .
*
* The implementation of this renderer is probably incomplete .
*
* @ copyright 2009 Tim Hunt
2012-01-05 13:28:08 +13:00
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
* @ since Moodle 2.0
2012-02-14 18:24:09 +13:00
* @ package core
2012-01-11 10:40:55 +13:00
* @ category output
2009-08-10 06:22:04 +00:00
*/
2009-12-17 13:45:54 +00:00
class core_renderer_cli extends core_renderer {
2012-01-05 13:28:08 +13:00
2009-08-10 06:22:04 +00:00
/**
* Returns the page header .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ return string HTML fragment
*/
public function header () {
return $this -> page -> heading . " \n " ;
}
/**
* Returns a template fragment representing a Heading .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param string $text The text of the heading
* @ param int $level The level of importance of the heading
* @ param string $classes A space - separated list of CSS classes
* @ param string $id An optional ID
* @ return string A template fragment for a heading
*/
2010-04-10 22:23:46 +00:00
public function heading ( $text , $level = 2 , $classes = 'main' , $id = null ) {
2009-08-10 06:22:04 +00:00
$text .= " \n " ;
switch ( $level ) {
case 1 :
return '=>' . $text ;
case 2 :
return '-->' . $text ;
default :
return $text ;
}
}
/**
* Returns a template fragment representing a fatal error .
2012-01-05 13:28:08 +13:00
*
2009-08-10 06:22:04 +00:00
* @ param string $message The message to output
* @ param string $moreinfourl URL where more info can be found about the error
* @ param string $link Link for the Continue button
* @ param array $backtrace The execution backtrace
* @ param string $debuginfo Debugging information
* @ return string A template fragment for a fatal error
*/
2016-09-13 14:23:21 +02:00
public function fatal_error ( $message , $moreinfourl , $link , $backtrace , $debuginfo = null , $errorcode = " " ) {
2013-09-24 22:43:46 +02:00
global $CFG ;
2009-08-10 06:22:04 +00:00
$output = " !!! $message !!! \n " ;
2013-08-10 22:46:49 +02:00
if ( $CFG -> debugdeveloper ) {
2009-08-10 06:22:04 +00:00
if ( ! empty ( $debuginfo )) {
2010-10-27 07:48:19 +00:00
$output .= $this -> notification ( $debuginfo , 'notifytiny' );
2009-08-10 06:22:04 +00:00
}
if ( ! empty ( $backtrace )) {
2010-10-27 07:48:19 +00:00
$output .= $this -> notification ( 'Stack trace: ' . format_backtrace ( $backtrace , true ), 'notifytiny' );
2009-08-10 06:22:04 +00:00
}
}
2010-10-27 07:48:19 +00:00
return $output ;
2009-08-10 06:22:04 +00:00
}
/**
* Returns a template fragment representing a notification .
2012-01-05 13:28:08 +13:00
*
2016-02-16 08:45:29 +08:00
* @ param string $message The message to print out .
* @ param string $type The type of notification . See constants on \core\output\notification .
2009-08-10 06:22:04 +00:00
* @ return string A template fragment for a notification
*/
2016-02-16 08:45:29 +08:00
public function notification ( $message , $type = null ) {
2009-08-10 06:22:04 +00:00
$message = clean_text ( $message );
2016-02-16 08:45:29 +08:00
if ( $type === 'notifysuccess' || $type === 'success' ) {
2009-08-10 06:22:04 +00:00
return " ++ $message ++ \n " ;
}
return " !! $message !! \n " ;
}
2014-10-22 14:32:15 +11:00
/**
* There is no footer for a cli request , however we must override the
* footer method to prevent the default footer .
*/
public function footer () {}
2016-05-18 01:48:37 +00:00
/**
* Render a notification ( that is , a status message about something that has
* just happened ) .
*
* @ param \core\output\notification $notification the notification to print out
* @ return string plain text output
*/
public function render_notification ( \core\output\notification $notification ) {
return $this -> notification ( $notification -> get_message (), $notification -> get_message_type ());
}
2009-08-10 06:22:04 +00:00
}
2010-03-28 09:05:47 +00:00
/**
* A renderer that generates output for ajax scripts .
*
* This renderer prevents accidental sends back only json
* encoded error messages , all other output is ignored .
*
* @ copyright 2010 Petr Skoda
2012-01-05 13:28:08 +13:00
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
* @ since Moodle 2.0
2012-02-14 18:24:09 +13:00
* @ package core
2012-01-11 10:40:55 +13:00
* @ category output
2010-03-28 09:05:47 +00:00
*/
class core_renderer_ajax extends core_renderer {
2012-01-05 13:28:08 +13:00
2010-03-28 09:05:47 +00:00
/**
* Returns a template fragment representing a fatal error .
2012-01-05 13:28:08 +13:00
*
2010-03-28 09:05:47 +00:00
* @ param string $message The message to output
* @ param string $moreinfourl URL where more info can be found about the error
* @ param string $link Link for the Continue button
* @ param array $backtrace The execution backtrace
* @ param string $debuginfo Debugging information
* @ return string A template fragment for a fatal error
*/
2016-09-13 14:23:21 +02:00
public function fatal_error ( $message , $moreinfourl , $link , $backtrace , $debuginfo = null , $errorcode = " " ) {
2010-09-17 08:02:32 +00:00
global $CFG ;
2010-08-16 19:11:21 +00:00
$this -> page -> set_context ( null ); // ugly hack - make sure page context is set to something, we do not want bogus warnings here
2010-03-28 09:05:47 +00:00
$e = new stdClass ();
$e -> error = $message ;
2016-09-13 14:23:21 +02:00
$e -> errorcode = $errorcode ;
2010-03-28 09:05:47 +00:00
$e -> stacktrace = NULL ;
$e -> debuginfo = NULL ;
2010-07-16 08:30:06 +00:00
$e -> reproductionlink = NULL ;
2010-03-28 09:05:47 +00:00
if ( ! empty ( $CFG -> debug ) and $CFG -> debug >= DEBUG_DEVELOPER ) {
2014-04-16 15:11:44 +08:00
$link = ( string ) $link ;
if ( $link ) {
$e -> reproductionlink = $link ;
}
2010-03-28 09:05:47 +00:00
if ( ! empty ( $debuginfo )) {
$e -> debuginfo = $debuginfo ;
}
if ( ! empty ( $backtrace )) {
$e -> stacktrace = format_backtrace ( $backtrace , true );
}
}
2010-08-10 08:50:08 +00:00
$this -> header ();
2010-03-28 09:05:47 +00:00
return json_encode ( $e );
}
2012-01-05 13:28:08 +13:00
/**
* Used to display a notification .
* For the AJAX notifications are discarded .
*
2016-02-16 08:45:29 +08:00
* @ param string $message The message to print out .
* @ param string $type The type of notification . See constants on \core\output\notification .
2012-01-05 13:28:08 +13:00
*/
2016-02-16 08:45:29 +08:00
public function notification ( $message , $type = null ) {}
2010-08-10 08:50:08 +00:00
2012-01-05 13:28:08 +13:00
/**
* Used to display a redirection message .
2012-01-12 12:55:50 +13:00
* AJAX redirections should not occur and as such redirection messages
2012-01-05 13:28:08 +13:00
* are discarded .
2012-02-14 18:24:09 +13:00
*
* @ param moodle_url | string $encodedurl
* @ param string $message
* @ param int $delay
* @ param bool $debugdisableredirect
2016-02-16 08:49:42 +08:00
* @ param string $messagetype The type of notification to show the message in .
* See constants on \core\output\notification .
2012-01-05 13:28:08 +13:00
*/
2016-02-16 08:49:42 +08:00
public function redirect_message ( $encodedurl , $message , $delay , $debugdisableredirect ,
$messagetype = \core\output\notification :: NOTIFY_INFO ) {}
2010-08-10 08:50:08 +00:00
2012-01-05 13:28:08 +13:00
/**
* Prepares the start of an AJAX output .
*/
2010-03-28 09:05:47 +00:00
public function header () {
2010-08-10 08:50:08 +00:00
// unfortunately YUI iframe upload does not support application/json
if ( ! empty ( $_FILES )) {
2011-01-14 09:32:17 +01:00
@ header ( 'Content-type: text/plain; charset=utf-8' );
2013-06-11 20:15:42 +02:00
if ( ! core_useragent :: supports_json_contenttype ()) {
@ header ( 'X-Content-Type-Options: nosniff' );
}
} else if ( ! core_useragent :: supports_json_contenttype ()) {
@ header ( 'Content-type: text/plain; charset=utf-8' );
@ header ( 'X-Content-Type-Options: nosniff' );
2010-08-10 08:50:08 +00:00
} else {
2011-01-14 09:32:17 +01:00
@ header ( 'Content-type: application/json; charset=utf-8' );
2010-08-10 08:50:08 +00:00
}
2012-02-14 18:24:09 +13:00
// Headers to make it not cacheable and json
2010-08-10 08:50:08 +00:00
@ header ( 'Cache-Control: no-store, no-cache, must-revalidate' );
@ header ( 'Cache-Control: post-check=0, pre-check=0' , false );
@ header ( 'Pragma: no-cache' );
@ header ( 'Expires: Mon, 20 Aug 1969 09:23:00 GMT' );
@ header ( 'Last-Modified: ' . gmdate ( 'D, d M Y H:i:s' ) . ' GMT' );
@ header ( 'Accept-Ranges: none' );
2010-03-28 09:05:47 +00:00
}
2010-08-10 08:50:08 +00:00
2012-01-05 13:28:08 +13:00
/**
* There is no footer for an AJAX request , however we must override the
* footer method to prevent the default footer .
*/
public function footer () {}
2010-03-28 09:05:47 +00:00
2012-01-05 13:28:08 +13:00
/**
* No need for headers in an AJAX request ... this should never happen .
* @ param string $text
* @ param int $level
* @ param string $classes
* @ param string $id
*/
public function heading ( $text , $level = 2 , $classes = 'main' , $id = null ) {}
2012-04-11 10:56:49 +12:00
}
MDL-29624 Media embedding system, part 1: new API and filter changes
Includes new API in medialib.php and core_media_renderer in outputrenderers.php.
Enable/disable settings moved from filter to systemwide appearance page.
Filter changed to use new API.
AMOS BEGIN
MOV [flashanimation,filter_mediaplugin],[flashanimation,core_media]
MOV [flashanimation_help,filter_mediaplugin],[flashanimation_desc,core_media]
MOV [flashvideo,filter_mediaplugin],[flashvideo,core_media]
MOV [flashvideo_help,filter_mediaplugin],[flashvideo_desc,core_media]
MOV [html5audio,filter_mediaplugin],[html5audio,core_media]
MOV [html5audio_help,filter_mediaplugin],[html5audio_desc,core_media]
MOV [html5video,filter_mediaplugin],[html5video,core_media]
MOV [html5video_help,filter_mediaplugin],[html5video_desc,core_media]
MOV [mp3audio,filter_mediaplugin],[mp3audio,core_media]
MOV [mp3audio_help,filter_mediaplugin],[mp3audio_desc,core_media]
MOV [legacyquicktime,filter_mediaplugin],[legacyquicktime,core_media]
MOV [legacyquicktime_help,filter_mediaplugin],[legacyquicktime_desc,core_media]
MOV [legacyreal,filter_mediaplugin],[legacyreal,core_media]
MOV [legacyreal_help,filter_mediaplugin],[legacyreal_desc,core_media]
MOV [legacywmp,filter_mediaplugin],[legacywmp,core_media]
MOV [legacywmp_help,filter_mediaplugin],[legacywmp_desc,core_media]
MOV [legacyheading,filter_mediaplugin],[legacyheading,core_media]
MOV [legacyheading_help,filter_mediaplugin],[legacyheading_desc,core_media]
MOV [sitevimeo,filter_mediaplugin],[sitevimeo,core_media]
MOV [sitevimeo_help,filter_mediaplugin],[sitevimeo_desc,core_media]
MOV [siteyoutube,filter_mediaplugin],[siteyoutube,core_media]
MOV [siteyoutube_help,filter_mediaplugin],[siteyoutube_desc,core_media]
AMOS END
2011-12-13 17:08:34 +00:00
/**
* Renderer for media files .
*
* Used in file resources , media filter , and any other places that need to
* output embedded media .
*
MDL-38158 core_media: Convert media players to new plugin type
AMOS BEGIN
MOV [siteyoutube,core_media],[pluginname,media_youtube]
MOV [siteyoutube_desc,core_media],[pluginname_help,media_youtube]
MOV [sitevimeo,core_media],[pluginname,media_vimeo]
MOV [sitevimeo_desc,core_media],[pluginname_help,media_vimeo]
MOV [html5audio,core_media],[pluginname,media_html5audio]
MOV [html5audio_desc,core_media],[pluginname_help,media_html5audio]
MOV [html5video,core_media],[pluginname,media_html5video]
MOV [html5video_desc,core_media],[pluginname_help,media_html5video]
MOV [flashanimation,core_media],[pluginname,media_swf]
MOV [flashanimation_desc,core_media],[pluginname_help,media_swf]
AMOS END
2016-09-15 15:52:41 +08:00
* @ deprecated since Moodle 3.2
MDL-29624 Media embedding system, part 1: new API and filter changes
Includes new API in medialib.php and core_media_renderer in outputrenderers.php.
Enable/disable settings moved from filter to systemwide appearance page.
Filter changed to use new API.
AMOS BEGIN
MOV [flashanimation,filter_mediaplugin],[flashanimation,core_media]
MOV [flashanimation_help,filter_mediaplugin],[flashanimation_desc,core_media]
MOV [flashvideo,filter_mediaplugin],[flashvideo,core_media]
MOV [flashvideo_help,filter_mediaplugin],[flashvideo_desc,core_media]
MOV [html5audio,filter_mediaplugin],[html5audio,core_media]
MOV [html5audio_help,filter_mediaplugin],[html5audio_desc,core_media]
MOV [html5video,filter_mediaplugin],[html5video,core_media]
MOV [html5video_help,filter_mediaplugin],[html5video_desc,core_media]
MOV [mp3audio,filter_mediaplugin],[mp3audio,core_media]
MOV [mp3audio_help,filter_mediaplugin],[mp3audio_desc,core_media]
MOV [legacyquicktime,filter_mediaplugin],[legacyquicktime,core_media]
MOV [legacyquicktime_help,filter_mediaplugin],[legacyquicktime_desc,core_media]
MOV [legacyreal,filter_mediaplugin],[legacyreal,core_media]
MOV [legacyreal_help,filter_mediaplugin],[legacyreal_desc,core_media]
MOV [legacywmp,filter_mediaplugin],[legacywmp,core_media]
MOV [legacywmp_help,filter_mediaplugin],[legacywmp_desc,core_media]
MOV [legacyheading,filter_mediaplugin],[legacyheading,core_media]
MOV [legacyheading_help,filter_mediaplugin],[legacyheading_desc,core_media]
MOV [sitevimeo,filter_mediaplugin],[sitevimeo,core_media]
MOV [sitevimeo_help,filter_mediaplugin],[sitevimeo_desc,core_media]
MOV [siteyoutube,filter_mediaplugin],[siteyoutube,core_media]
MOV [siteyoutube_help,filter_mediaplugin],[siteyoutube_desc,core_media]
AMOS END
2011-12-13 17:08:34 +00:00
* @ copyright 2011 The Open University
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
class core_media_renderer extends plugin_renderer_base {
/** @var array Array of available 'player' objects */
private $players ;
/** @var string Regex pattern for links which may contain embeddable content */
private $embeddablemarkers ;
/**
MDL-38158 core_media: Convert media players to new plugin type
AMOS BEGIN
MOV [siteyoutube,core_media],[pluginname,media_youtube]
MOV [siteyoutube_desc,core_media],[pluginname_help,media_youtube]
MOV [sitevimeo,core_media],[pluginname,media_vimeo]
MOV [sitevimeo_desc,core_media],[pluginname_help,media_vimeo]
MOV [html5audio,core_media],[pluginname,media_html5audio]
MOV [html5audio_desc,core_media],[pluginname_help,media_html5audio]
MOV [html5video,core_media],[pluginname,media_html5video]
MOV [html5video_desc,core_media],[pluginname_help,media_html5video]
MOV [flashanimation,core_media],[pluginname,media_swf]
MOV [flashanimation_desc,core_media],[pluginname_help,media_swf]
AMOS END
2016-09-15 15:52:41 +08:00
* Constructor
MDL-29624 Media embedding system, part 1: new API and filter changes
Includes new API in medialib.php and core_media_renderer in outputrenderers.php.
Enable/disable settings moved from filter to systemwide appearance page.
Filter changed to use new API.
AMOS BEGIN
MOV [flashanimation,filter_mediaplugin],[flashanimation,core_media]
MOV [flashanimation_help,filter_mediaplugin],[flashanimation_desc,core_media]
MOV [flashvideo,filter_mediaplugin],[flashvideo,core_media]
MOV [flashvideo_help,filter_mediaplugin],[flashvideo_desc,core_media]
MOV [html5audio,filter_mediaplugin],[html5audio,core_media]
MOV [html5audio_help,filter_mediaplugin],[html5audio_desc,core_media]
MOV [html5video,filter_mediaplugin],[html5video,core_media]
MOV [html5video_help,filter_mediaplugin],[html5video_desc,core_media]
MOV [mp3audio,filter_mediaplugin],[mp3audio,core_media]
MOV [mp3audio_help,filter_mediaplugin],[mp3audio_desc,core_media]
MOV [legacyquicktime,filter_mediaplugin],[legacyquicktime,core_media]
MOV [legacyquicktime_help,filter_mediaplugin],[legacyquicktime_desc,core_media]
MOV [legacyreal,filter_mediaplugin],[legacyreal,core_media]
MOV [legacyreal_help,filter_mediaplugin],[legacyreal_desc,core_media]
MOV [legacywmp,filter_mediaplugin],[legacywmp,core_media]
MOV [legacywmp_help,filter_mediaplugin],[legacywmp_desc,core_media]
MOV [legacyheading,filter_mediaplugin],[legacyheading,core_media]
MOV [legacyheading_help,filter_mediaplugin],[legacyheading_desc,core_media]
MOV [sitevimeo,filter_mediaplugin],[sitevimeo,core_media]
MOV [sitevimeo_help,filter_mediaplugin],[sitevimeo_desc,core_media]
MOV [siteyoutube,filter_mediaplugin],[siteyoutube,core_media]
MOV [siteyoutube_help,filter_mediaplugin],[siteyoutube_desc,core_media]
AMOS END
2011-12-13 17:08:34 +00:00
*
* This is needed in the constructor ( not later ) so that you can use the
* constants and static functions that are defined in core_media class
* before you call renderer functions .
*/
public function __construct () {
MDL-38158 core_media: Convert media players to new plugin type
AMOS BEGIN
MOV [siteyoutube,core_media],[pluginname,media_youtube]
MOV [siteyoutube_desc,core_media],[pluginname_help,media_youtube]
MOV [sitevimeo,core_media],[pluginname,media_vimeo]
MOV [sitevimeo_desc,core_media],[pluginname_help,media_vimeo]
MOV [html5audio,core_media],[pluginname,media_html5audio]
MOV [html5audio_desc,core_media],[pluginname_help,media_html5audio]
MOV [html5video,core_media],[pluginname,media_html5video]
MOV [html5video_desc,core_media],[pluginname_help,media_html5video]
MOV [flashanimation,core_media],[pluginname,media_swf]
MOV [flashanimation_desc,core_media],[pluginname_help,media_swf]
AMOS END
2016-09-15 15:52:41 +08:00
debugging ( 'Class core_media_renderer is deprecated, please use core_media_manager::instance()' , DEBUG_DEVELOPER );
MDL-29624 Media embedding system, part 1: new API and filter changes
Includes new API in medialib.php and core_media_renderer in outputrenderers.php.
Enable/disable settings moved from filter to systemwide appearance page.
Filter changed to use new API.
AMOS BEGIN
MOV [flashanimation,filter_mediaplugin],[flashanimation,core_media]
MOV [flashanimation_help,filter_mediaplugin],[flashanimation_desc,core_media]
MOV [flashvideo,filter_mediaplugin],[flashvideo,core_media]
MOV [flashvideo_help,filter_mediaplugin],[flashvideo_desc,core_media]
MOV [html5audio,filter_mediaplugin],[html5audio,core_media]
MOV [html5audio_help,filter_mediaplugin],[html5audio_desc,core_media]
MOV [html5video,filter_mediaplugin],[html5video,core_media]
MOV [html5video_help,filter_mediaplugin],[html5video_desc,core_media]
MOV [mp3audio,filter_mediaplugin],[mp3audio,core_media]
MOV [mp3audio_help,filter_mediaplugin],[mp3audio_desc,core_media]
MOV [legacyquicktime,filter_mediaplugin],[legacyquicktime,core_media]
MOV [legacyquicktime_help,filter_mediaplugin],[legacyquicktime_desc,core_media]
MOV [legacyreal,filter_mediaplugin],[legacyreal,core_media]
MOV [legacyreal_help,filter_mediaplugin],[legacyreal_desc,core_media]
MOV [legacywmp,filter_mediaplugin],[legacywmp,core_media]
MOV [legacywmp_help,filter_mediaplugin],[legacywmp_desc,core_media]
MOV [legacyheading,filter_mediaplugin],[legacyheading,core_media]
MOV [legacyheading_help,filter_mediaplugin],[legacyheading_desc,core_media]
MOV [sitevimeo,filter_mediaplugin],[sitevimeo,core_media]
MOV [sitevimeo_help,filter_mediaplugin],[sitevimeo_desc,core_media]
MOV [siteyoutube,filter_mediaplugin],[siteyoutube,core_media]
MOV [siteyoutube_help,filter_mediaplugin],[siteyoutube_desc,core_media]
AMOS END
2011-12-13 17:08:34 +00:00
}
/**
* Renders a media file ( audio or video ) using suitable embedded player .
*
* See embed_alternatives function for full description of parameters .
* This function calls through to that one .
*
* When using this function you can also specify width and height in the
* URL by including ? d = 100 x100 at the end . If specified in the URL , this
* will override the $width and $height parameters .
*
* @ param moodle_url $url Full URL of media file
* @ param string $name Optional user - readable name to display in download link
* @ param int $width Width in pixels ( optional )
* @ param int $height Height in pixels ( optional )
* @ param array $options Array of key / value pairs
* @ return string HTML content of embed
*/
public function embed_url ( moodle_url $url , $name = '' , $width = 0 , $height = 0 ,
$options = array ()) {
MDL-38158 core_media: Convert media players to new plugin type
AMOS BEGIN
MOV [siteyoutube,core_media],[pluginname,media_youtube]
MOV [siteyoutube_desc,core_media],[pluginname_help,media_youtube]
MOV [sitevimeo,core_media],[pluginname,media_vimeo]
MOV [sitevimeo_desc,core_media],[pluginname_help,media_vimeo]
MOV [html5audio,core_media],[pluginname,media_html5audio]
MOV [html5audio_desc,core_media],[pluginname_help,media_html5audio]
MOV [html5video,core_media],[pluginname,media_html5video]
MOV [html5video_desc,core_media],[pluginname_help,media_html5video]
MOV [flashanimation,core_media],[pluginname,media_swf]
MOV [flashanimation_desc,core_media],[pluginname_help,media_swf]
AMOS END
2016-09-15 15:52:41 +08:00
return core_media_manager :: instance () -> embed_url ( $url , $name , $width , $height , $options );
MDL-29624 Media embedding system, part 1: new API and filter changes
Includes new API in medialib.php and core_media_renderer in outputrenderers.php.
Enable/disable settings moved from filter to systemwide appearance page.
Filter changed to use new API.
AMOS BEGIN
MOV [flashanimation,filter_mediaplugin],[flashanimation,core_media]
MOV [flashanimation_help,filter_mediaplugin],[flashanimation_desc,core_media]
MOV [flashvideo,filter_mediaplugin],[flashvideo,core_media]
MOV [flashvideo_help,filter_mediaplugin],[flashvideo_desc,core_media]
MOV [html5audio,filter_mediaplugin],[html5audio,core_media]
MOV [html5audio_help,filter_mediaplugin],[html5audio_desc,core_media]
MOV [html5video,filter_mediaplugin],[html5video,core_media]
MOV [html5video_help,filter_mediaplugin],[html5video_desc,core_media]
MOV [mp3audio,filter_mediaplugin],[mp3audio,core_media]
MOV [mp3audio_help,filter_mediaplugin],[mp3audio_desc,core_media]
MOV [legacyquicktime,filter_mediaplugin],[legacyquicktime,core_media]
MOV [legacyquicktime_help,filter_mediaplugin],[legacyquicktime_desc,core_media]
MOV [legacyreal,filter_mediaplugin],[legacyreal,core_media]
MOV [legacyreal_help,filter_mediaplugin],[legacyreal_desc,core_media]
MOV [legacywmp,filter_mediaplugin],[legacywmp,core_media]
MOV [legacywmp_help,filter_mediaplugin],[legacywmp_desc,core_media]
MOV [legacyheading,filter_mediaplugin],[legacyheading,core_media]
MOV [legacyheading_help,filter_mediaplugin],[legacyheading_desc,core_media]
MOV [sitevimeo,filter_mediaplugin],[sitevimeo,core_media]
MOV [sitevimeo_help,filter_mediaplugin],[sitevimeo_desc,core_media]
MOV [siteyoutube,filter_mediaplugin],[siteyoutube,core_media]
MOV [siteyoutube_help,filter_mediaplugin],[siteyoutube_desc,core_media]
AMOS END
2011-12-13 17:08:34 +00:00
}
/**
* Renders media files ( audio or video ) using suitable embedded player .
* The list of URLs should be alternative versions of the same content in
* multiple formats . If there is only one format it should have a single
* entry .
*
* If the media files are not in a supported format , this will give students
* a download link to each format . The download link uses the filename
* unless you supply the optional name parameter .
*
* Width and height are optional . If specified , these are suggested sizes
* and should be the exact values supplied by the user , if they come from
* user input . These will be treated as relating to the size of the video
* content , not including any player control bar .
*
* For audio files , height will be ignored . For video files , a few formats
* work if you specify only width , but in general if you specify width
* you must specify height as well .
*
* The $options array is passed through to the core_media_player classes
* that render the object tag . The keys can contain values from
* core_media :: OPTION_xx .
*
* @ param array $alternatives Array of moodle_url to media files
* @ param string $name Optional user - readable name to display in download link
* @ param int $width Width in pixels ( optional )
* @ param int $height Height in pixels ( optional )
* @ param array $options Array of key / value pairs
* @ return string HTML content of embed
*/
public function embed_alternatives ( $alternatives , $name = '' , $width = 0 , $height = 0 ,
$options = array ()) {
MDL-38158 core_media: Convert media players to new plugin type
AMOS BEGIN
MOV [siteyoutube,core_media],[pluginname,media_youtube]
MOV [siteyoutube_desc,core_media],[pluginname_help,media_youtube]
MOV [sitevimeo,core_media],[pluginname,media_vimeo]
MOV [sitevimeo_desc,core_media],[pluginname_help,media_vimeo]
MOV [html5audio,core_media],[pluginname,media_html5audio]
MOV [html5audio_desc,core_media],[pluginname_help,media_html5audio]
MOV [html5video,core_media],[pluginname,media_html5video]
MOV [html5video_desc,core_media],[pluginname_help,media_html5video]
MOV [flashanimation,core_media],[pluginname,media_swf]
MOV [flashanimation_desc,core_media],[pluginname_help,media_swf]
AMOS END
2016-09-15 15:52:41 +08:00
return core_media_manager :: instance () -> embed_alternatives ( $alternatives , $name , $width , $height , $options );
MDL-29624 Media embedding system, part 1: new API and filter changes
Includes new API in medialib.php and core_media_renderer in outputrenderers.php.
Enable/disable settings moved from filter to systemwide appearance page.
Filter changed to use new API.
AMOS BEGIN
MOV [flashanimation,filter_mediaplugin],[flashanimation,core_media]
MOV [flashanimation_help,filter_mediaplugin],[flashanimation_desc,core_media]
MOV [flashvideo,filter_mediaplugin],[flashvideo,core_media]
MOV [flashvideo_help,filter_mediaplugin],[flashvideo_desc,core_media]
MOV [html5audio,filter_mediaplugin],[html5audio,core_media]
MOV [html5audio_help,filter_mediaplugin],[html5audio_desc,core_media]
MOV [html5video,filter_mediaplugin],[html5video,core_media]
MOV [html5video_help,filter_mediaplugin],[html5video_desc,core_media]
MOV [mp3audio,filter_mediaplugin],[mp3audio,core_media]
MOV [mp3audio_help,filter_mediaplugin],[mp3audio_desc,core_media]
MOV [legacyquicktime,filter_mediaplugin],[legacyquicktime,core_media]
MOV [legacyquicktime_help,filter_mediaplugin],[legacyquicktime_desc,core_media]
MOV [legacyreal,filter_mediaplugin],[legacyreal,core_media]
MOV [legacyreal_help,filter_mediaplugin],[legacyreal_desc,core_media]
MOV [legacywmp,filter_mediaplugin],[legacywmp,core_media]
MOV [legacywmp_help,filter_mediaplugin],[legacywmp_desc,core_media]
MOV [legacyheading,filter_mediaplugin],[legacyheading,core_media]
MOV [legacyheading_help,filter_mediaplugin],[legacyheading_desc,core_media]
MOV [sitevimeo,filter_mediaplugin],[sitevimeo,core_media]
MOV [sitevimeo_help,filter_mediaplugin],[sitevimeo_desc,core_media]
MOV [siteyoutube,filter_mediaplugin],[siteyoutube,core_media]
MOV [siteyoutube_help,filter_mediaplugin],[siteyoutube_desc,core_media]
AMOS END
2011-12-13 17:08:34 +00:00
}
/**
* Checks whether a file can be embedded . If this returns true you will get
* an embedded player ; if this returns false , you will just get a download
* link .
*
* This is a wrapper for can_embed_urls .
*
* @ param moodle_url $url URL of media file
* @ param array $options Options ( same as when embedding )
* @ return bool True if file can be embedded
*/
public function can_embed_url ( moodle_url $url , $options = array ()) {
MDL-38158 core_media: Convert media players to new plugin type
AMOS BEGIN
MOV [siteyoutube,core_media],[pluginname,media_youtube]
MOV [siteyoutube_desc,core_media],[pluginname_help,media_youtube]
MOV [sitevimeo,core_media],[pluginname,media_vimeo]
MOV [sitevimeo_desc,core_media],[pluginname_help,media_vimeo]
MOV [html5audio,core_media],[pluginname,media_html5audio]
MOV [html5audio_desc,core_media],[pluginname_help,media_html5audio]
MOV [html5video,core_media],[pluginname,media_html5video]
MOV [html5video_desc,core_media],[pluginname_help,media_html5video]
MOV [flashanimation,core_media],[pluginname,media_swf]
MOV [flashanimation_desc,core_media],[pluginname_help,media_swf]
AMOS END
2016-09-15 15:52:41 +08:00
return core_media_manager :: instance () -> can_embed_url ( $url , $options );
MDL-29624 Media embedding system, part 1: new API and filter changes
Includes new API in medialib.php and core_media_renderer in outputrenderers.php.
Enable/disable settings moved from filter to systemwide appearance page.
Filter changed to use new API.
AMOS BEGIN
MOV [flashanimation,filter_mediaplugin],[flashanimation,core_media]
MOV [flashanimation_help,filter_mediaplugin],[flashanimation_desc,core_media]
MOV [flashvideo,filter_mediaplugin],[flashvideo,core_media]
MOV [flashvideo_help,filter_mediaplugin],[flashvideo_desc,core_media]
MOV [html5audio,filter_mediaplugin],[html5audio,core_media]
MOV [html5audio_help,filter_mediaplugin],[html5audio_desc,core_media]
MOV [html5video,filter_mediaplugin],[html5video,core_media]
MOV [html5video_help,filter_mediaplugin],[html5video_desc,core_media]
MOV [mp3audio,filter_mediaplugin],[mp3audio,core_media]
MOV [mp3audio_help,filter_mediaplugin],[mp3audio_desc,core_media]
MOV [legacyquicktime,filter_mediaplugin],[legacyquicktime,core_media]
MOV [legacyquicktime_help,filter_mediaplugin],[legacyquicktime_desc,core_media]
MOV [legacyreal,filter_mediaplugin],[legacyreal,core_media]
MOV [legacyreal_help,filter_mediaplugin],[legacyreal_desc,core_media]
MOV [legacywmp,filter_mediaplugin],[legacywmp,core_media]
MOV [legacywmp_help,filter_mediaplugin],[legacywmp_desc,core_media]
MOV [legacyheading,filter_mediaplugin],[legacyheading,core_media]
MOV [legacyheading_help,filter_mediaplugin],[legacyheading_desc,core_media]
MOV [sitevimeo,filter_mediaplugin],[sitevimeo,core_media]
MOV [sitevimeo_help,filter_mediaplugin],[sitevimeo_desc,core_media]
MOV [siteyoutube,filter_mediaplugin],[siteyoutube,core_media]
MOV [siteyoutube_help,filter_mediaplugin],[siteyoutube_desc,core_media]
AMOS END
2011-12-13 17:08:34 +00:00
}
/**
* Checks whether a file can be embedded . If this returns true you will get
* an embedded player ; if this returns false , you will just get a download
* link .
*
* @ param array $urls URL of media file and any alternatives ( moodle_url )
* @ param array $options Options ( same as when embedding )
* @ return bool True if file can be embedded
*/
public function can_embed_urls ( array $urls , $options = array ()) {
MDL-38158 core_media: Convert media players to new plugin type
AMOS BEGIN
MOV [siteyoutube,core_media],[pluginname,media_youtube]
MOV [siteyoutube_desc,core_media],[pluginname_help,media_youtube]
MOV [sitevimeo,core_media],[pluginname,media_vimeo]
MOV [sitevimeo_desc,core_media],[pluginname_help,media_vimeo]
MOV [html5audio,core_media],[pluginname,media_html5audio]
MOV [html5audio_desc,core_media],[pluginname_help,media_html5audio]
MOV [html5video,core_media],[pluginname,media_html5video]
MOV [html5video_desc,core_media],[pluginname_help,media_html5video]
MOV [flashanimation,core_media],[pluginname,media_swf]
MOV [flashanimation_desc,core_media],[pluginname_help,media_swf]
AMOS END
2016-09-15 15:52:41 +08:00
return core_media_manager :: instance () -> can_embed_urls ( $urls , $options );
MDL-29624 Media embedding system, part 1: new API and filter changes
Includes new API in medialib.php and core_media_renderer in outputrenderers.php.
Enable/disable settings moved from filter to systemwide appearance page.
Filter changed to use new API.
AMOS BEGIN
MOV [flashanimation,filter_mediaplugin],[flashanimation,core_media]
MOV [flashanimation_help,filter_mediaplugin],[flashanimation_desc,core_media]
MOV [flashvideo,filter_mediaplugin],[flashvideo,core_media]
MOV [flashvideo_help,filter_mediaplugin],[flashvideo_desc,core_media]
MOV [html5audio,filter_mediaplugin],[html5audio,core_media]
MOV [html5audio_help,filter_mediaplugin],[html5audio_desc,core_media]
MOV [html5video,filter_mediaplugin],[html5video,core_media]
MOV [html5video_help,filter_mediaplugin],[html5video_desc,core_media]
MOV [mp3audio,filter_mediaplugin],[mp3audio,core_media]
MOV [mp3audio_help,filter_mediaplugin],[mp3audio_desc,core_media]
MOV [legacyquicktime,filter_mediaplugin],[legacyquicktime,core_media]
MOV [legacyquicktime_help,filter_mediaplugin],[legacyquicktime_desc,core_media]
MOV [legacyreal,filter_mediaplugin],[legacyreal,core_media]
MOV [legacyreal_help,filter_mediaplugin],[legacyreal_desc,core_media]
MOV [legacywmp,filter_mediaplugin],[legacywmp,core_media]
MOV [legacywmp_help,filter_mediaplugin],[legacywmp_desc,core_media]
MOV [legacyheading,filter_mediaplugin],[legacyheading,core_media]
MOV [legacyheading_help,filter_mediaplugin],[legacyheading_desc,core_media]
MOV [sitevimeo,filter_mediaplugin],[sitevimeo,core_media]
MOV [sitevimeo_help,filter_mediaplugin],[sitevimeo_desc,core_media]
MOV [siteyoutube,filter_mediaplugin],[siteyoutube,core_media]
MOV [siteyoutube_help,filter_mediaplugin],[siteyoutube_desc,core_media]
AMOS END
2011-12-13 17:08:34 +00:00
}
/**
* Obtains a list of markers that can be used in a regular expression when
* searching for URLs that can be embedded by any player type .
*
* This string is used to improve peformance of regex matching by ensuring
* that the ( presumably C ) regex code can do a quick keyword check on the
* URL part of a link to see if it matches one of these , rather than having
* to go into PHP code for every single link to see if it can be embedded .
*
* @ return string String suitable for use in regex such as '(\.mp4|\.flv)'
*/
public function get_embeddable_markers () {
MDL-38158 core_media: Convert media players to new plugin type
AMOS BEGIN
MOV [siteyoutube,core_media],[pluginname,media_youtube]
MOV [siteyoutube_desc,core_media],[pluginname_help,media_youtube]
MOV [sitevimeo,core_media],[pluginname,media_vimeo]
MOV [sitevimeo_desc,core_media],[pluginname_help,media_vimeo]
MOV [html5audio,core_media],[pluginname,media_html5audio]
MOV [html5audio_desc,core_media],[pluginname_help,media_html5audio]
MOV [html5video,core_media],[pluginname,media_html5video]
MOV [html5video_desc,core_media],[pluginname_help,media_html5video]
MOV [flashanimation,core_media],[pluginname,media_swf]
MOV [flashanimation_desc,core_media],[pluginname_help,media_swf]
AMOS END
2016-09-15 15:52:41 +08:00
return core_media_manager :: instance () -> get_embeddable_markers ();
MDL-29624 Media embedding system, part 1: new API and filter changes
Includes new API in medialib.php and core_media_renderer in outputrenderers.php.
Enable/disable settings moved from filter to systemwide appearance page.
Filter changed to use new API.
AMOS BEGIN
MOV [flashanimation,filter_mediaplugin],[flashanimation,core_media]
MOV [flashanimation_help,filter_mediaplugin],[flashanimation_desc,core_media]
MOV [flashvideo,filter_mediaplugin],[flashvideo,core_media]
MOV [flashvideo_help,filter_mediaplugin],[flashvideo_desc,core_media]
MOV [html5audio,filter_mediaplugin],[html5audio,core_media]
MOV [html5audio_help,filter_mediaplugin],[html5audio_desc,core_media]
MOV [html5video,filter_mediaplugin],[html5video,core_media]
MOV [html5video_help,filter_mediaplugin],[html5video_desc,core_media]
MOV [mp3audio,filter_mediaplugin],[mp3audio,core_media]
MOV [mp3audio_help,filter_mediaplugin],[mp3audio_desc,core_media]
MOV [legacyquicktime,filter_mediaplugin],[legacyquicktime,core_media]
MOV [legacyquicktime_help,filter_mediaplugin],[legacyquicktime_desc,core_media]
MOV [legacyreal,filter_mediaplugin],[legacyreal,core_media]
MOV [legacyreal_help,filter_mediaplugin],[legacyreal_desc,core_media]
MOV [legacywmp,filter_mediaplugin],[legacywmp,core_media]
MOV [legacywmp_help,filter_mediaplugin],[legacywmp_desc,core_media]
MOV [legacyheading,filter_mediaplugin],[legacyheading,core_media]
MOV [legacyheading_help,filter_mediaplugin],[legacyheading_desc,core_media]
MOV [sitevimeo,filter_mediaplugin],[sitevimeo,core_media]
MOV [sitevimeo_help,filter_mediaplugin],[sitevimeo_desc,core_media]
MOV [siteyoutube,filter_mediaplugin],[siteyoutube,core_media]
MOV [siteyoutube_help,filter_mediaplugin],[siteyoutube_desc,core_media]
AMOS END
2011-12-13 17:08:34 +00:00
}
}
2013-09-12 09:51:58 +12:00
/**
* The maintenance renderer .
*
* The purpose of this renderer is to block out the core renderer methods that are not usable when the site
* is running a maintenance related task .
* It must always extend the core_renderer as we switch from the core_renderer to this renderer in a couple of places .
*
2014-05-19 17:03:04 +01:00
* @ since Moodle 2.6
2013-09-12 09:51:58 +12:00
* @ package core
* @ category output
* @ copyright 2013 Sam Hemelryk
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
class core_renderer_maintenance extends core_renderer {
/**
* Initialises the renderer instance .
* @ param moodle_page $page
* @ param string $target
* @ throws coding_exception
*/
public function __construct ( moodle_page $page , $target ) {
if ( $target !== RENDERER_TARGET_MAINTENANCE || $page -> pagelayout !== 'maintenance' ) {
throw new coding_exception ( 'Invalid request for the maintenance renderer.' );
}
parent :: __construct ( $page , $target );
}
/**
* Does nothing . The maintenance renderer cannot produce blocks .
*
* @ param block_contents $bc
* @ param string $region
* @ return string
*/
public function block ( block_contents $bc , $region ) {
// Computer says no blocks.
// debugging('Please do not use $OUTPUT->'.__FUNCTION__.'() when performing maintenance tasks.', DEBUG_DEVELOPER);
return '' ;
}
/**
* Does nothing . The maintenance renderer cannot produce blocks .
*
* @ param string $region
* @ param array $classes
* @ param string $tag
* @ return string
*/
public function blocks ( $region , $classes = array (), $tag = 'aside' ) {
// Computer says no blocks.
// debugging('Please do not use $OUTPUT->'.__FUNCTION__.'() when performing maintenance tasks.', DEBUG_DEVELOPER);
return '' ;
}
/**
* Does nothing . The maintenance renderer cannot produce blocks .
*
* @ param string $region
* @ return string
*/
public function blocks_for_region ( $region ) {
// Computer says no blocks for region.
// debugging('Please do not use $OUTPUT->'.__FUNCTION__.'() when performing maintenance tasks.', DEBUG_DEVELOPER);
return '' ;
}
/**
* Does nothing . The maintenance renderer cannot produce a course content header .
*
* @ param bool $onlyifnotcalledbefore
* @ return string
*/
public function course_content_header ( $onlyifnotcalledbefore = false ) {
// Computer says no course content header.
// debugging('Please do not use $OUTPUT->'.__FUNCTION__.'() when performing maintenance tasks.', DEBUG_DEVELOPER);
return '' ;
}
/**
* Does nothing . The maintenance renderer cannot produce a course content footer .
*
* @ param bool $onlyifnotcalledbefore
* @ return string
*/
public function course_content_footer ( $onlyifnotcalledbefore = false ) {
// Computer says no course content footer.
// debugging('Please do not use $OUTPUT->'.__FUNCTION__.'() when performing maintenance tasks.', DEBUG_DEVELOPER);
return '' ;
}
/**
* Does nothing . The maintenance renderer cannot produce a course header .
*
* @ return string
*/
public function course_header () {
// Computer says no course header.
// debugging('Please do not use $OUTPUT->'.__FUNCTION__.'() when performing maintenance tasks.', DEBUG_DEVELOPER);
return '' ;
}
/**
* Does nothing . The maintenance renderer cannot produce a course footer .
*
* @ return string
*/
public function course_footer () {
// Computer says no course footer.
// debugging('Please do not use $OUTPUT->'.__FUNCTION__.'() when performing maintenance tasks.', DEBUG_DEVELOPER);
return '' ;
}
/**
* Does nothing . The maintenance renderer cannot produce a custom menu .
*
* @ param string $custommenuitems
* @ return string
*/
public function custom_menu ( $custommenuitems = '' ) {
// Computer says no custom menu.
// debugging('Please do not use $OUTPUT->'.__FUNCTION__.'() when performing maintenance tasks.', DEBUG_DEVELOPER);
return '' ;
}
/**
* Does nothing . The maintenance renderer cannot produce a file picker .
*
* @ param array $options
* @ return string
*/
public function file_picker ( $options ) {
// Computer says no file picker.
// debugging('Please do not use $OUTPUT->'.__FUNCTION__.'() when performing maintenance tasks.', DEBUG_DEVELOPER);
return '' ;
}
/**
* Does nothing . The maintenance renderer cannot produce and HTML file tree .
*
* @ param array $dir
* @ return string
*/
public function htmllize_file_tree ( $dir ) {
// Hell no we don't want no htmllized file tree.
// Also why on earth is this function on the core renderer???
// debugging('Please do not use $OUTPUT->'.__FUNCTION__.'() when performing maintenance tasks.', DEBUG_DEVELOPER);
return '' ;
}
/**
* Does nothing . The maintenance renderer does not support JS .
*
* @ param block_contents $bc
*/
public function init_block_hider_js ( block_contents $bc ) {
// Computer says no JavaScript.
// Do nothing, ridiculous method.
}
/**
* Does nothing . The maintenance renderer cannot produce language menus .
*
* @ return string
*/
public function lang_menu () {
// Computer says no lang menu.
// debugging('Please do not use $OUTPUT->'.__FUNCTION__.'() when performing maintenance tasks.', DEBUG_DEVELOPER);
return '' ;
}
/**
* Does nothing . The maintenance renderer has no need for login information .
*
* @ param null $withlinks
* @ return string
*/
public function login_info ( $withlinks = null ) {
// Computer says no login info.
// debugging('Please do not use $OUTPUT->'.__FUNCTION__.'() when performing maintenance tasks.', DEBUG_DEVELOPER);
return '' ;
}
/**
* Does nothing . The maintenance renderer cannot produce user pictures .
*
* @ param stdClass $user
* @ param array $options
* @ return string
*/
public function user_picture ( stdClass $user , array $options = null ) {
// Computer says no user pictures.
// debugging('Please do not use $OUTPUT->'.__FUNCTION__.'() when performing maintenance tasks.', DEBUG_DEVELOPER);
return '' ;
}
}