Browse files

Initial Commit

  • Loading branch information...
0 parents commit c71ac716b089dc607411656c31329568e85ff5c7 @russjohnson committed Jul 30, 2009
Showing with 8,148 additions and 0 deletions.
  1. +3 −0 .htaccess
  2. +3 −0 Application.cfc
  3. +3 −0 IsapiRewrite4.ini
  4. 0 README.textile
  5. +6 −0 config/design/settings.cfm
  6. +5 −0 config/development/settings.cfm
  7. +5 −0 config/environment.cfm
  8. +5 −0 config/maintenance/settings.cfm
  9. +5 −0 config/production/settings.cfm
  10. +5 −0 config/routes.cfm
  11. +14 −0 config/settings.cfm
  12. +5 −0 config/testing/settings.cfm
  13. +6 −0 controllers/Controller.cfc
  14. +17 −0 controllers/Wheels.cfc
  15. +1 −0 events/functions.cfm
  16. +1 −0 events/onapplicationend.cfm
  17. +1 −0 events/onapplicationstart.cfm
  18. +6 −0 events/onerror.cfm
  19. +6 −0 events/onmaintenance.cfm
  20. +6 −0 events/onmissingtemplate.cfm
  21. +1 −0 events/onrequestend.cfm
  22. +1 −0 events/onrequeststart.cfm
  23. +1 −0 events/onsessionend.cfm
  24. +1 −0 events/onsessionstart.cfm
  25. +1 −0 index.cfm
  26. +53 −0 index.html
  27. +6 −0 miscellaneous/Application.cfc
  28. +6 −0 models/Model.cfc
  29. BIN plugins/PluginManager-0.4.zip
  30. +77 −0 plugins/pluginmanager/PluginManager.cfc
  31. +14 −0 plugins/pluginmanager/index.cfm
  32. +1 −0 rewrite.cfm
  33. +1 −0 root.cfm
  34. +1 −0 views/helpers.cfm
  35. +6 −0 views/layout.cfm
  36. +14 −0 views/wheels/congratulations.cfm
  37. +134 −0 views/wheels/layout.cfm
  38. +1 −0 views/wheels/plugins.cfm
  39. +7 −0 wheels/Controller.cfc
  40. +5 −0 wheels/Dispatch.cfc
  41. +5 −0 wheels/Model.cfc
  42. +17 −0 wheels/controller/appfunctions.cfm
  43. +19 −0 wheels/controller/caching.cfm
  44. +49 −0 wheels/controller/filters.cfm
  45. +47 −0 wheels/controller/flash.cfm
  46. +7 −0 wheels/controller/functions.cfm
  47. +53 −0 wheels/controller/initialization.cfm
  48. +148 −0 wheels/controller/miscellaneous.cfm
  49. +32 −0 wheels/controller/redirection.cfm
  50. +263 −0 wheels/controller/rendering.cfm
  51. +1 −0 wheels/dispatch/functions.cfm
  52. +389 −0 wheels/dispatch/request.cfm
  53. +6 −0 wheels/events/onapplicationend.cfm
  54. +174 −0 wheels/events/onapplicationstart.cfm
  55. +19 −0 wheels/events/onapplicationstart/routes.cfm
  56. +155 −0 wheels/events/onapplicationstart/settings.cfm
  57. +63 −0 wheels/events/onerror.cfm
  58. +34 −0 wheels/events/onerror/cfmlerror.cfm
  59. +17 −0 wheels/events/onerror/wheelserror.cfm
  60. +14 −0 wheels/events/onmissingtemplate.cfm
  61. +6 −0 wheels/events/onrequest.cfm
  62. +21 −0 wheels/events/onrequestend.cfm
  63. +103 −0 wheels/events/onrequestend/debug.cfm
  64. +66 −0 wheels/events/onrequeststart.cfm
  65. +15 −0 wheels/events/onsessionend.cfm
  66. +11 −0 wheels/events/onsessionstart.cfm
  67. +29 −0 wheels/functions.cfm
  68. +11 −0 wheels/global/appfunctions.cfm
  69. +159 −0 wheels/global/cfml.cfm
  70. +4 −0 wheels/global/functions.cfm
  71. +469 −0 wheels/global/internal.cfm
  72. +331 −0 wheels/global/public.cfm
  73. +1 −0 wheels/index.cfm
  74. +177 −0 wheels/license.txt
  75. +11 −0 wheels/model/adapters/Base.cfc
  76. +4 −0 wheels/model/adapters/MicrosoftSQLServer.cfc
  77. +4 −0 wheels/model/adapters/MySQL.cfc
  78. +4 −0 wheels/model/adapters/Oracle.cfc
  79. +4 −0 wheels/model/adapters/PostgreSQL.cfc
  80. +107 −0 wheels/model/adapters/microsoftsqlserver/functions.cfm
  81. +73 −0 wheels/model/adapters/mysql/functions.cfm
  82. +74 −0 wheels/model/adapters/oracle/functions.cfm
  83. +71 −0 wheels/model/adapters/postgresql/functions.cfm
  84. +45 −0 wheels/model/associations.cfm
  85. +98 −0 wheels/model/calculations.cfm
  86. +165 −0 wheels/model/callbacks.cfm
  87. +1,208 −0 wheels/model/crud.cfm
  88. +74 −0 wheels/model/errors.cfm
  89. +8 −0 wheels/model/functions.cfm
  90. +128 −0 wheels/model/initialization.cfm
  91. +311 −0 wheels/model/miscellaneous.cfm
  92. +357 −0 wheels/model/validations.cfm
  93. +21 −0 wheels/plugins/injection.cfm
  94. +6 −0 wheels/styles/footer.cfm
  95. +127 −0 wheels/styles/header.cfm
  96. +12 −0 wheels/view/content.cfm
  97. +89 −0 wheels/view/dates.cfm
  98. +58 −0 wheels/view/errors.cfm
  99. +1,102 −0 wheels/view/forms.cfm
  100. +8 −0 wheels/view/functions.cfm
  101. +121 −0 wheels/view/media.cfm
  102. +122 −0 wheels/view/miscellaneous.cfm
  103. +134 −0 wheels/view/text.cfm
  104. +253 −0 wheels/view/urls.cfm
