Actualización

This commit is contained in:
Xes
2025-04-10 12:24:57 +02:00
parent 8969cc929d
commit 45420b6f0d
39760 changed files with 4303286 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
composer.lock
vendor
.idea/
.phpunit.result.cache

View File

@@ -0,0 +1,22 @@
language: php
dist: trusty
php:
- 7.3
- 8.0
- hhvm
sudo: false
before_script:
- composer self-update
- composer install --prefer-source --no-interaction
script:
- vendor/bin/phpunit --coverage-text
matrix:
allow_failures:
- php: hhvm
fast_finish: true

View File

@@ -0,0 +1,76 @@
1.2.2 (2015-11-30)
--
Improvements:
* Probably a fix for UTF-8 in outlook 2010
1.2.1 (2015-07-23)
--
Improvements:
* You can now set the charset by using $vcard->setCharset('ISO-8859-1');
1.2.0 (2015-06-01)
--
Improvements:
* You can now add some properties multiple times: email, address, phone number and url
1.1.11 (2015-05-21)
--
Improvements:
* addMedia updated to check if correct file type.
1.1.10 (2015-05-20)
--
Improvements:
* Multiple mailaddresses allowed.
* Chaining integrated to add functions.
1.1.9 (2015-04-21)
--
Improvements:
* getHeaders() is now separate function. So frameworks can use this.
* Fix for iOS 8 to return vcard without calendar wrapper.
1.1.8 (2015-03-09)
--
Bugfixes:
* Fixes $include/$exclude, #27
* Fixes special characters by using external transliterator class.
1.1.7 (2015-03-05)
--
Improvements:
* Images should per default be included in our vcard.
Bugfixes:
* Fix for the ->get() which didn't return anything.
1.1.6 (2015-02-24)
--
Improvements:
* Add line folding, check #16
* Refactored some functions.
* PSR-2-code-styling applied.
* PHPCS applied.
Bugfixes:
* Fix fetching PHOTO elements.
1.1.5 (2015-01-30)
--
Bugfixes:
* Updated the deprecated MIME detection, check #16
1.1.4 (2015-01-22)
--
Improvements:
* PHPUnit Tests added
* Exception is now a separate class.
* Renamed the variables $firstName and $lastName
Bugfixes:
* Filename: Fixed double underscores when no "additional" field was given.
1.1.3 (2015-01-22)
--
Bugfixes:
* Name: Double space when no "additional" field is given. Fixes #8

20
vendor/jeroendesloovere/vcard/LICENSE vendored Normal file
View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2014 Jeroen Desloovere
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

137
vendor/jeroendesloovere/vcard/README.md vendored Normal file
View File

