Skip to content

Commit

Permalink
Document how to add custom properties to the event component (#150)
Browse files Browse the repository at this point in the history
  • Loading branch information
markuspoerschke authored Feb 16, 2020
1 parent 216da28 commit ed1afe1
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 5 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# eluceo — iCal 2
# 📅 eluceo — iCal 2

[![Build Status](https://travis-ci.org/markuspoerschke/iCal.svg?branch=2.x)](https://travis-ci.org/markuspoerschke/iCal)
[![codecov](https://codecov.io/gh/markuspoerschke/iCal/branch/2.x/graph/badge.svg)](https://codecov.io/gh/markuspoerschke/iCal)
Expand Down
3 changes: 3 additions & 0 deletions couscous.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ menu:
url: /components/calendar.html
- section: Advanced
items:
advanced/custom-properties:
text: Custom Properties
url: /advanced/custom-properties.html
advanced/maturity-matrix:
text: Maturity Matrix
url: /advanced/maturity-matrix.html
Expand Down
102 changes: 102 additions & 0 deletions docs/advanced/custom-properties.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
currentMenu: advanced/custom-properties
title: Custom Properties
---

# Custom Properties

The domain entities in this packages are equipped with the commonly needed properties.
In some cases these properties do not fully cover every use case.
In the following, a way how to add custom properties to the event entity and in result to the generated iCal file is described.

In this tutorial, we will add a custom property called `X-CUSTOM` to the iCal file, which can look like this:

```text
X-CUSTOM: foo bar baz!
```

## 1. Create a custom event domain entity

First we need to create a custom event entity to store the additional value.
This can be done by extending from `\Eluceo\iCal\Domain\Entity\Event`.
The following example shows a class with an added property named `$myCustomProperty`.
It is up to you, how to implement this class.
In this example, the property is read-only.

```php
namespace Documentation;

use Eluceo\iCal\Domain\Entity\Event;

class CustomEvent extends Event
{
private string $myCustomProperty = 'foo bar baz!';

public function getMyCustomProperty(): string
{
return $this->myCustomProperty;
}
}
```

## 2. Create a custom event factory

The presentation components are created by factories.
It is possible to extend these factories to add custom properties to the iCal file.
In the following example, the factory reads the value `$myCustomProperty` and adds its value as property `X-CUSTOM`.

```php
namespace Documentation;

use Eluceo\iCal\Domain\Entity\Event;
use Eluceo\iCal\Presentation\Component;
use Eluceo\iCal\Presentation\Component\Property;
use Eluceo\iCal\Presentation\Component\Property\Value\TextValue;
use Eluceo\iCal\Presentation\Factory\EventFactory;

class CustomEventFactory extends EventFactory
{
public function createComponent(Event $event): Component
{
$component = parent::createComponent($event);

if ($event instanceof CustomEvent) {
$component = $component->withProperty(
Property::create(
'X-CUSTOM',
TextValue::fromString($event->getMyCustomProperty())
)
);
}

return $component;
}
}
```

## 3. Let's plug it all together

A new custom event can now be created.

```php
$event = CustomEvent::create();
$event->setSummary('This is a test event');
$calendar = Calendar::create([$event]);
```

To see the new property, an instance of class `CustomEventFactory` must be passed to the standard calendar factory:

```php
$calendarComponentFactory = new CalendarFactory(new CustomEventFactory());
$calendarComponent = $calendarComponentFactory->createCalendar($calendar);
```

After that, the iCal file can be rendered like normal.

```php
header('Content-Type: text/calendar; charset=utf-8');
header('Content-Disposition: attachment; filename="cal.ics"');
echo $calendarComponent;
```

For a full sample, please have a look at [`example2.php`](https://github.com/markuspoerschke/iCal/blob/master/examples/example2.php).
8 changes: 4 additions & 4 deletions examples/example1.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

require_once __DIR__ . '/../vendor/autoload.php';

// 1. Create Event domain entity
// 1. Create Event domain entity.
$event = Event::create();
$event
->setSummary('Christmas Eve')
Expand All @@ -36,16 +36,16 @@
)
);

// 2. Create Calendar domain entity
// 2. Create Calendar domain entity.
$calendar = Calendar::create([$event]);

// 3. Transform domain entity into an iCalendar component
$componentFactory = new CalendarFactory();
$calendarComponent = $componentFactory->createCalendar($calendar);

// 4. Set HTTP headers
// 4. Set HTTP headers.
header('Content-Type: text/calendar; charset=utf-8');
header('Content-Disposition: attachment; filename="cal.ics"');

// 5. Output
// 5. Output.
echo $calendarComponent;
68 changes: 68 additions & 0 deletions examples/example2.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

/*
* This file is part of the eluceo/iCal package.
*
* (c) 2020 Markus Poerschke <[email protected]>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Example;

use Eluceo\iCal\Domain\Entity\Calendar;
use Eluceo\iCal\Domain\Entity\Event;
use Eluceo\iCal\Presentation\Component;
use Eluceo\iCal\Presentation\Component\Property;
use Eluceo\iCal\Presentation\Component\Property\Value\TextValue;
use Eluceo\iCal\Presentation\Factory\CalendarFactory;
use Eluceo\iCal\Presentation\Factory\EventFactory;

require_once __DIR__ . '/../vendor/autoload.php';

// 1. Define a custom event domain entity.
class CustomEvent extends Event
{
private string $myCustomProperty = 'foo bar baz!';

public function getMyCustomProperty(): string
{
return $this->myCustomProperty;
}
}

// 2. Create a custom event factory,
// that can add the additional property to the presentation component.
class CustomEventFactory extends EventFactory
{
public function createComponent(Event $event): Component
{
$component = parent::createComponent($event);

if ($event instanceof CustomEvent) {
$component = $component->withProperty(
Property::create(
'X-CUSTOM',
TextValue::fromString($event->getMyCustomProperty())
)
);
}

return $component;
}
}

// 3. Create events and calendar objects as normal.
$event = CustomEvent::create();
$event->setSummary('This is a test event');
$calendar = Calendar::create([$event]);

// 4. Pass your custom event factory to the calendar factory via the constructor call.
$calendarComponentFactory = new CalendarFactory(new CustomEventFactory());
$calendarComponent = $calendarComponentFactory->createCalendar($calendar);

// 5. The output can happen as usual.
header('Content-Type: text/calendar; charset=utf-8');
header('Content-Disposition: attachment; filename="cal.ics"');
echo $calendarComponent;
8 changes: 8 additions & 0 deletions src/Presentation/Component.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ public static function create(string $componentName, array $properties = []): se
return new static($componentName, $properties);
}

public function withProperty(Property $property): self
{
$new = clone $this;
$new->addProperty($property);

return $new;
}

public function __toString(): string
{
return implode(
Expand Down
24 changes: 24 additions & 0 deletions tests/Unit/Presentation/ComponentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,28 @@ public function testComponentWithPropertiesToString()
(string) Component::create('VEVENT', $properties)
);
}

public function testWithProperties()
{
$component = Component::create('VEVENT', [Property::create('TEST', TextValue::fromString('value'))]);
$newComponent = $component->withProperty(Property::create('TEST2', TextValue::fromString('value2')));

self::assertNotSame($component, $newComponent);

$expectedOutputFromComponent = implode(Component::LINE_SEPARATOR, [
'BEGIN:VEVENT',
'TEST:value',
'END:VEVENT',
]);

$expectedOutputFromNewComponent = implode(Component::LINE_SEPARATOR, [
'BEGIN:VEVENT',
'TEST:value',
'TEST2:value2',
'END:VEVENT',
]);

self::assertSame($expectedOutputFromComponent, (string) $component);
self::assertSame($expectedOutputFromNewComponent, (string) $newComponent);
}
}

0 comments on commit ed1afe1

Please sign in to comment.