- qpscanner/fusebox5/fuseboxDoFuseaction.cfc
- v0.7.3.2
- 16 KB
- 366
1<!---
2Copyright 2006-2007 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 am the representation of the do and fuseaction verbs.">
17
18 <cffunction name="init" returntype="any" access="public" output="false"
19 hint="I am the constructor.">
20 <cfargument name="action" type="any" required="true"
21 hint="I am the enclosing fuseaction object." />
22 <cfargument name="attributes" type="struct" required="true"
23 hint="I am the attributes for this verb." />
24 <cfargument name="children" type="any" required="true"
25 hint="I am the XML representation of any children this verb has." />
26 <cfargument name="verb" type="string" required="true"
27 hint="I am the name of this verb." />
28
29 <cfset var nAttrs = 1 />
30
31 <cfset variables.action = arguments.action />
32 <cfset variables.attributes = structNew() />
33 <cfset variables.children = arguments.children />
34 <cfset variables.numChildren = arrayLen(variables.children) />
35 <cfset variables.verb = arguments.verb />
36
37 <!---
38 validate the attributes:
39 action - required
40 append - boolean - optional
41 prepend - boolean - optional
42 overwrite - boolean - optional
43 contentvariable - optional
44 --->
45 <cfif structKeyExists(arguments.attributes,"action")>
46 <cfset variables.attributes.action = arguments.attributes.action />
47 <cfelse>
48 <cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
49 message="Required attribute is missing"
50 detail="The attribute 'action' is required, for a '#variables.verb#' verb in fuseaction #variables.action.getCircuit().getAlias()#.#variables.action.getName()#." />
51 </cfif>
52 <cfif variables.verb is "fuseaction" and listLen(variables.attributes.action,".") lt 2>
53 <!--- illegal: there is no circuit associated with a (global) action --->
54 <cfthrow type="fusebox.badGrammar.invalidAttributeValue"
55 message="Attribute has invalid value"
56 detail="The attribute 'action' must be a fully-qualified fuseaction, for a 'fuseaction' verb in a global pre/post process." />
57 </cfif>
58
59 <cfif structKeyExists(arguments.attributes,"append")>
60 <cfset variables.attributes.append = arguments.attributes.append />
61 <cfset nAttrs = nAttrs + 1 />
62 <cfif listFind("true,false,yes,no",variables.attributes.append) eq 0>
63 <cfthrow type="fusebox.badGrammar.invalidAttributeValue"
64 message="Attribute has invalid value"
65 detail="The attribute 'append' must either be ""true"" or ""false"", for a '#variables.verb#' verb in fuseaction #variables.action.getCircuit().getAlias()#.#variables.action.getName()#." />
66 </cfif>
67 <cfif not structKeyExists(arguments.attributes,"contentvariable")>
68 <cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
69 message="Required attribute is missing"
70 detail="The attribute 'contentvariable' is required when the attribute 'append' is present, for a '#variables.verb#' verb in fuseaction #variables.action.getCircuit().getAlias()#.#variables.action.getName()#." />
71 </cfif>
72 <cfelse>
73 <cfset variables.attributes.append = false />
74 </cfif>
75
76 <cfif structKeyExists(arguments.attributes,"prepend")>
77 <cfset variables.attributes.prepend = arguments.attributes.prepend />
78 <cfset nAttrs = nAttrs + 1 />
79 <cfif listFind("true,false,yes,no",variables.attributes.prepend) eq 0>
80 <cfthrow type="fusebox.badGrammar.invalidAttributeValue"
81 message="Attribute has invalid value"
82 detail="The attribute 'prepend' must either be ""true"" or ""false"", for a '#variables.verb#' verb in fuseaction #variables.action.getCircuit().getAlias()#.#variables.action.getName()#." />
83 </cfif>
84 <cfif not structKeyExists(arguments.attributes,"contentvariable")>
85 <cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
86 message="Required attribute is missing"
87 detail="The attribute 'contentvariable' is required when the attribute 'append' is present, for a '#variables.verb#' verb in fuseaction #variables.action.getCircuit().getAlias()#.#variables.action.getName()#." />
88 </cfif>
89 <cfelse>
90 <cfset variables.attributes.prepend = false />
91 </cfif>
92
93 <cfif structKeyExists(arguments.attributes,"overwrite")>
94 <cfset variables.attributes.overwrite = arguments.attributes.overwrite />
95 <cfset nAttrs = nAttrs + 1 />
96 <cfif listFind("true,false,yes,no",variables.attributes.overwrite) eq 0>
97 <cfthrow type="fusebox.badGrammar.invalidAttributeValue"
98 message="Attribute has invalid value"
99 detail="The attribute 'overwrite' must either be ""true"" or ""false"", for a '#variables.verb#' verb in fuseaction #variables.action.getCircuit().getAlias()#.#variables.action.getName()#." />
100 </cfif>
101 <cfif not structKeyExists(arguments.attributes,"contentvariable")>
102 <cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
103 message="Required attribute is missing"
104 detail="The attribute 'contentvariable' is required when the attribute 'append' is present, for a '#variables.verb#' verb in fuseaction #variables.action.getCircuit().getAlias()#.#variables.action.getName()#." />
105 </cfif>
106 <cfelse>
107 <cfset variables.attributes.overwrite = true />
108 </cfif>
109
110 <cfif structKeyExists(arguments.attributes,"contentvariable")>
111 <cfset variables.attributes.contentvariable = arguments.attributes.contentvariable />
112 <cfset nAttrs = nAttrs + 1 />
113 </cfif>
114
115 <cfif variables.action.getCircuit().getApplication().strictMode and structCount(arguments.attributes) neq nAttrs>
116 <cfthrow type="fusebox.badGrammar.unexpectedAttributes"
117 message="Unexpected attributes"
118 detail="Unexpected attributes were found in a '#variables.verb#' verb in fuseaction #variables.action.getCircuit().getAlias()#.#variables.action.getName()#." />
119 </cfif>
120
121 <cfreturn this />
122
123 </cffunction>
124
125 <cffunction name="compile" returntype="void" access="public" output="false"
126 hint="I compile this do/fuseaction verb.">
127 <cfargument name="writer" type="any" required="false"
128 hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." />
129
130 <cfset var i = 0 />
131 <cfset var n = 0 />
132 <cfset var app = variables.action.getCircuit().getApplication() />
133 <cfset var plugins = app.pluginPhases />
134 <cfset var c = "" />
135 <cfset var f = "" />
136 <cfset var cDotF = "" />
137 <cfset var old_c = "" />
138 <cfset var old_f = "" />
139 <cfset var circuits = app.circuits />
140 <cfset var needTryOnFuseaction = false />
141
142 <cfif listLen(variables.attributes.action,".") gte 2>
143 <!--- action is a circuit.fuseaction pair somewhere --->
144 <cfset f = listLast(variables.attributes.action,".") />
145 <cfset c = left(variables.attributes.action,len(variables.attributes.action)-len(f)-1) />
146 <cfset cDotF = variables.attributes.action />
147 <cfelse>
148 <cfset c = variables.action.getCircuit().getAlias() />
149 <cfset f = variables.attributes.action />
150 <cfset cDotF = c & "." & f />
151 </cfif>
152
153 <cfif structKeyExists(request.__fusebox.fuseactionsDone,cDotF)>
154 <cfthrow type="fusebox.badGrammar.recursiveDo"
155 message="Recursive do is illegal"
156 detail="An attempt was made to compile a fuseaction '#cDotF#' that is already being compiled, in fuseaction #variables.action.getCircuit().getAlias()#.#variables.action.getName()#." />
157 </cfif>
158 <cfset request.__fusebox.fuseactionsDone[cDotF] = true />
159
160 <cfset arguments.writer.rawPrintln('<!--- #variables.verb# action="#variables.attributes.action#" --->') />
161 <cfif app.debug>
162 <cfset arguments.writer.rawPrintln('<' & 'cfset myFusebox.trace("Runtime","<#variables.verb# action=""#variables.attributes.action#""/>") >') />
163 </cfif>
164 <cfset old_c = arguments.writer.setCircuit(c) />
165 <cfset old_f = arguments.writer.setFuseaction(f) />
166
167 <cfif structKeyExists(plugins,"fuseactionException") and
168 arrayLen(plugins["fuseactionException"]) gt 0 and
169 not request.__fusebox.SuppressPlugins>
170 <cfset needTryOnFuseaction = true />
171 <cfset arguments.writer.rawPrintln("<cftry>") />
172 </cfif>
173
174 <cfif structKeyExists(plugins,"preFuseaction")>
175 <cfset n = arrayLen(plugins["preFuseaction"]) />
176 <cfloop from="1" to="#n#" index="i">
177 <cfset plugins["preFuseaction"][i].compile(arguments.writer) />
178 </cfloop>
179 </cfif>
180
181 <cfif variables.numChildren gt 0>
182 <cfset enterStackFrame(arguments.writer) />
183 </cfif>
184
185 <cfif structKeyExists(variables.attributes,"contentvariable")>
186 <cfif not variables.attributes.overwrite>
187 <cfset arguments.writer.println('<cfif not isDefined("#variables.attributes.contentvariable#")>') />
188 </cfif>
189 <cfif variables.attributes.append or variables.attributes.prepend>
190 <cfset arguments.writer.println('<cfparam name="#variables.attributes.contentvariable#" default="">') />
191 </cfif>
192 <cfset arguments.writer.println('<cfsavecontent variable="#variables.attributes.contentvariable#">') />
193 <cfif variables.attributes.append>
194 <cfset arguments.writer.println('<' & 'cfoutput>###variables.attributes.contentvariable###</' & 'cfoutput>') />
195 </cfif>
196 </cfif>
197
198 <cfif listLen(variables.attributes.action,".") gte 2>
199
200 <cfif structKeyExists(circuits,c)>
201
202 <cfif structKeyExists(circuits[c].fuseactions,f)>
203
204 <!--- if not in the same circuit, check access is not private --->
205 <cfif c is not variables.action.getCircuit().getAlias()>
206
207 <cfif circuits[c].fuseactions[f].getAccess() is "private">
208
209 <cfthrow type="fusebox.invalidAccessModifier"
210 message="invalid access modifier"
211 detail="The fuseaction '#c#.#f#' has an access modifier of private and can only be called from within its own circuit. Use an access modifier of internal or public to make it available outside its immediate circuit.">
212
213 </cfif>
214
215 </cfif>
216
217 <!--- ticket 309 - remove fuseaction check prior to compile so that implicit circuits work --->
218
219 </cfif>
220
221 <cfelseif not variables.action.getCircuit().getApplication().allowImplicitCircuits>
222
223 <cfthrow type="fusebox.undefinedCircuit"
224 message="undefined Circuit"
225 detail="You specified a Circuit of #c# which is not defined." />
226
227 </cfif>
228
229 <cfset variables.action.getCircuit().getApplication().compile(arguments.writer,c,f) />
230
231 <cfelse>
232
233 <!--- action is a fuseaction in this same circuit --->
234 <cfif not structKeyExists(variables.action.getCircuit().fuseactions,f)>
235 <cfthrow type="fusebox.undefinedFuseaction"
236 message="undefined Fuseaction"
237 detail="You specified a Fuseaction of #f# which is not defined in Circuit #c#." />
238 </cfif>
239
240 <cfset variables.action.getCircuit().compile(arguments.writer,f) />
241
242 </cfif>
243
244 <cfif structKeyExists(variables.attributes,"contentvariable")>
245 <cfif variables.attributes.prepend>
246 <cfset arguments.writer.println('<' & 'cfoutput>###variables.attributes.contentvariable###</' & 'cfoutput>') />
247 </cfif>
248 <cfset arguments.writer.println('</cfsavecontent>') />
249 <cfif not variables.attributes.overwrite>
250 <cfset arguments.writer.println('</cfif>') />
251 </cfif>
252 </cfif>
253
254 <cfif variables.numChildren gt 0>
255 <cfset leaveStackFrame(arguments.writer) />
256 </cfif>
257
258 <cfif structKeyExists(plugins,"postFuseaction")>
259 <cfset n = arrayLen(plugins["postFuseaction"]) />
260 <cfloop from="1" to="#n#" index="i">
261 <cfset plugins["postFuseaction"][i].compile(arguments.writer) />
262 </cfloop>
263 </cfif>
264
265 <cfif needTryOnFuseaction>
266 <cfset n = arrayLen(plugins["fuseactionException"]) />
267 <cfloop from="1" to="#n#" index="i">
268 <cfset plugins["fuseactionException"][i].compile(arguments.writer) />
269 </cfloop>
270 <cfset arguments.writer.rawPrintln("</cftry>") />
271 </cfif>
272
273 <cfset arguments.writer.setFuseaction(old_f) />
274 <cfset arguments.writer.setCircuit(old_c) />
275
276 <cfset structDelete(request.__fusebox.fuseactionsDone,cDotF) />
277
278 </cffunction>
279
280 <cffunction name="enterStackFrame" returntype="void" access="private" output="false"
281 hint="I generate code to create a new stack frame and push the scoped variables.">
282 <cfargument name="writer" type="any" required="false"
283 hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." />
284
285 <cfset var i = 0 />
286 <cfset var child = 0 />
287 <cfset var match1 = 0 />
288 <cfset var match2 = 0 />
289 <cfset var nameLen = 0 />
290
291 <cfset arguments.writer.rawPrintln('<cfset myFusebox.enterStackFrame() >') />
292 <cfloop from="1" to="#variables.numChildren#" index="i">
293 <cfset child = variables.children[i] />
294 <!--- validate the child: it must be <parameter> and have both name= and value= --->
295 <cfif child.xmlName is "parameter">
296 <cfif not structKeyExists(child.xmlAttributes,"name")>
297 <cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
298 message="Required attribute is missing"
299 detail="The attribute 'name' is required, for a 'parameter' verb in fuseaction #variables.action.getCircuit().getAlias()#.#variables.action.getName()#." />
300 </cfif>
301 <cfset match1 = REFind("[A-Za-z0-9_]*",child.xmlAttributes.name,1,true) />
302 <cfset match2 = REFind("[A-Za-z0-9_]*\.[A-Za-z0-9_]*",child.xmlAttributes.name,1,true) />
303 <cfset nameLen = len(child.xmlAttributes.name) />
304 <cfif match1.pos[1] eq 1 and match1.len[1] eq nameLen>
305 <!--- simple varname: patch up XML to make leaveStackFrame() simpler --->
306 <cfset child.xmlAttributes.name = "variables." & child.xmlAttributes.name />
307 <cfelseif match2.pos[1] eq 1 and match2.len[1] eq nameLen>
308 <!--- scoped varname.varname: nothing to patch up --->
309 <cfelse>
310 <cfthrow type="fusebox.badGrammar.invalidAttributeValue"
311 message="Attribute has invalid value"
312 detail="The attribute 'name' must be a simple variable name, optionally qualified by a scope name, for a 'parameter' verb in fuseaction #variables.action.getCircuit().getAlias()#.#variables.action.getName()#." />
313 </cfif>
314 <cfset arguments.writer.rawPrintln('<' & 'cfif isDefined("#child.xmlAttributes.name#")><' &
315 'cfset myFusebox.stack["#child.xmlAttributes.name#"] = #child.xmlAttributes.name# ></' & 'cfif>') />
316 <cfif structKeyExists(child.xmlAttributes,"value")>
317 <cfset arguments.writer.rawPrintln('<' & 'cfset #child.xmlAttributes.name# = "#child.xmlAttributes.value#" >') />
318 </cfif>
319 <cfelse>
320 <cfthrow type="fusebox.badGrammar.illegalVerb"
321 message="Illegal verb encountered"
322 detail="The '#child.xmlName#' verb is illegal inside a 'do' verb, in fuseaction #variables.action.getCircuit().getAlias()#.#variables.action.getName()#." />
323 </cfif>
324 </cfloop>
325
326 </cffunction>
327
328 <cffunction name="leaveStackFrame" returntype="void" access="private" output="false"
329 hint="I generate code to pop the scoped variables and drop the stack frame.">
330 <cfargument name="writer" type="any" required="false"
331 hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." />
332
333 <cfset var i = 0 />
334 <cfset var child = 0 />
335 <cfset var scope = "" />
336 <cfset var qName = "" />
337
338 <cfloop from="#variables.numChildren#" to="1" step="-1" index="i">
339 <cfset child = variables.children[i] />
340 <cfset arguments.writer.rawPrintln('<' & 'cfif structKeyExists(myFusebox.stack,"#child.xmlAttributes.name#")><' &
341 'cfset #child.xmlAttributes.name# = myFusebox.stack["#child.xmlAttributes.name#"] ></' & 'cfif>') />
342 <cfset scope = listFirst(child.xmlAttributes.name,".") />
343 <cfset qName = listRest(child.xmlAttributes.name,".") />
344 <cfset arguments.writer.rawPrintln('<' & 'cfif structKeyExists(myFusebox.stack,"#child.xmlAttributes.name#")><' &
345 'cfset #child.xmlAttributes.name# = myFusebox.stack["#child.xmlAttributes.name#"] ><' &
346 'cfelse><' &
347 'cfset structDelete(#scope#,"#qName#")></' & 'cfif>') />
348 </cfloop>
349 <cfset arguments.writer.rawPrintln('<cfset myFusebox.leaveStackFrame() >') />
350
351 </cffunction>
352
353 <cffunction name="getNamespace" returntype="string" access="public" output="false"
354 hint="I return the namespace for this verb (which will be empty).">
355
356 <cfreturn "" />
357
358 </cffunction>
359
360 <cffunction name="getVerb" returntype="string" access="public" output="false">
361
362 <cfreturn variables.verb />
363
364 </cffunction>
365
366</cfcomponent>