ColdFusion function variable naming with [ ] brackets - coldfusion

I've got a ColdFusion handler that is taking in 3 arguments one of which is a structure. The issue I'm facing is one of the variable name contains brackets which is an illegal character in the naming of a cfargument, see example.
chargifyResponse&id=123456&event=test&payload[chargify]=testing
Any suggestions would be greatly appreciated!
Code
<cffunction name="Webhook" access="remote" output="false">
<cfargument name="id" required="false" type="string" />
<cfargument name="event" required="false" type="string" />
<cfargument name="payload&##91;chargify&##93;" required="false" type="any"/>
...
Error
Attribute validation error for CFARGUMENT.
The value of the NAME attribute is invalid.

Related

how to pass the data of the function to a custom tag attribute

My Custom tag expects a “query” in one of the attribute but my cfc function returns me the structure when I dump it. This is my function listScores()
<cffunction name="listScores" access="public" output="false" returntype="any"> <!--- not really scores, should probably rename this function - something to consider --->
<cfargument name="link" type="string" required="false" />
<cfargument name="linktype" type="numeric" required="false" default="2" /> <!--- 2 = ace inspection -> ace action--->
<cfargument name="reftype" type="numeric" required="false" default="2" /> <!--- 2 = equipment --->
<cfargument name="siteid" type="numeric" required="false" />
<cfargument name="archived" type="numeric" required="false" default="0" /> <!--- 0 = not archived --->
<cfargument name="acerefid" type="numeric" required="false" hint="ace_links refid" />
<cfargument name="apprefid" type="numeric" required="false" hint="equip tracker refid" />
<cfargument name="responseType" type="string" require="false" />
<cfif structKeyExists(arguments,'responseType') && arguments.responseType is 'query'>
<cfreturn OCRUD.listScores(argumentCollection=arguments) />
</cfif>
<cfreturn getArrayFromQuery(OCRUD.listScores(argumentCollection=arguments)) />
</cffunction>
When i dump the iEngine.listScores() i get the structure output.
I want to pass this iEngine.listScores() data to the custom tag which expects a query.
<cfmodule template="#request.library.customtags.virtualpath#excel.cfm" file="#filename#" sheetname="ACE Report">
<cfmodule template="#request.library.customtags.virtualpath#exceldata.cfm"
query="#variables.qlistScoreData#"
action="AddWorksheet"
sheetname="ACE Report"
colorscheme="blue"
useheaders="true"
contentformat="#{bold=true}#"
<!--- customheaders="#ListScore#" --->
>
<cfoutput>Excel Extract - ACE Report - #DateFormat(Now(),"d-mmm-yyyy")#</cfoutput>
</cfmodule>
</cfmodule>

"Variable TotalCorpAudits is undefined" when invoking a function from cfc

I am getting Variable undefined error when i try to invoke a function from a cfc.
The best part is it is already defined above.
"IandI" is the cfc name.
Code snippet :
<cfparam name="TotalCorpAudits" default="0">
<cfset TotalAudits = TotalSiteAudits + TotalCorpAudits>
<cfinvoke component="#IandI#"
method="calcRate"
Cases="#TotalCorpAudits#"
Hours="#TotalAudits#"
iiFactor="1"
convertToPercent="true"
NumberFormatOn="true"
returnOnZeroHours="0"
returnOnNonNumericData="0"
returnvariable="TotalCorpRatioAudits"
>
Getting error at ... Cases="#TotalCorpAudits#"
CFC Code :
<cffunction name="calcRate" access="public" returntype="string"
displayname="calcs Rate" hint="" description="">
<cfargument name="Hours" required="Yes" type="string">
<cfargument name="Cases" required="Yes" type="string">
<cfargument name="IIFactor" required="No" type="numeric" default="200000">
<cfargument name="FormatMask" required="No" type="string" default="999.99">
<cfargument name="NumberFormatOn" required="No" type="boolean" default="false">
<cfargument name="returnOnZeroHours" required="No" type="string" default="0">
<cfargument name="returnOnNonNumericData" required="No" type="string" default="N/A">
<cfargument name="returnOnZeroCasesWithHours" required="No" type="string" default="0">
<cfargument name="convertToPercent" required="No" type="boolean" default="false">
CFINVOKE works like so:
<cfinvoke component="[CFC_FileName]" method="calcRate" returnvariable="TotalCorpRatioAudits">
<cfinvokeargument name="Hours" value="[whateverValueYouWant]">
<cfinvokeargument name="Cases" value="[whateverValueYouWant]">
</cfinvoke>
Notice a couple things: <cfinvokeargument> is underneath the <cfinvoke> tag. Also, I only used those two argument since they were required in the CFC, but you can add more if needed. Use https://wikidocs.adobe.com/wiki/display/coldfusionen/cfinvoke as a reference.
is the name of component comeing from a variables? Is IandI a variable? If it is not you dont have to wrap it in # signs. And that is what I think is causing the problem.
I've run into this a few times lately; it definitely seems like a bug in the ColdFusion engine. Seems as if the compiler is trying to evaluate the variable from within the CFC, rather than the calling page.
I've been able to work around it by defining my struct of arguments beforehand, then simply including the struct in the invoke().
<cfset argStruct = {argName1=val1,argName2=val2,argName3="hardcodedValue"}>
<cfinvoke component="cfcPath" method="methodName" argumentCollection="#argStruct#" />

