root / framework / tags / fusebox51B1 / fuseboxPlugin.cfc

Revision 294, 9.5 kB (checked in by scorfield, 2 years ago)

Fixes #163 by creating a centralized function to canonicalize a path that actually does it correctly!

Line 
1<!---
2Copyright 2006 TeraTech, Inc. http://teratech.com/
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15--->
16<cfcomponent output="false" hint="I represent a plugin declaration.">
17
18        <cffunction name="init" returntype="fuseboxPlugin" access="public" output="false"
19                                hint="I am the constructor.">
20                <cfargument name="phase" type="string" required="true"
21                                        hint="I am the phase with which this plugin is associated." />
22                <cfargument name="pluginXML" type="any" required="true"
23                                        hint="I am the XML representation of this plugin's declaration." />
24                <cfargument name="fbApp" type="fuseboxApplication" required="true"
25                                        hint="I am the fusebox application object." />
26                <cfargument name="lexicons" type="struct" required="true"
27                                        hint="I am the lexicons declared in the fusebox.xml file that are available as custom attributes." />
28       
29                <cfset var i = 0 />
30                <cfset var n = arrayLen(arguments.pluginXML.xmlChildren) />
31                <cfset var attr = 0 />
32                <cfset var ns = "" />
33                <cfset var verbChildren = arrayNew(1) />
34                <cfset var factory = arguments.fbApp.getFuseactionFactory() />
35                <cfset var ext = "." & arguments.fbApp.scriptFileDelimiter />
36               
37                <cfif arguments.pluginXML.xmlName is "plugin">
38               
39                        <cfif not structKeyExists(arguments.pluginXML.xmlAttributes,"name")>
40                                <cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
41                                                message="Required attribute is missing"
42                                                detail="The attribute 'name' is required, for a '#arguments.phase#' plugin declaration in fusebox.xml." />
43                        </cfif>
44                       
45                        <cfset variables.name = arguments.pluginXML.xmlAttributes.name />
46                        <cfset variables.fuseboxApplication = arguments.fbApp />
47                        <cfset variables.customAttribs = structNew() />
48       
49                        <cfif not structKeyExists(arguments.pluginXML.xmlAttributes,"template")>
50                                <cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
51                                                message="Required attribute is missing"
52                                                detail="The attribute 'template' is required, for the '#getName()#' plugin declaration in fusebox.xml." />
53                        </cfif>
54       
55                        <cfset variables.phase = arguments.phase />
56
57                        <cfset this.path = arguments.fbApp.getPluginsPath() />
58
59                        <cfif structKeyExists(arguments.pluginXML.xmlAttributes,"path")>
60                                <cfif left(arguments.pluginXML.xmlAttributes.path,1) is "/">
61                                        <!--- path is absolute, ignore normal plugins path --->
62                                        <cfset this.path = arguments.fbApp.normalizePartialPath(arguments.pluginXML.xmlAttributes.path) />
63                                <cfelse>
64                                        <cfset this.path = this.path & arguments.fbApp.normalizePartialPath(arguments.pluginXML.xmlAttributes.path) />
65                                </cfif>
66                        </cfif>
67                       
68                        <!--- look for any valid custom attributes --->
69                        <cfloop collection="#arguments.pluginXML.xmlAttributes#" item="attr">
70                                <cfswitch expression="#attr#">
71
72                                <cfcase value="name,template,path">
73                                        <!--- already processed --->
74                                </cfcase>
75
76                                <cfdefaultcase>
77
78                                        <cfif listLen(attr,":") eq 2>
79                                                <!--- looks like a custom attribute: --->
80                                                <cfset ns = listFirst(attr,":") />
81                                                <cfif structKeyExists(arguments.lexicons,ns)>
82                                                        <cfset customAttribs[ns][listLast(attr,":")] = arguments.pluginXML.xmlAttributes[attr] />
83                                                <cfelse>
84                                                        <cfthrow type="fusebox.badGrammar.undeclaredNamespace"
85                                                                        message="Undeclared lexicon namespace"
86                                                                        detail="The lexicon prefix '#ns#' was found on a custom attribute in the '#getName()#' plugin declaration in fusebox.xml but no such lexicon namespace has been declared." />
87                                                </cfif>
88       
89                                        <cfelseif arguments.fbApp.strictMode>
90                                                <cfthrow type="fusebox.badGrammar.unexpectedAttributes"
91                                                                message="Unexpected attributes"
92                                                                detail="Unexpected attribute '#attr#' found in the '#getName()#' plugin declaration in fusebox.xml." />
93                                        </cfif>
94                                       
95                                </cfdefaultcase>
96
97                                </cfswitch>
98                        </cfloop>
99                       
100                        <cfset variables.template = arguments.pluginXML.xmlAttributes.template />
101                        <cfif len(variables.template) lt 4 or right(variables.template,4) is not ext>
102                                <cfset variables.template = variables.template & ext />
103                        </cfif>
104                        <cfif left(this.path,1) is "/">
105                                <cfset this.rootpath =
106                                                arguments.fbApp.relativePath(arguments.fbApp.expandFuseboxPath(this.path),arguments.fbApp.getApplicationRoot()) />
107                        <cfelse>
108                                <cfset this.rootpath =
109                                                arguments.fbApp.relativePath(arguments.fbApp.getApplicationRoot() &
110                                                                                                                this.path,arguments.fbApp.getApplicationRoot()) />
111                        </cfif>
112                       
113                        <cfset this.rootpath = arguments.fbApp.getCanonicalPath(this.rootpath) />
114                       
115                        <cfset variables.parameters = arguments.pluginXML.xmlChildren />
116                        <cfset variables.paramVerbs = structNew() />
117                        <cfloop from="1" to="#n#" index="i">
118                               
119                                <cfif not structKeyExists(variables.parameters[i].xmlAttributes,"name")>
120                                        <cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
121                                                        message="Required attribute is missing"
122                                                        detail="The attribute 'name' is required, for a 'parameter' to the '#getName()#' plugin declaration in fusebox.xml." />
123                                </cfif>
124
125                                <cfif not structKeyExists(variables.parameters[i].xmlAttributes,"value")>
126                                        <cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
127                                                        message="Required attribute is missing"
128                                                        detail="The attribute 'value' is required, for a 'parameter' to the '#getName()#' plugin declaration in fusebox.xml." />
129                                </cfif>
130
131                                <cfif arguments.fbApp.strictMode and structCount(variables.parameters[i].xmlAttributes) neq 2>
132                                        <cfthrow type="fusebox.badGrammar.unexpectedAttributes"
133                                                        message="Unexpected attributes"
134                                                        detail="Unexpected attributes were found in the '#variables.parameters[i].xmlAttributes.name#' parameter of the '#getName()#' plugin declaration in fusebox.xml." />
135                                </cfif>
136
137                                <cfset attr = structNew() />
138                                <cfset attr.name = "myFusebox.plugins.#getName()#.parameters." & variables.parameters[i].xmlAttributes.name />
139                                <cfset attr.value = variables.parameters[i].xmlAttributes.value />
140                                <cfset variables.paramVerbs[i] = factory.create("set",this,attr,verbChildren) />
141
142                        </cfloop>
143                <cfelse>
144                        <cfthrow type="fusebox.badGrammar.illegalDeclaration"
145                                        message="Illegal declaration"
146                                        detail="The XML entity '#arguments.pluginXML.xmlName#' was found where a plugin declaration was expected in fusebox.xml." />
147                </cfif>
148       
149                <cfreturn this />
150               
151        </cffunction>
152       
153        <cffunction name="compile" returntype="void" access="public" output="false"
154                                hint="I compile this plugin object.">
155                <cfargument name="writer" type="any" required="false"
156                                        hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." />
157               
158                <cfset var i = 0 />
159                <cfset var n = structCount(variables.paramVerbs) />
160                <cfset var file = "" />
161                <cfset var p = "" />
162               
163                <cfif request.__fusebox.SuppressPlugins>
164                        <cfreturn />
165                </cfif>
166                <cfswitch expression="#variables.phase#">
167                <cfcase value="processError,fuseactionException">
168                        <cfif left(this.path,1) is "/">
169                                <cffile action="read" file="#variables.fuseboxApplication.expandFuseboxPath(this.path)##variables.template#"
170                                                variable="file"
171                                                charset="#variables.fuseboxApplication.characterEncoding#" />
172                        <cfelse>
173                                <cffile action="read" file="#variables.fuseboxApplication.getApplicationRoot()##this.path##variables.template#"
174                                                variable="file"
175                                                charset="#variables.fuseboxApplication.characterEncoding#" />
176                        </cfif>
177                        <cfset arguments.writer.rawPrintln(file) />
178                </cfcase>
179                <cfdefaultcase>
180                        <cfloop from="1" to="#n#" index="i">
181                                <cfset variables.paramVerbs[i].compile(arguments.writer) />
182                        </cfloop>
183                        <cfset p = arguments.writer.setPhase(variables.phase) />
184                        <cfset arguments.writer.println('<cfset myFusebox.thisPlugin = "#getName()#"/>') />
185                        <cfset arguments.writer.print('<' & 'cfoutput><' & 'cfinclude template=') />
186                        <cfif left(this.path,1) is "/">
187                                <cfset arguments.writer.print('"#this.path##variables.template#"') />
188                        <cfelse>
189                                <cfset arguments.writer.print('"#variables.fuseboxApplication.parseRootPath##this.path##variables.template#"') />
190                        </cfif>
191                        <cfset arguments.writer.println('/><' & '/cfoutput>') />
192                        <cfset arguments.writer.setPhase(p) />
193                </cfdefaultcase>
194                </cfswitch>
195
196        </cffunction>
197       
198        <cffunction name="getName" returntype="string" access="public" output="false"
199                                hint="I return the name of the plugin.">
200               
201                <cfreturn variables.name />
202               
203        </cffunction>
204
205        <cffunction name="getCircuit" returntype="any" access="public" output="false"
206                                hint="I return the enclosing application object. This is an edge case to allow code that works with fuseactions to work with plugins too.">
207       
208                <cfreturn variables.fuseboxApplication />
209       
210        </cffunction>
211       
212        <cffunction name="getCustomAttributes" returntype="struct" access="public" output="false"
213                                hint="I return the custom (namespace-qualified) attributes for this plugin tag.">
214                <cfargument name="ns" type="string" required="true"
215                                        hint="I am the namespace prefix whose attributes should be returned." />
216               
217                <cfif structKeyExists(variables.customAttribs,arguments.ns)>
218                        <!--- we structCopy() this so folks can't poke values back into the metadata! --->
219                        <cfreturn structCopy(variables.customAttribs[arguments.ns]) />
220                <cfelse>
221                        <cfreturn structNew() />
222                </cfif>
223               
224        </cffunction>
225       
226</cfcomponent>
Note: See TracBrowser for help on using the browser.