MuraCon Notes - Getting Started With Mura Plugins

October 01, 2013

Getting Started With Mura Plugins - Steve Withington

While at MuraCon this week I had several moments where the info I got out of a presentation wasn't what I was -hoping- to get beforehand, but it was just as useful. One of those moments came in Steve's talk on Mura plugins. I saw 1 demo ages ago about building a Mura plugin, and the demo was rather complex and hard to follow (I don't remember who the speaker was). It looked as if building a Mura plugin required all kinds of machinery and configuration and such to get working (and heck maybe at the time, it did, this was a few years ago). At the time, I dismissed Mura plugins as difficult and didn't give them much thought....until the FW/1 Connector plugin came out. With that, I was able to start building Mura plugins as FW/1 apps and there was basically no learning curve at all.

Then I saw Steve's preso today, on an "intro to mura plugins". Up until this talk, I was under the impression that there were 2 ways to build Mura plugins -- 1) Using the streamlined FW/1 method I'd been using or 2) whatever that old complex system was I saw before.

It turns out...you can build Mura plugins ANY way you want! All you need to do is put a config file in the /plugins directory and then write whatever code you feel like writing! It can be spaghetti CFM, it can be ColdBox, whatever you want!

Developers: Ever felt like you want to present on a topic at a conference, but someone else has already done that subject?

Advisory Boards at Conferences: Ever looked at a submission from a new speaker and thought "oh, that topic is old" or "we already have a guy that speaks on that subject"?

This is a prime example of when ALL of that thinking is wrong! Had Steve not given his version of this talk, I would have gone on thinking wrongly about how to build Mura plugins (due to whatever that old, poorly constructed, presentation was that I saw.) Getting different people to discuss "older" concepts definitely has value at conferences. Also, not everybody builds sites the way you do, and not everybody wants to see them same people give the same presentations over and over...especially when we pay money to attend these things. So thank you, Mura/Blue River for not following the trend that I see at all too many other conferences in this regard.

Anyway, my notes are like so...

before we start...
learncfinaweek.com
-- free resource to learn CF code

why plugins?
- update-safe customizations
- distribute code across sites / installs
- customize the Mura Admin
- integrate existing applications
- can sell plugins on the MarketPlace

plugin anatomy --
index.cfm
license.txt
/plugin
/plugin/config.xml.cfm
/plugin.cfc
/config.cfm
...zip it up and that's your plugin

plugin/config.xml.cfm
set some base variables for your plugin in here

as of 6.0, the basics are:
name - name of the plugin
package - the directory name that's used when deploying the plugin. a cf mapping is AUTOMATICALLY created based on the package name
directoryFormat (no longer needed in 6.1)
loadPriority - if you have multiple plugins that are depending on each other (maybe a "Setup" plugin loads first, then a 2nd plugin later uses that Setup stuff). use this to specify which order the plugins get loaded. mostly for stuffing things into application scope
version
provider
provider url
category -- application or utility. those are the 2 main ones. but you can call it whatever you want. all IT DOESis create a new tab in the "site view" of Admin
settings -- can define custom settings yo might want to collect from the user. api key, 3rd party dsn, etc
eventHandlers
displayObjects
extension...for custom class extensions, to make them available.

to install a plugin, just put your folder in the /plugin directory and click "reload"...auto-installs the plugin
(new in 6.1 can also deploy via URL)

http://site/plugin/plugin1

calls the index.cfm in that plugin folder
by default this it NOT protected by being logged in/out of Mura Admin, etc -- it will be a PUBLICLY available URL

plugin.cfc
install()
update()
delete()
...custom handlers for when this plugin is installed, updated, deleted. so you can clean up after your plugin nicely, build new database tables, etc.

