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