PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

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

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