/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. <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."
  3. examples=
  4. '
  5. <!--- Get a member and send a welcome email, passing in a few custom variables to the template --->
  6. <cfset newMember = model("member").findByKey(params.member.id)>
  7. <cfset sendEmail(
  8. to=newMember.email,
  9. template="myemailtemplate",
  10. subject="Thank You for Becoming a Member",
  11. recipientName=newMember.name,
  12. startDate=newMember.startDate
  13. )>
  14. '
  15. categories="controller-request,miscellaneous" chapters="sending-email" functions="">
  16. <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`.">
  17. <cfargument name="from" type="string" required="false" default="" hint="Email address to send from.">
  18. <cfargument name="to" type="string" required="false" default="" hint="List of email addresses to send the email to.">
  19. <cfargument name="subject" type="string" required="false" default="" hint="The subject line of the email.">
  20. <cfargument name="layout" type="any" required="false" hint="Layout(s) to wrap the email template in. This argument is also aliased as `layouts`.">
  21. <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`.">
  22. <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).">
  23. <cfargument name="$deliver" type="boolean" required="false" default="true">
  24. <cfscript>
  25. var loc = {};
  26. $args(args=arguments, name="sendEmail", combine="template/templates/!,layout/layouts,file/files", required="template,from,to,subject");
  27. loc.nonPassThruArgs = "template,templates,layout,layouts,file,files,detectMultipart,$deliver";
  28. 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";
  29. loc.deliver = arguments.$deliver;
  30. // if two templates but only one layout was passed in we set the same layout to be used on both
  31. if (ListLen(arguments.template) > 1 && ListLen(arguments.layout) == 1)
  32. arguments.layout = ListAppend(arguments.layout, arguments.layout);
  33. // set the variables that should be available to the email view template (i.e. the custom named arguments passed in by the developer)
  34. for (loc.key in arguments)
  35. {
  36. if (!ListFindNoCase(loc.nonPassThruArgs, loc.key) && !ListFindNoCase(loc.mailTagArgs, loc.key))
  37. {
  38. variables[loc.key] = arguments[loc.key];
  39. StructDelete(arguments, loc.key);
  40. }
  41. }
  42. // get the content of the email templates and store them as cfmailparts
  43. arguments.mailparts = [];
  44. loc.iEnd = ListLen(arguments.template);
  45. for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
  46. {
  47. // include the email template and return it
  48. loc.content = $renderPage($template=ListGetAt(arguments.template, loc.i), $layout=ListGetAt(arguments.layout, loc.i));
  49. loc.mailpart = {};
  50. loc.mailpart.tagContent = loc.content;
  51. if (ArrayIsEmpty(arguments.mailparts))
  52. {
  53. ArrayAppend(arguments.mailparts, loc.mailpart);
  54. }
  55. else
  56. {
  57. // make sure the text version is the first one in the array
  58. loc.existingContentCount = ListLen(arguments.mailparts[1].tagContent, "<");
  59. loc.newContentCount = ListLen(loc.content, "<");
  60. if (loc.newContentCount < loc.existingContentCount)
  61. ArrayPrepend(arguments.mailparts, loc.mailpart);
  62. else
  63. ArrayAppend(arguments.mailparts, loc.mailpart);
  64. arguments.mailparts[1].type = "text";
  65. arguments.mailparts[2].type = "html";
  66. }
  67. }
  68. // 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
  69. if (ArrayLen(arguments.mailparts) == 1)
  70. {
  71. arguments.tagContent = arguments.mailparts[1].tagContent;
  72. StructDelete(arguments, "mailparts");
  73. if (arguments.detectMultipart && !StructKeyExists(arguments, "type"))
  74. {
  75. if (Find("<", arguments.tagContent) && Find(">", arguments.tagContent))
  76. arguments.type = "html";
  77. else
  78. arguments.type = "text";
  79. }
  80. }
  81. // attach files using the cfmailparam tag
  82. if (Len(arguments.file))
  83. {
  84. arguments.mailparams = [];
  85. loc.iEnd = ListLen(arguments.file);
  86. for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
  87. {
  88. arguments.mailparams[loc.i] = {};
  89. arguments.mailparams[loc.i].file = ExpandPath(application.wheels.filePath) & "/" & ListGetAt(arguments.file, loc.i);
  90. }
  91. }
  92. // delete arguments that we don't want to pass through to the cfmail tag
  93. loc.iEnd = ListLen(loc.nonPassThruArgs);
  94. for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
  95. StructDelete(arguments, ListGetAt(loc.nonPassThruArgs, loc.i));
  96. // send the email using the cfmail tag
  97. if (loc.deliver)
  98. $mail(argumentCollection=arguments);
  99. else
  100. return arguments;
  101. </cfscript>
  102. </cffunction>
  103. <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)."
  104. examples=
  105. '
  106. <!--- Send a PDF file to the user --->
  107. <cfset sendFile(file="wheels_tutorial_20081028_J657D6HX.pdf")>
  108. <!--- Send the same file but give the user a different name in the browser dialog window --->
  109. <cfset sendFile(file="wheels_tutorial_20081028_J657D6HX.pdf", name="Tutorial.pdf")>
  110. <!--- Send a file that is located outside of the web root --->
  111. <cfset sendFile(file="../../tutorials/wheels_tutorial_20081028_J657D6HX.pdf")>
  112. '
  113. categories="controller-request,miscellaneous" chapters="sending-files" functions="">
  114. <cfargument name="file" type="string" required="true" hint="The file to send to the user.">
  115. <cfargument name="name" type="string" required="false" default="" hint="The file name to show in the browser download dialog box.">
  116. <cfargument name="type" type="string" required="false" default="" hint="The HTTP content type to deliver the file as.">
  117. <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.">
  118. <cfargument name="directory" type="string" required="false" default="" hint="Directory outside of the webroot where the file exists. Must be a full path.">
  119. <cfargument name="deleteFile" type="boolean" required="false" default="false" hint="Pass in `true` to delete the file on the server after sending it.">
  120. <cfargument name="$testingMode" type="boolean" required="false" default="false">
  121. <cfscript>
  122. var loc = {};
  123. $args(name="sendFile", args=arguments);
  124. loc.relativeRoot = application.wheels.rootPath;
  125. if (Right(loc.relativeRoot, 1) != "/")
  126. {
  127. loc.relativeRoot = loc.relativeRoot & "/";
  128. }
  129. loc.root = ExpandPath(loc.relativeRoot);
  130. loc.folder = arguments.directory;
  131. if (!Len(loc.folder))
  132. {
  133. loc.folder = loc.relativeRoot & application.wheels.filePath;
  134. }
  135. if (Left(loc.folder, Len(loc.root)) eq loc.root)
  136. {
  137. loc.folder = RemoveChars(loc.folder, 1, Len(loc.root));
  138. }
  139. loc.fullPath = Replace(loc.folder, "\", "/", "all");
  140. loc.fullPath = ListAppend(loc.fullPath, arguments.file, "/");
  141. loc.fullPath = ExpandPath(loc.fullPath);
  142. loc.fullPath = Replace(loc.fullPath, "\", "/", "all");
  143. loc.file = ListLast(loc.fullPath, "/");
  144. loc.directory = Reverse(ListRest(Reverse(loc.fullPath), "/"));
  145. // if the file is not found, try searching for it
  146. if (!FileExists(loc.fullPath))
  147. {
  148. loc.match = $directory(action="list", directory="#loc.directory#", filter="#loc.file#.*");
  149. // only extract the extension if we find a single match
  150. if (loc.match.recordCount == 1)
  151. {
  152. loc.file = loc.file & "." & ListLast(loc.match.name, ".");
  153. loc.fullPath = loc.directory & "/" & loc.file;
  154. }
  155. else
  156. {
  157. $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.");
  158. }
  159. }
  160. loc.name = loc.file;
  161. loc.extension = ListLast(loc.file, ".");
  162. // replace the display name for the file if supplied
  163. if (Len(arguments.name))
  164. loc.name = arguments.name;
  165. loc.mime = arguments.type;
  166. if (!Len(loc.mime))
  167. loc.mime = mimeTypes(loc.extension);
  168. // if testing, return the variables
  169. if (arguments.$testingMode)
  170. {
  171. StructAppend(loc, arguments, false);
  172. return loc;
  173. }
  174. // prompt the user to download the file
  175. $header(name="content-disposition", value="#arguments.disposition#; filename=""#loc.name#""");
  176. $content(type="#loc.mime#", file="#loc.fullPath#", deleteFile="#arguments.deleteFile#");
  177. </cfscript>
  178. </cffunction>