Passed
Push — EXTRACT_CLASSES ( 0382f2...c25e41 )
by Rafael
52:18
created

vCard::setAddress()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 4
nop 9
dl 0
loc 12
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
/* Copyright (C)            Kai Blankenhorn             <[email protected]>
4
 * Copyright (C) 2005-2017  Laurent Destailleur         <[email protected]>
5
 * Copyright (C) 2020		Tobias Sekan		        <[email protected]>
6
 * Copyright (C) 2024       Rafael San José             <[email protected]>
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
namespace Dolibarr\Code\Core\Classes;
23
24
/**
25
 *  \file       htdocs/core/class/vcard.class.php
26
 *  \brief      Class to manage vCard files
27
 */
28
29
30
/**
31
 * Encode a string for vCard
32
 *
33
 * @param   string  $string     String to encode
34
 * @return  string              String encoded
35
 */
36
function encode($string)
37
{
38
    return str_replace(";", "\;", (dol_quoted_printable_encode($string)));
39
}
40
41
42
/**
43
 * Taken from php documentation comments
44
 * No more used
45
 *
46
 * @param   string  $input      String
47
 * @param   int     $line_max   Max length of lines
48
 * @return  string              Encoded string
49
 */
50
function dol_quoted_printable_encode($input, $line_max = 76)
51
{
52
    $hex = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
53
    $lines = preg_split("/(\?:\r\n|\r|\n)/", $input);
54
    $eol = "\r\n";
55
    $linebreak = "=0D=0A";
56
    $escape = "=";
57
    $output = "";
58
59
    $num = count($lines);
60
    for ($j = 0; $j < $num; $j++) {
61
        $line = $lines[$j];
62
        $linlen = strlen($line);
63
        $newline = "";
64
        for ($i = 0; $i < $linlen; $i++) {
65
            $c = substr($line, $i, 1);
66
            $dec = ord($c);
67
            if (($dec == 32) && ($i == ($linlen - 1))) { // convert space at eol only
68
                $c = "=20";
69
            } elseif (($dec == 61) || ($dec < 32) || ($dec > 126)) { // always encode "\t", which is *not* required
70
                $h2 = floor($dec / 16);
71
                $h1 = floor($dec % 16);
72
                $c = $escape . $hex["$h2"] . $hex["$h1"];
73
            }
74
            if ((strlen($newline) + strlen($c)) >= $line_max) { // CRLF is not counted
75
                $output .= $newline . $escape . $eol; // soft line break; " =\r\n" is okay
76
                $newline = "    ";
77
            }
78
            $newline .= $c;
79
        } // end of for
80
        $output .= $newline;
81
        if ($j < count($lines) - 1) {
82
            $output .= $linebreak;
83
        }
84
    }
85
    return trim($output);
86
}
87
88
89
/**
90
 *  Class to build vCard files
91
 */