Coldfusion CFINVOKE parameter not working?

I want to invoke a cfc file on my webserver, but I always get the error: The required parameter [UserID] was not provided.
Coldfusion code:
<CFINVOKE component="changeTree" method="getTreeWidth" returnVariable="httpTreeWidth">
<cfinvokeargument name="UserID" value="#checklogin.UserID#">
</CFINVOKE>
changeTree.cfc:
<CFFUNCTION name="getTreeWidth">
<CFPARAM name="UserID" required="true">
...
Thanks for help.
In changeTree.cfc, it's suppposed to be <cfargument name="UserID" required="true"> not <cfparam>.

How To Share Query Data Between Two ColdFusion CFCs?

I am creating a CFC called "core_appdata". This CFC will hold the core stored procedures for an application. Example....
<cfcomponent displayname="core_appdata" hint="I Return Core App Data" output="no">
<cffunction name="getprogram_list">
<cfargument name="getstoredproc_input_campaignid" type="string" required="false">
<cfargument name="getstoredproc_input_filtertestrecs" type="string" required="false">
<cfargument name="getstoredproc_input_startdate" type="date" required="false">
<cfargument name="getstoredproc_input_enddate" type="date" required="false">
<cfargument name="getstoredproc_input_listtypeid" type="string" required="false">
<cfargument name="getstoredproc_input_listid" type="string" required="false">
<cfargument name="getstoredproc_input_appenvr" type="string" required="false">
<cfset var rst_getprogram_list ="">
--- stored proc ---
<cfstoredproc procedure = "p_adb_getprogram_list">
</cfstoredproc>
<cfreturn rst_getprogram_list />
</cffunction>
</cfcomponent>
I would also like to create a CFC called "core_appdata_grids". This CFC would be used to bind to cfgrids and allow paging etc. In a perfect world, this CFC would get its data from the method/function "getprogram_list" in the CFC "core_appdata" above. Example...
<cfcomponent displayname="core_appdata_grids" hint="I Return Core App Data For CFGrids " output="no">
<cffunction name="getprogram_list_grid">
<cfargument name="page" required="no" />
<cfargument name="pageSize" required="no" />
<cfargument name="gridsortcolumn" required="no" />
<cfargument name="gridsortdirection" required="no" />
<cfargument name="getstoredproc_input_campaignid" type="string" required="false">
<cfargument name="getstoredproc_input_filtertestrecs" type="string" required="false">
<cfargument name="getstoredproc_input_startdate" type="date" required="false">
<cfargument name="getstoredproc_input_enddate" type="date" required="false">
<cfargument name="getstoredproc_input_listtypeid" type="string" required="false">
<cfargument name="getstoredproc_input_listid" type="string" required="false">
<cfargument name="getstoredproc_input_appenvr" type="string" required="false">
<cfset var rst_getprogram_list_grid ="">
--- get data ---
<cfreturn queryconvertforgrid(rst_getprogram_list_grid, page, pagesize) />
</cffunction>
</cfcomponent>
Questions:
Is this possible? If so, how is it done?
If so, is this best practice when working with CFCs?
If not, what is the best way to share data between CFCs
Thank you in advance for your time in helping me with this question.
OC
I can't see the name of the cfc that produces the grid but just extend the base cfc which will inherit all the methods.
<cfcomponent extends="core_appdata">
<cffunction name="getprogram_list_grid">
<cfargument name="page" required="no" />
<cfargument name="pageSize" required="no" />
<cfargument name="gridsortcolumn" required="no" />
<cfargument name="gridsortdirection" required="no" />
<cfargument name="getstoredproc_input_campaignid" type="string" required="false">
<cfargument name="getstoredproc_input_filtertestrecs" type="string" required="false">
<cfargument name="getstoredproc_input_startdate" type="date" required="false">
<cfargument name="getstoredproc_input_enddate" type="date" required="false">
<cfargument name="getstoredproc_input_listtypeid" type="string" required="false">
<cfargument name="getstoredproc_input_listid" type="string" required="false">
<cfargument name="getstoredproc_input_appenvr" type="string" required="false">
<cfset var rst_getprogram_list_grid = super.getprogram_list() />
<cfreturn queryconvertforgrid(rst_getprogram_list_grid, page, pagesize) />
</cffunction>
</cfcomponent>
If you don't want to extend the CFC, especially if that's not being true to your model, you could just call the other CFC:
<cfset var rst_getprogram_list_grid = createObject("component","core_appdata").getprogram_list() />
OR even better somewhere above it all set:
<cfset request.core_appdata=createObject("component","core_appdata")>
And then in your CFC:
<cfset var rst_getprogram_list_grid = request.core_appdata.getprogram_list() />
Just a few options.