3 .htaccess
@@ -0,0 +1,3 @@
+RewriteEngine on
+RewriteCond %{REQUEST_URI} !^/(flex2gateway|jrunscripts|cfide|cfformgateway|railo-context|files|images|javascripts|miscellaneous|stylesheets|rewrite.cfm|index.cfm) [NC]
+RewriteRule ^(.*)$ /rewrite.cfm/$1
3 Application.cfc
@@ -0,0 +1,3 @@
+<cfcomponent output="false">
+ <cfinclude template="wheels/functions.cfm">
+</cfcomponent>
3 IsapiRewrite4.ini
@@ -0,0 +1,3 @@
+RewriteRule ^(/(flex2gateway|jrunscripts|cfide|cfformgateway|railo-context|files|images|javascripts|miscellaneous|stylesheets).*)$ $1 [L,I]
+RewriteRule ^(/.+/.+/.*\?.+\..*)$ /rewrite.cfm/$1
+RewriteRule ^(/[^.]*)$ /rewrite.cfm/$1
0 README.textile
No changes.
6 config/design/settings.cfm
@@ -0,0 +1,6 @@
+<!---
+ This file is used to configure specific settings for the "design" environment.
+ A variable set in this file will override the one in "config/settings.cfm".
+ Example: <cfset set(dataSourceName="devDB")>
+--->
+
5 config/development/settings.cfm
@@ -0,0 +1,5 @@
+<!---
+ This file is used to configure specific settings for the "development" environment.
+ A variable set in this file will override the one in "config/settings.cfm".
+ Example: <cfset set(dataSourceName="devDB")>
+--->
5 config/environment.cfm
@@ -0,0 +1,5 @@
+<!---
+ The environment setting can be set to "design", "development", "testing", "maintenance" or "production".
+ For example, set it to "design" or "development" when you are building your application and to "production" when it's running live.
+--->
+<cfset set(environment="design")>
5 config/maintenance/settings.cfm
@@ -0,0 +1,5 @@
+<!---
+ This file is used to configure specific settings for the "maintenance" environment.
+ A variable set in this file will override the one in "config/settings.cfm".
+ Example: <cfset set(ipExceptions="an.ip.num.ber")>
+--->
5 config/production/settings.cfm
@@ -0,0 +1,5 @@
+<!---
+ This file is used to configure specific settings for the "production" environment.
+ A variable set in this file will override the one in "config/settings.cfm".
+ Example: <cfset set(errorEmailAddress="someone@somewhere.com")>
+--->
5 config/routes.cfm
@@ -0,0 +1,5 @@
+<!---
+ Here you can add routes to your application and edit the default one.
+ The default route is the one that will be called on your application's "home" page.
+--->
+<cfset addRoute(name="home", pattern="", controller="wheels", action="congratulations")>
14 config/settings.cfm
@@ -0,0 +1,14 @@
+<!---
+ If you leave these settings commented out, Wheels will set the data source name to the same name as the folder the application resides in.
+ <cfset set(dataSourceName="")>
+ <cfset set(dataSourceUserName="")>
+ <cfset set(dataSourcePassword="")>
+--->
+
+<!---
+ If you leave this setting commented out, Wheels will try to determine the URL rewrite capabilities automatically.
+ The URLRewriting setting can bet set to "On", "Partial" or "Off".
+ To run with "Partial" rewriting, the "cgi.path_info" variable needs to be supported by the web server.
+ To run with rewriting "On", you need to apply the necessary rewrite rules on the web server first.
+ <cfset set(URLRewriting="Partial")>
+--->
5 config/testing/settings.cfm
@@ -0,0 +1,5 @@
+<!---
+ This file is used to configure specific settings for the "testing" environment.
+ A variable set in this file will override the one in "config/settings.cfm".
+ Example: <cfset set(cacheQueries=false)>
+--->
6 controllers/Controller.cfc
@@ -0,0 +1,6 @@
+<!---
+ This is the parent controller file that all your controllers should extend.
+ Do not delete this file.
+--->
+<cfcomponent extends="wheels.Controller">
+</cfcomponent>
17 controllers/Wheels.cfc
@@ -0,0 +1,17 @@
+<!---
+ This is a controller file that Wheels uses internally.
+ Do not delete this file.
+--->
+<cfcomponent extends="Controller">
+
+ <cffunction name="congratulations">
+ <cfset version = application.wheels.version>
+ </cffunction>
+
+ <cffunction name="plugins">
+ <cfif get("environment") IS "production">
+ <cfset renderNothing()>
+ </cfif>
+ </cffunction>
+
+</cfcomponent>
1 events/functions.cfm
@@ -0,0 +1 @@
+<!--- Place functions here that should be globally available in your application. --->
1 events/onapplicationend.cfm
@@ -0,0 +1 @@
+<!--- Place code here that should be executed on the "onApplicationEnd" event. --->
1 events/onapplicationstart.cfm
@@ -0,0 +1 @@
+<!--- Place code here that should be executed on the "onApplicationStart" event. --->
6 events/onerror.cfm
@@ -0,0 +1,6 @@
+<!--- Place HTML here that should be displayed when an error is encountered while running in "production" mode. --->
+<h1>Error!</h1>
+<p>
+ Sorry, that caused an unexpected error.<br />
+ Please try again later.
+</p>
6 events/onmaintenance.cfm
@@ -0,0 +1,6 @@
+<!--- Place HTML here that should be displayed when the application is running in "maintenance" mode. --->
+<h1>Maintenance!</h1>
+<p>
+ Sorry, maintenance work is being performed.<br />
+ Please try again later.
+</p>
6 events/onmissingtemplate.cfm
@@ -0,0 +1,6 @@
+<!--- Place HTML here that should be displayed when a file is not found while running in "production" mode. --->
+<h1>File Not Found!</h1>
+<p>
+ Sorry, the page you requested could not be found.<br />
+ Please verify the address.
+</p>
1 events/onrequestend.cfm
@@ -0,0 +1 @@
+<!--- Place code here that should be executed on the "onRequestEnd" event. --->
1 events/onrequeststart.cfm
@@ -0,0 +1 @@
+<!--- Place code here that should be executed on the "onRequestStart" event. --->
1 events/onsessionend.cfm
@@ -0,0 +1 @@
+<!--- Place code here that should be executed on the "onSessionEnd" event. --->
1 events/onsessionstart.cfm
@@ -0,0 +1 @@
+<!--- Place code here that should be executed on the "onSessionStart" event. --->
1 index.cfm
@@ -0,0 +1 @@
+<cfinclude template="wheels/index.cfm">
53 index.html
@@ -0,0 +1,53 @@
+<html>
+<head>
+<title>Welcome to chronos.dev</title>
+<style type="text/css">
+ body, div, td { font-family: "Lucida Grande"; font-size: 12px; color: #666666; }
+ b { color: #333333; }
+ .indent { margin-left: 10px; }
+</style>
+</head>
+<body link="#993300" vlink="#771100" alink="#ff6600">
+
+<table border="0" width="100%" height="95%"><tr><td align="center" valign="middle">
+<div style="width: 500px; background-color: #eeeeee; border: 1px dotted #cccccc; padding: 20px; padding-top: 15px;">
+ <div align="center" style="font-size: 14px; font-weight: bold;">
+ Congratulations!
+ </div>
+
+ <div align="left">
+ <p>If you are reading this in your web browser, then the only logical conclusion is that the <b><a href="http://chronos.dev/">http://chronos.dev/</a></b> virtualhost was setup correctly. :)</p>
+
+ <p>You can find the configuration file for this virtual host in:<br>
+ <table class="indent" border="0" cellspacing="3">
+ <tr>
+ <td><img src="/icons/script.gif" width="20" height="22" border="0"></td>
+ <td><b>/private/etc/apache2/virtualhosts/chronos.dev</b></td>
+ </tr>
+ </table>
+ </p>
+
+ <p>You will need to place all of your website files in:<br>
+ <table class="indent" border="0" cellspacing="3">
+ <tr>
+ <td><img src="/icons/dir.gif" width="20" height="22" border="0"></td>
+ <td><b><a href="file:///Library/WebServer/Documents/chronos">/Library/WebServer/Documents/chronos</b></a></td>
+ </tr>
+ </table>
+ </p>
+
+ <p>For the latest version of this script, tips, comments, <span style="font-size: 10px; color: #999999;">donations,</span> etc. visit:<br>
+ <table class="indent" border="0" cellspacing="3">
+ <tr>
+ <td><img src="/icons/forward.gif" width="20" height="22" border="0"></td>
+ <td><b><a href="http://patrickg.com/virtualhost">http://patrickg.com/virtualhost</a></b></td>
+ </tr>
+ </table>
+ </p>
+ </div>
+
+</div>
+</td></tr></table>
+
+</body>
+</html>
6 miscellaneous/Application.cfc
@@ -0,0 +1,6 @@
+<!---
+ You can place ".cfm" files in this folder and run them independently from Wheels.
+ This empty "Application.cfc" file makes sure that Wheels does not interfer with the request.
+--->
+<cfcomponent>
+</cfcomponent>
6 models/Model.cfc
@@ -0,0 +1,6 @@
+<!---
+ This is the parent model file that all your models should extend.
+ Do not delete this file.
+--->
+<cfcomponent extends="wheels.Model">
+</cfcomponent>
BIN plugins/PluginManager-0.4.zip
Binary file not shown.
77 plugins/pluginmanager/PluginManager.cfc
@@ -0,0 +1,77 @@
+<cfcomponent output="false">
+
+ <cffunction name="init">
+ <cfreturn this>
+ </cffunction>
+
+ <cffunction name="$installPlugin" returntype="void">
+ <cfargument name="pluginFile" type="string" required="true">
+ <cfset var loc = StructNew()>
+ <cfset loc.pluginURL = "http://cfwheels.googlecode.com/files/" & arguments.pluginFile & ".zip">
+ <cfhttp url="#loc.pluginURL#" result="loc.fileData" method="GET" getAsBinary="yes">
+ <cfset loc.pluginFile = loc.fileData.FileContent>
+ <cfset loc.pluginDirectory = "plugins/">
+ <cffile action="write" file="#ExpandPath(loc.pluginDirectory)&arguments.pluginFile#.zip" output="#loc.pluginFile#" mode="777">
+ <cflocation url="?reload=true" addToken="false">
+ </cffunction>
+
+ <cffunction name="$getAvailablePlugins" returntype="array">
+ <cfset var loc = StructNew()>
+
+ <!--- store all plugins in an array --->
+ <cfset loc.plugins = ArrayNew(1)>
+
+ <!--- get html that lists all files with label "plugin" on google code --->
+ <cfhttp url="http://code.google.com/p/cfwheels/downloads/list?can=2&q=label:plugin&colspec=Filename%20Summary%20Uploaded%20Size%20DownloadCount" result="loc.file"></cfhttp>
+ <cfset loc.content = loc.file.FileContent>
+
+ <!--- remove some chars for easier parsing --->
+ <cfset loc.content = Replace(loc.content, Chr(10), "", "all")>
+ <cfset loc.content = Replace(loc.content, Chr(13), "", "all")>
+ <cfset loc.content = Replace(loc.content, Chr(9), "", "all")>
+ <cfset loc.content = Replace(loc.content, " ", " ", "all")>
+
+ <!--- count the number of plugins available so we know how long to loop for --->
+ <cfset loc.startStr = "http://cfwheels.googlecode.com/files/">
+ <cfset loc.endStr = """">
+ <cfset loc.pluginCount = ArrayLen(REMatchNoCase(loc.startStr, loc.content))>
+
+ <cfset loc.pos = 1>
+ <cfloop from="1" to="#loc.pluginCount#" index="loc.i">
+
+ <!--- parse out plugin name and version from the .zip file name --->
+ <cfset loc.startStr = "http://cfwheels.googlecode.com/files/">
+ <cfset loc.startPos = FindNoCase(loc.startStr, loc.content, loc.pos)>
+ <cfset loc.endPos = FindNoCase(loc.endStr, loc.content, loc.startPos)>
+ <cfset loc.str = Mid(loc.content, loc.startPos, loc.endPos-loc.startPos)>
+ <cfset loc.name = SpanExcluding(Replace(loc.str, loc.startStr, ""), "-")>
+ <cfset loc.version = Replace(Replace(Replace(Replace(loc.str, ".zip", ""), "-", ""), loc.name, ""), loc.startStr, "")>
+
+ <!--- parse out description --->
+ <cfset loc.startStr = ".zip&amp;can=2&amp;q=label%3Aplugin"">">
+ <cfset loc.startPos = FindNoCase(loc.startStr, loc.content, loc.pos)>
+ <cfset loc.endPos = FindNoCase("</a>", loc.content, loc.startPos)>
+ <cfset loc.description = Trim(Replace(Mid(loc.content, loc.startPos, loc.endPos-loc.startPos), loc.startStr, ""))>
+
+ <!--- parse out if it's compatible from the label --->
+ <cfset loc.startStr = "</a><a onclick=""cancelBubble=true;"" class=""label"" href=""list?q=label:">
+ <cfset loc.startPos = FindNoCase(loc.startStr, loc.content, loc.pos)>
+ <cfset loc.endPos = FindNoCase(""" >", loc.content, loc.startPos)>
+ <cfset loc.compatible = Replace(Mid(loc.content, loc.startPos, loc.endPos-loc.startPos), loc.startStr, "")>
+
+ <cfset loc.pos = loc.endPos>
+
+ <cfif SpanExcluding(application.wheels.version, " ") GTE loc.compatible>
+ <!--- add plugin info to array if it's compatible with the installed wheels version --->
+ <cfset loc.plugin = StructNew()>
+ <cfset loc.plugin.name = loc.name>
+ <cfset loc.plugin.version = loc.version>
+ <cfset loc.plugin.description = loc.description>
+ <cfset ArrayAppend(loc.plugins, loc.plugin)>
+ </cfif>
+
+ </cfloop>
+ <cfreturn loc.plugins>
+ </cffunction>
+
+</cfcomponent>
14 plugins/pluginmanager/index.cfm
@@ -0,0 +1,14 @@
+<cfif StructKeyExists(URL, "plugin")>
+ <cfset $installPlugin(URL.plugin)>
+</cfif>
+
+<h1>Plugin Manager</h1>
+<p>With the Plugin Manager you can download and install all authorized plugins available for the version of Wheels you have installed. Click on the installation links for any of the plugins listed below and the Plugin Manager will download the desired plugin and reload the application for you, no extra steps are needed.</p>
+
+<cfoutput>
+ <cfloop array="#$getAvailablePlugins()#" index="plugin">
+ <h2>#plugin.name# (#plugin.version#<cfif Left(plugin.version, 1) IS 0> beta</cfif>)</h2>
+ <p>#plugin.description#</p>
+ <ul><li><strong><cfif ListFindNoCase(pluginNames(), plugin.name)><span style="color:green;">This plugin is installed.</span><cfelse><a href="#cgi.script_name#?#cgi.query_string#&plugin=#plugin.name#-#plugin.version#">Download and install</a></cfif></strong></li></ul>
+ </cfloop>
+</cfoutput>
1 rewrite.cfm
@@ -0,0 +1 @@
+<cfinclude template="wheels/index.cfm">
1 root.cfm
@@ -0,0 +1 @@
+<cfinvoke attributeCollection="#arguments#">
1 views/helpers.cfm
@@ -0,0 +1 @@
+<!--- Place helper functions here that should be available for use in all view pages of your application --->
6 views/layout.cfm
@@ -0,0 +1,6 @@
+<!--- Place HTML here that should be used as the default layout of your application --->
+<html>
+ <body>
+ <cfoutput>#contentForLayout()#</cfoutput>
+ </body>
+</html>
14 views/wheels/congratulations.cfm
@@ -0,0 +1,14 @@
+<h1>Congratulations!</h1>
+<p><strong>You have successfully installed version <cfoutput>#version#</cfoutput> of Wheels.</strong><br />
+Welcome to the wonderful world of Wheels, we hope you will enjoy it!</p>
+
+<h2>Now What?</h2>
+<p>Now that you have a working installation of Wheels you may be wondering what to do next. Here are some suggestions...</p>
+<ul>
+<li><a href="http://cfwheels.org/docs/chapter/hello-world">View and code along with our "Hello World" tutorial.</a></li>
+<li><a href="http://cfwheels.org/docs">Have a look at the rest of our documentation.</a></li>
+<li><a href="http://groups.google.com/group/cfwheels">Say "Hello!" to everyone in the Google Group.</a></li>
+<li>Build the next killer website on the World Wide Web...</li>
+</ul>
+
+<p><strong>Good Luck!</strong></p>
134 views/wheels/layout.cfm
@@ -0,0 +1,134 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+ <title>ColdFusion on Wheels</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <style>
+ *
+ {
+ padding: 0;
+ margin: 0;
+ }
+
+ body
+ {
+ text-align: center;
+ font-family: "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
+ line-height: 1.5em;
+ font-size: 14px;
+ color: #333;
+ background: #ddd;
+ }
+
+ #wrapper
+ {
+ margin: auto;
+ text-align: left;
+ width: 698px;
+ background: #fff;
+ border-left: 3px solid #999;
+ border-right: 3px solid #999;
+ border-bottom: 3px solid #999;
+ }
+
+ #content
+ {
+ background: #fff;
+ padding: 15px;
+ }
+
+ #footer p
+ {
+ font-family: Arial;
+ font-size: 10px;
+ }
+
+ h1
+ {
+ font-size: 24px;
+ font-weight: bold;
+ color: #902c2c;
+ margin: 10px 0 5px 0;
+ }
+
+ h2
+ {
+ font-size: 16px;
+ font-weight: bold;
+ color: #902c2c;
+ }
+
+ p
+ {
+ margin-bottom: 15px;
+ }
+
+ p.small
+ {
+ font-size: 11px;
+ }
+
+ #content a
+ {
+ color: #922c2c;
+ text-decoration: underline;
+ padding: 1px;
+ }
+
+ #content a:hover
+ {
+ color: #fff;
+ background: #922c2c;
+ text-decoration: none;
+ }
+
+ #content ul
+ {
+ margin: 10px 0 15px 25px;
+ }
+
+ #content ul li
+ {
+ padding-bottom: 0;
+ }
+
+ img
+ {
+ border: none;
+ }
+
+ pre
+ {
+ border: 1px solid #a6a2a2;
+ overflow-x: auto;
+ width: 646px;
+ padding: 15px;
+ margin-bottom: 15px;
+ background: #ffffe0;
+ }
+
+ code
+ {
+ color: #000;
+ font-family: Courier;
+ }
+
+ tt
+ {
+ font-size: 12px;
+ color: #666;
+ }
+ </style>
+</head>
+<body>
+
+<div id="wrapper">
+<div id="content">
+<cfoutput>#contentForLayout()#</cfoutput>
+</div>
+</div>
+<div id="footer">
+</div>
+</body>
+</html>
1 views/wheels/plugins.cfm
@@ -0,0 +1 @@
+<cfinclude template="../../plugins/#params.name#/index.cfm">
7 wheels/Controller.cfc
@@ -0,0 +1,7 @@
+<cfcomponent output="false">
+ <cfinclude template="global/functions.cfm">
+ <cfinclude template="controller/functions.cfm">
+ <cfinclude template="view/functions.cfm">
+ <cfinclude template="plugins/injection.cfm">
+ <cfinclude template="../#application.wheels.viewPath#/helpers.cfm">
+</cfcomponent>
5 wheels/Dispatch.cfc
@@ -0,0 +1,5 @@
+<cfcomponent output="false">
+ <cfinclude template="global/functions.cfm">
+ <cfinclude template="dispatch/functions.cfm">
+ <cfinclude template="plugins/injection.cfm">
+</cfcomponent>
5 wheels/Model.cfc
@@ -0,0 +1,5 @@
+<cfcomponent output="false">
+ <cfinclude template="global/functions.cfm">
+ <cfinclude template="model/functions.cfm">
+ <cfinclude template="plugins/injection.cfm">
+</cfcomponent>
17 wheels/controller/appfunctions.cfm
@@ -0,0 +1,17 @@
+<cfif StructKeyExists(server, "railo")>
+ <cfinclude template="initialization.cfm">
+ <cfinclude template="filters.cfm">
+ <cfinclude template="flash.cfm">
+ <cfinclude template="caching.cfm">
+ <cfinclude template="rendering.cfm">
+ <cfinclude template="redirection.cfm">
+ <cfinclude template="miscellaneous.cfm">
+<cfelse>
+ <cfinclude template="wheels/controller/initialization.cfm">
+ <cfinclude template="wheels/controller/filters.cfm">
+ <cfinclude template="wheels/controller/flash.cfm">
+ <cfinclude template="wheels/controller/caching.cfm">
+ <cfinclude template="wheels/controller/rendering.cfm">
+ <cfinclude template="wheels/controller/redirection.cfm">
+ <cfinclude template="wheels/controller/miscellaneous.cfm">
+</cfif>
19 wheels/controller/caching.cfm
@@ -0,0 +1,19 @@
+<cffunction name="caches" returntype="void" access="public" output="false" hint="Tells Wheels to cache one or more actions.">
+ <cfargument name="action" type="string" required="false" default="#arguments.actions#" hint="Action(s) to cache">
+ <cfargument name="actions" type="string" required="false" default="#arguments.action#" hint="See `action`">
+ <cfargument name="time" type="numeric" required="false" default="#application.wheels.caches.time#" hint="Minutes to cache the action(s) for">
+ <cfscript>
+ var loc = {};
+ loc.iEnd = ListLen(arguments.actions);
+ for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
+ {
+ loc.item = Trim(ListGetAt(arguments.actions, loc.i));
+ loc.thisAction = {action=loc.item, time=arguments.time};
+ ArrayAppend(variables.wheels.cachableActions, loc.thisAction);
+ }
+ </cfscript>
+</cffunction>
+
+<cffunction name="$getCachableActions" returntype="array" access="public" output="false">
+ <cfreturn variables.wheels.cachableActions>
+</cffunction>
49 wheels/controller/filters.cfm
@@ -0,0 +1,49 @@
+<cffunction name="filters" returntype="void" access="public" output="false" hint="Tells Wheels to run a function before an action is run or after an action has been run. You can also specify multiple functions and actions.">
+ <cfargument name="through" type="string" required="true" hint="Function(s) to execute before or after the action(s)">
+ <cfargument name="type" type="string" required="false" default="before" hint="Whether to run the function(s) before or after the action(s)">
+ <cfargument name="only" type="string" required="false" default="" hint="Pass in a list of action names (or one action name) to tell Wheels that the filter function(s) should only be run on these actions">
+ <cfargument name="except" type="string" required="false" default="" hint="Pass in a list of action names (or one action name) to tell Wheels that the filter function(s) should be run on all actions except the specified ones">
+ <cfscript>
+ var loc = {};
+ loc.iEnd = ListLen(arguments.through);
+ for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
+ {
+ loc.item = Trim(ListGetAt(arguments.through, loc.i));
+ loc.thisFilter = {};
+ loc.thisFilter.through = loc.item;
+ loc.thisFilter.only = Replace(arguments.only, ", ", ",", "all");
+ loc.thisFilter.except = Replace(arguments.except, ", ", ",", "all");
+ if (arguments.type == "before")
+ ArrayAppend(variables.wheels.beforeFilters, loc.thisFilter);
+ else
+ ArrayAppend(variables.wheels.afterFilters, loc.thisFilter);
+ }
+ </cfscript>
+</cffunction>
+
+<cffunction name="verifies" returntype="void" access="public" output="false" hint="Tells Wheels to verify that some specific criterias are met before running an action.">
+ <cfargument name="only" type="string" required="false" default="" hint="Pass in a list of action names (or one action name) to tell Wheels that the verifications should only be run on these actions">
+ <cfargument name="except" type="string" required="false" default="" hint="Pass in a list of action names (or one action name) to tell Wheels that the filter function(s) should be run on all actions except the specified ones">
+ <cfargument name="post" type="any" required="false" default="" hint="Set to true to verify that this is a post request">
+ <cfargument name="get" type="any" required="false" default="" hint="Set to true to verify that this is a get request">
+ <cfargument name="ajax" type="any" required="false" default="" hint="Set to true to verify that this is an AJAX request">
+ <cfargument name="cookie" type="string" required="false" default="" hint="Verify that the passed in variable name exists in the cookie">
+ <cfargument name="session" type="string" required="false" default="" hint="Verify that the passed in variable name exists in the session">
+ <cfargument name="params" type="string" required="false" default="" hint="Verify that the passed in variable name exists in the params">
+ <cfargument name="handler" type="string" required="false" default="#application.wheels.verifies.handler#" hint="Pass in the name of a function that should handle failed verifications (default is to just abort the request when a verification fails)">
+ <cfscript>
+ ArrayAppend(variables.wheels.verifications, Duplicate(arguments));
+ </cfscript>
+</cffunction>
+
+<cffunction name="$getBeforeFilters" returntype="array" access="public" output="false">
+ <cfreturn variables.wheels.beforeFilters>
+</cffunction>
+
+<cffunction name="$getAfterFilters" returntype="array" access="public" output="false">
+ <cfreturn variables.wheels.afterFilters>
+</cffunction>
+
+<cffunction name="$getVerifications" returntype="array" access="public" output="false">
+ <cfreturn variables.wheels.verifications>
+</cffunction>
47 wheels/controller/flash.cfm
@@ -0,0 +1,47 @@
+<cffunction name="flash" returntype="any" access="public" output="false" hint="Gets the value of a specific key in the Flash (or the entire flash as a struct if no key is passed in).">
+ <cfargument name="key" type="string" required="false" default="" hint="The key to get the value for">
+ <cfscript>
+ var returnValue = "";
+ if (Len(arguments.key))
+ {
+ if (flashKeyExists(arguments.key))
+ returnValue = session.flash[arguments.key];
+ }
+ else
+ {
+ if (!flashIsEmpty())
+ returnValue = session.flash;
+ }
+ </cfscript>
+ <cfreturn returnValue>
+</cffunction>
+
+<cffunction name="flashClear" returntype="void" access="public" output="false" hint="Deletes everything from the Flash.">
+ <cfscript>
+ session.flash = {};
+ </cfscript>
+</cffunction>
+
+<cffunction name="flashCount" returntype="numeric" access="public" output="false" hint="Checks how many keys exist in the Flash.">
+ <cfreturn StructCount(session.flash)>
+</cffunction>
+
+<cffunction name="flashDelete" returntype="boolean" access="public" output="false" hint="Deletes a specific key from the Flash.">
+ <cfargument name="key" type="string" required="true" hint="The key to delete">
+ <cfreturn StructDelete(session.flash, arguments.key, true)>
+</cffunction>
+
+<cffunction name="flashInsert" returntype="void" access="public" output="false" hint="Inserts a new key/value to the Flash.">
+ <cfscript>
+ session.flash[StructKeyList(arguments)] = arguments[1];
+ </cfscript>
+</cffunction>
+
+<cffunction name="flashIsEmpty" returntype="boolean" access="public" output="false" hint="Checks if the Flash is empty.">
+ <cfreturn NOT flashCount()>
+</cffunction>
+
+<cffunction name="flashKeyExists" returntype="boolean" access="public" output="false" hint="Checks if a specific key exists in the Flash.">
+ <cfargument name="key" type="string" required="true" hint="The key to check if it exists">
+ <cfreturn StructKeyExists(session.flash, arguments.key)>
+</cffunction>
7 wheels/controller/functions.cfm
@@ -0,0 +1,7 @@
+<cfinclude template="initialization.cfm">
+<cfinclude template="filters.cfm">
+<cfinclude template="flash.cfm">
+<cfinclude template="caching.cfm">
+<cfinclude template="rendering.cfm">
+<cfinclude template="redirection.cfm">
+<cfinclude template="miscellaneous.cfm">
53 wheels/controller/initialization.cfm
@@ -0,0 +1,53 @@
+<cffunction name="$initControllerClass" returntype="any" access="public" output="false">
+ <cfargument name="name" type="string" required="true">
+ <cfscript>
+ variables.wheels.name = arguments.name;
+ variables.wheels.verifications = [];
+ variables.wheels.beforeFilters = [];
+ variables.wheels.afterFilters = [];
+ variables.wheels.cachableActions = [];
+ if (StructKeyExists(variables, "init"))
+ init();
+ </cfscript>
+ <cfreturn this>
+</cffunction>
+
+<cffunction name="$createControllerObject" returntype="any" access="public" output="false">
+ <cfargument name="params" type="struct" required="true">
+ <cfscript>
+ var loc = {};
+ loc.fileName = capitalize(variables.wheels.name);
+ if (!ListFindNoCase(application.wheels.existingControllerFiles, variables.wheels.name))
+ loc.fileName = "Controller";
+ loc.returnValue = $createObjectFromRoot(path=application.wheels.controllerComponentPath, fileName=loc.fileName, method="$initControllerObject", name=variables.wheels.name, params=arguments.params);
+ </cfscript>
+ <cfreturn loc.returnValue>
+</cffunction>
+
+<cffunction name="$setControllerClassData" returntype="void" access="public" output="false">
+ <cfscript>
+ variables.wheels = application.wheels.controllers[arguments.name].$getControllerClassData();
+ </cfscript>
+</cffunction>
+
+<cffunction name="$initControllerObject" returntype="any" access="public" output="false">
+ <cfargument name="name" type="string" required="true">
+ <cfargument name="params" type="struct" required="true">
+ <cfscript>
+ var loc = {};
+
+ // include controller specific helper files if they exist
+ if (ListFindNoCase(application.wheels.existingHelperFiles, arguments.params.controller))
+ $include(template="#application.wheels.viewPath#/#arguments.params.controller#/helpers.cfm");
+
+ loc.executeArgs = {};
+ loc.executeArgs.name = arguments.name;
+ $simpleLock(name="controllerLock", type="readonly", execute="$setControllerClassData", executeArgs=loc.executeArgs);
+ variables.params = arguments.params;
+ </cfscript>
+ <cfreturn this>
+</cffunction>
+
+<cffunction name="$getControllerClassData" returntype="struct" access="public" output="false">
+ <cfreturn variables.wheels>
+</cffunction>
148 wheels/controller/miscellaneous.cfm
@@ -0,0 +1,148 @@
+<cffunction name="isGet" returntype="boolean" access="public" output="false" hint="Returns whether the request was a normal (GET) request or not.">
+ <cfscript>
+ var returnValue = "";
+ if (cgi.request_method == "get")
+ returnValue = true;
+ else
+ returnValue = false;
+ </cfscript>
+ <cfreturn returnValue>
+</cffunction>
+
+<cffunction name="isPost" returntype="boolean" access="public" output="false" hint="Returns whether the request came from a form submission or not.">
+ <cfscript>
+ var returnValue = "";
+ if (cgi.request_method == "post")
+ returnValue = true;
+ else
+ returnValue = false;
+ </cfscript>
+ <cfreturn returnValue>
+</cffunction>
+
+<cffunction name="isAjax" returntype="boolean" access="public" output="false" hint="Returns whether the page was called from JavaScript or not.">
+ <cfscript>
+ var returnValue = "";
+ if (cgi.http_x_requested_with == "XMLHTTPRequest")
+ returnValue = true;
+ else
+ returnValue = false;
+ </cfscript>
+ <cfreturn returnValue>
+</cffunction>
+
+<cffunction name="sendEmail" returntype="void" access="public" output="false" hint="Sends an email using a template and an optional layout to wrap it in.">
+ <cfargument name="template" type="string" required="false" default="#arguments.templates#" hint="The path to the email template or two paths if you want to send a multipart email (if the `detectMultipart` argument is `false` the template for the text version should be the first one in the list).">
+ <cfargument name="templates" type="string" required="false" default="#arguments.template#" hint="See `template`">
+ <cfargument name="from" type="string" required="true" hint="Email address to send from">
+ <cfargument name="to" type="string" required="true" hint="Email address to send to">
+ <cfargument name="subject" type="string" required="true" hint="The subject line of the email">
+ <cfargument name="layout" type="any" required="false" default="#application.wheels.sendEmail.layout#" hint="Layout to wrap body in">
+ <cfargument name="detectMultipart" type="boolean" required="false" default="#application.wheels.sendEmail.detectMultipart#" hint="When set to `true` Wheels will detect which of the templates is text and which one is html (by counting the `<` characters)">
+ <cfscript>
+ var loc = {};
+
+ arguments = $insertDefaults(name="sendEmail", input=arguments);
+
+ // set the variables that should be available to the email view template
+ for (loc.key in arguments)
+ {
+ if (!ListFindNoCase("template,templates,layout,detectMultipart", loc.key) && !ListFindNoCase("from,to,bcc,cc,charset,debug,failto,group,groupcasesensitive,mailerid,maxrows,mimeattach,password,port,priority,query,replyto,server,spoolenable,startrow,subject,timeout,type,username,useSSL,useTLS,wraptext", loc.key))
+ {
+ variables[loc.key] = arguments[loc.key];
+ StructDelete(arguments, loc.key);
+ }
+ }
+
+ arguments.body = [];
+ loc.iEnd = ListLen(arguments.templates);
+ for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
+ {
+ // include the email template and return it
+ loc.content = $renderPage($template=ListGetAt(arguments.templates, loc.i), $layout=arguments.layout);
+ if (ArrayIsEmpty(arguments.body))
+ {
+ ArrayAppend(arguments.body, loc.content);
+ }
+ else
+ {
+ if (arguments.detectMultipart)
+ {
+ // make sure the text version is the first one in the array
+ loc.existingContentCount = ListLen(arguments.body[1], "<");
+ loc.newContentCount = ListLen(loc.content, "<");
+ if (loc.newContentCount < loc.existingContentCount)
+ ArrayPrepend(arguments.body, loc.content);
+ else
+ ArrayAppend(arguments.body, loc.content);
+ }
+ else
+ {
+ ArrayAppend(arguments.body, loc.content);
+ }
+ }
+ }
+
+ // delete arguments that we don't need to pass on to cfmail and send the email
+ StructDelete(arguments, "template");
+ StructDelete(arguments, "templates");
+ StructDelete(arguments, "layout");
+ StructDelete(arguments, "detectMultipart");
+ $mail(argumentCollection=arguments);
+ </cfscript>
+</cffunction>
+
+<cffunction name="sendFile" returntype="void" access="public" output="false" hint="Sends a file to the user.">
+ <cfargument name="file" type="string" required="true" hint="The file to send to the user">
+ <cfargument name="name" type="string" required="false" default="" hint="The file name to show in the browser download dialog box">
+ <cfargument name="type" type="string" required="false" default="" hint="The HTTP content type to deliver the file as">
+ <cfargument name="disposition" type="string" required="false" default="#application.wheels.sendFile.disposition#" hint="Set to 'inline' to have the browser handle the opening of the file or set to 'attachment' to force a download dialog box">
+ <cfscript>
+ var loc = {};
+ arguments.file = Replace(arguments.file, "\", "/", "all");
+ loc.path = Reverse(ListRest(Reverse(arguments.file), "/"));
+ loc.folder = application.wheels.filePath;
+ if (Len(loc.path))
+ {
+ loc.folder = loc.folder & "/" & loc.path;
+ loc.file = Replace(arguments.file, loc.path, "");
+ loc.file = Right(loc.file, Len(loc.file)-1);
+ }
+ else
+ {
+ loc.file = arguments.file;
+ }
+ loc.folder = ExpandPath(loc.folder);
+ if (!FileExists(loc.folder & "/" & loc.file))
+ {
+ loc.match = $directory(action="list", directory=loc.folder, filter="#loc.file#.*");
+ if (loc.match.recordCount)
+ loc.file = loc.file & "." & ListLast(loc.match.name, ".");
+ else
+ $throw(type="Wheels.FileNotFound", message="File Not Found", extendedInfo="Make sure a file with the name '#loc.file#' exists in the '#loc.folder#' folder.");
+ }
+ loc.fullPath = loc.folder & "/" & loc.file;
+ if (Len(arguments.name))
+ loc.name = arguments.name;
+ else
+ loc.name = loc.file;
+ loc.extension = ListLast(loc.file, ".");
+ switch(loc.extension)
+ {
+ case "txt": {loc.type = "text/plain"; break;}
+ case "gif": {loc.type = "image/gif"; break;}
+ case "jpg": case "jpeg": case "pjpeg": {loc.type = "image/jpg"; break;}
+ case "png": {loc.type = "image/png"; break;}
+ case "wav": {loc.type = "audio/wav"; break;}
+ case "mp3": {loc.type = "audio/mpeg3"; break;}
+ case "pdf": {loc.type = "application/pdf"; break;}
+ case "zip": {loc.type = "application/zip"; break;}
+ case "ppt": case "pptx": {loc.type = "application/powerpoint"; break;}
+ case "doc": case "docx": {loc.type = "application/word"; break;}
+ case "xls": case "xlsx": {loc.type = "application/excel"; break;}
+ default: {loc.type = "application/octet-stream"; break;}
+ }
+ $header(name="content-disposition", value="#arguments.disposition#; filename=""#loc.name#""");
+ $content(type=loc.type, file=loc.fullPath);
+ </cfscript>
+</cffunction>
32 wheels/controller/redirection.cfm
@@ -0,0 +1,32 @@
+<cffunction name="redirectTo" returntype="void" access="public" output="false" hint="Redirects the browser to the supplied controller/action/key, route or back to the referring page. Internally It uses the URLFor function to build the link and the cflocation tag to perform the redirect.">
+ <cfargument name="back" type="boolean" required="false" default="false" hint="Set to true to redirect back to the referring page">
+ <cfargument name="addToken" type="boolean" required="false" default="#application.wheels.redirectTo.addToken#" hint="See documentation for cflocation">
+ <cfargument name="statusCode" type="numeric" required="false" default="#application.wheels.redirectTo.statusCode#" hint="See documentation for cflocation">
+ <cfargument name="route" type="string" required="false" default="" hint="See documentation for URLFor">
+ <cfargument name="controller" type="string" required="false" default="" hint="See documentation for URLFor">
+ <cfargument name="action" type="string" required="false" default="" hint="See documentation for URLFor">
+ <cfargument name="key" type="any" required="false" default="" hint="See documentation for URLFor">
+ <cfargument name="params" type="string" required="false" default="" hint="See documentation for URLFor">
+ <cfargument name="anchor" type="string" required="false" default="" hint="See documentation for URLFor">
+ <cfargument name="onlyPath" type="boolean" required="false" default="#application.wheels.redirectTo.onlyPath#" hint="See documentation for URLFor">
+ <cfargument name="host" type="string" required="false" default="#application.wheels.redirectTo.host#" hint="See documentation for URLFor">
+ <cfargument name="protocol" type="string" required="false" default="#application.wheels.redirectTo.protocol#" hint="See documentation for URLFor">
+ <cfargument name="port" type="numeric" required="false" default="#application.wheels.redirectTo.port#" hint="See documentation for URLFor">
+ <cfscript>
+ var loc = {};
+ if (arguments.back)
+ {
+ if (!Len(cgi.http_referer))
+ $throw(type="Wheels.RedirectBackError", message="Can't redirect back to the referring URL because it is blank.", extendedInfo="Catch this error in your code to handle it gracefully.");
+ else if (cgi.http_referer Does Not Contain cgi.server_name)
+ $throw(type="Wheels.RedirectBackError", message="Can't redirect back to the referring URL because it is not on the same domain.", extendedInfo="Catch this error in your code to handle it gracefully.");
+ else
+ loc.url = cgi.http_referer;
+ }
+ else
+ {
+ loc.url = URLFor(argumentCollection=arguments);
+ }
+ $location(url=loc.url, addToken=arguments.addToken, statusCode=arguments.statusCode);
+ </cfscript>
+</cffunction>
263 wheels/controller/rendering.cfm
@@ -0,0 +1,263 @@
+<cffunction name="renderPageToString" returntype="string" access="public" output="false" hint="Includes the view page for the specified controller and action and returns it as a string.">
+ <cfargument name="controller" type="string" required="false" default="#variables.params.controller#" hint="See documentation for renderPage">
+ <cfargument name="action" type="string" required="false" default="#variables.params.action#" hint="See documentation for renderPage">
+ <cfargument name="template" type="string" required="false" default="" hint="See documentation for renderPage">
+ <cfargument name="layout" type="any" required="false" default="#application.wheels.renderPageToString.layout#" hint="See documentation for renderPage">
+ <cfargument name="cache" type="any" required="false" default="" hint="See documentation for renderPage">
+ <cfargument name="$showDebugInformation" type="any" required="false" default="#application.wheels.showDebugInformation#">
+ <cfscript>
+ var returnValue = "";
+ renderPage(argumentCollection=arguments);
+ returnValue = request.wheels.response;
+ StructDelete(request.wheels, "response");
+ </cfscript>
+ <cfreturn returnValue>
+</cffunction>
+
+<cffunction name="renderPage" returntype="void" access="public" output="false" hint="Renders content to the browser by including the view page for the specified controller and action.">
+ <cfargument name="controller" type="string" required="false" default="#variables.params.controller#" hint="Controller to include the view page for">
+ <cfargument name="action" type="string" required="false" default="#variables.params.action#" hint="Action to include the view page for">
+ <cfargument name="template" type="string" required="false" default="" hint="A specific template to render">
+ <cfargument name="layout" type="any" required="false" default="#application.wheels.renderPage.layout#" hint="The layout to wrap the content in">
+ <cfargument name="cache" type="any" required="false" default="" hint="Minutes to cache the content for">
+ <cfargument name="$showDebugInformation" type="any" required="false" default="#application.wheels.showDebugInformation#">
+ <cfscript>
+ var loc = {};
+ arguments = $dollarify(arguments, "controller,action,template,layout,cache");
+ if (application.wheels.showDebugInformation)
+ $debugPoint("view");
+ // if renderPage was called with a layout set a flag to indicate that it's ok to show debug info at the end of the request
+ if ((!IsBoolean(arguments.$layout) || arguments.$layout) && arguments.$showDebugInformation)
+ request.wheels.showDebugInformation = true;
+ if (application.wheels.cachePages && (IsNumeric(arguments.$cache) || (IsBoolean(arguments.$cache) && arguments.$cache)))
+ {
+ loc.category = "action";
+ loc.key = "#arguments.$action##$hashStruct(variables.params)##$hashStruct(arguments)#";
+ loc.lockName = loc.category & loc.key;
+ loc.conditionArgs = {};
+ loc.conditionArgs.category = loc.category;
+ loc.conditionArgs.key = loc.key;
+ loc.executeArgs = arguments;
+ loc.executeArgs.category = loc.category;
+ loc.executeArgs.key = loc.key;
+ loc.page = $doubleCheckedLock(name=loc.lockName, condition="$getFromCache", execute="$renderPageAndAddToCache", conditionArgs=loc.conditionArgs, executeArgs=loc.executeArgs);
+ }
+ else
+ {
+ loc.page = $renderPage(argumentCollection=arguments);
+ }
+ if (application.wheels.showDebugInformation)
+ $debugPoint("view");
+
+ // we put the response in the request scope here so that the developer does not have to specifically return anything from the controller code
+ request.wheels.response = loc.page;
+ </cfscript>
+</cffunction>
+
+<cffunction name="renderNothing" returntype="void" access="public" output="false" hint="Renders a blank string to the browser. This is very similar to calling 'cfabort' with the advantage that any after filters you have set on the action will still be run.">
+ <cfscript>
+ request.wheels.response = "";
+ </cfscript>
+</cffunction>
+
+<cffunction name="renderText" returntype="void" access="public" output="false" hint="Renders the specified text to the browser.">
+ <cfargument name="text" type="any" required="true" hint="The text to be rendered">
+ <cfscript>
+ request.wheels.response = arguments.text;
+ </cfscript>
+</cffunction>
+
+<cffunction name="renderPartial" returntype="void" access="public" output="false" hint="Renders content to the browser by including a partial.">
+ <cfargument name="name" type="string" required="true" hint="The name of the file to be used (starting with an optional path and with the underscore and file extension excluded)">
+ <cfargument name="cache" type="any" required="false" default="" hint="See documentation for `renderPage`">
+ <cfargument name="layout" type="string" required="false" default="#application.wheels.renderPartial.layout#" hint="See documentation for `renderPage`">
+ <cfargument name="$partialType" type="string" required="false" default="render">
+ <cfscript>
+ $includeOrRenderPartial(argumentCollection=$dollarify(arguments, "name,cache,layout"));
+ </cfscript>
+</cffunction>
+
+<cffunction name="$renderPageAndAddToCache" returntype="string" access="public" output="false">
+ <cfscript>
+ var returnValue = "";
+ returnValue = $renderPage(argumentCollection=arguments);
+ if (!IsNumeric(arguments.$cache))
+ arguments.$cache = application.wheels.defaultCacheTime;
+ $addToCache(key=arguments.key, value=returnValue, time=arguments.$cache, category=arguments.category);
+ </cfscript>
+ <cfreturn returnValue>
+</cffunction>
+
+<cffunction name="$renderPage" returntype="string" access="public" output="false">
+ <cfscript>
+ var loc = {};
+ if (!Len(arguments.$template))
+ arguments.$template = "/" & arguments.$controller & "/" & arguments.$action;
+ loc.content = $includeFile($name=arguments.$template, $type="page");
+ loc.returnValue = $renderLayout($content=loc.content, $layout=arguments.$layout);
+ </cfscript>
+ <cfreturn loc.returnValue>
+</cffunction>
+
+<cffunction name="$renderPartialAndAddToCache" returntype="string" access="public" output="false">
+ <cfscript>
+ var returnValue = "";
+ returnValue = $renderPartial(argumentCollection=arguments);
+ if (!IsNumeric(arguments.$cache))
+ arguments.$cache = application.wheels.defaultCacheTime;
+ $addToCache(key=arguments.key, value=returnValue, time=arguments.$cache, category=arguments.category);
+ </cfscript>
+ <cfreturn returnValue>
+</cffunction>
+
+<cffunction name="$renderPartial" returntype="string" access="public" output="false">
+ <cfscript>
+ var loc = {};
+ if (IsQuery(arguments.$name))
+ {
+ loc.name = request.wheels[Hash(GetMetaData(arguments.$name).toString())];
+ arguments[loc.name] = arguments.$name;
+ arguments.$name = singularize(loc.name);
+ }
+ else if (IsObject(arguments.$name))
+ {
+ loc.name = arguments.$name.$classData().name;
+ arguments[loc.name] = arguments.$name;
+ arguments.$name = loc.name;
+ }
+ if (Len(arguments.$layout))
+ arguments.$layout = Replace("_" & arguments.$layout, "__", "_", "one");
+ arguments.$type = "partial";
+ loc.content = $includeFile(argumentCollection=arguments);
+ loc.returnValue = $renderLayout($content=loc.content, $layout=arguments.$layout);
+ </cfscript>
+ <cfreturn loc.returnValue>
+</cffunction>
+
+<cffunction name="$includeOrRenderPartial" returntype="string" access="public" output="false">
+ <cfscript>
+ var loc = {};
+ loc.returnValue = "";
+ if (application.wheels.cachePartials && (isNumeric(arguments.$cache) || (IsBoolean(arguments.$cache) && arguments.$cache)))
+ {
+ loc.category = "partial";
+ loc.key = "#arguments.$name##$hashStruct(variables.params)##$hashStruct(arguments)#";
+ loc.lockName = loc.category & loc.key;
+ loc.conditionArgs = {};
+ loc.conditionArgs.category = loc.category;
+ loc.conditionArgs.key = loc.key;
+ loc.executeArgs = arguments;
+ loc.executeArgs.category = loc.category;
+ loc.executeArgs.key = loc.key;
+ loc.partial = $doubleCheckedLock(name=loc.lockName, condition="$getFromCache", execute="$renderPartialAndAddToCache", conditionArgs=loc.conditionArgs, executeArgs=loc.executeArgs);
+ }
+ else
+ {
+ loc.partial = $renderPartial(argumentCollection=arguments);
+ }
+ if (arguments.$partialType == "include")
+ loc.returnValue = loc.partial;
+ else if (arguments.$partialType == "render")
+ request.wheels.response = loc.partial;
+ </cfscript>
+ <cfreturn loc.returnValue>
+</cffunction>
+
+<cffunction name="$includeFile" returntype="string" access="public" output="false">
+ <cfargument name="$name" type="any" required="true">
+ <cfargument name="$type" type="string" required="true">
+ <cfscript>
+ var loc = {};
+ loc.include = application.wheels.viewPath;
+ loc.fileName = Spanexcluding(Reverse(ListFirst(Reverse(arguments.$name), "/")), ".") & ".cfm"; // extracts the file part of the path and replace ending ".cfm"
+ if (arguments.$type == "partial")
+ loc.fileName = Replace("_" & loc.fileName, "__", "_", "one"); // replaces leading "_" when the file is a partial
+ loc.folderName = Reverse(ListRest(Reverse(arguments.$name), "/"));
+ if (Left(arguments.$name, 1) == "/")
+ loc.include = loc.include & loc.folderName & "/" & loc.fileName; // Include a file in a sub folder to views
+ else if (arguments.$name Contains "/")
+ loc.include = loc.include & "/" & variables.params.controller & "/" & loc.folderName & "/" & loc.fileName; // Include a file in a sub folder of the current controller
+ else
+ loc.include = loc.include & "/" & variables.params.controller & "/" & loc.fileName; // Include a file in the current controller's view folder
+ arguments.$template = loc.include;
+ if (arguments.$type == "partial")
+ {
+ loc.pluralizedName = pluralize(arguments.$name);
+ if (StructKeyExists(arguments, loc.pluralizedName) && IsQuery(arguments[loc.pluralizedName]))
+ {
+ loc.query = arguments[loc.pluralizedName];
+ loc.returnValue = "";
+ loc.iEnd = loc.query.recordCount;
+ for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
+ {
+ arguments.currentRow = loc.i;
+ loc.jEnd = ListLen(loc.query.columnList);
+ for (loc.j=1; loc.j <= loc.jEnd; loc.j++)
+ {
+ loc.property = ListGetAt(loc.query.columnList, loc.j);
+ arguments[loc.property] = loc.query[loc.property][loc.i];
+ }
+ loc.returnValue = loc.returnValue & $includeAndReturnOutput(argumentCollection=arguments);
+ if (StructKeyExists(arguments, "$spacer") && loc.i < loc.iEnd)
+ loc.returnValue = loc.returnValue & arguments.$spacer;
+ }
+ }
+ else if (StructKeyExists(arguments, arguments.$name) && IsObject(arguments[arguments.$name]))
+ {
+ loc.object = arguments[arguments.$name];
+ loc.properties = loc.object.$classData().propertyList;
+ loc.iEnd = ListLen(loc.properties);
+ for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
+ {
+ loc.property = ListGetAt(loc.properties, loc.i);
+ if (StructKeyExists(loc.object, loc.property) && IsSimpleValue(loc.object[loc.property]))
+ arguments[loc.property] = loc.object[loc.property];
+ }
+ }
+ }
+ if (!StructKeyExists(loc, "returnValue"))
+ loc.returnValue = $includeAndReturnOutput(argumentCollection=arguments);
+ </cfscript>
+ <cfreturn loc.returnValue>
+</cffunction>
+
+<cffunction name="$renderLayout" returntype="string" access="public" output="false">
+ <cfargument name="$content" type="string" required="true">
+ <cfargument name="$layout" type="any" required="true">
+ <cfscript>
+ var loc = {};
+ if ((IsBoolean(arguments.$layout) && arguments.$layout) || (!IsBoolean(arguments.$layout) && Len(arguments.$layout)))
+ {
+ request.wheels.contentForLayout = arguments.$content; // store the content in a variable in the request scope so it can be accessed by the contentForLayout function that the developer uses in layout files (this is done so we avoid passing data to/from it since it would complicate things for the developer)
+ loc.include = application.wheels.viewPath;
+ if (IsBoolean(arguments.$layout))
+ {
+ if (!ListFindNoCase(application.wheels.existingLayoutFiles, variables.params.controller) && !ListFindNoCase(application.wheels.nonExistingLayoutFiles, variables.params.controller))
+ {
+ if (FileExists(ExpandPath("#application.wheels.viewPath#/#LCase(variables.params.controller)#/layout.cfm")))
+ application.wheels.existingLayoutFiles = ListAppend(application.wheels.existingLayoutFiles, variables.params.controller);
+ else
+ application.wheels.nonExistingLayoutFiles = ListAppend(application.wheels.nonExistingLayoutFiles, variables.params.controller);
+ }
+ if (ListFindNoCase(application.wheels.existingLayoutFiles, variables.params.controller))
+ {
+ loc.include = loc.include & "/" & variables.params.controller & "/" & "layout.cfm";
+ }
+ else
+ {
+ loc.include = loc.include & "/" & "layout.cfm";
+ }
+ loc.returnValue = $includeAndReturnOutput($template=loc.include);
+ }
+ else
+ {
+ loc.returnValue = $includeFile($name=arguments.$layout, $type="layout");
+ }
+ }
+ else
+ {
+ loc.returnValue = arguments.$content;
+ }
+ </cfscript>
+ <cfreturn loc.returnValue>
+</cffunction>
1 wheels/dispatch/functions.cfm
@@ -0,0 +1 @@
+<cfinclude template="request.cfm">
389 wheels/dispatch/request.cfm
@@ -0,0 +1,389 @@
+<cffunction name="$runFilters" returntype="void" access="public" output="false">
+ <cfargument name="controller" type="any" required="true">
+ <cfargument name="actionName" type="string" required="true">
+ <cfargument name="type" type="string" required="true">
+ <cfscript>
+ var loc = {};
+ if (arguments.type == "before")
+ loc.filters = arguments.controller.$getBeforeFilters();
+ else
+ loc.filters = arguments.controller.$getAfterFilters();
+ loc.iEnd = ArrayLen(loc.filters);
+ for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
+ {
+ if ((!Len(loc.filters[loc.i].only) && !Len(loc.filters[loc.i].except)) || (Len(loc.filters[loc.i].only) && ListFindNoCase(loc.filters[loc.i].only, arguments.actionName)) || (Len(loc.filters[loc.i].except) && !ListFindNoCase(loc.filters[loc.i].except, arguments.actionName)))
+ $invoke(componentReference=arguments.controller, method=loc.filters[loc.i].through);
+ }
+ </cfscript>
+</cffunction>
+
+<cffunction name="$runVerifications" returntype="void" access="public" output="false">
+ <cfargument name="controller" type="any" required="true">
+ <cfargument name="actionName" type="string" required="true">
+ <cfargument name="params" type="struct" required="true">
+ <cfscript>
+ var loc = {};
+ loc.returnValue = "";
+ loc.verifications = arguments.controller.$getVerifications();
+ loc.abort = false;
+ loc.iEnd = ArrayLen(loc.verifications);
+ for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
+ {
+ loc.verification = loc.verifications[loc.i];
+ if ((!Len(loc.verification.only) && !Len(loc.verification.except)) || (Len(loc.verification.only) && ListFindNoCase(loc.verification.only, arguments.actionName)) || (Len(loc.verification.except) && !ListFindNoCase(loc.verification.except, arguments.actionName)))
+ {
+ if (IsBoolean(loc.verification.post) && ((loc.verification.post && cgi.request_method != "post") || (!loc.verification.post && cgi.request_method == "post")))
+ loc.abort = true;
+ if (IsBoolean(loc.verification.get) && ((loc.verification.get && cgi.request_method != "get") || (!loc.verification.get && cgi.request_method == "get")))
+ loc.abort = true;
+ if (IsBoolean(loc.verification.ajax) && ((loc.verification.ajax && cgi.http_x_requested_with != "XMLHTTPRequest") || (!loc.verification.ajax && cgi.http_x_requested_with == "XMLHTTPRequest")))
+ loc.abort = true;
+ loc.jEnd = ListLen(loc.verification.params);
+ for (loc.j=1; loc.j <= loc.jEnd; loc.j++)
+ {
+ if (!StructKeyExists(arguments.params, ListGetAt(loc.verification.params, loc.j)))
+ loc.abort = true;
+ }
+ loc.jEnd = ListLen(loc.verification.session);
+ for (loc.j=1; loc.j <= loc.jEnd; loc.j++)
+ {
+ if (!StructKeyExists(session, ListGetAt(loc.verification.session, loc.j)))
+ loc.abort = true;
+ }
+ loc.jEnd = ListLen(loc.verification.cookie);
+ for (loc.j=1; loc.j <= loc.jEnd; loc.j++)
+ {
+ if (!StructKeyExists(cookie, ListGetAt(loc.verification.cookie, loc.j)))
+ loc.abort = true;
+ }
+ }
+ if (loc.abort)
+ {
+ if (Len(loc.verification.handler))
+ {
+ $invoke(componentReference=arguments.controller, method=loc.verification.handler);
+ $location(url=cgi.http_referer, addToken=false);
+ }
+ else
+ {
+ $abort();
+ }
+ }
+ }
+ </cfscript>
+</cffunction>
+
+<cffunction name="$getRouteFromRequest" returntype="string" access="public" output="false">
+ <cfargument name="pathInfo" type="string" required="false" default="#cgi.path_info#">
+ <cfargument name="scriptName" type="string" required="false" default="#cgi.script_name#">
+ <cfscript>
+ var returnValue = "";
+ if (arguments.pathInfo == arguments.scriptName || arguments.pathInfo == "/" || arguments.pathInfo == "")
+ returnValue = "";
+ else
+ returnValue = Right(arguments.pathInfo, Len(arguments.pathInfo)-1);
+ </cfscript>
+ <cfreturn returnValue>
+</cffunction>
+
+<cffunction name="$findMatchingRoute" returntype="struct" access="public" output="false">
+ <cfargument name="route" type="string" required="true">
+ <cfargument name="routes" type="array" required="false" default="#application.wheels.routes#">
+ <cfscript>
+ var loc = {};
+ loc.iEnd = ArrayLen(arguments.routes);
+ for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
+ {
+ loc.currentRoute = arguments.routes[loc.i].pattern;
+ if (arguments.route == "" && loc.currentRoute == "")
+ {
+ loc.returnValue = arguments.routes[loc.i];
+ break;
+ }
+ else
+ {
+ if (ListLen(arguments.route, "/") >= ListLen(loc.currentRoute, "/") && loc.currentRoute != "")
+ {
+ loc.match = true;
+ loc.jEnd = ListLen(loc.currentRoute, "/");
+ for (loc.j=1; loc.j <= loc.jEnd; loc.j++)
+ {
+ loc.item = ListGetAt(loc.currentRoute, loc.j, "/");
+ loc.thisRoute = ReplaceList(loc.item, "[,]", ",");
+ loc.thisURL = ListGetAt(arguments.route, loc.j, "/");
+ if (Left(loc.item, 1) != "[" && loc.thisRoute != loc.thisURL)
+ loc.match = false;
+ }
+ if (loc.match)
+ {
+ loc.returnValue = arguments.routes[loc.i];
+ break;
+ }
+ }
+ }
+ }
+ if (!StructKeyExists(loc, "returnValue"))
+ $throw(type="Wheels.RouteNotFound", message="Wheels couldn't find a route that matched this request.", extendedInfo="Make sure there is a route setup in your 'config/routes.cfm' file that matches the '#arguments.route#' request.");
+ </cfscript>
+ <cfreturn loc.returnValue>
+</cffunction>
+
+<cffunction name="$createParams" returntype="struct" access="public" output="false">
+ <cfargument name="route" type="string" required="true">
+ <cfargument name="foundRoute" type="struct" required="true">
+ <cfargument name="formScope" type="struct" required="false" default="#form#">
+ <cfargument name="urlScope" type="struct" required="false" default="#url#">
+ <cfscript>
+ var loc = {};
+
+ // add all normal URL variables to struct (i.e. ?x=1&y=2 etc)
+ loc.returnValue = arguments.urlScope;
+
+ // go through the matching route pattern and add URL variables from the route to the struct
+ loc.iEnd = ListLen(arguments.foundRoute.pattern, "/");
+ for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
+ {
+ loc.item = ListGetAt(arguments.foundRoute.pattern, loc.i, "/");
+ if (Left(loc.item, 1) == "[")
+ loc.returnValue[ReplaceList(loc.item, "[,]", ",")] = ListGetAt(arguments.route, loc.i, "/");
+ }
+
+ // add controller and action unless they already exist
+ if (!StructKeyExists(loc.returnValue, "controller"))
+ loc.returnValue.controller = arguments.foundRoute.controller;
+ if (!StructKeyExists(loc.returnValue, "action"))
+ loc.returnValue.action = arguments.foundRoute.action;
+
+ // convert controller to upperCamelCase and action to normal camelCase
+ loc.returnValue.controller = REReplace(loc.returnValue.controller, "-([a-z])", "\u\1", "all");
+ loc.returnValue.action = REReplace(loc.returnValue.action, "-([a-z])", "\u\1", "all");
+
+ // add name of route to params if a named route is running
+ if (StructKeyExists(arguments.foundRoute, "name") && Len(arguments.foundRoute.name) && !StructKeyExists(loc.returnValue, "route"))
+ loc.returnValue.route = arguments.foundRoute.name;
+
+ // decrypt all values except controller and action
+ if (application.wheels.obfuscateUrls)
+ {
+ for (loc.key in loc.returnValue)
+ {
+ if (loc.key != "controller" && loc.key != "action")
+ {
+ try
+ {
+ loc.returnValue[loc.key] = deobfuscateParam(loc.returnValue[loc.key]);
+ }
+ catch(Any e) {}
+ }
+ }
+ }
+
+ if (StructCount(arguments.formScope))
+ {
+ // loop through form variables, merge any date variables into one, fix checkbox submissions
+ loc.dates = {};
+ for (loc.key in arguments.formScope)
+ {
+ if (FindNoCase("($checkbox)", loc.key))
+ {
+ // if no other form parameter exists with this name it means that the checkbox was left blank and therefore we force the value to 0 (to get around the problem that unchecked checkboxes don't post at all)
+ loc.formParamName = ReplaceNoCase(loc.key, "($checkbox)", "");
+ if (!StructKeyExists(arguments.formScope, loc.formParamName))
+ arguments.formScope[loc.formParamName] = 0;
+ StructDelete(arguments.formScope, loc.key);
+ }
+ else if (REFindNoCase(".*\((\$year|\$month|\$day|\$hour|\$minute|\$second)\)$", loc.key))
+ {
+ loc.temp = ListToArray(loc.key, "(");
+ loc.firstKey = loc.temp[1];
+ loc.secondKey = SpanExcluding(loc.temp[2], ")");
+ if (!StructKeyExists(loc.dates, loc.firstKey))
+ loc.dates[loc.firstKey] = {};
+ loc.dates[loc.firstKey][ReplaceNoCase(loc.secondKey, "$", "")] = arguments.formScope[loc.key];
+ }
+ }
+ for (loc.key in loc.dates)
+ {
+ if (!StructKeyExists(loc.dates[loc.key], "year"))
+ loc.dates[loc.key].year = 1899;
+ if (!StructKeyExists(loc.dates[loc.key], "month"))
+ loc.dates[loc.key].month = 12;
+ if (!StructKeyExists(loc.dates[loc.key], "day"))
+ loc.dates[loc.key].day = 30;
+ if (!StructKeyExists(loc.dates[loc.key], "hour"))
+ loc.dates[loc.key].hour = 0;
+ if (!StructKeyExists(loc.dates[loc.key], "minute"))
+ loc.dates[loc.key].minute = 0;
+ if (!StructKeyExists(loc.dates[loc.key], "second"))
+ loc.dates[loc.key].second = 0;
+ try
+ {
+ arguments.formScope[loc.key] = CreateDateTime(loc.dates[loc.key].year, loc.dates[loc.key].month, loc.dates[loc.key].day, loc.dates[loc.key].hour, loc.dates[loc.key].minute, loc.dates[loc.key].second);
+ }
+ catch(Any e)
+ {
+ arguments.formScope[loc.key] = "";
+ }
+ if (StructKeyExists(arguments.formScope, "#loc.key#($year)"))
+ StructDelete(arguments.formScope, "#loc.key#($year)");
+ if (StructKeyExists(arguments.formScope, "#loc.key#($month)"))
+ StructDelete(arguments.formScope, "#loc.key#($month)");
+ if (StructKeyExists(arguments.formScope, "#loc.key#($day)"))
+ StructDelete(arguments.formScope, "#loc.key#($day)");
+ if (StructKeyExists(arguments.formScope, "#loc.key#($hour)"))
+ StructDelete(arguments.formScope, "#loc.key#($hour)");
+ if (StructKeyExists(arguments.formScope, "#loc.key#($minute)"))
+ StructDelete(arguments.formScope, "#loc.key#($minute)");
+ if (StructKeyExists(arguments.formScope, "#loc.key#($second)"))
+ StructDelete(arguments.formScope, "#loc.key#($second)");
+ }
+
+ // add form variables to the params struct
+ for (loc.key in arguments.formScope)
+ {
+ loc.match = REFindNoCase("(.*?)\[(.*?)\]", loc.key, 1, true);
+ if (ArrayLen(loc.match.pos) == 3)
+ {
+ // model object form field, build a struct to hold the data, named after the model object
+ loc.objectName = LCase(Mid(loc.key, loc.match.pos[2], loc.match.len[2]));
+ loc.fieldName = LCase(Mid(loc.key, loc.match.pos[3], loc.match.len[3]));
+ if (!StructKeyExists(loc.returnValue, loc.objectName))
+ loc.returnValue[loc.objectName] = {};
+ loc.returnValue[loc.objectName][loc.fieldName] = arguments.formScope[loc.key];
+ }
+ else
+ {
+ // normal form field
+ loc.returnValue[loc.key] = arguments.formScope[loc.key];
+ }
+ }
+ }
+ </cfscript>
+ <cfreturn loc.returnValue>
+</cffunction>
+
+<cffunction name="$request" returntype="string" access="public" output="false">
+ <cfscript>
+ var loc = {};
+ if (application.wheels.showDebugInformation)
+ $debugPoint("setup");
+
+ // set route from incoming url, find a matching one and create the params struct
+ loc.route = $getRouteFromRequest();
+ loc.foundRoute = $findMatchingRoute(route=loc.route);
+ loc.params = $createParams(route=loc.route, foundRoute=loc.foundRoute);
+
+ // set params in the request scope as well so we can display it in the debug info outside of the controller context
+ request.wheels.params = loc.params;
+
+ // create an empty flash unless it already exists
+ if (!StructKeyExists(session, "flash"))
+ session.flash = {};
+
+ // create the requested controller
+ loc.controller = $controller(loc.params.controller).$createControllerObject(loc.params);
+
+ if (application.wheels.showDebugInformation)
+ $debugPoint("setup,beforeFilters");
+
+ // run verifications and before filters if they exist on the controller
+ $runVerifications(controller=loc.controller, actionName=loc.params.action, params=loc.params);
+ $runFilters(controller=loc.controller, type="before", actionName=loc.params.action);
+
+ if (application.wheels.showDebugInformation)
+ $debugPoint("beforeFilters,action");
+
+ // call action on controller if it exists
+ loc.actionIsCachable = false;
+ if (application.wheels.cacheActions && StructIsEmpty(session.flash) && StructIsEmpty(form))
+ {
+ loc.cachableActions = loc.controller.$getCachableActions();
+ loc.iEnd = ArrayLen(loc.cachableActions);
+ for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
+ {
+ if (loc.cachableActions[loc.i].action == loc.params.action)
+ {
+ loc.actionIsCachable = true;
+ loc.timeToCache = loc.cachableActions[loc.i].time;
+ }
+ }
+ }
+ if (loc.actionIsCachable)
+ {
+ loc.category = "action";
+ loc.key = "#cgi.script_name##cgi.path_info##cgi.query_string#";
+ loc.lockName = loc.category & loc.key;
+ loc.conditionArgs = {};
+ loc.conditionArgs.key = loc.key;
+ loc.conditionArgs.category = loc.category;
+ loc.executeArgs = {};
+ loc.executeArgs.controller = loc.controller;
+ loc.executeArgs.controllerName = loc.params.controller;
+ loc.executeArgs.actionName = loc.params.action;
+ loc.executeArgs.key = loc.key;
+ loc.executeArgs.time = loc.timeToCache;
+ loc.executeArgs.category = loc.category;
+ $doubleCheckedLock(name=loc.lockName, condition="$getFromCache", execute="$callActionAndAddToCache", conditionArgs=loc.conditionArgs, executeArgs=loc.executeArgs);
+ }
+ else
+ {
+ $callAction(controller=loc.controller, controllerName=loc.params.controller, actionName=loc.params.action);
+ }
+ if (application.wheels.showDebugInformation)
+ $debugPoint("action,afterFilters");
+ $runFilters(controller=loc.controller, type="after", actionName=loc.params.action);
+ if (application.wheels.showDebugInformation)
+ $debugPoint("afterFilters");
+
+ // clear the flash (note that this is not done for redirectTo since the processing does not get here)
+ StructClear(session.flash);
+ </cfscript>
+ <cfreturn request.wheels.response>
+</cffunction>
+
+<cffunction name="$callActionAndAddToCache" returntype="string" access="public" output="false">
+ <cfscript>
+ $callAction(controller=arguments.controller, controllerName=arguments.controllerName, actionName=arguments.actionName);
+ $addToCache(key=arguments.key, value=request.wheels.response, time=arguments.time, category=arguments.category);
+ </cfscript>
+ <cfreturn request.wheels.response>
+</cffunction>
+
+<cffunction name="$callAction" returntype="void" access="public" output="false">
+ <cfargument name="controller" type="any" required="true">
+ <cfargument name="controllerName" type="string" required="true">
+ <cfargument name="actionName" type="string" required="true">
+ <cfscript>
+ var loc = {};
+ if (StructKeyExists(arguments.controller, arguments.actionName))
+ $invoke(componentReference=arguments.controller, method=arguments.actionName);
+ if (!StructKeyExists(request.wheels, "response"))
+ {
+ // a render function has not been called yet so call it here
+ try
+ {
+ arguments.controller.renderPage();
+ }
+ catch(Any e)
+ {
+ if (FileExists(ExpandPath("#application.wheels.viewPath#/#LCase(arguments.controllerName)#/#LCase(arguments.actionName)#.cfm")))
+ {
+ $throw(object=e);
+ }
+ else
+ {
+ if (application.wheels.showErrorInformation)
+ {
+ $throw(type="Wheels.ViewNotFound", message="Could not find the view page for the '#arguments.actionName#' action in the '#arguments.controllerName#' controller.", extendedInfo="Create a file named '#LCase(arguments.actionName)#.cfm' in the 'views/#LCase(arguments.controllerName)#' directory (create the directory as well if it doesn't already exist).");
+ }
+ else
+ {
+ $header(statusCode="404", statusText="Not Found");
+ $includeAndOutput(template="#application.wheels.eventPath#/onmissingtemplate.cfm");
+ $abort();
+ }
+ }
+ }
+ }
+ </cfscript>
+</cffunction>
6 wheels/events/onapplicationend.cfm
@@ -0,0 +1,6 @@
+<cffunction name="onApplicationEnd" returntype="void" access="public" output="false">
+ <cfargument name="applicationscope" type="struct" required="true">
+ <cfscript>
+ $include(template="#arguments.applicationscope.wheels.eventPath#/onapplicationend.cfm");
+ </cfscript>
+</cffunction>
174 wheels/events/onapplicationstart.cfm
@@ -0,0 +1,174 @@