Skip to content

Commit

Permalink
Merge pull request #1 from jeroendesloovere/2.0.0-dev
Browse files Browse the repository at this point in the history
2.0.0 dev update
  • Loading branch information
melroy89 authored Mar 4, 2019
2 parents fd104fc + 6869766 commit 4f385ff
Show file tree
Hide file tree
Showing 15 changed files with 522 additions and 36 deletions.
36 changes: 33 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,40 @@ Documentation about vCard 4.0:
* [vCard 4.0 specification: RFC6350](https://tools.ietf.org/html/rfc6350)
* [vCard 4.0 versus vCard 3.0](https://devguide.calconnect.org/vCard/vcard-4/)

## Installation

```bash
composer require jeroendesloovere/vcard:dev-2.0.0-dev
```
> This will install the 2.0 WIP development version of vcard with [Composer](https://getcomposer.org)

## Examples

Since this is a WIP, we refer to the [test class](tests/VCardTest.php) to view multiple examples.

### Basic example

```php
use JeroenDesloovere\VCard\VCard;
use JeroenDesloovere\VCard\Property\Name;
use JeroenDesloovere\VCard\Formatter\Formatter;
use JeroenDesloovere\VCard\Formatter\VcfFormatter;

$lastname = "Berg";
$firstname = "Melroy";
$additional = "van den";
$prefix = "Mr.";
$suffix = "";

$vcard = new VCard();
$vcard->add(new Name($lastname, $firstname, $additional, $prefix, $suffix));

$formatter = new Formatter(new VcfFormatter(), 'vcard-export');
$formatter->addVCard($vcard);
$formatter->download();
```

## Properties

### Identification Properties:
Expand All @@ -30,8 +60,8 @@ Since this is a WIP, we refer to the [test class](tests/VCardTest.php) to view m
* [x] [ADDRESS](./src/Property/Address.php) - The address of the object represented in structured parts

### Communications Properties:
* [x] [TEL](./src/Property/Telephone.php) - The telephone number as a tel URI
* [x] [EMAIL](./src/Property/Email.php) - The email address as a mailto URI
* [x] [TEL](./src/Property/Telephone.php) - The telephone number(s) as a tel URI
* [x] [EMAIL](./src/Property/Email.php) - The email address(es) as a mailto URI
* [ ] IMPP - The IMPP instant messaging contact information
* [ ] LANG - The language of the object

Expand All @@ -57,7 +87,7 @@ Since this is a WIP, we refer to the [test class](tests/VCardTest.php) to view m
* [ ] UID - A unique identifier for the object
* [ ] CLIENTPIDMAP - Not required
* [ ] URL - Any URL related to the object
* [X] [VERSION](./src/Property/Parameter/Version.php) - Not required (namespace will capture this)
* [X] [VERSION](./src/Property/Parameter/Version.php) - Is mandatory for 4.0

### Security Properties:
* [ ] KEY - The security key of the object
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"require-dev": {
"phpunit/phpunit": "^6.5",
"squizlabs/php_codesniffer": "^3.2",
"mikey179/vfsStream": "^1.6"
"mikey179/vfsstream": "^1.6"
},
"autoload": {
"psr-4": { "JeroenDesloovere\\VCard\\": "src/" }
Expand Down
2 changes: 1 addition & 1 deletion src/Formatter/Property/NameFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public function __construct(Name $name)
public function getVcfString(): string
{
return $this->name::getNode() . ':' . $this->escape(implode(';', array(
$this->name->getLastName(),
$this->name->getFirstName(),
$this->name->getAdditional(),
$this->name->getLastName(),
$this->name->getPrefix(),
$this->name->getSuffix()
)));
Expand Down
12 changes: 12 additions & 0 deletions src/Formatter/Property/Parameter/ValueFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace JeroenDesloovere\VCard\Formatter\Property\Parameter;

use JeroenDesloovere\VCard\Formatter\Property\SimpleNodeFormatter;

final class ValueFormatter extends SimpleNodeFormatter
{

}
4 changes: 3 additions & 1 deletion src/Formatter/Property/TelephoneFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public function __construct(Telephone $telephone)

public function getVcfString(): string
{
return $this->telephone->getNode() . ';tel:' . $this->telephone->getValue();
return $this->telephone->getNode() .
';TYPE=' . $this->telephone->getType()->__toString() .
';VALUE=' . $this->telephone->getValue() . ':tel:' . $this->telephone->getTelephoneNumber();
}
}
17 changes: 17 additions & 0 deletions src/Parser/Property/Parameter/ValueParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace JeroenDesloovere\VCard\Parser\Property\Parameter;

use JeroenDesloovere\VCard\Parser\Property\NodeParserInterface;
use JeroenDesloovere\VCard\Property\NodeInterface;
use JeroenDesloovere\VCard\Property\Parameter\Value;

final class ValueParser implements NodeParserInterface
{
public function parseVcfString(string $value, array $parameters = []): NodeInterface
{
return new Value($value);
}
}
14 changes: 13 additions & 1 deletion src/Parser/Property/TelephoneParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,23 @@

use JeroenDesloovere\VCard\Property\NodeInterface;
use JeroenDesloovere\VCard\Property\Telephone;
use JeroenDesloovere\VCard\Property\Parameter\Type;
use JeroenDesloovere\VCard\Property\Parameter\Value;

final class TelephoneParser extends PropertyParser implements NodeParserInterface
{
public function parseVcfString(string $value, array $parameters = []): NodeInterface
{
return new Telephone(str_replace('tel:', '', $value));
$telephone = new Telephone(str_replace('tel:', '', $value));

if (array_key_exists(Type::getNode(), $parameters)) {
$telephone->setType($parameters[Type::getNode()]);
}

if (array_key_exists(Value::getNode(), $parameters)) {
$telephone->setValue($parameters[Value::getNode()]);
}

return $telephone;
}
}
33 changes: 30 additions & 3 deletions src/Parser/VcfParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use JeroenDesloovere\VCard\Parser\Property\NodeParserInterface;
use JeroenDesloovere\VCard\Property\NodeInterface;
use JeroenDesloovere\VCard\VCard;
use JeroenDesloovere\VCard\Property\Parameter\Version;
use JeroenDesloovere\VCard\Property\Parameter\Kind;

final class VcfParser implements ParserInterface
{
Expand Down Expand Up @@ -67,16 +69,41 @@ private function parseParameters(?string $parameters): array

private function parseVCard(string $content): VCard
{
$vCard = new VCard();
$vCard = $this->createVcardObjectWithProperties($content);

$lines = explode("\n", $content);
foreach ($lines as $line) {
$this->parseVCardLine($line, $vCard);
$this->parseVCardContentLine($line, $vCard);
}

return $vCard;
}

private function parseVCardLine(string $line, VCard &$vCard): void
private function createVcardObjectWithProperties(string $content): VCard
{
$vcardProperties = array(
Kind::getNode() => null,
Version::getNode() => null);

$lines = explode("\n", $content);
foreach ($lines as $line) {
/**
* @var string $node
* @var string $value
*/
@list($node, $value) = explode(':', $line, 2);
if (array_key_exists($node, $this->parsers)) {
// Only check on either Kind or Version node
if ($node == Kind::getNode() || $node == Version::getNode()) {
$vcardProperties[$node] = $this->parsers[$node]->parseVcfString($value);
}
}
}

return new VCard($vcardProperties[Kind::getNode()], $vcardProperties[Version::getNode()]);
}

private function parseVCardContentLine(string $line, VCard &$vCard): void
{
// Strip grouping information. We don't use the group names. We
// simply use a list for entries that have multiple values.
Expand Down
21 changes: 12 additions & 9 deletions src/Property/Parameter/Kind.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@
*/
final class Kind implements PropertyParameterInterface, SimpleNodeInterface
{
// Group - To represent groups of vCard objects
protected const GROUP = 'Group';
// group - To represent groups of vCard objects
protected const GROUP = 'group';

// Individual - To represent people
protected const INDIVIDUAL = 'Individual';
// individual - To represent people
protected const INDIVIDUAL = 'individual';

// Location - To represent location objects
protected const LOCATION = 'Location';
// location - To represent location objects
protected const LOCATION = 'location';

// Organization - To represent organisations
protected const ORGANIZATION = 'Organization';
// org - To represent organisations
protected const ORGANIZATION = 'org';

public const POSSIBLE_VALUES = [
self::GROUP,
Expand All @@ -43,8 +43,11 @@ final class Kind implements PropertyParameterInterface, SimpleNodeInterface
*/
public function __construct(string $value)
{
$value = strtolower($value);
if (!in_array($value, self::POSSIBLE_VALUES, true)) {
throw PropertyParameterException::forWrongValue($value, self::POSSIBLE_VALUES);
// If value is absent or not understood 'individual' must be used,
// as stated in RFC 6350
$this->value = self::INDIVIDUAL;
}

$this->value = $value;
Expand Down
138 changes: 138 additions & 0 deletions src/Property/Parameter/Value.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<?php

declare(strict_types=1);

namespace JeroenDesloovere\VCard\Property\Parameter;

use JeroenDesloovere\VCard\Exception\PropertyParameterException;
use JeroenDesloovere\VCard\Formatter\Property\NodeFormatterInterface;
use JeroenDesloovere\VCard\Formatter\Property\Parameter\ValueFormatter;
use JeroenDesloovere\VCard\Parser\Property\NodeParserInterface;
use JeroenDesloovere\VCard\Parser\Property\Parameter\ValueParser;
use JeroenDesloovere\VCard\Property\SimpleNodeInterface;

final class Value implements PropertyParameterInterface, SimpleNodeInterface
{
protected const TEXT = 'text';
protected const URI = 'uri';
protected const DATE = 'date';
protected const TIME = 'time';
protected const DATE_TIME = 'date-time';
protected const DATE_AND_OR_TIME = 'date-and-or-time';
protected const TIMESTAMP = 'timestamp';
protected const BOOLEAN = 'boolean';
protected const INTEGER = 'integer';
protected const FLOAT = 'float';
protected const UTC_OFFSET = 'utc-offset';
protected const LANGUAGE_TAG = 'language-tag';

public const POSSIBLE_VALUES = [
self::TEXT,
self::URI,
self::DATE,
self::TIME,
self::DATE_TIME,
self::DATE_AND_OR_TIME,
self::TIMESTAMP,
self::BOOLEAN,
self::INTEGER,
self::FLOAT,
self::UTC_OFFSET,
self::LANGUAGE_TAG
];

private $value;

/**
* @param string $value
* @throws PropertyParameterException
*/
public function __construct(string $value)
{
if (!in_array($value, self::POSSIBLE_VALUES, true)) {
throw PropertyParameterException::forWrongValue($value, self::POSSIBLE_VALUES);
}

$this->value = $value;
}

public function __toString(): string
{
return $this->value;
}

public function getFormatter(): NodeFormatterInterface
{
return new ValueFormatter($this);
}

public static function getNode(): string
{
return 'VALUE';
}

public static function getParser(): NodeParserInterface
{
return new ValueParser();
}

public static function text(): self
{
return new self(self::TEXT);
}

public static function uri(): self
{
return new self(self::URI);
}

public static function date(): self
{
return new self(self::DATE);
}

public static function time(): self
{
return new self(self::TIME);
}

public static function dateTime(): self
{
return new self(self::DATE_TIME);
}

public static function dateAndOrTime(): self
{
return new self(self::DATE_AND_OR_TIME);
}

public static function timestamp(): self
{
return new self(self::TIMESTAMP);
}

public static function boolean(): self
{
return new self(self::BOOLEAN);
}

public static function integer(): self
{
return new self(self::INTEGER);
}

public static function float(): self
{
return new self(self::FLOAT);
}

public static function utcOffset(): self
{
return new self(self::UTC_OFFSET);
}

public static function languageTag(): self
{
return new self(self::LANGUAGE_TAG);
}
}
Loading

0 comments on commit 4f385ff

Please sign in to comment.