Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.x] Types; no magic, final, strict_types; #190

Merged
merged 21 commits into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/psalm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ on:
push:
paths:
- '**.php'
- 'psalm.xml'
- 'psalm.yml'
- 'psalm*'

jobs:
psalm:
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, json, libxml, mbstring, pcre, reflection, spl, xml, xmlwriter
coverage: none
ini-values: assert.exception=1, zend.assertions=1

Expand Down
3 changes: 1 addition & 2 deletions .php-cs-fixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@
__DIR__ . '/tests',
])
->name('*.php')
->notName('*.blade.php')
->ignoreDotFiles(true)
->ignoreVCS(true);

return (new PhpCsFixer\Config())
->setRules([
'@PSR2' => true,
'@PSR12' => true,
'array_syntax' => ['syntax' => 'short'],
'ordered_imports' => ['sort_algorithm' => 'alpha'],
'no_unused_imports' => true,
Expand Down
56 changes: 1 addition & 55 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
@@ -1,63 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="5.22.1@e9dad66e11274315dac27e08349c628c7d6a1a43">
<file src="src/Generators/BaseOutlook.php">
<MissingDocblockType>
<code><![CDATA[protected $dateFormat = 'Y-m-d';]]></code>
<code><![CDATA[protected $dateTimeFormat = 'Y-m-d\TH:i:s\Z';]]></code>
</MissingDocblockType>
<MissingPropertyType>
<code><![CDATA[$dateFormat]]></code>
<code><![CDATA[$dateTimeFormat]]></code>
</MissingPropertyType>
<UndefinedInterfaceMethod>
<code><![CDATA[setTimezone]]></code>
<code><![CDATA[setTimezone]]></code>
</UndefinedInterfaceMethod>
</file>
<file src="src/Generators/Google.php">
<MissingDocblockType>
<code><![CDATA[protected $dateFormat = 'Ymd';]]></code>
</MissingDocblockType>
<MissingPropertyType>
<code><![CDATA[$dateFormat]]></code>
</MissingPropertyType>
</file>
<file src="src/Generators/Ics.php">
<MissingDocblockType>
<code><![CDATA[protected $dateFormat = 'Ymd';]]></code>
</MissingDocblockType>
<MissingPropertyType>
<code><![CDATA[$dateFormat]]></code>
</MissingPropertyType>
</file>
<file src="src/Generators/Yahoo.php">
<MissingDocblockType>
<code><![CDATA[protected $dateFormat = 'Ymd';]]></code>
</MissingDocblockType>
<MissingPropertyType>
<code><![CDATA[$dateFormat]]></code>
</MissingPropertyType>
<UndefinedInterfaceMethod>
<code><![CDATA[setTimezone]]></code>
<code><![CDATA[setTimezone]]></code>
</UndefinedInterfaceMethod>
</file>
<file src="src/Link.php">
<MissingParamType>
<code><![CDATA[$property]]></code>
</MissingParamType>
<PropertyTypeCoercion>
<code><![CDATA[clone $from]]></code>
<code><![CDATA[clone $to]]></code>
</PropertyTypeCoercion>
<UndefinedInterfaceMethod>
<code><![CDATA[modify]]></code>
<code><![CDATA[setTimezone]]></code>
</UndefinedInterfaceMethod>
<UnsafeInstantiation/>
</file>
<file src="tests/Generators/IcsGeneratorTest.php">
<InvalidArgument>
<code><![CDATA[$presentationOptions]]></code>
</InvalidArgument>
</file>
</files>
10 changes: 2 additions & 8 deletions src/Exceptions/InvalidLink.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Spatie\CalendarLinks\Exceptions;

use DateTimeInterface;
Expand All @@ -9,14 +11,6 @@ class InvalidLink extends InvalidArgumentException
{
private const DATETIME_FORMAT = 'Y-m-d H:i:s';

/** @deprecated Will be removed in 2.0, please use {@see InvalidLink::negativeDateRange} instead */
public static function invalidDateRange(DateTimeInterface $to, DateTimeInterface $from): self
{
trigger_error(sprintf('Method %s::%s is deprecated, please use %s::negativeDateRange method instead', self::class, __METHOD__, self::class), \E_USER_DEPRECATED);

return new self("TO time (`{$to->format(self::DATETIME_FORMAT)}`) must be greater than FROM time (`{$from->format(self::DATETIME_FORMAT)}`)");
}

public static function negativeDateRange(DateTimeInterface $from, DateTimeInterface $to): self
{
return new self("TO time (`{$to->format(self::DATETIME_FORMAT)}`) must be greater than FROM time (`{$from->format(self::DATETIME_FORMAT)}`)");
Expand Down
7 changes: 4 additions & 3 deletions src/Generator.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<?php

declare(strict_types=1);

namespace Spatie\CalendarLinks;

interface Generator
{
/**
* Generate an URL to add event to calendar.
* @param \Spatie\CalendarLinks\Link $link
* @return string
* Generate a URL to add event to calendar.
* @return non-empty-string
*/
public function generate(Link $link): string;
}
33 changes: 19 additions & 14 deletions src/Generators/BaseOutlook.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php declare(strict_types=1);
<?php

declare(strict_types=1);

namespace Spatie\CalendarLinks\Generators;

Expand All @@ -7,41 +9,44 @@
use Spatie\CalendarLinks\Link;

/**
* @see https://github.com/InteractionDesignFoundation/add-event-to-calendar-docs/blob/master/services/outlook-web.md
* @see https://github.com/InteractionDesignFoundation/add-event-to-calendar-docs/blob/main/services/outlook-web.md
* @psalm-type OutlookUrlParameters = array<string, scalar|null>
*/
abstract class BaseOutlook implements Generator
{
/** @var string {@see https://www.php.net/manual/en/function.date.php} */
protected $dateFormat = 'Y-m-d';
/** @see https://www.php.net/manual/en/function.date.php */
private const DATE_FORMAT = 'Y-m-d';

/** @var string {@see https://www.php.net/manual/en/function.date.php} */
protected $dateTimeFormat = 'Y-m-d\TH:i:s\Z';
/** @see https://www.php.net/manual/en/function.date.php */
private const DATETIME_FORMAT = 'Y-m-d\TH:i:s\Z';

/** @psalm-var OutlookUrlParameters */
protected array $urlParameters = [];

/**
* Get base URL for links.
* @return non-empty-string
*/
abstract protected function baseUrl(): string;

/** @psalm-param OutlookUrlParameters $urlParameters */
public function __construct(array $urlParameters = [])
{
$this->urlParameters = $urlParameters;
}

/** Get base URL for links. */
abstract public function baseUrl(): string;

/** {@inheritDoc} */
/** @inheritDoc */
public function generate(Link $link): string
{
$url = $this->baseUrl();

if ($link->allDay) {
$url .= '&startdt='.$link->from->format($this->dateFormat);
$url .= '&enddt='.$link->to->format($this->dateFormat);
$url .= '&startdt='.$link->from->format(self::DATE_FORMAT);
$url .= '&enddt='.$link->to->format(self::DATE_FORMAT);
$url .= '&allday=true';
} else {
$url .= '&startdt='.(clone $link->from)->setTimezone(new DateTimeZone('UTC'))->format($this->dateTimeFormat);
$url .= '&enddt='.(clone $link->to)->setTimezone(new DateTimeZone('UTC'))->format($this->dateTimeFormat);
$url .= '&startdt='.(clone $link->from)->setTimezone(new DateTimeZone('UTC'))->format(self::DATETIME_FORMAT);
$url .= '&enddt='.(clone $link->to)->setTimezone(new DateTimeZone('UTC'))->format(self::DATETIME_FORMAT);
}

$url .= '&subject='.$this->sanitizeString($link->title);
Expand Down
22 changes: 14 additions & 8 deletions src/Generators/Google.php
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
<?php

declare(strict_types=1);

namespace Spatie\CalendarLinks\Generators;

use Spatie\CalendarLinks\Generator;
use Spatie\CalendarLinks\Link;

/**
* @see https://github.com/InteractionDesignFoundation/add-event-to-calendar-docs/blob/master/services/google.md
* @see https://github.com/InteractionDesignFoundation/add-event-to-calendar-docs/blob/main/services/google.md
* @psalm-type GoogleUrlParameters = array<string, scalar|null>
*/
class Google implements Generator
{
/** @var string {@see https://www.php.net/manual/en/function.date.php} */
protected $dateFormat = 'Ymd';
/** @var string */
protected $dateTimeFormat = 'Ymd\THis';
/** @see https://www.php.net/manual/en/function.date.php */
private const DATE_FORMAT = 'Ymd';

/** @see https://www.php.net/manual/en/function.date.php */
private const DATETIME_FORMAT = 'Ymd\THis';

/** @psalm-var GoogleUrlParameters */
protected array $urlParameters = [];
Expand All @@ -25,12 +28,15 @@ public function __construct(array $urlParameters = [])
$this->urlParameters = $urlParameters;
}

/** {@inheritDoc} */
/** @var non-empty-string */
protected const BASE_URL = 'https://calendar.google.com/calendar/render?action=TEMPLATE';

/** @inheritDoc */
public function generate(Link $link): string
{
$url = 'https://calendar.google.com/calendar/render?action=TEMPLATE';
$url = self::BASE_URL;

$dateTimeFormat = $link->allDay ? $this->dateFormat : $this->dateTimeFormat;
$dateTimeFormat = $link->allDay ? self::DATE_FORMAT : self::DATETIME_FORMAT;
$url .= '&dates='.$link->from->format($dateTimeFormat).'/'.$link->to->format($dateTimeFormat);
$url .= '&ctz=' . $link->from->getTimezone()->getName();
$url .= '&text='.urlencode($link->title);
Expand Down
30 changes: 20 additions & 10 deletions src/Generators/Ics.php
Original file line number Diff line number Diff line change
@@ -1,48 +1,50 @@
<?php

declare(strict_types=1);

namespace Spatie\CalendarLinks\Generators;

use Spatie\CalendarLinks\Generator;
use Spatie\CalendarLinks\Link;

/**
* @see https://icalendar.org/RFC-Specifications/iCalendar-RFC-5545/
* @psalm-type IcsOptions = array{UID?: string, URL?: string, REMINDER?: array{DESCRIPTION?: string, TIME?: \DateTimeInterface}}
* @psalm-type IcsOptions = array{UID?: string, URL?: string, PRODID?: string, REMINDER?: array{DESCRIPTION?: string, TIME?: \DateTimeInterface}}
* @psalm-type IcsPresentationOptions = array{format?: self::FORMAT_*}
*/
class Ics implements Generator
{
public const FORMAT_HTML = 'html';
public const FORMAT_FILE = 'file';

/** @var string {@see https://www.php.net/manual/en/function.date.php} */
protected $dateFormat = 'Ymd';
/** @see https://www.php.net/manual/en/function.date.php */
protected string $dateFormat = 'Ymd';

/** @var string */
protected $dateTimeFormat = 'Ymd\THis\Z';
protected string $dateTimeFormat = 'Ymd\THis\Z';

/** @psalm-var IcsOptions */
protected $options = [];
protected array $options = [];

/** @var array{format?: self::FORMAT_*} */
/** @psalm-var IcsPresentationOptions */
protected $presentationOptions = [];

/**
* @param IcsOptions $options Optional ICS properties and components
* @param array{format?: self::FORMAT_*} $presentationOptions
* @param IcsPresentationOptions $presentationOptions
*/
public function __construct(array $options = [], array $presentationOptions = [])
{
$this->options = $options;
$this->presentationOptions = $presentationOptions;
}

/** {@inheritDoc} */
/** @inheritDoc */
public function generate(Link $link): string
{
$url = [
'BEGIN:VCALENDAR',
'VERSION:2.0', // @see https://datatracker.ietf.org/doc/html/rfc5545#section-3.7.4
'PRODID:Spatie calendar-links', // @see https://datatracker.ietf.org/doc/html/rfc5545#section-3.7.3
'PRODID:'.($this->options['PRODID'] ?? 'Spatie calendar-links'), // @see https://datatracker.ietf.org/doc/html/rfc5545#section-3.7.3
'BEGIN:VEVENT',
'UID:'.($this->options['UID'] ?? $this->generateEventUid($link)),
'SUMMARY:'.$this->escapeString($link->title),
Expand Down Expand Up @@ -86,11 +88,19 @@ public function generate(Link $link): string
};
}

/**
* @param non-empty-list<string> $propertiesAndComponents
* @return non-empty-string
*/
protected function buildLink(array $propertiesAndComponents): string
{
return 'data:text/calendar;charset=utf8;base64,'.base64_encode(implode("\r\n", $propertiesAndComponents));
}

/**
* @param non-empty-list<string> $propertiesAndComponents
* @return non-empty-string
*/
protected function buildFile(array $propertiesAndComponents): string
{
return implode("\r\n", $propertiesAndComponents);
Expand Down
9 changes: 6 additions & 3 deletions src/Generators/WebOffice.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
<?php

declare(strict_types=1);

namespace Spatie\CalendarLinks\Generators;

class WebOffice extends BaseOutlook
final class WebOffice extends BaseOutlook
{
protected const BASE_URL = 'https://outlook.office.com/calendar/deeplink/compose?path=/calendar/action/compose&rru=addevent';
/** @var non-empty-string */
private const BASE_URL = 'https://outlook.office.com/calendar/deeplink/compose?path=/calendar/action/compose&rru=addevent';

/** @inheritDoc */
public function baseUrl(): string
protected function baseUrl(): string
{
return static::BASE_URL;
}
Expand Down
9 changes: 6 additions & 3 deletions src/Generators/WebOutlook.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
<?php

declare(strict_types=1);

namespace Spatie\CalendarLinks\Generators;

class WebOutlook extends BaseOutlook
final class WebOutlook extends BaseOutlook
{
protected const BASE_URL = 'https://outlook.live.com/calendar/action/compose?path=/calendar/action/compose&rru=addevent';
/** @var non-empty-string */
private const BASE_URL = 'https://outlook.live.com/calendar/action/compose?path=/calendar/action/compose&rru=addevent';

/** @inheritDoc */
public function baseUrl(): string
protected function baseUrl(): string
{
return static::BASE_URL;
}
Expand Down