Created
February 3, 2011 06:58
-
-
Save Zoramite/809143 to your computer and use it in GitHub Desktop.
Railo multiple variables scope bug
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cfcomponent output="false"> | |
<cfscript> | |
public component function init() { | |
variables.columns = []; | |
variables.extend = createObject('component', 'extend').init(); | |
return this; | |
} | |
public void function addColumn(struct options = {}) { | |
var defaults = { | |
class = '', | |
format = '', | |
key = '', | |
label = '', | |
link = [], | |
title = '', | |
type = 'text', | |
value = '' | |
}; | |
// Normalize the options | |
if (structKeyExists(arguments.options, 'link') && !isArray(arguments.options.link)) { | |
arguments.options.link = [ arguments.options.link ]; | |
} | |
arrayAppend(variables.columns, variables.extend.extend(defaults, arguments.options)); | |
} | |
</cfscript> | |
<cffunction name="createLink" access="private" returntype="string" output="false"> | |
<cfargument name="text" type="any" required="true" /> | |
<cfargument name="column" type="struct" required="true" /> | |
<cfargument name="data" type="any" required="true" /> | |
<cfargument name="rowNum" type="numeric" required="true" /> | |
<cfargument name="colNum" type="numeric" required="true" /> | |
<cfargument name="options" type="struct" default="#{}#" /> | |
<cfset var href = '' /> | |
<cfset var html = '' /> | |
<cfset var i = '' /> | |
<cfset var j = '' /> | |
<cfset var theUrl = '' /> | |
<cfset var value = '' /> | |
<cfset theUrl = arguments.options.theUrl /> | |
<!--- Adjust for the startRow ---> | |
<cfset arguments.rowNum += arguments.options.startRow - 1 /> | |
<cfsavecontent variable="html"> | |
<cfoutput> | |
<cfloop from="1" to="#arrayLen(arguments.column.link)#" index="i"> | |
<cfloop list="#structKeyList(arguments.column.link[i])#" index="j"> | |
<cfset value = arguments.data[arguments.rowNum][arguments.column.link[i][j]] /> | |
<cfset theUrl['setDGCol#arguments.colNum#Link#i#'](j, value) /> | |
</cfloop> | |
<cfset href = theUrl['getDGCol#arguments.colNum#Link#i#']() /> | |
<a href="#href#">#arguments.text#</a> | |
</cfloop> | |
</cfoutput> | |
</cfsavecontent> | |
<cfreturn html /> | |
</cffunction> | |
<cffunction name="toHTML" access="public" returntype="string" output="false"> | |
<cfargument name="data" type="any" required="true" /> | |
<cfargument name="options" type="struct" default="#{}#" /> | |
<cfset var col = '' /> | |
<cfset var counter = '' /> | |
<cfset var defaults = { | |
class = '', | |
linkBase = '', | |
minimumRows = 15, | |
numPerPage = 30, | |
startRow = 1 | |
} /> | |
<cfset var html = '' /> | |
<cfset var i = '' /> | |
<cfset var item = '' /> | |
<cfset var rowNum = '' /> | |
<cfset var title = '' /> | |
<cfset var value = '' /> | |
<cfset arguments.options = variables.extend.extend(defaults, arguments.options) /> | |
<cfsavecontent variable="html"> | |
<table class="datagrid <cfoutput>#arguments.options.class#</cfoutput>"> | |
<tbody> | |
<cfset rowNum = 0 /> | |
<cfloop from="#arguments.options.startRow#" to="#min(arrayLen(arguments.data), arguments.options.startRow + arguments.options.numPerPage)#" index="i"> | |
<cfset item = arguments.data[i] /> | |
<cfset rowNum++ /> | |
<cfoutput> | |
<tr> | |
<cfset counter = 0 /> | |
<cfloop array="#variables.columns#" index="col"> | |
<td class="#col.key# #col.class# column-#counter++#"> | |
<cfset value = item[col.key] /> | |
#createLink(value, col, data, rowNum, counter, arguments.options)# | |
</td> | |
</cfloop> | |
</tr> | |
</cfoutput> | |
</cfloop> | |
</tbody> | |
</table> | |
</cfsavecontent> | |
<cfreturn html /> | |
</cffunction> | |
</cfcomponent> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cfcomponent output="false"> | |
<cffunction name="init" access="public" returntype="any" output="false"> | |
<cfreturn this /> | |
</cffunction> | |
<cffunction name="extend" access="public" output="false"> | |
<cfargument name="defaults" type="struct" required="true" /> | |
<cfargument name="original" type="struct" default="#{}#" /> | |
<cfargument name="depth" type="numeric" default="1" /> | |
<cfset var extended = duplicate(arguments.original) /> | |
<cfset var i = '' /> | |
<!--- Loop through and test each value in the values struct and see if it has been set already ---> | |
<cfloop list="#structKeyList(arguments.defaults)#" index="i"> | |
<cfif not structKeyExists(extended, i)> | |
<cfset extended[i] = arguments.defaults[i] /> | |
<cfelseif (arguments.depth gt 1 or arguments.depth lt 0) and isStruct(arguments.defaults[i]) and isStruct(extended[i])> | |
<cfset extended[i] = extend(arguments.defaults[i], extended[i], arguments.depth - 1) /> | |
</cfif> | |
</cfloop> | |
<cfreturn extended /> | |
</cffunction> | |
</cfcomponent> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cfset theUrl = createObject('component', 'urlRewrite').init('') /> | |
<cfset datagrid = createObject('component', 'datagrid').init() /> | |
<cfset datagrid.addColumn({ | |
key = 'name', | |
link = { | |
'userID' = 'userID' | |
} | |
}) /> | |
<cfset data = [ | |
{ | |
userID = 1, | |
name = "John" | |
} | |
] /> | |
<cfoutput>#datagrid.toHTML(data, { | |
theUrl = theUrl | |
})#</cfoutput> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cfcomponent output="false"> | |
<cffunction name="init" access="public" returntype="any" output="false"> | |
<cfargument name="masterBase" type="any" default="" /> | |
<cfargument name="options" type="struct" default="#{}#" /> | |
<cfset variables.urlOptions = { | |
start = '', | |
startChar = '?', | |
ampEncodeChar = '&', | |
eqEncodeChar = '=' | |
} /> | |
<cfset variables.extend = createObject('component', 'extend').init() /> | |
<cfset variables.locations = {} /> | |
<cfset variables.locations[''] = {} /> | |
<cfreturn this /> | |
</cffunction> | |
<cffunction name="__findLocation" access="private" returntype="struct" output="false"> | |
<cfargument name="locationName" type="string" required="true" /> | |
<cfset arguments.locationName = trim(arguments.locationName) /> | |
<!--- Check for valid location ---> | |
<cfif not __has(arguments.locationName)> | |
<cfset variables.locations[arguments.locationName] = variables.extend.extend({}, variables.locations['']) /> | |
</cfif> | |
<cfreturn variables.locations[arguments.locationName] /> | |
</cffunction> | |
<cffunction name="__get" access="private" returntype="string" output="false"> | |
<cfargument name="locationName" type="string" default="" /> | |
<cfargument name="useEncoded" type="boolean" default="true" /> | |
<cfargument name="options" type="struct" default="#{}#" /> | |
<cfset var formatted = '' /> | |
<cfset var current = '' /> | |
<cfset var ampChar = '' /> | |
<cfset var eqChar = '' /> | |
<cfset var currentLocation = __findLocation(arguments.locationName) /> | |
<cfset var getOptions = '' /> | |
<!--- Extend the options ---> | |
<cfset getOptions = variables.extend.extend(variables.urlOptions, arguments.options) /> | |
<cfset ampChar = getOptions.ampEncodeChar /> | |
<cfset eqChar = getOptions.eqEncodeChar /> | |
<cfif not structKeyExists(getOptions, 'keys')> | |
<cfset getOptions.keys = structKeyList(currentLocation) /> | |
</cfif> | |
<!--- Add each variable ---> | |
<cftry> | |
<cfloop list="#getOptions.keys#" index="current"> | |
<cfset formatted &= current & eqChar & currentLocation[current] & ampChar /> | |
</cfloop> | |
<cfcatch type="any"> | |
<cfdump var="#currentLocation#" label="Url currentLocation" /> | |
<cfdump var="#variables.locations#" label="Url variables.locations" /> | |
<cfrethrow /> | |
</cfcatch> | |
</cftry> | |
<cfreturn formatted /> | |
</cffunction> | |
<cffunction name="__has" access="private" returntype="boolean" output="false"> | |
<cfargument name="locationName" type="string" default="" /> | |
<!--- Check if is master ---> | |
<cfif arguments.locationName eq ''> | |
<cfreturn true /> | |
</cfif> | |
<cfreturn structKeyExists(variables.locations, arguments.locationName) /> | |
</cffunction> | |
<cffunction name="onMissingMethod" access="public" returntype="any" output="false"> | |
<cfargument name="missingMethodName" type="string" required="true" /> | |
<cfargument name="missingMethodArguments" type="struct" required="true" /> | |
<cfset var findParts = '' /> | |
<cfset var name = '' /> | |
<cfset var extra = '' /> | |
<!--- Since railo has uppercase missingMethodName need to have missingMethodName in lowercase ---> | |
<cfset arguments.missingMethodName = lCase(arguments.missingMethodName) /> | |
<!--- Find the parts of the function name we are interested in ---> | |
<cfset findParts = reFind('^(get|has|set)(.*)', arguments.missingMethodName, 1, true) /> | |
<!--- Check if not one that we are equiped to handle ---> | |
<cfif not findParts.pos[1]> | |
<cfthrow message="The #arguments.missingMethodName# method was not found" /> | |
</cfif> | |
<!--- Set the name ---> | |
<cfset name = left(arguments.missingMethodName, findParts.len[2]) /> | |
<!--- Set the extra information ---> | |
<cfif findParts.len[3]> | |
<cfset extra = mid(arguments.missingMethodName, findParts.pos[3], findParts.len[3]) /> | |
</cfif> | |
<!--- Determine what we are really doing ---> | |
<cfswitch expression="#name#"> | |
<cfcase value="get"> | |
<cfif len(extra)> | |
<cfset arrayPrepend(arguments.missingMethodArguments, extra) /> | |
</cfif> | |
<cfreturn __get(argumentCollection = arguments.missingMethodArguments) /> | |
</cfcase> | |
<cfcase value="has"> | |
<cfif arrayLen(arguments.missingMethodArguments) eq 1> | |
<cfreturn __has(arguments.missingMethodArguments[1]) /> | |
</cfif> | |
<cfreturn __has(extra) /> | |
</cfcase> | |
<cfcase value="set"> | |
<cfif arrayLen(arguments.missingMethodArguments) eq 3> | |
<cfreturn __set(arguments.missingMethodArguments[1], arguments.missingMethodArguments[2], arguments.missingMethodArguments[3]) /> | |
</cfif> | |
<cfreturn __set(extra, arguments.missingMethodArguments[1], arguments.missingMethodArguments[2]) /> | |
</cfcase> | |
</cfswitch> | |
<cfthrow message="The #arguments.missingMethodName# method was not found" /> | |
</cffunction> | |
<cffunction name="__set" access="private" returntype="void" output="false"> | |
<cfargument name="locationName" type="string" required="true" /> | |
<cfargument name="varName" type="string" required="true" /> | |
<cfargument name="varValue" type="any" required="true" /> | |
<cfset var currentLocation = '' /> | |
<!--- Get the location ---> | |
<cfset currentLocation = __findLocation(arguments.locationName) /> | |
<!--- Set the value ---> | |
<cfset currentLocation[arguments.varName] = arguments.varValue /> | |
</cffunction> | |
</cfcomponent> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
component extends="url" { | |
public component function init(any masterBase = '', struct options = {}) { | |
if(!structKeyExists(arguments.options, 'rewriteBase') || arguments.options.rewriteBase eq '') { | |
arguments.options['rewriteBase'] = '_base'; | |
} | |
super.init(argumentCollection = arguments); | |
return this; | |
} | |
private string function __get( string locationName = '', boolean useEncoded = true, struct options = {} ) { | |
var keys = ''; | |
var locate = ''; | |
var currentLocation = __findLocation(arguments.locationName); | |
// Extend the options | |
arguments.options = variables.extend.extend(variables.urlOptions, arguments.options); | |
arguments.options.keys = structKeyList(currentLocation); | |
try { | |
return super.__get(argumentCollection = arguments); | |
} catch(any e) { | |
writeDump(var = currentLocation, label = 'Rewrite currentlocation'); | |
writeDump(var = variables.locations, label = 'Rewrite variables.locations'); | |
writeDump(var = e, label = 'Original Error'); | |
abort; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment