root / framework / tags / fusebox550 / fuseboxImplicitCircuit.cfc

Revision 545, 14.9 kB (checked in by scorfield, 1 year ago)

Fixes #253 and #254 by adding contentvariable= on dynamic do() and pre/postfuseaction() methods on controllers.
Also fixes a number of bugs around the behavior of dynamic do().
Updated the skeleton app to simplify things and make the power of the conventions more visible.

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 hint="I represent an implicit circuit." output="false">
17       
18        <cffunction name="init" returntype="any" access="public" output="false"
19                                hint="I am the constructor.">
20                <cfargument name="fbApp" type="fuseboxApplication" required="true"
21                                        hint="I am the fusebox application object." />
22                <cfargument name="alias" type="string" required="true"
23                                        hint="I am the circuit alias." />
24                <cfargument name="myFusebox" type="myFusebox" required="true"
25                                        hint="I am the myFusebox data structure." />
26
27                <cfset var traditionalCircuit = false />
28                <cfset var circuitPrefix = "" />
29                <cfset var circuitSearchPath =
30                                        "controller/#arguments.alias#,model/#arguments.alias#,view/#arguments.alias#," &
31                                        "#arguments.alias#/controller,#arguments.alias#/model,#arguments.alias#/view," &
32                                        "#arguments.alias#" />
33               
34                <cfset variables.fuseboxApplication = arguments.fbApp />
35                <cfset variables.alias = arguments.alias />
36               
37                <cfset variables.appPath = variables.fuseboxApplication.getApplicationRoot() />
38                <cfset variables.fuseboxLexicon = variables.fuseboxApplication.getFuseactionFactory().getBuiltinLexicon() />
39
40                <!--- ensure we don't reload this in the same request --->
41                <cfset request.__fusebox.CircuitsLoaded[variables.alias] = true />
42
43                <!---
44                        look for traditional circuit in MVC/alias or alias/MVC or just alias directories:
45                --->
46                <cfloop index="circuitPrefix" list="#circuitSearchPath#">
47                        <cfset traditionalCircuit =
48                                        fileExists(variables.appPath & circuitPrefix & "/circuit.xml.cfm") or
49                                        fileExists(variables.appPath & circuitPrefix & "/circuit.xml") />
50                        <cfif traditionalCircuit>
51                                <cfbreak />
52                        </cfif>
53                </cfloop>
54                <!---
55                        if we found a traditional circuit that simply wasn't declared,
56                        return a regular Fusebox 5.x style circuit object:
57                --->
58                <cfif traditionalCircuit>
59                        <cfif variables.fuseboxApplication.debug>
60                                <cfset arguments.myFusebox.trace("Compiler","Implicit #circuitPrefix#/circuit.xml(.cfm) identified") />
61                        </cfif>
62                        <cfreturn createObject("component","fuseboxCircuit")
63                                                .init(variables.fuseboxApplication,
64                                                                getAlias(),
65                                                                circuitPrefix,
66                                                                "",
67                                                                arguments.myFusebox,
68                                                                true) />
69                </cfif>
70
71                <!---
72                        now we're off into convention over configuration territory...
73                --->
74                <cfset reload(arguments.myFusebox) />
75                       
76                <cfreturn this />
77               
78        </cffunction>
79       
80        <cffunction name="reload" returntype="any" access="public" output="false"
81                                hint="I reload the circuit file and build the in-memory structures from it.">
82                <cfargument name="myFusebox" type="myFusebox" required="true"
83                                        hint="I am the myFusebox data structure." />
84
85                <cfset var found = false />
86                <cfset var path = "" />
87               
88                <cfset this.access = "public" />
89                <cfset variables.fuseactionIsMethod = false />
90               
91                <!---
92                        in order of preference, we want to find:
93                        1. {MVC}/{alias}.cfc
94                                - this implies fuseactions are methods
95                        2. {MVC}/{alias}/
96                                - we can look for {fuseaction}.xml or {fuseaction}.cfm later
97                        3. {alias}/
98                                - we can look for {fuseaction}.xml or {fuseaction}.cfm later
99                --->
100
101                <cfloop index="path" list="controller/,model/,view/">
102
103                        <cfset variables.originalPath = path />
104                        <cfset variables.fullPath = variables.appPath & variables.originalPath />
105                        <cfset variables.relativePath = variables.fuseboxApplication.relativePath(variables.appPath,variables.fullPath) />
106       
107                        <!--- if the CFC actually exists, see if we can figure out if it exists in a sensible place --->
108                        <cfif fileExists(variables.fullPath & getAlias() & ".cfc")>
109                                <cfset variables.dottedPath = variables.fuseboxApplication.locateCfc(variables.fullPath & getAlias() & ".cfc") />
110                                <cfif variables.dottedPath is not "">
111                                        <cfset found = true />
112                                        <cfset variables.fuseactionIsMethod = true />
113                                        <cfif variables.fuseboxApplication.debug>
114                                                <cfset arguments.myFusebox.trace("Compiler","Implicit component-as-circuit #variables.originalPath##getAlias()#.cfc identified") />
115                                        </cfif>
116                                        <cfbreak />
117                                </cfif>
118                        </cfif>
119
120                        <!--- first time through, access is public for controller - should change to internal for model / view circuits --->
121                        <cfset this.access = "internal" />
122                       
123                </cfloop>
124
125                <cfif not found>
126                        <!--- no CFCs so look for an MVC directory --->
127                        <cfset this.access = "public" />
128
129                        <cfloop index="path" list="controller/,model/,view/">
130       
131                                <cfset variables.originalPath = path & getAlias() & "/" />
132                                <cfset variables.fullPath = variables.appPath & variables.originalPath />
133                                <cfset variables.relativePath = variables.fuseboxApplication.relativePath(variables.appPath,variables.fullPath) />
134       
135                                <!--- MVC circuit directory? --->
136                                <cfif directoryExists(variables.fullPath)>
137                                        <!--- looks like we have a candidate --->
138                                        <cfset found = true />
139                                        <cfif variables.fuseboxApplication.debug>
140                                                <cfset arguments.myFusebox.trace("Compiler","Implicit circuit #variables.originalPath# identified") />
141                                        </cfif>
142                                        <cfbreak />
143                                </cfif>
144                               
145                                <!--- first time through, access is public for controller - should change to internal for model / view circuits --->
146                                <cfset this.access = "internal" />
147                               
148                        </cfloop>
149
150                </cfif>                                 
151               
152                <cfif not found>
153                        <!--- no MVC, what about just a directory? --->
154                        <cfset this.access = "public" />
155                        <cfset variables.originalPath = getAlias() & "/" />
156                        <cfset variables.fullPath = variables.appPath & variables.originalPath />
157                        <cfset variables.relativePath = variables.fuseboxApplication.relativePath(variables.appPath,variables.fullPath) />
158
159                        <cfif directoryExists(variables.fullPath)>
160
161                                <!--- ok, the directory exists --->
162                                <cfif variables.fuseboxApplication.debug>
163                                        <cfset arguments.myFusebox.trace("Compiler","Implicit circuit #getAlias()# identified") />
164                                </cfif>
165
166                        <cfelse>
167
168                                <cfthrow type="fusebox.undefinedCircuit"
169                                                message="undefined Circuit"
170                                                detail="You specified a Circuit of #getAlias()# which is not defined." />
171
172                        </cfif>
173
174                </cfif>
175               
176                <!--- TODO: we don't know what fuseactions an implicit circuit has --->
177                <cfset this.fuseactions = structNew() />
178                <cfset this.parent = "" />
179                <cfset this.permissions = "" />
180                <cfset this.path = variables.relativePath />
181                <cfset this.rootPath = variables.fuseboxApplication.relativePath(variables.fullPath,variables.appPath) />
182                <cfset this.timestamp = now() />
183
184        </cffunction>
185       
186        <cffunction name="compile" returntype="void" access="public" output="false"
187                                hint="I compile a given fuseaction within this circuit.">
188                <cfargument name="writer" type="any" required="false"
189                                        hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." />
190                <cfargument name="fuseaction" type="any" required="false"
191                                        hint="I am the name of the fuseaction to compile. I am required but it's faster to specify that I am not required." />
192                <cfargument name="topLevel" type="boolean" default="false"
193                                        hint="I specify whether or not this is a top-level (public) request." />
194
195                <cfset var f = arguments.writer.setFuseaction(arguments.fuseaction) />
196
197                <!--- prefuseaction is handled internally to the circuit mechanism --->
198
199                <!--- TODO: check accessibility --->           
200                <cfif not structKeyExists(this.fuseactions,arguments.fuseaction)>
201                        <cfif variables.fuseactionIsMethod>
202                                <cfset this.fuseactions[arguments.fuseaction] =
203                                                        createObject("component","fuseboxControllerMethod")
204                                                                .init(this,variables.dottedPath,arguments.fuseaction,true) />
205                        <cfelse>
206                                <!--- attempt to find the fuseaction as a file in the circuit directory --->
207                                <cfif fileExists(variables.fullPath & arguments.fuseaction & ".xml")>
208                                        <!--- fuseaction.xml fragment --->
209                                        <cfthrow type="fusebox.undefinedFuseaction"
210                                                        message="undefined Fuseaction"
211                                                        detail="You specified a Fuseaction of #arguments.fuseaction# which is not defined in Circuit #getAlias()#." />
212                                <cfelseif fileExists(variables.fullPath & arguments.fuseaction & ".cfc")>
213                                        <!--- fuseaction.cfc (call do() on this) --->
214                                        <cfset variables.dottedPath = getApplication().locateCfc(variables.fullPath & arguments.fuseaction & ".cfc") />
215                                        <cfif variables.dottedPath is not "">
216                                                <cfset this.fuseactions[arguments.fuseaction] =
217                                                                        createObject("component","fuseboxControllerMethod")
218                                                                                .init(this,variables.dottedPath,arguments.fuseaction,false) />
219                                        <cfelse>
220                                                <cfthrow type="fusebox.undefinedFuseaction"
221                                                                message="undefined Fuseaction"
222                                                                detail="You specified a Fuseaction of #arguments.fuseaction# which is not defined in Circuit #getAlias()#." />
223                                        </cfif>
224                                <cfelseif fileExists(variables.fullPath & arguments.fuseaction & ".cfm")>
225                                        <!--- fuseaction.cfm (i.e., a fuse) --->
226                                        <cfset this.fuseactions[arguments.fuseaction] =
227                                                                createObject("component","fuseboxImplicitFuseaction")
228                                                                        .init(this,arguments.fuseaction) />
229                                <cfelse>
230                                        <cfthrow type="fusebox.undefinedFuseaction"
231                                                        message="undefined Fuseaction"
232                                                        detail="You specified a Fuseaction of #arguments.fuseaction# which is not defined in Circuit #getAlias()#." />
233                                </cfif>
234                        </cfif>
235                </cfif>
236                <cfset this.fuseactions[arguments.fuseaction].compile(arguments.writer) />
237               
238                <!--- postfuseaction is handled internally to the circuit mechanism --->
239
240                <cfset arguments.writer.setFuseaction(f) />
241               
242        </cffunction>
243
244        <cffunction name="compilePreOrPostFuseaction" returntype="void" access="public" output="false"
245                                hint="I compile the pre/post-fuseaction for a circuit.">
246                <cfargument name="writer" type="any" required="false"
247                                        hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." />
248                <cfargument name="preOrPost" type="string" required="false"
249                                        hint="I am either 'pre' or 'post' to indicate whether this is a prefuseaction or a postfuseaction. I am required but it's faster to specify that I am not required." />
250
251                <!--- implicit circuits do not have pre/post fuseactions so this is a no-op --->
252
253        </cffunction>
254       
255        <cffunction name="buildCircuitTrace" returntype="void" access="public" output="false"
256                                hint="I build the 'circuit trace' structure - the array of parents. Required for Fusebox 4.1 compatibility.">
257
258                <cfset this.circuitTrace = arrayNew(1) />
259                <cfset arrayAppend(this.circuitTrace,getAlias()) />
260               
261        </cffunction>
262       
263        <cffunction name="getOriginalPath" returntype="string" access="public" output="false"
264                                hint="I return the original relative path specified in the circuit declaration.">
265               
266                <cfreturn variables.originalPath />
267               
268        </cffunction>
269       
270        <cffunction name="getCircuitRoot" returntype="string" access="public" output="false"
271                                hint="I return the full file system path to the circuit directory.">
272
273                <cfreturn variables.fullPath />
274               
275        </cffunction>
276       
277        <cffunction name="getCircuitXMLFilename" returntype="string" access="public" output="false"
278                                hint="I return the actual name of the circuit XML file: circuit.xml or circuit.xml.cfm.">
279               
280                <!--- there is no XML file for an implicit circuit --->
281                <cfreturn "" />
282               
283        </cffunction>
284       
285        <cffunction name="getOriginalPathIsRelative" returntype="string" access="public" output="false"
286                                hint="I return true if this circuit's declaration used a relative path.">
287               
288                <!--- original path is relative by definition --->
289                <cfreturn true />
290               
291        </cffunction>
292       
293        <cffunction name="getParentName" returntype="string" access="public" output="false"
294                                hint="I return the name (alias) of this circuit's parent.">
295       
296                <cfreturn this.parent />
297       
298        </cffunction>
299
300        <cffunction name="hasParent" returntype="boolean" access="public" output="false"
301                                hint="I return true if this circuit has a parent, otherwise I return false.">
302       
303                <cfreturn getParentName() is not "" />
304       
305        </cffunction>
306
307        <cffunction name="getParent" returntype="any" access="public" output="false"
308                                hint="I return this circuit's parent circuit object. I throw an exception if hasParent() returns false.">
309       
310                <!---
311                        note that this will throw an exception if the circuit has no parent
312                        code should call hasParent() first
313                --->
314                <cfreturn variables.fuseboxApplication.circuits[getParentName()] />
315       
316        </cffunction>
317
318        <cffunction name="getPermissions" returntype="string" access="public" output="false"
319                                hint="I return the aggregated permissions for this circuit.">
320                <cfargument name="useCircuitTrace" type="boolean" default="false"
321                                        hint="I indicate whether or not to inherit the parent circuit's permissions if this circuit has no permissions specified." />
322
323                <cfreturn this.permissions />
324                               
325        </cffunction>
326
327        <cffunction name="getRelativePath" returntype="string" access="public" output="false"
328                                hint="I return the normalized relative path from the application root to this circuit's directory.">
329       
330                <cfreturn variables.relativePath />
331       
332        </cffunction>
333
334        <cffunction name="getFuseactions" returntype="struct" access="public" output="false"
335                                hint="I return the structure containing the definitions of the fuseactions within this circuit.">
336               
337                <cfreturn this.fuseactions />
338               
339        </cffunction>
340
341        <cffunction name="getLexiconDefinition" returntype="any" access="public" output="false"
342                                hint="I return the definition of the specified lexicon.">
343                <cfargument name="namespace" type="any" required="false"
344                                        hint="I am the namespace whose lexicon is to be retrieved. I am required but it's faster to specify that I am not required." />
345               
346                <cfif arguments.namespace is variables.fuseboxLexicon.namespace>
347                        <cfreturn variables.fuseboxLexicon />
348                <!--- else we return nothing because this is an illegal call --->
349                </cfif>
350
351        </cffunction>
352
353        <cffunction name="getAccess" returntype="any" access="public" output="false"
354                                hint="I return the access specified for this circuit.">
355       
356                <cfreturn this.access />
357       
358        </cffunction>
359       
360        <cffunction name="getAlias" returntype="any" access="public" output="false"
361                                hint="I return the circuit alias.">
362       
363                <cfreturn variables.alias />
364       
365        </cffunction>
366
367        <cffunction name="getApplication" returntype="any" access="public" output="false"
368                                hint="I return the fusebox application object.">
369       
370                <cfreturn variables.fuseboxApplication />
371       
372        </cffunction>
373
374        <cffunction name="getCustomAttributes" returntype="struct" access="public" output="false"
375                                hint="I return any custom attributes for the specified namespace prefix.">
376                <cfargument name="ns" type="string" required="true"
377                                        hint="I am the namespace for which to return custom attributes." />
378               
379                <!--- implicit circuits have no custom attributes --->
380                <cfreturn structNew() />
381
382        </cffunction>
383
384</cfcomponent>
Note: See TracBrowser for help on using the browser.