1 | <?php |
||||
2 | |||||
3 | /* |
||||
4 | * @copyright 2016 Mautic Contributors. All rights reserved |
||||
5 | * @author Mautic |
||||
6 | * |
||||
7 | * @link http://mautic.org |
||||
8 | * |
||||
9 | * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html |
||||
10 | */ |
||||
11 | |||||
12 | namespace Mautic\DynamicContentBundle\EventListener; |
||||
13 | |||||
14 | use DOMDocument; |
||||
15 | use DOMXPath; |
||||
16 | use Mautic\AssetBundle\Helper\TokenHelper as AssetTokenHelper; |
||||
17 | use Mautic\CoreBundle\Event as MauticEvents; |
||||
18 | use Mautic\CoreBundle\Model\AuditLogModel; |
||||
19 | use Mautic\CoreBundle\Security\Permissions\CorePermissions; |
||||
20 | use Mautic\DynamicContentBundle\DynamicContentEvents; |
||||
21 | use Mautic\DynamicContentBundle\Entity\DynamicContent; |
||||
22 | use Mautic\DynamicContentBundle\Event as Events; |
||||
23 | use Mautic\DynamicContentBundle\Helper\DynamicContentHelper; |
||||
24 | use Mautic\DynamicContentBundle\Model\DynamicContentModel; |
||||
25 | use Mautic\EmailBundle\EventListener\MatchFilterForLeadTrait; |
||||
26 | use Mautic\FormBundle\Helper\TokenHelper as FormTokenHelper; |
||||
27 | use Mautic\LeadBundle\Entity\Lead; |
||||
28 | use Mautic\LeadBundle\Helper\TokenHelper; |
||||
29 | use Mautic\LeadBundle\Tracker\ContactTracker; |
||||
30 | use Mautic\PageBundle\Entity\Trackable; |
||||
31 | use Mautic\PageBundle\Event\PageDisplayEvent; |
||||
32 | use Mautic\PageBundle\Helper\TokenHelper as PageTokenHelper; |
||||
33 | use Mautic\PageBundle\Model\TrackableModel; |
||||
34 | use Mautic\PageBundle\PageEvents; |
||||
35 | use MauticPlugin\MauticFocusBundle\Helper\TokenHelper as FocusTokenHelper; |
||||
36 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; |
||||
37 | |||||
38 | class DynamicContentSubscriber implements EventSubscriberInterface |
||||
39 | { |
||||
40 | use MatchFilterForLeadTrait; |
||||
41 | |||||
42 | /** |
||||
43 | * @var TrackableModel |
||||
44 | */ |
||||
45 | private $trackableModel; |
||||
46 | |||||
47 | /** |
||||
48 | * @var PageTokenHelper |
||||
49 | */ |
||||
50 | private $pageTokenHelper; |
||||
51 | |||||
52 | /** |
||||
53 | * @var AssetTokenHelper |
||||
54 | */ |
||||
55 | private $assetTokenHelper; |
||||
56 | |||||
57 | /** |
||||
58 | * @var FormTokenHelper |
||||
59 | */ |
||||
60 | private $formTokenHelper; |
||||
61 | |||||
62 | /** |
||||
63 | * @var FocusTokenHelper |
||||
64 | */ |
||||
65 | private $focusTokenHelper; |
||||
66 | |||||
67 | /** |
||||
68 | * @var AuditLogModel |
||||
69 | */ |
||||
70 | private $auditLogModel; |
||||
71 | |||||
72 | /** |
||||
73 | * @var DynamicContentHelper |
||||
74 | */ |
||||
75 | private $dynamicContentHelper; |
||||
76 | |||||
77 | /** |
||||
78 | * @var DynamicContentModel |
||||
79 | */ |
||||
80 | private $dynamicContentModel; |
||||
81 | |||||
82 | /** |
||||
83 | * @var CorePermissions |
||||
84 | */ |
||||
85 | private $security; |
||||
86 | |||||
87 | /** |
||||
88 | * @var ContactTracker |
||||
89 | */ |
||||
90 | private $contactTracker; |
||||
91 | |||||
92 | public function __construct( |
||||
93 | TrackableModel $trackableModel, |
||||
94 | PageTokenHelper $pageTokenHelper, |
||||
95 | AssetTokenHelper $assetTokenHelper, |
||||
96 | FormTokenHelper $formTokenHelper, |
||||
97 | FocusTokenHelper $focusTokenHelper, |
||||
98 | AuditLogModel $auditLogModel, |
||||
99 | DynamicContentHelper $dynamicContentHelper, |
||||
100 | DynamicContentModel $dynamicContentModel, |
||||
101 | CorePermissions $security, |
||||
102 | ContactTracker $contactTracker |
||||
103 | ) { |
||||
104 | $this->trackableModel = $trackableModel; |
||||
105 | $this->pageTokenHelper = $pageTokenHelper; |
||||
106 | $this->assetTokenHelper = $assetTokenHelper; |
||||
107 | $this->formTokenHelper = $formTokenHelper; |
||||
108 | $this->focusTokenHelper = $focusTokenHelper; |
||||
109 | $this->auditLogModel = $auditLogModel; |
||||
110 | $this->dynamicContentHelper = $dynamicContentHelper; |
||||
111 | $this->dynamicContentModel = $dynamicContentModel; |
||||
112 | $this->security = $security; |
||||
113 | $this->contactTracker = $contactTracker; |
||||
114 | } |
||||
115 | |||||
116 | /** |
||||
117 | * @return array |
||||
118 | */ |
||||
119 | public static function getSubscribedEvents() |
||||
120 | { |
||||
121 | return [ |
||||
122 | DynamicContentEvents::POST_SAVE => ['onPostSave', 0], |
||||
123 | DynamicContentEvents::POST_DELETE => ['onDelete', 0], |
||||
124 | DynamicContentEvents::TOKEN_REPLACEMENT => ['onTokenReplacement', 0], |
||||
125 | PageEvents::PAGE_ON_DISPLAY => ['decodeTokens', 254], |
||||
126 | ]; |
||||
127 | } |
||||
128 | |||||
129 | /** |
||||
130 | * Add an entry to the audit log. |
||||
131 | */ |
||||
132 | public function onPostSave(Events\DynamicContentEvent $event) |
||||
133 | { |
||||
134 | $entity = $event->getDynamicContent(); |
||||
135 | if ($details = $event->getChanges()) { |
||||
136 | $log = [ |
||||
137 | 'bundle' => 'dynamicContent', |
||||
138 | 'object' => 'dynamicContent', |
||||
139 | 'objectId' => $entity->getId(), |
||||
140 | 'action' => ($event->isNew()) ? 'create' : 'update', |
||||
141 | 'details' => $details, |
||||
142 | ]; |
||||
143 | $this->auditLogModel->writeToLog($log); |
||||
144 | } |
||||
145 | } |
||||
146 | |||||
147 | /** |
||||
148 | * Add a delete entry to the audit log. |
||||
149 | */ |
||||
150 | public function onDelete(Events\DynamicContentEvent $event) |
||||
151 | { |
||||
152 | $entity = $event->getDynamicContent(); |
||||
153 | $log = [ |
||||
154 | 'bundle' => 'dynamicContent', |
||||
155 | 'object' => 'dynamicContent', |
||||
156 | 'objectId' => $entity->deletedId, |
||||
157 | 'action' => 'delete', |
||||
158 | 'details' => ['name' => $entity->getName()], |
||||
159 | ]; |
||||
160 | $this->auditLogModel->writeToLog($log); |
||||
161 | } |
||||
162 | |||||
163 | public function onTokenReplacement(MauticEvents\TokenReplacementEvent $event) |
||||
164 | { |
||||
165 | /** @var Lead $lead */ |
||||
166 | $lead = $event->getLead(); |
||||
167 | $content = $event->getContent(); |
||||
168 | $clickthrough = $event->getClickthrough(); |
||||
169 | |||||
170 | if ($content) { |
||||
171 | $tokens = array_merge( |
||||
172 | TokenHelper::findLeadTokens($content, $lead->getProfileFields()), |
||||
173 | $this->pageTokenHelper->findPageTokens($content, $clickthrough), |
||||
174 | $this->assetTokenHelper->findAssetTokens($content, $clickthrough), |
||||
175 | $this->formTokenHelper->findFormTokens($content), |
||||
176 | $this->focusTokenHelper->findFocusTokens($content) |
||||
177 | ); |
||||
178 | |||||
179 | list($content, $trackables) = $this->trackableModel->parseContentForTrackables( |
||||
180 | $content, |
||||
181 | $tokens, |
||||
182 | 'dynamicContent', |
||||
183 | $clickthrough['dynamic_content_id'] |
||||
184 | ); |
||||
185 | |||||
186 | $dwc = $this->dynamicContentModel->getEntity($clickthrough['dynamic_content_id']); |
||||
187 | $utmTags = []; |
||||
188 | if ($dwc && $dwc instanceof DynamicContent) { |
||||
189 | $utmTags = $dwc->getUtmTags(); |
||||
190 | } |
||||
191 | |||||
192 | /** |
||||
193 | * @var string |
||||
194 | * @var Trackable $trackable |
||||
195 | */ |
||||
196 | foreach ($trackables as $token => $trackable) { |
||||
197 | $tokens[$token] = $this->trackableModel->generateTrackableUrl($trackable, $clickthrough, false, $utmTags); |
||||
198 | } |
||||
199 | |||||
200 | $content = str_replace(array_keys($tokens), array_values($tokens), $content); |
||||
201 | |||||
202 | $event->setContent($content); |
||||
203 | } |
||||
204 | } |
||||
205 | |||||
206 | public function decodeTokens(PageDisplayEvent $event) |
||||
207 | { |
||||
208 | $lead = $this->security->isAnonymous() ? $this->contactTracker->getContact() : null; |
||||
209 | if (!$lead) { |
||||
210 | return; |
||||
211 | } |
||||
212 | |||||
213 | $content = $event->getContent(); |
||||
214 | if (empty($content)) { |
||||
215 | return; |
||||
216 | } |
||||
217 | |||||
218 | $tokens = $this->dynamicContentHelper->findDwcTokens($content, $lead); |
||||
219 | $leadArray = []; |
||||
220 | if ($lead instanceof Lead) { |
||||
0 ignored issues
–
show
introduced
by
Loading history...
|
|||||
221 | $leadArray = $this->dynamicContentHelper->convertLeadToArray($lead); |
||||
222 | } |
||||
223 | $result = []; |
||||
224 | foreach ($tokens as $token => $dwc) { |
||||
225 | $result[$token] = ''; |
||||
226 | if ($this->matchFilterForLead($dwc['filters'], $leadArray)) { |
||||
227 | $result[$token] = $dwc['content']; |
||||
228 | } |
||||
229 | } |
||||
230 | $content = str_replace(array_keys($result), array_values($result), $content); |
||||
231 | |||||
232 | // replace slots |
||||
233 | $dom = new DOMDocument('1.0', 'utf-8'); |
||||
234 | $dom->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'), LIBXML_NOERROR); |
||||
0 ignored issues
–
show
It seems like
mb_convert_encoding($con...TML-ENTITIES', 'UTF-8') can also be of type array ; however, parameter $source of DOMDocument::loadHTML() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
235 | $xpath = new DOMXPath($dom); |
||||
236 | |||||
237 | $divContent = $xpath->query('//*[@data-slot="dwc"]'); |
||||
238 | for ($i = 0; $i < $divContent->length; ++$i) { |
||||
239 | $slot = $divContent->item($i); |
||||
240 | if (!$slotName = $slot->getAttribute('data-param-slot-name')) { |
||||
241 | continue; |
||||
242 | } |
||||
243 | |||||
244 | if (!$slotContent = $this->dynamicContentHelper->getDynamicContentForLead($slotName, $lead)) { |
||||
245 | continue; |
||||
246 | } |
||||
247 | |||||
248 | $newnode = $dom->createDocumentFragment(); |
||||
249 | $newnode->appendXML('<![CDATA['.mb_convert_encoding($slotContent, 'HTML-ENTITIES', 'UTF-8').']]>'); |
||||
250 | $slot->parentNode->replaceChild($newnode, $slot); |
||||
251 | } |
||||
252 | |||||
253 | $content = $dom->saveHTML(); |
||||
254 | |||||
255 | $event->setContent($content); |
||||
256 | } |
||||
257 | } |
||||
258 |