Issues (3627)

app/bundles/EmailBundle/Entity/Email.php (1 issue)

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\EmailBundle\Entity;
13
14
use Doctrine\Common\Collections\ArrayCollection;
15
use Doctrine\DBAL\Types\Type;
16
use Doctrine\ORM\Events;
17
use Doctrine\ORM\Mapping as ORM;
18
use Doctrine\ORM\PersistentCollection;
19
use Mautic\ApiBundle\Serializer\Driver\ApiMetadataDriver;
20
use Mautic\AssetBundle\Entity\Asset;
21
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
22
use Mautic\CoreBundle\Entity\DynamicContentEntityTrait;
23
use Mautic\CoreBundle\Entity\FormEntity;
24
use Mautic\CoreBundle\Entity\TranslationEntityInterface;
25
use Mautic\CoreBundle\Entity\TranslationEntityTrait;
26
use Mautic\CoreBundle\Entity\VariantEntityInterface;
27
use Mautic\CoreBundle\Entity\VariantEntityTrait;
28
use Mautic\CoreBundle\Helper\EmojiHelper;
29
use Mautic\FormBundle\Entity\Form;
30
use Mautic\LeadBundle\Entity\LeadList;
31
use Mautic\LeadBundle\Form\Validator\Constraints\LeadListAccess;
32
use Mautic\PageBundle\Entity\Page;
33
use Symfony\Component\Validator\Constraints\Callback;
34
use Symfony\Component\Validator\Constraints\NotBlank;
35
use Symfony\Component\Validator\Context\ExecutionContextInterface;
36
use Symfony\Component\Validator\Mapping\ClassMetadata;
37
38
/**
39
 * Class Email.
40
 */
