1 | <?php |
||
2 | |||
3 | namespace Azine\EmailBundle\Services; |
||
4 | |||
5 | use Symfony\Component\Translation\TranslatorInterface; |
||
6 | |||
7 | class AzineEmailTwigExtension extends \Twig_Extension |
||
8 | { |
||
9 | /** |
||
10 | * @var TemplateProviderInterface |
||
11 | */ |
||
12 | private $templateProvider; |
||
13 | |||
14 | /** |
||
15 | * @var TranslatorInterface |
||
16 | */ |
||
17 | private $translator; |
||
18 | |||
19 | /** |
||
20 | * @var array |
||
21 | */ |
||
22 | private $domainsToTrack; |
||
23 | |||
24 | /** |
||
25 | * @param TemplateProviderInterface $templateProvider |
||
26 | * @param array of string $domainsToTrack |
||
0 ignored issues
–
show
|
|||
27 | */ |
||
28 | 12 | public function __construct(TemplateProviderInterface $templateProvider, TranslatorInterface $translator, array $domainsToTrack = array()) |
|
29 | { |
||
30 | 12 | $this->templateProvider = $templateProvider; |
|
31 | 12 | $this->translator = $translator; |
|
32 | 12 | $this->domainsToTrack = $domainsToTrack; |
|
33 | 12 | } |
|
34 | |||
35 | /** |
||
36 | * {@inheritdoc} |
||
37 | */ |
||
38 | 1 | public function getFilters() |
|
39 | { |
||
40 | 1 | $filters[] = new \Twig_SimpleFilter('textWrap', array($this, 'textWrap')); |
|
41 | 1 | $filters[] = new \Twig_SimpleFilter('urlEncodeText', array($this, 'urlEncodeText'), array('is_safe' => array('html'))); |
|
42 | 1 | $filters[] = new \Twig_SimpleFilter('addCampaignParamsForTemplate', array($this, 'addCampaignParamsForTemplate'), array('is_safe' => array('html'))); |
|
43 | 1 | $filters[] = new \Twig_SimpleFilter('stripAndConvertTags', array($this, 'stripAndConvertTags'), array('is_safe' => array('html'))); |
|
44 | 1 | $filters[] = new \Twig_SimpleFilter('printVars', array($this, 'printVars')); |
|
45 | |||
46 | 1 | return $filters; |
|
47 | } |
||
48 | |||
49 | 1 | public function urlEncodeText($text) |
|
50 | { |
||
51 | 1 | $text = str_replace('%', '%25', $text); |
|
52 | 1 | $text = str_replace(array("\n", |
|
53 | ' ', |
||
54 | '&', |
||
55 | '\\', |
||
56 | '<', |
||
57 | '>', |
||
58 | '"', |
||
59 | ' ', |
||
60 | ), |
||
61 | 1 | array('%0D%0A', |
|
62 | '%20', |
||
63 | '%26', |
||
64 | '%5C', |
||
65 | '%3D', |
||
66 | '%3E', |
||
67 | '%23', |
||
68 | '%09', |
||
69 | 1 | ), $text); |
|
70 | |||
71 | 1 | return $text; |
|
72 | } |
||
73 | |||
74 | /** |
||
75 | * Wrap the text to the lineLength is not exeeded. |
||
76 | * |
||
77 | * @param string $text |
||
78 | * @param int $lineLength default: 75 |
||
79 | * |
||
80 | * @return string the wrapped string |
||
81 | */ |
||
82 | 3 | public function textWrap($text, $lineLength = 75) |
|
83 | { |
||
84 | 3 | return wordwrap($text, $lineLength); |
|
85 | } |
||
86 | |||
87 | /** |
||
88 | * Returns the name of the extension. |
||
89 | * |
||
90 | * @return string The extension name |
||
91 | */ |
||
92 | 1 | public function getName() |
|
93 | { |
||
94 | 1 | return 'azine_email_bundle_twig_extension'; |
|
95 | } |
||
96 | |||
97 | public function addCampaignParamsForTemplate($html, $templateId, $templateParams) |
||
98 | { |
||
99 | $campaignParams = $this->templateProvider->getCampaignParamsFor($templateId, $templateParams); |
||
100 | |||
101 | return $this->addCampaignParamsToAllUrls($html, $campaignParams); |
||
102 | } |
||
103 | |||
104 | /** |
||
105 | * Add the campaign-parameters to all URLs in the html. |
||
106 | * |
||
107 | * @param string $html |
||
108 | * @param array $campaignParams |
||
109 | * |
||
110 | * @return string |
||
111 | */ |
||
112 | 4 | public function addCampaignParamsToAllUrls($html, $campaignParams) |
|
113 | { |
||
114 | 4 | $urlPattern = '/(href=[\'|"])(http[s]?\:\/\/\S*)([\'|"])/'; |
|
115 | |||
116 | $filteredHtml = preg_replace_callback($urlPattern, function ($matches) use ($campaignParams) { |
||
117 | 4 | $start = $matches[1]; |
|
118 | 4 | $url = $matches[2]; |
|
119 | 4 | $end = $matches[3]; |
|
120 | 4 | $domain = parse_url($url, PHP_URL_HOST); |
|
121 | |||
122 | // if the url is not in the list of domains to track then |
||
123 | 4 | if (false === array_search($domain, $this->domainsToTrack)) { |
|
124 | // don't append tracking parameters to the url |
||
125 | 3 | return $start.$url.$end; |
|
126 | } |
||
127 | |||
128 | // avoid duplicate params and don't replace existing params |
||
129 | 1 | $params = array(); |
|
130 | 1 | foreach ($campaignParams as $nextKey => $nextValue) { |
|
131 | 1 | if (false === strpos($url, $nextKey)) { |
|
132 | 1 | $params[$nextKey] = $nextValue; |
|
133 | } |
||
134 | } |
||
135 | |||
136 | 1 | $urlParams = http_build_query($params); |
|
137 | |||
138 | 1 | if (false === strpos($url, '?')) { |
|
139 | 1 | $urlParams = '?'.$urlParams; |
|
140 | } else { |
||
141 | 1 | $urlParams = '&'.$urlParams; |
|
142 | } |
||
143 | |||
144 | 1 | $replacement = $start.$url.$urlParams.$end; |
|
145 | |||
146 | 1 | return $replacement; |
|
147 | 4 | }, $html); |
|
148 | |||
149 | 4 | return $filteredHtml; |
|
150 | } |
||
151 | |||
152 | /** |
||
153 | * Convert: |
||
154 | * - a-tags to show the link and if the link-text is not contained in the link, also the link-text |
||
155 | * - remove double-whitespaces and whitespaces at line beginnings and ends. |
||
156 | * - html-special chars to their original representation (php => htmlspecialchars_decode) |
||
157 | * and then remove all html-tags (php => strip_tags). |
||
158 | */ |
||
159 | public function stripAndConvertTags($html) |
||
160 | { |
||
161 | 1 | $linkConvertedHtml = preg_replace_callback('/<a.*?href=[\'|"](.+?)[\'|"].*?>(.*?)<\/a>/s', function ($matches) { |
|
162 | 1 | $url = $matches[1]; |
|
163 | 1 | $text = trim(strip_tags($matches[2])); |
|
164 | |||
165 | 1 | if (0 == strlen($text) || false !== stripos($url, $text)) { |
|
166 | 1 | $replacement = $url; |
|
167 | } else { |
||
168 | 1 | $replacement = $text.': '.$url; |
|
169 | } |
||
170 | |||
171 | 1 | return $replacement; |
|
172 | 1 | }, $html); |
|
173 | |||
174 | 1 | $txt = strip_tags($linkConvertedHtml); |
|
175 | 1 | $txt = preg_replace('/[[:blank:]]+/', ' ', $txt); |
|
176 | 1 | $txt = preg_replace("/\n[[:blank:]]/", "\n", $txt); |
|
177 | 1 | $txt = preg_replace("/[[:blank:]]\n/", "\n", $txt); |
|
178 | 1 | $txt = html_entity_decode($txt); |
|
179 | |||
180 | 1 | return $txt; |
|
181 | } |
||
182 | |||
183 | public function printVars(array $vars, $allDetails = false, $indent = '') |
||
184 | { |
||
185 | $output = ''; |
||
186 | $defaultIndent = ' '; |
||
187 | ksort($vars); |
||
188 | foreach ($vars as $key => $value) { |
||
189 | if ($allDetails && !((array) $value == $vars)) { // avoid infinite recursion |
||
190 | $value = "\n".$this->printVars((array) $value, $allDetails, $indent.$defaultIndent); |
||
191 | } else { |
||
192 | if (is_array($value)) { |
||
193 | $value = 'array('.sizeof($value).')'; |
||
194 | } elseif (is_object($value)) { |
||
195 | $value = 'object('.get_class($value).')'; |
||
196 | } |
||
197 | } |
||
198 | $output .= "$indent $key: $value\n"; |
||
199 | } |
||
200 | |||
201 | return $output; |
||
202 | } |
||
203 | } |
||
204 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths