UPDATED: The functionality has now been rolled into the framework as of version 1.2, so the hack is unnecessary. The methodology for overriding a framework method still applies, but let me reiterate: be very careful what you change, and look out for any code changes to the overridden method in future releases!
Original post continues below…
My (first) FW/1 application consists of two subsystems: public and admin. The public subsystem is the default, so if I invoke a URL action without a subsystem specified explicitly, it will use ‘public’.
Of course, if you use the buildURL() method to create your links (which you should be doing!) it will always prepend your action with public: – which I find a little untidy, especially when using SES URLs.
It’s very easy to customise FW/1 to “fix” this. Simply import a customisation file at the top of your Application.cfc file – alongside all the application settings – and put the following code in that file:
<cffunction name="buildURL_custom" access="public" output="false">
<cfargument name="action" type="string" />
<cfargument name="path" type="string" default="#variables.framework.baseURL#" />
<cfargument name="queryString" type="string" default="" />
<cfset var initialDelim = '?' />
<cfset var varDelim = '&' />
<cfset var equalDelim = '=' />
<cfset var basePath = '' />
<cfset var extraArgs = '' />
<cfset var queryPart = '' />
<cfset var anchor = '' />
<cfset var ses = false />
<cfset var omitIndex = false />
<cfif arguments.path eq "useCgiScriptName">
<cfset arguments.path = CGI.SCRIPT_NAME />
<cfif variables.framework.SESOmitIndex>
<cfset arguments.path = getDirectoryFromPath( arguments.path ) />
<cfset omitIndex = true />
</cfif>
</cfif>
<cfif find( '?', arguments.action ) and arguments.queryString is ''>
<!--- shorthand for action/queryString pairing --->
<cfset arguments.queryString = REReplace( arguments.action, '[^\?]*\?', '') />
<cfset arguments.action = REReplace( arguments.action, '([^\?\##]*).*', '\1') />
</cfif>
<cfif find( '?', arguments.path ) gt 0>
<cfif right( arguments.path, 1 ) eq '?' or right( arguments.path, 1 ) eq '&'>
<cfset initialDelim = '' />
<cfelse>
<cfset initialDelim = '&' />
</cfif>
<cfelseif structKeyExists( request, 'generateSES' ) and request.generateSES>
<cfif omitIndex>
<cfset initialDelim = '' />
<cfelse>
<cfset initialDelim = '/' />
</cfif>
<cfset varDelim = '/' />
<cfset equalDelim = '/' />
<cfset ses = true />
</cfif>
<!--- Start customisation. Don't display subsystem if in default subsystem --->
<cfif ses>
<cfif getSubsystem( arguments.action ) eq getConfig().defaultsubsystem>
<cfset basePath = arguments.path & initialDelim & replace( getSectionAndItem( arguments.action ), '.', '/' ) />
<cfelse>
<cfset basePath = arguments.path & initialDelim & replace( getFullyQualifiedAction( arguments.action ), '.', '/' ) />
</cfif>
<cfelse>
<cfif getSubsystem( arguments.action ) eq getConfig().defaultsubsystem>
<cfset basePath = arguments.path & initialDelim & variables.framework.action & equalDelim & getSectionAndItem(arguments.action) />
<cfelse>
<cfset basePath = arguments.path & initialDelim & variables.framework.action & equalDelim & getFullyQualifiedAction(arguments.action) />
</cfif>
</cfif>
<!--- End customisation --->
<cfif len( arguments.queryString )>
<cfset extraArgs = REReplace( arguments.queryString, '([^\?\##]*).*', '\1') />
<cfif find( '?', arguments.queryString )>
<cfset queryPart = REReplace( arguments.queryString, '[^\?]*\?([^\##]*).*', '\1') />
</cfif>
<cfif find( '##', arguments.queryString )>
<cfset anchor = REReplace( arguments.queryString, '[^\##]*\##(.*)', '\1' ) />
</cfif>
<cfif ses>
<cfset extraArgs = listChangeDelims( extraArgs, '/', '&=' ) />
</cfif>
<cfif extraArgs is not ''>
<cfset basePath = basePath & varDelim & extraArgs />
</cfif>
<cfif queryPart is not ''>
<cfif ses>
<cfset basePath = basePath & '?' & queryPart />
<cfelse>
<cfset basePath = basePath & '&' & queryPart />
</cfif>
</cfif>
<cfif anchor is not ''>
<cfset basePath = basePath & '##' & anchor />
</cfif>
</cfif>
<cfreturn basePath />
</cffunction>
<cfset variables.buildURL = variables.buildURL_custom />
The code is just a copy-and-paste of the buildURL() method from the org.corfield.framework cfc. The changes I’ve made are in the commented area in the middle, and just tell it that if the requested action is in the default subsystem, then only return the section and item in the URL; otherwise use the fully qualified action.
Note that I’ve renamed the method to buildURL_custom, and then used a cfset after the end of the function to replace the pre-defined method, as you are not allowed to define the same method twice.
You can use this method to override other FW/1 methods, but I’d advise a touch of caution: your changes might have knock-on effects! Also, keep an eye on any future updates of the framework to see if you need to apply code changes to your custom methods.
Posted on 26 August, 2010, in
ColdFusion, FW/1