Files
ipwhitelist-app/research/payg-sso-full/lib/data/del.cfm
T

297 lines
12 KiB
Plaintext

<cfsilent>
<!--- v0.4---><!---9:50 06.10.2020--->
<!--- v0.5---><!---2024-12-11 15:10:07--->
<!--- DEL.CFM - унифицированный шаблон операции удаления записи --->
<cfimport prefix="m" taglib="../../lib"/>
<cfimport prefix="m" taglib="../../lib/controls"/>
</cfsilent><cfif thisTag.executionMode IS "end" OR !thisTag.hasEndTag><m:silent silent="No">
<cfparam name="ATTRIBUTES.savemarker" type="string" default="delete"/>
<cfparam name="ATTRIBUTES.readonly" type="boolean" default="No"/>
<cfparam name="ATTRIBUTES.checkQuery" type="string" default="select 0 as chk"/> <!--- запрос проверки целостности.
Простая строка (параметр преобразуется до вызова тега).
Если можно удалять, должен вернуть 0 в поле chk --->
<cfparam name="ATTRIBUTES.displayDependencies" type="boolean" default="Yes"/>
<cfparam name="ATTRIBUTES.ignoreDependencies" type="boolean" default="No"/><!--- будем удалять, несмотря на наличие зависимостей Предположительно, мы примем меры в запросе удаления, или расчитываем на каскадное удаление. Имеет смысл, видимо, только в комбинации с displayDependencies=TRUE, иначе зачем описывать зависимости и потом их игнорировать. --->
<cfparam name="ATTRIBUTES.entity" type="string"/>
<cfparam name="ATTRIBUTES.accessObj" type="string" default="#ATTRIBUTES.entity#"/> <!--- объект доступа, права к которому проверяем --->
<cfparam name="ATTRIBUTES.deleteQuery" type="string" default=""/> <!--- запрос удаления *** надо бы параметризовать --->
<cfparam name="ATTRIBUTES.confirmMessage" type="string"/> <!--- текст для javascript:confirm() --->
<cfparam name="ATTRIBUTES.denyMessage" type="string" default="Удаление невозможно, существуют зависимые записи."/> <!---
сообщение о невозможности удаления записи (если проверка целостности говорит нельзя) --->
<cfparam name="ATTRIBUTES.queryString" type="string" default=""/>
<cfparam name="ATTRIBUTES.defaultBackUrl" type="string" default="#ATTRIBUTES.entity#_ls.cfm"/>
<cfparam name="ATTRIBUTES.output" type="string" default=""/>
<cfparam name="ATTRIBUTES.status" type="string" default=""/>
<cfparam name="thisTag.dependencies" type="array" default=#arrayNew(1)#/>
<cfparam name="thisTag.conditions" type="array"/>
<cfset "CALLER.#ATTRIBUTES.status#"=CreateObject("component","status").init(false,"","")/>
<cfif len(ATTRIBUTES.queryString) EQ 0>
<cfset i = 0 />
<cfloop array=#thisTag.conditions# index="condition">
<cfif i GT 0>
<cfset ATTRIBUTES.queryString="#ATTRIBUTES.queryString#&"/>
</cfif>
<cfset i = i+1/>
<cfset ATTRIBUTES.queryString="#ATTRIBUTES.queryString##condition.field#=#condition.value#"/>
</cfloop>
</cfif>
<m:track
thisURL="#request.thisPage#?#ATTRIBUTES.queryString#"
defaultBackUrl="#ATTRIBUTES.defaultBackUrl#"
output="tr"
/>
<cfquery name="qCheck" datasource="#request.DS#">
#preserveSingleQuotes(ATTRIBUTES.checkQuery)#
</cfquery>
<cfset sDenyMessage=""/>
<cfoutput query="qCheck">
<cfset sDenyMessage=evaluate("""#ATTRIBUTES.denyMessage#""")/>
</cfoutput>
<!--- быстрая проверка --->
<cfset dependentRecordsExist = false/>
<cfloop array=#thisTag.dependencies# index="dep">
<cfif dep.query.recordCount GT 0>
<cfset dependentRecordsExist = true/>
<cfbreak/>
</cfif>
</cfloop>
<!--- do delete --->
<m:ac obj="#ATTRIBUTES.accessObj#" act="#request.PERMISSION_WRITE#" output="writePermitted">
<cfset doSave = false/>
<cfif !ATTRIBUTES.readonly>
<cfloop list=#ATTRIBUTES.savemarker# index="marker">
<cfif structKeyExists(FORM,"#marker#")><!--- удаление можно делать только постом --->
<cfset doSave = true/>
<cfbreak/>
</cfif>
</cfloop>
</cfif>
<cfif doSave AND qCheck.chk EQ 0>
<cftry> <!--- <cfoutput> <cfset i = 0 />
<cfloop list=#ATTRIBUTES.deleteQuery# delimiters="?" index="queryPart">
<cfif i GT 0>
cfqueryparam
cfsqltype='#condition.cfsqltype#'
value='#condition.value#'
null='#condition.null#'/
</cfif><cfset i = i + 1/>*#queryPart#* #i#
</cfloop>
</cfoutput> --->
<cfquery name="qDel" datasource="#request.DS#" result="result">
<cfif len(ATTRIBUTES.deleteQuery)>
<!--- запрос удаления должен быть сформулирован так,
чтобы условия удаления были в конце --->
<cfset i = 0 />
<cfloop list=#ATTRIBUTES.deleteQuery# delimiters="?" index="queryPart">
<cfif i GT 0>
<cfqueryparam
cfsqltype='#condition.cfsqltype#'
value='#condition.value#'
null='#condition.null#'/>
</cfif><cfset i = i + 1/>#queryPart#
</cfloop>
<cfelse>
delete from #ATTRIBUTES.entity# where /**/
<cfset i = 0 />
<cfloop array=#thisTag.conditions# index="condition">
<cfif i GT 0> AND </cfif>
<cfset i = i + 1/>
#condition.expression#=<cfqueryparam
cfsqltype='#condition.cfsqltype#'
value='#condition.value#'
null='#condition.null#'/>
</cfloop>
</cfif>
</cfquery>
<!--- *** неуклюжий костыль --->
<cfset CALLER.saveAndClose = true/><!--- сигнал для закрытия экрана --->
<cfcatch type="database">
<cfset "CALLER.#ATTRIBUTES.status#.errorState"=true/>
<cfset "CALLER.#ATTRIBUTES.status#.errorMessage"="Ошибка при обращении к базе данных. #cfcatch.message# #cfcatch.detail# #cfcatch.tagcontext[1].template# line #cfcatch.tagcontext[1].line#"/>
<!--- <cfrethrow/> --->
</cfcatch>
</cftry>
</cfif>
</m:ac>
<cfif !writePermitted><!--- перетирания cfcatch не будет --->
<cfset "CALLER.#ATTRIBUTES.status#.errorState"=true/>
<cfset "CALLER.#ATTRIBUTES.status#.errorMessage"="Ваших полномочий недостаточно для выполнения данной операции."/>
</cfif>
<!--- print output --->
<cfsavecontent variable="markup">
<cfoutput>
<div class="container-fluid">
<div class="row">
<br>
<form name="frmDel" action="#request.thisPage#" method="POST">
<cfif NOT writePermitted>
<!--- ситуация возможна при прямом заходе по URL. Надо высказать юзарю свое неодобрение. --->
<!--- <h4 class="text-danger">Ваших полномочий недостаточно для выполнения данной операции.</h4>
<br/> --->
<cfelseif qCheck.chk GT 0>
<h4 class="text-danger">#ATTRIBUTES.denyMessage#</h4>
<br/>
<cfelseif dependentRecordsExist>
<cfif ATTRIBUTES.displayDependencies>
<h4 class="text-danger">#ATTRIBUTES.denyMessage#</h4>
<br/>
<cftry>
<cfloop array=#thisTag.dependencies# index="dep">
<cfif dep.query.recordCount GT 0>
<h5>#dep.title#</h5>
<cfif dep.showDetails>
<table class="worktable">
<thead>
<tr>
<th width="1%" class="c"></th>
<cfloop array=#dep.fields# item="fld">
<cfif len(fld.title)>
<th>#fld.title#</th>
</cfif>
</cfloop>
<th width="1%"></th>
</tr>
</thead>
<cfoutput query=#dep.query#>
<cfset urlQueryString=""/>
<cfloop array=#dep.keys# index="keyName">
<cfif len(urlQueryString)>
<cfset urlQueryString="#urlQueryString#&"/><!---***--->
</cfif>
<cfset urlQueryString="#urlQueryString##keyName#=#dep.query[keyName][currentRow]#"/>
</cfloop>
<tr>
<td>
<a href="#dep.page#?#urlQueryString#&#tr.fwx#" <!---class="far fa-edit"--->><img src="img/edit.gif"/></a>
</td>
<cfloop array=#dep.fields# item="fld">
<cfif len(fld.title)>
<td>
<cfif isDefined("fld.formatter")>
#fld.formatter(dep.query[fld.name][currentRow])#
<cfelse>
#dep.query[fld.name][currentRow]#
</cfif>
</td>
</cfif>
</cfloop>
<td>
<a href="#dep.delete_page#?#urlQueryString#&#tr.fwx#" <!---class="far fa-trash-alt text-danger"--->><img src="img/del.gif"/></a>
</td>
</tr>
</cfoutput>
</table>
<cfelse><!---dep.showDetails--->
<cfoutput><p>#dep.denyMessage# (#dep.query.recordCount#)</p></cfoutput>
</cfif><!---dep.showDetails--->
</cfif>
</cfloop>
<cfcatch type="any">
<cfoutput>#cfcatch.message# #cfcatch.detail# #cfcatch.tagcontext[1].template# line #cfcatch.tagcontext[1].line#/></cfoutput><cfrethrow/>
</cfcatch>
</cftry>
<cfelse><!---ATTRIBUTES.displayDependencies--->
<cfoutput>#ATTRIBUTES.denyMessage#</cfoutput>
</cfif><!---ATTRIBUTES.displayDependencies--->
</cfif>
<cfif NOT dependentRecordsExist OR ATTRIBUTES.ignoreDependencies><!--- qCheck.chk GT 0 | dependentRecordsExist --->
<cfif writePermitted>
<input type="hidden" name="track" value="#tr.self#">
<cfloop array=#thisTag.conditions# index="condition">
<!---<input type="hidden" name="#condition.expression#" value="#evaluate('#condition.expression#')#"/>--->
<input type="hidden" name="#condition.field#" value="#evaluate('#condition.field#')#"/><!--- по замыслу, берется из скоупа FORM (*** слишком неявно)--->
</cfloop>
<button type="submit" class="maincontrol btn btn-secondary" name="delete" onclick="if(!confirm('#evaluate("""#ATTRIBUTES.confirmMessage#""")#')) return false;">Удалить</button>
</cfif>
</cfif>
<button type="button" class="maincontrol btn btn-secondary" name="close" onclick="document.location.href='#tr.backURL#'">
Закрыть
</button>
<!--- <cfdump var=#dependentRecordsExist#/>
<cfdump var=#ATTRIBUTES.ignoreDependencies#/>
<cfdump var=#NOT dependentRecordsExist OR ATTRIBUTES.ignoreDependencies#/> --->
</form>
</div>
</div>
</cfoutput>
</cfsavecontent>
</m:silent><cfif len(ATTRIBUTES.output)><cfset "CALLER.#ATTRIBUTES.output#" = #markup#/><cfelse>
<cfoutput>#markup#</cfoutput>
</cfif></cfif>
<!--- пример монструозной конструкции Postgre для каскадного удаления --->
<!--- with
inst as (
delete from instance
where instance_uid='e283e337-0ddc-459c-88b8-57d1963b4a7d'
returning instance_uid
),
st as (
delete from instance_state
where instance_uid in (select instance_uid from inst)
returning instance_state_uid
),
op as (
delete from instance_operation
where instance_uid in (select instance_uid from inst)
returning instance_operation_uid
),
par as (
delete from instance_operation_param
where instance_operation_uid in (select instance_operation_uid from op)
returning instance_operation_param_uid
),
cfs as (
delete from instance_operation_cfs_param
where instance_operation_uid in (select instance_operation_uid from op)
returning instance_operation_cfs_param_uid
)
select * from inst
left outer join st on (inst.instance_uid=st.instance_uid)
left outer join op on (inst.instance_uid=op.instance_uid)
left outer join par on (op.instance_operation_uid=par.instance_operation_uid)
left outer join cfs on (op.instance_operation_uid=cfs.instance_operation_uid)
; --->
<!--- такой вопрос: точно ли будут задействованы все CTE, если я на них не сошлюсь? На месте оптимизатора я бы проигнорил незадействованные. Наверное, надо все включить в джойн для уверенности? --->