| 1 | <!----------------------------------------------------------------------- |
|---|
| 2 | ******************************************************************************** |
|---|
| 3 | Copyright 2005-2008 ColdBox Framework by Luis Majano and Ortus Solutions, Corp |
|---|
| 4 | www.coldboxframework.com | www.luismajano.com | www.ortussolutions.com |
|---|
| 5 | ******************************************************************************** |
|---|
| 6 | |
|---|
| 7 | Author : Luis Majano |
|---|
| 8 | Date : 10/31/2007 |
|---|
| 9 | Description : |
|---|
| 10 | This is a method injector based on the work by Mark Mandel. |
|---|
| 11 | -----------------------------------------------------------------------> |
|---|
| 12 | <cfcomponent name="methodInjector" |
|---|
| 13 | hint="Method Injector plugin. It provides a nice way to mixin and remove methods from cfc's" |
|---|
| 14 | extends="coldbox.system.plugin" |
|---|
| 15 | output="false" |
|---|
| 16 | cache="true"> |
|---|
| 17 | |
|---|
| 18 | <!------------------------------------------- CONSTRUCTOR -------------------------------------------> |
|---|
| 19 | |
|---|
| 20 | <cffunction name="init" access="public" returntype="methodInjector" output="false" hint="Constructor"> |
|---|
| 21 | <!--- ************************************************************* ---> |
|---|
| 22 | <cfargument name="controller" type="any" required="true"> |
|---|
| 23 | <!--- ************************************************************* ---> |
|---|
| 24 | <cfscript> |
|---|
| 25 | super.init(arguments.controller); |
|---|
| 26 | |
|---|
| 27 | /* Plugin Properties */ |
|---|
| 28 | setPluginName("Method Injector"); |
|---|
| 29 | setPluginVersion("1.0"); |
|---|
| 30 | setPluginDescription("A way to inject and remove methods from cfc's"); |
|---|
| 31 | |
|---|
| 32 | /* Our mixins Struct */ |
|---|
| 33 | instance.mixins = StructNew(); |
|---|
| 34 | |
|---|
| 35 | /* Place our methods on the mixins struct */ |
|---|
| 36 | instance.mixins["removeMixin"] = variables.removeMixin; |
|---|
| 37 | instance.mixins["injectMixin"] = variables.injectMixin; |
|---|
| 38 | instance.mixins["invokerMixin"] = variables.invokerMixin; |
|---|
| 39 | instance.mixins["injectPropertyMixin"] = variables.injectPropertyMixin; |
|---|
| 40 | instance.mixins["removePropertyMixin"] = variables.removePropertyMixin; |
|---|
| 41 | instance.mixins["populatePropertyMixin"] = variables.populatePropertyMixin; |
|---|
| 42 | |
|---|
| 43 | /* Remove mixin methods */ |
|---|
| 44 | stop(this); |
|---|
| 45 | |
|---|
| 46 | return this; |
|---|
| 47 | </cfscript> |
|---|
| 48 | </cffunction> |
|---|
| 49 | |
|---|
| 50 | <!------------------------------------------- PUBLIC METHODS -------------------------------------------> |
|---|
| 51 | |
|---|
| 52 | <!--- Start Method Injection on a CFC ---> |
|---|
| 53 | <cffunction name="start" hint="start method injection set. Injects: injectMixin,removeMixin,invokerMixin,injectPropertyMixin,removePropertyMixin" access="public" returntype="void" output="false"> |
|---|
| 54 | <!--- ************************************************************* ---> |
|---|
| 55 | <cfargument name="CFC" hint="The cfc to inject the method into" type="any" required="Yes"> |
|---|
| 56 | <!--- ************************************************************* ---> |
|---|
| 57 | <cfset var udf = 0> |
|---|
| 58 | |
|---|
| 59 | <cflock name="plugin.methodInjector.#getmetadata(arguments.cfc).name#" type="exclusive" timeout="5" throwontimeout="true"> |
|---|
| 60 | <cfscript> |
|---|
| 61 | /* Inject Mixins methods */ |
|---|
| 62 | for( udf in instance.mixins ){ |
|---|
| 63 | arguments.CFC[udf] = instance.mixins[udf]; |
|---|
| 64 | } |
|---|
| 65 | </cfscript> |
|---|
| 66 | </cflock> |
|---|
| 67 | </cffunction> |
|---|
| 68 | |
|---|
| 69 | <!--- Stop the injection, do cleanup ---> |
|---|
| 70 | <cffunction name="stop" hint="stop injection block. Removes mixed in methods." access="public" returntype="void" output="false"> |
|---|
| 71 | <!--- ************************************************************* ---> |
|---|
| 72 | <cfargument name="CFC" hint="The cfc to inject the method into" type="any" required="Yes"> |
|---|
| 73 | <!--- ************************************************************* ---> |
|---|
| 74 | <cfset var udf = 0> |
|---|
| 75 | |
|---|
| 76 | <cflock name="plugin.methodInjector.#getmetadata(arguments.cfc).name#" type="exclusive" timeout="5" throwontimeout="true"> |
|---|
| 77 | <cfscript> |
|---|
| 78 | /* Remove Mixin Methods */ |
|---|
| 79 | for( udf in instance.mixins ){ |
|---|
| 80 | arguments.CFC[udf] = instance.mixins[udf]; |
|---|
| 81 | StructDelete(arguments.CFC, udf); |
|---|
| 82 | } |
|---|
| 83 | </cfscript> |
|---|
| 84 | </cflock> |
|---|
| 85 | </cffunction> |
|---|
| 86 | |
|---|
| 87 | <!--- ColdBox Controller Accessor/Mutators used to mixing ---> |
|---|
| 88 | <cffunction name="getcontroller" access="public" output="false" returntype="any" hint="Get controller: coldbox.system.controller"> |
|---|
| 89 | <cfreturn variables.controller/> |
|---|
| 90 | </cffunction> |
|---|
| 91 | <cffunction name="setcontroller" access="public" output="false" returntype="void" hint="Set controller"> |
|---|
| 92 | <cfargument name="controller" type="any" required="true" hint="coldbox.system.controller"/> |
|---|
| 93 | <cfset variables.controller = arguments.controller/> |
|---|
| 94 | </cffunction> |
|---|
| 95 | |
|---|
| 96 | <!------------------------------------------- PRIVATE -------------------------------------------> |
|---|
| 97 | |
|---|
| 98 | <!--- mixin ---> |
|---|
| 99 | <cffunction name="injectMixin" hint="injects a method into the CFC scope" access="public" returntype="void" output="false"> |
|---|
| 100 | <!--- ************************************************************* ---> |
|---|
| 101 | <cfargument name="UDF" hint="UDF to be checked" type="any" required="Yes"> |
|---|
| 102 | <!--- ************************************************************* ---> |
|---|
| 103 | <cfscript> |
|---|
| 104 | var metadata = getMetaData(arguments.UDF); |
|---|
| 105 | |
|---|
| 106 | /* Check for metadata Access */ |
|---|
| 107 | if( not structKeyExists(metadata, "access") ){ |
|---|
| 108 | metadata.access = "public"; |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | /* Place UDF on the variables Scope */ |
|---|
| 112 | variables[metadata.name] = arguments.UDF; |
|---|
| 113 | |
|---|
| 114 | if(metadata.access neq "private"){ |
|---|
| 115 | /* Place UDF on the this public scope */ |
|---|
| 116 | this[metaData.name] = arguments.UDF; |
|---|
| 117 | } |
|---|
| 118 | </cfscript> |
|---|
| 119 | </cffunction> |
|---|
| 120 | |
|---|
| 121 | <!--- mixin ---> |
|---|
| 122 | <cffunction name="populatePropertyMixin" hint="Populates a property if it exists" access="public" returntype="void" output="false"> |
|---|
| 123 | <!--- ************************************************************* ---> |
|---|
| 124 | <cfargument name="propertyName" type="string" required="true" hint="The name of the property to inject."/> |
|---|
| 125 | <cfargument name="propertyValue" type="any" required="true" hint="The value of the property to inject"/> |
|---|
| 126 | <cfargument name="scope" type="string" required="false" default="variables" hint="The scope to which inject the property to."/> |
|---|
| 127 | <!--- ************************************************************* ---> |
|---|
| 128 | <cfscript> |
|---|
| 129 | /* Validate Property */ |
|---|
| 130 | if( structKeyExists(evaluate(arguments.scope),arguments.propertyName) ){ |
|---|
| 131 | /* Populate Property */ |
|---|
| 132 | "#arguments.scope#.#arguments.propertyName#" = arguments.propertyValue; |
|---|
| 133 | } |
|---|
| 134 | </cfscript> |
|---|
| 135 | </cffunction> |
|---|
| 136 | |
|---|
| 137 | <!--- mixin ---> |
|---|
| 138 | <cffunction name="injectPropertyMixin" hint="injects a property into the passed scope" access="public" returntype="void" output="false"> |
|---|
| 139 | <!--- ************************************************************* ---> |
|---|
| 140 | <cfargument name="propertyName" type="string" required="true" hint="The name of the property to inject."/> |
|---|
| 141 | <cfargument name="propertyValue" type="any" required="true" hint="The value of the property to inject"/> |
|---|
| 142 | <cfargument name="scope" type="string" required="false" default="variables" hint="The scope to which inject the property to."/> |
|---|
| 143 | <!--- ************************************************************* ---> |
|---|
| 144 | <cfscript> |
|---|
| 145 | /* Inject Property */ |
|---|
| 146 | "#arguments.scope#.#arguments.propertyName#" = arguments.propertyValue; |
|---|
| 147 | </cfscript> |
|---|
| 148 | </cffunction> |
|---|
| 149 | |
|---|
| 150 | <!--- Remove Mixin ---> |
|---|
| 151 | <cffunction name="removeMixin" hint="removes a method in a CFC" access="public" returntype="void" output="false"> |
|---|
| 152 | <!--- ************************************************************* ---> |
|---|
| 153 | <cfargument name="UDFName" hint="Name of the UDF to be removed" type="string" required="Yes"> |
|---|
| 154 | <!--- ************************************************************* ---> |
|---|
| 155 | <cfscript> |
|---|
| 156 | StructDelete(this, arguments.udfName); |
|---|
| 157 | StructDelete(variables, arguments.udfName); |
|---|
| 158 | </cfscript> |
|---|
| 159 | </cffunction> |
|---|
| 160 | |
|---|
| 161 | <!--- Remove Mixin ---> |
|---|
| 162 | <cffunction name="removePropertyMixin" hint="removes a property from the cfc used." access="public" returntype="void" output="false"> |
|---|
| 163 | <!--- ************************************************************* ---> |
|---|
| 164 | <cfargument name="propertyName" type="string" required="true" hint="The name of the property to remove."/> |
|---|
| 165 | <cfargument name="scope" type="string" required="false" default="variables" hint="The scope to which inject the property to."/> |
|---|
| 166 | <!--- ************************************************************* ---> |
|---|
| 167 | <cfscript> |
|---|
| 168 | structDelete(evaluate(arguments.scope),arguments.propertyName); |
|---|
| 169 | </cfscript> |
|---|
| 170 | </cffunction> |
|---|
| 171 | |
|---|
| 172 | <!--- Invoker Mixin ---> |
|---|
| 173 | <cffunction name="invokerMixin" hint="calls private/packaged/public methods" access="public" returntype="any" output="false"> |
|---|
| 174 | <!--- ************************************************************* ---> |
|---|
| 175 | <cfargument name="method" type="string" required="Yes" hint="Name of the private method to call"> |
|---|
| 176 | <cfargument name="argCollection" type="struct" required="No" hint="Can be called with an argument collection struct"> |
|---|
| 177 | <cfargument name="argList" type="string" required="No" hint="Can be called with an argument list, for simple values only: ex: 'plugin=logger,number=1'"> |
|---|
| 178 | <!--- ************************************************************* ---> |
|---|
| 179 | <cfset var results = ""> |
|---|
| 180 | <cfset var key = ""> |
|---|
| 181 | |
|---|
| 182 | <!--- Determine type of invocation ---> |
|---|
| 183 | <cfif structKeyExists(arguments,"argCollection")> |
|---|
| 184 | <cfinvoke method="#arguments.method#" |
|---|
| 185 | returnvariable="results" |
|---|
| 186 | argumentcollection="#arguments.argCollection#" /> |
|---|
| 187 | <cfelseif structKeyExists(arguments, "argList")> |
|---|
| 188 | <cfinvoke method="#arguments.method#" |
|---|
| 189 | returnvariable="results"> |
|---|
| 190 | <cfloop list="#argList#" index="key"> |
|---|
| 191 | <cfinvokeargument name="#listFirst(key,'=')#" value="#listLast(key,'=')#"> |
|---|
| 192 | </cfloop> |
|---|
| 193 | </cfinvoke> |
|---|
| 194 | <cfelse> |
|---|
| 195 | <cfinvoke method="#arguments.method#" |
|---|
| 196 | returnvariable="results" /> |
|---|
| 197 | </cfif> |
|---|
| 198 | |
|---|
| 199 | <!--- Return results if Found ---> |
|---|
| 200 | <cfif isDefined("results")> |
|---|
| 201 | <cfreturn results> |
|---|
| 202 | </cfif> |
|---|
| 203 | </cffunction> |
|---|
| 204 | |
|---|
| 205 | </cfcomponent> |
|---|