Passed
Push — new-version ( 8ddc0b...b26f83 )
by Jeroen
02:25
created

VCard::getParameters()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace JeroenDesloovere\VCard;
4
5
use JeroenDesloovere\VCard\Exception\VCardException;
6
use JeroenDesloovere\VCard\Property\Address;
7
use JeroenDesloovere\VCard\Property\Anniversary;
8
use JeroenDesloovere\VCard\Property\FullName;
9
use JeroenDesloovere\VCard\Property\Gender;
10
use JeroenDesloovere\VCard\Property\Name;
11
use JeroenDesloovere\VCard\Property\Nickname;
12
use JeroenDesloovere\VCard\Property\NodeInterface;
13
use JeroenDesloovere\VCard\Property\Note;
14
use JeroenDesloovere\VCard\Property\Parameter\Kind;
15
use JeroenDesloovere\VCard\Property\Parameter\PropertyParameterInterface;
16
use JeroenDesloovere\VCard\Property\Parameter\Revision;
17
use JeroenDesloovere\VCard\Property\Parameter\Type;
18
use JeroenDesloovere\VCard\Property\Parameter\Version;
19
use JeroenDesloovere\VCard\Property\PropertyInterface;
20
use JeroenDesloovere\VCard\Property\Title;
21
22
final class VCard
23
{
24
    public const POSSIBLE_VALUES = [
25
        // All possible property parameters
26
        Version::class,
27
        Revision::class,
28
        Kind::class,
29
        Type::class,
30
        // All possible properties
31
        Name::class,
32
        FullName::class,
33
        Address::class,
34
        Note::class,
35
        Gender::class,
36
        Nickname::class,
37
        Title::class,
38
        Anniversary::class,
39
    ];
40
41
    protected const ONLY_APPLY_TO_INDIVIDUAL_KIND = [
42
        Anniversary::class,
43
        Gender::class,
44
    ];
45
46
    /**
47
     * @var PropertyParameterInterface[]
48
     */
49
    private $parameters = [];
50
51
    /**
52
     * @var PropertyInterface[]
53
     */
54
    private $properties = [];
55
56
    public function __construct(Kind $kind = null)
57
    {
58
        $this->add($kind ?? Kind::individual());
59
    }
60
61
    public function add(NodeInterface $node): self
62
    {
63
        if (!in_array(get_class($node), self::POSSIBLE_VALUES)) {
64
            throw VCardException::forNotAllowedNode($node);
65
        }
66
67
        switch (true) {
68
            case $node instanceof PropertyInterface:
69
                $this->addProperty($node);
70
                break;
71
            case $node instanceof PropertyParameterInterface:
72
                $this->addPropertyParameter($node);
73
                break;
74
        }
75
76
        return $this;
77
    }
78
79
    private function addProperty(PropertyInterface $property): void
80
    {
81
        // Property is not allowed multiple times
82
        if (!$property->isAllowedMultipleTimes() && $this->hasPropertyByClassName(get_class($property))) {
83
            throw VCardException::forExistingProperty($property);
84
        }
85
86
        // Property must only be applied to "individual" kind
87
        if (!$this->getKind()->isIndividual() && in_array(get_class($property), self::ONLY_APPLY_TO_INDIVIDUAL_KIND)) {
88
            throw VCardException::forNotAllowedPropertyOnVCardKind($property, Kind::individual());
89
        }
90
91
        $this->properties[] = $property;
92
    }
93
94
    private function addPropertyParameter(PropertyParameterInterface $propertyParameter): void
95
    {
96
        // Property is not allowed multiple times
97
        if ($this->hasPropertyByClassName(get_class($propertyParameter))) {
98
            throw VCardException::forExistingPropertyParameter($propertyParameter);
99
        }
100
101
        $this->parameters[] = $propertyParameter;
102
    }
103
104
    public function getKind(): Kind
105
    {
106
        return $this->getParameters(Kind::class)[0];
107
    }
108
109
    public function getParameters(string $filterByPropertyParameterClass = null): array
110
    {
111
        if ($filterByPropertyParameterClass === null) {
112
            return $this->parameters;
113
        }
114
115
        return array_filter($this->parameters, function (PropertyParameterInterface $parameter) use ($filterByPropertyParameterClass) {
116
            return $parameter instanceof $filterByPropertyParameterClass;
117
        });
118
    }
119
120
    public function getProperties(string $filterByPropertyClass = null): array
121
    {
122
        if ($filterByPropertyClass === null) {
123
            return $this->properties;
124
        }
125
126
        return array_filter($this->properties, function (PropertyInterface $property) use ($filterByPropertyClass) {
127
            return $property instanceof $filterByPropertyClass;
128
        });
129
    }
130
131
    public function hasParameterByClassName(string $filterByParameterClass): bool
132
    {
133
        return count($this->getParameters($filterByParameterClass)) > 0;
134
    }
135
136
    public function hasPropertyByClassName(string $filterByPropertyClass): bool
137
    {
138
        return count($this->getProperties($filterByPropertyClass)) > 0;
139
    }
140
}
141