VCard::addAddress()   A
last analyzed

Complexity

Conditions 2
Paths 1

Size

Total Lines 20
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 1
nop 8
dl 0
loc 20
rs 10
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php 
2
3
namespace Rogersxd\VCard;
4
5
/**
6
*  VCard Class
7
*
8
*  @author Rogers Corrêa
9
*/
10
11
class VCard{
12
13
    /**
14
    * existsElements
15
    *
16
    * @var array
17
    */
18
    private $existsElements;
19
20
    /**
21
    * charset
22
    *
23
    * @var string
24
    */
25
    private $charset = 'UTF-8';
26
27
    /**
28
    * filename
29
    *
30
    * @var string
31
    */
32
    private $filename;
33
34
    /**
35
    * properties
36
    *
37
    * @var array
38
    */
39
    private $properties;
40
41
    /**
42
     * Save Path
43
     *
44
     * @var string
45
     */
46
    private $savePath = null;
47
48
    /**
49
    * multipleAllowed
50
    *
51
    * @var array
52
    */
53
54
    private $multipleAllowed;
55
56
    /**
57
    * Construct method 
58
    *
59
    * Set filename on init and difine the multiple properties allowed
60
    *
61
    * @return string
62
    */
63
    
64
    public function __construct()
65
    {
66
        $this->setFilename(uniqid());
67
68
        $this->multipleAllowed = [
69
            'email',
70
            'address',
71
            'phone',
72
            'url',
73
            'label',
74
            'custom',
75
            'social'
76
        ];
77
    }
78
79
    /**
80
    * Add names method
81
    *
82
    * @param  string [optional] $lastName
83
    * @param  string [optional] $firstName
84
    * @param  string [optional] $additional
85
    * @param  string [optional] $prefix
86
    * @param  string [optional] $suffix
87
    * @return $this
88
    */
89
90
    public function addNames(
91
        $lastName = '',
92
        $firstName = '',
93
        $additional = '',
94
        $prefix = '',
95
        $suffix = '',
96
        $fullName = false
97
    ){
98
        // set property
99
        $property = $lastName . ';' . $firstName . ';' . $additional . ';' . $prefix . ';' . $suffix;
100
        $this->setProperty(
101
            'name',
102
            'N' . $this->getCharsetInVCard(),
103
            $property
104
        );
105
106
        if($fullName === true) {
107
            $values = array_filter([
108
                $prefix,
109
                $firstName,
110
                $additional,
111
                $lastName,
112
                $suffix,
113
            ]);
114
115
            $this->setProperty(
116
                'fullname',
117
                'FN' . $this->getCharsetInVCard(),
118
                trim(implode(' ', $values))
119
            );
120
        }
121
122
        return $this;
123
    }
124
125
    /**
126
    * Add phone number
127
    *
128
    * @param  string $number
129
    * @param  string $type
130
    * TYPES = PREF | WORK | HOME | VOICE | FAX | MSG |
131
    * CELL | PAGER | BBS | CAR | MODEM | ISDN | VIDEO
132
    * @return $this
133
    */
134
    public function addPhone($number, $type = '')
135
    {
136
        $this->setProperty(
137
            'phone',
138
            $type,
139
            $number
140
        );
141
142
        return $this;
143
    }
144
145
    /**
146
    * Add role
147
    *
148
    * @param  string $role
149
    * @return $this
150
    */
151
    public function addRole($role)
152
    {
153
        $this->setProperty(
154
            'role',
155
            'ROLE' . $this->getCharsetInVCard(),
156
            $role
157
        );
158
159
        return $this;
160
    }
161
162
    /**
163
    * Add jobtitle
164
    *
165
    * @param  string $jobtitle
166
    * @return $this
167
    */
168
    public function addJobtitle($jobtitle)
169
    {
170
        $this->setProperty(
171
            'jobtitle',
172
            'TITLE' . $this->getCharsetInVCard(),
173
            $jobtitle
174
        );
175
        return $this;
176
    }
177
178
    /**
179
    * Add birthday
180
    *
181
    * @param  string $date - YYYY-MM-DD
182
    * @return $this
183
    */
184
    public function addBirthday($date)
185
    {
186
        $this->setProperty(
187
            'birthday',
188
            'BDAY',
189
            $date
190
        );
191
        return $this;
192
    }
193
194
    /**
195
     * Add email
196
     *
197
     * @param  string $email E-mail address
198
     * @param  string [optional] $type
199
     * TYPES = PREF | WORK | HOME;
200
     * @return $this
201
     */
202
    public function addEmail($email, $type = '')
203
    {
204
        $this->setProperty(
205
            'email',
206
            'EMAIL;INTERNET' . (($type != '') ? ';' . $type : ''),
207
            $email
208
        );
209
210
        return $this;
211
    }
212
213
    /**
214
    * Add company
215
    *
216
    * @param string $company
217
    * @param string $department
218
    * @return $this
219
    */
220
    public function addCompany($company, $department = '')
221
    {
222
        $this->setProperty(
223
            'company',
224
            'ORG' . $this->getCharsetInVCard(),
225
            $company
226
            . ($department != '' ? ';' . $department : '')
227
        );
228
229
        return $this;
230
    }
231
232
    /**
233
    * Add note
234
    *
235
    * @param  string $note
236
    * @return $this
237
    */
238
    public function addNote($note)
239
    {
240
        $this->setProperty(
241
            'note',
242
            'NOTE' . $this->getCharsetInVCard(),
243
            $note
244
        );
245
246
        return $this;
247
    }
248
249
    /**
250
    * Add Photo
251
    *
252
    * @param  string $path image url or path
253
    * @return $this
254
    */
255
    public function addPhoto($path)
256
    {
257
        $mimeType = null;
258
259
        if (filter_var($path, FILTER_VALIDATE_URL) !== false) {
260
261
            $headers = get_headers($path, 1);
262
263
            if (array_key_exists('Content-Type', $headers)) {
264
                $mimeType = $headers['Content-Type'];
265
                if (is_array($mimeType)) {
266
                    $mimeType = end($mimeType);
267
                }
268
            }
269
        } else {
270
            $mimeType = mime_content_type($path);
271
        }
272
273
        if (strpos($mimeType, ';') !== false) {
274
            $mimeType = strstr($mimeType, ';', true);
275
        }
276
        if (!is_string($mimeType) || substr($mimeType, 0, 6) !== 'image/') {
277
            throw VCardException::invalidImage();
278
        }
279
        $fileType = strtoupper(substr($mimeType, 6));
280
281
        if ((bool) ini_get('allow_url_fopen') === true) {
282
            $value = file_get_contents($path);
283
        } else {
284
            $curl = curl_init();
285
            curl_setopt($curl, CURLOPT_URL, $path);
286
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
287
            $value = curl_exec($curl);
288
            curl_close($curl);
289
        }
290
291
        if (!$value) {
292
            throw VCardException::emptyURL();
293
        }
294
295
        $value = base64_encode($value);
296
297
        $property = "PHOTO;ENCODING=BASE64;TYPE=" . $fileType;
298
299
        $this->setProperty(
300
            'photo',
301
            $property,
302
            $value
303
        );
304
305
        return $this;
306
    }
307
308
    /**
309
    * Add URL
310
    *
311
    * @param  string $url
312
    * @param  string [optional] $type Type may be WORK | HOME
313
    * @return $this
314
    */
315
    public function addURL($url, $type = '')
316
    {
317
        $this->setProperty(
318
            'url',
319
            'URL' . (($type != '') ? ';' . $type : ''),
320
            $url
321
        );
322
323
        return $this;
324
    }
325
326
    /**
327
    * Add address
328
    *
329
    * @param  string [optional] $socialProfile
330
    * @param  string [optional] $type
331
    * TYPES = facebook | twitter | instagram | linkedin
332
    * @return $this
333
    */
334
    public function addSocialProfile($socialProfile, $type)
335
    {
336
        $this->setProperty(
337
            'social',
338
            'X-SOCIALPROFILE;type='. $type,
339
            $socialProfile
340
        );
341
342
        return $this;
343
    }
344
345
    /**
346
    * Add address
347
    *
348
    * @param  string [optional] $name
349
    * @param  string [optional] $extended
350
    * @param  string [optional] $street
351
    * @param  string [optional] $city
352
    * @param  string [optional] $region
353
    * @param  string [optional] $zip
354
    * @param  string [optional] $country
355
    * @param  string [optional] $type
356
    * TYPES = DOM | INTL | POSTAL | PARCEL | HOME | WORK
357
    * @return $this
358
    */
359
    public function addAddress(
360
        $name = '',
361
        $extended = '',
362
        $street = '',
363
        $city = '',
364
        $region = '',
365
        $zip = '',
366
        $country = '',
367
        $type = 'WORK;POSTAL'
368
    ) {
369
370
        $value = $name . ';' . $extended . ';' . $street . ';' . $city . ';' . $region . ';' . $zip . ';' . $country;
371
372
        $this->setProperty(
373
            'address',
374
            'ADR' . (($type != '') ? ';' . $type : '') . $this->getCharsetInVCard(),
375
            $value
376
        );
377
378
        return $this;
379
    }
380
381
    /**
382
    * Add custom
383
    *
384
    * @param  string $param
385
    * @param  string $custom
386
    * @return $this
387
    */
388
    public function addCustom($param, $custom)
389
    {
390
        $this->setProperty(
391
            'custom',
392
            $param,
393
            $custom
394
        );
395
396
        return $this;
397
    }
398
    /**
399
    * Set charset string
400
    */
401
    public function setCharset($charset)
402
    {
403
        $this->charset = $charset;
404
    }
405
406
    /**
407
    * Get charset in vCard
408
    *
409
    * @return string
410
    */
411
    public function getCharsetInVCard()
412
    {
413
        return ';CHARSET=' . $this->charset;
414
    }
415
416
    /**
417
    * Get charset string
418
    *
419
    * @return string
420
    */
421
    public function getCharset()
422
    {
423
        return $this->charset;
424
    }
425
426
    /**
427
    * Set property
428
    *
429
    * @param  string $element
430
    * @param  string $key
431
    * @param  string $value
432
    * @throws VCardException
433
    */
434
    public function setFilename($value, $overwrite = true)
435
    {
436
        $value = trim($value);
437
438
        $value = preg_replace('/\s+/', ' ', $value);
439
440
        if (empty($value)) {
441
            return;
442
        }
443
444
        $value = strtolower($value);
445
446
        $this->filename = ($overwrite) ?
447
        $value : $this->filename . $value;
448
    }
449
450
    /**
451
    * Get filename
452
    *
453
    * @return string
454
    */
455
    public function getFilename()
456
    {
457
        if (!$this->filename) {
458
            return 'unknown';
459
        }
460
461
        return $this->filename;
462
    }
463
464
    /**
465
    * Set property
466
    *
467
    * @param  string $element
468
    * @param  string $key
469
    * @param  string $value
470
    * @throws VCardException
471
    */
472
473
    private function setProperty($element, $key, $value)
474
    {
475
        if (!in_array($element, $this->multipleAllowed)
476
            && isset($this->existsElements[$element])
477
        ) {
478
            throw VCardException::elementExists($element);
479
        }
480
481
            // we define that we set this element
482
        $this->existsElements[$element] = true;
483
484
            // adding property
485
        $this->properties[] = [
486
            'key' => $key,
487
            'value' => $value
488
        ];
489
    }
490
491
    public function getProperties()
492
    {
493
        return $this->properties;
494
    }
495
496
    /**
497
     * Build VCard (.vcf)
498
     *
499
     * @return string
500
     */
501
    public function genVCard()
502
    {
503
        // init string
504
        $string = "BEGIN:VCARD\r\n";
505
        $string .= "VERSION:3.0\r\n";
506
        $string .= "REV:" . date("Y-m-d") . "T" . date("H:i:s") . "Z\r\n";
507
508
        // loop all properties
509
        $properties = $this->getProperties();
510
        foreach ($properties as $property) {
511
            // add to string
512
            $string .= $this->fold($property['key'] . ':' . $this->escape($property['value']) . "\r\n");
513
        }
514
515
        // add to string
516
        $string .= "END:VCARD\r\n";
517
518
        // return
519
        return $string;
520
    }
521
522
    /**
523
    * Set the save path directory
524
    *
525
    * @param  string $savePath Save Path
526
    * @throws VCardException
527
    */
528
    public function setSavePath($savePath)
529
    {
530
        if (!is_dir($savePath)) {
531
            throw VCardException::outputDirectoryNotExists();
532
        }
533
534
        // Add trailing directory separator the save path
535
        if (substr($savePath, -1) != DIRECTORY_SEPARATOR) {
536
            $savePath .= DIRECTORY_SEPARATOR;
537
        }
538
539
        $this->savePath = $savePath;
540
    }
541
542
543
    /**
544
     * Save to a file
545
     *
546
     * @return void
547
     */
548
    public function save()
549
    {
550
        $file = $this->getFilename() . '.vcf';
551
552
        // Add save path if given
553
        if (null !== $this->savePath) {
554
            $file = $this->savePath . $file;
555
        }
556
557
        file_put_contents(
558
            $file,
559
            $this->genVCard()
560
        );
561
    }
562
563
564
    /**
565
    * Fold a line according to RFC2425 section 5.8.1.
566
    *
567
    * @link http://tools.ietf.org/html/rfc2425#section-5.8.1
568
    * @param  string $text
569
    * @return mixed
570
    */
571
    protected function fold($text)
572
    {
573
        if (strlen($text) <= 75) {
574
            return $text;
575
        }
576
577
        // split, wrap and trim trailing separator
578
        return substr($this->chunk_split_unicode($text, 75, "\r\n "), 0, -3);
579
    }
580
581
    /**
582
    * multibyte word chunk split
583
    * @link http://php.net/manual/en/function.chunk-split.php#107711
584
    * 
585
    * @param  string  $body     The string to be chunked.
586
    * @param  integer $chunklen The chunk length.
587
    * @param  string  $end      The line ending sequence.
588
    * @return string            Chunked string
589
    */
590
    protected function chunk_split_unicode($body, $chunklen = 76, $end = "\r\n")
591
    {
592
        $array = array_chunk(
593
            preg_split("//u", $body, -1, PREG_SPLIT_NO_EMPTY), $chunklen);
0 ignored issues
show
Bug introduced by
It seems like preg_split('//u', $body,...rd\PREG_SPLIT_NO_EMPTY) can also be of type false; however, parameter $input of array_chunk() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

593
            /** @scrutinizer ignore-type */ preg_split("//u", $body, -1, PREG_SPLIT_NO_EMPTY), $chunklen);
Loading history...
594
        $body = "";
595
        foreach ($array as $item) {
596
            $body .= join("", $item) . $end;
597
        }
598
        return $body;
599
    }
600
601
    /**
602
    * Escape newline characters according to RFC2425 section 5.8.4.
603
    *
604
    * @link http://tools.ietf.org/html/rfc2425#section-5.8.4
605
    * @param  string $text
606
    * @return string
607
    */
608
    protected function escape($text)
609
    {
610
        $text = str_replace("\r\n", "\\n", $text);
611
        $text = str_replace("\n", "\\n", $text);
612
613
        return $text;
614
    }
615
}