PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/swift/Swift/Plugin/Decorator.php

https://gitlab.com/staging06/myproject
PHP | 259 lines | 155 code | 8 blank | 96 comment | 18 complexity | 5aae63e8916ae7392c3efccfd286e2e8 MD5 | raw file
  1. <?php
  2. /**
  3. * Swift Mailer Message Decorating Plugin.
  4. * Please read the LICENSE file
  5. * @author Chris Corbyn <chris@w3style.co.uk>
  6. * @package Swift_Plugin
  7. * @subpackage Decorator
  8. * @license GNU Lesser General Public License
  9. */
  10. require_once dirname(__FILE__) . "/../ClassLoader.php";
  11. Swift_ClassLoader::load("Swift_Events_BeforeSendListener");
  12. Swift_ClassLoader::load("Swift_Plugin_Decorator_Replacements");
  13. /**
  14. * Swift Decorator Plugin.
  15. * Allows messages to be slightly different for each recipient.
  16. * @package Swift_Plugin
  17. * @subpackage Decorator
  18. * @author Chris Corbyn <chris@w3style.co.uk>
  19. */
  20. class Swift_Plugin_Decorator implements Swift_Events_BeforeSendListener
  21. {
  22. /**
  23. * The replacements object.
  24. * @var Swift_Plugin_Decorator_Replacements
  25. */
  26. protected $replacements;
  27. /**
  28. * Temporary storage so we can restore changes we make.
  29. * @var array
  30. */
  31. protected $store;
  32. /**
  33. * A list of allowed mime types to replace bodies for.
  34. * @var array
  35. */
  36. protected $permittedTypes = array("text/plain" => 1, "text/html" => 1);
  37. /**
  38. * True if values in the headers can be replaced
  39. * @var boolean
  40. */
  41. protected $permittedInHeaders = true;
  42. /**
  43. * Ctor.
  44. * @param mixed Replacements as a 2-d array or Swift_Plugin_Decorator_Replacements instance.
  45. */
  46. public function __construct($replacements=null)
  47. {
  48. $this->setReplacements($replacements);
  49. }
  50. /**
  51. * Enable of disable the ability to replace values in the headers
  52. * @param boolean
  53. */
  54. public function setPermittedInHeaders($bool)
  55. {
  56. $this->permittedInHeaders = (bool) $bool;
  57. }
  58. /**
  59. * Check if replacements in headers are allowed.
  60. * @return boolean
  61. */
  62. public function getPermittedInHeaders()
  63. {
  64. return $this->permittedInHeaders;
  65. }
  66. /**
  67. * Add a mime type to the list of permitted type to replace values in the body.
  68. * @param string The mime type (e.g. text/plain)
  69. */
  70. public function addPermittedType($type)
  71. {
  72. $type = strtolower($type);
  73. $this->permittedTypes[$type] = 1;
  74. }
  75. /**
  76. * Remove the ability to replace values in the body of the given mime type
  77. * @param string The mime type
  78. */
  79. public function removePermittedType($type)
  80. {
  81. unset($this->permittedTypes[$type]);
  82. }
  83. /**
  84. * Get the list of mime types for which the body can be changed.
  85. * @return array
  86. */
  87. public function getPermittedTypes()
  88. {
  89. return array_keys($this->permittedTypes);
  90. }
  91. /**
  92. * Check if the body can be replaced in the given mime type.
  93. * @param string The mime type
  94. * @return boolean
  95. */
  96. public function isPermittedType($type)
  97. {
  98. return array_key_exists(strtolower($type), $this->permittedTypes);
  99. }
  100. /**
  101. * Called just before Swift sends a message.
  102. * We perform operations on the message here.
  103. * @param Swift_Events_SendEvent The event object for sending a message
  104. */
  105. public function beforeSendPerformed(Swift_Events_SendEvent $e)
  106. {
  107. $message = $e->getMessage();
  108. $this->recursiveRestore($message, $this->store); //3.3.3 bugfix
  109. $recipients = $e->getRecipients();
  110. $to = array_keys($recipients->getTo());
  111. if (count($to) > 0) $to = $to[0];
  112. else return;
  113. $replacements = (array)$this->replacements->getReplacementsFor($to);
  114. $this->store = array(
  115. "headers" => array(),
  116. "body" => false,
  117. "children" => array()
  118. );
  119. $this->recursiveReplace($message, $replacements, $this->store);
  120. }
  121. /**
  122. * Replace strings in the message searching through all the allowed sub-parts.
  123. * @param Swift_Message_Mime The message (or part)
  124. * @param array The list of replacements
  125. * @param array The array to cache original values into where needed
  126. */
  127. protected function recursiveReplace(Swift_Message_Mime $mime, $replacements, &$store)
  128. {
  129. //Check headers
  130. if ($this->getPermittedInHeaders())
  131. {
  132. foreach ($mime->headers->getList() as $name => $value)
  133. {
  134. if (is_string($value) && ($replaced = $this->replace($replacements, $value)) != $value)
  135. {
  136. $mime->headers->set($name, $replaced);
  137. $store["headers"][$name] = array();
  138. $store["headers"][$name]["value"] = $value;
  139. $store["headers"][$name]["attributes"] = array();
  140. }
  141. foreach ($mime->headers->listAttributes($name) as $att_name => $att_value)
  142. {
  143. if (is_string($att_value)
  144. && ($att_replaced = $this->replace($replacements, $att_value)) != $att_value)
  145. {
  146. if (!isset($store["headers"][$name]))
  147. {
  148. $store["headers"][$name] = array("value" => false, "attributes" => array());
  149. }
  150. $mime->headers->setAttribute($name, $att_name, $att_replaced);
  151. $store["headers"][$name]["attributes"][$att_name] = $att_value;
  152. }
  153. }
  154. }
  155. }
  156. //Check body
  157. $body = $mime->getData();
  158. if ($this->isPermittedType($mime->getContentType())
  159. && is_string($body) && ($replaced = $this->replace($replacements, $body)) != $body)
  160. {
  161. $mime->setData($replaced);
  162. $store["body"] = $body;
  163. }
  164. //Check sub-parts
  165. foreach ($mime->listChildren() as $id)
  166. {
  167. $store["children"][$id] = array(
  168. "headers" => array(),
  169. "body" => false,
  170. "children" => array()
  171. );
  172. $child = $mime->getChild($id);
  173. $this->recursiveReplace($child, $replacements, $store["children"][$id]);
  174. }
  175. }
  176. /**
  177. * Perform a str_replace() over the given value.
  178. * @param array The list of replacements as (search => replacement)
  179. * @param string The string to replace
  180. * @return string
  181. */
  182. protected function replace($replacements, $value)
  183. {
  184. return str_replace(array_keys($replacements), array_values($replacements), $value);
  185. }
  186. /**
  187. * Put the original values back in the message after it was modified before sending.
  188. * @param Swift_Message_Mime The message (or part)
  189. * @param array The location of the stored values
  190. */
  191. protected function recursiveRestore(Swift_Message_Mime $mime, &$store)
  192. {
  193. if (empty($store)) //3.3.3 bugfix
  194. {
  195. return;
  196. }
  197. //Restore headers
  198. foreach ($store["headers"] as $name => $array)
  199. {
  200. if ($array["value"] !== false) $mime->headers->set($name, $array["value"]);
  201. foreach ($array["attributes"] as $att_name => $att_value)
  202. {
  203. $mime->headers->setAttribute($name, $att_name, $att_value);
  204. }
  205. }
  206. //Restore body
  207. if ($store["body"] !== false)
  208. {
  209. $mime->setData($store["body"]);
  210. }
  211. //Restore children
  212. foreach ($store["children"] as $id => $child_store)
  213. {
  214. $child = $mime->getChild($id);
  215. $this->recursiveRestore($child, $child_store);
  216. }
  217. }
  218. /**
  219. * Set the replacements as a 2-d array or an instance of Swift_Plugin_Decorator_Replacements.
  220. * @param mixed Array or Swift_Plugin_Decorator_Replacements
  221. */
  222. public function setReplacements($replacements)
  223. {
  224. if ($replacements === null)
  225. {
  226. $r = array();
  227. $this->replacements = new Swift_Plugin_Decorator_Replacements($r);
  228. }
  229. elseif (is_array($replacements))
  230. {
  231. $this->replacements = new Swift_Plugin_Decorator_Replacements($replacements);
  232. }
  233. elseif ($replacements instanceof Swift_Plugin_Decorator_Replacements)
  234. {
  235. $this->replacements = $replacements;
  236. }
  237. else
  238. {
  239. throw new Exception(
  240. "Decorator replacements must be array or instance of Swift_Plugin_Decorator_Replacements.");
  241. }
  242. }
  243. /**
  244. * Get the replacements object.
  245. * @return Swift_Plugin_Decorator_Replacements
  246. */
  247. public function getReplacements()
  248. {
  249. return $this->replacements;
  250. }
  251. }