Passed
Branch 2.0.0-dev (9fc37f)
by Jeroen
02:57
created

VCard::hasParameter()   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
        // Property must only be applied to "individual" kind
109
        if (!$this->getKind()->isIndividual() && in_array(
110
            get_class($property),
111
            self::ONLY_APPLY_TO_INDIVIDUAL_KIND,
112
            true
113
        )) {
114
            throw VCardException::forNotAllowedPropertyOnVCardKind($property, Kind::individual());
115
        }
116
117
        $this->properties[] = $property;
118
    }
119
120
    /**
121
     * @param PropertyParameterInterface $propertyParameter
122
     * @throws VCardException
123
     */
124
    private function addPropertyParameter(PropertyParameterInterface $propertyParameter): void
125
    {
126
        // Property is not allowed multiple times
127
        if ($this->hasProperty(get_class($propertyParameter))) {
128
            throw VCardException::forExistingPropertyParameter($propertyParameter);
129
        }
130
131
        $this->parameters[] = $propertyParameter;
132
    }
133
134
    public function getKind(): Kind
135
    {
136
        return $this->getParameters(Kind::class)[0];
137
    }
138
139
    public function getParameters(string $filterByPropertyParameterClass = null): array
140
    {
141
        if ($filterByPropertyParameterClass === null) {
142
            return $this->parameters;
143
        }
144
145
        return array_filter($this->parameters, function (PropertyParameterInterface $parameter) use ($filterByPropertyParameterClass) {
146
            return $parameter instanceof $filterByPropertyParameterClass;
147
        });
148
    }
149
150
    public function getProperties(string $forPropertyClass = null): array
151
    {
152
        if ($forPropertyClass === null) {
153
            return $this->properties;
154
        }
155
156
        return array_filter($this->properties, function (PropertyInterface $property) use ($forPropertyClass) {
157
            return $property instanceof $forPropertyClass;
158
        });
159
    }
160
161
    public function hasParameter(string $forParameterClass): bool
162
    {
163
        return count($this->getParameters($forParameterClass)) > 0;
164
    }
165
166
    public function hasProperty(string $forPropertyClass): bool
167
    {
168
        return count($this->getProperties($forPropertyClass)) > 0;
169
    }
170
}
171