PageRenderTime 15ms CodeModel.GetById 7ms app.highlight 2ms RepoModel.GetById 2ms app.codeStats 0ms

/wheels/controller/miscellaneous.cfm

http://raihan.googlecode.com/
ColdFusion | 199 lines | 185 code | 10 blank | 4 comment | 23 complexity | e196ef27d683d1fd42a58c7cfc71a516 MD5 | raw file
  1<!--- PUBLIC CONTROLLER REQUEST FUNCTIONS --->
  2
  3<cffunction name="sendEmail" returntype="any" access="public" output="false" hint="Sends an email using a template and an optional layout to wrap it in. Besides the Wheels-specific arguments documented here, you can also pass in any argument that is accepted by the `cfmail` tag as well as your own arguments to be used by the view."
  4	examples=
  5	'
  6		<!--- Get a member and send a welcome email, passing in a few custom variables to the template --->
  7		<cfset newMember = model("member").findByKey(params.member.id)>
  8		<cfset sendEmail(
  9			to=newMember.email,
 10			template="myemailtemplate",
 11			subject="Thank You for Becoming a Member",
 12			recipientName=newMember.name,
 13			startDate=newMember.startDate
 14		)>
 15	'
 16	categories="controller-request,miscellaneous" chapters="sending-email" functions="">
 17	<cfargument name="template" type="string" required="false" default="" hint="The path to the email template or two paths if you want to send a multipart email. if the `detectMultipart` argument is `false`, the template for the text version should be the first one in the list. This argument is also aliased as `templates`.">
 18	<cfargument name="from" type="string" required="false" default="" hint="Email address to send from.">
 19	<cfargument name="to" type="string" required="false" default="" hint="List of email addresses to send the email to.">
 20	<cfargument name="subject" type="string" required="false" default="" hint="The subject line of the email.">
 21	<cfargument name="layout" type="any" required="false" hint="Layout(s) to wrap the email template in. This argument is also aliased as `layouts`.">
 22	<cfargument name="file" type="string" required="false" default="" hint="A list of the names of the files to attach to the email. This will reference files stored in the `files` folder (or a path relative to it). This argument is also aliased as `files`.">
 23	<cfargument name="detectMultipart" type="boolean" required="false" hint="When set to `true` and multiple values are provided for the `template` argument, Wheels will detect which of the templates is text and which one is HTML (by counting the `<` characters).">
 24	<cfargument name="$deliver" type="boolean" required="false" default="true">
 25	<cfscript>
 26		var loc = {};
 27		$args(args=arguments, name="sendEmail", combine="template/templates/!,layout/layouts,file/files", required="template,from,to,subject");
 28
 29		loc.nonPassThruArgs = "template,templates,layout,layouts,file,files,detectMultipart,$deliver";
 30		loc.mailTagArgs = "from,to,bcc,cc,charset,debug,failto,group,groupcasesensitive,mailerid,maxrows,mimeattach,password,port,priority,query,replyto,server,spoolenable,startrow,subject,timeout,type,username,useSSL,useTLS,wraptext";
 31		loc.deliver = arguments.$deliver;
 32
 33		// if two templates but only one layout was passed in we set the same layout to be used on both
 34		if (ListLen(arguments.template) > 1 && ListLen(arguments.layout) == 1)
 35			arguments.layout = ListAppend(arguments.layout, arguments.layout);
 36
 37		// set the variables that should be available to the email view template (i.e. the custom named arguments passed in by the developer)
 38		for (loc.key in arguments)
 39		{
 40			if (!ListFindNoCase(loc.nonPassThruArgs, loc.key) && !ListFindNoCase(loc.mailTagArgs, loc.key))
 41			{
 42				variables[loc.key] = arguments[loc.key];
 43				StructDelete(arguments, loc.key);
 44			}
 45		}
 46
 47		// get the content of the email templates and store them as cfmailparts
 48		arguments.mailparts = [];
 49		loc.iEnd = ListLen(arguments.template);
 50		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
 51		{
 52			// include the email template and return it
 53			loc.content = $renderPage($template=ListGetAt(arguments.template, loc.i), $layout=ListGetAt(arguments.layout, loc.i));
 54			loc.mailpart = {};
 55			loc.mailpart.tagContent = loc.content;
 56			if (ArrayIsEmpty(arguments.mailparts))
 57			{
 58				ArrayAppend(arguments.mailparts, loc.mailpart);
 59			}
 60			else
 61			{
 62				// make sure the text version is the first one in the array
 63				loc.existingContentCount = ListLen(arguments.mailparts[1].tagContent, "<");
 64				loc.newContentCount = ListLen(loc.content, "<");
 65				if (loc.newContentCount < loc.existingContentCount)
 66					ArrayPrepend(arguments.mailparts, loc.mailpart);
 67				else
 68					ArrayAppend(arguments.mailparts, loc.mailpart);
 69				arguments.mailparts[1].type = "text";
 70				arguments.mailparts[2].type = "html";
 71			}
 72		}
 73
 74		// figure out if the email should be sent as html or text when only one template is used and the developer did not specify the type explicitly
 75		if (ArrayLen(arguments.mailparts) == 1)
 76		{
 77			arguments.tagContent = arguments.mailparts[1].tagContent;
 78			StructDelete(arguments, "mailparts");
 79			if (arguments.detectMultipart && !StructKeyExists(arguments, "type"))
 80			{
 81				if (Find("<", arguments.tagContent) && Find(">", arguments.tagContent))
 82					arguments.type = "html";
 83				else
 84					arguments.type = "text";
 85			}
 86		}
 87
 88		// attach files using the cfmailparam tag
 89		if (Len(arguments.file))
 90		{
 91			arguments.mailparams = [];
 92			loc.iEnd = ListLen(arguments.file);
 93			for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
 94			{
 95				arguments.mailparams[loc.i] = {};
 96				arguments.mailparams[loc.i].file = ExpandPath(application.wheels.filePath) & "/" & ListGetAt(arguments.file, loc.i);
 97			}
 98		}
 99
