Passed
Push — master ( b8156a...5ec36b )
by Stefan
01:47
created

VCardContact::parseAdr()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 2
1
<?php
2
declare(strict_types=1);
3
4
namespace SKien\VCard;
5
6
/**
7
 * Class representing all data to one contact.
8
 *
9
 * Uses helpers from trait VCardHelper
10
 * @see VCardHelper
11
 *
12
* history:
13
 * date         version
14
 * 2020-02-23   initial version.
15
 * 2020-05-28   renamed namespace to fit PSR-4 recommendations for autoloading.
16
 * 2020-07-22   added missing PHP 7.4 type hints / docBlock changes
17
 * 2021-07-14   The transparency of images is retained
18
 *
19
 * @package SKien-VCard
20
 * @since 1.0.0
21
 * @version 1.0.4
22
 * @author Stefanius <[email protected]>
23
 * @copyright MIT License - see the LICENSE file for details
24
 */
25
class VCardContact
26
{
27
    use VCardHelper;
28
29
    /** @var string  lastname   */
30
    protected string $strLastName = '';
31
    /** @var string  firstname  */
32
    protected string $strFirstName = '';
33
    /** @var string  prefix (salutation, title,...) */
34
    protected string $strPrefix = '';
35
    /** @var string  suffix (graduation,...)    */
36
    protected string $strSuffix = '';
37
    /** @var string  nickname   */
38
    protected string $strNickName = '';
39
    /** @var string  organisation name  */
40
    protected string $strOrganisation = '';
41
    /** @var string  position within the organisation   */
42
    protected string $strPosition = '';
43
    /** @var string  section within the organisation    */
44
    protected string $strSection = '';
45
    /** @var string  role / profession  */
46
    protected string $strRole = '';
47
    /** @var array   array of VCardAddress objects  */
48
    protected array $aAddress = array();
49
    /** @var array   array of phone numbers */
50
    protected array $aPhone = array();
51
    /** @var array   array of email addresses   */
52
    protected array $aEMail = array();
53
    /** @var array   array of categories    */
54
    protected array $aCategories = array();
55
    /** @var string  homepage URL   */
56
    protected string $strHomepage = '';
57
    /** @var string  date of birth in format YYYY-DD-MM */
58
    protected string $strDateOfBirth = '';
59
    /** @var int     gender (0: not specified, 1: female, 2: male)  */
60
    protected int $iGender = 0;
61
    /** @var string  note   */
62
    protected string $strNote = '';
63
    /** @var string  address label (readonly)   */
64
    protected string $strLabel = '';
65
    /** @var string  binary portrait base64 coded   */
66
    protected string $blobPortrait = '';
67
68
    /**
69
     * Create empty contact
70
     */
71
    public function __construct()
72
    {
73
    }
74
75
    /**
76
     * Add address.
77
     * Only one address should be marked as preferred. In case of multiple addresses
78
     * specified as preferred, last call counts!
79
     * @param VCardAddress $oAddress
80
     * @param bool $bPreferred
81
     */
82
    public function addAddress(VCardAddress $oAddress, bool $bPreferred) : void
83
    {
84
        $oAddress->setPreferred($bPreferred);
85
        $this->aAddress[] = $oAddress;
86
    }
87
88
    /**
89
     * Aadd phone number.
90
     * Can also be used to set FAX number
91
     * there may be defined multiple numbers with same type.
92
     * @param string $strPhone
93
     * @param string $strType   one of VCard::WORK, VCard::HOME, VCard::CELL, VCard::FAX
94
     * @param bool $bPreferred
95
     */
96
    public function addPhone(string $strPhone, string $strType, bool $bPreferred) : void
97
    {
98
        if ($bPreferred && strpos($strType, 'PREF') === false) {
99
            $strType .= ',PREF';
100
        }
101
        $this->aPhone[] = array('strPhone' => $strPhone, 'strType' => $strType);
102
    }
103
104
    /**
105
     * aAdd mail address.
106
     * @param string $strEMail
107
     * @param bool $bPreferred
108
     */
109
    public function addEMail(string $strEMail, bool $bPreferred) : void
110
    {
111
        if ($bPreferred) {
112
            // just set preferred mail on top of the list!
113
            array_unshift($this->aEMail, $strEMail);
114
        } else {
115
            $this->aEMail[] = $strEMail;
116
        }
117
    }
118
119
    /**
120
     * Add category.
121
     * @param string $strCategory
122
     */
123
    public function addCategory(string $strCategory) : void
124
    {
125
        $this->aCategories[] = $strCategory;
126
    }
127
128
    /**
129
     * Set date of birth.
130
     * @param mixed $DateOfBirth    may be string (format YYYY-MM-DD), int (unixtimestamp) or DateTime - object
131
     */
132
    public function setDateOfBirth($DateOfBirth) : void
133
    {
134
        if (is_object($DateOfBirth) && get_class($DateOfBirth) == 'DateTime') {
135
            // DateTime -object
136
            $this->strDateOfBirth = $DateOfBirth->format('Y-m-d');
137
        } else if (is_numeric($DateOfBirth)) {
138
            $this->strDateOfBirth = date('Y-m-d', $DateOfBirth);
139
        } else {
140
            $this->strDateOfBirth = $DateOfBirth;
141
        }
142
    }
143
144
    /**
145
     * Set the gender.
146
     * MS-extension!
147
     * windows contacts: export/import.
148
     * outlook: import only.
149
     * only male or female accepted
150
     * @param string $strGender
151
     */
152
    public function setGender(string $strGender) : void
153
    {
154
        $chGender = strtolower(substr($strGender, 0, 1));
155
        if (in_array($chGender, array('w', 'f', '1'))) {
156
            // weibl., female
157
            $this->iGender = 1;
158
        } elseif (in_array($chGender, array('m', '2'))) {
159
            // männl., male
160
            $this->iGender = 2;
161
        }
162
    }
163
164
    /**
165
     * Set portrait from image file.
166
     * supported types are JPG, PNG, GIF and BMP
167
     * @param string $strFilename
168
     */
169
    public function setPortraitFile(string $strFilename) : void
170
    {
171
        if (filter_var($strFilename, FILTER_VALIDATE_URL)) {
172
            // get type from extension
173
            $strType = strtolower((string) pathinfo($strFilename, PATHINFO_EXTENSION));
174
            $this->blobPortrait = 'data:image/' . $strType . ';base64,';
175
176
            // use curl to be independet of [allow_url_fopen] enabled on system
177
            $curl = curl_init();
178
            curl_setopt($curl, CURLOPT_URL, $strFilename);
179
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
180
181
            $img = curl_exec($curl);
182
            curl_close($curl);
183
184
            if (is_string($img)) {
185
                $this->blobPortrait .= base64_encode($img);
186
            }
187
        } elseif (file_exists($strFilename)) {
188
            switch (exif_imagetype($strFilename)) {
189
                case IMAGETYPE_JPEG:
190
                    $this->blobPortrait = 'data:image/jpg;base64,';
191
                    break;
192
                case IMAGETYPE_PNG:
193
                    $this->blobPortrait = 'data:image/png;base64,';
194
                    break;
195
                case IMAGETYPE_GIF:
196
                    $this->blobPortrait = 'data:image/gif;base64,';
197
                    break;
198
                case IMAGETYPE_BMP:
199
                    $this->blobPortrait = 'data:image/bmp;base64,';
200
                    break;
201
                default:
202
                    break;
203
            }
204
            $img = file_get_contents($strFilename);
205
206
            $this->blobPortrait .= base64_encode($img);
207
        }
208
    }
209
210
    /**
211
     * @param string $strLastName
212
     * @param string $strFirstName
213
     */
214
    public function setName(string $strLastName, string $strFirstName) : void
215
    {
216
        $this->strLastName = $strLastName;
217
        $this->strFirstName = $strFirstName;
218
    }
219
220
    /**
221
     * @param string $strPrefix
222
     */
223
    public function setPrefix(string $strPrefix) : void
224
    {
225
        $this->strPrefix = $strPrefix;
226
    }
227
228
    /**
229
     * @param string $strSuffix
230
     */
231
    public function setSuffix(string $strSuffix) : void
232
    {
233
        $this->strSuffix = $strSuffix;
234
    }
235
236
    /**
237
     * @param string $strNickName
238
     */
239
    public function setNickName(string $strNickName) : void
240
    {
241
        $this->strNickName = $strNickName;
242
    }
243
244
    /**
245
     * @param string $strOrganisation
246
     */
247
    public function setOrganisation(string $strOrganisation) : void
248
    {
249
        $this->strOrganisation = $strOrganisation;
250
    }
251
252
    /**
253
     * @param string $strSection
254
     */
255
    public function setSection(string $strSection) : void
256
    {
257
        $this->strSection = $strSection;
258
    }
259
260
    /**
261
     * @param string $strPosition
262
     */
263
    public function setPosition(string $strPosition) : void
264
    {
265
        $this->strPosition = $strPosition;
266
    }
267
268
    /**
269
     * @param string $strRole
270
     */
271
    public function setRole(string $strRole) : void
272
    {
273
        $this->strPosition = $strRole;
274
    }
275
276
    /**
277
     * @param string $strHomepage
278
     */
279
    public function setHomepage(string $strHomepage) : void
280
    {
281
        $this->strHomepage = $strHomepage;
282
    }
283
284
    /**
285
     * @param string $strNote
286
     */
287
    public function setNote(string $strNote) : void
288
    {
289
        $this->strNote = $strNote;
290
    }
291
292
    /**
293
     * Set portrait from data.
294
     * @param string $blobPortrait base64 encoded image
295
     */
296
    public function setPortraitBlob(string $blobPortrait) : void
297
    {
298
        $this->blobPortrait = $blobPortrait;
299
    }
300
301
    /**
302
     * Save portrait as file.
303
     * Supportet types are JPG, PNG, GIF and BMP
304
     * The type depends on the fileextension. If no extensiomnm given, the
305
     * type of the imported image will be used.
306
     * @param string $strFilename
307
     */
308
    public function savePortrait(string $strFilename) : void
309
    {
310
        if (strlen($this->blobPortrait) > 0) {
311
            $strType = '';
312
            $strImage = '';
313
            $this->parseImageData($this->blobPortrait, $strType, $strImage);
314
            if (strlen($strType) > 0 && strlen($strImage) > 0) {
315
                $img = $this->imageFromString($strImage, $strType);
316
                imagealphablending($img, true);
317
                imagesavealpha($img, true);
318
                $strExt = strtolower((string) pathinfo($strFilename, PATHINFO_EXTENSION));
319
                if (strlen($strExt) == 0) {
320
                    $strExt = strtolower($strType);
321
                    $strFilename .= '.' . $strExt;
322
                }
323
                switch ($strExt) {
324
                    case 'jpg':
325
                    case 'jpeg':
326
                        imagejpeg($img, $strFilename);
327
                        break;
328
                    case 'png':
329
                        imagepng($img, $strFilename);
330
                        break;
331
                    case 'gif':
332
                        imagegif($img, $strFilename);
333
                        break;
334
                    case 'bmp':
335
                        imagebmp($img, $strFilename);
336
                        break;
337
                }
338
            }
339
        }
340
    }
341
342
    /**
343
     * Number of addresses the contact contains.
344
     * @return int
345
     */
346
    public function getAddressCount() : int
347
    {
348
        return count($this->aAddress);
349
    }
350
351
    /**
352
     * Get address.
353
     * can be referenced by index or type.
354
     * type requests (=> $i non numeric value):
355
     * - first address matches specified type is used (contact may contains multiple addresses of same type)
356
     * - if VCard::PREF specified, first address in contact used, if no preferred item found
357
     * @param mixed $i     reference to address (int => index, string => type)
358
     * @return VCardAddress or null
359
     */
360
    public function getAddress($i) : ?VCardAddress
361
    {
362
        $oAddr = null;
363
        if (is_numeric($i)) {
364
            if ($i >= 0 && $i < count($this->aAddress)) {
365
                $oAddr = $this->aAddress[$i];
366
            }
367
        } else {
368
            foreach ($this->aAddress as $oAddress) {
369
                if (strpos($oAddress->getType(), $i) !== false) {
370
                    $oAddr = $oAddress;
371
                    break;
372
                }
373
            }
374
        }
375
        if (!$oAddr && $i == VCard::PREF && count($this->aAddress) > 0) {
376
            // if preferred item requested and no address in contact defined as prefered, just return first...
377
            $oAddr = $this->aAddress[0];
378
        }
379
        return $oAddr;
380
    }
381
382
    /**
383
     * Count of phone numbers.
384
     * @return int
385
     */
386
    public function getPhoneCount() : int
387
    {
388
        return count($this->aPhone);
389
    }
390
391
    /**
392
     * Get phone number.
393
     * can be referenced by index or type.
394
     * type requests (=> $i non numeric value):
395
     * - first phone matches specified type is used (contact may contains multiple phone numbers of same type)
396
     * - if VCard::PREF specified, first number in contact used, if no preferred item found
397
     * @param mixed $i     reference to address (int => index, string => type)
398
     * @return array or null
399
     */
400
    public function getPhone($i) : ?array
401
    {
402
        $aPhone = null;
403
        if (is_numeric($i)) {
404
            if ($i >= 0 && $i < count($this->aPhone)) {
405
                $aPhone = $this->aPhone[$i];
406
            }
407
        } else {
408
            foreach ($this->aPhone as $aPhone) {
409
                if (strpos($aPhone['strType'], $i) !== false) {
410
                    return $aPhone;
411
                }
412
                $aPhone = null;
413
            }
414
        }
415
        if (!$aPhone && $i == VCard::PREF && count($this->aPhone) > 0) {
416
            // if preferred item requested and no phone in contact defined as prefered, just return first...
417
            $aPhone = $this->aPhone[0];
418
        }
419
        return $aPhone;
420
    }
421
422
    /**
423
     * Number of EMail addresses.
424
     * @return int
425
     */
426
    public function getEMailCount() : int
427
    {
428
        return count($this->aEMail);
429
    }
430
431
    /**
432
     * @param int $i
433
     * @return string
434
     */
435
    public function getEMail(int $i) : string
436
    {
437
        $strEMail = '';
438
        if ($i >= 0 && $i < count($this->aEMail)) {
439
            $strEMail = $this->aEMail[$i];
440
        }
441
        return $strEMail;
442
    }
443
444
    /**
445
     * Number of categories.
446
     * @return int
447
     */
448
    public function getCategoriesCount() : int
449
    {
450
        return count($this->aCategories);
451
    }
452
453
    /**
454
     * @param int $i
455
     * @return string
456
     */
457
    public function getCategory(int $i) : string
458
    {
459
        $strCategory = '';
460
        if ($i >= 0 && $i < count($this->aCategories)) {
461
            $strCategory = $this->aCategories[$i];
462
        }
463
        return $strCategory;
464
    }
465
466
    /**
467
     * Return Categories separated by comma.
468
     * @return string
469
     */
470
    public function getCategories() : string
471
    {
472
        $strCategories = '';
473
        $strSep = '';
474
        foreach ($this->aCategories as $strCategory) {
475
            $strCategories .= $strSep . $strCategory;
476
            $strSep = ',';
477
        }
478
        return $strCategories;
479
    }
480
481
    /**
482
     * @return string
483
     */
484
    public function getName() : string
485
    {
486
        return $this->strFirstName . ' ' . $this->strLastName;
487
    }
488
489
    /**
490
     * @return string
491
     */
492
    public function getLastName() : string
493
    {
494
        return $this->strLastName;
495
    }
496
497
    /**
498
     * @return string
499
     */
500
    public function getFirstName() : string
501
    {
502
        return $this->strFirstName;
503
    }
504
505
    /**
506
     * @return string
507
     */
508
    public function getNickName() : string
509
    {
510
        return $this->strNickName;
511
    }
512
513
    /**
514
     * @return string
515
     */
516
    public function getOrganisation() : string
517
    {
518
        return $this->strOrganisation;
519
    }
520
521
    /**
522
     * @return string
523
     */
524
    public function getPosition() : string
525
    {
526
        return $this->strPosition;
527
    }
528
529
    /**
530
     * @return string
531
     */
532
    public function getRole() : string
533
    {
534
        return $this->strRole;
535
    }
536
537
    /**
538
     * @return string
539
     */
540
    public function getHomepage() : string
541
    {
542
        return $this->strHomepage;
543
    }
544
545
    /**
546
     * Get date of birth.
547
     * @return string   format YYYY-DD-MM
548
     */
549
    public function getDateOfBirth() : string
550
    {
551
        return $this->strDateOfBirth;
552
    }
553
554
    /**
555
     * Get gender (MS only).
556
     * @return int  0: not set, 1: male, 2: female
557
     */
558
    public function getGender() : int
559
    {
560
        return $this->iGender;
561
    }
562
563
    /**
564
     * @return string
565
     */
566
    public function getSection() : string
567
    {
568
        return $this->strSection;
569
    }
570
571
    /**
572
     * @return string
573
     */
574
    public function getNote() : string
575
    {
576
        return $this->strNote;
577
    }
578
579
    /**
580
     * @return string
581
     */
582
    public function getLabel() : string
583
    {
584
        return $this->strLabel;
585
    }
586
587
    /**
588
     * @return string
589
     */
590
    public function getPrefix() : string
591
    {
592
        return $this->strPrefix;
593
    }
594
595
    /**
596
     * @return string
597
     */
598
    public function getSuffix() : string
599
    {
600
        return $this->strSuffix;
601
    }
602
603
    /**
604
     * @return string base64 encoded image
605
     */
606
    public function getPortraitBlob() : string
607
    {
608
        return $this->blobPortrait;
609
    }
610
}
611