92
class vCard
93
{
94
    /**
95
     * @var array array of properties
96
     */
97
    public $properties;
98
99
    /**
100
     * @var string filename
101
     */
102
    public $filename;
103
104
    /**
105
     * @var string encoding
106
     */
107
    public $encoding = "ENCODING=QUOTED-PRINTABLE";
108
109
110
    /**
111
     *  mise en forme du numero de telephone
112
     *
113
     *  @param  int     $number     numero de telephone
114
     *  @param  string  $type       Type ('cell')
115
     *  @return void
116
     */
117
    public function setPhoneNumber($number, $type = "")
118
    {
119
        // type may be PREF | WORK | HOME | VOICE | FAX | MSG | CELL | PAGER | BBS | CAR | MODEM | ISDN | VIDEO or any senseful combination, e.g. "PREF;WORK;VOICE"
120
        $key = "TEL";
121
        if ($type != "") {
122
            $key .= ";" . $type;
123
        }
124
        $key .= ";VALUE=uri";
125
        //$key .= ";".$this->encoding;
126
        $this->properties[$key] = 'tel:' . $number;
127
    }
128
129
    /**
130
     *  mise en forme de la photo
131
     *  warning NON TESTE !
132
     *
133
     *  @param  string  $type           Type 'image/jpeg' or 'JPEG'
134
     *  @param  string  $photo          Photo
135
     *  @return void
136
     */
137
    public function setPhoto($type, $photo)
138
    {
139
        // $type = "GIF" | "JPEG"
140
        //$this->properties["PHOTO;MEDIATYPE=$type;ENCODING=BASE64"] = base64_encode($photo);
141
        $this->properties["PHOTO;MEDIATYPE=$type"] = $photo;        // must be url of photo
142
        //$this->properties["PHOTO;TYPE=$type;ENCODING=BASE64"] = base64_encode($photo);   // must be content of image
143
    }
144
145
    /**
146
     *  mise en forme du nom format
147
     *
148
     *  @param  string  $name           Name
149
     *  @return void
150
     */
151
    public function setFormattedName($name)
152
    {
153
        $this->properties["FN;" . $this->encoding] = encode($name);
154
    }
155
156
    /**
157
     *  mise en forme du nom complete
158
     *
159
     *  @param  string  $family         Family name
160
     *  @param  string  $first          First name
161
     *  @param  string  $additional     Additional (e.g. second name, nick name)
162
     *  @param  string  $prefix         Title prefix (e.g. "Mr.", "Ms.", "Prof.")
163
     *  @param  string  $suffix         Suffix (e.g. "sen." for senior, "jun." for junior)
164
     *  @return void
165
     */
166
    public function setName($family = "", $first = "", $additional = "", $prefix = "", $suffix = "")
167
    {
168
        //$this->properties["N;".$this->encoding] = encode($family).";".encode($first).";".encode($additional).";".encode($prefix).";".encode($suffix);
169
        $this->properties["N"] = encode($family) . ";" . encode($first) . ";" . encode($additional) . ";" . encode($prefix) . ";" . encode($suffix);
170
        $this->filename = "$first%20$family.vcf";
171
        if (empty($this->properties["FN"])) {
172
            $this->setFormattedName(trim("$prefix $first $additional $family $suffix"));
173
        }
174
    }
175
176
    /**
177
     *  mise en forme de l'anniversaire
178
     *
179
     *  @param  integer   $date     Date
180
     *  @return void
181
     */
182
    public function setBirthday($date)
183
    {
184
        // $date format is YYYY-MM-DD - RFC 2425 and RFC 2426 for vcard v3
185
        // $date format is YYYYMMDD or ISO8601 for vcard v4
186
        $this->properties["BDAY"] = dol_print_date($date, 'dayxcard');
187
    }
188
189
    /**
190
     *  Address
191
     *
192
     *  @param  string  $postoffice     Postoffice
193
     *  @param  string  $extended       Extended
194
     *  @param  string  $street         Street
195
     *  @param  string  $city           City
196
     *  @param  string  $region         Region
197
     *  @param  string  $zip            Zip
198
     *  @param  string  $country        Country
199
     *  @param  string  $type           Type
200
     *  @param  string  $label          Label
201
     *  @return void
202
     */
203
    public function setAddress($postoffice = "", $extended = "", $street = "", $city = "", $region = "", $zip = "", $country = "", $type = "", $label = "")
204
    {
205
        // $type may be DOM | INTL | POSTAL | PARCEL | HOME | WORK or any combination of these: e.g. "WORK;PARCEL;POSTAL"
206
        $key = "ADR";
207
        if ($type != "") {
208
            $key .= ";" . $type;
209
        }
210
        if ($label != "") {
211
            $key .= ';LABEL="' . encode($label) . '"';
212
        }
213
        $key .= ";" . $this->encoding;
214
        $this->properties[$key] = encode($postoffice) . ";" . encode($extended) . ";" . encode($street) . ";" . encode($city) . ";" . encode($region) . ";" . encode($zip) . ";" . encode($country);
215
216
        //if ($this->properties["LABEL;".$type.";".$this->encoding] == '') {
217
            //$this->setLabel($postoffice, $extended, $street, $city, $region, $zip, $country, $type);
218
        //}
219
    }
220
221
    /**
222
     *  Address (old standard)
223
     *
224
     *  @param  string  $postoffice     Postoffice
225
     *  @param  string  $extended       Extended
226
     *  @param  string  $street         Street
227
     *  @param  string  $city           City
228
     *  @param  string  $region         Region
229
     *  @param  string  $zip            Zip
230
     *  @param  string  $country        Country
231
     *  @param  string  $type           Type
232
     *  @return void
233
     *  @deprecated
234
     */
235
    public function setLabel($postoffice = "", $extended = "", $street = "", $city = "", $region = "", $zip = "", $country = "", $type = "HOME")
236
    {
237
        $label = "";
238
        if ($postoffice != "") {
239
            $label .= "$postoffice\r\n";
240
        }
241
        if ($extended != "") {
242
            $label .= "$extended\r\n";
243
        }
244
        if ($street != "") {
245
            $label .= "$street\r\n";
246
        }
247
        if ($zip != "") {
248
            $label .= "$zip ";
249
        }
250
        if ($city != "") {
251
            $label .= "$city\r\n";
252
        }
253
        if ($region != "") {
254
            $label .= "$region\r\n";
255
        }
256
        if ($country != "") {
257
            $country .= "$country\r\n";
258
        }
259
260
        $this->properties["LABEL;$type;" . $this->encoding] = encode($label);
261
    }
262
263
    /**
264
     *  Add a e-mail address to this vCard
265
     *
266
     *  @param  string  $address        E-mail address
267
     *  @param  string  $type           (optional) The type of the e-mail (typical "PREF" or "INTERNET")
268
     *  @return void
269
     */
270
    public function setEmail($address, $type = "")
271
    {
272
        $key = "EMAIL";
273
        if ($type == "PREF") {
274
            $key .= ";PREF=1";
275
        } elseif (!empty($type)) {
276
            $key .= ";TYPE=" . dol_strtolower($type);
277
        }
278
        $this->properties[$key] = $address;
279
    }
280
281
    /**
282
     *  mise en forme de la note
283
     *
284
     *  @param  string  $note       Note
285
     *  @return void
286
     */
287
    public function setNote($note)
288
    {
289
        $this->properties["NOTE;" . $this->encoding] = encode($note);
290
    }
291
292
    /**
293
     *  mise en forme de la fonction
294
     *
295
     *  @param  string  $title      Title
296
     *  @return void
297
     */
298
    public function setTitle($title)
299
    {
300
        $this->properties["TITLE;" . $this->encoding] = encode($title);
301
    }
302
303
304
    /**
305
     *  mise en forme de la societe
306
     *
307
     *  @param  string  $org        Org
308
     *  @return void
309
     */
310
    public function setOrg($org)
311
    {
312
        $this->properties["ORG;" . $this->encoding] = encode($org);
313
    }
314
315
316
    /**
317
     *  mise en forme du logiciel generateur
318
     *
319
     *  @param  string  $prodid     Prodid
320
     *  @return void
321
     */
322
    public function setProdId($prodid)
323
    {
324
        $this->properties["PRODID"] = encode($prodid);
325
    }
326
327
328
    /**
329
     *  mise en forme du logiciel generateur
330
     *
331
     *  @param  string  $uid    Uid
332
     *  @return void
333
     */
334
    public function setUID($uid)
335
    {
336
        $this->properties["UID"] = encode($uid);
337
    }
338
339
340
    /**
341
     *  mise en forme de l'url
342
     *
343
     *  @param  string  $url        URL
344
     *  @param  string  $type       Type
345
     *  @return void
346
     */
347
    public function setURL($url, $type = "")
348
    {
349
        // $type may be WORK | HOME
350
        $key = "URL";
351
        if ($type != "") {
352
            $key .= ";$type";
353
        }
354
        $this->properties[$key] = $url;
355
    }
356
357
    /**
358
     *  permet d'obtenir une vcard
359
     *
360
     *  @return string
361
     */
362
    public function getVCard()
363
    {
364
        $text = "BEGIN:VCARD\r\n";
365
        $text .= "VERSION:4.0\r\n";     // With V4, all encoding are UTF-8
366
        //$text.= "VERSION:2.1\r\n";
367
        foreach ($this->properties as $key => $value) {
368
            $newkey = preg_replace('/-.*$/', '', $key); // remove suffix -twitter, -facebook, ...
369
            $text .= $newkey . ":" . $value . "\r\n";
370
        }
371
        $text .= "REV:" . date("Ymd") . "T" . date("His") . "Z\r\n";
372
        //$text .= "MAILER: Dolibarr\r\n";
373
        $text .= "END:VCARD\r\n";
374
        return $text;
375
    }
376
377
    /**
378
     *  permet d'obtenir le nom de fichier
379
     *
380
     *  @return string      Filename
381
     */
382
    public function getFileName()
383
    {
384
        return $this->filename;
385
    }
386
387
    /**
388
     * Return a VCARD string
389
     * See RFC https://datatracker.ietf.org/doc/html/rfc6350
390
     *
391
     * @param   Object          $object     Object (User or Contact)
392
     * @param   Societe|null    $company    Company. May be null
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Core\Classes\Societe was not found. Did you mean Societe? If so, make sure to prefix the type with \.
Loading history...
393
     * @param   Translate       $langs      Lang object
394
     * @param   string          $urlphoto   Full public URL of photo
395
     * @return  string                      String
396
     */
397
    public function buildVCardString($object, $company, $langs, $urlphoto = '')
398
    {
399
        global $dolibarr_main_instance_unique_id;
400
401
        $this->setProdId('Dolibarr ' . DOL_VERSION);
402
403
        $this->setUID('DOLIBARR-USERID-' . dol_trunc(md5('vcard' . $dolibarr_main_instance_unique_id), 8, 'right', 'UTF-8', 1) . '-' . $object->id);
404
        $this->setName($object->lastname, $object->firstname, "", $object->civility_code, "");
405
        $this->setFormattedName($object->getFullName($langs, 1));
406
407
        if ($urlphoto) {
408
            $mimetype = dol_mimetype($urlphoto);
409
            if ($mimetype) {
410
                $this->setPhoto($mimetype, $urlphoto);
411
            }
412
        }
413
414
        if ($object->office_phone) {
415
            $this->setPhoneNumber($object->office_phone, "TYPE=WORK,VOICE");
416
        }
417
        /* disabled
418
        if ($object->personal_mobile) {
419
            $this->setPhoneNumber($object->personal_mobile, "TYPE=CELL,VOICE");
420
        }*/
421
        if ($object->user_mobile) {
422
            $this->setPhoneNumber($object->user_mobile, "TYPE=CELL,VOICE");
423
        }
424
        if ($object->office_fax) {
425
            $this->setPhoneNumber($object->office_fax, "TYPE=WORK,FAX");
426
        }
427
428
        if (!empty($object->socialnetworks)) {
429
            foreach ($object->socialnetworks as $key => $val) {
430
                if (empty($val)) {  // Disacard social network if empty
431
                    continue;
432
                }
433
                $urlsn = '';
434
                if ($key == 'linkedin') {
435
                    if (!preg_match('/^http/', $val)) {
436
                        $urlsn = 'https://www.' . $key . '.com/company/' . urlencode($val);
437
                    } else {
438
                        $urlsn = $val;
439
                    }
440
                } elseif ($key == 'youtube') {
441
                    if (!preg_match('/^http/', $val)) {
442
                        $urlsn = 'https://www.' . $key . '.com/user/' . urlencode($val);
443
                    } else {
444
                        $urlsn = $val;
445
                    }
446
                } else {
447
                    if (!preg_match('/^http/', $val)) {
448
                        $urlsn = 'https://www.' . $key . '.com/' . urlencode($val);
449
                    } else {
450
                        $urlsn = $val;
451
                    }
452
                }
453
                if ($urlsn) {
454
                    $this->properties["SOCIALPROFILE;TYPE=WORK-" . $key] = $key . ':' . $urlsn;
455
                }
456
            }
457
        }
458
459
        $country = $object->country_code ? $object->country : '';
460
461
        // User address
462
        if (!($object->element != 'user') || getDolUserInt('USER_PUBLIC_SHOW_ADDRESS', 0, $object)) {
463
            if ($object->address || $object->town || $object->state || $object->zip || $object->country) {
464
                $this->setAddress("", "", $object->address, $object->town, $object->state, $object->zip, $country, "");
465
                //$this->setLabel("", "", $object->address, $object->town, $object->state, $object->zip, $country, "TYPE=HOME");
466
            }
467
        }
468
469
        if ($object->email) {
470
            $this->setEmail($object->email, "TYPE=WORK");
471
        }
472
        /* disabled
473
        if ($object->personal_email) {
474
            $this->setEmail($object->personal_email, "TYPE=HOME");
475
        } */
476
        if ($object->note_public) {
477
            $this->setNote($object->note_public);
478
        }
479
        if ($object->job) {
480
            $this->setTitle($object->job);
481
        }
482
483
        // For user, $object->url is not defined
484
        // For contact, $object->url is not defined
485
        if (!empty($object->url)) {
486
            $this->setURL($object->url, "");
487
        }
488
489
        if (is_object($company)) {
490
            // Si user linked to a thirdparty and not a physical people
491
            if ($company->typent_code != 'TE_PRIVATE') {
492
                $this->setOrg($company->name);
493
            }
494
495
            $this->setURL($company->url, "");
496
497
            if ($company->phone && $company->phone != $object->office_phone) {
498
                $this->setPhoneNumber($company->phone, "TYPE=WORK,VOICE");
499
            }
500
            if ($company->fax && $company->fax != $object->office_fax) {
501
                $this->setPhoneNumber($company->fax, "TYPE=WORK,FAX");
502
            }
503
            if ($company->address || $company->town || $company->state || $company->zip || $company->country) {
504
                $this->setAddress("", "", $company->address, $company->town, $company->state, $company->zip, $company->country, "TYPE=WORK");
505
            }
506
507
            if ($company->email && $company->email != $object->email) {
508
                $this->setEmail($company->email, "TYPE=WORK");
509
            }
510
511
            /*
512
            if (!empty($company->socialnetworks)) {
513
                foreach ($company->socialnetworks as $key => $val) {
514
                    $urlsn = '';
515
                    if ($key == 'linkedin') {
516
                        if (!preg_match('/^http/', $val)) {
517
                            $urlsn = 'https://www.'.$key.'.com/company/'.urlencode($val);
518
                        } else {
519
                            $urlsn = $val;
520
                        }
521
                    } elseif ($key == 'youtube') {
522
                        if (!preg_match('/^http/', $val)) {
523
                            $urlsn = 'https://www.'.$key.'.com/user/'.urlencode($val);
524
                        } else {
525
                            $urlsn = $val;
526
                        }
527
                    } else {
528
                        if (!preg_match('/^http/', $val)) {
529
                            $urlsn = 'https://www.'.$key.'.com/'.urlencode($val);
530
                        } else {
531
                            $urlsn = $val;
532
                        }
533
                    }
534
                    if ($urlsn) {
535
                        $this->properties["socialProfile;type=".$key] = $urlsn;
536
                    }
537
                }
538
            }
539
            */
540
        }
541
542
        // Birthday
543
        if (!($object->element != 'user') || getDolUserInt('USER_PUBLIC_SHOW_BIRTH', 0, $object)) {
544
            if ($object->birth) {
545
                $this->setBirthday($object->birth);
546
            }
547
        }
548
549
        // Return VCard string
550
        return $this->getVCard();
551
    }
552
553
554
    /* Example from Microsoft Outlook 2019
555
556
    BEGIN:VCARD
557
    VERSION:2.1
558
559
    N;LANGUAGE=de:surename;forename;secondname;Sir;jun.
560
    FN:Sir surename secondname forename jun.
561
    ORG:Companyname
562
    TITLE:position
563
    TEL;WORK;VOICE:work-phone-number
564
    TEL;HOME;VOICE:private-phone-number
565
    TEL;CELL;VOICE:mobile-phone-number
566
    TEL;WORK;FAX:fax-phone-number
567
    ADR;WORK;PREF:;;street and number;town;region;012345;Deutschland
568
    LABEL;WORK;PREF;ENCODING=QUOTED-PRINTABLE:street and number=0D=0A=
569
    =0D=0A=
570
    012345  town  region
571
    X-MS-OL-DEFAULT-POSTAL-ADDRESS:2
572
    URL;WORK:www.mywebpage.de
573
    EMAIL;PREF;INTERNET:[email protected]
574
    EMAIL;INTERNET:[email protected]
575
    EMAIL;INTERNET:[email protected]
576
    X-MS-IMADDRESS:[email protected]
577
    REV:20200424T104242Z
578
579
    END:VCARD
580
    */
581
}
582