Two possible suggestions... which may or may not work depending on your array structure (it looks like it's a 2-dimensional array... but it's unclear why, or what's in the other child elements).
First, you could use structures instead of arrays. If you set up structures, like:
Code:
strPermissionDeny["some_function_id"]
:
and
Code:
strPermissionAccess["some_function_id"]
:
then you would only have to have one loop, and use StructFind to see if there was a match:
Code:
<CFLOOP collection="#strPermissionDeny#" item="whichFunction">
<CFIF StructFind(strPermissionAccess,whichFunction)>
<CFSET StructDelete(strPermissionAccess, whichFunction)>
</CFIF>
</CFLOOP>
or, even faster, since StructDelete() doesn't throw an error if the key you're trying to delete doesn't actually exist, you could do without the StructFind():
Code:
<CFLOOP collection="#strPermissionDeny#" item="whichFunction">
<CFSET StructDelete(strPermissionAccess, whichFunction)>
</CFLOOP>
Second option, if structures won't work for you, use ArrayToList() to temporarily make the array a little easier to manage:
Code:
<CFSET lstDeny = ArrayToList(strPermissionDeny)>
<CFSET lstAccess = ArrayToList(strPermissionAccess)>
<CFLOOP list="#lstDeny#" index="whichFunction">
<CFSET nFunctionPos = ListFindNoCase("#strPermissionAccess#",whichFunction)>
<CFIF nFunctionPos GT 0>
<CFSET lstAccess = ListDeleteAt("#lstAccess#",nFunctionPos)>
</CFIF>
</CFLOOP>
Of course, I might also look at why you're using two arrays. If you were to use a structure, you could simply store a flag as to whether a given function was granted or denied... and keep it all in the same object:
Code:
<CFSCRIPT>
strFunctionAccess = StructNew();
strFunctionAccess["1234"] = true;
strFunctionAccess["5678"] = false;
strFunctionAccess["ABCD"] = true;
strFunctionAccess["EFGH"] = true;
</CFSCRIPT>
so this user would be granted permission to use functions "1234","ABCD", and "EFGH"... but not "5678". So when it comes time to check whether a function should process or be displayed, you simply do:
Code:
<CFIF strFunctionAccess["#function_id#"]>
<!--- perform functionality --->
:
<CFELSE>
Sorry, you don't have permission to do that!
</CFIF>
You can easily store other information about the function, if you wish (like I guess you're doing in the other dimension of your current array), by making the element in the structure a child/nested structure:
Code:
<CFSCRIPT>
strFunctions = StructNew();
strFunctions["1234"] = StructNew();
strFunctions["1234"]["permitted"] = true;
strFunctions["1234"]["name"] = "Delete Record";
strFunctions["1234"]["url"] = "/utilities/delete_record.cfm";
strFunctions["1234"]["email"] = "admin@mydomain.com";
:
</CFSCRIPT>
A third option could be to set up a query... if that would be advantageous. So you'd have a resultset like:
Code:
function_id permitted name
------------------------------------------------
1234 y delete record
5678 n update record
you can do this dynamically with something like:
Code:
<CFSCRIPT>
qryFunctions = QueryNew("function_id, permitted, name");
QueryAddRow(qryFunctions,1);
QuerySetCell(qryFunctions,"function_id","1234",1);
QuerySetCell(qryFunctions,"permitted","y",1);
QuerySetCell(qryFunctions,"name","delete record",1);
QuerySetCell(qryFunctions,"function_id","5678",1);
QuerySetCell(qryFunctions,"permitted","n",1);
QuerySetCell(qryFunctions,"name","update record",1);
:
</CFSCRIPT>
then you'd only have to run a query-on-query, like:
Code:
<CFQUERY name="qryPermitted" dbtype="query">
SELECT *
FROM qryFunctions
WHERE function_id = '#sFunctionID#'
</CFQUERY>
<CFIF qryPermitted.RecordCount GT 0 AND qryPermitted.permitted EQ 'y'>
<!--- proceed --->
<CFELSE>
Sorry, you're not permitted to do that.
</CFIF>
-Carl