Plugins have access to Mura $scope
Everything in Mura scope is available in the plugin
...need a way to define the Mura scope in my app:
(Steve's slide deck has a code sample for this)

plugin config:
$.getBean( "pluginManager" ).getConfig("packageName");
then can do getName, getApplication, getSession, etc.

getAssignedSites-- what sites are assigned to use this plugin

getApplication() - application scope for the plugin
getSession() - session scope for the plugin
...safe way to use those scopes without colliding with Mura's own app/session scopes


$.getBean( "pluginManager" ).renderAdminTemplate( body="#pluginBody#", pageTitle = pluginConfig.getName() )
...wraps your plugin in the Mura Admin chrome
...does NOT control the access.
Just because i called renderAdminTemplate() doesn't mean it's restricted! (Though the Mura Admin stuff is still locked down correctly.)

github.com/stevewithinton/MuraPlugin
...uses application.cfc to restrict

display objects --
<displayObject name = "say hello" displayobjectfile="extensions/dspHello.cfm">

or
< displayObjects component="extensions.displayObjects", displayMethod=dspHello" >
...will envoke the dspHello method in the dispalyObjects.cfc file

displayObjects file
-- can put whatever you want in there

Mura Events
applicationFlow = chain of events that fire in sequence
each link in the chain can be added to, or REPLACED

...be careful about what plugins you install. because i could install a plugin that intercepts ALL the site events and just takes down your site

when using

500 Error

Syntax Error, Invalid Construct

Code: 0

Type: 0


Column: 0
ID: ??
Line: 2736
Raw Trace: content.contentrenderer_cfc$cf.udfCallb(/mura/content/contentRenderer.cfc:2736)
Template: D:\Websites\southofshasta.com\core\mura\content\contentRenderer.cfc
Type: cfml


Column: 0
ID: ??
Line: 88
Raw Trace: content.contentrendererutility_cfc$cf.udfCall1(/mura/content/contentRendererUtility.cfc:88)
Template: D:\Websites\southofshasta.com\core\mura\content\contentRendererUtility.cfc
Type: cfml


Column: 0
ID: ??
Line: 3089
Raw Trace: content.contentrenderer_cfc$cf.udfCalle(/mura/content/contentRenderer.cfc:3089)
Template: D:\Websites\southofshasta.com\core\mura\content\contentRenderer.cfc
Type: cfml


Column: 0
ID: ??
Line: 1918
Raw Trace: content.contentrenderer_cfc$cf.udfCall7(/mura/content/contentRenderer.cfc:1918)
Template: D:\Websites\southofshasta.com\core\mura\content\contentRenderer.cfc
Type: cfml


Column: 0
ID: ??
Line: 262
Raw Trace: cfobject_cfc$cf.udfCall3(/mura/cfobject.cfc:262)
Template: D:\Websites\southofshasta.com\core\mura\cfobject.cfc
Type: cfml


Column: 0
ID: ??
Line: 135
Raw Trace: masascope_cfc$cf.udfCall1(/mura/MasaScope.cfc:135)
Template: D:\Websites\southofshasta.com\core\mura\MasaScope.cfc
Type: cfml


Column: 0
ID: ??
Line: 28
Raw Trace: themes.sos.templates.one_column_cfm180$cf$5fdo.call(/muraWRM/themes/sos/templates/one-column.cfm:28)
Template: D:\Websites\southofshasta.com\themes\sos\templates\one-column.cfm
Type: cfml


Column: 0
ID: ??
Line: 2
Raw Trace: themes.sos.templates.default_cfm$cf$5fdn.call(/muraWRM/themes/sos/templates/default.cfm:2)
Template: D:\Websites\southofshasta.com\themes\sos\templates\default.cfm
Type: cfml


Column: 0
ID: ??
Line: 130
Raw Trace: translator.standardhtmltranslator_cfc$cf$5lur.udfCall(/mura/Translator/standardHTMLTranslator.cfc:130)
Template: D:\Websites\southofshasta.com\core\mura\Translator\standardHTMLTranslator.cfc
Type: cfml


Column: 0
ID: ??
Line: 169
Raw Trace: plugin.pluginstandardeventwrapper_cfc$cf.udfCall(/mura/plugin/pluginStandardEventWrapper.cfc:169)
Template: D:\Websites\southofshasta.com\core\mura\plugin\pluginStandardEventWrapper.cfc
Type: cfml


Column: 0
ID: ??
Line: 119
Raw Trace: handler.standardeventshandler_cfc$cf.udfCall1(/mura/Handler/standardEventsHandler.cfc:119)
Template: D:\Websites\southofshasta.com\core\mura\Handler\standardEventsHandler.cfc
Type: cfml


Column: 0
ID: ??
Line: 1404
Raw Trace: utility_cfc$cf.udfCall7(/mura/utility.cfc:1404)
Template: D:\Websites\southofshasta.com\core\mura\utility.cfc
Type: cfml


Column: 0
ID: ??
Line: 119
Raw Trace: plugin.pluginstandardeventwrapper_cfc$cf.udfCall(/mura/plugin/pluginStandardEventWrapper.cfc:119)
Template: D:\Websites\southofshasta.com\core\mura\plugin\pluginStandardEventWrapper.cfc
Type: cfml


Column: 0
ID: ??
Line: 454
Raw Trace: handler.standardeventshandler_cfc$cf.udfCall3(/mura/Handler/standardEventsHandler.cfc:454)
Template: D:\Websites\southofshasta.com\core\mura\Handler\standardEventsHandler.cfc
Type: cfml


Column: 0
ID: ??
Line: 1404
Raw Trace: utility_cfc$cf.udfCall7(/mura/utility.cfc:1404)
Template: D:\Websites\southofshasta.com\core\mura\utility.cfc
Type: cfml


Column: 0
ID: ??
Line: 119
Raw Trace: plugin.pluginstandardeventwrapper_cfc$cf.udfCall(/mura/plugin/pluginStandardEventWrapper.cfc:119)
Template: D:\Websites\southofshasta.com\core\mura\plugin\pluginStandardEventWrapper.cfc
Type: cfml


Column: 0
ID: ??
Line: 909
Raw Trace: content.contentserver_cfc$cf.udfCall2(/mura/content/contentServer.cfc:909)
Template: D:\Websites\southofshasta.com\core\mura\content\contentServer.cfc
Type: cfml


Column: 0
ID: ??
Line: 294
Raw Trace: content.contentserver_cfc$cf.udfCall1(/mura/content/contentServer.cfc:294)
Template: D:\Websites\southofshasta.com\core\mura\content\contentServer.cfc
Type: cfml


Column: 0
ID: ??
Line: 380
Raw Trace: content.contentserver_cfc$cf.udfCall1(/mura/content/contentServer.cfc:380)
Template: D:\Websites\southofshasta.com\core\mura\content\contentServer.cfc
Type: cfml


Column: 0
ID: ??
Line: 780
Raw Trace: content.contentserver_cfc$cf.udfCall2(/mura/content/contentServer.cfc:780)
Template: D:\Websites\southofshasta.com\core\mura\content\contentServer.cfc
Type: cfml


Column: 0
ID: ??
Line: 75
Raw Trace: index_cfm$cf$5fgo.call(/index.cfm:75)
Template: D:\Websites\southofshasta.com\index.cfm
Type: cfml

</div>

Other resources:
getmura.com/forum
...tho that's going away
use the Google Group and the LInkedIn (MuraCMS Develoeprs) instead
MuraBooks (not updated for 6.1 yet)
muracloud.com