100		// delete arguments that we don't want to pass through to the cfmail tag
101		loc.iEnd = ListLen(loc.nonPassThruArgs);
102		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
103			StructDelete(arguments, ListGetAt(loc.nonPassThruArgs, loc.i));
104
105		// send the email using the cfmail tag
106		if (loc.deliver)
107			$mail(argumentCollection=arguments);
108		else
109			return arguments;
110	</cfscript>
111</cffunction>
112
113<cffunction name="sendFile" returntype="any" access="public" output="false" hint="Sends a file to the user (from the `files` folder or a path relative to it by default)."
114	examples=
115	'
116		<!--- Send a PDF file to the user --->
117		<cfset sendFile(file="wheels_tutorial_20081028_J657D6HX.pdf")>
118
119		<!--- Send the same file but give the user a different name in the browser dialog window --->
120		<cfset sendFile(file="wheels_tutorial_20081028_J657D6HX.pdf", name="Tutorial.pdf")>
121
122		<!--- Send a file that is located outside of the web root --->
123		<cfset sendFile(file="../../tutorials/wheels_tutorial_20081028_J657D6HX.pdf")>
124	'
125	categories="controller-request,miscellaneous" chapters="sending-files" functions="">
126	<cfargument name="file" type="string" required="true" hint="The file to send to the user.">
127	<cfargument name="name" type="string" required="false" default="" hint="The file name to show in the browser download dialog box.">
128	<cfargument name="type" type="string" required="false" default="" hint="The HTTP content type to deliver the file as.">
129	<cfargument name="disposition" type="string" required="false" hint="Set to `inline` to have the browser handle the opening of the file (possibly inline in the browser) or set to `attachment` to force a download dialog box.">
130	<cfargument name="directory" type="string" required="false" default="" hint="Directory outside of the webroot where the file exists. Must be a full path.">
131	<cfargument name="deleteFile" type="boolean" required="false" default="false" hint="Pass in `true` to delete the file on the server after sending it.">
132	<cfargument name="$testingMode" type="boolean" required="false" default="false">
133	<cfscript>
134		var loc = {};
135		$args(name="sendFile", args=arguments);
136		loc.relativeRoot = application.wheels.rootPath;
137		if (Right(loc.relativeRoot, 1) != "/")
138		{
139			loc.relativeRoot = loc.relativeRoot & "/";
140		}
141
142		loc.root = ExpandPath(loc.relativeRoot);
143		loc.folder = arguments.directory;
144		if (!Len(loc.folder))
145		{
146			loc.folder = loc.relativeRoot & application.wheels.filePath; 
147		}
148
149		if (Left(loc.folder, Len(loc.root)) eq loc.root)
150		{
151			loc.folder = RemoveChars(loc.folder, 1, Len(loc.root));
152		}
153
154		loc.fullPath = Replace(loc.folder, "\", "/", "all");
155		loc.fullPath = ListAppend(loc.fullPath, arguments.file, "/");
156		loc.fullPath = ExpandPath(loc.fullPath);
157		loc.fullPath = Replace(loc.fullPath, "\", "/", "all");
158		loc.file = ListLast(loc.fullPath, "/");
159		loc.directory = Reverse(ListRest(Reverse(loc.fullPath), "/"));
160
161		// if the file is not found, try searching for it
162		if (!FileExists(loc.fullPath))
163		{
164			loc.match = $directory(action="list", directory="#loc.directory#", filter="#loc.file#.*");
165			// only extract the extension if we find a single match
166			if (loc.match.recordCount == 1)
167			{
168				loc.file = loc.file & "." & ListLast(loc.match.name, ".");
169				loc.fullPath = loc.directory & "/" & loc.file;
170			}
171			else
172			{
173				$throw(type="Wheels.FileNotFound", message="A file could not be found.", extendedInfo="Make sure a file with the name `#loc.file#` exists in the `#loc.directory#` folder.");
174			}
175		}
176
177		loc.name = loc.file;
178		loc.extension = ListLast(loc.file, ".");
179
180		// replace the display name for the file if supplied
181		if (Len(arguments.name))
182			loc.name = arguments.name;
183
184		loc.mime = arguments.type;
185		if (!Len(loc.mime))
186			loc.mime = mimeTypes(loc.extension);
187
188		// if testing, return the variables
189		if (arguments.$testingMode)
190		{
191			StructAppend(loc, arguments, false);
192			return loc;
193		}
194
195		// prompt the user to download the file
196		$header(name="content-disposition", value="#arguments.disposition#; filename=""#loc.name#""");
197		$content(type="#loc.mime#", file="#loc.fullPath#", deleteFile="#arguments.deleteFile#");
198	</cfscript>
199</cffunction>