Passed
Push — master ( 643e9e...084100 )
by Stefan
07:04
created

VCardContactReader::parseTel()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
nc 1
nop 2
1
<?php
2
declare(strict_types=1);
3
4
namespace SKien\VCard;
5
6
/**
7
 * Helper class that parses property lines from a VCard format file.
8
 *
9
 * @package VCard
10
 * @author Stefanius <[email protected]>
11
 * @copyright MIT License - see the LICENSE file for details
12
 * @internal
13
 */
14
class VCardContactReader
15
{
16
    use VCardHelper;
17
18
    /** @var VCardContact the contact to write     */
19
    protected VCardContact $oContact;
20
21
    /**
22
     * Create a contact reader object.
23
     * @param VCardContact $oContact    the contact to build
24
     */
25
    function __construct(VCardContact $oContact)
26
    {
27
        $this->oContact = $oContact;
28
    }
29
30
    /**
31
     * Add property from import file.
32
     * @param string $strName
33
     * @param array<string,string> $aParams
34
     * @param string $strValue
35
     */
36
    public function addProperty(string $strName, array $aParams, string $strValue) : void
37
    {
38
        // table to parse property depending on propertyname.
39
        // value have to be either name of method of this class with signature
40
        //
41
        //      methodname(string strValue, array aParams)
42
        //
43
        // or property from VCardContact ($this->oContact)
44
        //
45
        //      settername(string strValue);
46
        //
47
        $aMethodOrProperty = [
48
            'N'             => 'parseName',
49
            'ADR'           => 'parseAdr',
50
            'TEL'           => 'parseTel',
51
            'EMAIL'         => 'parseEMail',
52
            'CATEGORIES'    => 'parseCategories',
53
            'CATEGORY'      => 'parseCategories',
54
            'ORG'           => 'parseOrg',
55
            'PHOTO'         => 'parsePhoto',
56
            'NICKNAME'      => 'setNickName',
57
            'TITLE'         => 'setPosition',
58
            'ROLE'          => 'setRole',
59
            'URL'           => 'addHomepage',
60
            'NOTE'          => 'setNote',
61
            'LABEL'         => 'setLabel',
62
            'BDAY'          => 'parseDateOfBirth',
63
            'GENDER'        => 'setGender',
64
            'X-GENDER'      => 'setGender',
65
            'X-WAB-GENDER'  => 'setGender',
66
        ];
67
68
        // supported only by vcard version 2.1
69
        if (isset($aParams['ENCODING']) && $aParams['ENCODING'] == 'QUOTED-PRINTABLE') {
70
            $strValue = quoted_printable_decode($strValue);
71
        }
72
73
        if (isset($aMethodOrProperty[$strName])) {
74
            $strPtr = $aMethodOrProperty[$strName];
75
            $ownMethod = [$this, $strPtr];
76
            $contactMethod = [$this->oContact, $strPtr];
77
            if (is_callable($ownMethod)) {
78
                // call method
79
                call_user_func_array($ownMethod, array($strValue, $aParams));
80
            } elseif (is_callable($contactMethod)) {
81
                // call setter from contact with unmasket value
82
                call_user_func_array($contactMethod, array($this->unmaskString($strValue)));
83
            }
84
        }
85
    }
86
87
    /**
88
     * Explode string into name components.
89
     * Order of the components separated by ';':
90
     *  - family name
91
     *  - given name
92
     *  - additional name(s) (not supported)
93
     *  - honorific prefixes
94
     *  - honorific suffixes
95
     *  delimitered by semicolon (be aware of masked delimiters)
96
     * @param string $strValue
97
     * @param array<string,string> $aParams
98
     */
99
    protected function parseName(string $strValue, array $aParams) : void
100
    {
101
        $aSplit = $this->explodeMaskedString(';', $strValue);
102
        // family name; given name; ; honorific prefixes; honorific suffixes
103
        $strLastName = $this->unmaskString($aSplit[0]);
104
        $strFirstName = isset($aSplit[1]) ? $this->unmaskString($aSplit[1]) : '';
105
        $this->oContact->setName($strLastName, $strFirstName);
106
        if (isset($aSplit[3])) {
107
            $this->oContact->setPrefix($this->unmaskString($aSplit[3]));
108
        }
109
        if (isset($aSplit[4])) {
110
            $this->oContact->setSuffix($this->unmaskString($aSplit[4]));
111
        }
112
    }
113
114
    /**
115
     * @param string $strValue
116
     * @param array<string,string> $aParams
117
     * @see VCardAddress::parseFullAddress()
118
     */
119
    protected function parseAdr(string $strValue, array $aParams) : void
120
    {
121
        $oAdr = new VCardAddress();
122
        $oAdr->parseFullAddress($strValue, $aParams);
123
        $this->oContact->addAddress($oAdr, false);
124
    }
125
126
    /**
127
     * Unmask value and add with typeinfo to phone list.
128
     * @param string $strValue
129
     * @param array<string,string> $aParams
130
     */
131
    protected function parseTel(string $strValue, array $aParams) : void
132
    {
133
        $strValue = $this->unmaskString($strValue);
134
        $this->oContact->addPhone($strValue, $aParams['TYPE'], strpos($aParams['TYPE'], 'PREF') !== false);
135
    }
136
137
    /**
138
     * Unmask value and add to email list.
139
     * @param string $strValue
140
     * @param array<string,string> $aParams
141
     */
142
    protected function parseEMail(string $strValue, array $aParams) : void
143
    {
144
        $strValue = $this->unmaskString($strValue);
145
        $this->oContact->addEMail($strValue, strpos($aParams['TYPE'], 'PREF') !== false);
146
    }
147
148
    /**
149
     * Split into company and section.
150
     * @param string $strValue
151
     * @param array<string,string> $aParams
152
     */
153
    protected function parseOrg(string $strValue, array $aParams) : void
154
    {
155
        $aSplit = $this->explodeMaskedString(';', $strValue);
156
        $this->oContact->setOrganisation($this->unmaskString($aSplit[0]));
157
        if (isset($aSplit[1])) {
158
            $this->oContact->setSection($this->unmaskString($aSplit[1]));
159
        }
160
    }
161
162
    /**
163
     * Split comma separated categories.
164
     * @param string $strValue
165
     * @param array<string,string> $aParams
166
     */
167
    protected function parseCategories(string $strValue, array $aParams) : void
168
    {
169
        $aSplit = $this->explodeMaskedString(',', $strValue);
170
        foreach ($aSplit as $strCategory) {
171
            $this->oContact->addCategory($this->unmaskString($strCategory));
172
        }
173
    }
174
175
    /**
176
     * Parse different formats of date of birth.
177
     * - vCard v2.1 BDAY was specified without separators...
178
     * - since v3.0 BDAY can contain '1996-04-15', '1953-10-15T23:10:00Z', '1987-09-27T08:30:00-06:00'
179
     * @param string $strValue
180
     * @param array $aParams
181
     */
182
    protected function parseDateOfBirth(string $strValue, array $aParams) : void
183
    {
184
        // we just try to create a valid DateTime object and pass it to the contact
185
        $dtDoB = new \DateTime($strValue);
186
        $this->oContact->setDateOfBirth($dtDoB);
187
    }
188
189
    /**
190
     * @param string $strValue
191
     * @param array<string,string> $aParams
192
     */
193
    protected function parsePhoto(string $strValue, array $aParams) : void
194
    {
195
        $strEncoding = isset($aParams['ENCODING']) ? $aParams['ENCODING'] : '';
196
        if ($strEncoding == 'B' || $strEncoding == 'BASE64') {
197
            $strType = strtolower($aParams['TYPE']);
198
            $this->oContact->setPortraitBlob('data:image/' . $strType . ';base64,' . $strValue);
199
        } else {
200
            // assuming URL value... e.g. export from google contacts
201
            $this->oContact->setPortraitFile($strValue);
202
        }
203
    }
204
}