Skip to content

Commit fb860b4

Browse files
committed
utf8 check
1 parent da58bad commit fb860b4

5 files changed

Lines changed: 50 additions & 16 deletions

File tree

src/Fields/AgentField.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public function relevantRender(): mixed
3636
public function __toString(): string
3737
{
3838
if (! $this->agentVCard) {
39-
return null;
39+
return '';
4040
}
4141

4242
$agentVCardArray = explode(PHP_EOL, (string) $this->agentVCard);

src/Models/AbstractVCard.php

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
abstract class AbstractVCard
1616
{
17+
public const RFC_LINE_BREAK = "\r\n";
18+
1719
public string $version;
1820

1921
public stdClass $relevantData;
@@ -418,19 +420,28 @@ public function getX(string $name, bool $multiple = false): mixed
418420

419421
public function toString(): string
420422
{
421-
$vCardString = 'BEGIN:VCARD'.PHP_EOL;
422-
$vCardString .= 'VERSION:'.$this->version.PHP_EOL;
423+
$lines = [
424+
'BEGIN:VCARD',
425+
'VERSION:'.$this->version,
426+
];
423427

424428
foreach ($this->properties as $name => $property) {
425429
if ($name == 'version') {
426430
continue;
427431
}
428-
$vCardString .= (string) $property.PHP_EOL;
432+
433+
$propertyString = trim((string) $property);
434+
435+
if ($propertyString === '') {
436+
continue;
437+
}
438+
439+
$lines[] = $propertyString;
429440
}
430441

431-
$vCardString .= 'END:VCARD';
442+
$lines[] = 'END:VCARD';
432443

433-
return $vCardString;
444+
return implode(self::RFC_LINE_BREAK, $lines);
434445
}
435446

436447
public function __toString(): string
@@ -441,7 +452,7 @@ public function __toString(): string
441452
public function export(string $filePath): void
442453
{
443454
try {
444-
$fp = fopen($filePath, 'w');
455+
$fp = fopen($filePath, 'wb');
445456
fwrite($fp, $this->toString());
446457
fclose($fp);
447458
} catch (Throwable $e) {

src/VCardBuilder.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,11 @@ public function getVersion(): ?VCardVersionEnum
8181
$versionProperty = $this->version ?? $this->getProperty('version');
8282

8383
if ($versionProperty) {
84-
if($versionProperty instanceof VCardVersionEnum){
84+
if ($versionProperty instanceof VCardVersionEnum) {
8585
$versionEnum = $versionProperty;
86-
}elseif (! empty($versionProperty->fields)) {
86+
} elseif (! empty($versionProperty->fields)) {
8787
$versionValue = reset($versionProperty->fields)->value;
88-
88+
8989
$versionEnum = VCardVersionEnum::tryFrom($versionValue);
9090
}
9191
}

src/VCardsCollection.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,13 @@ public function first(): ?AbstractVCard
5656

5757
public function toString(): string
5858
{
59-
$collectionString = '';
59+
$vCards = [];
60+
6061
foreach ($this->vCards as $vCard) {
61-
$collectionString .= (string) $vCard;
62+
$vCards[] = $vCard->toString();
6263
}
6364

64-
return $collectionString;
65+
return implode(AbstractVCard::RFC_LINE_BREAK, $vCards);
6566
}
6667

6768
public function __toString(): string
@@ -74,11 +75,11 @@ public function export(string $filePath, bool $append = false): void
7475
try {
7576
$mode = ($append) ? 'a' : 'w';
7677

77-
$fp = fopen($filePath, $mode);
78+
$fp = fopen($filePath, $mode.'b');
7879

7980
if ($mode == 'a') {
80-
if (filesize($filePath) > 0) {
81-
fwrite($fp, PHP_EOL);
81+
if (file_exists($filePath) && filesize($filePath) > 0) {
82+
fwrite($fp, AbstractVCard::RFC_LINE_BREAK);
8283
}
8384
}
8485

tests/BuilderTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,25 @@
4141
assertEquals('Jeffrey Lebowski', $vCard->getFullName());
4242
assertStringContainsString('EMAIL:jeff@example.com', (string) $vCard);
4343
});
44+
45+
it('exports utf-8 vcards with windows-safe line endings', function () {
46+
$path = sys_get_temp_dir().DIRECTORY_SEPARATOR.'vcardio-accented.vcf';
47+
48+
VCardBuilder::make()
49+
->version('3.0')
50+
->fullName('Élodie Brûlé')
51+
->name('Brûlé', 'Élodie')
52+
->organization('Société Générale')
53+
->export($path);
54+
55+
$raw = file_get_contents($path);
56+
57+
expect($raw)->not->toBeFalse();
58+
59+
expect(substr($raw, 0, 3))->not->toBe("\xEF\xBB\xBF");
60+
assertStringContainsString("BEGIN:VCARD\r\nVERSION:3.0\r\n", $raw);
61+
assertStringContainsString("FN:Élodie Brûlé\r\n", $raw);
62+
assertStringContainsString("N:Brûlé;Élodie\r\n", $raw);
63+
assertStringContainsString("ORG:Société Générale\r\n", $raw);
64+
expect($raw)->toContain("\r\nEND:VCARD");
65+
});

0 commit comments

Comments
 (0)