JC Panzerpants asks:

Hey Ray! I've been googling for a good 45 minutes trying to find a way to do this... maybe you know off the top of your head. Is there a way for a CF file to determine how it's being accessed? Like, directly vs cfincluded vs cfmoduled etc. Mostly I'm interested in if it can tell whether it's being accessed directly or not, but being able to tell what the parent file is that's calling it would be useful too.

I'm trying to convert an old, big, messy 1000+ line application.cfm file into something readable, functional, and able to be edited without cringing in fear that one change might break other parts.

I'm absolutely sure I've seen a way to do this before, but all I've been able to find is the executionmode function for custom tags, which is nice, but not what I'm looking for...

Well there are a few things going on here and a few things we can try. For the simplest check - how can you tell a custom tag? One quick way is just do:

<cfif isDefined("attributes")>

This used to be sufficient, but don't forget that you also get an attributes scope inside cfthread. So the better check may be:

<cfif isDefined("attributes") and not isDefined("thread")>

Now, as to checking a cfincluded template, the only way I know of is to compare getBaseTemplatePath to getCurrentTemplatePath. getBaseTemplatePath always gets the "core" CFM whereas getCurrentTemplatePath returns the "active" one. I put this and the earlier code block together to form this:

<cfif isDefined("attributes") and not isDefined("thread")> I seem to be a custom tag. <cfelseif getBaseTemplatePath() neq getCurrentTemplatePath()> I seem to be an include <cfelse> I seem to be vanilla code. </cfif>

I then wrote this test:

<h2>Root</h2>

<cfif isDefined("attributes") and not isDefined("thread")> I seem to be a custom tag. <cfelseif getBaseTemplatePath() neq getCurrentTemplatePath()> I seem to be an include <cfelse> I seem to be vanilla code. </cfif>

<h2>CFInclude</h2>

<cfinclude template="test2.cfm">

<h2>Custom Tag</h2>

<cf_simpletag>

The contents of test2.cfm were the CFIF. Ditto in simpletag.cfm. The result seemed fine to me:

As for getting the immediate parent, that isn't quite as easy. If test1.cfm includes test2.cfm and test2.cfm includes test3.cfm, your base template path in test3.cfm will go all the way up to test1.cfm. The only way I know of to get that lineage in that case is with a try/catch and introspecting the tag context array.