PageRenderTime 52ms CodeModel.GetById 49ms app.highlight 1ms RepoModel.GetById 1ms app.codeStats 0ms

/wheels/controller/filters.cfm

http://raihan.googlecode.com/
ColdFusion | 132 lines | 117 code | 12 blank | 3 comment | 27 complexity | ef69c59e926be8f7e4745da0a3777019 MD5 | raw file
  1<!--- PUBLIC CONTROLLER INITIALIZATION FUNCTIONS --->
  2
  3<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."
  4	examples=
  5	'
  6		<!--- Always execute `restrictAccess` before all actions in this controller --->
  7		<cfset filters("restrictAccess")>
  8
  9		<!--- Always execute `isLoggedIn` and `checkIPAddress` (in that order) before all actions in this controller except the `home` and `login` actions --->
 10		<cfset filters(through="isLoggedIn,checkIPAddress", except="home,login")>
 11	'
 12	categories="controller-initialization,filtering" chapters="filters-and-verification" functions="setFilterChain,filterChain">
 13	<cfargument name="through" type="string" required="true" hint="Function(s) to execute before or after the action(s).">
 14	<cfargument name="type" type="string" required="false" default="before" hint="Whether to run the function(s) before or after the action(s).">
 15	<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.">
 16	<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.">
 17	<cfscript>
 18		var loc = {};
 19
 20		arguments.through = $listClean(arguments.through);
 21		arguments.only = $listClean(arguments.only);
 22		arguments.except = $listClean(arguments.except);
 23
 24		loc.namedArguments = "through,type,only,except";
 25		loc.iEnd = ListLen(arguments.through);
 26		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
 27		{
 28			loc.filter = {};
 29			loc.filter.through = ListGetAt(arguments.through, loc.i);
 30			loc.filter.type = arguments.type;
 31			loc.filter.only = arguments.only;
 32			loc.filter.except = arguments.except;
 33			loc.filter.arguments = {};
 34			if (StructCount(arguments) > ListLen(loc.namedArguments))
 35			{
 36				loc.dynamicArgument = loc.filter.through & "Arguments";
 37				if (StructKeyExists(arguments, loc.dynamicArgument))
 38					loc.filter.arguments = arguments[loc.dynamicArgument];
 39				for (loc.key in arguments)
 40				{
 41					if (!ListFindNoCase(ListAppend(loc.namedArguments, loc.dynamicArgument), loc.key))
 42						loc.filter.arguments[loc.key] = arguments[loc.key];
 43				}
 44			}
 45			ArrayAppend(variables.$class.filters, loc.filter);
 46		}
 47	</cfscript>
 48</cffunction>
 49
 50<cffunction name="setFilterChain" returntype="void" access="public" output="false" hint="Use this function if you need a more low level way of setting the entire filter chain for a controller."
 51	examples=
 52	'
 53		<!--- Set filter chain directly in an array --->
 54		<cfset setFilterChain([
 55			{through="restrictAccess"},
 56			{through="isLoggedIn,checkIPAddress", except="home,login"},
 57			{type="after", through="logConversion", only="thankYou"}
 58		])>
 59	'
 60	categories="controller-initialization,filtering" chapters="filters-and-verification" functions="filters,filterChain">
 61	<cfargument name="chain" type="array" required="true" hint="An array of structs, each of which represent an `argumentCollection` that get passed to the `filters` function. This should represent the entire filter chain that you want to use for this controller.">
 62	<cfscript>
 63		var loc = {};
 64		
 65		// Clear current filter chain
 66		variables.$class.filters = [];
 67		// Loop through chain passed in arguments and add each item to filter chain
 68		for(loc.i = 1; loc.i <= ArrayLen(arguments.chain); loc.i++) {
 69			filters(argumentCollection=arguments.chain[loc.i]);
 70		}
 71	</cfscript>
 72</cffunction>
 73
 74<!--- PUBLIC CONTROLLER CLASS FUNCTIONS --->
 75
 76<cffunction name="filterChain" returntype="array" access="public" output="false" hint="Returns an array of all the filters set on this controller in the order in which they will be executed."
 77	examples=
 78	'
 79		<!--- Get filter chain, remove the first item, and set it back --->
 80		<cfset myFilterChain = filterChain()>
 81		<cfset ArrayDeleteAt(myFilterChain, 1)>
 82		<cfset setFilterChain(myFilterChain)>
 83	'
 84	categories="controller-initialization,filtering" chapters="filters-and-verification" functions="filters,setFilterChain">
 85	<cfargument name="type" type="string" required="false" default="all" hint="Use this argument to return only `before` or `after` filters.">
 86	<cfscript>
 87		var loc = {};
 88
 89		// invalid type
 90		if (!ListFindNoCase("before,after,all", arguments.type))
 91			$throw(type="Wheels.InvalidFilterType", message="The filter type of `#arguments.type#` is invalid.", extendedInfo="Please use either `before` or `after`.");
 92
 93		// return all filters
 94		if (arguments.type == "all")
 95			return variables.$class.filters;
 96
 97		// loop over the filters and return all those that match the supplied type
 98		loc.returnValue = ArrayNew(1);
 99		loc.iEnd = ArrayLen(variables.$class.filters);
100		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
101		{
102			if (variables.$class.filters[loc.i].type == arguments.type)
103				ArrayAppend(loc.returnValue, variables.$class.filters[loc.i]);
104		}
105		return loc.returnValue;
106	</cfscript>
107</cffunction>
108
109<!--- PRIVATE FUNCTIONS --->
110
111<cffunction name="$runFilters" returntype="void" access="public" output="false">
112	<cfargument name="type" type="string" required="true">
113	<cfargument name="action" type="string" required="true">
114	<cfscript>
115		var loc = {};
116		loc.filters = filterChain(arguments.type);
117		loc.iEnd = ArrayLen(loc.filters);
118		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
119		{
120			loc.filter = loc.filters[loc.i];
121			if ((!Len(loc.filter.only) && !Len(loc.filter.except)) || (Len(loc.filter.only) && ListFindNoCase(loc.filter.only, arguments.action)) || (Len(loc.filter.except) && !ListFindNoCase(loc.filter.except, arguments.action)))
122			{
123				if (!StructKeyExists(variables, loc.filter.through))
124					$throw(type="Wheels.filterNotFound", message="Wheels tried to run the `#loc.filter.through#` function as a #arguments.type# filter but could not find it.", extendedInfo="Make sure there is a function named `#loc.filter.through#` in the `#variables.$class.name#.cfc` file.");
125				loc.result = $invoke(method=loc.filter.through, invokeArgs=loc.filter.arguments);
126				// if the filter function returned false or rendered content we skip the remaining filters in the chain
127				if ((StructKeyExists(loc, "result") && !loc.result) || $performedRenderOrRedirect())
128					break;
129			}
130		}
131	</cfscript>
132</cffunction>