root / framework / tags / fusebox550 / fuseboxDoFuseaction.cfc

Revision 531, 16.5 kB (checked in by scorfield, 1 year ago)

Fixes #251 by updating the copyright date in every file.

Line 
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","&lt;#variables.verb# action=""#variables.attributes.action#""/&gt;") >') />
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                                <cfelse>
218
219                                        <cfthrow type="fusebox.undefinedFuseaction"
220                                                        message="undefined Fuseaction"
221                                                        detail="You specified a Fuseaction of #f# which is not defined in Circuit #c#." />
222
223                                </cfif>
224
225                        <cfelseif not variables.action.getCircuit().getApplication().allowImplicitCircuits>
226
227                                <cfthrow type="fusebox.undefinedCircuit"
228                                                message="undefined Circuit"
229                                                detail="You specified a Circuit of #c# which is not defined." />
230
231                        </cfif>
232
233                        <cfset variables.action.getCircuit().getApplication().compile(arguments.writer,c,f) />
234
235                <cfelse>
236
237                        <!--- action is a fuseaction in this same circuit --->
238                        <cfif not structKeyExists(variables.action.getCircuit().fuseactions,f)>
239                                <cfthrow type="fusebox.undefinedFuseaction"
240                                                message="undefined Fuseaction"
241                                                detail="You specified a Fuseaction of #f# which is not defined in Circuit #c#." />
242                        </cfif>
243
244                        <cfset variables.action.getCircuit().compile(arguments.writer,f) />
245
246                </cfif>
247               
248                <cfif structKeyExists(variables.attributes,"contentvariable")>
249                        <cfif variables.attributes.prepend>
250                                <cfset arguments.writer.println('<' & 'cfoutput>###variables.attributes.contentvariable###</' & 'cfoutput>') />
251                        </cfif>
252                        <cfset arguments.writer.println('</cfsavecontent>') />
253                        <cfif not variables.attributes.overwrite>
254                                <cfset arguments.writer.println('</cfif>') />
255                        </cfif>
256                </cfif>
257
258                <cfif variables.numChildren gt 0>
259                        <cfset leaveStackFrame(arguments.writer) />
260                </cfif>
261               
262                <cfif structKeyExists(plugins,"postFuseaction")>
263                        <cfset n = arrayLen(plugins["postFuseaction"]) />
264                        <cfloop from="1" to="#n#" index="i">
265                                <cfset plugins["postFuseaction"][i].compile(arguments.writer) />
266                        </cfloop>
267                </cfif>
268
269                <cfif needTryOnFuseaction>
270                        <cfset n = arrayLen(plugins["fuseactionException"]) />
271                        <cfloop from="1" to="#n#" index="i">
272                                <cfset plugins["fuseactionException"][i].compile(arguments.writer) />
273                        </cfloop>
274                        <cfset arguments.writer.rawPrintln("</cftry>") />
275                </cfif>
276
277                <cfset arguments.writer.setFuseaction(old_f) />
278                <cfset arguments.writer.setCircuit(old_c) />
279
280                <cfset structDelete(request.__fusebox.fuseactionsDone,cDotF) />
281               
282        </cffunction>
283       
284        <cffunction name="enterStackFrame" returntype="void" access="private" output="false"
285                                hint="I generate code to create a new stack frame and push the scoped variables.">
286                <cfargument name="writer" type="any" required="false"
287                                        hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." />
288               
289                <cfset var i = 0 />
290                <cfset var child = 0 />
291                <cfset var match1 = 0 />
292                <cfset var match2 = 0 />
293                <cfset var nameLen = 0 />
294               
295                <cfset arguments.writer.rawPrintln('<cfset myFusebox.enterStackFrame() >') />
296                <cfloop from="1" to="#variables.numChildren#" index="i">
297                        <cfset child = variables.children[i] />
298                        <!--- validate the child: it must be <parameter> and have both name= and value= --->
299                        <cfif child.xmlName is "parameter">
300                                <cfif not structKeyExists(child.xmlAttributes,"name")>
301                                        <cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
302                                                        message="Required attribute is missing"
303                                                        detail="The attribute 'name' is required, for a 'parameter' verb in fuseaction #variables.action.getCircuit().getAlias()#.#variables.action.getName()#." />
304                                </cfif>
305                                <cfset match1 = REFind("[A-Za-z0-9_]*",child.xmlAttributes.name,1,true) />
306                                <cfset match2 = REFind("[A-Za-z0-9_]*\.[A-Za-z0-9_]*",child.xmlAttributes.name,1,true) />
307                                <cfset nameLen = len(child.xmlAttributes.name) />
308                                <cfif match1.pos[1] eq 1 and match1.len[1] eq nameLen>
309                                        <!--- simple varname: patch up XML to make leaveStackFrame() simpler --->
310                                        <cfset child.xmlAttributes.name = "variables." & child.xmlAttributes.name />
311                                <cfelseif match2.pos[1] eq 1 and match2.len[1] eq nameLen>
312                                        <!--- scoped varname.varname: nothing to patch up --->
313                                <cfelse>
314                                        <cfthrow type="fusebox.badGrammar.invalidAttributeValue"
315                                                        message="Attribute has invalid value"
316                                                        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()#." />
317                                </cfif>
318                                <cfset arguments.writer.rawPrintln('<' & 'cfif isDefined("#child.xmlAttributes.name#")><' &
319                                                        'cfset myFusebox.stack["#child.xmlAttributes.name#"] = #child.xmlAttributes.name# ></' & 'cfif>') />
320                                <cfif structKeyExists(child.xmlAttributes,"value")>
321                                        <cfset arguments.writer.rawPrintln('<' & 'cfset #child.xmlAttributes.name# = "#child.xmlAttributes.value#" >') />
322                                </cfif>
323                        <cfelse>
324                                <cfthrow type="fusebox.badGrammar.illegalVerb"
325                                                message="Illegal verb encountered"
326                                                detail="The '#child.xmlName#' verb is illegal inside a 'do' verb, in fuseaction #variables.action.getCircuit().getAlias()#.#variables.action.getName()#." />
327                        </cfif>
328                </cfloop>
329               
330        </cffunction>
331       
332        <cffunction name="leaveStackFrame" returntype="void" access="private" output="false"
333                                hint="I generate code to pop the scoped variables and drop the stack frame.">
334                <cfargument name="writer" type="any" required="false"
335                                        hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." />
336               
337                <cfset var i = 0 />
338                <cfset var child = 0 />
339                <cfset var scope = "" />
340                <cfset var qName = "" />
341               
342                <cfloop from="#variables.numChildren#" to="1" step="-1" index="i">
343                        <cfset child = variables.children[i] />
344                        <cfset arguments.writer.rawPrintln('<' & 'cfif structKeyExists(myFusebox.stack,"#child.xmlAttributes.name#")><' &
345                                                'cfset #child.xmlAttributes.name# = myFusebox.stack["#child.xmlAttributes.name#"] ></' & 'cfif>') />
346                        <cfset scope = listFirst(child.xmlAttributes.name,".") />
347                        <cfset qName = listRest(child.xmlAttributes.name,".") />
348                        <cfset arguments.writer.rawPrintln('<' & 'cfif structKeyExists(myFusebox.stack,"#child.xmlAttributes.name#")><' &
349                                                        'cfset #child.xmlAttributes.name# = myFusebox.stack["#child.xmlAttributes.name#"] ><' &
350                                                        'cfelse><' &
351                                                        'cfset structDelete(#scope#,"#qName#")></' & 'cfif>') />
352                </cfloop>
353                <cfset arguments.writer.rawPrintln('<cfset myFusebox.leaveStackFrame() >') />
354               
355        </cffunction>
356
357        <cffunction name="getNamespace" returntype="string" access="public" output="false"
358                                hint="I return the namespace for this verb (which will be empty).">
359
360                <cfreturn "" />
361
362        </cffunction>   
363       
364        <cffunction name="getVerb" returntype="string" access="public" output="false">
365
366                <cfreturn variables.verb />
367
368        </cffunction>
369       
370</cfcomponent>
Note: See TracBrowser for help on using the browser.