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

Type declarations to increase phpstan to level 6 #591

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from
Draft
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
4 changes: 2 additions & 2 deletions composer.json
Expand Up @@ -40,7 +40,7 @@
"require-dev" : {
"friendsofphp/php-cs-fixer": "^3.38",
"phpunit/phpunit" : "^9.6",
"phpunit/php-invoker" : "^2.0 || ^3.1",
"phpunit/php-invoker" : "^3.1",
"phpstan/phpstan": "^1.10"
},
"suggest" : {
Expand Down Expand Up @@ -91,7 +91,7 @@
},
"scripts": {
"phpstan": [
"phpstan analyse lib tests --memory-limit 1G"
"phpstan analyse lib tests --memory-limit 2G"
],
"cs-fixer": [
"php-cs-fixer fix"
Expand Down
49 changes: 32 additions & 17 deletions lib/Component.php
Expand Up @@ -2,7 +2,7 @@

namespace Sabre\VObject;

use Sabre\VObject;
use Sabre\VObject\Property\FlatText;
use Sabre\Xml;

/**
Expand All @@ -15,21 +15,16 @@
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*
* @property VObject\Property\FlatText UID
* @property FlatText $UID
*/
class Component extends Node
{
/**
* Component name.
*
* This will contain a string such as VEVENT, VTODO, VCALENDAR, VCARD.
*/
public string $name;

/**
* A list of properties and/or sub-components.
*
* @var array<string, Component|Property>
* ToDo: maybe be more specific array<string, Component<int, mixed>|Property<int, mixed>>
*
* @var array<string, array<int, mixed>>
*/
protected array $children = [];

Expand All @@ -44,7 +39,9 @@ class Component extends Node
* an iCalendar object, this may be something like CALSCALE:GREGORIAN. To
* ensure that this does not happen, set $defaults to false.
*
* @param string|null $name such as VCALENDAR, VEVENT
* @param Document<int, mixed> $root
* @param string|null $name such as VCALENDAR, VEVENT
* @param array<int|string, mixed> $children
*/
public function __construct(Document $root, ?string $name, array $children = [], bool $defaults = true)
{
Expand All @@ -54,7 +51,7 @@ public function __construct(Document $root, ?string $name, array $children = [],
if ($defaults) {
// This is a terribly convoluted way to do this, but this ensures
// that the order of properties as they are specified in both
// defaults and the childrens list, are inserted in the object in a
// defaults and the children's list, are inserted in the object in a
// natural way.
$list = $this->getDefaults();
$nodes = [];
Expand Down Expand Up @@ -97,6 +94,8 @@ public function __construct(Document $root, ?string $name, array $children = [],
* add($name, $value, array $parameters = []) // Adds a new property
* add($name, array $children = []) // Adds a new component
* by name.
*
* @return Node<int, mixed>
*/
public function add(): Node
{
Expand All @@ -114,7 +113,7 @@ public function add(): Node
throw new \InvalidArgumentException('The first argument must either be a \\Sabre\\VObject\\Node or a string');
}

/** @var Component|Property|Parameter $newNode */
/** @var Component<int, mixed>|Property<int, mixed>|Parameter $newNode */
$name = $newNode->name;
if (isset($this->children[$name])) {
$this->children[$name][] = $newNode;
Expand All @@ -133,7 +132,7 @@ public function add(): Node
* pass an instance of a property or component, in which case only that
* exact item will be removed.
*
* @param string|Property|Component $item
* @param string|Property<int, mixed>|Component<int, mixed> $item
*/
public function remove($item): void
{
Expand Down Expand Up @@ -167,6 +166,8 @@ public function remove($item): void
/**
* Returns a flat list of all the properties and components in this
* component.
*
* @return array<int, Component<int, mixed>|Property<int, mixed>>
*/
public function children(): array
{
Expand All @@ -181,6 +182,8 @@ public function children(): array
/**
* This method only returns a list of sub-components. Properties are
* ignored.
*
* @return array<int, Component<int, mixed>>
*/
public function getComponents(): array
{
Expand All @@ -206,6 +209,10 @@ public function getComponents(): array
* search for a property in a specific group, you can select on the entire
* string ("HOME.EMAIL"). If you want to search on a specific property that
* has not been assigned a group, specify ".EMAIL".
*
* ToDo: something like (array<int, mixed> & Component)|(array<int, mixed> & Property)
*
* @return array<int, mixed>
*/
public function select(string $name): array
{
Expand Down Expand Up @@ -271,7 +278,7 @@ public function serialize(): string
*
* @return int
*/
$sortScore = function (int $key, array $array): ?int {
$sortScore = function (int $key, array $array): int {
if ($array[$key] instanceof Component) {
// We want to encode VTIMEZONE first, this is a personal
// preference.
Expand Down Expand Up @@ -322,6 +329,8 @@ function ($a, $b) use ($sortScore, $tmp): int {
/**
* This method returns an array, with the representation as it should be
* encoded in JSON. This is used to create jCard or jCal documents.
*
* @return array{0: string, 1: array<int, mixed>, 2: array<int, mixed>}
*/
#[\ReturnTypeWillChange]
public function jsonSerialize(): array
Expand Down Expand Up @@ -394,6 +403,8 @@ public function xmlSerialize(Xml\Writer $writer): void

/**
* This method should return a list of default property values.
*
* @return array<string, string>
*/
protected function getDefaults(): array
{
Expand All @@ -412,7 +423,7 @@ protected function getDefaults(): array
*
* $event = $calendar->VEVENT;
*
* @return Property|Component
* @return Property<int, mixed>|Component<int, mixed>
*/
public function __get(string $name): ?Node
{
Expand Down Expand Up @@ -507,6 +518,8 @@ public function __clone()
*
* See the VEVENT implementation for getValidationRules for a more complex
* example.
*
* @return array<string, string|int>
*/
public function getValidationRules(): array
{
Expand All @@ -532,6 +545,8 @@ public function getValidationRules(): array
* 1 - The issue was repaired (only happens if REPAIR was turned on).
* 2 - A warning.
* 3 - An error.
*
* @return array<int, array{level: int, message: string, node: object}>
*/
public function validate(int $options = 0): array
{
Expand Down Expand Up @@ -578,7 +593,7 @@ public function validate(int $options = 0): array
}
break;
case '+':
if (!isset($propertyCounters[$propName]) || $propertyCounters[$propName] < 1) {
if (!isset($propertyCounters[$propName])) {
$messages[] = [
'level' => 3,
'message' => $propName.' MUST appear at least once in a '.$this->name.' component',
Expand Down
6 changes: 3 additions & 3 deletions lib/Component/Available.php
Expand Up @@ -14,9 +14,9 @@
* @author Ivan Enderlin
* @license http://sabre.io/license/ Modified BSD License
*
* @property VObject\Property\ICalendar\DateTime DTSTART
* @property VObject\Property\ICalendar\DateTime DTEND
* @property VObject\Property\ICalendar\Duration DURATION
* @property VObject\Property\ICalendar\DateTime $DTSTART
* @property VObject\Property\ICalendar\DateTime $DTEND
* @property VObject\Property\ICalendar\Duration $DURATION
*/
class Available extends VObject\Component
{
Expand Down
10 changes: 5 additions & 5 deletions lib/Component/VAlarm.php
Expand Up @@ -14,11 +14,11 @@
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*
* @property VObject\Property\ICalendar\DateTime DTSTART
* @property VObject\Property\ICalendar\DateTime DTEND
* @property VObject\Property\ICalendar\Duration DURATION
* @property VObject\Property\ICalendar\Duration|VObject\Property\ICalendar\DateTime TRIGGER
* @property VObject\Property\IntegerValue REPEAT
* @property VObject\Property\ICalendar\DateTime $DTSTART
* @property VObject\Property\ICalendar\DateTime $DTEND
* @property VObject\Property\ICalendar\Duration $DURATION
* @property VObject\Property\ICalendar\Duration|VObject\Property\ICalendar\DateTime $TRIGGER
* @property VObject\Property\IntegerValue $REPEAT
*/
class VAlarm extends VObject\Component
{
Expand Down
6 changes: 3 additions & 3 deletions lib/Component/VAvailability.php
Expand Up @@ -14,9 +14,9 @@
* @author Ivan Enderlin
* @license http://sabre.io/license/ Modified BSD License
*
* @property VObject\Property\ICalendar\DateTime DTSTART
* @property VObject\Property\ICalendar\DateTime DTEND
* @property VObject\Property\ICalendar\Duration DURATION
* @property VObject\Property\ICalendar\DateTime $DTSTART
* @property VObject\Property\ICalendar\DateTime $DTEND
* @property VObject\Property\ICalendar\Duration $DURATION
*/
class VAvailability extends VObject\Component
{
Expand Down
8 changes: 4 additions & 4 deletions lib/Component/VCalendar.php
Expand Up @@ -18,10 +18,10 @@
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*
* @property VEvent VEVENT
* @property VJournal VJOURNAL
* @property VObject\Property\Text ORG
* @property VObject\Property\FlatText METHOD
* @property VEvent $VEVENT
* @property VJournal $VJOURNAL
* @property VObject\Property\Text $ORG
* @property VObject\Property\FlatText $METHOD
*/
class VCalendar extends VObject\Document
{
Expand Down
6 changes: 3 additions & 3 deletions lib/Component/VCard.php
Expand Up @@ -15,9 +15,9 @@
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*
* @property VObject\Property\FlatText FN
* @property VObject\Property\Text ORG
* @property VObject\Property\FlatText EMAIL
* @property VObject\Property\FlatText $FN
* @property VObject\Property\Text $ORG
* @property VObject\Property\FlatText $EMAIL
*/
class VCard extends VObject\Document
{
Expand Down
41 changes: 27 additions & 14 deletions lib/Component/VEvent.php
Expand Up @@ -15,17 +15,18 @@
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*
* @property VObject\Property\ICalendar\DateTime DTSTART
* @property VObject\Property\ICalendar\DateTime DTEND
* @property VObject\Property\ICalendar\DateTime DTSTAMP
* @property VObject\Property\ICalendar\Duration DURATION
* @property VObject\Property\ICalendar\Recur RRULE
* @property VObject\Property\ICalendar\DateTime[] EXDATE
* @property VObject\Property\ICalendar\DateTime RDATE
* @property VObject\Property\ICalendar\Recur EXRULE
* @property VObject\Property\ICalendar\DateTime RECURRENCE-ID
* @property VObject\Property\FlatText TRANSP
* @property VObject\Property\FlatText STATUS
* @property VObject\Property\ICalendar\DateTime $DTSTART
* @property VObject\Property\ICalendar\DateTime $DTEND
* @property VObject\Property\ICalendar\DateTime $DTSTAMP
* @property VObject\Property\ICalendar\Duration $DURATION
* @property VObject\Property\ICalendar\Recur $RRULE
* @property VObject\Property\ICalendar\DateTime[] $EXDATE
* @property VObject\Property\ICalendar\DateTime $RDATE
* @property VObject\Property\ICalendar\Recur $EXRULE
* @property VObject\Property\ICalendar\DateTime $RECURRENCE-ID
* @property VObject\Property\ICalendar\CalAddress $ATTENDEE
* @property VObject\Property\FlatText $TRANSP
* @property VObject\Property\FlatText $STATUS
*/
class VEvent extends VObject\Component
{
Expand Down Expand Up @@ -61,18 +62,26 @@ public function isInTimeRange(\DateTimeInterface $start, \DateTimeInterface $end
return $it->getDTStart() < $end && $it->getDTEnd() > $start;
}

$effectiveStart = $this->DTSTART->getDateTime($start->getTimezone());
/**
* @var \Sabre\VObject\Property\ICalendar\DateTime<int, DateTimeInterface> $dateTimeStart
*/
$dateTimeStart = $this->DTSTART;
$effectiveStart = $dateTimeStart->getDateTime($start->getTimezone());
if (isset($this->DTEND)) {
/**
* @var \Sabre\VObject\Property\ICalendar\DateTime<int, DateTimeInterface> $dateTimeEnd
*/
$dateTimeEnd = $this->DTEND;
// The DTEND property is considered non-inclusive. So for a 3-day
// event in july, dtstart and dtend would have to be July 1st and
// July 4th respectively.
//
// See:
// http://tools.ietf.org/html/rfc5545#page-54
$effectiveEnd = $this->DTEND->getDateTime($end->getTimezone());
$effectiveEnd = $dateTimeEnd->getDateTime($end->getTimezone());
} elseif (isset($this->DURATION)) {
$effectiveEnd = $effectiveStart->add(VObject\DateTimeParser::parseDuration($this->DURATION));
} elseif (!$this->DTSTART->hasTime()) {
} elseif (!$dateTimeStart->hasTime()) {
$effectiveEnd = $effectiveStart->modify('+1 day');
} else {
$effectiveEnd = $effectiveStart;
Expand All @@ -85,6 +94,8 @@ public function isInTimeRange(\DateTimeInterface $start, \DateTimeInterface $end

/**
* This method should return a list of default property values.
*
* @return array<string, string>
*/
protected function getDefaults(): array
{
Expand All @@ -106,6 +117,8 @@ protected function getDefaults(): array
* * + - Must appear at least once.
* * * - Can appear any number of times.
* * ? - May appear, but not more than once.
*
* @return array<string, string|int>
*/
public function getValidationRules(): array
{
Expand Down
2 changes: 1 addition & 1 deletion lib/Component/VFreeBusy.php
Expand Up @@ -14,7 +14,7 @@
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*
* @property VObject\Property\ICalendar\Period FREEBUSY
* @property VObject\Property\ICalendar\Period $FREEBUSY
*/
class VFreeBusy extends VObject\Component
{
Expand Down
2 changes: 1 addition & 1 deletion lib/Component/VJournal.php
Expand Up @@ -13,7 +13,7 @@
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*
* @property VObject\Property\ICalendar\DateTime DTSTART
* @property VObject\Property\ICalendar\DateTime $DTSTART
*/
class VJournal extends VObject\Component
{
Expand Down
2 changes: 1 addition & 1 deletion lib/Component/VTimeZone.php
Expand Up @@ -15,7 +15,7 @@
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*
* @property VObject\Property\FlatText TZID
* @property VObject\Property\FlatText $TZID
*/
class VTimeZone extends VObject\Component
{
Expand Down
24 changes: 12 additions & 12 deletions lib/Component/VTodo.php
Expand Up @@ -13,18 +13,18 @@
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*
* @property VObject\Property\ICalendar\DateTime DTSTART
* @property VObject\Property\ICalendar\DateTime DTEND
* @property VObject\Property\ICalendar\DateTime DTSTAMP
* @property VObject\Property\ICalendar\Duration DURATION
* @property VObject\Property\ICalendar\Recur RRULE
* @property VObject\Property\ICalendar\DateTime EXDATE
* @property VObject\Property\ICalendar\DateTime RDATE
* @property VObject\Property\ICalendar\Recur EXRULE
* @property VObject\Property\ICalendar\DateTime {'RECURRENCE-ID'}
* @property VObject\Property\ICalendar\DateTime DUE
* @property VObject\Property\ICalendar\DateTime COMPLETED
* @property VObject\Property\ICalendar\DateTime CREATED
* @property VObject\Property\ICalendar\DateTime $DTSTART
* @property VObject\Property\ICalendar\DateTime $DTEND
* @property VObject\Property\ICalendar\DateTime $DTSTAMP
* @property VObject\Property\ICalendar\Duration $DURATION
* @property VObject\Property\ICalendar\Recur $RRULE
* @property VObject\Property\ICalendar\DateTime $EXDATE
* @property VObject\Property\ICalendar\DateTime $RDATE
* @property VObject\Property\ICalendar\Recur $EXRULE
* @property VObject\Property\ICalendar\DateTime $RECURRENCE-ID
* @property VObject\Property\ICalendar\DateTime $DUE
* @property VObject\Property\ICalendar\DateTime $COMPLETED
* @property VObject\Property\ICalendar\DateTime $CREATED
*/
class VTodo extends VObject\Component
{
Expand Down