spec/lib/filterparam.cfm
2025-06-02 16:16:51 +03:00

174 lines
6.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--- 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="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>