Issues (3627)

app/bundles/FormBundle/Entity/Form.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\FormBundle\Entity;
13
14
use Doctrine\Common\Collections\ArrayCollection;
15
use Doctrine\ORM\Mapping as ORM;
16
use Mautic\ApiBundle\Serializer\Driver\ApiMetadataDriver;
17
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
18
use Mautic\CoreBundle\Entity\FormEntity;
19
use Mautic\CoreBundle\Helper\InputHelper;
20
use Symfony\Component\Validator\Constraints as Assert;
21
use Symfony\Component\Validator\Mapping\ClassMetadata;
22
23
/**
24
 * Class Form.
25
 */
26
class Form extends FormEntity
27
{
28
    /**
29
     * @var int
30
     */
31
    private $id;
32
33
    /**
34
     * @var string
35
     */
36
    private $name;
37
38
    /**
39
     * @var string
40
     */
41
    private $formAttributes;
42
43
    /**
44
     * @var string
45
     */
46
    private $description;
47
48
    /**
49
     * @var string
50
     */
51
    private $alias;
52
53
    /**
54
     * @var \Mautic\CategoryBundle\Entity\Category
55
     **/
56
    private $category;
57
58
    /**
59
     * @var string
60
     */
61
    private $cachedHtml;
62
63
    /**
64
     * @var string
65
     */
66
    private $postAction = 'return';
67
68
    /**
69
     * @var string
70
     */
71
    private $postActionProperty;
72
73
    /**
74
     * @var \DateTime
75
     */
76
    private $publishUp;
77
78
    /**
79
     * @var \DateTime
80
     */
81
    private $publishDown;
82
83
    /**
84
     * @var ArrayCollection
85
     */
86
    private $fields;
87
88
    /**
89
     * @var ArrayCollection
90
     */
91
    private $actions;
92
93
    /**
94
     * @var string
95
     */
96
    private $template;
97
98
    /**
99
     * @var bool
100
     */
101
    private $inKioskMode = false;
102
103
    /**
104
     * @var bool
105
     */
106
    private $renderStyle = false;
107
108
    /**
109
     * @ORM\OneToMany(targetEntity="Submission", mappedBy="form", fetch="EXTRA_LAZY")
110
     * @ORM\OrderBy({"dateSubmitted" = "DESC"})
111
     *
112
     * @var ArrayCollection
113
     */
114
    private $submissions;
115
116
    /**
117
     * @var int
118
     */
119
    public $submissionCount;
120
121
    /**
122
     * @var string
123
     */
124
    private $formType;
125
126
    /**
127
     * @var bool
128
     */
129
    private $noIndex;
130
131
    /**
132
     * This var is used to cache the result once gained from the loop.
133
     *
134
     * @var bool
135
     */
136
    private $usesProgressiveProfiling;
137
138
    public function __clone()
139
    {
140
        $this->id = null;
141
142
        parent::__clone();
143
    }
144
145
    /**
146
     * Construct.
147
     */
148
    public function __construct()
149
    {
150
        $this->fields      = new ArrayCollection();
151
        $this->actions     = new ArrayCollection();
152
        $this->submissions = new ArrayCollection();
153
    }
154
155
    public static function loadMetadata(ORM\ClassMetadata $metadata)
156
    {
157
        $builder = new ClassMetadataBuilder($metadata);
158
159
        $builder->setTable('forms')
160
            ->setCustomRepositoryClass('Mautic\FormBundle\Entity\FormRepository');
161
162
        $builder->addIdColumns();
163
164
        $builder->addField('alias', 'string');
165
166
        $builder->addNullableField('formAttributes', 'string', 'form_attr');
167
168
        $builder->addCategory();
169
170
        $builder->createField('cachedHtml', 'text')
171
            ->columnName('cached_html')
172
            ->nullable()
173
            ->build();
174
175
        $builder->createField('postAction', 'string')
176
            ->columnName('post_action')
177
            ->build();
178
179
        $builder->createField('postActionProperty', 'string')
180
            ->columnName('post_action_property')
181
            ->nullable()
182
            ->build();
183
184
        $builder->addPublishDates();
185
186
        $builder->createOneToMany('fields', 'Field')
187
            ->setIndexBy('id')
188
            ->setOrderBy(['order' => 'ASC'])
189
            ->mappedBy('form')
190
            ->cascadeAll()
191
            ->fetchExtraLazy()
192
            ->build();
193
194
        $builder->createOneToMany('actions', 'Action')
195
            ->setIndexBy('id')
196
            ->setOrderBy(['order' => 'ASC'])
197
            ->mappedBy('form')
198
            ->cascadeAll()
199
            ->fetchExtraLazy()
200
            ->build();
201
202
        $builder->createField('template', 'string')
203
            ->nullable()
204
            ->build();
205
206
        $builder->createField('inKioskMode', 'boolean')
207
            ->columnName('in_kiosk_mode')
208
            ->nullable()
209
            ->build();
210
211
        $builder->createField('renderStyle', 'boolean')
212
            ->columnName('render_style')
213
            ->nullable()
214
            ->build();
215
216
        $builder->createOneToMany('submissions', 'Submission')
217
            ->setOrderBy(['dateSubmitted' => 'DESC'])
218
            ->mappedBy('form')
219
            ->fetchExtraLazy()
220
            ->build();
221
222
        $builder->addNullableField('formType', 'string', 'form_type');
223
224
        $builder->createField('noIndex', 'boolean')
225
            ->columnName('no_index')
226
            ->nullable()
227
            ->build();
228
    }
229
230
    public static function loadValidatorMetadata(ClassMetadata $metadata)
231
    {
232
        $metadata->addPropertyConstraint('name', new Assert\NotBlank([
233
            'message' => 'mautic.core.name.required',
234
            'groups'  => ['form'],
235
        ]));
236
237
        $metadata->addPropertyConstraint('postActionProperty', new Assert\NotBlank([
238
            'message' => 'mautic.form.form.postactionproperty_message.notblank',
239
            'groups'  => ['messageRequired'],
240
        ]));
241
242
        $metadata->addPropertyConstraint('postActionProperty', new Assert\NotBlank([
243
            'message' => 'mautic.form.form.postactionproperty_redirect.notblank',
244
            'groups'  => ['urlRequired'],
245
        ]));
246
247
        $metadata->addPropertyConstraint('postActionProperty', new Assert\Url([
248
            'message' => 'mautic.form.form.postactionproperty_redirect.notblank',
249
            'groups'  => ['urlRequiredPassTwo'],
250
        ]));
251
252
        $metadata->addPropertyConstraint('formType', new Assert\Choice([
253
            'choices' => ['standalone', 'campaign'],
254
        ]));
255
    }
256
257
    /**
258
     * @return array
259
     */
260
    public static function determineValidationGroups(\Symfony\Component\Form\Form $form)
261
    {
262
        $data   = $form->getData();
263
        $groups = ['form'];
264
265
        $postAction = $data->getPostAction();
266
267
        if ('message' == $postAction) {
268
            $groups[] = 'messageRequired';
269
        } elseif ('redirect' == $postAction) {
270
            $groups[] = 'urlRequired';
271
        }
272
273
        return $groups;
274
    }
275
276
    /**
277
     * Prepares the metadata for API usage.
278
     *
279
     * @param $metadata
280
     */
281
    public static function loadApiMetadata(ApiMetadataDriver $metadata)
282
    {
283
        $metadata->setGroupPrefix('form')
284
            ->addListProperties(
285
                [
286
                    'id',
287
                    'name',
288
                    'alias',
289
                    'category',
290
                ]
291
            )
292
            ->addProperties(
293
                [
294
                    'description',
295
                    'cachedHtml',
296
                    'publishUp',
297
                    'publishDown',
298
                    'fields',
299
                    'actions',
300
                    'template',
301
                    'inKioskMode',
302
                    'renderStyle',
303
                    'formType',
304
                    'postAction',
305
                    'postActionProperty',
306
                    'noIndex',
307
                    'formAttributes',
308
                ]
309
            )
310
            ->build();
311
    }
312
313
    /**
314
     * @param $prop
315
     * @param $val
316
     */
317
    protected function isChanged($prop, $val)
318
    {
319
        if ('actions' == $prop || 'fields' == $prop) {
320
            //changes are already computed so just add them
321
            $this->changes[$prop][$val[0]] = $val[1];
322
        } else {
323
            parent::isChanged($prop, $val);
324
        }
325
    }
326
327
    /**
328
     * Get id.
329
     *
330
     * @return int
331
     */
332
    public function getId()
333
    {
334
        return $this->id;
335
    }
336
337
    /**
338
     * Set name.
339
     *
340
     * @param string $name
341
     *
342
     * @return Form
343
     */
344
    public function setName($name)
345
    {
346
        $this->isChanged('name', $name);
347
        $this->name = $name;
348
349
        return $this;
350
    }
351
352
    /**
353
     * Get name.
354
     *
355
     * @return string
356
     */
357
    public function getName()
358
    {
359
        return $this->name;
360
    }
361
362
    /**
363
     * Set description.
364
     *
365
     * @param string $description
366
     *
367
     * @return Form
368
     */
369
    public function setDescription($description)
370
    {
371
        $this->isChanged('description', $description);
372
        $this->description = $description;
373
374
        return $this;
375
    }
376
377
    /**
378
     * Get description.
379
     *
380
     * @return string
381
     */
382
    public function getDescription($truncate = false, $length = 45)
383
    {
384
        if ($truncate) {
385
            if (strlen($this->description) > $length) {
386
                return substr($this->description, 0, $length).'...';
387
            }
388
        }
389
390
        return $this->description;
391
    }
392
393
    /**
394
     * Set cachedHtml.
395
     *
396
     * @param string $cachedHtml
397
     *
398
     * @return Form
399
     */
400
    public function setCachedHtml($cachedHtml)
401
    {
402
        $this->cachedHtml = $cachedHtml;
403
404
        return $this;
405
    }
406
407
    /**
408
     * Get cachedHtml.
409
     *
410
     * @return string
411
     */
412
    public function getCachedHtml()
413
    {
414
        return $this->cachedHtml;
415
    }
416
417
    /**
418
     * Get render style.
419
     *
420
     * @return string
421
     */
422
    public function getRenderStyle()
423
    {
424
        return $this->renderStyle;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->renderStyle returns the type boolean which is incompatible with the documented return type string.
Loading history...
425
    }
426
427
    /**
428
     * Set postAction.
429
     *
430
     * @param string $postAction
431
     *
432
     * @return Form
433
     */
434
    public function setPostAction($postAction)
435
    {
436
        $this->isChanged('postAction', $postAction);
437
        $this->postAction = $postAction;
438
439
        return $this;
440
    }
441
442
    /**
443
     * Get postAction.
444
     *
445
     * @return string
446
     */
447
    public function getPostAction()
448
    {
449
        return $this->postAction;
450
    }
451
452
    /**
453
     * Set postActionProperty.
454
     *
455
     * @param string $postActionProperty
456
     *
457
     * @return Form
458
     */
459
    public function setPostActionProperty($postActionProperty)
460
    {
461
        $this->isChanged('postActionProperty', $postActionProperty);
462
        $this->postActionProperty = $postActionProperty;
463
464
        return $this;
465
    }
466
467
    /**
468
     * Get postActionProperty.
469
     *
470
     * @return string
471
     */
472
    public function getPostActionProperty()
473
    {
474
        return $this->postActionProperty;
475
    }
476
477
    /**
478
     * Get result count.
479
     */
480
    public function getResultCount()
481
    {
482
        return count($this->submissions);
483
    }
484
485
    /**
486
     * Set publishUp.
487
     *
488
     * @param \DateTime $publishUp
489
     *
490
     * @return Form
491
     */
492
    public function setPublishUp($publishUp)
493
    {
494
        $this->isChanged('publishUp', $publishUp);
495
        $this->publishUp = $publishUp;
496
497
        return $this;
498
    }
499
500
    /**
501
     * Get publishUp.
502
     *
503
     * @return \DateTime
504
     */
505
    public function getPublishUp()
506
    {
507
        return $this->publishUp;
508
    }
509
510
    /**
511
     * Set publishDown.
512
     *
513
     * @param \DateTime $publishDown
514
     *
515
     * @return Form
516
     */
517
    public function setPublishDown($publishDown)
518
    {
519
        $this->isChanged('publishDown', $publishDown);
520
        $this->publishDown = $publishDown;
521
522
        return $this;
523
    }
524
525
    /**
526
     * Get publishDown.
527
     *
528
     * @return \DateTime
529
     */
530
    public function getPublishDown()
531
    {
532
        return $this->publishDown;
533
    }
534
535
    /**
536
     * Add a field.
537
     *
538
     * @param $key
539
     *
540
     * @return Form
541
     */
542
    public function addField($key, Field $field)
543
    {
544
        if ($changes = $field->getChanges()) {
545
            $this->isChanged('fields', [$key, $changes]);
546
        }
547
        $this->fields[$key] = $field;
548
549
        return $this;
550
    }
551
552
    /**
553
     * Remove a field.
554
     *
555
     * @param $key
556
     */
557
    public function removeField($key, Field $field)
558
    {
559
        if ($changes = $field->getChanges()) {
560
            $this->isChanged('fields', [$key, $changes]);
561
        }
562
        $this->fields->removeElement($field);
563
    }
564
565
    /**
566
     * Get fields.
567
     *
568
     * @return \Doctrine\Common\Collections\Collection|Field[]
569
     */
570
    public function getFields()
571
    {
572
        return $this->fields;
573
    }
574
575
    /**
576
     * Get array of field aliases.
577
     *
578
     * @return array
579
     */
580
    public function getFieldAliases()
581
    {
582
        $aliases = [];
583
        $fields  = $this->getFields();
584
585
        if ($fields) {
586
            foreach ($fields as $field) {
587
                $aliases[] = $field->getAlias();
588
            }
589
        }
590
591
        return $aliases;
592
    }
593
594
    /**
595
     * Set alias.
596
     *
597
     * @param string $alias
598
     *
599
     * @return Form
600
     */
601
    public function setAlias($alias)
602
    {
603
        $this->isChanged('alias', $alias);
604
        $this->alias = $alias;
605
606
        return $this;
607
    }
608
609
    /**
610
     * Get alias.
611
     *
612
     * @return string
613
     */
614
    public function getAlias()
615
    {
616
        return $this->alias;
617
    }
618
619
    /**
620
     * Add submissions.
621
     *
622
     * @return Form
623
     */
624
    public function addSubmission(Submission $submissions)
625
    {
626
        $this->submissions[] = $submissions;
627
628
        return $this;
629
    }
630
631
    /**
632
     * Remove submissions.
633
     */
634
    public function removeSubmission(Submission $submissions)
635
    {
636
        $this->submissions->removeElement($submissions);
637
    }
638
639
    /**
640
     * Get submissions.
641
     *
642
     * @return \Doctrine\Common\Collections\Collection|Submission[]
643
     */
644
    public function getSubmissions()
645
    {
646
        return $this->submissions;
647
    }
648
649
    /**
650
     * Add actions.
651
     *
652
     * @param $key
653
     *
654
     * @return Form
655
     */
656
    public function addAction($key, Action $action)
657
    {
658
        if ($changes = $action->getChanges()) {
659
            $this->isChanged('actions', [$key, $changes]);
660
        }
661
        $this->actions[$key] = $action;
662
663
        return $this;
664
    }
665
666
    /**
667
     * Remove action.
668
     */
669
    public function removeAction(Action $action)
670
    {
671
        $this->actions->removeElement($action);
672
    }
673
674
    /**
675
     * Removes all actions.
676
     */
677
    public function clearActions()
678
    {
679
        $this->actions = new ArrayCollection();
680
    }
681
682
    /**
683
     * Get actions.
684
     *
685
     * @return \Doctrine\Common\Collections\Collection|Action[]
686
     */
687
    public function getActions()
688
    {
689
        return $this->actions;
690
    }
691
692
    /**
693
     * @return mixed
694
     */
695
    public function getCategory()
696
    {
697
        return $this->category;
698
    }
699
700
    /**
701
     * @param mixed $category
702
     */
703
    public function setCategory($category)
704
    {
705
        $this->category = $category;
706
    }
707
708
    /**
709
     * @return mixed
710
     */
711
    public function getTemplate()
712
    {
713
        return $this->template;
714
    }
715
716
    /**
717
     * @param mixed $template
718
     */
719
    public function setTemplate($template)
720
    {
721
        $this->template = $template;
722
    }
723
724
    /**
725
     * @return mixed
726
     */
727
    public function getInKioskMode()
728
    {
729
        return $this->inKioskMode;
730
    }
731
732
    /**
733
     * @param mixed $inKioskMode
734
     */
735
    public function setInKioskMode($inKioskMode)
736
    {
737
        $this->inKioskMode = $inKioskMode;
738
    }
739
740
    /**
741
     * @param mixed $renderStyle
742
     */
743
    public function setRenderStyle($renderStyle)
744
    {
745
        $this->renderStyle = $renderStyle;
746
    }
747
748
    /**
749
     * @return mixed
750
     */
751
    public function isInKioskMode()
752
    {
753
        return $this->getInKioskMode();
754
    }
755
756
    /**
757
     * @return mixed
758
     */
759
    public function getFormType()
760
    {
761
        return $this->formType;
762
    }
763
764
    /**
765
     * @param mixed $formType
766
     *
767
     * @return Form
768
     */
769
    public function setFormType($formType)
770
    {
771
        $this->formType = $formType;
772
773
        return $this;
774
    }
775
776
    /**
777
     * Set noIndex.
778
     *
779
     * @param bool $noIndex
780
     */
781
    public function setNoIndex($noIndex)
782
    {
783
        $this->isChanged('noIndex', $noIndex);
784
        $this->noIndex = $noIndex;
785
    }
786
787
    /**
788
     * Get noIndex.
789
     *
790
     * @return bool
791
     */
792
    public function getNoIndex()
793
    {
794
        return $this->noIndex;
795
    }
796
797
    /**
798
     * @param string $formAttributes
799
     *
800
     * @return Form
801
     */
802
    public function setFormAttributes($formAttributes)
803
    {
804
        $this->isChanged('formAttributes', $formAttributes);
805
        $this->formAttributes = $formAttributes;
806
807
        return $this;
808
    }
809
810
    /**
811
     * @return string
812
     */
813
    public function getFormAttributes()
814
    {
815
        return $this->formAttributes;
816
    }
817
818
    /**
819
     * @return bool
820
     */
821
    public function isStandalone()
822
    {
823
        return 'campaign' != $this->formType;
824
    }
825
826
    /**
827
     * Generate a form name for HTML attributes.
828
     */
829
    public function generateFormName()
830
    {
831
        $name = strtolower(
832
            InputHelper::alphanum(
833
                InputHelper::transliterate(
834
                    $this->name
835
                )
836
            )
837
        );
838
839
        return (empty($name)) ? 'form-'.$this->id : $name;
840
    }
841
842
    /**
843
     * Check if some Progressive Profiling setting is turned on on any of the form fields.
844
     *
845
     * @return bool
846
     */
847
    public function usesProgressiveProfiling()
848
    {
849
        if (null !== $this->usesProgressiveProfiling) {
850
            return $this->usesProgressiveProfiling;
851
        }
852
853
        // Progressive profiling must be turned off in the kiosk mode
854
        if (false === $this->getInKioskMode()) {
855
            // Search for a field with a progressive profiling setting on
856
            foreach ($this->fields->toArray() as $field) {
857
                if (false === $field->getShowWhenValueExists() || $field->getShowAfterXSubmissions() > 0) {
858
                    $this->usesProgressiveProfiling = true;
859
860
                    return $this->usesProgressiveProfiling;
861
                }
862
            }
863
        }
864
865
        $this->usesProgressiveProfiling = false;
866
867
        return $this->usesProgressiveProfiling;
868
    }
869
}
870