MDL-21148 geenral support for rendering targets, this should give us more flexibility; please propose improvements in the tracker if necessary, thanks

This commit is contained in:
Petr Skoda 2009-12-17 22:43:27 +00:00
parent be1bb80efa
commit c927e35c48
8 changed files with 112 additions and 64 deletions

View file

@ -27,6 +27,21 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
/** General rendering target, usually normal browser page */
define('RENDERER_TARGET_GENERAL', 'general');
/** Plain text rendering for CLI scripts and cron */
define('RENDERER_TARGET_CLI', 'cli');
/** Plain text rendering intended for sending via email */
define('RENDERER_TARGET_TEXTEMAIL', 'textemail');
/** Rich text html rendering intended for sending via email */
define('RENDERER_TARGET_HTMLEMAIL', 'htmlemail');
/* note: maybe we could define portfolio export target too */
/** /**
* A renderer factory is just responsible for creating an appropriate renderer * A renderer factory is just responsible for creating an appropriate renderer
* for any given part of Moodle. * for any given part of Moodle.
@ -64,9 +79,10 @@ interface renderer_factory {
* @param moodle_page $page the page the renderer is outputting content for. * @param moodle_page $page the page the renderer is outputting content for.
* @param string $component name such as 'core', 'mod_forum' or 'qtype_multichoice'. * @param string $component name such as 'core', 'mod_forum' or 'qtype_multichoice'.
* @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news' * @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news'
* @param string $target one of rendering target constants
* @return object an object implementing the requested renderer interface. * @return object an object implementing the requested renderer interface.
*/ */
public function get_renderer(moodle_page $page, $component, $subtype=null); public function get_renderer(moodle_page $page, $component, $subtype=null, $target=null);
} }
@ -86,7 +102,8 @@ interface renderer_factory {
abstract class renderer_factory_base implements renderer_factory { abstract class renderer_factory_base implements renderer_factory {
/** @var theme_config the theme we belong to. */ /** @var theme_config the theme we belong to. */
protected $theme; protected $theme;
/** @var hardcoded list of core subtypes and their locations */
/** @var hardcoded list of core subtypes and their locations, add more if ßneeded */
protected $core_subtypes = array('webservice' => 'webservice'); protected $core_subtypes = array('webservice' => 'webservice');
/** /**
@ -97,6 +114,27 @@ abstract class renderer_factory_base implements renderer_factory {
$this->theme = $theme; $this->theme = $theme;
} }
/**
* Returns suffix of renderer class expected for given target.
* @param string $target one of the renderer target constants, target is guessed if null used
* @return array two element array, first element is target, second the target suffix string
*/
protected function get_target_suffix($target) {
if (empty($target) and CLI_SCRIPT) {
// automatically guessed default for all CLI scripts
$target = RENDERER_TARGET_CLI;
}
switch ($target) {
case RENDERER_TARGET_CLI: $suffix = '_cli'; break;
case RENDERER_TARGET_TEXTEMAIL: $suffix = '_textemail'; break;
case RENDERER_TARGET_HTMLEMAIL: $suffix = '_htmlemail'; break;
default: $target = RENDERER_TARGET_GENERAL; $suffix = '';
}
return array($target, $suffix);
}
/** /**
* For a given module name, return the name of the standard renderer class * For a given module name, return the name of the standard renderer class
* that defines the renderer interface for that module. * that defines the renderer interface for that module.
@ -114,7 +152,7 @@ abstract class renderer_factory_base implements renderer_factory {
if ($component !== 'core') { if ($component !== 'core') {
// standardize component names // standardize component names
if (strpos($component, '_') === false) { if (strpos($component, '_') === false) {
$component = $component.'_mod'; $component = 'mod_' . $component;
} }
// renderers are stored in renderer.php files // renderers are stored in renderer.php files
if (!$compdirectory = get_component_directory($component)) { if (!$compdirectory = get_component_directory($component)) {
@ -159,42 +197,23 @@ class standard_renderer_factory extends renderer_factory_base {
* @param moodle_page $page the page the renderer is outputting content for. * @param moodle_page $page the page the renderer is outputting content for.
* @param string $component name such as 'core', 'mod_forum' or 'qtype_multichoice'. * @param string $component name such as 'core', 'mod_forum' or 'qtype_multichoice'.
* @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news' * @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news'
* @param string $target one of rendering target constants
* @return object an object implementing the requested renderer interface. * @return object an object implementing the requested renderer interface.
*/ */
public function get_renderer(moodle_page $page, $component, $subtype=null) { public function get_renderer(moodle_page $page, $component, $subtype = null, $target = null) {
$classname = $this->standard_renderer_classname($component, $subtype); $classname = $this->standard_renderer_classname($component, $subtype);
if (!class_exists($classname)) { if (!class_exists($classname)) {
throw new coding_exception('Request for an unknown renderer class ' . $classname); throw new coding_exception('Request for an unknown renderer class ' . $classname);
} }
return new $classname($page);
} list($target, $suffix) = $this->get_target_suffix($target);
if (class_exists($classname . $suffix)) {
// use the specialised renderer for given target, default renderer might also decide
// to implement support for more targets
$classname = $classname . $suffix;
} }
return new $classname($page, $target);
/**
* This is a slight variation on the standard_renderer_factory used by CLI scripts.
* CLI renderers use suffic '_cli' added to the standard renderer names
*
* @copyright 2009 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 2.0
*/
class cli_renderer_factory extends renderer_factory_base {
/**
* Implement the subclass method
* @param moodle_page $page the page the renderer is outputting content for.
* @param string $component name such as 'core', 'mod_forum' or 'qtype_multichoice'.
* @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news'
* @return object an object implementing the requested renderer interface.
*/
public function get_renderer(moodle_page $page, $component, $subtype=null) {
$classname = $this->standard_renderer_classname($component, $subtype);
if (class_exists($classname . '_cli')) {
$classname = $classname . '_cli';
} else if (!class_exists($classname)) {
throw new coding_exception('Request for an unknown renderer class ' . $classname);
}
return new $classname($page);
} }
} }
@ -232,23 +251,43 @@ class theme_overridden_renderer_factory extends renderer_factory_base {
* @param moodle_page $page the page the renderer is outputting content for. * @param moodle_page $page the page the renderer is outputting content for.
* @param string $component name such as 'core', 'mod_forum' or 'qtype_multichoice'. * @param string $component name such as 'core', 'mod_forum' or 'qtype_multichoice'.
* @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news' * @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news'
* @param string $target one of rendering target constants
* @return object an object implementing the requested renderer interface. * @return object an object implementing the requested renderer interface.
*/ */
public function get_renderer(moodle_page $page, $component, $subtype=null) { public function get_renderer(moodle_page $page, $component, $subtype = null, $target = null) {
$classname = $this->standard_renderer_classname($component, $subtype); $classname = $this->standard_renderer_classname($component, $subtype);
if (!class_exists($classname)) { if (!class_exists($classname)) {
// standard renderer must always exist // standard renderer must always exist
throw new coding_exception('Request for an unknown renderer class ' . $classname); throw new coding_exception('Request for an unknown renderer class ' . $classname);
} }
foreach ($this->prefixes as $prefix) { list($target, $suffix) = $this->get_target_suffix($target);
// theme lib.php and renderers.php files are loaded automatically // theme lib.php and renderers.php files are loaded automatically
// when loading the theme configs
// first try the renderers with correct suffix
foreach ($this->prefixes as $prefix) {
if (class_exists($prefix . '_' . $classname . $suffix)) {
$classname = $prefix . '_' . $classname . $suffix;
return new $classname($page, $target);
}
}
if (class_exists($classname . $suffix)) {
// use the specialised renderer for given target, default renderer might also decide
// to implement support for more targets
$classname = $classname . $suffix;
return new $classname($page, $target);
}
// then try general renderer
foreach ($this->prefixes as $prefix) {
if (class_exists($prefix . '_' . $classname)) { if (class_exists($prefix . '_' . $classname)) {
$classname = $prefix . '_' . $classname; $classname = $prefix . '_' . $classname;
return new $classname($page); return new $classname($page, $target);
} }
} }
// use standard renderes if themes do not contain overridden renderer
return new $classname($page); return new $classname($page, $target);
} }
} }

