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 --->
100101 <cfloop index="path" list="controller/,model/,view/">
102103 <cfset variables.originalPath = path />
104 <cfset variables.fullPath = variables.appPath & variables.originalPath />
105 <cfset variables.relativePath = variables.fuseboxApplication.relativePath(variables.appPath,variables.fullPath) />
106107 <!--- 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>
119120 <!--- first time through, access is public for controller - should change to internal for model / view circuits --->
121 <cfset this.access = "internal" />
122123 </cfloop>
124125 <cfif not found>
126 <!--- no CFCs so look for an MVC directory --->
127 <cfset this.access = "public" />
128129 <cfloop index="path" list="controller/,model/,view/">
130131 <cfset variables.originalPath = path & getAlias() & "/" />
132 <cfset variables.fullPath = variables.appPath & variables.originalPath />
133 <cfset variables.relativePath = variables.fuseboxApplication.relativePath(variables.appPath,variables.fullPath) />
134135 <!--- 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>
144145 <!--- first time through, access is public for controller - should change to internal for model / view circuits --->
146 <cfset this.access = "internal" />
147148 </cfloop>
149150 </cfif>
151152 <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) />
158159 <cfif directoryExists(variables.fullPath)>
160161 <!--- ok, the directory exists --->
162 <cfif variables.fuseboxApplication.debug>
163 <cfset arguments.myFusebox.trace("Compiler","Implicit circuit #getAlias()# identified") />
164 </cfif>
165166 <cfelse>
167168 <cfthrow type="fusebox.undefinedCircuit"
169 message="undefined Circuit"
170 detail="You specified a Circuit of #getAlias()# which is not defined." />
171172 </cfif>
173174 </cfif>
175176 <!--- 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() />
183184 </cffunction>
185186 <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." />
194195 <cfset var f = arguments.writer.setFuseaction(arguments.fuseaction) />
196197 <cfif arguments.fuseaction is "prefuseaction" or arguments.fuseaction is "postfuseaction">
198 <cfthrow type="fusebox.undefinedFuseaction"
199 message="undefined Fuseaction"
200 detail="You specified a Fuseaction of #arguments.fuseaction# which is uncallable in Circuit #getAlias()#." />
201 </cfif>
202203 <!--- prefuseaction is handled internally to the circuit mechanism --->
204205 <cfif not structKeyExists(this.fuseactions,arguments.fuseaction)>
206 <cfif variables.fuseactionIsMethod>
207 <cfset this.fuseactions[arguments.fuseaction] =
208 createObject("component","fuseboxControllerMethod")
209 .init(this,variables.dottedPath,arguments.fuseaction,true) />
210 <cfelse>
211 <!--- attempt to find the fuseaction as a file in the circuit directory --->
212 <cfif fileExists(variables.fullPath & arguments.fuseaction & ".xml")>
213 <!--- fuseaction.xml fragment --->
214 <cfthrow type="fusebox.undefinedFuseaction"
215 message="undefined Fuseaction"
216 detail="You specified a Fuseaction of #arguments.fuseaction# which is not defined in Circuit #getAlias()#." />
217 <cfelseif fileExists(variables.fullPath & arguments.fuseaction & ".cfc")>
218 <!--- fuseaction.cfc (call do() on this) --->
219 <cfset variables.dottedPath = getApplication().locateCfc(variables.fullPath & arguments.fuseaction & ".cfc") />
220 <cfif variables.dottedPath is not "">
221 <cfset this.fuseactions[arguments.fuseaction] =
222 createObject("component","fuseboxControllerMethod")
223 .init(this,variables.dottedPath,arguments.fuseaction,false) />
224 <cfelse>
225 <cfthrow type="fusebox.undefinedFuseaction"
226 message="undefined Fuseaction"
227 detail="You specified a Fuseaction of #arguments.fuseaction# which is not defined in Circuit #getAlias()#." />
228 </cfif>
229 <cfelseif fileExists(variables.fullPath & arguments.fuseaction & ".cfm")>
230 <!--- fuseaction.cfm (i.e., a fuse) --->
231 <cfset this.fuseactions[arguments.fuseaction] =
232 createObject("component","fuseboxImplicitFuseaction")
233 .init(this,arguments.fuseaction) />
234 <cfelse>
235 <cfthrow type="fusebox.undefinedFuseaction"
236 message="undefined Fuseaction"
237 detail="You specified a Fuseaction of #arguments.fuseaction# which is not defined in Circuit #getAlias()#." />
238 </cfif>
239 </cfif>
240 </cfif>
241242 <cfif arguments.topLevel>
243 <cfif this.access is not "public">
244 <cfthrow type="fusebox.invalidAccessModifier"
245 message="Invalid Access Modifier"
246 detail="You tried to access #getAlias()#.#arguments.fuseaction# which does not have access modifier of public. A Fuseaction which is to be accessed from anywhere outside the application (such as called via an URL, or a FORM, or as a web service) must have an access modifier of public or if unspecified at least inherit such a modifier from its circuit." />
247 </cfif>
248 </cfif>
249250 <cfset this.fuseactions[arguments.fuseaction].compile(arguments.writer) />
251252 <!--- postfuseaction is handled internally to the circuit mechanism --->
253254 <cfset arguments.writer.setFuseaction(f) />
255256 </cffunction>
257258 <cffunction name="compilePreOrPostFuseaction" returntype="void" access="public" output="false"
259 hint="I compile the pre/post-fuseaction for a circuit.">
260 <cfargument name="writer" type="any" required="false"
261 hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." />
262 <cfargument name="preOrPost" type="string" required="false"
263 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." />
264265 <!--- implicit circuits do not have pre/post fuseactions so this is a no-op --->
266267 </cffunction>
268269 <cffunction name="buildCircuitTrace" returntype="void" access="public" output="false"
270 hint="I build the 'circuit trace' structure - the array of parents. Required for Fusebox 4.1 compatibility.">
271272 <cfset this.circuitTrace = arrayNew(1) />
273 <cfset arrayAppend(this.circuitTrace,getAlias()) />
274275 </cffunction>
276277 <cffunction name="getOriginalPath" returntype="string" access="public" output="false"
278 hint="I return the original relative path specified in the circuit declaration.">
279280 <cfreturn variables.originalPath />
281282 </cffunction>
283284 <cffunction name="getCircuitRoot" returntype="string" access="public" output="false"
285 hint="I return the full file system path to the circuit directory.">
286287 <cfreturn variables.fullPath />
288289 </cffunction>
290291 <cffunction name="getCircuitXMLFilename" returntype="string" access="public" output="false"
292 hint="I return the actual name of the circuit XML file: circuit.xml or circuit.xml.cfm.">
293294 <!--- there is no XML file for an implicit circuit --->
295 <cfreturn "" />
296297 </cffunction>
298299 <cffunction name="getOriginalPathIsRelative" returntype="string" access="public" output="false"
300 hint="I return true if this circuit's declaration used a relative path.">
301302 <!--- original path is relative by definition --->
303 <cfreturn true />
304305 </cffunction>
306307 <cffunction name="getParentName" returntype="string" access="public" output="false"
308 hint="I return the name (alias) of this circuit's parent.">
309310 <cfreturn this.parent />
311312 </cffunction>
313314 <cffunction name="hasParent" returntype="boolean" access="public" output="false"
315 hint="I return true if this circuit has a parent, otherwise I return false.">
316317 <cfreturn getParentName() is not "" />
318319 </cffunction>
320321 <cffunction name="getParent" returntype="any" access="public" output="false"
322 hint="I return this circuit's parent circuit object. I throw an exception if hasParent() returns false.">
323324 <!---
325 note that this will throw an exception if the circuit has no parent
326 code should call hasParent() first
327 --->
328 <cfreturn variables.fuseboxApplication.circuits[getParentName()] />
329330 </cffunction>
331332 <cffunction name="getPermissions" returntype="string" access="public" output="false"
333 hint="I return the aggregated permissions for this circuit.">
334 <cfargument name="useCircuitTrace" type="boolean" default="false"
335 hint="I indicate whether or not to inherit the parent circuit's permissions if this circuit has no permissions specified." />
336337 <cfreturn this.permissions />
338339 </cffunction>
340341 <cffunction name="getRelativePath" returntype="string" access="public" output="false"
342 hint="I return the normalized relative path from the application root to this circuit's directory.">
343344 <cfreturn variables.relativePath />
345346 </cffunction>
347348 <cffunction name="getFuseactions" returntype="struct" access="public" output="false"
349 hint="I return the structure containing the definitions of the fuseactions within this circuit.">
350351 <cfreturn this.fuseactions />
352353 </cffunction>
354355 <cffunction name="getLexiconDefinition" returntype="any" access="public" output="false"
356 hint="I return the definition of the specified lexicon.">
357 <cfargument name="namespace" type="any" required="false"
358 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." />
359360 <cfif arguments.namespace is variables.fuseboxLexicon.namespace>
361 <cfreturn variables.fuseboxLexicon />
362 <!--- else we return nothing because this is an illegal call --->
363 </cfif>
364365 </cffunction>
366367 <cffunction name="getAccess" returntype="any" access="public" output="false"
368 hint="I return the access specified for this circuit.">
369370 <cfreturn this.access />
371372 </cffunction>
373374 <cffunction name="getAlias" returntype="any" access="public" output="false"
375 hint="I return the circuit alias.">
376377 <cfreturn variables.alias />
378379 </cffunction>
380381 <cffunction name="getApplication" returntype="any" access="public" output="false"
382 hint="I return the fusebox application object.">
383384 <cfreturn variables.fuseboxApplication />
385386 </cffunction>
387388 <cffunction name="getCustomAttributes" returntype="struct" access="public" output="false"
389 hint="I return any custom attributes for the specified namespace prefix.">
390 <cfargument name="ns" type="string" required="true"
391 hint="I am the namespace for which to return custom attributes." />
392393 <!--- implicit circuits have no custom attributes --->
394 <cfreturn structNew() />
395396 </cffunction>
397398</cfcomponent>