@@ -0,0 +1,137 @@
# VCard PHP library
[![Latest Stable Version](http://img.shields.io/packagist/v/jeroendesloovere/vcard.svg)](https://packagist.org/packages/jeroendesloovere/vcard)
[![License](http://img.shields.io/badge/license-MIT-lightgrey.svg)](https://github.com/jeroendesloovere/vcard/blob/master/LICENSE)
[![Build Status](https://travis-ci.org/jeroendesloovere/vcard.svg?branch=master)](https://travis-ci.org/jeroendesloovere/vcard)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/jeroendesloovere/vcard/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/jeroendesloovere/vcard/?branch=master)
This VCard PHP library can generate a vCard with some data. When using an iOS device < iOS 8 it will export as a .ics file because iOS devices don't support the default .vcf files.
**NOTE**: We are working on a complete new version to work with vCard version 4.0, with extreme good code quality. [Check out the new version](https://github.com/jeroendesloovere/vcard/tree/2.0.0-dev)
## Usage
### Installation
```bash
composer require jeroendesloovere/vcard
```
> This will install the latest version of vcard with [Composer](https://getcomposer.org)
### Example
``` php
use JeroenDesloovere\VCard\VCard;
// define vcard
$vcard = new VCard();
// define variables
$lastname = 'Desloovere';
$firstname = 'Jeroen';
$additional = '';
$prefix = '';
$suffix = '';
// add personal data
$vcard->addName($lastname, $firstname, $additional, $prefix, $suffix);
// add work data
$vcard->addCompany('Siesqo');
$vcard->addJobtitle('Web Developer');
$vcard->addRole('Data Protection Officer');
$vcard->addEmail('info@jeroendesloovere.be');
$vcard->addPhoneNumber(1234121212, 'PREF;WORK');
$vcard->addPhoneNumber(123456789, 'WORK');
$vcard->addAddress(null, null, 'street', 'worktown', null, 'workpostcode', 'Belgium');
$vcard->addLabel('street, worktown, workpostcode Belgium');
$vcard->addURL('http://www.jeroendesloovere.be');
$vcard->addPhoto(__DIR__ . '/landscape.jpeg');
// return vcard as a string
//return $vcard->getOutput();
// return vcard as a download
return $vcard->download();
// save vcard on disk
//$vcard->setSavePath('/path/to/directory');
//$vcard->save();
```
> [View all examples](/examples/example.php) or check [the VCard class](/src/VCard.php).
### Parsing examples
The parser can either get passed a VCard string, like so:
```php
// load VCardParser classes
use JeroenDesloovere\VCard\VCardParser;
$parser = new VCardParser($vcardString);
echo $parser->getCardAtIndex(0)->fullname; // Prints the full name.
```
Or by using a factory method with a file name:
```php
$parser = VCardParser::parseFromFile('path/to/file.vcf');
echo $parser->getCardAtIndex(0)->fullname; // Prints the full name.
```
> [View the parsing example](/examples/example_parsing.php) or check the [the VCardParser class](/src/VCardParser.php) class.
**Support for frameworks**
I've created a Symfony Bundle: [VCard Bundle](https://github.com/jeroendesloovere/vcard-bundle)
Usage in for example: Laravel
```php
return Response::make(
$this->vcard->getOutput(),
200,
$this->vcard->getHeaders(true)
);
```
## Tests
```bash
vendor/bin/phpunit tests
```
## Documentation
The class is well documented inline. If you use a decent IDE you'll see that each method is documented with PHPDoc.
## Contributing
Contributions are **welcome** and will be fully **credited**.
### Pull Requests
> To add or update code
- **Coding Syntax** - Please keep the code syntax consistent with the rest of the package.
- **Add unit tests!** - Your patch won't be accepted if it doesn't have tests.
- **Document any change in behavior** - Make sure the README and any other relevant documentation are kept up-to-date.
- **Consider our release cycle** - We try to follow [semver](http://semver.org/). Randomly breaking public APIs is not an option.
- **Create topic branches** - Don't ask us to pull from your master branch.
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
### Issues
> For bug reporting or code discussions.
More info on how to work with GitHub on help.github.com.
## Credits
- [Jeroen Desloovere](https://github.com/jeroendesloovere)
- [All Contributors](https://github.com/jeroendesloovere/vcard/contributors)
## License
The module is licensed under [MIT](./LICENSE.md). In short, this license allows you to do everything as long as the copyright statement stays present.

View File

@@ -0,0 +1,29 @@
{
"name": "jeroendesloovere/vcard",
"type": "library",
"description": "This VCard PHP class can generate a vCard with some data. When using an iOS device it will export as a .ics file because iOS devices don't support the default .vcf files.",
"keywords": ["vcard", "generator", ".vcf", "php"],
"homepage": "https://github.com/jeroendesloovere/vcard",
"license": "MIT",
"authors": [
{
"name": "Jeroen Desloovere",
"email": "info@jeroendesloovere.be",
"homepage": "http://jeroendesloovere.be",
"role": "Developer"
}
],
"require": {
"php": ">=7.3.0",
"behat/transliterator": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"autoload": {
"psr-4": { "JeroenDesloovere\\VCard\\": "src/" }
},
"autoload-dev": {
"psr-4": { "JeroenDesloovere\\VCard\\": "tests/" }
}
}

View File

@@ -0,0 +1,63 @@
BEGIN:VCARD
VERSION:3.0
FN:Thies-Tillman Jacobsen
N:Jacobsen;Thies-Tillman;;;
BDAY:1908-10-25
CATEGORIES:Sportverein
TZ:+0100
NOTE:Lieblingsfarbe: Violett
END:VCARD
BEGIN:VCARD
VERSION:3.0
FN:Lenn Biernoth
N:Biernoth;Lenn;;;
X-MAIDENNAME:Iser
BDAY:1951-11-22
BIRTHPLACE:Hörstel
TITLE:Strassenreiniger
CATEGORIES:Familie
TZ:+0100
EMAIL;TYPE=INTERNET;TYPE=HOME;TYPE=PREF:lenn@lbi.net
NOTE:Interessen: Internet trollen, Kekse backen, Videos schneiden\nLieblingsessen: Chillibrot mit Kartoffelpuffer
END:VCARD
BEGIN:VCARD
VERSION:3.0
FN:Ludwig-Götz Graßl
N:Graßl;Ludwig-Götz;;;
X-MAIDENNAME:Schoen
BDAY:1943-02-07
BIRTHPLACE:Kaltennordheim
TITLE:Rentner
CATEGORIES:Piratenpartei
TZ:+0100
EMAIL;TYPE=INTERNET;TYPE=HOME;TYPE=PREF:ludwig-goetz@ludwig-goetz-grassl.org
NOTE:Interessen: Stofftiere, Basketball\nLieblingsessen: Reiberouladen
END:VCARD
BEGIN:VCARD
VERSION:3.0
FN:Marita Kreutzer
N:Kreutzer;Marita;;;
NICKNAME:mkr
X-MAIDENNAME:Sievers
BDAY:1943-07-26
TITLE:Rentnerin
CATEGORIES:CCC
TZ:+0100
NOTE:Interessen: Handarbeiten\nLieblingsfarbe: Weiß\nLieblingsessen: Orangen
END:VCARD
BEGIN:VCARD
VERSION:3.0
FN:Kathi Hoelzl
N:Hoelzl;Kathi;;;
BDAY:2002-07-11
BIRTHPLACE:Grevenbroich
CATEGORIES:Piratenpartei
TZ:+0100
EMAIL;TYPE=INTERNET;TYPE=HOME;TYPE=PREF:kathi.hoelzl@alhilal.net
URL;TYPE=HOME:http://kho.me/
END:VCARD

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@@ -0,0 +1,53 @@
<?php
/**
* VCard generator test - can save to file or output as a download
*/
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../src/VCard.php';
use JeroenDesloovere\VCard\VCard;
// define vcard
$vcard = new VCard();
// define variables
$firstname = 'Jeroen';
$lastname = 'Desloovere';
$additional = '';
$prefix = '';
$suffix = '';
// add personal data
$vcard->addName($lastname, $firstname, $additional, $prefix, $suffix);
// add work data
$vcard->addCompany('Siesqo');
$vcard->addJobtitle('Web Developer');
$vcard->addEmail('info@jeroendesloovere.be');
$vcard->addPhoneNumber(1234121212, 'PREF;WORK');
$vcard->addPhoneNumber(123456789, 'WORK');
$vcard->addAddress(null, null, 'street', 'worktown', null, 'workpostcode', 'Belgium');
$vcard->addURL('http://www.jeroendesloovere.be');
$vcard->addLabel('street, worktown, workpostcode Belgium', 'work');
$vcard->addPhoto(__DIR__ . '/assets/landscape.jpeg');
//$vcard->addPhoto('https://raw.githubusercontent.com/jeroendesloovere/vcard/master/tests/image.jpg');
// return vcard as a string
//return $vcard->getOutput();
// return vcard as a download
return $vcard->download();
// echo message
echo 'A personal vCard is saved in this folder: ' . __DIR__;
// or
// save the card in file in the current folder
// return $vcard->save();
// echo message
// echo 'A personal vCard is saved in this folder: ' . __DIR__;

View File

@@ -0,0 +1,24 @@
<?php
/**
* VCardParser test - can parse bundled VCF file into CSV
*/
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../src/VCardParser.php';
// load VCardParser classes
use JeroenDesloovere\VCard\VCardParser;
$pathToVCardExample = __DIR__ . '/assets/contacts.vcf';
$parser = VCardParser::parseFromFile($pathToVCardExample);
foreach($parser as $vcard) {
$lastname = $vcard->lastname;
$firstname = $vcard->firstname;
$birthday = $vcard->birthday->format('Y-m-d');
printf("\"%s\",\"%s\",\"%s\"", $lastname, $firstname, $birthday);
echo PHP_EOL;
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="./vendor/autoload.php" colors="true" verbose="true" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<coverage>
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>
<testsuites>
<testsuite name="JeroenDesloovere Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
<?php
namespace JeroenDesloovere\VCard;
/*
* This file is part of the VCard PHP Class from Jeroen Desloovere.
*
* For the full copyright and license information, please view the license
* file that was distributed with this source code.
*/
/**
* VCard Exception PHP Class.
*/
class VCardException extends \Exception
{
public static function elementAlreadyExists($element)
{
return new self('You can only set "' . $element . '" once.');
}
public static function emptyURL()
{
return new self('Nothing returned from URL.');
}
public static function invalidImage()
{
return new self('Returned data is not an image.');
}
public static function outputDirectoryNotExists()
{
return new self('Output directory does not exist.');
}
}

View File

@@ -0,0 +1,341 @@
<?php
namespace JeroenDesloovere\VCard;
/*
* This file is part of the VCard PHP Class from Jeroen Desloovere.
*
* For the full copyright and license information, please view the license
* file that was distributed with this source code.
*/
use Iterator;
use OutOfBoundsException;
use RuntimeException;
use stdClass;
/**
* VCard PHP Class to parse .vcard files.
*
* This class is heavily based on the Zendvcard project (seemingly abandoned),
* which is licensed under the Apache 2.0 license.
* More information can be found at https://code.google.com/archive/p/zendvcard/
*/
class VCardParser implements Iterator
{
/**
* The raw VCard content.
*
* @var string
*/
protected $content;
/**
* The VCard data objects.
*
* @var array
*/
protected $vcardObjects;
/**
* The iterator position.
*
* @var int
*/
protected $position;
/**
* Helper function to parse a file directly.
*
* @param string $filename
* @return self
*/
public static function parseFromFile($filename)
{
if (file_exists($filename) && is_readable($filename)) {
return new self(file_get_contents($filename));
} else {
throw new \RuntimeException(sprintf("File %s is not readable, or doesn't exist.", $filename));
}
}
public function __construct($content)
{
$this->content = $content;
$this->vcardObjects = [];
$this->rewind();
$this->parse();
}
public function rewind(): void
{
$this->position = 0;
}
public function current(): \stdClass
{
if (! $this->valid()) {
throw new RuntimeException('invalid');
}
return $this->getCardAtIndex($this->position);
}
public function key(): int
{
return $this->position;
}
public function next(): void
{
$this->position++;
}
public function valid(): bool
{
return !empty($this->vcardObjects[$this->position]);
}
/**
* Fetch all the imported VCards.
*
* @return array
* A list of VCard card data objects.
*/
public function getCards(): array
{
return $this->vcardObjects;
}
/**
* Fetch the imported VCard at the specified index.
*
* @throws OutOfBoundsException
*
* @param int $i
*
* @return stdClass
* The card data object.
*/
public function getCardAtIndex($i): stdClass
{
if (isset($this->vcardObjects[$i])) {
return $this->vcardObjects[$i];
}
throw new \OutOfBoundsException();
}
/**
* Start the parsing process.
*
* This method will populate the data object.
*/
protected function parse()
{
// Normalize new lines.
$this->content = str_replace(["\r\n", "\r"], "\n", $this->content);
// RFC2425 5.8.1. Line delimiting and folding
// Unfolding is accomplished by regarding CRLF immediately followed by
// a white space character (namely HTAB ASCII decimal 9 or. SPACE ASCII
// decimal 32) as equivalent to no characters at all (i.e., the CRLF
// and single white space character are removed).
$this->content = preg_replace("/\n(?:[ \t])/", "", $this->content);
$lines = explode("\n", $this->content);
// Parse the VCard, line by line.
foreach ($lines as $line) {
$line = trim($line);
if (strtoupper($line) == "BEGIN:VCARD") {
$cardData = new \stdClass();
} elseif (strtoupper($line) == "END:VCARD") {
$this->vcardObjects[] = $cardData;
} elseif (!empty($line)) {
// Strip grouping information. We don't use the group names. We
// simply use a list for entries that have multiple values.
// As per RFC, group names are alphanumerical, and end with a
// period (.).
$line = preg_replace('/^\w+\./', '', $line);
$type = '';
$value = '';
@list($type, $value) = explode(':', $line, 2);
$types = explode(';', $type);
$element = strtoupper($types[0]);
array_shift($types);
// Normalize types. A type can either be a type-param directly,
// or can be prefixed with "type=". E.g.: "INTERNET" or
// "type=INTERNET".
if (!empty($types)) {
$types = array_map(function($type) {
return preg_replace('/^type=/i', '', $type);
}, $types);
}
$i = 0;
$rawValue = false;
foreach ($types as $type) {
if (preg_match('/base64/', strtolower($type))) {
$value = base64_decode($value);
unset($types[$i]);
$rawValue = true;
} elseif (preg_match('/encoding=b/', strtolower($type))) {
$value = base64_decode($value);
unset($types[$i]);
$rawValue = true;
} elseif (preg_match('/quoted-printable/', strtolower($type))) {
$value = quoted_printable_decode($value);
unset($types[$i]);
$rawValue = true;
} elseif (strpos(strtolower($type), 'charset=') === 0) {
try {
$value = mb_convert_encoding($value, "UTF-8", substr($type, 8));
} catch (\Exception $e) {
}
unset($types[$i]);
}
$i++;
}
switch (strtoupper($element)) {
case 'FN':
$cardData->fullname = $value;
break;
case 'N':
foreach ($this->parseName($value) as $key => $val) {
$cardData->{$key} = $val;
}
break;
case 'BDAY':
$cardData->birthday = $this->parseBirthday($value);
break;
case 'ADR':
if (!isset($cardData->address)) {
$cardData->address = [];
}
$key = !empty($types) ? implode(';', $types) : 'WORK;POSTAL';
$cardData->address[$key][] = $this->parseAddress($value);
break;
case 'TEL':
if (!isset($cardData->phone)) {
$cardData->phone = [];
}
$key = !empty($types) ? implode(';', $types) : 'default';
$cardData->phone[$key][] = $value;
break;
case 'EMAIL':
if (!isset($cardData->email)) {
$cardData->email = [];
}
$key = !empty($types) ? implode(';', $types) : 'default';
$cardData->email[$key][] = $value;
break;
case 'REV':
$cardData->revision = $value;
break;
case 'VERSION':
$cardData->version = $value;
break;
case 'ORG':
$cardData->organization = $value;
break;
case 'URL':
if (!isset($cardData->url)) {
$cardData->url = [];
}
$key = !empty($types) ? implode(';', $types) : 'default';
$cardData->url[$key][] = $value;
break;
case 'TITLE':
$cardData->title = $value;
break;
case 'PHOTO':
if ($rawValue) {
$cardData->rawPhoto = $value;
} else {
$cardData->photo = $value;
}
break;
case 'LOGO':
if ($rawValue) {
$cardData->rawLogo = $value;
} else {
$cardData->logo = $value;
}
break;
case 'NOTE':
$cardData->note = $this->unescape($value);
break;
case 'CATEGORIES':
$cardData->categories = array_map('trim', explode(',', $value));
break;
case 'LABEL':
$cardData->label = $value;
break;
}
}
}
}
protected function parseName($value)
{
@list(
$lastname,
$firstname,
$additional,
$prefix,
$suffix
) = explode(';', $value);
return (object) [
'lastname' => $lastname,
'firstname' => $firstname,
'additional' => $additional,
'prefix' => $prefix,
'suffix' => $suffix,
];
}
protected function parseBirthday($value)
{
return new \DateTime($value);
}
protected function parseAddress($value)
{
@list(
$name,
$extended,
$street,
$city,
$region,
$zip,
$country,
) = explode(';', $value);
return (object) [
'name' => $name,
'extended' => $extended,
'street' => $street,
'city' => $city,
'region' => $region,
'zip' => $zip,
'country' => $country,
];
}
/**
* Unescape newline characters according to RFC2425 section 5.8.4.
* This function will replace escaped line breaks with PHP_EOL.
*
* @link http://tools.ietf.org/html/rfc2425#section-5.8.4
* @param string $text
* @return string
*/
protected function unescape($text)
{
return str_replace("\\n", PHP_EOL, $text);
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace JeroenDesloovere\VCard;
use PHPUnit\Framework\TestCase;
/*
* This file is part of the VCard PHP Class from Jeroen Desloovere.
*
* For the full copyright and license information, please view the license
* file that was distributed with this source code.
*/
/**
* VCard Exception Test.
*/
final class VCardExceptionTest extends TestCase
{
public function testException()
{
$this->expectException(\JeroenDesloovere\VCard\VCardException::class);
throw new VCardException('Testing the VCard error.');
}
}

View File

@@ -0,0 +1,296 @@
<?php
namespace JeroenDesloovere\VCard\tests;
use JeroenDesloovere\VCard\VCard;
use JeroenDesloovere\VCard\VCardParser;
use OutOfBoundsException;
use PHPUnit\Framework\TestCase;
/**
* Unit tests for our VCard parser.
*/
final class VCardParserTest extends TestCase
{
public function testOutOfRangeException()
{
$this->expectException(OutOfBoundsException::class);
$parser = new VCardParser('');
$parser->getCardAtIndex(2);
}
public function testSimpleVcard()
{
$vcard = new VCard();
$vcard->addName("Desloovere", "Jeroen");
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->firstname, "Jeroen");
$this->assertEquals($parser->getCardAtIndex(0)->lastname, "Desloovere");
$this->assertEquals($parser->getCardAtIndex(0)->fullname, "Jeroen Desloovere");
}
public function testBDay()
{
$vcard = new VCard();
$vcard->addBirthday('31-12-2015');
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->birthday->format('Y-m-d'), '2015-12-31');
}
public function testAddress()
{
$vcard = new VCard();
$vcard->addAddress(
"Lorem Corp.",
"(extended info)",
"54th Ipsum Street",
"PHPsville",
"Guacamole",
"01158",
"Gitland",
'WORK;POSTAL'
);
$vcard->addAddress(
"Jeroen Desloovere",
"(extended info, again)",
"25th Some Address",
"Townsville",
"Area 51",
"045784",
"Europe (is a country, right?)",
'WORK;PERSONAL'
);
$vcard->addAddress(
"Georges Desloovere",
"(extended info, again, again)",
"26th Some Address",
"Townsville-South",
"Area 51B",
"04554",
"Europe (no, it isn't)",
'WORK;PERSONAL'
);
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->address['WORK;POSTAL'][0], (object) array(
'name' => "Lorem Corp.",
'extended' => "(extended info)",
'street' => "54th Ipsum Street",
'city' => "PHPsville",
'region' => "Guacamole",
'zip' => "01158",
'country' => "Gitland",
));
$this->assertEquals($parser->getCardAtIndex(0)->address['WORK;PERSONAL'][0], (object) array(
'name' => "Jeroen Desloovere",
'extended' => "(extended info, again)",
'street' => "25th Some Address",
'city' => "Townsville",
'region' => "Area 51",
'zip' => "045784",
'country' => "Europe (is a country, right?)",
));
$this->assertEquals($parser->getCardAtIndex(0)->address['WORK;PERSONAL'][1], (object) array(
'name' => "Georges Desloovere",
'extended' => "(extended info, again, again)",
'street' => "26th Some Address",
'city' => "Townsville-South",
'region' => "Area 51B",
'zip' => "04554",
'country' => "Europe (no, it isn't)",
));
}
public function testPhone()
{
$vcard = new VCard();
$vcard->addPhoneNumber('0984456123');
$vcard->addPhoneNumber('2015123487', 'WORK');
$vcard->addPhoneNumber('4875446578', 'WORK');
$vcard->addPhoneNumber('9875445464', 'PREF;WORK;VOICE');
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->phone['default'][0], '0984456123');
$this->assertEquals($parser->getCardAtIndex(0)->phone['WORK'][0], '2015123487');
$this->assertEquals($parser->getCardAtIndex(0)->phone['WORK'][1], '4875446578');
$this->assertEquals($parser->getCardAtIndex(0)->phone['PREF;WORK;VOICE'][0], '9875445464');
}
public function testEmail()
{
$vcard = new VCard();
$vcard->addEmail('some@email.com');
$vcard->addEmail('site@corp.net', 'WORK');
$vcard->addEmail('site.corp@corp.net', 'WORK');
$vcard->addEmail('support@info.info', 'PREF;WORK');
$parser = new VCardParser($vcard->buildVCard());
// The VCard class uses a default type of "INTERNET", so we do not test
// against the "default" key.
$this->assertEquals($parser->getCardAtIndex(0)->email['INTERNET'][0], 'some@email.com');
$this->assertEquals($parser->getCardAtIndex(0)->email['INTERNET;WORK'][0], 'site@corp.net');
$this->assertEquals($parser->getCardAtIndex(0)->email['INTERNET;WORK'][1], 'site.corp@corp.net');
$this->assertEquals($parser->getCardAtIndex(0)->email['INTERNET;PREF;WORK'][0], 'support@info.info');
}
public function testOrganization()
{
$vcard = new VCard();
$vcard->addCompany('Lorem Corp.');
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->organization, 'Lorem Corp.');
}
public function testUrl()
{
$vcard = new VCard();
$vcard->addUrl('http://www.jeroendesloovere.be');
$vcard->addUrl('http://home.example.com', 'HOME');
$vcard->addUrl('http://work1.example.com', 'PREF;WORK');
$vcard->addUrl('http://work2.example.com', 'PREF;WORK');
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->url['default'][0], 'http://www.jeroendesloovere.be');
$this->assertEquals($parser->getCardAtIndex(0)->url['HOME'][0], 'http://home.example.com');
$this->assertEquals($parser->getCardAtIndex(0)->url['PREF;WORK'][0], 'http://work1.example.com');
$this->assertEquals($parser->getCardAtIndex(0)->url['PREF;WORK'][1], 'http://work2.example.com');
}
public function testNote()
{
$vcard = new VCard();
$vcard->addNote('This is a testnote');
$parser = new VCardParser($vcard->buildVCard());
$vcardMultiline = new VCard();
$vcardMultiline->addNote("This is a multiline note\nNew line content!\r\nLine 2");
$parserMultiline = new VCardParser($vcardMultiline->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->note, 'This is a testnote');
$this->assertEquals(nl2br($parserMultiline->getCardAtIndex(0)->note), nl2br("This is a multiline note" . PHP_EOL . "New line content!" . PHP_EOL . "Line 2"));
}
public function testCategories()
{
$vcard = new VCard();
$vcard->addCategories([
'Category 1',
'cat-2',
'another long category!'
]);
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->categories[0], 'Category 1');
$this->assertEquals($parser->getCardAtIndex(0)->categories[1], 'cat-2');
$this->assertEquals($parser->getCardAtIndex(0)->categories[2], 'another long category!');
}
public function testTitle()
{
$vcard = new VCard();
$vcard->addJobtitle('Ninja');
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->title, 'Ninja');
}
public function testLogo()
{
$image = __DIR__ . '/image.jpg';
$imageUrl = 'https://raw.githubusercontent.com/jeroendesloovere/vcard/master/tests/image.jpg';
$vcard = new VCard();
$vcard->addLogo($image, true);
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->rawLogo, file_get_contents($image));
$vcard = new VCard();
$vcard->addLogo($image, false);
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->logo, __DIR__ . '/image.jpg');
$vcard = new VCard();
$vcard->addLogo($imageUrl, false);
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->logo, $imageUrl);
}
public function testPhoto()
{
$image = __DIR__ . '/image.jpg';
$imageUrl = 'https://raw.githubusercontent.com/jeroendesloovere/vcard/master/tests/image.jpg';
$vcard = new VCard();
$vcard->addPhoto($image, true);
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->rawPhoto, file_get_contents($image));
$vcard = new VCard();
$vcard->addPhoto($image, false);
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->photo, __DIR__ . '/image.jpg');
$vcard = new VCard();
$vcard->addPhoto($imageUrl, false);
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->photo, $imageUrl);
}
public function testVcardDB()
{
$db = '';
$vcard = new VCard();
$vcard->addName("Desloovere", "Jeroen");
$db .= $vcard->buildVCard();
$vcard = new VCard();
$vcard->addName("Lorem", "Ipsum");
$db .= $vcard->buildVCard();
$parser = new VCardParser($db);
$this->assertEquals($parser->getCardAtIndex(0)->fullname, "Jeroen Desloovere");
$this->assertEquals($parser->getCardAtIndex(1)->fullname, "Ipsum Lorem");
}
public function testIteration()
{
// Prepare a VCard DB.
$db = '';
$vcard = new VCard();
$vcard->addName("Desloovere", "Jeroen");
$db .= $vcard->buildVCard();
$vcard = new VCard();
$vcard->addName("Lorem", "Ipsum");
$db .= $vcard->buildVCard();
$parser = new VCardParser($db);
foreach ($parser as $i => $card) {
$this->assertEquals($card->fullname, $i == 0 ? "Jeroen Desloovere" : "Ipsum Lorem");
}
}
public function testFromFile()
{
$parser = VCardParser::parseFromFile(__DIR__ . '/example.vcf');
// Use this opportunity to test fetching all cards directly.
$cards = $parser->getCards();
$this->assertEquals($cards[0]->firstname, "Jeroen");
$this->assertEquals($cards[0]->lastname, "Desloovere");
$this->assertEquals($cards[0]->fullname, "Jeroen Desloovere");
// Check the parsing of grouped items as well, which are present in the
// example file.
$this->assertEquals($cards[0]->url['default'][0], 'http://www.jeroendesloovere.be');
$this->assertEquals($cards[0]->email['INTERNET'][0], 'site@example.com');
}
public function testFileNotFound()
{
$this->expectException(\RuntimeException::class);
$parser = VCardParser::parseFromFile(__DIR__ . '/does-not-exist.vcf');
}
public function testLabel()
{
$label = 'street, worktown, workpostcode Belgium';
$vcard = new VCard();
$vcard->addLabel($label, 'work');
$parser = new VCardParser($vcard->buildVCard());
$this->assertEquals($parser->getCardAtIndex(0)->label, $label);
}
}

View File

@@ -0,0 +1,466 @@
<?php
namespace JeroenDesloovere\VCard\tests;
// required to load
require_once __DIR__ . '/../vendor/autoload.php';
/*
* This file is part of the VCard PHP Class from Jeroen Desloovere.
*
* For the full copyright and license information, please view the license
* file that was distributed with this source code.
*/
use Exception;
use JeroenDesloovere\VCard\VCard;
use PHPUnit\Framework\TestCase;
/**
* This class will test our VCard PHP Class which can generate VCards.
*/
class VCardTest extends TestCase
{
/**
* @var VCard
*/
protected $vcard = null;
/**
* Data provider for testEmail()
*
* @return array
*/
public function emailDataProvider()
{
return [
[['john@doe.com']],
[['john@doe.com', 'WORK' => 'john@work.com']],
[['WORK' => 'john@work.com', 'HOME' => 'john@home.com']],
[['PREF;WORK' => 'john@work.com', 'HOME' => 'john@home.com']],
];
}
/**
* Set up before class
*
* @return void
*/
protected function setUp(): void
{
// set timezone
date_default_timezone_set('Europe/Brussels');
$this->vcard = new VCard();
$this->firstName = 'Jeroen';
$this->lastName = 'Desloovere';
$this->additional = '&';
$this->prefix = 'Mister';
$this->suffix = 'Junior';
$this->emailAddress1 = '';
$this->emailAddress2 = '';
$this->firstName2 = 'Ali';
$this->lastName2 = 'ÖZSÜT';
$this->firstName3 = 'Garçon';
$this->lastName3 = 'Jéroèn';
}
/**
* Tear down after class
*/
protected function tearDown(): void
{
$this->vcard = null;
}
public function testAddAddress()
{
$this->assertEquals($this->vcard, $this->vcard->addAddress(
'',
'88th Floor',
'555 East Flours Street',
'Los Angeles',
'CA',
'55555',
'USA'
));
$this->assertStringContainsString('ADR;WORK;POSTAL;CHARSET=utf-8:;88th Floor;555 East Flours Street;Los Angele', $this->vcard->getOutput());
// Should fold on row 75, so we should not see the full address.
$this->assertStringNotContainsString('ADR;WORK;POSTAL;CHARSET=utf-8:;88th Floor;555 East Flours Street;Los Angeles;CA;55555;', $this->vcard->getOutput());
}
public function testAddBirthday()
{
$this->assertEquals($this->vcard, $this->vcard->addBirthday(''));
}
public function testAddCompany()
{
$this->assertEquals($this->vcard, $this->vcard->addCompany(''));
}
public function testAddCategories()
{
$this->assertEquals($this->vcard, $this->vcard->addCategories([]));
}
public function testAddEmail()
{
$this->assertEquals($this->vcard, $this->vcard->addEmail($this->emailAddress1));
$this->assertEquals($this->vcard, $this->vcard->addEmail($this->emailAddress2));
$this->assertEquals(2, count($this->vcard->getProperties()));
}
public function testAddJobTitle()
{
$this->assertEquals($this->vcard, $this->vcard->addJobtitle(''));
}
public function testAddRole()
{
$this->assertEquals($this->vcard, $this->vcard->addRole(''));
}
public function testAddName()
{
$this->assertEquals($this->vcard, $this->vcard->addName(''));
}
public function testAddNote()
{
$this->assertEquals($this->vcard, $this->vcard->addNote(''));
}
public function testAddPhoneNumber()
{
$this->assertEquals($this->vcard, $this->vcard->addPhoneNumber(''));
$this->assertEquals($this->vcard, $this->vcard->addPhoneNumber(''));
$this->assertCount(2, $this->vcard->getProperties());
}
public function testAddPhotoWithJpgPhoto()
{
$return = $this->vcard->addPhoto(__DIR__ . '/image.jpg', true);
$this->assertEquals($this->vcard, $return);
}
public function testAddPhotoWithRemoteJpgPhoto()
{
$return = $this->vcard->addPhoto(
'https://raw.githubusercontent.com/jeroendesloovere/vcard/master/tests/image.jpg',
true
);
$this->assertEquals($this->vcard, $return);
}
/**
* Test adding remote empty photo
*/
public function testAddPhotoWithRemoteEmptyJpgPhoto()
{
$this->expectException(Exception::class);
$this->expectExceptionMessage('Returned data is not an image.');
$this->vcard->addPhoto(
'https://raw.githubusercontent.com/jeroendesloovere/vcard/master/tests/empty.jpg',
true
);
}
public function testAddPhotoContentWithJpgPhoto()
{
$return = $this->vcard->addPhotoContent(file_get_contents(__DIR__ . '/image.jpg'));
$this->assertEquals($this->vcard, $return);
}
/**
* Test adding empty photo
*/
public function testAddPhotoContentWithEmptyContent()
{
$this->expectException(Exception::class);
$this->expectExceptionMessage('Returned data is not an image.');
$this->vcard->addPhotoContent('');
}
public function testAddLogoWithJpgImage()
{
$return = $this->vcard->addLogo(__DIR__ . '/image.jpg', true);
$this->assertEquals($this->vcard, $return);
}
public function testAddLogoWithJpgImageNoInclude()
{
$return = $this->vcard->addLogo(__DIR__ . '/image.jpg', false);
$this->assertEquals($this->vcard, $return);
}
public function testAddLogoContentWithJpgImage()
{
$return = $this->vcard->addLogoContent(file_get_contents(__DIR__ . '/image.jpg'));
$this->assertEquals($this->vcard, $return);
}
/**
* Test adding empty photo
*/
public function testAddLogoContentWithEmptyContent()
{
$this->expectException(Exception::class);
$this->expectExceptionMessage('Returned data is not an image.');
$this->vcard->addLogoContent('');
}
public function testAddUrl()
{
$this->assertEquals($this->vcard, $this->vcard->addUrl('1'));
$this->assertEquals($this->vcard, $this->vcard->addUrl('2'));
$this->assertCount(2, $this->vcard->getProperties());
}
/**
* Test adding local photo using an empty file
*/
public function testAddPhotoWithEmptyFile()
{
$this->expectException(Exception::class);
$this->expectExceptionMessage('Returned data is not an image.');
$this->vcard->addPhoto(__DIR__ . '/emptyfile', true);
}
/**
* Test adding logo with no value
*/
public function testAddLogoWithNoValue()
{
$this->expectException(Exception::class);
$this->expectExceptionMessage('Returned data is not an image.');
$this->vcard->addLogo(__DIR__ . '/emptyfile', true);
}
/**
* Test adding photo with no photo
*/
public function testAddPhotoWithNoPhoto()
{
$this->expectException(Exception::class);
$this->expectExceptionMessage('Returned data is not an image.');
$this->vcard->addPhoto(__DIR__ . '/wrongfile', true);
}
/**
* Test adding logo with no image
*/
public function testAddLogoWithNoImage()
{
$this->expectException(Exception::class);
$this->expectExceptionMessage('Returned data is not an image.');
$this->vcard->addLogo(__DIR__ . '/wrongfile', true);
}
/**
* Test charset
*/
public function testCharset()
{
$charset = 'ISO-8859-1';
$this->vcard->setCharset($charset);
$this->assertEquals($charset, $this->vcard->getCharset());
}
/**
* Test Email
*
* @dataProvider emailDataProvider $emails
*/
public function testEmail($emails = [])
{
foreach ($emails as $key => $email) {
if (is_string($key)) {
$this->vcard->addEmail($email, $key);
} else {
$this->vcard->addEmail($email);
}
}
foreach ($emails as $key => $email) {
if (is_string($key)) {
$this->assertStringContainsString('EMAIL;INTERNET;' . $key . ':' . $email, $this->vcard->getOutput());
} else {
$this->assertStringContainsString('EMAIL;INTERNET:' . $email, $this->vcard->getOutput());
}
}
}
/**
* Test first name and last name
*/
public function testFirstNameAndLastName()
{
$this->vcard->addName(
$this->lastName,
$this->firstName
);
$this->assertEquals('jeroen-desloovere', $this->vcard->getFilename());
}
/**
* Test full blown name
*/
public function testFullBlownName()
{
$this->vcard->addName(
$this->lastName,
$this->firstName,
$this->additional,
$this->prefix,
$this->suffix
);
$this->assertEquals('mister-jeroen-desloovere-junior', $this->vcard->getFilename());
}
/**
* Test multiple birthdays
*/
public function testMultipleBirthdays()
{
$this->expectException(\Exception::class);
$this->assertEquals($this->vcard, $this->vcard->addBirthday('1'));
$this->expectException(Exception::class);
$this->assertEquals($this->vcard, $this->vcard->addBirthday('2'));
}
/**
* Test multiple categories
*/
public function testMultipleCategories()
{
$this->expectException(\Exception::class);
$this->assertEquals($this->vcard, $this->vcard->addCategories(['1']));
$this->expectException(Exception::class);
$this->assertEquals($this->vcard, $this->vcard->addCategories(['2']));
}
/**
* Test multiple companies
*/
public function testMultipleCompanies()
{
$this->expectException(\Exception::class);
$this->assertEquals($this->vcard, $this->vcard->addCompany('1'));
$this->expectException(Exception::class);
$this->assertEquals($this->vcard, $this->vcard->addCompany('2'));
}
/**
* Test multiple job titles
*/
public function testMultipleJobtitles()
{
$this->expectException(\Exception::class);
$this->assertEquals($this->vcard, $this->vcard->addJobtitle('1'));
$this->expectException(Exception::class);
$this->assertEquals($this->vcard, $this->vcard->addJobtitle('2'));
}
/**
* Test multiple roles
*/
public function testMultipleRoles()
{
$this->expectException(\Exception::class);
$this->assertEquals($this->vcard, $this->vcard->addRole('1'));
$this->expectException(Exception::class);
$this->assertEquals($this->vcard, $this->vcard->addRole('2'));
}
/**
* Test multiple names
*/
public function testMultipleNames()
{
$this->expectException(\Exception::class);
$this->assertEquals($this->vcard, $this->vcard->addName('1'));
$this->expectException(Exception::class);
$this->assertEquals($this->vcard, $this->vcard->addName('2'));
}
/**
* Test multiple notes
*/
public function testMultipleNotes()
{
$this->expectException(\Exception::class);
$this->assertEquals($this->vcard, $this->vcard->addNote('1'));
$this->expectException(Exception::class);
$this->assertEquals($this->vcard, $this->vcard->addNote('2'));
}
/**
* Test special first name and last name
*/
public function testSpecialFirstNameAndLastName()
{
$this->vcard->addName(
$this->lastName2,
$this->firstName2
);
$this->assertEquals('ali-ozsut', $this->vcard->getFilename());
}
/**
* Test special first name and last name
*/
public function testSpecialFirstNameAndLastName2()
{
$this->vcard->addName(
$this->lastName3,
$this->firstName3
);
$this->assertEquals('garcon-jeroen', $this->vcard->getFilename());
}
/**
* Test multiple labels
*/
public function testMultipleLabels()
{
$this->assertSame($this->vcard, $this->vcard->addLabel('My label'));
$this->assertSame($this->vcard, $this->vcard->addLabel('My work label', 'WORK'));
$this->assertSame(2, count($this->vcard->getProperties()));
$this->assertStringContainsString('LABEL;CHARSET=utf-8:My label', $this->vcard->getOutput());
$this->assertStringContainsString('LABEL;WORK;CHARSET=utf-8:My work label', $this->vcard->getOutput());
}
public function testChunkSplitUnicode()
{
$class_handler = new \ReflectionClass('JeroenDesloovere\VCard\VCard');
$method_handler = $class_handler->getMethod('chunk_split_unicode');
$method_handler->setAccessible(true);
$ascii_input="Lorem ipsum dolor sit amet,";
$ascii_output = $method_handler->invokeArgs(new VCard(), [$ascii_input,10,'|']);
$unicode_input='Τη γλώσσα μου έδωσαν ελληνική το σπίτι φτωχικό στις αμμουδιές του Ομήρου.';
$unicode_output = $method_handler->invokeArgs(new VCard(), [$unicode_input,10,'|']);
$this->assertEquals(
"Lorem ipsu|m dolor si|t amet,|",
$ascii_output);
$this->assertEquals(
"Τη γλώσσα |μου έδωσαν| ελληνική |το σπίτι φ|τωχικό στι|ς αμμουδιέ|ς του Ομήρ|ου.|",
$unicode_output);
}
}

View File

View File

View File

@@ -0,0 +1,10 @@
BEGIN:VCARD
VERSION:3.0
REV:2016-05-30T10:36:13Z
N;CHARSET=utf-8:Desloovere;Jeroen;;;
FN;CHARSET=utf-8:Jeroen Desloovere
item1.EMAIL;type=INTERNET:site@example.com
item1.X-ABLabel:$!<Email>!$
item2.URL:http://www.jeroendesloovere.be
item2.X-ABLabel:$!<Home>!$
END:VCARD

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

View File

@@ -0,0 +1 @@
foobar