stevewithington / MuraPlugin

A generic, ulta-simple starter plugin for Mura CMS
Apache License 2.0
9 stars 12 forks source link

Instantiation of /extensions/contentrenderer.cfc with MuraScope #3

Closed Jimcumming closed 9 years ago

Jimcumming commented 9 years ago

Hi Steve,

I've come across an issue whilst using your plugin example. When you are using the CFC based display method the MuraScope doesn't get passed to the content renderer. In fact you end up with the PluginConfig set as $ instead.

This is happening because MuraCMS/requirements/mura/plugin/pluginManager.cfc doesn't pass $ to the contentrenderer on init. See https://github.com/blueriver/MuraCMS/blob/develop/requirements/mura/plugin/pluginManager.cfc#L2322

I'm not sure if this is an issue with Mura or with the Plugin. I was hoping you could shed some light.

Thanks

Jim

stevewithington commented 9 years ago

@Jimcumming,

Do you have an error message or anything that you can point me to that you're actually running into? I'm asking because my plugin's contentRenderer.cfc is initialised during the onSiteRequestStart() method of my eventHandler.cfc, and I'm passing in the mura scope there. Then, any methods of the plugin's contentRenderer are available as $.muraPlugin.{yourMethodName()}.

In other words, I'm not actually stuffing the plugins' contentRenderer methods into Mura's contentRenderer. I hope that makes sense.

Jimcumming commented 9 years ago

Hi Steve,

If you just install your vanilla plugin, without making any changes, and then place the SayHello(CFC) display object on a page using the layout and objects tab. Then update your contentrenderer.cfc so it returns a dump of $ property instead of saying hello.

    public string function sayHello() {
        return writedump(get$());
    }

You'll see that you don't get the mura scope, you actually get the pluginconfig.

Or if you update the sayHello method so it uses something in the Mura Scope.

    public string function sayHello() {
        return '<h3>Hello from #get$().currentURL()#</h3>';
    }

You'll get the error - component [mura.plugin.pluginConfig] has no function with name [currentURL]

This is because the getComponent method in MuraCMS/requirements/mura/plugin/pluginManager.cfc creates a new instance of the plugin's content renderer and passes the pluginconfig and site's configbean instead of the Mura scope.

    <cfset pluginConfig=getConfig(arguments.pluginID)>
    <cfreturn createObject("component",componentPath).init(pluginConfig,configBean) />
stevewithington commented 9 years ago

Instead of calling get$(), just call $ and it should work.

stevewithington commented 9 years ago

The Mura Scope is being passed in to sayHello() ... so, I could go ahead and explicitly add it so others would know it's being injected (as well as the event scope). In fact, dump the arguments and you'll see.

stevewithington commented 9 years ago

I should also point out that the Mura Scope is only injected when using it as a registered display object of Mura!

Jimcumming commented 9 years ago

Ah ok, my actual issue is that I'm instantiating some of my custom components in the plugin.extensions.contentrenderer.init() method, so it's those that are falling over as they are expecting the mura scope.

For example

public any function init(required struct $) {
        set$(arguments.$);
        setDisplayManager( New customPlugin.lib.displayManager(get$()) );
        return this;
    }

Any ideas around this? At the moment I've written a custom set$() method, but it just feels a bit wrong that I need to do this.

    public void function set$($) {
        if(isInstanceOf($,'mura.MuraScope')){
            variables.$ = arguments.$;
        } else {
            var siteid = structKeyExists(session, "siteid") ? session.siteid : 'default';
            variables.$ = application.serviceFactory.getBean('$').init(siteid);
        }
    }
stevewithington commented 9 years ago

The thing you have to remember is at what point are you initialising it? For example, as I mentioned before, I initialise the contentRenderer during the onSiteRequestStart ... so, you could reinitialise it during onRenderStart as well if you wanted to.

stevewithington commented 9 years ago

@Jimcumming, also, if you're using things like displayManager and so forth, you might be better off using my MuraFW1 plugin instead.

Jimcumming commented 9 years ago

Thanks the advice, I originally thought of using the FW/1 version as I'm a big fan of that, but I'm not really doing anything that complex within Mura. It will be rendering a single view from multiple component templates. There aren't multiple views or changes in state, just one complex view. Any interactivity is happening via JS.

I'm still a bit confused as to why Mura wants to reinit the plugin's content renderer. But I'll just work around it for now, just seemed like a bug to me.

stevewithington commented 9 years ago

@Jimcumming, I'll take a closer look at what you've found ... but I just ran some tests. Here's the thing, in my sayHello() method, I placed a call to WriteDump(IsInstanceOf($, 'mura.MuraScope')); and included the display object both as a registered display object (through the UI), and also using the [m] tag. In both instances, the result was true.

However, if I dump WriteDump(IsInstanceOf(variables.$, 'mura.MuraScope')); it only returns true from the [m] usage, but false as a registered display object.

So, I've been able to replicate your issue and understand what you're saying. This would be a Mura issue, and I'll take a deeper look. On that note, I'll close this issue here for now. If you run into anything else, let me know.

Thanks!

stevewithington commented 9 years ago

@Jimcumming, i've made several changes to this plugin, and added notes to the various methods, etc. regarding the Mura Scope issue/s. the most notable change is that i've renamed the file originally called contentRenderer.cfc to displayObjects.cfc. you may want to browse through that file to see the main changes, but ultimately, i'm not longer passing in the Mura Scope to init it, and have created a separate way to obtain the Mura Scope.

if you need it from within the display method itself, you could call it like so: var $ = StructKeyExists(variables, '$') ? variables.$ : get$(arguments);

this way, it accounts for if the plugin is being displayed from a registered display object, or from [m] tags, or even $.dspMethod() ... because i've also included an example of how to inject custom methods into Mura's contentRenderer.cfc as found in the eventHandler.cfc.

thanks!