View file

@ -909,19 +909,16 @@ class theme_config {
* @param moodle_page $page the page we are rendering * @param moodle_page $page the page we are rendering
* @param string $module the name of part of moodle. E.g. 'core', 'quiz', 'qtype_multichoice'. * @param string $module the name of part of moodle. E.g. 'core', 'quiz', 'qtype_multichoice'.
* @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news' * @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news'
* @param string $target one of rendering target constants
* @return renderer_base the requested renderer. * @return renderer_base the requested renderer.
*/ */
public function get_renderer(moodle_page $page, $component, $subtype=null) { public function get_renderer(moodle_page $page, $component, $subtype = null, $target = null) {
if (is_null($this->rf)) { if (is_null($this->rf)) {
if (CLI_SCRIPT) {
$classname = 'cli_renderer_factory';
} else {
$classname = $this->rendererfactory; $classname = $this->rendererfactory;
}
$this->rf = new $classname($this); $this->rf = new $classname($this);
} }
return $this->rf->get_renderer($page, $component, $subtype); return $this->rf->get_renderer($page, $component, $subtype, $target);
} }
/** /**

View file

@ -42,14 +42,18 @@ class renderer_base {
protected $opencontainers; protected $opencontainers;
/** @var moodle_page the page we are rendering for. */ /** @var moodle_page the page we are rendering for. */
protected $page; protected $page;
/** @var requested rendering target conatnt */
protected $target;
/** /**
* Constructor * Constructor
* @param moodle_page $page the page we are doing output for. * @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) { public function __construct(moodle_page $page, $target) {
$this->opencontainers = $page->opencontainers; $this->opencontainers = $page->opencontainers;
$this->page = $page; $this->page = $page;
$this->target = $target;
} }
/** /**
@ -202,10 +206,13 @@ class renderer_base {
} }
} }
/** /**
* Basis for all plugin renderers. * Basis for all plugin renderers.
* *
* @author Petr Škoda * @author Petr Skoda (skodak)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 2.0
*/ */
class plugin_renderer_base extends renderer_base { class plugin_renderer_base extends renderer_base {
/** /**
@ -217,10 +224,11 @@ class plugin_renderer_base extends renderer_base {
/** /**
* Contructor method, calls the parent constructor * Contructor method, calls the parent constructor
* @param moodle_page $page * @param moodle_page $page
* @param string $target one of rendering target constants
*/ */
public function __construct(moodle_page $page) { public function __construct(moodle_page $page, $target) {
$this->output = $page->get_renderer('core'); $this->output = $page->get_renderer('core', null, $target);
parent::__construct($page); parent::__construct($page, $target);
} }
/** /**
@ -230,6 +238,8 @@ class plugin_renderer_base extends renderer_base {
* @param string $method * @param string $method
* @param array $arguments * @param array $arguments
* @return mixed * @return mixed
*
* TODO: this might not be the best idea, see MDL-21148 for pros&cons
*/ */
public function __call($method, $arguments) { public function __call($method, $arguments) {
if (method_exists($this->output, $method)) { if (method_exists($this->output, $method)) {
@ -240,6 +250,7 @@ class plugin_renderer_base extends renderer_base {
} }
} }
/** /**
* The standard implementation of the core_renderer interface. * The standard implementation of the core_renderer interface.
* *

View file

@ -524,10 +524,11 @@ class moodle_page {
* Returns instance of page renderer * Returns instance of page renderer
* @param string $component name such as 'core', 'mod_forum' or 'qtype_multichoice'. * @param string $component name such as 'core', 'mod_forum' or 'qtype_multichoice'.
* @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news' * @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news'
* @param string $target one of rendering target constants
* @return renderer_base * @return renderer_base
*/ */
public function get_renderer($component, $subtype = null) { public function get_renderer($component, $subtype = null, $target = null) {
return $this->magic_get_theme()->get_renderer($this, $component, $subtype); return $this->magic_get_theme()->get_renderer($this, $component, $subtype, $target);
} }
/** /**

View file

@ -5,7 +5,7 @@
Roger Johansson - see Roger Johansson - see
"<a href="http://www.456bereastreet.com/archive/200506/customising_custom_corners_and_borders/">customising_custom_corners_and_borders</a>" "<a href="http://www.456bereastreet.com/archive/200506/customising_custom_corners_and_borders/">customising_custom_corners_and_borders</a>"
However, the custom corners theme doesn't use all the JavaScript mentioned by Roger Johansson. However, the custom corners theme doesn't use all the JavaScript mentioned by Roger Johansson.
Instead, divs are added when using the custom_corners_core_renderer (defined in renderers.php) instead of moodle_core renderer. Instead, divs are added when using the custom_corners_core_renderer (defined in renderers.php) instead of core_renderer.
</p> </p>
<p> <p>

View file

@ -2,7 +2,7 @@
/** /**
* This is a slight variatoin on the standard_renderer_factory that uses * This is a slight variatoin on the standard_renderer_factory that uses
* custom_corners_core_renderer instead of moodle_core_renderer. * custom_corners_core_renderer instead of core_renderer.
* *
* This generates the slightly different HTML that the custom_corners theme expects. * This generates the slightly different HTML that the custom_corners theme expects.
* *
@ -18,10 +18,10 @@ class custom_corners_renderer_factory extends standard_renderer_factory {
} }
/* Implement the subclass method. */ /* Implement the subclass method. */
public function get_renderer(moodle_page $page, $module, $subtype=null) { public function get_renderer(moodle_page $page, $component, $subtype = null, $target = null) {
if ($module == 'core') { if ($component == 'core' and empty($subtype)) {
return new custom_corners_core_renderer($page); return new custom_corners_core_renderer($page, $target);
} }
return parent::get_renderer($page, $module, $subtype); return parent::get_renderer($page, $component, $subtype, $target);
} }
} }

View file

@ -37,7 +37,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 2.0 * @since Moodle 2.0
*/ */
class custom_corners_core_renderer extends moodle_core_renderer { class custom_corners_core_renderer extends core_renderer {
protected $wraplevel = 1; protected $wraplevel = 1;
protected function custom_corners_divs($classes = '', $idbase = '') { protected function custom_corners_divs($classes = '', $idbase = '') {

View file

@ -27,7 +27,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
class core_wsdoc_renderer extends plugin_renderer_base { class core_webservice_renderer extends plugin_renderer_base {
/** /**
* Create documentation for a description object * Create documentation for a description object
* @param object $params a part of parameter/return description * @param object $params a part of parameter/return description