PageRenderTime 22ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/app/bundles/EmailBundle/Controller/PublicController.php

https://gitlab.com/mautic-master/mautic
PHP | 435 lines | 294 code | 69 blank | 72 comment | 46 complexity | 2aaf1ec3f0bbbffa01b4f7899ae12b82 MD5 | raw file
  1. <?php
  2. /**
  3. * @package Mautic
  4. * @copyright 2014 Mautic Contributors. All rights reserved.
  5. * @author Mautic
  6. * @link http://mautic.org
  7. * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
  8. */
  9. namespace Mautic\EmailBundle\Controller;
  10. use Mautic\CoreBundle\Controller\FormController as CommonFormController;
  11. use Mautic\CoreBundle\Helper\EmojiHelper;
  12. use Mautic\EmailBundle\Helper\MailHelper;
  13. use Mautic\EmailBundle\Entity\Email;
  14. use Mautic\CoreBundle\Helper\TrackingPixelHelper;
  15. use Mautic\EmailBundle\Swiftmailer\Transport\InterfaceCallbackTransport;
  16. use Mautic\EmailBundle\EmailEvents;
  17. use Mautic\EmailBundle\Event\EmailSendEvent;
  18. use Mautic\LeadBundle\Entity\DoNotContact;
  19. use Symfony\Component\HttpFoundation\Response;
  20. class PublicController extends CommonFormController
  21. {
  22. public function indexAction($idHash)
  23. {
  24. /** @var \Mautic\EmailBundle\Model\EmailModel $model */
  25. $model = $this->getModel('email');
  26. $stat = $model->getEmailStatus($idHash);
  27. if (!empty($stat)) {
  28. if ($this->factory->getSecurity()->isAnonymous()) {
  29. $model->hitEmail($stat, $this->request, true);
  30. }
  31. $tokens = $stat->getTokens();
  32. if (is_array($tokens)) {
  33. // Override tracking_pixel so as to not cause a double hit
  34. $tokens['{tracking_pixel}'] = MailHelper::getBlankPixel();
  35. }
  36. if ($copy = $stat->getStoredCopy()) {
  37. $subject = $copy->getSubject();
  38. $content = $copy->getBody();
  39. // Convert emoji
  40. $content = EmojiHelper::toEmoji($content, 'short');
  41. $subject = EmojiHelper::toEmoji($subject, 'short');
  42. // Replace tokens
  43. if (!empty($tokens)) {
  44. $content = str_ireplace(array_keys($tokens), $tokens, $content);
  45. $subject = str_ireplace(array_keys($tokens), $tokens, $subject);
  46. }
  47. } else {
  48. $subject = '';
  49. $content = '';
  50. }
  51. // Add analytics
  52. $analytics = $this->factory->getHelper('template.analytics')->getCode();
  53. // Check for html doc
  54. if (strpos($content, '<html>') === false) {
  55. $content = "<html>\n<head>{$analytics}</head>\n<body>{$content}</body>\n</html>";
  56. } elseif (strpos($content, '<head>') === false) {
  57. $content = str_replace('<html>', "<html>\n<head>\n{$analytics}\n</head>", $content);
  58. } elseif (!empty($analytics)) {
  59. $content = str_replace('</head>', $analytics."\n</head>", $content);
  60. }
  61. // Add subject as title
  62. if (!empty($subject)) {
  63. if (strpos($content, '<title></title>') !== false) {
  64. $content = str_replace('<title></title>', "<title>$subject</title>", $content);
  65. } elseif (strpos($content, '<title>') === false) {
  66. $content = str_replace('<head>', "<head>\n<title>$subject</title>", $content);
  67. }
  68. }
  69. return new Response($content);
  70. }
  71. $this->notFound();
  72. }
  73. /**
  74. * @param $idHash
  75. *
  76. * @return Response
  77. */
  78. public function trackingImageAction($idHash)
  79. {
  80. /** @var \Mautic\EmailBundle\Model\EmailModel $model */
  81. $model = $this->getModel('email');
  82. $model->hitEmail($idHash, $this->request);
  83. return TrackingPixelHelper::getResponse($this->request);
  84. }
  85. /**
  86. * @param $idHash
  87. *
  88. * @return Response
  89. * @throws \Exception
  90. * @throws \Mautic\CoreBundle\Exception\FileNotFoundException
  91. */
  92. public function unsubscribeAction($idHash)
  93. {
  94. // Find the email
  95. /** @var \Mautic\EmailBundle\Model\EmailModel $model */
  96. $model = $this->getModel('email');
  97. $translator = $this->get('translator');
  98. $stat = $model->getEmailStatus($idHash);
  99. if (!empty($stat)) {
  100. $email = $stat->getEmail();
  101. $lead = $stat->getLead();
  102. if ($lead) {
  103. // Set the lead as current lead
  104. /** @var \Mautic\LeadBundle\Model\LeadModel $leadModel */
  105. $leadModel = $this->getModel('lead');
  106. $leadModel->setCurrentLead($lead);
  107. }
  108. $model->setDoNotContact($stat, $translator->trans('mautic.email.dnc.unsubscribed'), DoNotContact::UNSUBSCRIBED);
  109. $message = $this->factory->getParameter('unsubscribe_message');
  110. if (!$message) {
  111. $message = $translator->trans(
  112. 'mautic.email.unsubscribed.success',
  113. array(
  114. '%resubscribeUrl%' => '|URL|',
  115. '%email%' => '|EMAIL|'
  116. )
  117. );
  118. }
  119. $message = str_replace(
  120. array(
  121. '|URL|',
  122. '|EMAIL|'
  123. ),
  124. array(
  125. $this->generateUrl('mautic_email_resubscribe', array('idHash' => $idHash)),
  126. $stat->getEmailAddress()
  127. ),
  128. $message
  129. );
  130. if ($email !== null) {
  131. $template = $email->getTemplate();
  132. /** @var \Mautic\FormBundle\Entity\Form $unsubscribeForm */
  133. $unsubscribeForm = $email->getUnsubscribeForm();
  134. if ($unsubscribeForm != null && $unsubscribeForm->isPublished()) {
  135. $formTemplate = $unsubscribeForm->getTemplate();
  136. $formModel = $this->getModel('form');
  137. $formContent = '<div class="mautic-unsubscribeform">'.$formModel->getContent($unsubscribeForm).'</div>';
  138. }
  139. }
  140. } else {
  141. $email = $lead = false;
  142. $message = $translator->trans('mautic.email.stat_record.not_found');
  143. }
  144. if (empty($template) && empty($formTemplate)) {
  145. $template = $this->factory->getParameter('theme');
  146. } else if (!empty($formTemplate)) {
  147. $template = $formTemplate;
  148. }
  149. $theme = $this->factory->getTheme($template);
  150. if ($theme->getTheme() != $template) {
  151. $template = $theme->getTheme();
  152. }
  153. $config = $theme->getConfig();
  154. $viewParams = array(
  155. 'email' => $email,
  156. 'lead' => $lead,
  157. 'template' => $template,
  158. 'message' => $message,
  159. 'type' => 'notice',
  160. 'name' => $translator->trans('mautic.email.unsubscribe')
  161. );
  162. $contentTemplate = $this->factory->getHelper('theme')->checkForTwigTemplate(':' . $template . ':message.html.php');
  163. if (!empty($formContent)) {
  164. $viewParams['content'] = $formContent;
  165. if (in_array('form', $config['features'])) {
  166. $contentTemplate = $this->factory->getHelper('theme')->checkForTwigTemplate(':' . $template . ':form.html.php');
  167. } else {
  168. $contentTemplate = 'MauticFormBundle::form.html.php';
  169. }
  170. }
  171. return $this->render($contentTemplate, $viewParams);
  172. }
  173. /**
  174. * @param $idHash
  175. *
  176. * @return Response
  177. * @throws \Exception
  178. * @throws \Mautic\CoreBundle\Exception\FileNotFoundException
  179. */
  180. public function resubscribeAction($idHash)
  181. {
  182. //find the email
  183. $model = $this->getModel('email');
  184. $stat = $model->getEmailStatus($idHash);
  185. if (!empty($stat)) {
  186. $email = $stat->getEmail();
  187. $lead = $stat->getLead();
  188. if ($lead) {
  189. // Set the lead as current lead
  190. /** @var \Mautic\LeadBundle\Model\LeadModel $leadModel */
  191. $leadModel = $this->getModel('lead');
  192. $leadModel->setCurrentLead($lead);
  193. }
  194. $model->removeDoNotContact($stat->getEmailAddress());
  195. $message = $this->factory->getParameter('resubscribe_message');
  196. if (!$message) {
  197. $message = $this->factory->getTranslator()->trans(
  198. 'mautic.email.resubscribed.success',
  199. array(
  200. '%unsubscribedUrl%' => '|URL|',
  201. '%email%' => '|EMAIL|'
  202. )
  203. );
  204. }
  205. $message = str_replace(
  206. array(
  207. '|URL|',
  208. '|EMAIL|'
  209. ),
  210. array(
  211. $this->generateUrl('mautic_email_unsubscribe', array('idHash' => $idHash)),
  212. $stat->getEmailAddress()
  213. ),
  214. $message
  215. );
  216. } else {
  217. $email = $lead = false;
  218. $message = $this->factory->getTranslator()->trans('mautic.email.stat_record.not_found');
  219. }
  220. $template = ($email !== null) ? $email->getTemplate() : $this->factory->getParameter('theme');
  221. $theme = $this->factory->getTheme($template);
  222. if ($theme->getTheme() != $template) {
  223. $template = $theme->getTheme();
  224. }
  225. // Ensure template still exists
  226. $theme = $this->factory->getTheme($template);
  227. if (empty($theme) || $theme->getTheme() !== $template) {
  228. $template = $this->factory->getParameter('theme');
  229. }
  230. $analytics = $this->factory->getHelper('template.analytics')->getCode();
  231. if (! empty($analytics)) {
  232. $this->factory->getHelper('template.assets')->addCustomDeclaration($analytics);
  233. }
  234. $logicalName = $this->factory->getHelper('theme')->checkForTwigTemplate(':' . $template . ':message.html.php');
  235. return $this->render(
  236. $logicalName,
  237. array(
  238. 'message' => $message,
  239. 'type' => 'notice',
  240. 'email' => $email,
  241. 'lead' => $lead,
  242. 'template' => $template
  243. )
  244. );
  245. }
  246. /**
  247. * Handles mailer transport webhook post
  248. *
  249. * @param $transport
  250. *
  251. * @return Response
  252. */
  253. public function mailerCallbackAction($transport)
  254. {
  255. ignore_user_abort(true);
  256. // Check to see if transport matches currently used transport
  257. $currentTransport = $this->factory->getMailer()->getTransport();
  258. if ($currentTransport instanceof InterfaceCallbackTransport && $currentTransport->getCallbackPath() == $transport) {
  259. $response = $currentTransport->handleCallbackResponse($this->request, $this->factory);
  260. if (is_array($response)) {
  261. /** @var \Mautic\EmailBundle\Model\EmailModel $model */
  262. $model = $this->getModel('email');
  263. $model->processMailerCallback($response);
  264. }
  265. return new Response('success');
  266. }
  267. $this->notFound();
  268. }
  269. /**
  270. * Preview email
  271. *
  272. * @param $objectId
  273. *
  274. * @return \Symfony\Component\HttpFoundation\Response
  275. */
  276. public function previewAction($objectId)
  277. {
  278. /** @var \Mautic\EmailBundle\Model\EmailModel $model */
  279. $model = $this->getModel('email');
  280. $emailEntity = $model->getEntity($objectId);
  281. if (
  282. ($this->factory->getSecurity()->isAnonymous() && !$emailEntity->isPublished())
  283. || (!$this->factory->getSecurity()->isAnonymous()
  284. && !$this->factory->getSecurity()->hasEntityAccess(
  285. 'email:emails:viewown',
  286. 'email:emails:viewother',
  287. $emailEntity->getCreatedBy()
  288. ))
  289. ) {
  290. return $this->accessDenied();
  291. }
  292. //bogus ID
  293. $idHash = 'xxxxxxxxxxxxxx';
  294. $BCcontent = $emailEntity->getContent();
  295. $content = $emailEntity->getCustomHtml();
  296. if (empty($content) && !empty($BCcontent)) {
  297. $template = $emailEntity->getTemplate();
  298. $slots = $this->factory->getTheme($template)->getSlots('email');
  299. $assetsHelper = $this->factory->getHelper('template.assets');
  300. $assetsHelper->addCustomDeclaration('<meta name="robots" content="noindex">');
  301. $this->processSlots($slots, $emailEntity);
  302. $logicalName = $this->factory->getHelper('theme')->checkForTwigTemplate(':' . $template . ':email.html.php');
  303. $response = $this->render(
  304. $logicalName,
  305. array(
  306. 'inBrowser' => true,
  307. 'slots' => $slots,
  308. 'content' => $emailEntity->getContent(),
  309. 'email' => $emailEntity,
  310. 'lead' => null,
  311. 'template' => $template
  312. )
  313. );
  314. //replace tokens
  315. $content = $response->getContent();
  316. }
  317. // Convert emojis
  318. $content = EmojiHelper::toEmoji($content, 'short');
  319. // Override tracking_pixel
  320. $tokens = array('{tracking_pixel}' => '');
  321. // Prepare a fake lead
  322. /** @var \Mautic\LeadBundle\Model\FieldModel $fieldModel */
  323. $fieldModel = $this->getModel('lead.field');
  324. $fields = $fieldModel->getFieldList(false, false);
  325. array_walk(
  326. $fields,
  327. function (&$field) {
  328. $field = "[$field]";
  329. }
  330. );
  331. $fields['id'] = 0;
  332. // Generate and replace tokens
  333. $event = new EmailSendEvent(
  334. null,
  335. array(
  336. 'content' => $content,
  337. 'email' => $emailEntity,
  338. 'idHash' => $idHash,
  339. 'tokens' => $tokens,
  340. 'internalSend' => true,
  341. 'lead' => $fields
  342. )
  343. );
  344. $this->factory->getDispatcher()->dispatch(EmailEvents::EMAIL_ON_DISPLAY, $event);
  345. $content = $event->getContent(true);
  346. return new Response($content);
  347. }
  348. /**
  349. * @param $slots
  350. * @param Email $entity
  351. */
  352. public function processSlots($slots, $entity)
  353. {
  354. /** @var \Mautic\CoreBundle\Templating\Helper\SlotsHelper $slotsHelper */
  355. $slotsHelper = $this->factory->getHelper('template.slots');
  356. $content = $entity->getContent();
  357. foreach ($slots as $slot => $slotConfig) {
  358. if (is_numeric($slot)) {
  359. $slot = $slotConfig;
  360. $slotConfig = array();
  361. }
  362. $value = isset($content[$slot]) ? $content[$slot] : "";
  363. $slotsHelper->set($slot, $value);
  364. }
  365. }
  366. }