From f0e946b5f82ffb9aa475e7b36b7cc714b5f643f9 Mon Sep 17 00:00:00 2001 From: Alies Lapatsin Date: Fri, 26 Jan 2024 14:19:23 +0530 Subject: [PATCH] Support file output by ICS --- .gitattributes | 1 + composer.json | 8 +++--- src/Generators/Ics.php | 21 +++++++++++++--- src/Link.php | 7 +++--- tests/Generators/IcsGeneratorTest.php | 25 +++++++++++-------- ...erates_base64_encoded_link_for_html__1.txt | 1 + 6 files changed, 42 insertions(+), 21 deletions(-) create mode 100644 tests/Generators/__snapshots__/IcsGeneratorTest__it_generates_base64_encoded_link_for_html__1.txt diff --git a/.gitattributes b/.gitattributes index adfaba5..313045a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -19,3 +19,4 @@ tests/**/__snapshots__/IcsGeneratorTest* text eol=crlf # PHPUnit .phpunit.cache +.phpunit.cache/ diff --git a/composer.json b/composer.json index c7390c5..c6eb937 100644 --- a/composer.json +++ b/composer.json @@ -19,10 +19,10 @@ "php": "^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.14", - "phpunit/phpunit": "^9.6 || ^10.0", - "spatie/phpunit-snapshot-assertions": "^4.2 || ^5.0", - "vimeo/psalm": "^5.6" + "friendsofphp/php-cs-fixer": "^3.48", + "phpunit/phpunit": "^10.1", + "spatie/phpunit-snapshot-assertions": "^5.1", + "vimeo/psalm": "^5.20" }, "autoload": { "psr-4": { diff --git a/src/Generators/Ics.php b/src/Generators/Ics.php index b738974..a6a8b2e 100644 --- a/src/Generators/Ics.php +++ b/src/Generators/Ics.php @@ -18,12 +18,17 @@ class Ics implements Generator /** @var array */ protected $options = []; + /** @var array{format?: string} */ + protected $presentationOptions = []; + /** - * @param array $options + * @param array $options Optional ICS properties and components + * @param array{format?: string} $presentationOptions */ - public function __construct(array $options = []) + public function __construct(array $options = [], array $presentationOptions = []) { $this->options = $options; + $this->presentationOptions = $presentationOptions; } /** {@inheritDoc} */ @@ -64,7 +69,12 @@ public function generate(Link $link): string $url[] = 'END:VEVENT'; $url[] = 'END:VCALENDAR'; - return $this->buildLink($url); + $format = $this->presentationOptions['format'] ?? 'html'; + + return match ($format) { + 'file' => $this->buildFile($url), + default => $this->buildLink($url), + }; } protected function buildLink(array $propertiesAndComponents): string @@ -72,6 +82,11 @@ protected function buildLink(array $propertiesAndComponents): string return 'data:text/calendar;charset=utf8;base64,'.base64_encode(implode("\r\n", $propertiesAndComponents)); } + protected function buildFile(array $propertiesAndComponents): string + { + return implode("\r\n", $propertiesAndComponents); + } + /** @see https://tools.ietf.org/html/rfc5545.html#section-3.3.11 */ protected function escapeString(string $field): string { diff --git a/src/Link.php b/src/Link.php index 56ab3c3..60e9dee 100644 --- a/src/Link.php +++ b/src/Link.php @@ -115,12 +115,13 @@ public function google(): string } /** - * @param array $options + * @param array $options ICS specific properties and components + * @param array{format?: string} $presentationOptions * @return string */ - public function ics(array $options = []): string + public function ics(array $options = [], array $presentationOptions = []): string { - return $this->formatWith(new Ics($options)); + return $this->formatWith(new Ics($options, $presentationOptions)); } public function yahoo(): string diff --git a/tests/Generators/IcsGeneratorTest.php b/tests/Generators/IcsGeneratorTest.php index 9c3b481..8e1a82f 100644 --- a/tests/Generators/IcsGeneratorTest.php +++ b/tests/Generators/IcsGeneratorTest.php @@ -14,15 +14,10 @@ class IcsGeneratorTest extends TestCase * @param array $options @see \Spatie\CalendarLinks\Generators\Ics::__construct * @return \Spatie\CalendarLinks\Generator */ - protected function generator(array $options = []): Generator + protected function generator(array $options = [], array $presentationOptions = []): Generator { - // extend base class just to make output more readable and simplify reviewing of the snapshot diff - return new class($options) extends Ics { - protected function buildLink(array $propertiesAndComponents): string - { - return implode("\r\n", $propertiesAndComponents); - } - }; + $presentationOptions['format'] ??= 'file'; + return new Ics($options, $presentationOptions); } protected function linkMethodName(): string @@ -34,7 +29,7 @@ protected function linkMethodName(): string public function it_can_generate_an_ics_link_with_custom_uid(): void { $this->assertMatchesSnapshot( - $this->generator(['UID' => 'random-uid'])->generate($this->createShortEventLink()) + $this->generator(['UID' => 'random-uid', ['format' => 'file']])->generate($this->createShortEventLink()) ); } @@ -42,7 +37,7 @@ public function it_can_generate_an_ics_link_with_custom_uid(): void public function it_has_a_product_id(): void { $this->assertMatchesSnapshot( - $this->generator(['PRODID' => 'Spatie calendar-links'])->generate($this->createShortEventLink()) + $this->generator(['PRODID' => 'Spatie calendar-links'], ['format' => 'file'])->generate($this->createShortEventLink()) ); } @@ -50,7 +45,15 @@ public function it_has_a_product_id(): void public function it_has_a_product_dtstamp(): void { $this->assertMatchesSnapshot( - $this->generator(['DTSTAMP' => '20180201T090000Z'])->generate($this->createShortEventLink()) + $this->generator(['DTSTAMP' => '20180201T090000Z'], ['format' => 'file'])->generate($this->createShortEventLink()) + ); + } + + /** @test */ + public function it_generates_base64_encoded_link_for_html(): void + { + $this->assertMatchesSnapshot( + $this->generator([], ['format' => 'html'])->generate($this->createShortEventLink()) ); } } diff --git a/tests/Generators/__snapshots__/IcsGeneratorTest__it_generates_base64_encoded_link_for_html__1.txt b/tests/Generators/__snapshots__/IcsGeneratorTest__it_generates_base64_encoded_link_for_html__1.txt new file mode 100644 index 0000000..4639dd1 --- /dev/null +++ b/tests/Generators/__snapshots__/IcsGeneratorTest__it_generates_base64_encoded_link_for_html__1.txt @@ -0,0 +1 @@ +data:text/calendar;charset=utf8;base64,QkVHSU46VkNBTEVOREFSDQpWRVJTSU9OOjIuMA0KUFJPRElEOlNwYXRpZSBjYWxlbmRhci1saW5rcw0KQkVHSU46VkVWRU5UDQpVSUQ6OTRhYjc1YWRkODRhNjdjMDE5ZWFlNTc1Mzk2NTgwMzYNClNVTU1BUlk6QmlydGhkYXkNCkRUU1RBTVA6MjAxODAyMDFUMDkwMDAwWg0KRFRTVEFSVDoyMDE4MDIwMVQwOTAwMDBaDQpEVEVORDoyMDE4MDIwMVQxODAwMDBaDQpERVNDUklQVElPTjpXaXRoIGJhbGxvb25zXCwgY2xvd25zIGFuZCBzdHVmZlxuQnJpbmcgYSBkb2dcLCBicmluZyBhIGZyb2cNCkxPQ0FUSU9OOlBhcnR5IExhbmUgMUFcLCAxMzM3IEZ1bnRvd24NCkVORDpWRVZFTlQNCkVORDpWQ0FMRU5EQVI= \ No newline at end of file