Can you reassign the default <cfargument in a cfc?

I'm invoking a cfc, the cfc has a default set of arguments like so:
<cfargument name="EMAIL_TEMPLATE_CODE" type="string" required="yes" hint="EMAIL_TEMPLATE_CODE is required.">
<cfargument name="EMAIL_TEMPLATE_SUBJECT" default="" type="string" required="no" hint="EMAIL_TEMPLATE_SUBJECT is NOT required.">
<cfargument name="EMAIL_TEMPLATE_BODY" default="" type="string" required="no" hint="EMAIL_TEMPLATE_BODY is NOT required.">
What I'd like to do is make these arguments not requred (as you can see by required="no") but I'd like to reassign the arguments variable if needed.
So something like:
<cfargument name="EMAIL_TEMPLATE_CODE" type="string" required="yes" hint="EMAIL_TEMPLATE_CODE is required.">
<cfargument name="EMAIL_TEMPLATE_SUBJECT" default="" type="string" required="no" hint="EMAIL_TEMPLATE_SUBJECT is NOT required.">
<cfargument name="EMAIL_TEMPLATE_BODY" default="" type="string" required="no" hint="EMAIL_TEMPLATE_BODY is NOT required.">
<cfinvoke component="#Request.CFCPath#.email_template" method="getEmailTemplate" returnvariable="getEmailTemplate">
<cfinvokeargument name="EMAIL_TEMPLATE_CODE" value="#ARGUMENTS.EMAIL_TEMPLATE_CODE#">
</cfinvoke>
<cfif getEmailTemplate.RecordCount>
<cfparam name="ARGUMENTS.EMAIL_TEMPLATE_SUBJECT" default="#getEmailTemplate.EMAIL_TEMPLATE_SUBJECT#" type="string">
<cfparam name="ARGUMENTS.EMAIL_TEMPLATE_BODY" default="#getEmailTemplate.EMAIL_TEMPLATE_BODY#" type="string">
</cfif>
But I'm not able to override the default ARGUMENTS variable. Is there anything you can spot that I'm doing wrong?
EDIT:
I'm doing this because if no argument is passed to the cfc, I want to create one. I guess I should cfset a local variable if the argument doesn't have length?
<cfif Len(ARGUMENTS.EMAIL_TEMPLATE_ADDRESS_FROM)>
<cfset EMailTemplateAddressFrom = ARGUMENTS.EMAIL_TEMPLATE_ADDRESS_FROM>
<cfelse>
<cfset EMailTemplateAddressFrom = getEmailTemplate.EMAIL_TEMPLATE_ADDRESS_FROM>
</cfif>
<cfparam> works only if the variable has been undefined before. Your function parameters are not undefined, they just happen to have their default values. So you could do this:
<cffunction name="foo">
<cfargument name="arg" type="string" required="yes">
<cfargument name="opt" default="default" type="string" required="no">
<cfif arguments.opt eq "default">
<cfset arguments.opt = "whatever dynamic value">
</cfif>
</cffunction>
This way, if you don't supply "opt" (or deliberately set it to "default"), it will get assigned some kind of dynamic default value. And you can still make it empty, if you need.
Instead of "default", you could choose some other kind of improbable value that allows you to make a distinction between "not supplied" and "empty". (Sometimes I wish ColdFusion would support actual null values...)
<cfargument name="EMAIL_TEMPLATE_CODE" type="string"
default="#getEmailTemplate.EMAIL_TEMPLATE_ADDRESS_FROM#">
<cfargument name="EMAIL_TEMPLATE_SUBJECT" default="" type="string">
<cfargument name="EMAIL_TEMPLATE_BODY" default="" type="string">
or....
<cfargument name="EMAIL_TEMPLATE_CODE" type="string">
<cfargument name="EMAIL_TEMPLATE_SUBJECT" default="" type="string">
<cfargument name="EMAIL_TEMPLATE_BODY" default="" type="string">
<cfif NOT isDefined("arguments.EMAIL_TEMPLATE_CODE")>
<cfset arguments.EMAIL_TEMPLATE_CODE = getEmailTemplate.EMAIL_TEMPLATE_ADDRESS_FROM>
</cfif>
FYI, required="no" by default, so I usually don't specify it to the already verbose CFML. :)