Files
2025-09-14 12:09:18 +03:00

181 lines
6.4 KiB
Plaintext

<!--- version 2.01---><!---15:25 31.01.2019--->
<!--- 2017.06.16 исправлен баг с очисткой при числовом значении по умолчанию --->
<!---v0.5 10:02 02.01.2019--->
<cfassociate basetag="cf_filter_settings"/>
<cfparam name="ATTRIBUTES.filter" type="struct" default=#getBaseTagData("CF_FILTER_SETTINGS",1).filter#/><!--- *** possible Railo bug, getBaseTagData works only with second parameter --->
<cfparam name="ATTRIBUTES.param" type="string"/>
<cfparam name="ATTRIBUTES.default" type="string" default=""/><!--- список: значения, установленные по умолчанию. Обычно состоит из 1 значения даже для списка. В случае кодирования base64 этот список НЕ кодируется (проблемы с запятыми остаются на совести разработчика)--->
<!---*** И вообще Base64 нельзя использовать непосредственно, он не URLsafe --->
<cfparam name="ATTRIBUTES.ftype" type="string" default="string"/>
<cfparam name="ATTRIBUTES.list" type="boolean" default="No"/>
<cfparam name="ATTRIBUTES.compare" type="string" default="EQ"/>
<cfparam name="ATTRIBUTES.field" type="string" default=""/>
<cfparam name="ATTRIBUTES.base64" type="boolean" default="No"/><!--- означает, что параметр нужно раскодировать из base64---><!---*** Переделать на URL-safe base64--->
<!---
CFQUERYPARAM CFSQLTYPE="CF_SQL_VARCHAR" ставит апострофы вокруг значения параметра.
Поэтому приходится любые wildcards засовывать в значение bind variable. Запрос должен иметь вид
SELECT A,B FROM C WHERE A LIKE ?
(без всяких апострофов), а значение параметра будет, например,
"%#submitted_string#%"
--->
<cfparam name="ATTRIBUTES.prefix" type="string" default=""/>
<cfparam name="ATTRIBUTES.suffix" type="string" default=""/>
<cfparam name="ATTRIBUTES.expression" type="string" default=""/>
<!---
Хранение данных для списков
переделано обратно с массива на лист.
При этом случилась забавная, но неприятная и трудноуловимая ошибка
arrayAppend(array,item) механически заменил на listAppend(list,item)
а надо было на list=listAppend(list,item)
--->
<!---<cfif ATTRIBUTES.list>
<cfset def = "">
<cfloop list=#ATTRIBUTES.default# index="item">
<cfset listAppend(def, item)>Список значений по умолчанию НЕ должен быть кодирован в base64 при ATTRIBUTES.base64
</cfloop>
<cfelse>
</cfif>--->
<cfset def=ATTRIBUTES.default/>
<!---<cfoutput>#ATTRIBUTES.param#:</cfoutput>--->
<!---<cfif evaluate("isDefined('CALLER.#ATTRIBUTES.param#')")>
<cfset evaluate("val=(CALLER.#ATTRIBUTES.param#)")>--->
<cfif structKeyExists(CALLER, '#ATTRIBUTES.param#')>
<cfset val=structFind(CALLER, '#ATTRIBUTES.param#')/>
<!--- parse --->
<cfset to=1/>
<cfset values = ""/>
<cfif ATTRIBUTES.list>
<cfset to=listLen(val)/>
</cfif>
<cfloop from="1" to=#to# index="i">
<cfif ATTRIBUTES.list>
<cfset element=listGetAt(val,i)/>
<cfelse>
<cfset element=val/>
</cfif>
<cfswitch expression=#ATTRIBUTES.ftype#>
<cfcase value="numeric">
<cfset element=trim(element)>
<cfif NOT isNumeric(element)>
<cfset element=def/>
</cfif>
</cfcase>
<cfcase value="guid">
<cfset element=trim(element)>
<cfif NOT isValid('guid',element)>
<cfset element=def/>
</cfif>
</cfcase>
<cfcase value="date">
<cftry>
<cfset element=CreateDateTime(ListGetAt(element,3,'.'), ListGetAt(element,2,'.'), ListGetAt(element,1,'.'),0,0,0)>
<cfcatch type="Any">
<!--- <cfoutput>#cfcatch.message# #cfcatch.detail#</cfoutput> --->
</cfcatch>
</cftry>
</cfcase>
<cfcase value="string">
<cfif ATTRIBUTES.base64>
<cfset element=ToString(BinaryDecode(element , "base64"))>
</cfif>
<cfset element=safeStr(element)/>
</cfcase>
<cfdefaultcase>
<cfthrow message="Filterparam: unsupported ftype value '#ATTRIBUTES.ftype#'" detail="Supported values are 'numeric', 'date', 'string'">
</cfdefaultcase>
</cfswitch>
<cfif ATTRIBUTES.list>
<cfset values=listAppend(values, element)/>
<cfelse>
<cfset val=element/>
<cfbreak/>
</cfif>
</cfloop>
<cfif ATTRIBUTES.list>
<cfset val=values/><!---*** все это выглядит ужасно. Переиспользование переменных вперед-назад, IF вокруг листа--->
</cfif>
<!---/parse --->
<cfelseif structKeyExists(ATTRIBUTES.filter, ATTRIBUTES.param)><!--- если параметр есть в сохраненном фильтре, взять оттуда --->
<cfset filterItem = structFind(ATTRIBUTES.filter, ATTRIBUTES.param)>
<cfif isStruct(filterItem)>
<cfset val=filterItem.val>
<cfelse><!---not struct <cfoutput>#ATTRIBUTES.param#</cfoutput>--->
<cfset val=def>
</cfif>
<cfelse>
<cfset val=def>
</cfif>
<cfset setVariable("CALLER.#ATTRIBUTES.param#", "")/>
<cftry>
<cfset setVariable("CALLER.#ATTRIBUTES.param#",#val#)/>
<cfcatch type="Any"></cfcatch>
</cftry>
<cfif shouldRemoveValue(val, def)>
<cfset structDelete(ATTRIBUTES.filter, ATTRIBUTES.param)/>
<cfelse>
<cfset fltItem=structNew()>
<cfset fltItem.ftype=ATTRIBUTES.ftype>
<cfset fltItem.list=ATTRIBUTES.list>
<cfset fltItem.field=ATTRIBUTES.field>
<cfset fltItem.compare=ATTRIBUTES.compare>
<cfset fltItem.val=val>
<cfset fltItem.prefix=ATTRIBUTES.prefix/>
<cfset fltItem.suffix=ATTRIBUTES.suffix/>
<cfset fltItem.expression=ATTRIBUTES.expression/>
<cfset structInsert(ATTRIBUTES.filter,ATTRIBUTES.param,fltItem, "TRUE")>
</cfif>
<cfexit method="exittag"/>
<cffunction name="shouldRemoveValue" returnType="boolean">
<cfargument name="val"/>
<cfargument name="def"/>
<!---<cfdump var=#val#> <cfdump var=#def#>--->
<cfscript>
if (!IsSimpleValue(val)){
if (isArray(val)) {
return (arrayLen(val) == 0);
}
return false;
}
return ((val==def) OR (val==""));
</cfscript>
</cffunction>
<cffunction name="safeStr" returnType="string">
<cfargument name="val" type="string"/>
<cfreturn replaceList(val, "',"",<,>", ",,,")/>
</cffunction>