Completed
Push — fix-phpunit-inclusion ( 32fa89 )
by Dominik
14:50
created

AzineTemplateProvider::addTemplateVariablesFor()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 30
Code Lines 12

Duplication

Lines 17
Ratio 56.67 %

Code Coverage

Tests 15
CRAP Score 4

Importance

Changes 0
Metric Value
dl 17
loc 30
ccs 15
cts 15
cp 1
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 12
nc 4
nop 2
crap 4
1
<?php
2
namespace Azine\EmailBundle\Services;
3
4
/**
5
 * This Service provides the templates and template-variables to be used for emails
6
 * @author Dominik Businger
7
 */
8
use Azine\EmailBundle\DependencyInjection\AzineEmailExtension;
9
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
10
use Symfony\Bundle\FrameworkBundle\Translation\Translator;
11
12
class AzineTemplateProvider implements TemplateProviderInterface
13
{
14
    const BASE_TEMPLATE 					= 'AzineEmailBundle::baseEmailLayout';
15
    const NEWSLETTER_TEMPLATE 				= 'AzineEmailBundle::newsletterEmailLayout';
16
    const NOTIFICATIONS_TEMPLATE			= 'AzineEmailBundle::notificationsEmailLayout';
17
    const CONTENT_ITEM_MESSAGE_TEMPLATE		= 'AzineEmailBundle:contentItem:message';
18
    const FOS_USER_PWD_RESETTING_TEMPLATE	= "FOSUserBundle:Resetting:email";
19
    const FOS_USER_REGISTRATION_TEMPLATE	= "FOSUserBundle:Registration:email";
20
    const SEND_IMMEDIATELY_FLAG             = "AzineEmailBundle_SendThisEmailImmediately";
21
22
    /**
23
     * Override this function for your template(s)!
24
     *
25
     * For each template you like to render, you need to supply the array with variables that can be passed to the twig renderer.
26
     * Those variables can then be used in the twig-template => {{ logo_png }}
27
     *
28
     * In this function you should fill a set of variables for each template.
29
     *
30
     * @param string $template the template id in standard-notation, without the ending ( .txt.twig) => "AcmeFooBundle:bar:default"
31
     * @return array
32
     */
33 9
    protected function getParamArrayFor($template)
34
    {
35
        // this implementation uses the same array for all templates.
36
        // override this function with a more sophisticated logic
37
        // if you need different styles for different templates.
38
39 9
        $newVars = array();
40
41
        // add template-specific stuff.
42 9
        if ($template == self::NOTIFICATIONS_TEMPLATE) {
43 1
            $newVars['subject'] = "Your notifications sent by AzineEmailBundle";
44 1
        }
45
46 9
        if ($template == self::NEWSLETTER_TEMPLATE) {
47 5
            $newVars['subject'] = "Newsletter sent by AzineEmailBundle";
48 5
        }
49
50
        // send some mails immediately instead of spooled
51 9
        if($template == self::FOS_USER_PWD_RESETTING_TEMPLATE || $template == self::FOS_USER_REGISTRATION_TEMPLATE){
52 1
            $newVars[self::SEND_IMMEDIATELY_FLAG] = true;
53 1
        }
54
55
        // add generic stuff needed for all templates
56
57
        // add images to be encoded and attached to the email
58
        // the absolute file-path will be replaced with the CID of
59
        // the attached image, so it will be rendered in the html-email.
60
        // => to render the logo inside your twig-template you can write:
61
        // <html><body> ... <img src="{{ logo_png }}" alt="logo"> ... </body></html>
62 9
        $imagesDir = $this->getTemplateImageDir();
63 9
        $newVars['logo_png'] 				= $imagesDir.'logo.png';
64 9
        $newVars['bottom_shadow_png']		= $imagesDir.'bottomshadow.png';
65 9
        $newVars['top_shadow_png']			= $imagesDir.'topshadow.png';
66 9
        $newVars['left_shadow_png']			= $imagesDir.'left-shadow.png';
67 9
        $newVars['right_shadow_png']		= $imagesDir.'right-shadow.png';
68 9
        $newVars['placeholder_png'] 		= $imagesDir.'placeholder.png';
69
70
        // define some colors to be reused in the following style-definitions
71 9
        $azGreen							= "green";
72 9
        $azBlue								= "blue";
73 9
        $blackColor							= "black";
74 9
        $lightGray 							= "#EEEEEE";
75 9
        $newVars["azGreen"] 				= $azGreen;
76 9
        $newVars["azBlue"] 					= $azBlue;
77 9
        $newVars["blackColor"]				= $blackColor;
78 9
        $newVars["lightGray"]				= $lightGray;
79 9
        $newVars["bodyBackgroundColor"]		= "#fdfbfa";
80 9
        $newVars["contentBackgroundColor"]  = "#f2f1f0";
81 9
        $fontFamily							= "Arial, Helvetica, sans-serif";
82 9
        $newVars["fontFamily"]				= $fontFamily;
83 9
        $newVars["emailWidth"]				= 640;// width for the whole email-body
84 9
        $newVars["shadowWidth"]				= 10; // width for the shadows left and right of the content
85 9
        $newVars["contentWidth"]			= 620;// width for the mail content
86 9
        $newVars["mediaQueryWidth"]			= 479;// width for the media-query for mobile devices
87 9
        $newVars["mobileEmailWidth"]		= 459;// width for the whole email-body for mobile devices
88 9
        $newVars["mobileContentWidth"]		= 439;// width for the mail content for mobile devices
89 9
        $newVars["footerBackgroundColor"]   = "#434343";
90
91
        // add html-styles for your html-emails
92
        // css does not work in html-emails, so all styles need to be
93
        // embedded directly into the html-elements
94 9
        $newVars["h2Style"]					= "style='padding:0; margin:0; font:bold 24px $fontFamily; color:$azBlue; text-decoration:none;'";
95 9
        $newVars["h3Style"]					= "style='margin:12px 0 5px 0; font:bold 18px $fontFamily; padding:0; color:$azGreen; text-decoration:none;'";
96 9
        $newVars["h4Style"]					= "style='padding:0; margin:0 0 20px 0; color:$blackColor; font-size:14px; text-decoration:none;'";
97 9
        $newVars["txtH1Style"]				= "////////////////////////////////////////////////////////////////////////////////";
98 9
        $newVars["txtH2Style"]				= "================================================================================";
99 9
        $newVars["txtH3Style"]				= "--------------------------------------------------------------------------------";
100 9
        $newVars["txtH4Style"]				= "''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''";
101 9
        $newVars["txtHR"]					= "________________________________________________________________________________";
102 9
        $newVars["smallGreyStyle"]			= "style='color: grey; font: $fontFamily 11px;'";
103 9
        $newVars["salutationStyle"]			= "style='color:$azBlue; font:bold 16px $fontFamily;'";
104 9
        $newVars["dateStyle"]				= "style='padding:0; margin:5px 0; color:$blackColor; font-weight:bold; font-size:12px;'";
105 9
        $newVars["smallerTextStyle"]		= "style='font: normal 13px/18px $fontFamily;'";
106
107 9
        return $newVars;
108
    }
109
110
    /**
111
     * Override this function for your template(s) if you use other "snippets" with embedded images.
112
     *
113
     * This function adds more complex elements to the array of variables that are passed
114
     * to the twig-renderer, just before sending the mail.
115
     *
116
     * In this implementation for example some reusable "snippets" are added to render
117
     * a nice shadow around content parts and add a "link to top" at the top of each part.
118
     *
119
     * As these "snippets" contain references to images that first had to be embedded into the
120
     * Message, these "snippets" are added after embedding/adding the attachments.
121
     *
122
     * This means, that here the variable "bottom_shadow_png" defined in AzineTemplateProvider.fillParamArrayFor()
123
     * does not contain the path to the image-file anymore but now contains the CID of the embedded image.
124
     *
125
     * @param  string     $template    the template id in standard-notation, without the ending ( .txt.twig) => "AcmeFooBundle:bar:default"
126
     * @param  array      $vars
127
     * @param  string     $emailLocale
128
     * @throws \Exception
129
     * @return array      of strings
130
     */
131 9
    protected function getSnippetArrayFor($template, array $vars, $emailLocale)
132
    {
133
        // this implementation uses the same snippets for all templates.
134
        // override this function with a more sophisticated logic
135
        // if you need different snippets for different templates.
136
137
        // the snippets added in this implementation depend on the
138
        // following images, so they must be present in the $vars-array
139
        if(
140 9
                !array_key_exists("bottom_shadow_png", $vars) ||
141 8
                !array_key_exists("top_shadow_png", $vars) ||
142 8
                !array_key_exists("left_shadow_png", $vars) ||
143 8
                !array_key_exists("right_shadow_png", $vars)
144 9
        ) {
145 1
            throw new \Exception("some required images are not yet added to the template-vars array.");
146
        }
147
148 8
        $snippets = array();
149
150
        // define some vars that are used several times
151 8
        $lightGray	= $vars["lightGray"];;
152 8
        $blackColor	= $vars["blackColor"];
153 8
        $upLinkTitle= $this->getTranslator($emailLocale)->trans("html.email.go.to.top.link.label", array(), 'messages', $emailLocale);
154 7
        $fontFamily	= $vars["fontFamily"];
155
156
        // create and add html-elements for easy reuse in the twig-templates
157 7
        $snippets["linkToTop"] 		= "<a href='#top' style='text-decoration:none;color:$blackColor' title='$upLinkTitle'>Λ</a>";
158 7
        $snippets["tableOpen"]		= "<table summary='box with shadows' class='emailWidth' width='".$vars["emailWidth"]."' border='0' align='center' cellpadding='0' cellspacing='0'  style='font: normal 14px/18px $fontFamily;'>";
159 7
        $snippets["topShadow"]		= $snippets["tableOpen"]."<tr><td class='emailWidth'  colspan='3' width='".$vars["emailWidth"]."'><img class='emailWidth' width='".$vars["emailWidth"]."' height='10' src='".$vars["top_shadow_png"]."' alt='' style='vertical-align: bottom;'/></td></tr>";
160 7
        $snippets["leftShadow"]		= "<tr><td width='10' style='border-right: 1px solid $lightGray; background-image: url(\"".$vars["left_shadow_png"]."\");'>&nbsp;</td>";
161 7
        $snippets["rightShadow"]	= "<td width='10' style='border-left: 1px solid $lightGray; background-image: url(\"".$vars["right_shadow_png"]."\");'>&nbsp;</td></tr>";
162 7
        $snippets["bottomShadow"]	= "	<tr><td colspan='3' class='emailWidth' width='".$vars["emailWidth"]."'><img src='".$vars["bottom_shadow_png"]."' class='emailWidth' width='".$vars["emailWidth"]."' height='10' alt='' style='vertical-align: top;'/></td></tr></table>";
163 7
        $snippets["linkToTopRow"]	= $snippets["leftShadow"]."<td width='610' bgcolor='white' style='text-align: right; padding: 5px 5px 0; border-top: 1px solid $lightGray;'>".$snippets["linkToTop"]."</td>".$snippets["rightShadow"];
164 7
        $snippets["cellSeparator"]	= "</td>".$snippets["rightShadow"].$snippets["bottomShadow"].$snippets["topShadow"].$snippets["linkToTopRow"].$snippets["leftShadow"]."<td bgcolor='white' width='580' align='left' valign='top' style='padding:10px 20px 20px 20px;'>";
165
166 7
        return $snippets;
167
    }
168
169
    /**
170
     * Override this function to define your own campaign-parameters
171
     * (non-PHPdoc)
172
     * @see Azine\EmailBundle\Services\TemplateProviderInterface::getCampaignParamsFor()
173
     */
174 6
    public function getCampaignParamsFor($templateId, array $params = null) {
175
        $campaignParams = array(
176 6
            $this->tracking_params_campaign_medium => "email",
177 6
            $this->tracking_params_campaign_name => date("y-m-d")
178 6
        );
179
180 6
        if ($templateId == self::NEWSLETTER_TEMPLATE) {
181 5
            $campaignParams[$this->tracking_params_campaign_source] = "newsletter";
182 6
        } else if ($templateId == self::NOTIFICATIONS_TEMPLATE) {
183 1
            $campaignParams[$this->tracking_params_campaign_source] = "mailnotify";
184
185 2
        } else if ($templateId == self::CONTENT_ITEM_MESSAGE_TEMPLATE){
186 1
            $campaignParams[$this->tracking_params_campaign_content] = "message";
187
188
            // don't track password-reset emails
189 2
        } else if($templateId == self::FOS_USER_PWD_RESETTING_TEMPLATE || $templateId == self::FOS_USER_REGISTRATION_TEMPLATE){
190
            $campaignParams = array();
191
        }
192
193 6
        return $campaignParams;
194
    }
195
196
    /**
197
     * Override this function if you want to add extra headers to the messages sent.
198
     * (non-PHPdoc)
199
     * @see Azine\EmailBundle\Services.TemplateProviderInterface::addCustomHeaders()
200
     */
201 4
    public function addCustomHeaders($template, \Swift_Message $message, array $params)
202
    {
203
        //$headerSet = $message->getHeaders();
204
        //$headerSet->addTextHeader($name, $vale);
205 4
    }
206
207
    /**
208
     * (non-PHPdoc)
209
     * @see Azine\EmailBundle\Services.TemplateProviderInterface::saveWebViewFor()
210
     */
211 6
    public function saveWebViewFor($template)
212
    {
213 6
        if (array_search($template, $this->getTemplatesToStoreForWebView()) !== false ) {
214 5
            return true;
215
        }
216
217 2
        return false;
218
    }
219
220
    /**
221
     * Override this function to define which emails you want to make the web-view available and for which not.
222
     *
223
     * @return array of string => the template id in standard-notation, without the ending ( .txt.twig) => "AcmeFooBundle:bar:default"
224
     */
225 6
    protected function getTemplatesToStoreForWebView()
226
    {
227 6
        $include = array();
228 6
        $include[] = self::NEWSLETTER_TEMPLATE;
229
230 6
        return $include;
231
    }
232
233
    /**
234
     * Only override this method if you want to change the ID used in the twig-template for the web-view-link from 'azineEmailWebViewToken' to something else.
235
     * (non-PHPdoc)
236
     * @see Azine\EmailBundle\Services.TemplateProviderInterface::getWebViewTokenId()
237
     */
238 6
    public function getWebViewTokenId()
239
    {
240 6
        return self::EMAIL_WEB_VIEW_TOKEN;
241
    }
242
243
//////////////////////////////////////////////////////////////////////////
244
/* You probably don't need to change or override any of the stuff below */
245
//////////////////////////////////////////////////////////////////////////
246
247
    const CONTENT_ITEMS 		= 'contentItems';
248
    const EMAIL_WEB_VIEW_TOKEN 	= "azineEmailWebViewToken";
249
250
    /**
251
     * Full filesystem-path to the directory where you store your email-template images.
252
     * @var string
253
     */
254
    private $templateImageDir;
255
256
    /**
257
     * List of directories from which images are allowed to be embeded into emails
258
     * @var array of string
259
     */
260
    private $allowedImageFolders = array();
261
262
    /**
263
     * @var UrlGeneratorInterface
264
     */
265
    private $router;
266
267
    /**
268
     * @var Translator
269
     */
270
    private $translator;
271
272
    /**
273
     * Array to store all the arrays for the variables/parameters for all the different templates.
274
     * @var array of array
275
     */
276
    protected $paramArrays = array();
277
278
    /**
279
     * @var  string
280
     */
281
    protected $tracking_params_campaign_source;
282
283
    /**
284
     * @var  string
285
     */
286
    protected $tracking_params_campaign_medium;
287
288
    /**
289
     * @var  string
290
     */
291
    protected $tracking_params_campaign_content;
292
293
    /**
294
     * @var  string
295
     */
296
    protected $tracking_params_campaign_name;
297
298
    /**
299
     * @var  string
300
     */
301
    protected $tracking_params_campaign_term;
302
303
304
    /**
305
     * Array to store all the arrays for the code snippets for all the different temlpates.
306
     * @var unknown_type
307
     */
308
    protected $snippetArrays = array();
309
310 16
    public function __construct(UrlGeneratorInterface $router, Translator $translator, array $parameters)
311
    {
312 16
        $this->router = $router;
313 16
        $this->translator = $translator;
314 16
        $templateImageDir = realpath($parameters[AzineEmailExtension::TEMPLATE_IMAGE_DIR]);
315 16
        if ($this->templateImageDir !== false) {
316 16
            $this->templateImageDir = $templateImageDir."/";
317 16
        }
318
319 16
        foreach ($parameters[AzineEmailExtension::ALLOWED_IMAGES_FOLDERS] as $nextFolder) {
320 16
            $imageFolder = realpath($nextFolder);
321 16
            if ($imageFolder !== false) {
322 16
                $this->allowedImageFolders[md5($imageFolder)] = $imageFolder."/";
323 16
            }
324 16
        }
325 16
        $this->allowedImageFolders[md5($this->templateImageDir)] = $this->templateImageDir;
326 16
        $this->tracking_params_campaign_content = $parameters[AzineEmailExtension::TRACKING_PARAM_CAMPAIGN_CONTENT];
327 16
        $this->tracking_params_campaign_medium = $parameters[AzineEmailExtension::TRACKING_PARAM_CAMPAIGN_MEDIUM];
328 16
        $this->tracking_params_campaign_name = $parameters[AzineEmailExtension::TRACKING_PARAM_CAMPAIGN_NAME];
329 16
        $this->tracking_params_campaign_source = $parameters[AzineEmailExtension::TRACKING_PARAM_CAMPAIGN_SOURCE];
330 16
        $this->tracking_params_campaign_term = $parameters[AzineEmailExtension::TRACKING_PARAM_CAMPAIGN_TERM];
331 16
    }
332
333
    /**
334
     * (non-PHPdoc)
335
     * @see Azine\EmailBundle\Services.TemplateProviderInterface::getTemplateImageDir()
336
     */
337 9
    public function getTemplateImageDir()
338
    {
339 9
        return $this->templateImageDir;
340
    }
341
342
    /**
343
     * (non-PHPdoc)
344
     * @see Azine\EmailBundle\Services.TemplateProviderInterface::addTemplateVariablesFor()
345
     */
346 9
    public function addTemplateVariablesFor($template, array $contentVariables)
347
    {
348 9
        if (!array_key_exists($template, $this->paramArrays)) {
349 9
            $this->paramArrays[$template] = $this->getParamArrayFor($template);
350 9
        }
351
352
        // add vars for main template
353 9
        $contentVariables = array_merge($this->paramArrays[$template], $contentVariables);
354
355
        // add the template-variables to the contentItem-params-arrays
356 9 View Code Duplication
        if (array_key_exists(self::CONTENT_ITEMS, $contentVariables)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
357
358 6
            foreach ($contentVariables[self::CONTENT_ITEMS] as $key => $contentItem) {
359
                // get the key (=> template)
360 6
                reset($contentItem);
361 6
                $itemTemplate = key($contentItem);
362
363
                // get the params
364 6
                $itemParams = $contentItem[$itemTemplate];
365
366
                // add params for this template
367 6
                $contentItem[$itemTemplate] = $this->addTemplateVariablesFor($itemTemplate, $itemParams);
368
369
                // store back into the main array
370 6
                $contentVariables[self::CONTENT_ITEMS][$key] = $contentItem;
371 6
            }
372 6
        }
373
374 9
        return $contentVariables;
375
    }
376
377
    /**
378
     * (non-PHPdoc)
379
     * @see Azine\EmailBundle\Services.TemplateProviderInterface::addTemplateSnippetsWithImagesFor()
380
     */
381 9
    public function addTemplateSnippetsWithImagesFor($template, array $vars, $emailLocale, $forWebView = false)
382
    {
383 9
        $channel = $forWebView ? "webView" : "email";
384 9
        $templateKey = $channel.$template.$emailLocale;
385
386 9
        if (!array_key_exists($templateKey, $this->snippetArrays)) {
387 9
            $this->snippetArrays[$templateKey] = $this->getSnippetArrayFor($template, $vars, $emailLocale);
388 7
        }
389
390
        // add vars for main template
391 7
        $vars = array_merge($this->snippetArrays[$templateKey], $vars);
392
393
        // add the template-code-snippets to the contentItem-params-arrays
394 7 View Code Duplication
        if (array_key_exists(self::CONTENT_ITEMS, $vars)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
395
396 4
            foreach ($vars[self::CONTENT_ITEMS] as $key => $contentItem) {
397
                // get the key (=> template)
398 4
                reset($contentItem);
399 4
                $itemTemplate = key($contentItem);
400
401
                // get the params
402 4
                $itemParams = $contentItem[$itemTemplate];
403
404
                // add params for this template
405 4
                $contentItem[$itemTemplate] = $this->addTemplateSnippetsWithImagesFor($itemTemplate, $itemParams,  $emailLocale, $forWebView);
406
407
                // store back into the main array
408 4
                $vars[self::CONTENT_ITEMS][$key] = $contentItem;
409 4
            }
410 4
        }
411
412 7
        return $vars;
413
    }
414
415
    /**
416
     * @return UrlGeneratorInterface
417
     */
418 3
    protected function getRouter()
419
    {
420 3
        return $this->router;
421
    }
422
423
    /**
424
     * Only use the translator here when you already know in which language the user should get the email.
425
     * @param  string $emailLocale
426
     * @throws \Exception
427
     * @return Translator
428
     */
429 8
    protected function getTranslator($emailLocale)
430
    {
431 8
        if ($emailLocale === null) {
432 1
            throw new \Exception("Only use the translator here when you already know in which language the user should get the email.");
433
        }
434
435 7
        return $this->translator;
436
    }
437
438
    /**
439
     * Recursively replace all absolute image-file-paths with relative web-paths.
440
     * @param array $emailVars
441
     * @param string $locale
442
     * @return array
443
     */
444 3
    public function makeImagePathsWebRelative(array $emailVars, $locale)
445
    {
446 3
        foreach ($emailVars as $key => $value) {
447 3
            if (is_string($value) && is_file($value)) {
448
449
                // check if the file is in an allowed_images_folder
450 3
                $folderKey = $this->isFileAllowed($value);
451 3
                if ($folderKey !== false) {
452
453
                    // replace the fs-path with the web-path
454 3
                    $filename = substr($value, strrpos($value,"/")+1);
455 3
                    $newValue = $this->getRouter()->generate("azine_email_serve_template_image", array('folderKey' => $folderKey, 'filename' => $filename, '_locale' => $locale));
456 3
                    $emailVars[$key] = $newValue;
457 3
                }
458 3
            } elseif (is_array($value)) {
459
460 2
                $emailVars[$key] = $this->makeImagePathsWebRelative($value, $locale);
461 2
            }
462 3
        }
463
464 3
        return $emailVars;
465
    }
466
467
    /**
468
     * (non-PHPdoc)
469
     * @see Azine\EmailBundle\Services.TemplateProviderInterface::isFileAllowed()
470
     */
471 7
    public function isFileAllowed($filePath)
472
    {
473 7
        $filePath = realpath($filePath);
474 7
        foreach ($this->allowedImageFolders as $key => $nextFolder) {
475 7
            if (strpos($filePath, $nextFolder) === 0) {
476 7
                return $key;
477
            }
478 2
        }
479
480 2
        return false;
481
    }
482
483
    /**
484
     * (non-PHPdoc)
485
     * @see Azine\EmailBundle\Services.TemplateProviderInterface::getFolderFrom()
486
     */
487 1
    public function getFolderFrom($key)
488
    {
489 1
        if (array_key_exists($key, $this->allowedImageFolders)) {
490 1
            return $this->allowedImageFolders[$key];
491
        }
492
493 1
        return false;
494
    }
495
496
}
497