VCardContact::getSection()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
declare(strict_types=1);
3
4
namespace SKien\VCard;
5
6
/**
7
 * Class representing all data to one contact.
8
 * Each contact may contains multiple
9
 * - addresses
10
 * - communication numbers
11
 * - e-mail addresses
12
 * - homepages
13
 * - categories
14
 *
15
 * #### Add a contact to a VCard for writing:
16
 * Create a new instance of a `VCardContact`, set all properties and add the contact
17
 * to a vcard using `VCard::addContact()`
18
 *
19
 * #### Retrieve a contact after read VCard file:
20
 * Use `VCard::getContactList()` to retrieve list (array) of all contacts within the vcard.
21
 * Use `VCard::getContact()` to retrieve existing contact within vcard.
22
 *
23
 * @see VCard::addContact()
24
 * @see VCard::getContactList()
25
 * @see VCard::getContact()
26
 *
27
 * @package VCard
28
 * @author Stefanius <[email protected]>
29
 * @copyright MIT License - see the LICENSE file for details
30
 */
31
class VCardContact
32
{
33
    use VCardHelper;
34
35
    /** gender: female (Microsoft specific) */
36
    public const MS_FEMALE = '1';
37
    /** gender: male (Microsoft specific) */
38
    public const MS_MALE = '2';
39
    /** Date type: string */
40
    public const DT_STRING = 0;
41
    /** Date type: unix timestamp */
42
    public const DT_UNIX_TIMESTAMP = 1;
43
    /** Date type: DateTime - Object */
44
    public const DT_OBJECT = 2;
45
46
    /** @var string  lastname   */
47
    protected string $strLastName = '';
48
    /** @var string  firstname  */
49
    protected string $strFirstName = '';
50
    /** @var string  prefix (salutation, title,...) */
51
    protected string $strPrefix = '';
52
    /** @var string  suffix (graduation,...)    */
53
    protected string $strSuffix = '';
54
    /** @var string  nickname   */
55
    protected string $strNickName = '';
56
    /** @var string  organisation name  */
57
    protected string $strOrganisation = '';
58
    /** @var string  position within the organisation   */
59
    protected string $strPosition = '';
60
    /** @var string  section within the organisation    */
61
    protected string $strSection = '';
62
    /** @var string  role / profession  */
63
    protected string $strRole = '';
64
    /** @var VCardAddress[] array of VCardAddress objects  */
65
    protected array $aAddress = array();
66
    /** @var array<array<string,string>> array of phone numbers */
67
    protected array $aPhone = array();
68
    /** @var string[] array of email addresses   */
69
    protected array $aEMail = array();
70
    /** @var string[] array of categories    */
71
    protected array $aCategories = array();
72
    /** @var string[] array of homepage URL's    */
73
    protected array $aHomepages = array();
74
    /** @var string  date of birth in format YYYY-MM-DD */
75
    protected string $strDateOfBirth = '';
76
    /** @var string  gender  */
77
    protected string $strGender = '';
78
    /** @var string  note   */
79
    protected string $strNote = '';
80
    /** @var string  binary portrait base64 coded   */
81
    protected string $blobPortrait = '';
82
83
    /**
84
     * Add address.
85
     * Only one address should be marked as preferred.
86
     * @param VCardAddress $oAddress
87
     * @param bool $bPreferred  mark address as preferred.
88
     */
89
    public function addAddress(VCardAddress $oAddress, bool $bPreferred) : void
90
    {
91
        $oAddress->setPreferred($bPreferred);
92
        $this->aAddress[] = $oAddress;
93
    }
94
95
    /**
96
     * Add phone number.
97
     * Use to set a communication number (phone, mobile, FAX, ...). <br/>
98
     * Any combination of the predefined communication number constants plus the definition
99
     * HOME or WORK can be specified as the type. <br/>
100
     * Multiple numbers of the same type can be set within one contact.
101
     * @see VCard::constants VCard communication number constants
102
     * @link https://datatracker.ietf.org/doc/html/rfc2426#section-3.3.1
103
     * @link https://en.wikipedia.org/wiki/E.164
104
     * @link https://www.itu.int/rec/T-REC-X.121-200010-I/en
105
     * @param string $strPhone      the number (SHOULD conform to the semantics of E.164 / X.121)
106
     * @param string|array<string> $type    one single type or an array of multiple types
107
     * @param bool $bPreferred      mark number as preferred
108
     */
109
    public function addPhone(string $strPhone, $type, bool $bPreferred) : void
110
    {
111
        $strType = is_array($type) ? implode(',', $type) : $type;
112
        if ($bPreferred && strpos($strType, 'PREF') === false) {
113
            $strType .= ',PREF';
114
        }
115
        $this->aPhone[] = array('strPhone' => $strPhone, 'strType' => $strType);
116
    }
117
118
    /**
119
     * Add mail address.
120
     * @link https://datatracker.ietf.org/doc/html/rfc2426#section-3.3.2
121
     * @param string $strEMail  valid e-mail address
122
     * @param bool $bPreferred  mark e-mail as preferred
123
     */
124
    public function addEMail(string $strEMail, bool $bPreferred) : void
125
    {
126
        if ($bPreferred) {
127
            // just set preferred mail on top of the list!
128
            array_unshift($this->aEMail, $strEMail);
129
        } else {
130
            $this->aEMail[] = $strEMail;
131
        }
132
    }
133
134
    /**
135
     * Add a category.
136
     * @param string $strCategory
137
     */
138
    public function addCategory(string $strCategory) : void
139
    {
140
        $this->aCategories[] = $strCategory;
141
    }
142
143
    /**
144
     * Set date of birth.
145
     * Accepts string (format YYYY-MM-DD), int (unixtimestamp) or DateTime - object
146
     * @param string|int|\DateTime  $DateOfBirth
147
     */
148
    public function setDateOfBirth($DateOfBirth) : void
149
    {
150
        if (is_object($DateOfBirth) && get_class($DateOfBirth) == 'DateTime') {
151
            // DateTime -object
152
            $this->strDateOfBirth = $DateOfBirth->format('Y-m-d');
153
        } else if (is_numeric($DateOfBirth)) {
154
            $this->strDateOfBirth = date('Y-m-d', intval($DateOfBirth));
155
        } else if (is_string($DateOfBirth)) {
156
            $this->strDateOfBirth = $DateOfBirth;
157
        }
158
    }
159
160
    /**
161
     * Set the gender.
162
     * There are different posibilities:
163
     * X-WAB-GENDER     MS-extension    '1':Female, '2':Male, '9':Unknown
164
     * X-GENDER         Extension       'Female', 'Male'
165
     *
166
     * GENDER           vCard v4.0      A single letter
167
     *      - M: "male"
168
     *      - F: "female"
169
     *      - O: "other"
170
     *      - N: "none or not applicable"
171
     *      - U: "unknown".
172
     *
173
     * So we accept everything of this know variants and convert it
174
     * to the v4.0 single letter
175
     * when we build the data.
176
     * @param string $strGender
177
     */
178
    public function setGender(string $strGender) : void
179
    {
180
        $aMSGender = ['0' => '', '1' => 'F', '2' => 'M', '9' => 'U'];
181
        if (isset($aMSGender[$strGender])) {
182
            $this->strGender = $aMSGender[$strGender];
183
        } else {
184
            $chGender = strtoupper(substr($strGender, 0, 1));
185
            if ($chGender == 'W') {
186
                // ... tribute to german 'weiblich' ;-)
187
                $this->strGender = 'F';
188
            } else if (in_array($chGender, ['M', 'F', 'O', 'N', 'U'])) {
189
                $this->strGender = $chGender;
190
            }
191
        }
192
    }
193
194
    /**
195
     * Set portrait from image file.
196
     * Supported types are JPG, PNG, GIF and BMP. <br/>
197
     * > <b>Note: </b></br>
198
     * > For transparency the image type itself MUST support transparency (PNG, GIF)
199
     * > and when reading a portrait, it MUST be saved in the same image format!
200
     * @param string $strFilename
201
     */
202
    public function setPortraitFile(string $strFilename) : void
203
    {
204
        if (filter_var($strFilename, FILTER_VALIDATE_URL)) {
205
            // get type from extension
206
            $strType = strtolower((string)pathinfo($strFilename, PATHINFO_EXTENSION));
207
            $this->blobPortrait = 'data:image/' . $strType . ';base64,';
208
209
            // use curl to be independet of [allow_url_fopen] enabled on the system
210
            $curl = curl_init();
211
            curl_setopt($curl, CURLOPT_URL, $strFilename);
212
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
213
214
            $img = curl_exec($curl);
215
            curl_close($curl);
216
217
            if (is_string($img)) {
218
                $this->blobPortrait .= base64_encode($img);
219
            }
220
        } elseif (file_exists($strFilename)) {
221
            switch (exif_imagetype($strFilename)) {
222
                case IMAGETYPE_JPEG:
223
                    $this->blobPortrait = 'data:image/jpg;base64,';
224
                    break;
225
                case IMAGETYPE_PNG:
226
                    $this->blobPortrait = 'data:image/png;base64,';
227
                    break;
228
                case IMAGETYPE_GIF:
229
                    $this->blobPortrait = 'data:image/gif;base64,';
230
                    break;
231
                case IMAGETYPE_BMP:
232
                    $this->blobPortrait = 'data:image/bmp;base64,';
233
                    break;
234
                default:
235
                    break;
236
            }
237
            $img = file_get_contents($strFilename);
238
            if ($img !== false) {
239
                $this->blobPortrait .= base64_encode($img);
240
            }
241
        }
242
    }
243
244
    /**
245
     * Set the full name.
246
     * For companies just leave one of the params blank!
247
     * @param string $strLastName
248
     * @param string $strFirstName
249
     */
250
    public function setName(string $strLastName, string $strFirstName) : void
251
    {
252
        $this->strLastName = $strLastName;
253
        $this->strFirstName = $strFirstName;
254
    }
255
256
    /**
257
     * Set (honorific) name prefix.
258
     * i.E. 'Dr.', 'Prof.', ...
259
     * @param string $strPrefix
260
     */
261
    public function setPrefix(string $strPrefix) : void
262
    {
263
        $this->strPrefix = $strPrefix;
264
    }
265
266
    /**
267
     * Set (honorific) name suffix.
268
     * i.E. 'Jr.', 'M.D.', ...
269
     * @param string $strSuffix
270
     */
271
    public function setSuffix(string $strSuffix) : void
272
    {
273
        $this->strSuffix = $strSuffix;
274
    }
275
276
    /**
277
     * Set nickname.
278
     * @param string $strNickName
279
     */
280
    public function setNickName(string $strNickName) : void
281
    {
282
        $this->strNickName = $strNickName;
283
    }
284
285
    /**
286
     * Set name of the organisation.
287
     * @param string $strOrganisation
288
     */
289
    public function setOrganisation(string $strOrganisation) : void
290
    {
291
        $this->strOrganisation = $strOrganisation;
292
    }
293
294
    /**
295
     * Set section or organizational unit within the organisation.
296
     * @param string $strSection
297
     */
298
    public function setSection(string $strSection) : void
299
    {
300
        $this->strSection = $strSection;
301
    }
302
303
    /**
304
     * Set position, job title or function within the organisation.
305
     * @param string $strPosition
306
     */
307
    public function setPosition(string $strPosition) : void
308
    {
309
        $this->strPosition = $strPosition;
310
    }
311
312
    /**
313
     * Set role, occupation or business category within the organisation.
314
     * @param string $strRole
315
     */
316
    public function setRole(string $strRole) : void
317
    {
318
        $this->strPosition = $strRole;
319
    }
320
321
    /**
322
     * Set homepage
323
     * @param string $strHomepage
324
     */
325
    public function setHomepage(string $strHomepage) : void
326
    {
327
        // keep method for backward compatibility!
328
        // just set value on top of the list!
329
        array_unshift($this->aHomepages, $strHomepage);
330
        trigger_error('call of VCardContact::setHomepage() is deprecated - use VCardContact::addtHomepage() instead!', E_USER_DEPRECATED);
331
    }
332
333
    /**
334
     * Add homepage
335
     * @param string $strHomepage
336
     */
337
    public function addHomepage(string $strHomepage) : void
338
    {
339
        $this->aHomepages[] = $strHomepage;
340
    }
341
342
    /**
343
     * Set annotation.
344
     * @param string $strNote
345
     */
346
    public function setNote(string $strNote) : void
347
    {
348
        $this->strNote = $strNote;
349
    }
350
351
    /**
352
     * Set portrait from base64 encoded image data.
353
     * @param string $blobPortrait base64 encoded image
354
     */
355
    public function setPortraitBlob(string $blobPortrait) : void
356
    {
357
        $this->blobPortrait = $blobPortrait;
358
    }
359
360
    /**
361
     * Save portrait as file.
362
     * Supportet types are JPG, PNG, GIF and BMP
363
     * The type depends on the fileextension. If no extensiomnm given, the
364
     * type of the imported image will be used.
365
     * @param string $strFilename
366
     */
367
    public function savePortrait(string $strFilename) : void
368
    {
369
        if (strlen($this->blobPortrait) > 0) {
370
            $strType = '';
371
            $strImage = '';
372
            $this->parseImageData($this->blobPortrait, $strType, $strImage);
373
            if (strlen($strType) > 0 && strlen($strImage) > 0) {
374
                $img = $this->imageFromString($strImage, $strType);
375
                if ($img !== false) {
0 ignored issues
show
introduced by
The condition $img !== false is always true.
Loading history...
376
                    imagealphablending($img, true);
377
                    imagesavealpha($img, true);
378
                    $strExt = strtolower((string)pathinfo($strFilename, PATHINFO_EXTENSION));
379
                    if (strlen($strExt) == 0) {
380
                        $strExt = strtolower($strType);
381
                        $strFilename .= '.' . $strExt;
382
                    }
383
                    switch ($strExt) {
384
                        case 'jpg':
385
                        case 'jpeg':
386
                            imagejpeg($img, $strFilename);
387
                            break;
388
                        case 'png':
389
                            imagepng($img, $strFilename);
390
                            break;
391
                        case 'gif':
392
                            imagegif($img, $strFilename);
393
                            break;
394
                        case 'bmp':
395
                            imagebmp($img, $strFilename);
396
                            break;
397
                    }
398
                }
399
            }
400
        }
401
    }
402
403
    /**
404
     * Number of addresses the contact contains.
405
     * @return int
406
     */
407
    public function getAddressCount() : int
408
    {
409
        return count($this->aAddress);
410
    }
411
412
    /**
413
     * Get address.
414
     * An address can be referenced by index or by type. <br/>
415
     * For Type requests (=> $i non numeric value): <ul>
416
     * <li> The first address matches specified type is used (contact may contains multiple
417
     *      addresses of same type)  </li>
418
     * <li> If VCard::PREF is requested, the first preferred address in contact used (even
419
     *      if more than one is defined as preferred), if no preferred address found, the
420
     *      first address within the contact will be returned!   </li></ul>
421
     * @param int|string $i     reference to address (int => index, string => type)
422
     * @return VCardAddress|null    valid address object or null, if not found
423
     */
424
    public function getAddress($i) : ?VCardAddress
425
    {
426
        $oAddr = null;
427
        if (is_numeric($i)) {
428
            if ($i >= 0 && $i < count($this->aAddress)) {
429
                $oAddr = $this->aAddress[$i];
430
            }
431
        } else {
432
            foreach ($this->aAddress as $oAddress) {
433
                if (strpos($oAddress->getType(), $i) !== false) {
434
                    $oAddr = $oAddress;
435
                    break;
436
                }
437
            }
438
        }
439
        if (!$oAddr && $i == VCard::PREF && count($this->aAddress) > 0) {
440
            // if preferred item requested and no address in contact defined as prefered, just return first...
441
            $oAddr = $this->aAddress[0];
442
        }
443
        return $oAddr;
444
    }
445
446
    /**
447
     * Count of phone numbers.
448
     * @return int
449
     */
450
    public function getPhoneCount() : int
451
    {
452
        return count($this->aPhone);
453
    }
454
455
    /**
456
     * Get phone number.
457
     * Requested number can be referenced by index or type. <br/>
458
     * For index request: `0 <= $i < self::getPhoneCount()` <br/>
459
     * For type requests (=> $i non numeric value): <ul>
460
     * <li> first phone matches specified type is used (contact may contains multiple phone numbers of same type) </li>
461
     * <li> if VCard::PREF specified, first number in contact used, if no preferred item found </li></ul>
462
     * @param int|string $i     reference to address (int => index, string => type)
463
     * @return array<string,string>|null
464
     */
465
    public function getPhone($i) : ?array
466
    {
467
        $aPhone = null;
468
        if (is_numeric($i)) {
469
            if ($i >= 0 && $i < count($this->aPhone)) {
470
                $aPhone = $this->aPhone[$i];
471
            }
472
        } else {
473
            foreach ($this->aPhone as $aPhone) {
474
                if (strpos($aPhone['strType'], $i) !== false) {
475
                    return $aPhone;
476
                }
477
                $aPhone = null;
478
            }
479
        }
480
        if (!$aPhone && $i == VCard::PREF && count($this->aPhone) > 0) {
481
            // if preferred item requested and no phone in contact defined as prefered, just return first...
482
            $aPhone = $this->aPhone[0];
483
        }
484
        return $aPhone;
485
    }
486
487
    /**
488
     * Number of email addresses contained.
489
     * @return int
490
     */
491
    public function getEMailCount() : int
492
    {
493
        return count($this->aEMail);
494
    }
495
496
    /**
497
     * Get EMail addres at given index.
498
     * @param int $i    index (`0 <= $i < self::getEMailCount()`)
499
     * @return string
500
     */
501
    public function getEMail(int $i) : string
502
    {
503
        $strEMail = '';
504
        if ($i >= 0 && $i < count($this->aEMail)) {
505
            $strEMail = $this->aEMail[$i];
506
        }
507
        return $strEMail;
508
    }
509
510
    /**
511
     * Number of categories contained.
512
     * @return int
513
     */
514
    public function getCategoriesCount() : int
515
    {
516
        return count($this->aCategories);
517
    }
518
519
    /**
520
     * Get category for given index.
521
     * @param int $i    index (`0 <= $i < self::getCategoriesCount()`)
522
     * @return string
523
     */
524
    public function getCategory(int $i) : string
525
    {
526
        $strCategory = '';
527
        if ($i >= 0 && $i < count($this->aCategories)) {
528
            $strCategory = $this->aCategories[$i];
529
        }
530
        return $strCategory;
531
    }
532
533
    /**
534
     * Check, if contact is assigned to the requested categorie.
535
     * @param string $strSearch
536
     * @param bool $bCaseSensitive
537
     * @return bool
538
     */
539
    public function hasCategory(string $strSearch, bool $bCaseSensitive = true) : bool
540
    {
541
        $bFound = false;
542
        if (!$bCaseSensitive) {
543
            $strSearch = strtolower($strSearch);
544
        }
545
        foreach ($this->aCategories as $strCategory) {
546
            if (!$bCaseSensitive) {
547
                $strCategory = strtolower($strCategory);
548
            }
549
            if ($strCategory == $strSearch) {
550
                $bFound = true;
551
                break;
552
            }
553
        }
554
        return $bFound;
555
    }
556
557
    /**
558
     * Return Categories separated by comma.
559
     * @return string
560
     */
561
    public function getCategories() : string
562
    {
563
        $strCategories = '';
564
        $strSep = '';
565
        foreach ($this->aCategories as $strCategory) {
566
            $strCategories .= $strSep . $strCategory;
567
            $strSep = ',';
568
        }
569
        return $strCategories;
570
    }
571
572
    /**
573
     * Get full name.
574
     * `$strFirstName` followed by `$strLastName` separeted by blank.
575
     * @return string
576
     */
577
    public function getName() : string
578
    {
579
        $strSep = (empty($this->strFirstName) || empty($this->strLastName)) ? '' : ' ';
580
        return $this->strFirstName . $strSep . $this->strLastName;
581
    }
582
583
    /**
584
     * Get lastname.
585
     * @return string
586
     */
587
    public function getLastName() : string
588
    {
589
        return $this->strLastName;
590
    }
591
592
    /**
593
     * Get firstname.
594
     * @return string
595
     */
596
    public function getFirstName() : string
597
    {
598
        return $this->strFirstName;
599
    }
600
601
    /**
602
     * Get nickname.
603
     * @return string
604
     */
605
    public function getNickName() : string
606
    {
607
        return $this->strNickName;
608
    }
609
610
    /**
611
     * Get name of the organisation.
612
     * @return string
613
     */
614
    public function getOrganisation() : string
615
    {
616
        return $this->strOrganisation;
617
    }
618
619
    /**
620
     * Get position, job title or function within the organisation.
621
     * @return string
622
     */
623
    public function getPosition() : string
624
    {
625
        return $this->strPosition;
626
    }
627
628
    /**
629
     * Get role, occupation or business category within the organisation.
630
     * @return string
631
     */
632
    public function getRole() : string
633
    {
634
        return $this->strRole;
635
    }
636
637
    /**
638
     * Number of homepages contained.
639
     * @return int
640
     */
641
    public function getHomepageCount() : int
642
    {
643
        return count($this->aHomepages);
644
    }
645
646
    /**
647
     * Get homepage for given index.
648
     * @param int $i    index (`0 <= $i < self::getHomepageCount()`)
649
     * @return string
650
     */
651
    public function getHomepage(int $i = -1) : string
652
    {
653
        $strHomepage = '';
654
        if ($i === -1) {
655
            // default value -1 set for backward compatibility but give chance for a 'deprecated' message!
656
            // version < 1.05 of this package hadn't support for multiple homepages!
657
            trigger_error('call of VCardContact::getHomepage() without index is deprecated!', E_USER_DEPRECATED);
658
            $i = 0;
659
        }
660
        if ($i >= 0 && $i < count($this->aHomepages)) {
661
            $strHomepage = $this->aHomepages[$i];
662
        }
663
        return $strHomepage;
664
    }
665
666
    /**
667
     * Get date of birth.
668
     * The return type can be specified in the `$iType`parameter: <ul>
669
     * <li><b> self::DT_STRING (default):</b> Date as String in f´the format set with `$strFormat`param (default = 'Y-m-d') </li>
670
     * <li><b> self::DT_UNIX_TIMESTAMP:</b> Date as unix timestamp</li>
671
     * <li><b> self::DT_OBJECT:</b> Date as DateTime object </li></ul>
672
     *
673
     * if the property is not set in the contact method returns: <ul>
674
     * <li><b> self::DT_STRING:</b> empty string </li>
675
     * <li><b> self::DT_UNIX_TIMESTAMP:</b> integer 0</li>
676
     * <li><b> self::DT_OBJECT:</b> null </li></ul>
677
     *
678
     * @link https://datatracker.ietf.org/doc/html/rfc2426#section-3.1.5
679
     * @link https://www.php.net/manual/en/datetime.format.php
680
     * @param int $iType    self::DT_STRING (default), self::DT_UNIX_TIMESTAMP or self::DT_OBJECT
681
     * @param string $strFormat Date format compliant to DateTime::format() (default 'Y-m-d')
682
     * @return string|int|\DateTime
683
     */
684
    public function getDateOfBirth(int $iType = self::DT_STRING, string $strFormat = 'Y-m-d')
685
    {
686
        $dtBirth = new \DateTime($this->strDateOfBirth);
687
        switch ($iType) {
688
            case self::DT_UNIX_TIMESTAMP:
689
                return (empty($this->strDateOfBirth) ? 0 : $dtBirth->getTimestamp());
690
            case self::DT_OBJECT:
691
                return $dtBirth;
692
            default:
693
                return (empty($this->strDateOfBirth) ? '' : $dtBirth->format($strFormat));
694
        }
695
    }
696
697
    /**
698
     * Get gender.
699
     * M: "male"
700
     * F: "female"
701
     * O: "other"
702
     * N: "none or not applicable"
703
     * U: "unknown"
704
     * @return string
705
     */
706
    public function getGender() : string
707
    {
708
        return $this->strGender;
709
    }
710
711
    /**
712
     * Get section or organizational unit within the organisation.
713
     * @return string
714
     */
715
    public function getSection() : string
716
    {
717
        return $this->strSection;
718
    }
719
720
    /**
721
     * Get annotation.
722
     * @return string
723
     */
724
    public function getNote() : string
725
    {
726
        return $this->strNote;
727
    }
728
729
    /**
730
     * Get (honorific) name prefix.
731
     * i.E. 'Dr.', 'Prof.', ...
732
     * @return string
733
     */
734
    public function getPrefix() : string
735
    {
736
        return $this->strPrefix;
737
    }
738
739
    /**
740
     * Get (honorific) name suffix.
741
     * i.E. 'Jr.', 'M.D.', ...
742
     * @return string
743
     */
744
    public function getSuffix() : string
745
    {
746
        return $this->strSuffix;
747
    }
748
749
    /**
750
     * Get the image as base64 encoded string.
751
     * @return string base64 encoded image
752
     */
753
    public function getPortraitBlob() : string
754
    {
755
        return $this->blobPortrait;
756
    }
757
}
758