1 | <?php |
||
2 | |||
3 | /* |
||
4 | * @copyright 2014 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\CampaignBundle\Controller; |
||
13 | |||
14 | use Mautic\CampaignBundle\Entity\Campaign; |
||
15 | use Mautic\CampaignBundle\Entity\Event; |
||
16 | use Mautic\CampaignBundle\Entity\LeadEventLogRepository; |
||
17 | use Mautic\CampaignBundle\EventCollector\EventCollector; |
||
18 | use Mautic\CampaignBundle\EventListener\CampaignActionJumpToEventSubscriber; |
||
19 | use Mautic\CampaignBundle\Model\CampaignModel; |
||
20 | use Mautic\CampaignBundle\Model\EventModel; |
||
21 | use Mautic\CoreBundle\Controller\AbstractStandardFormController; |
||
22 | use Mautic\CoreBundle\Form\Type\DateRangeType; |
||
23 | use Mautic\LeadBundle\Controller\EntityContactsTrait; |
||
24 | use Symfony\Component\Form\Form; |
||
25 | use Symfony\Component\Form\FormError; |
||
26 | use Symfony\Component\HttpFoundation\JsonResponse; |
||
27 | use Symfony\Component\HttpFoundation\Response; |
||
28 | |||
29 | class CampaignController extends AbstractStandardFormController |
||
30 | { |
||
31 | use EntityContactsTrait; |
||
32 | |||
33 | /** |
||
34 | * @var array |
||
35 | */ |
||
36 | protected $addedSources = []; |
||
37 | |||
38 | /** |
||
39 | * @var array |
||
40 | */ |
||
41 | protected $campaignEvents = []; |
||
42 | |||
43 | /** |
||
44 | * @var array |
||
45 | */ |
||
46 | protected $campaignSources = []; |
||
47 | |||
48 | /** |
||
49 | * @var array |
||
50 | */ |
||
51 | protected $connections = []; |
||
52 | |||
53 | /** |
||
54 | * @var array |
||
55 | */ |
||
56 | protected $deletedEvents = []; |
||
57 | |||
58 | /** |
||
59 | * @var array |
||
60 | */ |
||
61 | protected $deletedSources = []; |
||
62 | |||
63 | /** |
||
64 | * @var array |
||
65 | */ |
||
66 | protected $listFilters = []; |
||
67 | |||
68 | /** |
||
69 | * @var array |
||
70 | */ |
||
71 | protected $modifiedEvents = []; |
||
72 | |||
73 | protected $sessionId; |
||
74 | |||
75 | /** |
||
76 | * @return array |
||
77 | */ |
||
78 | protected function getPermissions() |
||
79 | { |
||
80 | //set some permissions |
||
81 | return (array) $this->get('mautic.security')->isGranted( |
||
82 | [ |
||
83 | 'campaign:campaigns:viewown', |
||
84 | 'campaign:campaigns:viewother', |
||
85 | 'campaign:campaigns:create', |
||
86 | 'campaign:campaigns:editown', |
||
87 | 'campaign:campaigns:editother', |
||
88 | 'campaign:campaigns:cloneown', |
||
89 | 'campaign:campaigns:cloneother', |
||
90 | 'campaign:campaigns:deleteown', |
||
91 | 'campaign:campaigns:deleteother', |
||
92 | 'campaign:campaigns:publishown', |
||
93 | 'campaign:campaigns:publishother', |
||
94 | ], |
||
95 | 'RETURN_ARRAY' |
||
96 | ); |
||
97 | } |
||
98 | |||
99 | /** |
||
100 | * Deletes a group of entities. |
||
101 | * |
||
102 | * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse |
||
103 | */ |
||
104 | public function batchDeleteAction() |
||
105 | { |
||
106 | return $this->batchDeleteStandard(); |
||
107 | } |
||
108 | |||
109 | /** |
||
110 | * Clone an entity. |
||
111 | * |
||
112 | * @param $objectId |
||
113 | * |
||
114 | * @return JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|Response |
||
115 | */ |
||
116 | public function cloneAction($objectId) |
||
117 | { |
||
118 | return $this->cloneStandard($objectId); |
||
119 | } |
||
120 | |||
121 | /** |
||
122 | * @param $objectId |
||
123 | * @param int $page |
||
124 | * |
||
125 | * @return JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|Response |
||
126 | */ |
||
127 | public function contactsAction($objectId, $page = 1) |
||
128 | { |
||
129 | return $this->generateContactsGrid( |
||
130 | $objectId, |
||
131 | $page, |
||
132 | 'campaign:campaigns:view', |
||
133 | 'campaign', |
||
134 | 'campaign_leads', |
||
135 | null, |
||
136 | 'campaign_id', |
||
137 | ['manually_removed' => 0] |
||
138 | ); |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * Deletes the entity. |
||
143 | * |
||
144 | * @param $objectId |
||
145 | * |
||
146 | * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse |
||
147 | */ |
||
148 | public function deleteAction($objectId) |
||
149 | { |
||
150 | return $this->deleteStandard($objectId); |
||
151 | } |
||
152 | |||
153 | /** |
||
154 | * @param $objectId |
||
155 | * @param bool $ignorePost |
||
156 | * |
||
157 | * @return JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|Response |
||
158 | */ |
||
159 | public function editAction($objectId, $ignorePost = false) |
||
160 | { |
||
161 | return $this->editStandard($objectId, $ignorePost); |
||
162 | } |
||
163 | |||
164 | /** |
||
165 | * @param int $page |
||
166 | * |
||
167 | * @return JsonResponse|\Symfony\Component\HttpFoundation\Response |
||
168 | */ |
||
169 | public function indexAction($page = null) |
||
170 | { |
||
171 | return $this->indexStandard($page); |
||
172 | } |
||
173 | |||
174 | /** |
||
175 | * Generates new form and processes post data. |
||
176 | * |
||
177 | * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response |
||
178 | */ |
||
179 | public function newAction() |
||
180 | { |
||
181 | return $this->newStandard(); |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * View a specific campaign. |
||
186 | * |
||
187 | * @param $objectId |
||
188 | * |
||
189 | * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\Response |
||
190 | */ |
||
191 | public function viewAction($objectId) |
||
192 | { |
||
193 | return $this->viewStandard($objectId, $this->getModelName(), null, null, 'campaign'); |
||
194 | } |
||
195 | |||
196 | /** |
||
197 | * @param Campaign $campaign |
||
198 | * @param Campaign $oldCampaign |
||
199 | */ |
||
200 | protected function afterEntityClone($campaign, $oldCampaign) |
||
201 | { |
||
202 | $tempId = 'mautic_'.sha1(uniqid(mt_rand(), true)); |
||
203 | $objectId = $oldCampaign->getId(); |
||
204 | |||
205 | // Get the events that need to be duplicated as well |
||
206 | $events = $oldCampaign->getEvents()->toArray(); |
||
207 | |||
208 | $campaign->setIsPublished(false); |
||
209 | |||
210 | // Clone the campaign's events |
||
211 | /** @var Event $event */ |
||
212 | foreach ($events as $event) { |
||
213 | $tempEventId = 'new'.$event->getId(); |
||
214 | |||
215 | $clone = clone $event; |
||
216 | $clone->nullId(); |
||
217 | $clone->setCampaign($campaign); |
||
218 | $clone->setTempId($tempEventId); |
||
219 | |||
220 | // Just wipe out the parent as it'll be generated when the cloned entity is saved |
||
221 | $clone->setParent(null); |
||
222 | |||
223 | if (CampaignActionJumpToEventSubscriber::EVENT_NAME === $clone->getType()) { |
||
224 | // Update properties to point to the new temp ID |
||
225 | $properties = $clone->getProperties(); |
||
226 | $properties['jumpToEvent'] = 'new'.$properties['jumpToEvent']; |
||
227 | |||
228 | $clone->setProperties($properties); |
||
229 | } |
||
230 | |||
231 | $campaign->addEvent($tempEventId, $clone); |
||
232 | } |
||
233 | |||
234 | // Update canvas settings with new event ids |
||
235 | $canvasSettings = $campaign->getCanvasSettings(); |
||
236 | if (isset($canvasSettings['nodes'])) { |
||
237 | foreach ($canvasSettings['nodes'] as &$node) { |
||
238 | // Only events and not lead sources |
||
239 | if (is_numeric($node['id'])) { |
||
240 | $node['id'] = 'new'.$node['id']; |
||
241 | } |
||
242 | } |
||
243 | } |
||
244 | |||
245 | if (isset($canvasSettings['connections'])) { |
||
246 | foreach ($canvasSettings['connections'] as &$c) { |
||
247 | // Only events and not lead sources |
||
248 | if (is_numeric($c['sourceId'])) { |
||
249 | $c['sourceId'] = 'new'.$c['sourceId']; |
||
250 | } |
||
251 | |||
252 | // Only events and not lead sources |
||
253 | if (is_numeric($c['targetId'])) { |
||
254 | $c['targetId'] = 'new'.$c['targetId']; |
||
255 | } |
||
256 | } |
||
257 | } |
||
258 | |||
259 | // Simulate edit |
||
260 | $campaign->setCanvasSettings($canvasSettings); |
||
261 | $this->setSessionCanvasSettings($tempId, $canvasSettings); |
||
262 | $tempId = $this->getCampaignSessionId($campaign, 'clone', $tempId); |
||
263 | |||
264 | $campaignSources = $this->getCampaignModel()->getLeadSources($objectId); |
||
265 | $this->prepareCampaignSourcesForEdit($tempId, $campaignSources); |
||
266 | } |
||
267 | |||
268 | /** |
||
269 | * @param $entity |
||
270 | * @param $action |
||
271 | * @param null $persistConnections |
||
272 | */ |
||
273 | protected function afterEntitySave($entity, Form $form, $action, $persistConnections = null) |
||
274 | { |
||
275 | if ($persistConnections) { |
||
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
276 | // Update canvas settings with new event IDs then save |
||
277 | $this->connections = $this->getCampaignModel()->setCanvasSettings($entity, $this->connections); |
||
278 | } else { |
||
279 | // Just update and add to entity |
||
280 | $this->connections = $this->getCampaignModel()->setCanvasSettings($entity, $this->connections, false, $this->modifiedEvents); |
||
281 | } |
||
282 | } |
||
283 | |||
284 | /** |
||
285 | * @param $isValid |
||
286 | * @param $entity |
||
287 | * @param $action |
||
288 | * @param bool $isClone |
||
289 | */ |
||
290 | protected function afterFormProcessed($isValid, $entity, Form $form, $action, $isClone = false) |
||
291 | { |
||
292 | if (!$isValid) { |
||
293 | // Add the canvas settings to the entity to be able to rebuild it |
||
294 | $this->afterEntitySave($entity, $form, $action, false); |
||
295 | } else { |
||
296 | $this->clearSessionComponents($this->sessionId); |
||
297 | $this->sessionId = $entity->getId(); |
||
298 | } |
||
299 | } |
||
300 | |||
301 | /** |
||
302 | * @param $entity |
||
303 | * @param $action |
||
304 | * @param $isPost |
||
305 | * @param null $objectId |
||
306 | * @param bool $isClone |
||
307 | */ |
||
308 | protected function beforeFormProcessed($entity, Form $form, $action, $isPost, $objectId = null, $isClone = false) |
||
309 | { |
||
310 | $sessionId = $this->getCampaignSessionId($entity, $action, $objectId); |
||
311 | //set added/updated events |
||
312 | list($this->modifiedEvents, $this->deletedEvents, $this->campaignEvents) = $this->getSessionEvents($sessionId); |
||
313 | |||
314 | //set added/updated sources |
||
315 | list($this->addedSources, $this->deletedSources, $campaignSources) = $this->getSessionSources($sessionId, $isClone); |
||
316 | $this->connections = $this->getSessionCanvasSettings($sessionId); |
||
317 | |||
318 | if ($isPost) { |
||
319 | $this->getCampaignModel()->setCanvasSettings($entity, $this->connections, false, $this->modifiedEvents); |
||
320 | $this->prepareCampaignSourcesForEdit($sessionId, $campaignSources, true); |
||
321 | } else { |
||
322 | if (!$isClone) { |
||
323 | //clear out existing fields in case the form was refreshed, browser closed, etc |
||
324 | $this->clearSessionComponents($sessionId); |
||
325 | $this->modifiedEvents = $this->campaignSources = []; |
||
326 | |||
327 | if ($entity->getId()) { |
||
328 | $campaignSources = $this->getCampaignModel()->getLeadSources($entity->getId()); |
||
329 | $this->prepareCampaignSourcesForEdit($sessionId, $campaignSources); |
||
330 | |||
331 | $this->setSessionCanvasSettings($sessionId, $entity->getCanvasSettings()); |
||
332 | } |
||
333 | } |
||
334 | |||
335 | $this->deletedEvents = []; |
||
336 | |||
337 | $form->get('sessionId')->setData($sessionId); |
||
338 | |||
339 | $this->prepareCampaignEventsForEdit($entity, $sessionId, $isClone); |
||
340 | } |
||
341 | } |
||
342 | |||
343 | /** |
||
344 | * @param Campaign $entity |
||
345 | * @param $action |
||
346 | * @param null $objectId |
||
347 | * @param bool $isClone |
||
348 | * |
||
349 | * @return bool |
||
350 | */ |
||
351 | protected function beforeEntitySave($entity, Form $form, $action, $objectId = null, $isClone = false) |
||
352 | { |
||
353 | if (empty($this->campaignEvents)) { |
||
354 | //set the error |
||
355 | $form->addError( |
||
356 | new FormError( |
||
357 | $this->get('translator')->trans('mautic.campaign.form.events.notempty', [], 'validators') |
||
358 | ) |
||
359 | ); |
||
360 | |||
361 | return false; |
||
362 | } |
||
363 | |||
364 | if (empty($this->campaignSources['lists']) && empty($this->campaignSources['forms'])) { |
||
365 | //set the error |
||
366 | $form->addError( |
||
367 | new FormError( |
||
368 | $this->get('translator')->trans('mautic.campaign.form.sources.notempty', [], 'validators') |
||
369 | ) |
||
370 | ); |
||
371 | |||
372 | return false; |
||
373 | } |
||
374 | |||
375 | if ($isClone) { |
||
376 | list($this->addedSources, $this->deletedSources, $campaignSources) = $this->getSessionSources($objectId, $isClone); |
||
377 | $this->getCampaignModel()->setLeadSources($entity, $campaignSources, []); |
||
378 | // If this is a clone, we need to save the entity first to properly build the events, sources and canvas settings |
||
379 | $this->getCampaignModel()->getRepository()->saveEntity($entity); |
||
380 | // Set as new so that timestamps are still hydrated |
||
381 | $entity->setNew(); |
||
382 | $this->sessionId = $entity->getId(); |
||
383 | } |
||
384 | |||
385 | // Set lead sources |
||
386 | $this->getCampaignModel()->setLeadSources($entity, $this->addedSources, $this->deletedSources); |
||
387 | |||
388 | // Build and set Event entities |
||
389 | $this->getCampaignModel()->setEvents($entity, $this->campaignEvents, $this->connections, $this->deletedEvents); |
||
390 | |||
391 | if ('edit' === $action && null !== $this->connections) { |
||
392 | if (!empty($this->deletedEvents)) { |
||
393 | /** @var EventModel $eventModel */ |
||
394 | $eventModel = $this->getModel('campaign.event'); |
||
395 | $eventModel->deleteEvents($entity->getEvents()->toArray(), $this->deletedEvents); |
||
396 | } |
||
397 | } |
||
398 | |||
399 | return true; |
||
400 | } |
||
401 | |||
402 | /** |
||
403 | * Clear field and events from the session. |
||
404 | * |
||
405 | * @param $id |
||
406 | */ |
||
407 | protected function clearSessionComponents($id) |
||
408 | { |
||
409 | $session = $this->get('session'); |
||
410 | $session->remove('mautic.campaign.'.$id.'.events.modified'); |
||
411 | $session->remove('mautic.campaign.'.$id.'.events.deleted'); |
||
412 | $session->remove('mautic.campaign.'.$id.'.events.canvassettings'); |
||
413 | $session->remove('mautic.campaign.'.$id.'.leadsources.current'); |
||
414 | $session->remove('mautic.campaign.'.$id.'.leadsources.modified'); |
||
415 | $session->remove('mautic.campaign.'.$id.'.leadsources.deleted'); |
||
416 | } |
||
417 | |||
418 | /** |
||
419 | * @return CampaignModel |
||
420 | */ |
||
421 | protected function getCampaignModel() |
||
422 | { |
||
423 | /** @var CampaignModel $model */ |
||
424 | $model = $this->getModel($this->getModelName()); |
||
425 | |||
426 | return $model; |
||
427 | } |
||
428 | |||
429 | /** |
||
430 | * @param $action |
||
431 | * @param null $objectId |
||
432 | * |
||
433 | * @return int|string|null |
||
434 | */ |
||
435 | protected function getCampaignSessionId(Campaign $campaign, $action, $objectId = null) |
||
436 | { |
||
437 | if (isset($this->sessionId)) { |
||
438 | return $this->sessionId; |
||
439 | } |
||
440 | |||
441 | if ($objectId) { |
||
0 ignored issues
–
show
|
|||
442 | $sessionId = $objectId; |
||
443 | } elseif ('new' === $action && empty($sessionId)) { |
||
444 | $sessionId = 'mautic_'.sha1(uniqid(mt_rand(), true)); |
||
445 | if ($this->request->request->has('campaign')) { |
||
446 | $campaign = $this->request->request->get('campaign', []); |
||
447 | $sessionId = $campaign['sessionId'] ?? $sessionId; |
||
448 | } |
||
449 | } elseif ('edit' === $action) { |
||
450 | $sessionId = $campaign->getId(); |
||
451 | } |
||
452 | |||
453 | $this->sessionId = $sessionId; |
||
454 | |||
455 | return $sessionId; |
||
456 | } |
||
457 | |||
458 | /** |
||
459 | * @return string |
||
460 | */ |
||
461 | protected function getControllerBase() |
||
462 | { |
||
463 | return 'MauticCampaignBundle:Campaign'; |
||
464 | } |
||
465 | |||
466 | /** |
||
467 | * @param $start |
||
468 | * @param $limit |
||
469 | * @param $filter |
||
470 | * @param $orderBy |
||
471 | * @param $orderByDir |
||
472 | */ |
||
473 | protected function getIndexItems($start, $limit, $filter, $orderBy, $orderByDir, array $args = []) |
||
474 | { |
||
475 | $session = $this->get('session'); |
||
476 | $currentFilters = $session->get('mautic.campaign.list_filters', []); |
||
477 | $updatedFilters = $this->request->get('filters', false); |
||
478 | |||
479 | $sourceLists = $this->getCampaignModel()->getSourceLists(); |
||
480 | $listFilters = [ |
||
481 | 'filters' => [ |
||
482 | 'placeholder' => $this->get('translator')->trans('mautic.campaign.filter.placeholder'), |
||
483 | 'multiple' => true, |
||
484 | 'groups' => [ |
||
485 | 'mautic.campaign.leadsource.form' => [ |
||
486 | 'options' => $sourceLists['forms'], |
||
487 | 'prefix' => 'form', |
||
488 | ], |
||
489 | 'mautic.campaign.leadsource.list' => [ |
||
490 | 'options' => $sourceLists['lists'], |
||
491 | 'prefix' => 'list', |
||
492 | ], |
||
493 | ], |
||
494 | ], |
||
495 | ]; |
||
496 | |||
497 | if ($updatedFilters) { |
||
498 | // Filters have been updated |
||
499 | |||
500 | // Parse the selected values |
||
501 | $newFilters = []; |
||
502 | $updatedFilters = json_decode($updatedFilters, true); |
||
503 | |||
504 | if ($updatedFilters) { |
||
505 | foreach ($updatedFilters as $updatedFilter) { |
||
506 | list($clmn, $fltr) = explode(':', $updatedFilter); |
||
507 | |||
508 | $newFilters[$clmn][] = $fltr; |
||
509 | } |
||
510 | |||
511 | $currentFilters = $newFilters; |
||
512 | } else { |
||
513 | $currentFilters = []; |
||
514 | } |
||
515 | } |
||
516 | $session->set('mautic.campaign.list_filters', $currentFilters); |
||
517 | |||
518 | $joinLists = $joinForms = false; |
||
519 | if (!empty($currentFilters)) { |
||
520 | $listIds = $catIds = []; |
||
521 | foreach ($currentFilters as $type => $typeFilters) { |
||
522 | $listFilters['filters']['groups']['mautic.campaign.leadsource.'.$type]['values'] = $typeFilters; |
||
523 | |||
524 | foreach ($typeFilters as $fltr) { |
||
525 | if ('list' == $type) { |
||
526 | $listIds[] = (int) $fltr; |
||
527 | } else { |
||
528 | $formIds[] = (int) $fltr; |
||
529 | } |
||
530 | } |
||
531 | } |
||
532 | |||
533 | if (!empty($listIds)) { |
||
534 | $joinLists = true; |
||
535 | $filter['force'][] = ['column' => 'l.id', 'expr' => 'in', 'value' => $listIds]; |
||
536 | } |
||
537 | |||
538 | if (!empty($formIds)) { |
||
539 | $joinForms = true; |
||
540 | $filter['force'][] = ['column' => 'f.id', 'expr' => 'in', 'value' => $formIds]; |
||
541 | } |
||
542 | } |
||
543 | |||
544 | // Store for customizeViewArguments |
||
545 | $this->listFilters = $listFilters; |
||
546 | |||
547 | return parent::getIndexItems( |
||
548 | $start, |
||
549 | $limit, |
||
550 | $filter, |
||
551 | $orderBy, |
||
552 | $orderByDir, |
||
553 | [ |
||
554 | 'joinLists' => $joinLists, |
||
555 | 'joinForms' => $joinForms, |
||
556 | ] |
||
557 | ); |
||
558 | } |
||
559 | |||
560 | /** |
||
561 | * @return string |
||
562 | */ |
||
563 | protected function getModelName() |
||
564 | { |
||
565 | return 'campaign'; |
||
566 | } |
||
567 | |||
568 | /** |
||
569 | * @param $action |
||
570 | * |
||
571 | * @return array |
||
572 | */ |
||
573 | protected function getPostActionRedirectArguments(array $args, $action) |
||
574 | { |
||
575 | switch ($action) { |
||
576 | case 'new': |
||
577 | case 'edit': |
||
578 | if (!empty($args['entity'])) { |
||
579 | $sessionId = $this->getCampaignSessionId($args['entity'], $action); |
||
580 | $this->clearSessionComponents($sessionId); |
||
581 | } |
||
582 | break; |
||
583 | } |
||
584 | |||
585 | return $args; |
||
586 | } |
||
587 | |||
588 | /** |
||
589 | * Get events from session. |
||
590 | * |
||
591 | * @param $id |
||
592 | * |
||
593 | * @return array |
||
594 | */ |
||
595 | protected function getSessionEvents($id) |
||
596 | { |
||
597 | $session = $this->get('session'); |
||
598 | |||
599 | $modifiedEvents = $session->get('mautic.campaign.'.$id.'.events.modified', []); |
||
600 | $deletedEvents = $session->get('mautic.campaign.'.$id.'.events.deleted', []); |
||
601 | |||
602 | $events = array_diff_key($modifiedEvents, array_flip($deletedEvents)); |
||
603 | |||
604 | return [$modifiedEvents, $deletedEvents, $events]; |
||
605 | } |
||
606 | |||
607 | /** |
||
608 | * Get events from session. |
||
609 | * |
||
610 | * @param $id |
||
611 | * @param $isClone |
||
612 | * |
||
613 | * @return array |
||
614 | */ |
||
615 | protected function getSessionSources($id, $isClone = false) |
||
616 | { |
||
617 | $session = $this->get('session'); |
||
618 | |||
619 | $campaignSources = $session->get('mautic.campaign.'.$id.'.leadsources.current', []); |
||
620 | $modifiedSources = $session->get('mautic.campaign.'.$id.'.leadsources.modified', []); |
||
621 | |||
622 | if ($campaignSources === $modifiedSources) { |
||
623 | if ($isClone) { |
||
624 | // Clone hasn't saved the sources yet so return the current list as added |
||
625 | return [$campaignSources, [], $campaignSources]; |
||
626 | } else { |
||
627 | return [[], [], $campaignSources]; |
||
628 | } |
||
629 | } |
||
630 | |||
631 | // Deleted sources |
||
632 | $deletedSources = []; |
||
633 | foreach ($campaignSources as $type => $sources) { |
||
634 | if (isset($modifiedSources[$type])) { |
||
635 | $deletedSources[$type] = array_diff_key($sources, $modifiedSources[$type]); |
||
636 | } else { |
||
637 | $deletedSources[$type] = $sources; |
||
638 | } |
||
639 | } |
||
640 | |||
641 | // Added sources |
||
642 | $addedSources = []; |
||
643 | foreach ($modifiedSources as $type => $sources) { |
||
644 | if (isset($campaignSources[$type])) { |
||
645 | $addedSources[$type] = array_diff_key($sources, $campaignSources[$type]); |
||
646 | } else { |
||
647 | $addedSources[$type] = $sources; |
||
648 | } |
||
649 | } |
||
650 | |||
651 | return [$addedSources, $deletedSources, $modifiedSources]; |
||
652 | } |
||
653 | |||
654 | /** |
||
655 | * @param $action |
||
656 | * |
||
657 | * @return array |
||
658 | */ |
||
659 | protected function getViewArguments(array $args, $action) |
||
660 | { |
||
661 | /** @var EventCollector $eventCollector */ |
||
662 | $eventCollector = $this->get('mautic.campaign.event_collector'); |
||
663 | |||
664 | switch ($action) { |
||
665 | case 'index': |
||
666 | $args['viewParameters']['filters'] = $this->listFilters; |
||
667 | break; |
||
668 | case 'view': |
||
669 | /** @var Campaign $entity */ |
||
670 | $entity = $args['entity']; |
||
671 | $objectId = $args['objectId']; |
||
672 | // Init the date range filter form |
||
673 | $dateRangeValues = $this->request->get('daterange', []); |
||
674 | $action = $this->generateUrl('mautic_campaign_action', ['objectAction' => 'view', 'objectId' => $objectId]); |
||
675 | $dateRangeForm = $this->get('form.factory')->create(DateRangeType::class, $dateRangeValues, ['action' => $action]); |
||
676 | |||
677 | /** @var LeadEventLogRepository $eventLogRepo */ |
||
678 | $eventLogRepo = $this->getDoctrine()->getManager()->getRepository('MauticCampaignBundle:LeadEventLog'); |
||
679 | $events = $this->getCampaignModel()->getEventRepository()->getCampaignEvents($entity->getId()); |
||
680 | $leadCount = $this->getCampaignModel()->getRepository()->getCampaignLeadCount($entity->getId()); |
||
681 | $campaignLogCounts = $eventLogRepo->getCampaignLogCounts($entity->getId(), false, false, true); |
||
682 | $pendingCampaignLogCounts = $eventLogRepo->getCampaignLogCounts($entity->getId(), false, false); |
||
683 | $sortedEvents = [ |
||
684 | 'decision' => [], |
||
685 | 'action' => [], |
||
686 | 'condition' => [], |
||
687 | ]; |
||
688 | foreach ($events as &$event) { |
||
689 | $event['logCount'] = |
||
690 | $event['logCountForPending'] = |
||
691 | $event['percent'] = |
||
692 | $event['yesPercent'] = |
||
693 | $event['noPercent'] = 0; |
||
694 | $event['leadCount'] = $leadCount; |
||
695 | |||
696 | if (isset($campaignLogCounts[$event['id']])) { |
||
697 | $event['logCount'] = array_sum($campaignLogCounts[$event['id']]); |
||
698 | $event['logCountForPending'] = isset($pendingCampaignLogCounts[$event['id']]) ? array_sum($pendingCampaignLogCounts[$event['id']]) : 0; |
||
699 | |||
700 | $pending = $event['leadCount'] - $event['logCountForPending']; |
||
701 | $totalYes = $campaignLogCounts[$event['id']][1]; |
||
702 | $totalNo = $campaignLogCounts[$event['id']][0]; |
||
703 | $total = $totalYes + $totalNo + $pending; |
||
704 | if ($leadCount) { |
||
705 | $event['percent'] = round(($event['logCount'] / $total) * 100, 1); |
||
706 | $event['yesPercent'] = round(($campaignLogCounts[$event['id']][1] / $total) * 100, 1); |
||
707 | $event['noPercent'] = round(($campaignLogCounts[$event['id']][0] / $total) * 100, 1); |
||
708 | } |
||
709 | } |
||
710 | } |
||
711 | |||
712 | // rewrite stats data from parent condition if exist |
||
713 | foreach ($events as &$event) { |
||
714 | if (!empty($event['decisionPath']) && !empty($event['parent_id']) && isset($events[$event['parent_id']])) { |
||
715 | $parentEvent = $events[$event['parent_id']]; |
||
716 | $event['logCountForPending'] = $parentEvent['logCountForPending']; |
||
717 | $event['percent'] = $parentEvent['percent']; |
||
718 | $event['yesPercent'] = $parentEvent['yesPercent']; |
||
719 | $event['noPercent'] = $parentEvent['noPercent']; |
||
720 | if ('yes' == $event['decisionPath']) { |
||
721 | $event['noPercent'] = 0; |
||
722 | } else { |
||
723 | $event['yesPercent'] = 0; |
||
724 | } |
||
725 | } |
||
726 | $sortedEvents[$event['eventType']][] = $event; |
||
727 | } |
||
728 | |||
729 | $stats = $this->getCampaignModel()->getCampaignMetricsLineChartData( |
||
730 | null, |
||
731 | new \DateTime($dateRangeForm->get('date_from')->getData()), |
||
732 | new \DateTime($dateRangeForm->get('date_to')->getData()), |
||
733 | null, |
||
734 | ['campaign_id' => $objectId] |
||
735 | ); |
||
736 | |||
737 | $campaignSources = $this->getCampaignModel()->getSourceLists(); |
||
738 | |||
739 | $this->prepareCampaignSourcesForEdit($objectId, $campaignSources, true); |
||
740 | $this->prepareCampaignEventsForEdit($entity, $objectId, true); |
||
741 | |||
742 | $args['viewParameters'] = array_merge( |
||
743 | $args['viewParameters'], |
||
744 | [ |
||
745 | 'campaign' => $entity, |
||
746 | 'stats' => $stats, |
||
747 | 'events' => $sortedEvents, |
||
748 | 'eventSettings' => $eventCollector->getEventsArray(), |
||
749 | 'sources' => $this->getCampaignModel()->getLeadSources($entity), |
||
750 | 'dateRangeForm' => $dateRangeForm->createView(), |
||
751 | 'campaignSources' => $this->campaignSources, |
||
752 | 'campaignEvents' => $events, |
||
753 | 'campaignLeads' => $this->forward( |
||
754 | 'MauticCampaignBundle:Campaign:contacts', |
||
755 | [ |
||
756 | 'objectId' => $entity->getId(), |
||
757 | 'page' => $this->get('session')->get('mautic.campaign.contact.page', 1), |
||
758 | 'ignoreAjax' => true, |
||
759 | ] |
||
760 | )->getContent(), |
||
761 | ] |
||
762 | ); |
||
763 | break; |
||
764 | |||
765 | case 'new': |
||
766 | case 'edit': |
||
767 | $args['viewParameters'] = array_merge( |
||
768 | $args['viewParameters'], |
||
769 | [ |
||
770 | 'eventSettings' => $eventCollector->getEventsArray(), |
||
771 | 'campaignEvents' => $this->campaignEvents, |
||
772 | 'campaignSources' => $this->campaignSources, |
||
773 | 'deletedEvents' => $this->deletedEvents, |
||
774 | ] |
||
775 | ); |
||
776 | break; |
||
777 | } |
||
778 | |||
779 | return $args; |
||
780 | } |
||
781 | |||
782 | /** |
||
783 | * @param $entity |
||
784 | * @param $objectId |
||
785 | * @param bool $isClone |
||
786 | * |
||
787 | * @return array |
||
788 | */ |
||
789 | protected function prepareCampaignEventsForEdit($entity, $objectId, $isClone = false) |
||
790 | { |
||
791 | //load existing events into session |
||
792 | $campaignEvents = []; |
||
793 | |||
794 | $existingEvents = $entity->getEvents()->toArray(); |
||
795 | $translator = $this->get('translator'); |
||
796 | $dateHelper = $this->get('mautic.helper.template.date'); |
||
797 | foreach ($existingEvents as $e) { |
||
798 | $event = $e->convertToArray(); |
||
799 | |||
800 | if ($isClone) { |
||
801 | $id = $e->getTempId(); |
||
802 | $event['id'] = $id; |
||
803 | } else { |
||
804 | $id = $e->getId(); |
||
805 | } |
||
806 | |||
807 | unset($event['campaign']); |
||
808 | unset($event['children']); |
||
809 | unset($event['parent']); |
||
810 | unset($event['log']); |
||
811 | |||
812 | $label = false; |
||
813 | switch ($event['triggerMode']) { |
||
814 | case 'interval': |
||
815 | $label = $translator->trans( |
||
816 | 'mautic.campaign.connection.trigger.interval.label'.('no' == $event['decisionPath'] ? '_inaction' : ''), |
||
817 | [ |
||
818 | '%number%' => $event['triggerInterval'], |
||
819 | '%unit%' => $translator->transChoice( |
||
820 | 'mautic.campaign.event.intervalunit.'.$event['triggerIntervalUnit'], |
||
821 | $event['triggerInterval'] |
||
822 | ), |
||
823 | ] |
||
824 | ); |
||
825 | break; |
||
826 | case 'date': |
||
827 | $label = $translator->trans( |
||
828 | 'mautic.campaign.connection.trigger.date.label'.('no' == $event['decisionPath'] ? '_inaction' : ''), |
||
829 | [ |
||
830 | '%full%' => $dateHelper->toFull($event['triggerDate']), |
||
831 | '%time%' => $dateHelper->toTime($event['triggerDate']), |
||
832 | '%date%' => $dateHelper->toShort($event['triggerDate']), |
||
833 | ] |
||
834 | ); |
||
835 | break; |
||
836 | } |
||
837 | if ($label) { |
||
838 | $event['label'] = $label; |
||
839 | } |
||
840 | |||
841 | $campaignEvents[$id] = $event; |
||
842 | } |
||
843 | |||
844 | $this->modifiedEvents = $this->campaignEvents = $campaignEvents; |
||
845 | $this->get('session')->set('mautic.campaign.'.$objectId.'.events.modified', $campaignEvents); |
||
846 | } |
||
847 | |||
848 | /** |
||
849 | * @param $objectId |
||
850 | * @param $campaignSources |
||
851 | */ |
||
852 | protected function prepareCampaignSourcesForEdit($objectId, $campaignSources, $isPost = false) |
||
853 | { |
||
854 | $this->campaignSources = []; |
||
855 | if (is_array($campaignSources)) { |
||
856 | foreach ($campaignSources as $type => $sources) { |
||
857 | if (!empty($sources)) { |
||
858 | $sourceList = $this->getModel('campaign')->getSourceLists($type); |
||
859 | $this->campaignSources[$type] = [ |
||
860 | 'sourceType' => $type, |
||
861 | 'campaignId' => $objectId, |
||
862 | 'names' => implode(', ', array_intersect_key($sourceList, $sources)), |
||
863 | ]; |
||
864 | } |
||
865 | } |
||
866 | } |
||
867 | |||
868 | if (!$isPost) { |
||
869 | $session = $this->get('session'); |
||
870 | $session->set('mautic.campaign.'.$objectId.'.leadsources.current', $campaignSources); |
||
871 | $session->set('mautic.campaign.'.$objectId.'.leadsources.modified', $campaignSources); |
||
872 | } |
||
873 | } |
||
874 | |||
875 | /** |
||
876 | * @param $sessionId |
||
877 | * @param $canvasSettings |
||
878 | */ |
||
879 | protected function setSessionCanvasSettings($sessionId, $canvasSettings) |
||
880 | { |
||
881 | $this->get('session')->set('mautic.campaign.'.$sessionId.'.events.canvassettings', $canvasSettings); |
||
882 | } |
||
883 | |||
884 | /** |
||
885 | * @param $sessionId |
||
886 | * |
||
887 | * @return mixed |
||
888 | */ |
||
889 | protected function getSessionCanvasSettings($sessionId) |
||
890 | { |
||
891 | return $this->get('session')->get('mautic.campaign.'.$sessionId.'.events.canvassettings'); |
||
892 | } |
||
893 | } |
||
894 |