Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like AzineTemplateProvider often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use AzineTemplateProvider, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
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) |
|
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) |
|
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) |
|
206 | |||
207 | /** |
||
208 | * (non-PHPdoc) |
||
209 | * @see Azine\EmailBundle\Services.TemplateProviderInterface::saveWebViewFor() |
||
210 | */ |
||
211 | 6 | public function saveWebViewFor($template) |
|
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() |
|
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() |
|
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) |
|
332 | |||
333 | /** |
||
334 | * (non-PHPdoc) |
||
335 | * @see Azine\EmailBundle\Services.TemplateProviderInterface::getTemplateImageDir() |
||
336 | */ |
||
337 | 9 | public function getTemplateImageDir() |
|
341 | |||
342 | /** |
||
343 | * (non-PHPdoc) |
||
344 | * @see Azine\EmailBundle\Services.TemplateProviderInterface::addTemplateVariablesFor() |
||
345 | */ |
||
346 | 9 | public function addTemplateVariablesFor($template, array $contentVariables) |
|
376 | |||
377 | /** |
||
378 | * (non-PHPdoc) |
||
379 | * @see Azine\EmailBundle\Services.TemplateProviderInterface::addTemplateSnippetsWithImagesFor() |
||
380 | */ |
||
381 | 9 | public function addTemplateSnippetsWithImagesFor($template, array $vars, $emailLocale, $forWebView = false) |
|
414 | |||
415 | /** |
||
416 | * @return UrlGeneratorInterface |
||
417 | */ |
||
418 | 3 | protected function getRouter() |
|
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) |
|
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) |
|
466 | |||
467 | /** |
||
468 | * (non-PHPdoc) |
||
469 | * @see Azine\EmailBundle\Services.TemplateProviderInterface::isFileAllowed() |
||
470 | */ |
||
471 | 7 | public function isFileAllowed($filePath) |
|
482 | |||
483 | /** |
||
484 | * (non-PHPdoc) |
||
485 | * @see Azine\EmailBundle\Services.TemplateProviderInterface::getFolderFrom() |
||
486 | */ |
||
487 | 1 | public function getFolderFrom($key) |
|
495 | |||
496 | } |
||
497 |
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.