41
class Email extends FormEntity implements VariantEntityInterface, TranslationEntityInterface
42
{
43
    use VariantEntityTrait;
44
    use TranslationEntityTrait;
45
    use DynamicContentEntityTrait;
46
47
    /**
48
     * @var int
49
     */
50
    private $id;
51
52
    /**
53
     * @var string
54
     */
55
    private $name;
56
57
    /**
58
     * @var string
59
     */
60
    private $description;
61
62
    /**
63
     * @var string
64
     */
65
    private $subject;
66
67
    /**
68
     * @var string
69
     */
70
    private $fromAddress;
71
72
    /**
73
     * @var string
74
     */
75
    private $fromName;
76
77
    /**
78
     * @var string
79
     */
80
    private $replyToAddress;
81
82
    /**
83
     * @var string
84
     */
85
    private $bccAddress;
86
87
    /**
88
     * @var string
89
     */
90
    private $template;
91
92
    /**
93
     * @var array
94
     */
95
    private $content = [];
96
97
    /**
98
     * @var array
99
     */
100
    private $utmTags = [];
101
102
    /**
103
     * @var string
104
     */
105
    private $plainText;
106
107
    /**
108
     * @var string
109
     */
110
    private $customHtml;
111
112
    /**
113
     * @var string
114
     */
115
    private $emailType = 'template';
116
117
    /**
118
     * @var \DateTime
119
     */
120
    private $publishUp;
121
122
    /**
123
     * @var \DateTime
124
     */
125
    private $publishDown;
126
127
    /**
128
     * @var bool
129
     */
130
    private $publicPreview = 1;
131
132
    /**
133
     * @var int
134
     */
135
    private $readCount = 0;
136
137
    /**
138
     * @var int
139
     */
140
    private $sentCount = 0;
141
142
    /**
143
     * @var int
144
     */
145
    private $revision = 1;
146
147
    /**
148
     * @var \Mautic\CategoryBundle\Entity\Category
149
     **/
150
    private $category;
151
152
    /**
153
     * @var ArrayCollection
154
     */
155
    private $lists;
156
157
    /**
158
     * @var ArrayCollection
159
     */
160
    private $stats;
161
162
    /**
163
     * @var int
164
     */
165
    private $variantSentCount = 0;
166
167
    /**
168
     * @var int
169
     */
170
    private $variantReadCount = 0;
171
172
    /**
173
     * @var \Mautic\FormBundle\Entity\Form
174
     */
175
    private $unsubscribeForm;
176
177
    /**
178
     * @var \Mautic\PageBundle\Entity\Page
179
     */
180
    private $preferenceCenter;
181
182
    /**
183
     * @var ArrayCollection
184
     */
185
    private $assetAttachments;
186
187
    /**
188
     * Used to identify the page for the builder.
189
     */
190
    private $sessionId;
191
192
    /**
193
     * @var array
194
     */
195
    private $headers = [];
196
197
    /**
198
     * @var int
199
     */
200
    private $pendingCount = 0;
201
202
    /**
203
     * @var int
204
     */
205
    private $queuedCount = 0;
206
207
    /**
208
     * In some use cases, we need to get the original email ID after it's been cloned.
209
     *
210
     * @var int
211
     */
212
    private $clonedId;
213
214
    public function __clone()
215
    {
216
        $this->clonedId         = $this->id;
217
        $this->id               = null;
218
        $this->sentCount        = 0;
219
        $this->readCount        = 0;
220
        $this->revision         = 0;
221
        $this->variantSentCount = 0;
222
        $this->variantReadCount = 0;
223
        $this->variantStartDate = null;
224
        $this->emailType        = null;
225
        $this->sessionId        = 'new_'.hash('sha1', uniqid(mt_rand()));
226
        $this->clearTranslations();
227
        $this->clearVariants();
228
        $this->clearStats();
229
230
        parent::__clone();
231
    }
232
233
    /**
234
     * Email constructor.
235
     */
236
    public function __construct()
237
    {
238
        $this->lists               = new ArrayCollection();
239
        $this->stats               = new ArrayCollection();
240
        $this->translationChildren = new ArrayCollection();
241
        $this->variantChildren     = new ArrayCollection();
242
        $this->assetAttachments    = new ArrayCollection();
243
    }
244
245
    /**
246
     * Clear stats.
247
     */
248
    public function clearStats()
249
    {
250
        $this->stats = new ArrayCollection();
251
    }
252
253
    public static function loadMetadata(ORM\ClassMetadata $metadata)
254
    {
255
        $builder = new ClassMetadataBuilder($metadata);
256
257
        $builder->setTable('emails')
258
            ->setCustomRepositoryClass(EmailRepository::class)
259
            ->addLifecycleEvent('cleanUrlsInContent', Events::preUpdate)
260
            ->addLifecycleEvent('cleanUrlsInContent', Events::prePersist);
261
262
        $builder->addIdColumns();
263
        $builder->addNullableField('subject', Type::TEXT);
264
        $builder->addNullableField('fromAddress', Type::STRING, 'from_address');
265
        $builder->addNullableField('fromName', Type::STRING, 'from_name');
266
        $builder->addNullableField('replyToAddress', Type::STRING, 'reply_to_address');
267
        $builder->addNullableField('bccAddress', Type::STRING, 'bcc_address');
268
        $builder->addNullableField('template', Type::STRING);
269
        $builder->addNullableField('content', Type::TARRAY);
270
        $builder->addNullableField('utmTags', Type::TARRAY, 'utm_tags');
271
        $builder->addNullableField('plainText', Type::TEXT, 'plain_text');
272
        $builder->addNullableField('customHtml', Type::TEXT, 'custom_html');
273
        $builder->addNullableField('emailType', Type::TEXT, 'email_type');
274
        $builder->addPublishDates();
275
        $builder->addNamedField('readCount', Type::INTEGER, 'read_count');
276
        $builder->addNamedField('sentCount', Type::INTEGER, 'sent_count');
277
        $builder->addNamedField('variantSentCount', Type::INTEGER, 'variant_sent_count');
278
        $builder->addNamedField('variantReadCount', Type::INTEGER, 'variant_read_count');
279
        $builder->addField('revision', Type::INTEGER);
280
        $builder->addCategory();
281
282
        $builder->createManyToMany('lists', LeadList::class)
283
            ->setJoinTable('email_list_xref')
284
            ->setIndexBy('id')
285
            ->addInverseJoinColumn('leadlist_id', 'id', false, false, 'CASCADE')
286
            ->addJoinColumn('email_id', 'id', false, false, 'CASCADE')
287
            ->fetchExtraLazy()
288
            ->build();
289
290
        $builder->createOneToMany('stats', 'Stat')
291
            ->setIndexBy('id')
292
            ->mappedBy('email')
293
            ->cascadePersist()
294
            ->fetchExtraLazy()
295
            ->build();
296
297
        self::addTranslationMetadata($builder, self::class);
298
        self::addVariantMetadata($builder, self::class);
299
        self::addDynamicContentMetadata($builder);
300
301
        $builder->createManyToOne('unsubscribeForm', Form::class)
302
            ->addJoinColumn('unsubscribeform_id', 'id', true, false, 'SET NULL')
303
            ->build();
304
305
        $builder->createManyToOne('preferenceCenter', Page::class)
306
            ->addJoinColumn('preference_center_id', 'id', true, false, 'SET NULL')
307
            ->build();
308
309
        $builder->createManyToMany('assetAttachments', Asset::class)
310
            ->setJoinTable('email_assets_xref')
311
            ->addInverseJoinColumn('asset_id', 'id', false, false, 'CASCADE')
312
            ->addJoinColumn('email_id', 'id', false, false, 'CASCADE')
313
            ->fetchExtraLazy()
314
            ->build();
315
316
        $builder->addField('headers', 'json_array');
317
318
        $builder->addNullableField('publicPreview', Type::BOOLEAN, 'public_preview');
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::BOOLEAN has been deprecated: Use {@see Types::BOOLEAN} instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

318
        $builder->addNullableField('publicPreview', /** @scrutinizer ignore-deprecated */ Type::BOOLEAN, 'public_preview');

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
319
    }
320
321
    public static function loadValidatorMetadata(ClassMetadata $metadata)
322
    {
323
        $metadata->addPropertyConstraint(
324
            'name',
325
            new NotBlank(
326
                [
327
                    'message' => 'mautic.core.name.required',
328
                ]
329
            )
330
        );
331
332
        $metadata->addPropertyConstraint(
333
            'subject',
334
            new NotBlank(
335
                [
336
                    'message' => 'mautic.core.subject.required',
337
                ]
338
            )
339
        );
340
341
        $metadata->addPropertyConstraint(
342
            'fromAddress',
343
            new \Symfony\Component\Validator\Constraints\Email(
344
                [
345
                    'message' => 'mautic.core.email.required',
346
                ]
347
            )
348
        );
349
350
        $metadata->addPropertyConstraint(
351
            'replyToAddress',
352
            new \Symfony\Component\Validator\Constraints\Email(
353
                [
354
                    'message' => 'mautic.core.email.required',
355
                ]
356
            )
357
        );
358
359
        $metadata->addPropertyConstraint(
360
            'bccAddress',
361
            new \Symfony\Component\Validator\Constraints\Email(
362
                [
363
                    'message' => 'mautic.core.email.required',
364
                ]
365
            )
366
        );
367
368
        $metadata->addConstraint(new Callback([
369
            'callback' => function (Email $email, ExecutionContextInterface $context) {
370
                $type = $email->getEmailType();
371
                $translationParent = $email->getTranslationParent();
372
373
                if ('list' == $type && null == $translationParent) {
374
                    $validator = $context->getValidator();
375
                    $violations = $validator->validate(
376
                        $email->getLists(),
377
                        [
378
                            new LeadListAccess(),
379
                            new NotBlank(
380
                                [
381
                                    'message' => 'mautic.lead.lists.required',
382
                                ]
383
                            ),
384
                        ]
385
                    );
386
                    if (count($violations) > 0) {
387
                        foreach ($violations as $violation) {
388
                            $context->buildViolation($violation->getMessage())
389
                                ->atPath('lists')
390
                                ->addViolation();
391
                        }
392
                    }
393
                }
394
395
                if ($email->isVariant()) {
396
                    // Get a summation of weights
397
                    $parent = $email->getVariantParent();
398
                    $children = $parent ? $parent->getVariantChildren() : $email->getVariantChildren();
399
400
                    $total = 0;
401
                    foreach ($children as $child) {
402
                        $settings = $child->getVariantSettings();
403
                        $total += (int) $settings['weight'];
404
                    }
405
406
                    if ($total > 100) {
407
                        $context->buildViolation('mautic.core.variant_weights_invalid')
408
                            ->atPath('variantSettings[weight]')
409
                            ->addViolation();
410
                    }
411
                }
412
            },
413
        ]));
414
    }
415
416
    /**
417
     * Prepares the metadata for API usage.
418
     *
419
     * @param $metadata
420
     */
421
    public static function loadApiMetadata(ApiMetadataDriver $metadata)
422
    {
423
        $metadata->setGroupPrefix('email')
424
            ->addListProperties(
425
                [
426
                    'id',
427
                    'name',
428
                    'subject',
429
                    'language',
430
                    'category',
431
                ]
432
            )
433
            ->addProperties(
434
                [
435
                    'fromAddress',
436
                    'fromName',
437
                    'replyToAddress',
438
                    'bccAddress',
439
                    'utmTags',
440
                    'customHtml',
441
                    'plainText',
442
                    'template',
443
                    'emailType',
444
                    'publishUp',
445
                    'publishDown',
446
                    'readCount',
447
                    'sentCount',
448
                    'revision',
449
                    'assetAttachments',
450
                    'variantStartDate',
451
                    'variantSentCount',
452
                    'variantReadCount',
453
                    'variantParent',
454
                    'variantChildren',
455
                    'translationParent',
456
                    'translationChildren',
457
                    'unsubscribeForm',
458
                    'dynamicContent',
459
                    'lists',
460
                    'headers',
461
                ]
462
            )
463
            ->build();
464
    }
465
466
    /**
467
     * @param $prop
468
     * @param $val
469
     */
470
    protected function isChanged($prop, $val)
471
    {
472
        $getter  = 'get'.ucfirst($prop);
473
        $current = $this->$getter();
474
475
        if ('variantParent' == $prop || 'translationParent' == $prop || 'category' == $prop || 'list' == $prop) {
476
            $currentId = ($current) ? $current->getId() : '';
477
            $newId     = ($val) ? $val->getId() : null;
478
            if ($currentId != $newId) {
479
                $this->changes[$prop] = [$currentId, $newId];
480
            }
481
        } else {
482
            parent::isChanged($prop, $val);
483
        }
484
    }
485
486
    /**
487
     * @return mixed
488
     */
489
    public function getName()
490
    {
491
        return $this->name;
492
    }
493
494
    /**
495
     * @param $name
496
     *
497
     * @return $this
498
     */
499
    public function setName($name)
500
    {
501
        $this->name = $name;
502
503
        return $this;
504
    }
505
506
    /**
507
     * @return mixed
508
     */
509
    public function getDescription()
510
    {
511
        return $this->description;
512
    }
513
514
    /**
515
     * @param mixed $description
516
     *
517
     * @return Email
518
     */
519
    public function setDescription($description)
520
    {
521
        $this->description = $description;
522
523
        return $this;
524
    }
525
526
    /**
527
     * Get id.
528
     *
529
     * @return int
530
     */
531
    public function getId()
532
    {
533
        return $this->id;
534
    }
535
536
    /**
537
     * @return mixed
538
     */
539
    public function getCategory()
540
    {
541
        return $this->category;
542
    }
543
544
    /**
545
     * @param $category
546
     *
547
     * @return $this
548
     */
549
    public function setCategory($category)
550
    {
551
        $this->isChanged('category', $category);
552
        $this->category = $category;
553
554
        return $this;
555
    }
556
557
    /**
558
     * @return array
559
     */
560
    public function getContent()
561
    {
562
        return $this->content;
563
    }
564
565
    /**
566
     * @param $content
567
     *
568
     * @return $this
569
     */
570
    public function setContent($content)
571
    {
572
        // Ensure safe emoji
573
        $content = EmojiHelper::toShort($content);
574
575
        $this->isChanged('content', $content);
576
        $this->content = $content;
577
578
        return $this;
579
    }
580
581
    /**
582
     * @return array
583
     */
584
    public function getUtmTags()
585
    {
586
        return $this->utmTags;
587
    }
588
589
    /**
590
     * @param array $utmTags
591
     */
592
    public function setUtmTags($utmTags)
593
    {
594
        $this->isChanged('utmTags', $utmTags);
595
        $this->utmTags = $utmTags;
596
597
        return $this;
598
    }
599
600
    /**
601
     * @return mixed
602
     */
603
    public function getReadCount($includeVariants = false)
604
    {
605
        return ($includeVariants) ? $this->getAccumulativeVariantCount('getReadCount') : $this->readCount;
606
    }
607
608
    /**
609
     * @param $readCount
610
     *
611
     * @return $this
612
     */
613
    public function setReadCount($readCount)
614
    {
615
        $this->readCount = $readCount;
616
617
        return $this;
618
    }
619
620
    /**
621
     * @return mixed
622
     */
623
    public function getRevision()
624
    {
625
        return $this->revision;
626
    }
627
628
    /**
629
     * @param $revision
630
     *
631
     * @return $this
632
     */
633
    public function setRevision($revision)
634
    {
635
        $this->revision = $revision;
636
637
        return $this;
638
    }
639
640
    /**
641
     * @return mixed
642
     */
643
    public function getSessionId()
644
    {
645
        return $this->sessionId;
646
    }
647
648
    /**
649
     * @param $sessionId
650
     *
651
     * @return $this
652
     */
653
    public function setSessionId($sessionId)
654
    {
655
        $this->sessionId = $sessionId;
656
657
        return $this;
658
    }
659
660
    /**
661
     * @return mixed
662
     */
663
    public function getSubject()
664
    {
665
        return $this->subject;
666
    }
667
668
    /**
669
     * @param $subject
670
     *
671
     * @return $this
672
     */
673
    public function setSubject($subject)
674
    {
675
        $this->isChanged('subject', $subject);
676
        $this->subject = $subject;
677
678
        return $this;
679
    }
680
681
    /**
682
     * @return mixed
683
     */
684
    public function getFromAddress()
685
    {
686
        return $this->fromAddress;
687
    }
688
689
    /**
690
     * @param mixed $fromAddress
691
     *
692
     * @return Email
693
     */
694
    public function setFromAddress($fromAddress)
695
    {
696
        $this->fromAddress = $fromAddress;
697
698
        return $this;
699
    }
700
701
    /**
702
     * @return mixed
703
     */
704
    public function getFromName()
705
    {
706
        return $this->fromName;
707
    }
708
709
    /**
710
     * @param mixed $fromName
711
     *
712
     * @return Email
713
     */
714
    public function setFromName($fromName)
715
    {
716
        $this->fromName = $fromName;
717
718
        return $this;
719
    }
720
721
    /**
722
     * @return mixed
723
     */
724
    public function getReplyToAddress()
725
    {
726
        return $this->replyToAddress;
727
    }
728
729
    /**
730
     * @param mixed $replyToAddress
731
     *
732
     * @return Email
733
     */
734
    public function setReplyToAddress($replyToAddress)
735
    {
736
        $this->replyToAddress = $replyToAddress;
737
738
        return $this;
739
    }
740
741
    /**
742
     * @return mixed
743
     */
744
    public function getBccAddress()
745
    {
746
        return $this->bccAddress;
747
    }
748
749
    /**
750
     * @param mixed $bccAddress
751
     *
752
     * @return Email
753
     */
754
    public function setBccAddress($bccAddress)
755
    {
756
        $this->bccAddress = $bccAddress;
757
758
        return $this;
759
    }
760
761
    /**
762
     * @return mixed
763
     */
764
    public function getTemplate()
765
    {
766
        return $this->template;
767
    }
768
769
    /**
770
     * @param $template
771
     *
772
     * @return $this
773
     */
774
    public function setTemplate($template)
775
    {
776
        $this->isChanged('template', $template);
777
        $this->template = $template;
778
779
        return $this;
780
    }
781
782
    /**
783
     * @return mixed
784
     */
785
    public function getPublishDown()
786
    {
787
        return $this->publishDown;
788
    }
789
790
    /**
791
     * @param $publishDown
792
     *
793
     * @return $this
794
     */
795
    public function setPublishDown($publishDown)
796
    {
797
        $this->isChanged('publishDown', $publishDown);
798
        $this->publishDown = $publishDown;
799
800
        return $this;
801
    }
802
803
    /**
804
     * @return mixed
805
     */
806
    public function getPublishUp()
807
    {
808
        return $this->publishUp;
809
    }
810
811
    /**
812
     * @param $publishUp
813
     *
814
     * @return $this
815
     */
816
    public function setPublishUp($publishUp)
817
    {
818
        $this->isChanged('publishUp', $publishUp);
819
        $this->publishUp = $publishUp;
820
821
        return $this;
822
    }
823
824
    /**
825
     * @param bool $includeVariants
826
     *
827
     * @return mixed
828
     */
829
    public function getSentCount($includeVariants = false)
830
    {
831
        return ($includeVariants) ? $this->getAccumulativeVariantCount('getSentCount') : $this->sentCount;
832
    }
833
834
    /**
835
     * @param $sentCount
836
     *
837
     * @return $this
838
     */
839
    public function setSentCount($sentCount)
840
    {
841
        $this->sentCount = $sentCount;
842
843
        return $this;
844
    }
845
846
    /**
847
     * @return mixed
848
     */
849
    public function getVariantSentCount($includeVariants = false)
850
    {
851
        return ($includeVariants) ? $this->getAccumulativeVariantCount('getVariantSentCount') : $this->variantSentCount;
852
    }
853
854
    /**
855
     * @param $variantSentCount
856
     *
857
     * @return $this
858
     */
859
    public function setVariantSentCount($variantSentCount)
860
    {
861
        $this->variantSentCount = $variantSentCount;
862
863
        return $this;
864
    }
865
866
    /**
867
     * @return PersistentCollection
868
     */
869
    public function getLists()
870
    {
871
        return $this->lists;
872
    }
873
874
    /**
875
     * Add list.
876
     *
877
     * @return Email
878
     */
879
    public function addList(LeadList $list)
880
    {
881
        $this->lists[] = $list;
882
883
        return $this;
884
    }
885
886
    /**
887
     * Set the lists for this translation.
888
     */
889
    public function setLists(array $lists = [])
890
    {
891
        $this->lists = $lists;
892
893
        return $this;
894
    }
895
896
    /**
897
     * Remove list.
898
     */
899
    public function removeList(LeadList $list)
900
    {
901
        $this->lists->removeElement($list);
902
    }
903
904
    /**
905
     * @return mixed
906
     */
907
    public function getPlainText()
908
    {
909
        return $this->plainText;
910
    }
911
912
    /**
913
     * @param $plainText
914
     *
915
     * @return $this
916
     */
917
    public function setPlainText($plainText)
918
    {
919
        $this->plainText = $plainText;
920
921
        return $this;
922
    }
923
924
    /**
925
     * @return mixed
926
     */
927
    public function getVariantReadCount()
928
    {
929
        return $this->variantReadCount;
930
    }
931
932
    /**
933
     * @param $variantReadCount
934
     *
935
     * @return $this
936
     */
937
    public function setVariantReadCount($variantReadCount)
938
    {
939
        $this->variantReadCount = $variantReadCount;
940
941
        return $this;
942
    }
943
944
    /**
945
     * @return mixed
946
     */
947
    public function getStats()
948
    {
949
        return $this->stats;
950
    }
951
952
    /**
953
     * @return mixed
954
     */
955
    public function getCustomHtml()
956
    {
957
        return $this->customHtml;
958
    }
959
960
    /**
961
     * @param $customHtml
962
     *
963
     * @return $this
964
     */
965
    public function setCustomHtml($customHtml)
966
    {
967
        $this->customHtml = $customHtml;
968
969
        return $this;
970
    }
971
972
    /**
973
     * @return mixed
974
     */
975
    public function getUnsubscribeForm()
976
    {
977
        return $this->unsubscribeForm;
978
    }
979
980
    /**
981
     * @param Form $unsubscribeForm
982
     *
983
     * @return $this
984
     */
985
    public function setUnsubscribeForm(Form $unsubscribeForm = null)
986
    {
987
        $this->unsubscribeForm = $unsubscribeForm;
988
989
        return $this;
990
    }
991
992
    /**
993
     * @return mixed
994
     */
995
    public function getPreferenceCenter()
996
    {
997
        return $this->preferenceCenter;
998
    }
999
1000
    /**
1001
     * @param Page $preferenceCenter
1002
     *
1003
     * @return $this
1004
     */
1005
    public function setPreferenceCenter(Page $preferenceCenter = null)
1006
    {
1007
        $this->preferenceCenter = $preferenceCenter;
1008
1009
        return $this;
1010
    }
1011
1012
    /**
1013
     * @return mixed
1014
     */
1015
    public function getEmailType()
1016
    {
1017
        return $this->emailType;
1018
    }
1019
1020
    /**
1021
     * @param mixed $emailType
1022
     *
1023
     * @return Email
1024
     */
1025
    public function setEmailType($emailType)
1026
    {
1027
        $this->emailType = $emailType;
1028
1029
        return $this;
1030
    }
1031
1032
    /**
1033
     * Add asset.
1034
     *
1035
     * @return Email
1036
     */
1037
    public function addAssetAttachment(Asset $asset)
1038
    {
1039
        $this->assetAttachments[] = $asset;
1040
1041
        return $this;
1042
    }
1043
1044
    /**
1045
     * Remove asset.
1046
     */
1047
    public function removeAssetAttachment(Asset $asset)
1048
    {
1049
        $this->assetAttachments->removeElement($asset);
1050
    }
1051
1052
    /**
1053
     * Get assetAttachments.
1054
     *
1055
     * @return \Doctrine\Common\Collections\Collection
1056
     */
1057
    public function getAssetAttachments()
1058
    {
1059
        return $this->assetAttachments;
1060
    }
1061
1062
    /**
1063
     * @return array
1064
     */
1065
    public function getHeaders()
1066
    {
1067
        return $this->headers;
1068
    }
1069
1070
    /**
1071
     * @param array $headers
1072
     *
1073
     * @return Email
1074
     */
1075
    public function setHeaders($headers)
1076
    {
1077
        $this->headers = $headers;
1078
1079
        return $this;
1080
    }
1081
1082
    /**
1083
     * Lifecycle callback to clean URLs in the content.
1084
     */
1085
    public function cleanUrlsInContent()
1086
    {
1087
        $this->decodeAmpersands($this->plainText);
1088
        $this->decodeAmpersands($this->customHtml);
1089
    }
1090
1091
    /**
1092
     * Check all links in content and decode &amp;
1093
     * This even works with double encoded ampersands.
1094
     *
1095
     * @param $content
1096
     */
1097
    private function decodeAmpersands(&$content)
1098
    {
1099
        if (preg_match_all('/((https?|ftps?):\/\/)([a-zA-Z0-9-\.{}]*[a-zA-Z0-9=}]*)(\??)([^\s\"\]]+)?/i', $content, $matches)) {
1100
            foreach ($matches[0] as $url) {
1101
                $newUrl = $url;
1102
1103
                while (false !== strpos($newUrl, '&amp;')) {
1104
                    $newUrl = str_replace('&amp;', '&', $newUrl);
1105
                }
1106
1107
                $content = str_replace($url, $newUrl, $content);
1108
            }
1109
        }
1110
    }
1111
1112
    /**
1113
     * Calculate Read Percentage for each Email.
1114
     *
1115
     * @return int
1116
     */
1117
    public function getReadPercentage($includevariants = false)
1118
    {
1119
        if ($this->getSentCount($includevariants) > 0) {
1120
            return round($this->getReadCount($includevariants) / ($this->getSentCount($includevariants)) * 100, 2);
1121
        } else {
1122
            return 0;
1123
        }
1124
    }
1125
1126
    /**
1127
     * @return bool
1128
     */
1129
    public function getPublicPreview()
1130
    {
1131
        return $this->publicPreview;
1132
    }
1133
1134
    /**
1135
     * @return bool
1136
     */
1137
    public function isPublicPreview()
1138
    {
1139
        return $this->publicPreview;
1140
    }
1141
1142
    /**
1143
     * @param bool $publicPreview
1144
     *
1145
     * @return $this
1146
     */
1147
    public function setPublicPreview($publicPreview)
1148
    {
1149
        $this->isChanged('publicPreview', $publicPreview);
1150
        $this->publicPreview = $publicPreview;
1151
1152
        return $this;
1153
    }
1154
1155
    /**
1156
     * @param int $count
1157
     *
1158
     * @return $this
1159
     */
1160
    public function setQueuedCount($count)
1161
    {
1162
        $this->queuedCount = $count;
1163
1164
        return $this;
1165
    }
1166
1167
    /**
1168
     * @return int
1169
     */
1170
    public function getQueuedCount()
1171
    {
1172
        return $this->queuedCount;
1173
    }
1174
1175
    /**
1176
     * @param int $count
1177
     *
1178
     * @return $this
1179
     */
1180
    public function setPendingCount($count)
1181
    {
1182
        $this->pendingCount = $count;
1183
1184
        return $this;
1185
    }
1186
1187
    /**
1188
     * @return int
1189
     */
1190
    public function getPendingCount()
1191
    {
1192
        return $this->pendingCount;
1193
    }
1194
1195
    public function getClonedId(): ?int
1196
    {
1197
        return $this->clonedId;
1198
    }
1199
}
1200