Overriding a renderer

Overriding a renderer

by Richard Oelmann -
Number of replies: 15
Picture of Core developers Picture of Plugin developers Picture of Testers

OK, so overriding a renderer, generally, I'm comfortable with, BUT...

I'm trying to override the myprofile renderer - /user/classes/output/myprofile/renderer.php

I can't work out (and have tried various options) and I either get a coding error or nothing at all (as in I get the page as it normally is with no change from my renderer being put in - which at the moment is nothing more than adding an additional class to see it working)

class theme_mytheme_myprofile_renderer extends what_goes_here? {

I know its something simple and related to the namespace being used in the original renderer, but I'm stuck, so would appreciate any pointers to get me out of my blindly stupid moment smile

R

Average of ratings: -
In reply to Richard Oelmann

Re: Overriding a renderer

by Gareth J Barnard -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Plugin developers

Hi Richard,

You are not stupid, I have spent the last two days trying to get this right, hence: https://moodle.org/mod/forum/discuss.php?d=324064.

As you are in the 'output' folder and would have 'namespace theme_flexbase\output;' above then you need to extend '\core_user\output\myprofile\renderer' because of 'namespace core_user\output\myprofile' and 'class renderer'.

Have a look at: https://github.com/gjb2048/moodle-theme_shoelace/blob/MOODLE_29_Beard/classes/output/gizmos_renderer.php

Also see: https://docs.moodle.org/dev/Renderer_best_practices#Location_and_naming.

Cheers,

Gareth

Average of ratings: Useful (1)
In reply to Gareth J Barnard

Re: Overriding a renderer

by Richard Oelmann -
Picture of Core developers Picture of Plugin developers Picture of Testers

Thanks Gareth,

So at the moment I have

namespace theme_flexibase\output;
defined('MOODLE_INTERNAL') || die();
class renderer extends \core_user\output\myprofile\renderer {

public function render_category(category $category) {

But now I'm getting

Strict Standards: Declaration of theme_flexibase\output\renderer::render_category() should be compatible with core_user\output\myprofile\renderer::render_category(core_user\output\myprofile\category $category) in /var/www/html/moodle/theme/flexibase/renderers/core_user_output_myprofile_renderer.php on line 18

And the change I've made to the renderer isn't showing (literally all Ive done at the moment is change the h3 to h2 - I just want to see it working before I actually make my changes).

I guess a strict standards warning isn't exactly the end of the world - but if I can Id like to know why its there and how to fix it, but more importantly, I need to get my changes working.


R

In reply to Richard Oelmann

Re: Overriding a renderer

by Gareth J Barnard -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Plugin developers

Try adding 'use \core_user\output\myprofile\category;' after your 'namespace' declaration at the top but before 'class'.  And leave 'render_category' as 'public function render_category(category $category)'.

Average of ratings: Useful (1)
In reply to Gareth J Barnard

Re: Overriding a renderer

by Richard Oelmann -
Picture of Core developers Picture of Plugin developers Picture of Testers

Well, that got rid of the error Gareth

Now just need to work out why my changes to the renderer dont show up smile

In reply to Richard Oelmann

Re: Overriding a renderer

by Gareth J Barnard -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Plugin developers

Ok, so if the errors were showing up then the API was finding the file and loading it.  So no need for a 'get_renderer' sort of thing.  I think that the next thing to do is find the reference variable that is set to point to the renderer and do a 'error_log(get_class($theVariable))' to see what it is.  If it is yours then must be the your code, if not then your code is not being loaded.

In reply to Gareth J Barnard

Re: Overriding a renderer

by Richard Oelmann -
Picture of Core developers Picture of Plugin developers Picture of Testers
As you say Gareth, the errors suggest the file is being loaded - and if I mess about with the function definition, or the 'use' statements, then I get those errors back, and if I now mess about with the class...extends... bit I get renderers not found, so Im confident those bits are correct now, thanks to your help.

What I can't determine is why the change I make is having no effect - if I make a similar change in the original renderer, then that is implemented, so the original renderer is still in force and is not being overridden.

The code for the profile page uses 

$renderer = $PAGE->get_renderer('core_user', 'myprofile');

Is that preventing the override, perhaps? by directing the page to that specific renderer? In which case how do we override a renderer like that - I really don't want to have to build a new layout just to be able to point to my renderer, as to me that completely removes any point of using renderers and being able to override them in a theme.

Did think that this would be fairly simple, after all its not exactly the first time Ive overridden a renderer! But I can't see the wood for the trees here and I think Im digging myself a bigger hole every time sad Maybe Im over-thinking some of this and it really is simple - I just can't see it and can't see my way between the multiple different ways we now seem to have for doing the same thing!



GOT IT!!!

It is down to the class naming and name space - and I still don't really know what is the best way as I seem to have tried so many combinations, but the one I finally have working is - no namespace and

class theme_flexibase_core_user_myprofile_renderer extends \core_user\output\myprofile\renderer {


Thank you to everyone for your help! Much appreciated!!!

R

Average of ratings: Useful (1)
In reply to Richard Oelmann

Re: Overriding a renderer

by Mary Evans -
Picture of Core developers Picture of Documentation writers Picture of Peer reviewers Picture of Plugin developers Picture of Testers

I am not sure but I think the approach might be something like...

class theme_mytheme_core_user_renderer extends core_user\output\myprofile

the Moodle docs are not that clear...they assume too much.

Average of ratings: Useful (1)
In reply to Mary Evans

Re: Overriding a renderer

by Damyon Wiese -
The place I go to work these type of things out is the unit tests for the renderer factory.

The renderer you are overriding is using ($component = 'core_user', $subtype = 'myprofile').

So substituting this in the examples in the unit test (lib/tests/outputfactories_test.php) (ignore the cli ones as cli is the default renderer target for unit tests).

The search paths for your renderer (in order) are:
'theme_child\\output\\core_user\\myprofile_renderer',
'theme_child\\output\\core_user\\myprofile\\renderer',
'theme_child_core_user_myprofile_renderer',
'theme_parent\\output\\core_user\\myprofile_renderer',
'theme_parent\\output\\core_user\\myprofile\\renderer',
'theme_parent_core_user_myprofile_renderer',
'\\core_user\\output\\myprofile_renderer',
'\\core_user\\output\\myprofile\\renderer',
'core_user_myprofile_renderer',
Average of ratings: Useful (1)
In reply to Mary Evans

Re: Overriding a renderer

by Richard Oelmann -
Picture of Core developers Picture of Plugin developers Picture of Testers

Agree completely Mary

If Gareth has been stuck on the issue he linked earlier, and you and I are both finding the docs difficult to follow, then they need to be rewritten. And no, I'm not volunteering as they need to be rewritten by someone who understands what the blazes is going on with all these different methods of working (if anyone does)


To me, the whole process needs resimplifying - whether that is in terms of renderers, namespaced renderers, autoloaded renderers, templates, whatever. We need ONE system that works and ONE workflow for doing it

R

Average of ratings: Useful (3)
In reply to Richard Oelmann

Re: Overriding a renderer

by Gareth J Barnard -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Plugin developers

Hi Richard,

I'm glad you've solved it!  This is by no means a critisim but a reflection of the dual concurrent systems being used that the line:

class theme_flexibase_core_user_myprofile_renderer extends \core_user\output\myprofile\renderer {

uses both the pre M2.7 system and the post M2.7 namespace system!

So more of a question for those that know: Is the old system depreciated and if so when will it no longer be supported?

Cheers,

Gareth

In reply to Gareth J Barnard

Re: Overriding a renderer

by Gareth J Barnard -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Plugin developers

P.S.

I wonder to use the new system and this is where 'https://docs.moodle.org/dev/Overriding_a_renderer#Namespaces' does not really explain the folder location that it could be:

namespace theme_flexibase\output\core_user\myprofile;
class renderer extends \core_user\output\myprofile\renderer {

and the file be called 'renderer.php' in the folder '/theme/flexibase/classes/output/core_user/myprofile/'?

Average of ratings: Useful (1)
In reply to Gareth J Barnard

Re: Overriding a renderer

by Mary Evans -
Picture of Core developers Picture of Documentation writers Picture of Peer reviewers Picture of Plugin developers Picture of Testers

There's loads of info in php manuel about NAMESPACES and how they can be used in unison with each other.  This in itself is complex, but the commonality with the renderers and how we have used them in Moodle does not help especially when the docs assumes you know the format that NAMESPACES in Moodle have a set pattern. The pattern, or format or whatever it is called is well hidden in the docs and only briefly mentioned, as though it was a well known fact.

Perhaps we all need to go on a Moodle Themes Moot In the UK and talk seriously about all this stuff!

Cheers

Mary

Average of ratings: Useful (1)
In reply to Gareth J Barnard

Re: Overriding a renderer

by Richard Oelmann -
Picture of Core developers Picture of Plugin developers Picture of Testers
Was aware that I was mixing old and new, but was just relieved that it worked at that stage smile
Your method also works and is obviously better because it doesn't mix the old and new in the same file - which is what I was originally looking for.

Thanks for that smile
In reply to Gareth J Barnard

Re: Overriding a renderer

by Mary Evans -
Picture of Core developers Picture of Documentation writers Picture of Peer reviewers Picture of Plugin developers Picture of Testers

I think Gareth that overriding a namespace renderer using a normal renderer is acceptable the way Richard us using it now.

However, creating a new namespace renderer class as you suggested earlier, At least I think that is what you were suggesting, would be an alternative.

It does say in the Docs that a namespace class can override a none namespace renderer and vica versa. It just points you to thr lib/tests as Damyon mentioned in his reply today in this discussion.

Problem is there is a lot to learn and I'm trying to get on with some housework and finding it frustrating not to be able to go play on my computer! 

M

Average of ratings: Useful (1)
In reply to Mary Evans

Re: Overriding a renderer

by Gareth J Barnard -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Plugin developers

Hi Mary,

True on both accounts:

  • Can be done either way of a mixture of the two.
  • Housework does get in the way of Moodle ;).

Cheers

Gareth

Average of ratings: Useful (1)