Passed
Branch 2.0.0-dev (2821a4)
by Jeroen
06:26 queued 04:08
created

VCard::isAllowedIndividualKindProperty()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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