diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08c0b0a2d..8ffa41595 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,25 +12,28 @@ jobs: strategy: fail-fast: false matrix: - php-versions: ['8.0', '8.1', '8.2', '8.3', '8.4'] + php-versions: ['8.3', '8.4'] coverage: ['pcov'] code-style: ['no'] code-analysis: ['no'] + rector-check: ['no'] include: - - php-versions: '7.4' + - php-versions: '8.2' coverage: 'pcov' code-style: 'yes' code-analysis: 'yes' + rector-check: 'no' - php-versions: '8.5' coverage: 'pcov' code-style: 'no' code-analysis: 'yes' + rector-check: 'yes' steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php + uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2.37.2 with: php-version: ${{ matrix.php-versions }} extensions: mbstring, dom, fileinfo, mysql, redis, opcache @@ -42,7 +45,7 @@ jobs: run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache composer dependencies - uses: actions/cache@v5 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ${{ steps.composer-cache.outputs.dir }} # Use composer.json for key, if composer.lock is not committed. @@ -61,9 +64,13 @@ jobs: if: matrix.code-analysis == 'yes' run: composer phpstan + - name: Code Refactoring (rector) + if: matrix.rector-check == 'yes' + run: composer rector-check + - name: Test with phpunit run: vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-clover clover.xml - name: Code Coverage - uses: codecov/codecov-action@v6 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 if: matrix.coverage != 'none' diff --git a/.gitignore b/.gitignore index d6e0a1d04..2b1573b7f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ vendor/ composer.lock tests/cov/ tests/temp +tests/.phpunit.cache tests/.phpunit.result.cache # Development stuff diff --git a/CHANGELOG.md b/CHANGELOG.md index e61db1eac..6ce1ab77b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -182,6 +182,23 @@ ChangeLog * #3 Add daily occurrences to nextMonth and NextYear * #4 Enhance fast forward speed if no count value has been given +5.0.0 (2026-07-07) +------------------ +* #767 Drop PHP 7.4 8.0 8.1 and support PHP 8.2 and up (@phil-davis) +* #769 fix: minor code fixes (@phil-davis) +* #586 PHP types (@tcitworld @phil-davis) + +This major release v5 declares function parameter and return types across the +codebase. Users will need to be careful to call functions/methods with the +correct types. + +Support for PHP below 8.2 has been dropped. +This release supports PHP 8.2 and up. + +4.6.1 (2026-07-07) +------------------ +* #776 fix: preserve UTC 'Z' indicator in Period JSON serialization (@bastien-roucaries @guimard @phil-davis) + 4.6.0 (2026-05-31) ------------------ * #718 feat(VCard): add getByTypes method (@JimKnoxx) diff --git a/composer.json b/composer.json index f602f5200..e65762e17 100644 --- a/composer.json +++ b/composer.json @@ -32,16 +32,20 @@ "homepage" : "http://sabre.io/vobject/", "license" : "BSD-3-Clause", "require" : { - "php" : "^7.4 || ^8.0", + "php" : "^8.2", "ext-mbstring" : "*", "ext-json" : "*", "sabre/xml" : "^3.0 || ^4.0" }, "require-dev" : { - "friendsofphp/php-cs-fixer": "^3.94", - "phpunit/phpunit" : "^9.6", - "phpunit/php-invoker" : "^2.0 || ^3.1", - "phpstan/phpstan": "^2.1" + "friendsofphp/php-cs-fixer": "^3.95", + "phpstan/phpstan": "^2.2", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpstan/extension-installer": "^1.4", + "phpunit/phpunit": "^11.5", + "phpunit/php-invoker" : "^5.0", + "rector/rector": "^2.6" }, "suggest" : { "hoa/bench" : "If you would like to run the benchmark scripts" @@ -96,6 +100,12 @@ "cs-fixer": [ "PHP_CS_FIXER_IGNORE_ENV=true php-cs-fixer fix" ], + "rector-check": [ + "rector process --dry-run" + ], + "rector-fix": [ + "rector process" + ], "phpunit": [ "phpunit --configuration tests/phpunit.xml" ], @@ -104,5 +114,13 @@ "composer cs-fixer", "composer phpunit" ] + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": true + }, + "platform": { + "php": "8.2" + } } } diff --git a/lib/BirthdayCalendarGenerator.php b/lib/BirthdayCalendarGenerator.php index 49793b0d4..11ae8be14 100644 --- a/lib/BirthdayCalendarGenerator.php +++ b/lib/BirthdayCalendarGenerator.php @@ -95,7 +95,7 @@ public function getResult(): VCalendar // We've seen clients (ez-vcard) putting "BDAY:" properties // without a value into vCards. If we come across those, we'll // skip them. - if (empty($object->BDAY->getValue())) { + if ('' === $object->BDAY->getValue()) { continue; } @@ -116,7 +116,7 @@ public function getResult(): VCalendar // Skip if we can't parse the BDAY value. try { $dateParts = DateTimeParser::parseVCardDateTime($object->BDAY->getValue()); - } catch (InvalidDataException $e) { + } catch (InvalidDataException) { continue; } diff --git a/lib/Cli.php b/lib/Cli.php index 69af6f470..386cf2c73 100644 --- a/lib/Cli.php +++ b/lib/Cli.php @@ -92,7 +92,7 @@ public function main(array $argv): int // @codeCoverageIgnoreEnd try { - list($options, $positional) = $this->parseArguments($argv); + [$options, $positional] = $this->parseArguments($argv); if (isset($options['q'])) { $this->quiet = true; @@ -110,27 +110,10 @@ public function main(array $argv): int return 0; case 'format': - switch ($value) { - // jcard/jcal documents - case 'jcard': - case 'jcal': - // specific document versions - case 'vcard21': - case 'vcard30': - case 'vcard40': - case 'icalendar20': - // specific formats - case 'json': - case 'mimedir': - // icalendar/vcard - case 'icalendar': - case 'vcard': - $this->format = $value; - break; - - default: - throw new \InvalidArgumentException('Unknown format: '.$value); - } + $this->format = match ($value) { + 'jcard', 'jcal', 'vcard21', 'vcard30', 'vcard40', 'icalendar20', 'json', 'mimedir', 'icalendar', 'vcard' => $value, + default => throw new \InvalidArgumentException('Unknown format: '.$value), + }; break; case 'pretty': $this->pretty = true; @@ -139,28 +122,11 @@ public function main(array $argv): int $this->forgiving = true; break; case 'inputformat': - switch ($value) { - // json formats - case 'jcard': - case 'jcal': - case 'json': - $this->inputFormat = 'json'; - break; - - // mimedir formats - case 'mimedir': - case 'icalendar': - case 'vcard': - case 'vcard21': - case 'vcard30': - case 'vcard40': - case 'icalendar20': - $this->inputFormat = 'mimedir'; - break; - - default: - throw new \InvalidArgumentException('Unknown format: '.$value); - } + $this->inputFormat = match ($value) { + 'jcard', 'jcal', 'json' => 'json', + 'mimedir', 'icalendar', 'vcard', 'vcard21', 'vcard30', 'vcard40', 'icalendar20' => 'mimedir', + default => throw new \InvalidArgumentException('Unknown format: '.$value), + }; break; default: throw new \InvalidArgumentException('Unknown option: '.$name); @@ -181,7 +147,7 @@ public function main(array $argv): int throw new \InvalidArgumentException('Too many arguments'); } - if (!in_array($positional[0], ['validate', 'repair', 'convert', 'color'])) { + if (!in_array($positional[0], ['validate', 'repair', 'convert', 'color'], true)) { throw new \InvalidArgumentException('Unknown command: '.$positional[0]); } } catch (\InvalidArgumentException $e) { @@ -201,14 +167,14 @@ public function main(array $argv): int } if (null === $this->inputFormat) { - if ('.json' === substr($this->inputPath, -5)) { + if (str_ends_with($this->inputPath, '.json')) { $this->inputFormat = 'json'; } else { $this->inputFormat = 'mimedir'; } } if (null === $this->format) { - if ('.json' === substr($this->outputPath, -5)) { + if (str_ends_with($this->outputPath, '.json')) { $this->format = 'json'; } else { $this->format = 'mimedir'; @@ -219,12 +185,13 @@ public function main(array $argv): int try { while ($input = $this->readInput()) { + // @phpstan-ignore method.dynamicName $returnCode = $this->$command($input); if (0 !== $returnCode) { $realCode = $returnCode; } } - } catch (EofException $e) { + } catch (EofException) { // end of file } catch (\Exception $e) { $this->log('Error: '.$e->getMessage(), 'red'); @@ -408,7 +375,7 @@ protected function convert(Component $vObj): int } fwrite($this->stdout, json_encode($vObj->jsonSerialize(), $jsonOptions)); } else { - fwrite($this->stdout, $vObj->serialize()); + fwrite($this->stdout, (string) $vObj->serialize()); } return 0; @@ -538,7 +505,7 @@ protected function serializeProperty(Property $property): void $this->cWrite('red', ':'); if ($property instanceof Property\Binary) { - $this->cWrite('default', 'embedded binary stripped. ('.strlen($property->getValue()).' bytes)'); + $this->cWrite('default', 'embedded binary stripped. ('.strlen((string) $property->getValue()).' bytes)'); } else { $parts = $property->getParts(); $first1 = true; @@ -593,17 +560,17 @@ protected function parseArguments(array $argv): array $v = $argv[$ii]; - if ('--' === substr($v, 0, 2)) { + if (str_starts_with((string) $v, '--')) { // This is a long-form option. - $optionName = substr($v, 2); + $optionName = substr((string) $v, 2); $optionValue = true; if (strpos($optionName, '=')) { - list($optionName, $optionValue) = explode('=', $optionName); + [$optionName, $optionValue] = explode('=', $optionName); } $options[$optionName] = $optionValue; - } elseif ('-' === substr($v, 0, 1) && strlen($v) > 1) { + } elseif (str_starts_with((string) $v, '-') && strlen((string) $v) > 1) { // This is a short-form option. - foreach (str_split(substr($v, 1)) as $option) { + foreach (str_split(substr((string) $v, 1)) as $option) { $options[$option] = true; } } else { @@ -628,6 +595,9 @@ protected function readInput(): ?Document if (!$this->parser) { if ('-' !== $this->inputPath) { $this->stdin = fopen($this->inputPath, 'r'); + if (false === $this->stdin) { + throw new InvalidDataException('Cannot open "'.$this->inputPath); + } } if ('mimedir' === $this->inputFormat) { diff --git a/lib/Component.php b/lib/Component.php index 2c933ffda..5370b83d2 100644 --- a/lib/Component.php +++ b/lib/Component.php @@ -140,7 +140,7 @@ public function remove($item): void // If there's no dot in the name, it's an exact property name, // we can just wipe out all those properties. // - if (false === strpos($item, '.')) { + if (!str_contains($item, '.')) { unset($this->children[strtoupper($item)]); return; @@ -210,8 +210,8 @@ public function select(string $name): array { $group = null; $name = strtoupper($name); - if (false !== strpos($name, '.')) { - list($group, $name) = explode('.', $name, 2); + if (str_contains($name, '.')) { + [$group, $name] = explode('.', $name, 2); } if ('' === $name) { $name = null; @@ -228,9 +228,7 @@ public function select(string $name): array // more. return array_filter( $result, - function ($child) use ($group) { - return $child instanceof Property && (null !== $child->group ? strtoupper($child->group) : '') === $group; - } + fn ($child) => $child instanceof Property && (null !== $child->group ? strtoupper($child->group) : '') === $group ); } @@ -368,7 +366,7 @@ public function xmlSerialize(Xml\Writer $writer): void $writer->startElement(strtolower($this->name)); - if (!empty($properties)) { + if ([] !== $properties) { $writer->startElement('properties'); foreach ($properties as $property) { @@ -378,7 +376,7 @@ public function xmlSerialize(Xml\Writer $writer): void $writer->endElement(); } - if (!empty($components)) { + if ([] !== $components) { $writer->startElement('components'); foreach ($components as $component) { @@ -541,7 +539,7 @@ public function validate(int $options = 0): array $messages = []; foreach ($this->children() as $child) { - $name = strtoupper($child->name); + $name = strtoupper((string) $child->name); if (!isset($propertyCounters[$name])) { $propertyCounters[$name] = 1; } else { diff --git a/lib/Component/VAlarm.php b/lib/Component/VAlarm.php index 0cb6ab1de..47474dfbf 100644 --- a/lib/Component/VAlarm.php +++ b/lib/Component/VAlarm.php @@ -32,9 +32,9 @@ class VAlarm extends VObject\Component public function getEffectiveTriggerTime(): \DateTimeImmutable { $trigger = $this->TRIGGER; - if (!isset($trigger['VALUE']) || ($trigger['VALUE'] && 'DURATION' === strtoupper($trigger['VALUE']))) { + if (!isset($trigger['VALUE']) || ($trigger['VALUE'] && 'DURATION' === strtoupper((string) $trigger['VALUE']))) { $triggerDuration = VObject\DateTimeParser::parseDuration($this->TRIGGER); - $related = (isset($trigger['RELATED']) && 'END' == strtoupper($trigger['RELATED'])) ? 'END' : 'START'; + $related = (isset($trigger['RELATED']) && 'END' === strtoupper($trigger['RELATED'])) ? 'END' : 'START'; /** @var VEvent|VTodo $parentComponent */ $parentComponent = $this->parent; diff --git a/lib/Component/VAvailability.php b/lib/Component/VAvailability.php index ff6e9bd65..a4db47642 100644 --- a/lib/Component/VAvailability.php +++ b/lib/Component/VAvailability.php @@ -33,7 +33,7 @@ class VAvailability extends VObject\Component */ public function isInTimeRange(\DateTimeInterface $start, \DateTimeInterface $end): bool { - list($effectiveStart, $effectiveEnd) = $this->getEffectiveStartEnd(); + [$effectiveStart, $effectiveEnd] = $this->getEffectiveStartEnd(); return (is_null($effectiveStart) || $start < $effectiveEnd) diff --git a/lib/Component/VCalendar.php b/lib/Component/VCalendar.php index 5163c042a..46928a62d 100644 --- a/lib/Component/VCalendar.php +++ b/lib/Component/VCalendar.php @@ -327,7 +327,7 @@ public function expand(\DateTimeInterface $start, \DateTimeInterface $end, ?\Dat foreach ($recurringEvents as $events) { try { $it = new EventIterator($events, null, $timeZone); - } catch (NoInstancesException $e) { + } catch (NoInstancesException) { // This event is recurring, but it doesn't have a single // instance. We are skipping this event from the output // entirely. @@ -424,7 +424,7 @@ public function validate(int $options = 0): array if ($child instanceof Component) { ++$componentsFound; - if (!in_array($child->name, ['VEVENT', 'VTODO', 'VJOURNAL'])) { + if (!in_array($child->name, ['VEVENT', 'VTODO', 'VJOURNAL'], true)) { continue; } $componentTypes[] = $child->name; diff --git a/lib/Component/VCard.php b/lib/Component/VCard.php index 0dafb674b..bbb852cc2 100644 --- a/lib/Component/VCard.php +++ b/lib/Component/VCard.php @@ -423,10 +423,10 @@ public function getByType(string $propertyName, string $type) */ public function getByTypes(string $propertyName, array $types) { - $types = array_map('strtolower', $types); + $types = array_map(strtolower(...), $types); foreach ($this->select($propertyName) as $field) { if (isset($field['TYPE'])) { - $parts = array_map('strtolower', $field['TYPE']->getParts()); + $parts = array_map(strtolower(...), $field['TYPE']->getParts()); if (!array_diff($types, $parts) && !array_diff($parts, $types)) { return $field; @@ -481,9 +481,7 @@ public function xmlSerialize(Xml\Writer $writer): void foreach ($this->children() as $property) { $group = $property->group; - if (!isset($propertiesByGroup[$group])) { - $propertiesByGroup[$group] = []; - } + $propertiesByGroup[$group] ??= []; $propertiesByGroup[$group][] = $property; } @@ -491,9 +489,9 @@ public function xmlSerialize(Xml\Writer $writer): void $writer->startElement(strtolower($this->name)); foreach ($propertiesByGroup as $group => $properties) { - if (!empty($group)) { + if ('' !== $group) { $writer->startElement('group'); - $writer->writeAttribute('name', strtolower($group)); + $writer->writeAttribute('name', strtolower((string) $group)); } foreach ($properties as $property) { @@ -513,7 +511,7 @@ public function xmlSerialize(Xml\Writer $writer): void } } - if (!empty($group)) { + if ('' !== $group) { $writer->endElement(); } } @@ -529,7 +527,7 @@ public function getClassNameForPropertyName(string $propertyName): string $className = parent::getClassNameForPropertyName($propertyName); // In vCard 4, BINARY no longer exists, and we need URI instead. - if (VObject\Property\Binary::class == $className && self::VCARD40 === $this->getDocumentType()) { + if (VObject\Property\Binary::class === $className && self::VCARD40 === $this->getDocumentType()) { return VObject\Property\Uri::class; } diff --git a/lib/Component/VEvent.php b/lib/Component/VEvent.php index 6ca196d66..c13081884 100644 --- a/lib/Component/VEvent.php +++ b/lib/Component/VEvent.php @@ -44,7 +44,7 @@ public function isInTimeRange(\DateTimeInterface $start, \DateTimeInterface $end if ($this->RRULE || $this->RDATE) { try { $it = new EventIterator($this, null, $start->getTimezone()); - } catch (NoInstancesException $e) { + } catch (NoInstancesException) { // If we've caught this exception, there are no instances // for the event that fall into the specified time-range. return false; diff --git a/lib/Component/VFreeBusy.php b/lib/Component/VFreeBusy.php index a9891c92c..623652ff9 100644 --- a/lib/Component/VFreeBusy.php +++ b/lib/Component/VFreeBusy.php @@ -41,7 +41,7 @@ public function isFree(\DateTimeInterface $start, \DatetimeInterface $end): bool // Every period is formatted as [start]/[end]. The start is an // absolute UTC time, the end may be an absolute UTC time, or // duration (relative) value. - list($busyStart, $busyEnd) = explode('/', $period); + [$busyStart, $busyEnd] = explode('/', $period); $busyStart = VObject\DateTimeParser::parse($busyStart); $busyEnd = VObject\DateTimeParser::parse($busyEnd); diff --git a/lib/DateTimeParser.php b/lib/DateTimeParser.php index 712a40faf..9b0c55b2e 100644 --- a/lib/DateTimeParser.php +++ b/lib/DateTimeParser.php @@ -42,7 +42,7 @@ public static function parseDateTime(string $dt, ?\DateTimeZone $tz = null): \Da try { $date = new \DateTimeImmutable($matches[1].'-'.$matches[2].'-'.$matches[3].' '.$matches[4].':'.$matches[5].':'.$matches[6], $tz); - } catch (\Exception $e) { + } catch (\Exception) { throw new InvalidDataException('The supplied iCalendar datetime value is incorrect: '.$dt); } @@ -63,13 +63,11 @@ public static function parseDate(string $date, ?\DateTimeZone $tz = null): \Date throw new InvalidDataException('The supplied iCalendar date value is incorrect: '.$date); } - if (is_null($tz)) { - $tz = new \DateTimeZone('UTC'); - } + $tz ??= new \DateTimeZone('UTC'); try { $date = new \DateTimeImmutable($matches[1].'-'.$matches[2].'-'.$matches[3], $tz); - } catch (\Exception $e) { + } catch (\Exception) { throw new InvalidDataException('The supplied iCalendar date value is incorrect: '.$date); } @@ -329,7 +327,7 @@ public static function parseVCardDateTime(string $date): array $result = []; foreach ($parts as $part) { - if (empty($matches[$part])) { + if (!array_key_exists($part, $matches) || '' === $matches[$part]) { $result[$part] = null; } elseif ('-' === $matches[$part] || '--' === $matches[$part]) { $result[$part] = null; @@ -424,7 +422,7 @@ public static function parseVCardTime(string $date): array $result = []; foreach ($parts as $part) { - if (empty($matches[$part])) { + if (!array_key_exists($part, $matches) || '' === $matches[$part]) { $result[$part] = null; } elseif ('-' === $matches[$part]) { $result[$part] = null; @@ -541,7 +539,7 @@ public static function parseVCardDateAndOrTime(string $date): array $parts['year0'] = &$parts['year']; foreach ($parts as $part => &$value) { - if (!empty($matches[$part])) { + if (array_key_exists($part, $matches) && '' !== $matches[$part]) { $value = $matches[$part]; } } diff --git a/lib/Document.php b/lib/Document.php index dd2faf5bf..d07e2af93 100644 --- a/lib/Document.php +++ b/lib/Document.php @@ -118,10 +118,10 @@ public function getDocumentType(): int public function create(string $name) { if (isset(static::$componentMap[strtoupper($name)])) { - return call_user_func_array([$this, 'createComponent'], func_get_args()); + return $this->createComponent(...func_get_args()); } - return call_user_func_array([$this, 'createProperty'], func_get_args()); + return $this->createProperty(...func_get_args()); } /** @@ -146,9 +146,7 @@ public function createComponent(string $name, ?array $children = null, bool $def if (isset(static::$componentMap[$name])) { $class = static::$componentMap[$name]; } - if (is_null($children)) { - $children = []; - } + $children ??= []; return new $class($this, $name, $children, $defaults); } @@ -205,9 +203,7 @@ public function createProperty(string $name, $value = null, ?array $parameters = } } - if (is_null($parameters)) { - $parameters = []; - } + $parameters ??= []; return new $class($this, $name, $value, $parameters, $group, $lineIndex, $lineString); } diff --git a/lib/FreeBusyData.php b/lib/FreeBusyData.php index 405a5886d..6cdf2b937 100644 --- a/lib/FreeBusyData.php +++ b/lib/FreeBusyData.php @@ -11,25 +11,19 @@ */ class FreeBusyData { - /** - * Start timestamp. - */ - protected int $start; - - /** - * End timestamp. - */ - protected int $end; - /** * A list of free-busy times. */ protected array $data; - public function __construct(int $start, int $end) + public function __construct(/** + * Start timestamp. + */ + protected int $start, /** + * End timestamp. + */ + protected int $end) { - $this->start = $start; - $this->end = $end; $this->data = []; $this->data[] = [ diff --git a/lib/FreeBusyGenerator.php b/lib/FreeBusyGenerator.php index 424826034..9eec5c8d7 100644 --- a/lib/FreeBusyGenerator.php +++ b/lib/FreeBusyGenerator.php @@ -79,9 +79,7 @@ public function __construct(?\DateTimeInterface $start = null, ?\DateTimeInterfa if ($objects) { $this->setObjects($objects); } - if (is_null($timeZone)) { - $timeZone = new \DateTimeZone('UTC'); - } + $timeZone ??= new \DateTimeZone('UTC'); $this->setTimeZone($timeZone); } @@ -217,7 +215,7 @@ function ($a, $b) { $new = []; foreach ($old as $vavail) { - list($compStart, $compEnd) = $vavail->getEffectiveStartEnd(); + [$compStart, $compEnd] = $vavail->getEffectiveStartEnd(); // We don't care about date-times that are earlier or later than the // start and end of the freebusy report, so this gets normalized @@ -237,7 +235,7 @@ function ($a, $b) { // Going through our existing list of components to see if there's // a higher priority component that already fully covers this one. foreach ($new as $higherVavail) { - list($higherStart, $higherEnd) = $higherVavail->getEffectiveStartEnd(); + [$higherStart, $higherEnd] = $higherVavail->getEffectiveStartEnd(); if ( (is_null($higherStart) || $higherStart < $compStart) && (is_null($higherEnd) || $higherEnd > $compEnd) @@ -259,7 +257,7 @@ function ($a, $b) { // priority components to override the lower ones. foreach (array_reverse($new) as $vavail) { $busyType = isset($vavail->BUSYTYPE) ? strtoupper($vavail->BUSYTYPE) : 'BUSY-UNAVAILABLE'; - list($vavailStart, $vavailEnd) = $vavail->getEffectiveStartEnd(); + [$vavailStart, $vavailEnd] = $vavail->getEffectiveStartEnd(); // Making the component size no larger than the requested free-busy // report range. @@ -281,7 +279,7 @@ function ($a, $b) { // Looping over the AVAILABLE components. if (isset($vavail->AVAILABLE)) { foreach ($vavail->AVAILABLE as $available) { - list($availStart, $availEnd) = $available->getEffectiveStartEnd(); + [$availStart, $availEnd] = $available->getEffectiveStartEnd(); $fbData->add( $availStart->getTimeStamp(), $availEnd->getTimeStamp(), @@ -362,7 +360,7 @@ protected function calculateBusy(FreeBusyData $fbData, array $objects): void if ($component->RRULE) { try { $iterator = new EventIterator($object, (string) $component->UID, $this->timeZone); - } catch (NoInstancesException $e) { + } catch (NoInstancesException) { // This event is recurring, but it doesn't have a single // instance. We are skipping this event from the output // entirely. @@ -437,12 +435,12 @@ protected function calculateBusy(FreeBusyData $fbData, array $objects): void continue; } - $values = explode(',', $freebusy); + $values = explode(',', (string) $freebusy); foreach ($values as $value) { - list($startTime, $endTime) = explode('/', $value); + [$startTime, $endTime] = explode('/', $value); $startTime = DateTimeParser::parseDateTime($startTime); - if ('P' === substr($endTime, 0, 1) || '-P' === substr($endTime, 0, 2)) { + if (str_starts_with($endTime, 'P') || str_starts_with($endTime, '-P')) { $duration = DateTimeParser::parseDuration($endTime); $endTime = clone $startTime; $endTime = $endTime->add($duration); @@ -507,7 +505,7 @@ protected function generateFreeBusyCalendar(FreeBusyData $fbData): VCalendar $vfreebusy->add($dtstamp); foreach ($fbData->getData() as $busyTime) { - $busyType = strtoupper($busyTime['type']); + $busyType = strtoupper((string) $busyTime['type']); // Ignoring all the FREE parts, because those are already assumed. if ('FREE' === $busyType) { diff --git a/lib/ITip/Broker.php b/lib/ITip/Broker.php index 9bcdcc2a2..19de8b16b 100644 --- a/lib/ITip/Broker.php +++ b/lib/ITip/Broker.php @@ -228,7 +228,7 @@ public function parseEvent($calendar, $userHref, $oldCalendar = null): array $eventInfo = $oldEventInfo; - if (in_array($eventInfo['organizer'], $userHref)) { + if (in_array($eventInfo['organizer'], $userHref, true)) { // This is an organizer deleting the event. $eventInfo['attendees'] = []; // Increasing the sequence, but only if the organizer deleted @@ -237,7 +237,7 @@ public function parseEvent($calendar, $userHref, $oldCalendar = null): array } else { // This is an attendee deleting the event. foreach ($eventInfo['attendees'] as $key => $attendee) { - if (in_array($attendee['href'], $userHref)) { + if (in_array($attendee['href'], $userHref, true)) { $eventInfo['attendees'][$key]['instances'] = ['master' => ['id' => 'master', 'partstat' => 'DECLINED'], ]; } @@ -247,13 +247,13 @@ public function parseEvent($calendar, $userHref, $oldCalendar = null): array } // Check if the user is the organizer - if (in_array($eventInfo['organizer'], $userHref)) { + if (in_array($eventInfo['organizer'], $userHref, true)) { return $this->parseEventForOrganizer($baseCalendar, $eventInfo, $oldEventInfo); } // Check if the user is an attendee foreach ($eventInfo['attendees'] as $attendee) { - if (in_array($attendee['href'], $userHref)) { + if (in_array($attendee['href'], $userHref, true)) { // If this is a event update, we always generate a reply if ($oldCalendar) { return $this->parseEventForAttendee($baseCalendar, $eventInfo, $oldEventInfo, $attendee['href']); @@ -354,7 +354,7 @@ protected function processMessageReply(Message $itipMessage, ?VCalendar $existin $instances[$recurId] = $attendee['PARTSTAT']->getValue(); if (isset($vevent->{'REQUEST-STATUS'})) { $requestStatus = $vevent->{'REQUEST-STATUS'}->getValue(); - list($requestStatus) = explode(';', $requestStatus); + [$requestStatus] = explode(';', $requestStatus); } } @@ -566,7 +566,7 @@ protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo, $message->significantChange = 'REQUEST' === $attendee['forceSend'] - || count($oldAttendeeInstances) != count($newAttendeeInstances) + || count($oldAttendeeInstances) !== count($newAttendeeInstances) || count(array_diff($oldAttendeeInstances, $newAttendeeInstances)) > 0 || $oldEventInfo['significantChangeHash'] !== $eventInfo['significantChangeHash']; @@ -576,9 +576,9 @@ protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo, // We need to find a list of events that the attendee // is not a part of to add to the list of exceptions. $exceptions = []; - foreach ($eventInfo['instances'] as $instanceId => $vevent) { - if (!isset($attendee['newInstances'][$instanceId])) { - $exceptions[] = $instanceId; + foreach ($eventInfo['instances'] as $eventInstanceId => $vevent) { + if (!isset($attendee['newInstances'][$eventInstanceId])) { + $exceptions[] = $eventInstanceId; } } @@ -609,9 +609,7 @@ protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo, // We're adding PARTSTAT=NEEDS-ACTION to ensure that // iOS shows an "Inbox Item" - if (!isset($currentEventAttendee['PARTSTAT'])) { - $currentEventAttendee['PARTSTAT'] = 'NEEDS-ACTION'; - } + $currentEventAttendee['PARTSTAT'] ??= 'NEEDS-ACTION'; } } @@ -648,7 +646,12 @@ protected function parseEventForAttendee(VCalendar $calendar, array $eventInfo, return []; } - $oldInstances = !empty($oldEventInfo['attendees'][$attendee]['instances']) ? + $oldInstances = + is_array($oldEventInfo['attendees']) + && array_key_exists($attendee, $oldEventInfo['attendees']) + && is_array($oldEventInfo['attendees'][$attendee]) + && array_key_exists('instances', $oldEventInfo['attendees'][$attendee]) + && is_array($oldEventInfo['attendees'][$attendee]['instances']) ? $oldEventInfo['attendees'][$attendee]['instances'] : []; @@ -679,7 +682,7 @@ protected function parseEventForAttendee(VCalendar $calendar, array $eventInfo, // We only need to do that though, if the master event is not declined. if (isset($instances['master']) && 'DECLINED' !== $instances['master']['newstatus']) { foreach ($eventInfo['exdate'] as $exDate) { - if (!in_array($exDate, $oldEventInfo['exdate'] ?? [])) { + if (!in_array($exDate, $oldEventInfo['exdate'] ?? [], true)) { if (isset($instances[$exDate])) { $instances[$exDate]['newstatus'] = 'DECLINED'; } else { @@ -722,7 +725,7 @@ protected function parseEventForAttendee(VCalendar $calendar, array $eventInfo, $hasReply = false; foreach ($instances as $instance) { - if ($instance['oldstatus'] == $instance['newstatus'] && 'REPLY' !== $eventInfo['organizerForceSend']) { + if ($instance['oldstatus'] === $instance['newstatus'] && 'REPLY' !== $eventInfo['organizerForceSend']) { // Skip continue; } @@ -754,7 +757,7 @@ protected function parseEventForAttendee(VCalendar $calendar, array $eventInfo, // EXDATE $dt = DateTimeParser::parse($instance['id'], $eventInfo['timezone']); // Treat is as a DATE field - if (strlen($instance['id']) <= 8) { + if (strlen((string) $instance['id']) <= 8) { $event->add('DTSTART', $dt, ['VALUE' => 'DATE']); } else { $event->add('DTSTART', $dt); @@ -766,7 +769,7 @@ protected function parseEventForAttendee(VCalendar $calendar, array $eventInfo, if ('master' !== $instance['id']) { $dt = DateTimeParser::parse($instance['id'], $eventInfo['timezone']); // Treat is as a DATE field - if (strlen($instance['id']) <= 8) { + if (strlen((string) $instance['id']) <= 8) { $event->add('RECURRENCE-ID', $dt, ['VALUE' => 'DATE']); } else { $event->add('RECURRENCE-ID', $dt); @@ -858,7 +861,7 @@ protected function parseEventInfo(VCalendar $calendar): array $organizer = $vevent->ORGANIZER->getNormalizedValue(); $organizerName = $vevent->ORGANIZER['CN'] ?? null; } else { - if (strtoupper($organizer) !== strtoupper($vevent->ORGANIZER->getNormalizedValue())) { + if (strtoupper($organizer) !== strtoupper((string) $vevent->ORGANIZER->getNormalizedValue())) { throw new SameOrganizerForAllComponentsException('Every instance of the event must have the same organizer.'); } } @@ -884,7 +887,7 @@ protected function parseEventInfo(VCalendar $calendar): array foreach ($vevent->select('RRULE') as $rr) { foreach ($rr->getParts() as $key => $val) { // ignore default values (https://github.com/sabre-io/vobject/issues/126) - if ('INTERVAL' === $key && 1 == $val) { + if ('INTERVAL' === $key && '1' === (string) $val) { continue; } if (is_array($val)) { @@ -896,7 +899,7 @@ protected function parseEventInfo(VCalendar $calendar): array sort($rrule); } if (isset($vevent->STATUS)) { - $status = strtoupper($vevent->STATUS->getValue()); + $status = strtoupper((string) $vevent->STATUS->getValue()); } $recurId = isset($vevent->{'RECURRENCE-ID'}) ? $vevent->{'RECURRENCE-ID'}->getValue() : 'master'; @@ -914,7 +917,7 @@ protected function parseEventInfo(VCalendar $calendar): array foreach ($vevent->ATTENDEE as $attendee) { if ($this->scheduleAgentServerRules && isset($attendee['SCHEDULE-AGENT']) - && 'CLIENT' === strtoupper($attendee['SCHEDULE-AGENT']->getValue()) + && 'CLIENT' === strtoupper((string) $attendee['SCHEDULE-AGENT']->getValue()) ) { continue; } @@ -951,6 +954,7 @@ protected function parseEventInfo(VCalendar $calendar): array } foreach ($this->significantChangeProperties as $prop) { + // @phpstan-ignore property.dynamicName if (isset($vevent->$prop)) { $propertyValues = $vevent->select($prop); diff --git a/lib/ITip/Message.php b/lib/ITip/Message.php index 6f59eebc2..505e07f25 100644 --- a/lib/ITip/Message.php +++ b/lib/ITip/Message.php @@ -32,12 +32,12 @@ class Message * Contains the ITip method, which is something like REQUEST, REPLY or * CANCEL. */ - public ?string $method; + public ?string $method = null; /** * The current sequence number for the event. */ - public ?int $sequence; + public ?int $sequence = null; /** * The senders' email address. @@ -52,7 +52,7 @@ class Message * The name of the sender. This is often populated from a CN parameter from * either the ORGANIZER or ATTENDEE, depending on the message. */ - public ?string $senderName; + public ?string $senderName = null; /** * The recipient's email address. @@ -63,7 +63,7 @@ class Message * The name of the recipient. This is usually populated with the CN * parameter from the ATTENDEE or ORGANIZER property, if it's available. */ - public ?string $recipientName; + public ?string $recipientName = null; /** * After the message has been delivered, this should contain a string such @@ -108,7 +108,7 @@ public function getScheduleStatus() if (!$this->scheduleStatus) { return false; } - list($scheduleStatus) = explode(';', $this->scheduleStatus); + [$scheduleStatus] = explode(';', $this->scheduleStatus); return $scheduleStatus; } diff --git a/lib/Node.php b/lib/Node.php index 0dbe7cfad..47889a2ab 100644 --- a/lib/Node.php +++ b/lib/Node.php @@ -42,7 +42,7 @@ abstract class Node implements \IteratorAggregate, \ArrayAccess, \Countable, \Js /** * Reference to the parent object, if this is not the top object. */ - public ?Node $parent; + public ?Node $parent = null; /** * Iterator override. @@ -52,7 +52,7 @@ abstract class Node implements \IteratorAggregate, \ArrayAccess, \Countable, \Js /** * The root document. */ - protected ?Component $root; + protected ?Component $root = null; /** * Serializes the node into a mimedir format. diff --git a/lib/PHPUnitAssertions.php b/lib/PHPUnitAssertions.php index 1976c3afd..aad5438a5 100644 --- a/lib/PHPUnitAssertions.php +++ b/lib/PHPUnitAssertions.php @@ -41,7 +41,7 @@ public function assertVObjectEqualsVObject($expected, $actual, string $message = $input = Reader::read($input); } if (!$input instanceof Component) { - $this->fail('Input must be a string, stream or VObject component'); + self::fail('Input must be a string, stream or VObject component'); } unset($input->PRODID); if ($input instanceof Component\VCalendar && 'GREGORIAN' === (string) $input->CALSCALE) { @@ -51,23 +51,28 @@ public function assertVObjectEqualsVObject($expected, $actual, string $message = return $input; }; - $expected = $getObj($expected)->serialize(); - $actual = $getObj($actual)->serialize(); + /** + * @var string $expectedSerialized + */ + $expectedSerialized = $getObj($expected)->serialize(); + $actualSerialized = $getObj($actual)->serialize(); // Finding wildcards in expected. - preg_match_all('|^([A-Z]+):\\*\\*ANY\\*\\*\r$|m', $expected, $matches, PREG_SET_ORDER); + $result = preg_match_all('|^([A-Z]+):\\*\\*ANY\\*\\*\r$|m', $expectedSerialized, $matches, PREG_SET_ORDER); + + self::assertNotFalse($result); foreach ($matches as $match) { - $actual = preg_replace( + $actualSerialized = preg_replace( '|^'.preg_quote($match[1], '|').':(.*)\r$|m', $match[1].':**ANY**'."\r", - $actual + (string) $actualSerialized ); } - $this->assertEquals( - $expected, - $actual, + self::assertEquals( + $expectedSerialized, + $actualSerialized, $message ); } diff --git a/lib/Parameter.php b/lib/Parameter.php index f5eb58610..5988fa0fc 100644 --- a/lib/Parameter.php +++ b/lib/Parameter.php @@ -16,7 +16,7 @@ * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class Parameter extends Node +class Parameter extends Node implements \Stringable { /** * Parameter name. @@ -75,83 +75,12 @@ public function __construct(Document $root, ?string $name, $value = null) */ public static function guessParameterNameByValue(string $value): string { - switch (strtoupper($value)) { - // Encodings - case '7-BIT': - case 'QUOTED-PRINTABLE': - case 'BASE64': - $name = 'ENCODING'; - break; - - // Common types - case 'WORK': - case 'HOME': - case 'PREF': - // Delivery Label Type - case 'DOM': - case 'INTL': - case 'POSTAL': - case 'PARCEL': - // Telephone types - case 'VOICE': - case 'FAX': - case 'MSG': - case 'CELL': - case 'PAGER': - case 'BBS': - case 'MODEM': - case 'CAR': - case 'ISDN': - case 'VIDEO': - // EMAIL types (lol) - case 'AOL': - case 'APPLELINK': - case 'ATTMAIL': - case 'CIS': - case 'EWORLD': - case 'INTERNET': - case 'IBMMAIL': - case 'MCIMAIL': - case 'POWERSHARE': - case 'PRODIGY': - case 'TLX': - case 'X400': - // Photo / Logo format types - case 'GIF': - case 'CGM': - case 'WMF': - case 'BMP': - case 'DIB': - case 'PICT': - case 'TIFF': - case 'PDF': - case 'PS': - case 'JPEG': - case 'MPEG': - case 'MPEG2': - case 'AVI': - case 'QTIME': - // Sound Digital Audio Type - case 'WAVE': - case 'PCM': - case 'AIFF': - // Key types - case 'X509': - case 'PGP': - $name = 'TYPE'; - break; - - // Value types - case 'INLINE': - case 'URL': - case 'CONTENT-ID': - case 'CID': - $name = 'VALUE'; - break; - - default: - $name = ''; - } + $name = match (strtoupper($value)) { + '7-BIT', 'QUOTED-PRINTABLE', 'BASE64' => 'ENCODING', + 'WORK', 'HOME', 'PREF', 'DOM', 'INTL', 'POSTAL', 'PARCEL', 'VOICE', 'FAX', 'MSG', 'CELL', 'PAGER', 'BBS', 'MODEM', 'CAR', 'ISDN', 'VIDEO', 'AOL', 'APPLELINK', 'ATTMAIL', 'CIS', 'EWORLD', 'INTERNET', 'IBMMAIL', 'MCIMAIL', 'POWERSHARE', 'PRODIGY', 'TLX', 'X400', 'GIF', 'CGM', 'WMF', 'BMP', 'DIB', 'PICT', 'TIFF', 'PDF', 'PS', 'JPEG', 'MPEG', 'MPEG2', 'AVI', 'QTIME', 'WAVE', 'PCM', 'AIFF', 'X509', 'PGP' => 'TYPE', + 'INLINE', 'URL', 'CONTENT-ID', 'CID' => 'VALUE', + default => '', + }; return $name; } @@ -235,7 +164,8 @@ public function has(string $value): bool { return in_array( strtolower($value), - array_map('strtolower', (array) $this->value) + array_map(strtolower(...), (array) $this->value), + true ); } diff --git a/lib/Parser/Json.php b/lib/Parser/Json.php index 6403af4e9..45f985f68 100644 --- a/lib/Parser/Json.php +++ b/lib/Parser/Json.php @@ -27,12 +27,12 @@ class Json extends Parser /** * The input data. */ - protected ?array $input; + protected ?array $input = null; /** * Root component. */ - protected ?Document $root; + protected ?Document $root = null; /** * This method starts the parsing process. @@ -61,16 +61,11 @@ public function parse($input = null, int $options = 0): ?Document $this->options = $options; } - switch ($this->input[0]) { - case 'vcalendar': - $this->root = new VCalendar([], false); - break; - case 'vcard': - $this->root = new VCard([], false); - break; - default: - throw new ParseException('The root component must either be a vcalendar, or a vcard'); - } + $this->root = match ($this->input[0]) { + 'vcalendar' => new VCalendar([], false), + 'vcard' => new VCard([], false), + default => throw new ParseException('The root component must either be a vcalendar, or a vcard'), + }; foreach ($this->input[1] as $prop) { $this->root->add($this->parseProperty($prop)); } @@ -97,17 +92,13 @@ public function parseComponent(array $jComp): Component $self = $this; $properties = array_map( - function ($jProp) use ($self) { - return $self->parseProperty($jProp); - }, + $self->parseProperty(...), $jComp[1] ); if (isset($jComp[2])) { $components = array_map( - function ($jComp) use ($self) { - return $self->parseComponent($jComp); - }, + $self->parseComponent(...), $jComp[2] ); } else { @@ -134,7 +125,7 @@ public function parseProperty(array $jProp): Property $valueType, ) = $jProp; - $propertyName = strtoupper($propertyName); + $propertyName = strtoupper((string) $propertyName); // This is the default class we would be using if we didn't know the // value type. We're using this value later in this function. @@ -144,7 +135,7 @@ public function parseProperty(array $jProp): Property $value = array_slice($jProp, 3); - $valueType = strtoupper($valueType); + $valueType = strtoupper((string) $valueType); if (isset($parameters['group'])) { $propertyName = $parameters['group'].'.'.$propertyName; @@ -165,7 +156,7 @@ public function parseProperty(array $jProp): Property // If the value type we received (e.g.: TEXT) was not the default value // type for the given property (e.g.: BDAY), we need to add a VALUE= // parameter. - if ($defaultPropertyClass !== get_class($prop)) { + if ($defaultPropertyClass !== $prop::class) { $prop['VALUE'] = $valueType; } diff --git a/lib/Parser/MimeDir.php b/lib/Parser/MimeDir.php index f299978cd..85fd4156e 100644 --- a/lib/Parser/MimeDir.php +++ b/lib/Parser/MimeDir.php @@ -42,7 +42,7 @@ class MimeDir extends Parser /** * Root component. */ - protected ?Document $root; + protected ?Document $root = null; /** * By default, all input will be assumed to be UTF-8. @@ -112,7 +112,7 @@ public function parse($input = null, int $options = 0): ?Document */ public function setCharset(string $charset): void { - if (!in_array($charset, self::$SUPPORTED_CHARSETS)) { + if (!in_array($charset, self::$SUPPORTED_CHARSETS, true)) { throw new \InvalidArgumentException('Unsupported encoding. (Supported encodings: '.implode(', ', self::$SUPPORTED_CHARSETS).')'); } $this->charset = $charset; @@ -156,23 +156,18 @@ protected function parseDocument(): void // BOM is ZERO WIDTH NO-BREAK SPACE (U+FEFF). // It's 0xEF 0xBB 0xBF in UTF-8 hex. - if (3 <= strlen($line) + if (3 <= strlen((string) $line) && 0xEF === ord($line[0]) && 0xBB === ord($line[1]) && 0xBF === ord($line[2])) { - $line = \substr($line, 3); + $line = \substr((string) $line, 3); } - switch (strtoupper($line)) { - case 'BEGIN:VCALENDAR': - $class = VCalendar::$componentMap['VCALENDAR']; - break; - case 'BEGIN:VCARD': - $class = VCard::$componentMap['VCARD']; - break; - default: - throw new ParseException('This parser only supports VCARD and VCALENDAR files'); - } + $class = match (strtoupper((string) $line)) { + 'BEGIN:VCALENDAR' => VCalendar::$componentMap['VCALENDAR'], + 'BEGIN:VCARD' => VCard::$componentMap['VCARD'], + default => throw new ParseException('This parser only supports VCARD and VCALENDAR files'), + }; $this->root = new $class([], false); @@ -180,10 +175,10 @@ protected function parseDocument(): void // Reading until we hit END: try { $line = $this->readLine(); - } catch (EofException $oEx) { + } catch (EofException) { $line = 'END:'.$this->root->name; } - if ('END:' === strtoupper(\substr($line, 0, 4))) { + if ('END:' === strtoupper(\substr((string) $line, 0, 4))) { break; } $result = $this->parseLine($line); @@ -192,7 +187,7 @@ protected function parseDocument(): void } } - $name = strtoupper(\substr($line, 4)); + $name = strtoupper(\substr((string) $line, 4)); if ($name !== $this->root->name) { throw new ParseException('Invalid MimeDir file. expected: "END:'.$this->root->name.'" got: "END:'.$name.'"'); } @@ -222,7 +217,7 @@ protected function parseLine(string $line) while (true) { // Reading until we hit END: $line = $this->readLine(); - if ('END:' === strtoupper(\substr($line, 0, 4))) { + if ('END:' === strtoupper(\substr((string) $line, 0, 4))) { break; } try { @@ -247,7 +242,7 @@ protected function parseLine(string $line) } } - $name = strtoupper(\substr($line, 4)); + $name = strtoupper(\substr((string) $line, 4)); if ($name !== $component->name) { throw new ParseException('Invalid MimeDir file. expected: "END:'.$component->name.'" got: "END:'.$name.'"'); } @@ -419,7 +414,7 @@ protected function readProperty(string $line) throw new ParseException('Invalid Mimedir file. Line starting at '.$this->startLine.' did not follow iCalendar/vCard conventions'); } - if ('=' == $match[0][0] && self::TOKEN_PARAMNAME != $lastToken) { + if ('=' === $match[0][0] && self::TOKEN_PARAMNAME !== $lastToken) { throw new ParseException('Invalid Mimedir file. Line starting at '.$this->startLine.': Missing parameter name for parameter value "'.$match['paramValue'].'"'); } @@ -441,9 +436,7 @@ protected function readProperty(string $line) } if (isset($match['paramName'])) { $lastParam = strtoupper($match['paramName']); - if (!isset($property['parameters'][$lastParam])) { - $property['parameters'][$lastParam] = null; - } + $property['parameters'][$lastParam] ??= null; $lastToken = self::TOKEN_PARAMNAME; continue; } @@ -463,10 +456,8 @@ protected function readProperty(string $line) // @codeCoverageIgnoreEnd } - if (\is_null($property['value'])) { - $property['value'] = ''; - } - if (!isset($property['name']) || 0 == strlen($property['name'])) { + $property['value'] ??= ''; + if (!isset($property['name']) || 0 === strlen($property['name'])) { if ($this->options & self::OPTION_IGNORE_INVALID_LINES) { return false; } @@ -709,7 +700,7 @@ private function extractQuotedPrintableValue(): string // missing a whitespace. So if 'forgiving' is turned on, we will take // those as well. if ($this->options & self::OPTION_FORGIVING) { - while ('=' === \substr($value, -1) && $this->lineBuffer) { + while (str_ends_with($value, '=') && $this->lineBuffer) { // Reading the line $this->readLine(); // Grabbing the raw form diff --git a/lib/Parser/Parser.php b/lib/Parser/Parser.php index 29921d182..c5126445a 100644 --- a/lib/Parser/Parser.php +++ b/lib/Parser/Parser.php @@ -30,11 +30,6 @@ abstract class Parser */ public const OPTION_IGNORE_INVALID_LINES = 2; - /** - * Bitmask of parser options. - */ - protected int $options; - /** * Creates the parser. * @@ -42,12 +37,11 @@ abstract class Parser * * @param int $options any parser options (OPTION constants) */ - public function __construct($input = null, int $options = 0) + public function __construct($input = null, protected int $options = 0) { if (!is_null($input)) { $this->setInput($input); } - $this->options = $options; } /** diff --git a/lib/Parser/XML.php b/lib/Parser/XML.php index 9a5100684..6fb3e5624 100644 --- a/lib/Parser/XML.php +++ b/lib/Parser/XML.php @@ -28,17 +28,17 @@ class XML extends Parser /** * The input data. */ - protected ?array $input; + protected ?array $input = null; /** * A pointer/reference to the input. */ - private ?array $pointer; + private ?array $pointer = null; /** * Document, root component. */ - protected ?Document $root; + protected ?Document $root = null; /** * Creates the parser. @@ -112,7 +112,7 @@ public function parse($input = null, int $options = 0): ?Document */ protected function parseVCalendarComponents(Component $parentComponent): void { - foreach ($this->pointer['value'] ?: [] as $children) { + foreach ($this->pointer['value'] ?? [] as $children) { switch (static::getTagName($children['name'])) { case 'properties': $this->pointer = &$children['value']; @@ -145,8 +145,8 @@ protected function parseVCardComponents(Component $parentComponent): void */ protected function parseProperties(Component $parentComponent, string $propertyNamePrefix = ''): void { - foreach ($this->pointer ?: [] as $xmlProperty) { - list($namespace, $tagName) = SabreXml\Service::parseClarkNotation($xmlProperty['name']); + foreach ($this->pointer ?? [] as $xmlProperty) { + [$namespace, $tagName] = SabreXml\Service::parseClarkNotation($xmlProperty['name']); $propertyName = $tagName; $propertyValue = []; @@ -301,7 +301,7 @@ protected function parseProperties(Component $parentComponent, string $propertyN */ protected function parseComponent(Component $parentComponent): void { - $components = $this->pointer['value'] ?: []; + $components = $this->pointer['value'] ?? []; foreach ($components as $component) { $componentName = static::getTagName($component['name']); diff --git a/lib/Property.php b/lib/Property.php index 56b571e51..7432e5064 100644 --- a/lib/Property.php +++ b/lib/Property.php @@ -14,27 +14,8 @@ * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -abstract class Property extends Node +abstract class Property extends Node implements \Stringable { - /** - * The root document. - */ - public ?Component $root; - - /** - * Property name. - * - * This will contain a string such as DTSTART, SUMMARY, FN. - */ - public ?string $name; - - /** - * Property group. - * - * This is only used in vcards - */ - public ?string $group; - /** * List of parameters. */ @@ -75,13 +56,13 @@ abstract class Property extends Node * @param array $parameters List of parameters * @param string|null $group The vcard property group */ - public function __construct(Component $root, ?string $name, $value = null, array $parameters = [], ?string $group = null, ?int $lineIndex = null, ?string $lineString = null) + public function __construct(public ?Component $root, /** + * Property name. + * + * This will contain a string such as DTSTART, SUMMARY, FN. + */ + public ?string $name, $value = null, array $parameters = [], public ?string $group = null, ?int $lineIndex = null, ?string $lineString = null) { - $this->name = $name; - $this->group = $group; - - $this->root = $root; - foreach ($parameters as $k => $v) { $this->add($k, $v); } @@ -123,7 +104,7 @@ public function setValue($value): void public function getValue() { if (is_array($this->value)) { - if (0 == count($this->value)) { + if (0 === count($this->value)) { return null; } elseif (1 === count($this->value)) { return $this->value[0]; @@ -242,7 +223,7 @@ public function serialize(): string ); // remove single space after last CRLF - return \substr($str, 0, -1); + return \substr((string) $str, 0, -1); } /** @@ -282,7 +263,7 @@ public function jsonSerialize(): array if ('VALUE' === $parameter->name) { continue; } - $parameters[strtolower($parameter->name)] = $parameter->jsonSerialize(); + $parameters[strtolower((string) $parameter->name)] = $parameter->jsonSerialize(); } // In jCard, we need to encode the property-group as a separate 'group' // parameter. @@ -292,7 +273,7 @@ public function jsonSerialize(): array return array_merge( [ - strtolower($this->name), + strtolower((string) $this->name), (object) $parameters, strtolower($this->getValueType()), ], @@ -329,13 +310,13 @@ public function xmlSerialize(Xml\Writer $writer): void $parameters[] = $parameter; } - $writer->startElement(strtolower($this->name)); + $writer->startElement(strtolower((string) $this->name)); - if (!empty($parameters)) { + if ([] !== $parameters) { $writer->startElement('parameters'); foreach ($parameters as $parameter) { - $writer->startElement(strtolower($parameter->name)); + $writer->startElement(strtolower((string) $parameter->name)); $writer->write($parameter); $writer->endElement(); } @@ -520,7 +501,7 @@ public function validate(int $options = 0): array } // Checking if the property name does not contain any invalid bytes. - if (!preg_match('/^([A-Z0-9-]+)$/', $this->name)) { + if (!preg_match('/^([A-Z0-9-]+)$/', (string) $this->name)) { $warnings[] = [ 'level' => $options & self::REPAIR ? 1 : 3, 'message' => 'The property name: '.$this->name.' contains invalid characters. Only A-Z, 0-9 and - are allowed', @@ -572,7 +553,7 @@ public function validate(int $options = 0): array } break; } - if ($allowedEncoding && !in_array(strtoupper($encoding), $allowedEncoding)) { + if ($allowedEncoding && !in_array(strtoupper($encoding), $allowedEncoding, true)) { $warnings[] = [ 'level' => 3, 'message' => 'ENCODING='.strtoupper($encoding).' is not valid for this document type.', diff --git a/lib/Property/Binary.php b/lib/Property/Binary.php index 25cda8d25..9d68f415e 100644 --- a/lib/Property/Binary.php +++ b/lib/Property/Binary.php @@ -54,7 +54,7 @@ public function setValue($value): void */ public function setRawMimeDirValue(string $val): void { - $this->value = base64_decode($val); + $this->value = base64_decode($val, true); } /** @@ -62,7 +62,7 @@ public function setRawMimeDirValue(string $val): void */ public function getRawMimeDirValue(): string { - return base64_encode($this->value); + return base64_encode((string) $this->value); } /** @@ -83,7 +83,7 @@ public function getValueType(): string */ public function getJsonValue(): array { - return [base64_encode($this->getValue())]; + return [base64_encode((string) $this->getValue())]; } /** @@ -93,7 +93,7 @@ public function getJsonValue(): array */ public function setJsonValue(array $value): void { - $value = array_map('base64_decode', $value); + $value = array_map(base64_decode(...), $value); parent::setJsonValue($value); } } diff --git a/lib/Property/Boolean.php b/lib/Property/Boolean.php index cdc3408aa..f33fbafdc 100644 --- a/lib/Property/Boolean.php +++ b/lib/Property/Boolean.php @@ -56,9 +56,7 @@ public function getValueType(): string public function setXmlValue(array $value): void { $value = array_map( - function ($value) { - return 'true' === $value; - }, + fn ($value) => 'true' === $value, $value ); parent::setXmlValue($value); diff --git a/lib/Property/FloatValue.php b/lib/Property/FloatValue.php index 7a36e0976..32b02a972 100644 --- a/lib/Property/FloatValue.php +++ b/lib/Property/FloatValue.php @@ -67,7 +67,7 @@ public function getValueType(): string */ public function getJsonValue(): array { - $val = array_map('floatval', $this->getParts()); + $val = array_map(floatval(...), $this->getParts()); // Special-casing the GEO property. // @@ -86,7 +86,7 @@ public function getJsonValue(): array */ public function setXmlValue(array $value): void { - $value = array_map('floatval', $value); + $value = array_map(floatval(...), $value); parent::setXmlValue($value); } @@ -101,7 +101,7 @@ protected function xmlSerializeValue(Xml\Writer $writer): void // See: // http://tools.ietf.org/html/rfc6321#section-3.4.1.2 if ('GEO' === $this->name) { - $value = array_map('floatval', $this->getParts()); + $value = array_map(floatval(...), $this->getParts()); $writer->writeElement('latitude', $value[0]); $writer->writeElement('longitude', $value[1]); diff --git a/lib/Property/ICalendar/CalAddress.php b/lib/Property/ICalendar/CalAddress.php index 01969e87d..a2b13eee7 100644 --- a/lib/Property/ICalendar/CalAddress.php +++ b/lib/Property/ICalendar/CalAddress.php @@ -43,10 +43,10 @@ public function getValueType(): string public function getNormalizedValue(): string { $input = $this->getValue(); - if (!strpos($input, ':')) { + if (!strpos((string) $input, ':')) { return $input; } - list($schema, $everythingElse) = explode(':', $input, 2); + [$schema, $everythingElse] = explode(':', (string) $input, 2); $schema = strtolower($schema); if ('mailto' === $schema) { $everythingElse = strtolower($everythingElse); diff --git a/lib/Property/ICalendar/DateTime.php b/lib/Property/ICalendar/DateTime.php index e8a60935a..06230068a 100644 --- a/lib/Property/ICalendar/DateTime.php +++ b/lib/Property/ICalendar/DateTime.php @@ -110,7 +110,7 @@ public function isFloating(): bool !$this->hasTime() || ( !isset($this['TZID']) - && false === strpos($this->getValue(), 'Z') + && !str_contains((string) $this->getValue(), 'Z') ); } @@ -204,7 +204,7 @@ public function setDateTimes(array $dt, $isFloating = false): void } if (is_null($tz)) { $tz = $d->getTimeZone(); - $isUtc = in_array($tz->getName(), ['UTC', 'GMT', 'Z', '+00:00']); + $isUtc = in_array($tz->getName(), ['UTC', 'GMT', 'Z', '+00:00'], true); if (!$isUtc) { $this->offsetSet('TZID', $tz->getName()); } @@ -256,7 +256,7 @@ public function getJsonValue(): array $isFloating = $this->isFloating(); $tz = $dts[0]->getTimeZone(); - $isUtc = !$isFloating && in_array($tz->getName(), ['UTC', 'GMT', 'Z']); + $isUtc = !$isFloating && in_array($tz->getName(), ['UTC', 'GMT', 'Z'], true); return array_map( function (\DateTimeInterface $dt) use ($hasTime, $isUtc) { @@ -285,9 +285,7 @@ public function setJsonValue(array $value): void // those. $this->setValue( array_map( - function ($item) { - return strtr($item, [':' => '', '-' => '']); - }, + fn ($item) => strtr($item, [':' => '', '-' => '']), $value ) ); @@ -305,7 +303,7 @@ function ($item) { public function offsetSet($offset, $value): void { parent::offsetSet($offset, $value); - if ('VALUE' !== strtoupper($offset)) { + if ('VALUE' !== strtoupper((string) $offset)) { return; } @@ -346,7 +344,7 @@ public function validate(int $options = 0): array DateTimeParser::parseDateTime($value); break; } - } catch (InvalidDataException $e) { + } catch (InvalidDataException) { $messages[] = [ 'level' => 3, 'message' => 'The supplied value ('.$value.') is not a correct '.$valueType, diff --git a/lib/Property/ICalendar/Period.php b/lib/Property/ICalendar/Period.php index 7632cb4d1..da9d972b1 100644 --- a/lib/Property/ICalendar/Period.php +++ b/lib/Property/ICalendar/Period.php @@ -64,14 +64,17 @@ public function getValueType(): string public function setJsonValue(array $value): void { $value = array_map( - function ($item) { - return strtr(implode('/', $item), [':' => '', '-' => '']); - }, + fn ($item) => strtr(implode('/', $item), [':' => '', '-' => '']), $value ); parent::setJsonValue($value); } + public function appendUtc(string $strDate) + { + return !str_ends_with($strDate, 'Z') ? '' : 'Z'; + } + /** * Returns the value, in the format it should be encoded for json. * @@ -83,21 +86,21 @@ public function getJsonValue(): array { $return = []; foreach ($this->getParts() as $item) { - list($start, $end) = explode('/', $item, 2); + [$start, $end] = explode('/', (string) $item, 2); - $start = DateTimeParser::parseDateTime($start); + $startDt = DateTimeParser::parseDateTime($start)->format('Y-m-d\\TH:i:s').$this->appendUtc($start); // This is a duration value. if ('P' === $end[0]) { $return[] = [ - $start->format('Y-m-d\\TH:i:s'), + $startDt, $end, ]; } else { - $end = DateTimeParser::parseDateTime($end); + $endDt = DateTimeParser::parseDateTime($end)->format('Y-m-d\\TH:i:s').$this->appendUtc($end); $return[] = [ - $start->format('Y-m-d\\TH:i:s'), - $end->format('Y-m-d\\TH:i:s'), + $startDt, + $endDt, ]; } } diff --git a/lib/Property/ICalendar/Recur.php b/lib/Property/ICalendar/Recur.php index 10081673e..f3d45158a 100644 --- a/lib/Property/ICalendar/Recur.php +++ b/lib/Property/ICalendar/Recur.php @@ -29,14 +29,14 @@ class Recur extends Property /** * Reference to the parent object, if this is not the top object. */ - public ?Node $parent; + public ?Node $parent = null; /** * Updates the current value. * * This may be either a single, or multiple strings in an array. * - * @param string|array $value + * @param string|array|object $value */ public function setValue($value): void { @@ -52,17 +52,17 @@ public function setValue($value): void $v = strtoupper($v); // The value had multiple sub-values - if (false !== strpos($v, ',')) { + if (str_contains($v, ',')) { $v = explode(',', $v); } - if (0 === strcmp($k, 'until')) { + if (0 === strcmp((string) $k, 'until')) { $v = strtr($v, [':' => '', '-' => '']); } } elseif (is_array($v)) { - $v = array_map('strtoupper', $v); + $v = array_map(strtoupper(...), $v); } - $newVal[strtoupper($k)] = $v; + $newVal[strtoupper((string) $k)] = $v; } $this->value = $newVal; } elseif (is_string($value)) { @@ -151,13 +151,13 @@ public function getJsonValue(): array { $values = []; foreach ($this->getParts() as $k => $v) { - if (0 === strcmp($k, 'UNTIL')) { + if (0 === strcmp((string) $k, 'UNTIL')) { $date = new DateTime($this->root, null, $v); - $values[strtolower($k)] = $date->getJsonValue()[0]; - } elseif (0 === strcmp($k, 'COUNT')) { - $values[strtolower($k)] = intval($v); + $values[strtolower((string) $k)] = $date->getJsonValue()[0]; + } elseif (0 === strcmp((string) $k, 'COUNT')) { + $values[strtolower((string) $k)] = intval($v); } else { - $values[strtolower($k)] = $v; + $values[strtolower((string) $k)] = $v; } } @@ -186,7 +186,7 @@ public static function stringToArray(string $value): array $newValue = []; foreach (explode(';', $value) as $part) { // Skipping empty parts. - if (empty($part)) { + if ('' === $part) { continue; } @@ -196,10 +196,10 @@ public static function stringToArray(string $value): array throw new InvalidDataException('The supplied iCalendar RRULE part is incorrect: '.$part); } - list($partName, $partValue) = $parts; + [$partName, $partValue] = $parts; // The value itself had multiple values.. - if (false !== strpos($partValue, ',')) { + if (str_contains($partValue, ',')) { $partValue = explode(',', $partValue); } $newValue[$partName] = $partValue; @@ -243,7 +243,7 @@ public function validate(int $options = 0): array if ($repair) { unset($values[$key]); } - } elseif ('BYMONTH' == $key) { + } elseif ('BYMONTH' === $key) { $byMonth = (array) $value; foreach ($byMonth as $i => $v) { if (!is_numeric($v) || (int) $v < 1 || (int) $v > 12) { @@ -262,13 +262,13 @@ public function validate(int $options = 0): array } } // if there is no valid entry left, remove the whole value - if (is_array($value) && empty($values[$key])) { + if (is_array($value) && ([] === $values[$key])) { unset($values[$key]); } - } elseif ('BYWEEKNO' == $key) { + } elseif ('BYWEEKNO' === $key) { $byWeekNo = (array) $value; foreach ($byWeekNo as $i => $v) { - if (!is_numeric($v) || (int) $v < -53 || 0 == (int) $v || (int) $v > 53) { + if (!is_numeric($v) || (int) $v < -53 || 0 === (int) $v || (int) $v > 53) { $warnings[] = [ 'level' => $repair ? 1 : 3, 'message' => 'BYWEEKNO in RRULE must have value(s) from -53 to -1, or 1 to 53!', @@ -284,13 +284,13 @@ public function validate(int $options = 0): array } } // if there is no valid entry left, remove the whole value - if (is_array($value) && empty($values[$key])) { + if (is_array($value) && ([] === $values[$key])) { unset($values[$key]); } - } elseif ('BYYEARDAY' == $key) { + } elseif ('BYYEARDAY' === $key) { $byYearDay = (array) $value; foreach ($byYearDay as $i => $v) { - if (!is_numeric($v) || (int) $v < -366 || 0 == (int) $v || (int) $v > 366) { + if (!is_numeric($v) || (int) $v < -366 || 0 === (int) $v || (int) $v > 366) { $warnings[] = [ 'level' => $repair ? 1 : 3, 'message' => 'BYYEARDAY in RRULE must have value(s) from -366 to -1, or 1 to 366!', @@ -306,7 +306,7 @@ public function validate(int $options = 0): array } } // if there is no valid entry left, remove the whole value - if (is_array($value) && empty($values[$key])) { + if (is_array($value) && ([] === $values[$key])) { unset($values[$key]); } } diff --git a/lib/Property/IntegerValue.php b/lib/Property/IntegerValue.php index f1ae55d17..1cd7273cc 100644 --- a/lib/Property/IntegerValue.php +++ b/lib/Property/IntegerValue.php @@ -62,7 +62,7 @@ public function getJsonValue(): array */ public function setXmlValue(array $value): void { - $value = array_map('intval', $value); + $value = array_map(intval(...), $value); parent::setXmlValue($value); } } diff --git a/lib/Property/Text.php b/lib/Property/Text.php index 363c3fa4f..e585026fc 100644 --- a/lib/Property/Text.php +++ b/lib/Property/Text.php @@ -71,7 +71,7 @@ public function __construct(Component $root, string $name, $value = null, array // 2. structured value properties // // The former is always separated by a comma, the latter by semicolon. - if (in_array($name, $this->structuredValues)) { + if (in_array($name, $this->structuredValues, true)) { $this->delimiter = ';'; } @@ -155,7 +155,7 @@ public function getJsonValue(): array // Structured text values should always be returned as a single // array-item. Multi-value text should be returned as multiple items in // the top-array. - if (in_array($this->name, $this->structuredValues)) { + if (in_array($this->name, $this->structuredValues, true)) { return [$this->getParts()]; } @@ -213,7 +213,7 @@ public function serialize(): string // If the resulting value contains a \n, we must encode it as // quoted-printable. - if (false !== \strpos($val, "\n")) { + if (str_contains((string) $val, "\n")) { $str .= ';ENCODING=QUOTED-PRINTABLE:'; $lastLine = $str; $out = ''; @@ -222,13 +222,13 @@ public function serialize(): string // encode newlines for us. Specifically, the \r\n sequence must in // vcards be encoded as =0D=OA and we must insert soft-newlines // every 75 bytes. - for ($ii = 0; $ii < \strlen($val); ++$ii) { + for ($ii = 0; $ii < \strlen((string) $val); ++$ii) { $ord = \ord($val[$ii]); // These characters are encoded as themselves. if ($ord >= 32 && $ord <= 126) { $lastLine .= $val[$ii]; } else { - $lastLine .= '='.\strtoupper(\bin2hex($val[$ii])); + $lastLine .= '='.\strtoupper(\bin2hex((string) $val[$ii])); } if (\strlen($lastLine) >= 75) { // Soft line break @@ -255,7 +255,7 @@ public function serialize(): string ); // remove single space after last CRLF - return \substr($str, 0, -1); + return \substr((string) $str, 0, -1); } /** @@ -270,7 +270,7 @@ protected function xmlSerializeValue(Xml\Writer $writer): void foreach ($items as $i => $item) { $writer->writeElement( $item, - !empty($values[$i]) ? $values[$i] : null + ('' !== $values[$i] && [] !== $values[$i]) ? $values[$i] : null ); } }; diff --git a/lib/Property/Time.php b/lib/Property/Time.php index ed314fc0d..9c4016c64 100644 --- a/lib/Property/Time.php +++ b/lib/Property/Time.php @@ -104,7 +104,7 @@ public function getJsonValue(): array $timeStr .= 'Z'; } else { $timeStr .= - preg_replace('/([0-9]{2})([0-9]{2})$/', '$1:$2', $parts['timezone']); + preg_replace('/([0-9]{2})([0-9]{2})$/', '$1:$2', (string) $parts['timezone']); } } @@ -118,9 +118,7 @@ public function getJsonValue(): array public function setXmlValue(array $value): void { $value = array_map( - function ($value) { - return str_replace(':', '', $value); - }, + fn ($value) => str_replace(':', '', $value), $value ); parent::setXmlValue($value); diff --git a/lib/Property/Uri.php b/lib/Property/Uri.php index 228b7090f..dce7bf4bb 100644 --- a/lib/Property/Uri.php +++ b/lib/Property/Uri.php @@ -38,7 +38,7 @@ public function getValueType(): string public function parameters(): array { $parameters = parent::parameters(); - if (!isset($parameters['VALUE']) && in_array($this->name, ['URL', 'PHOTO'])) { + if (!isset($parameters['VALUE']) && in_array($this->name, ['URL', 'PHOTO'], true)) { // If we are encoding a URI value, and this URI value has no // VALUE=URI parameter, we add it anyway. // @@ -74,14 +74,10 @@ public function setRawMimeDirValue(string $val): void $matches = preg_split($regex, $val, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); $newVal = ''; foreach ($matches as $match) { - switch ($match) { - case '\:': - $newVal .= ':'; - break; - default: - $newVal .= $match; - break; - } + match ($match) { + '\:' => $newVal .= ':', + default => $newVal .= $match, + }; } $this->value = $newVal; } else { diff --git a/lib/Property/UtcOffset.php b/lib/Property/UtcOffset.php index 09aab0151..52d81f1f6 100644 --- a/lib/Property/UtcOffset.php +++ b/lib/Property/UtcOffset.php @@ -42,9 +42,7 @@ public function getValueType(): string public function setJsonValue(array $value): void { $value = array_map( - function ($value) { - return str_replace(':', '', $value); - }, + fn ($value) => str_replace(':', '', $value), $value ); parent::setJsonValue($value); @@ -58,10 +56,8 @@ function ($value) { public function getJsonValue(): array { return array_map( - function ($value) { - return substr($value, 0, -2).':'. - substr($value, -2); - }, + fn ($value) => substr((string) $value, 0, -2).':'. + substr((string) $value, -2), parent::getJsonValue() ); } diff --git a/lib/Property/VCard/DateAndOrTime.php b/lib/Property/VCard/DateAndOrTime.php index e87bf1b3a..9a7693961 100644 --- a/lib/Property/VCard/DateAndOrTime.php +++ b/lib/Property/VCard/DateAndOrTime.php @@ -77,7 +77,7 @@ public function setValue($value): void public function setDateTime(\DateTimeInterface $dt): void { $tz = $dt->getTimeZone(); - $isUtc = in_array($tz->getName(), ['UTC', 'GMT', 'Z']); + $isUtc = in_array($tz->getName(), ['UTC', 'GMT', 'Z'], true); if ($isUtc) { $value = $dt->format('Ymd\\THis\\Z'); @@ -232,14 +232,10 @@ protected function xmlSerializeValue(Xml\Writer $writer): void $value = ''; // $d = defined - $d = function ($part) use ($parts): bool { - return !is_null($parts[$part]); - }; + $d = (fn ($part): bool => !is_null($parts[$part])); // $r = read - $r = function ($part) use ($parts) { - return $parts[$part]; - }; + $r = (fn ($part) => $parts[$part]); // From the Relax NG Schema. // @@ -341,7 +337,7 @@ public function validate(int $options = 0): array try { DateTimeParser::parseVCardDateTime($value); - } catch (InvalidDataException $e) { + } catch (InvalidDataException) { $messages[] = [ 'level' => 3, 'message' => 'The supplied value ('.$value.') is not a correct DATE-AND-OR-TIME property', diff --git a/lib/Recur/EventIterator.php b/lib/Recur/EventIterator.php index d0317e14b..5db409350 100644 --- a/lib/Recur/EventIterator.php +++ b/lib/Recur/EventIterator.php @@ -91,9 +91,7 @@ class EventIterator implements \Iterator */ public function __construct($input, ?string $uid = null, ?\DateTimeZone $timeZone = null) { - if (is_null($timeZone)) { - $timeZone = new \DateTimeZone('UTC'); - } + $timeZone ??= new \DateTimeZone('UTC'); $this->timeZone = $timeZone; if (is_array($input)) { diff --git a/lib/Recur/RDateIterator.php b/lib/Recur/RDateIterator.php index 4ad688f9d..b9bd0beff 100644 --- a/lib/Recur/RDateIterator.php +++ b/lib/Recur/RDateIterator.php @@ -26,9 +26,13 @@ class RDateIterator implements \Iterator * * @param string|array $rrule */ - public function __construct($rrule, \DateTimeInterface $start) + public function __construct($rrule, /** + * The reference start date/time for the rrule. + * + * All calculations are based on this initial date. + */ + protected \DateTimeInterface $startDate) { - $this->startDate = $start; $this->parseRDate($rrule); $this->currentDate = clone $this->startDate; } @@ -117,13 +121,6 @@ public function fastForward(\DateTimeInterface $dt): void } } - /** - * The reference start date/time for the rrule. - * - * All calculations are based on this initial date. - */ - protected \DateTimeInterface $startDate; - /** * The date of the current iteration. You can get this by calling * ->current(). diff --git a/lib/Recur/RRuleIterator.php b/lib/Recur/RRuleIterator.php index fe14f7efb..b59c5c946 100644 --- a/lib/Recur/RRuleIterator.php +++ b/lib/Recur/RRuleIterator.php @@ -28,8 +28,6 @@ class RRuleIterator implements \Iterator */ public const dateUpperLimit = 253402300799; - private bool $yearlySkipUpperLimit; - /** * Creates the Iterator. * @@ -37,12 +35,15 @@ class RRuleIterator implements \Iterator * * @throws InvalidDataException */ - public function __construct($rrule, \DateTimeInterface $start, bool $yearlySkipUpperLimit = true) + public function __construct($rrule, /** + * The reference start date/time for the rrule. + * + * All calculations are based on this initial date. + */ + protected \DateTimeInterface $startDate, private readonly bool $yearlySkipUpperLimit = true) { - $this->startDate = $start; $this->parseRRule($rrule); $this->currentDate = clone $this->startDate; - $this->yearlySkipUpperLimit = $yearlySkipUpperLimit; } /* Implementation of the Iterator interface {{{ */ @@ -225,27 +226,14 @@ public function getFrequency(): string */ private function getFrequencyCoeff() { - $frequencyCoeff = null; - - switch ($this->frequency) { - case 'hourly': - $frequencyCoeff = 1 / 24; - break; - case 'daily': - $frequencyCoeff = 1; - break; - case 'weekly': - $frequencyCoeff = 7; - break; - case 'monthly': - $frequencyCoeff = 30; - break; - case 'yearly': - $frequencyCoeff = 365; - break; - } - - return $frequencyCoeff; + return match ($this->frequency) { + 'hourly' => 1 / 24, + 'daily' => 1, + 'weekly' => 7, + 'monthly' => 30, + 'yearly' => 365, + default => null, + }; } /** @@ -298,11 +286,33 @@ private function jumpForward(\DateTimeInterface $dt): void } /** - * The reference start date/time for the rrule. + * Falls back to the current value when the BYSECOND, BYMINUTE or BYHOUR rule part is absent. * - * All calculations are based on this initial date. + * @param array|null $ruleValues + * + * @return array */ - protected \DateTimeInterface $startDate; + private function ruleValuesOrCurrent(?array $ruleValues, int $current): array + { + return null === $ruleValues || [] === $ruleValues ? [$current] : $ruleValues; + } + + /** + * Occurrences are [day, hour, minute, second] tuples, compared in that order. + * + * @param array $occurrence + * @param array $moment + */ + private function isOccurrenceAfter(array $occurrence, array $moment): bool + { + foreach ($occurrence as $index => $value) { + if ((int) $value !== (int) $moment[$index]) { + return (int) $value > (int) $moment[$index]; + } + } + + return false; + } /** * The date of the current iteration. You can get this by calling @@ -508,23 +518,23 @@ protected function nextDaily($amount = 1): void } $recurrenceHours = []; - if (!empty($this->byHour)) { + if ($this->byHour) { $recurrenceHours = $this->getHours(); } $recurrenceDays = []; - if (!empty($this->byDay)) { + if ($this->byDay) { $recurrenceDays = $this->getDays(); } $recurrenceMonths = []; - if (!empty($this->byMonth)) { + if ($this->byMonth) { $recurrenceMonths = $this->getMonths(); } do { if ($this->byHour) { - if ('23' == $this->currentDate->format('G')) { + if ('23' === $this->currentDate->format('G')) { // to obey the interval rule $this->currentDate = $this->currentDate->modify('+'.(($amount * $this->interval) - 1).' days'); $amount = 1; @@ -551,9 +561,9 @@ protected function nextDaily($amount = 1): void return; } } while ( - ($this->byDay && !in_array($currentDay, $recurrenceDays)) - || ($this->byHour && !in_array($currentHour, $recurrenceHours)) - || ($this->byMonth && !in_array($currentMonth, $recurrenceMonths)) + ($this->byDay && !in_array((int) $currentDay, $recurrenceDays, true)) + || ($this->byHour && !in_array($currentHour, $recurrenceHours, true)) + || ($this->byMonth && !in_array($currentMonth, $recurrenceMonths, true)) ); } @@ -595,18 +605,18 @@ protected function nextWeekly($amount = 1): void $currentHour = (int) $this->currentDate->format('G'); // We need to roll over to the next week - if ($currentDay === $firstDay && (!$this->byHour || '0' == $currentHour)) { + if ($currentDay === $firstDay && (!$this->byHour || 0 === $currentHour)) { $this->currentDate = $this->currentDate->modify('+'.(($amount * $this->interval) - 1).' weeks'); $amount = 1; // We need to go to the first day of this week, but only if we // are not already on this first day of this week. - if ($this->currentDate->format('w') != $firstDay) { + if ((int) $this->currentDate->format('w') !== $firstDay) { $this->currentDate = $this->currentDate->modify('last '.$this->dayNames[$this->dayMap[$this->weekStart]]); } } // We have a match - } while (($this->byDay && !in_array($currentDay, $recurrenceDays)) || ($this->byHour && !in_array($currentHour, $recurrenceHours))); + } while (($this->byDay && !in_array($currentDay, $recurrenceDays, true)) || ($this->byHour && !in_array((string) $currentHour, $recurrenceHours, true))); } /** @@ -632,37 +642,22 @@ protected function nextMonthly($amount = 1): void ++$increase; $tempDate = clone $this->currentDate; $tempDate = $tempDate->modify('+ '.($this->interval * $increase).' months '.$this->startTime()); - } while ($tempDate->format('j') != $currentDayOfMonth); + } while ($tempDate->format('j') !== $currentDayOfMonth); $this->currentDate = $tempDate; } return; } - $occurrence = -1; + $selectedOccurrence = -1; while (true) { $occurrences = $this->getMonthlyOccurrences(); foreach ($occurrences as $occurrence) { // The first occurrence that's higher than the current // day of the month wins. - if ($occurrence[0] > $currentDayOfMonth) { - break 2; - } elseif ($occurrence[0] < $currentDayOfMonth) { - continue; - } - if ($occurrence[1] > $currentHourOfMonth) { - break 2; - } elseif ($occurrence[1] < $currentHourOfMonth) { - continue; - } - - if ($occurrence[2] > $currentMinuteOfMonth) { - break 2; - } elseif ($occurrence[2] < $currentMinuteOfMonth) { - continue; - } - if ($occurrence[3] > $currentSecondOfMonth) { + if ($this->isOccurrenceAfter($occurrence, [$currentDayOfMonth, $currentHourOfMonth, $currentMinuteOfMonth, $currentSecondOfMonth])) { + $selectedOccurrence = $occurrence; break 2; } } @@ -709,8 +704,8 @@ protected function nextMonthly($amount = 1): void $this->currentDate = $this->currentDate->setDate( (int) $this->currentDate->format('Y'), (int) $this->currentDate->format('n'), - $occurrence[0] - )->setTime($occurrence[1], $occurrence[2], $occurrence[3]); + $selectedOccurrence[0] + )->setTime($selectedOccurrence[1], $selectedOccurrence[2], $selectedOccurrence[3]); } /** @@ -726,9 +721,9 @@ protected function nextYearly($amount = 1): void $currentSecondOfMonth = $this->currentDate->format('s'); // No sub-rules, so we just advance by year - if (empty($this->byMonth)) { + if (!$this->byMonth) { // Unless it was a leap day! - if (2 == $currentMonth && 29 == $currentDayOfMonth) { + if (2 === (int) $currentMonth && 29 === (int) $currentDayOfMonth) { $counter = 0; do { ++$counter; @@ -742,7 +737,7 @@ protected function nextYearly($amount = 1): void // functions instead. $nextDate = clone $this->currentDate; $nextDate = $nextDate->modify('+ '.($this->interval * $counter).' years'); - } while (2 != $nextDate->format('n')); + } while (2 !== (int) $nextDate->format('n')); $this->currentDate = $nextDate; @@ -814,7 +809,7 @@ protected function nextYearly($amount = 1): void $date = $date->sub(new \DateInterval('P'.abs($byYearDay + 1).'D')); } - if ($date > $this->currentDate && in_array($date->format('N'), $dayOffsets)) { + if ($date > $this->currentDate && in_array((int) $date->format('N'), $dayOffsets, true)) { $checkDates[] = $date; } } @@ -842,32 +837,18 @@ protected function nextYearly($amount = 1): void // If we got a byDay or getMonthDay filter, we must first expand // further. if ($this->byDay || $this->byMonthDay) { - $occurrence = -1; + $selectedOccurrence = -1; while (true) { // If the start date is incorrect we must directly jump to the next value - if (in_array($currentMonth, $this->byMonth)) { + if (in_array((string) $currentMonth, $this->byMonth, true)) { $occurrences = $this->getMonthlyOccurrences(); foreach ($occurrences as $occurrence) { - // The first occurrence that's higher than the current - // day of the month wins. + // The first occurrence that's later than the current + // moment of the month wins. // If we advanced to the next month or year, the first // occurrence is always correct. - if ($occurrence[0] > $currentDayOfMonth || $advancedToNewMonth) { - break 2; - } elseif ($occurrence[0] < $currentDayOfMonth) { - continue; - } - if ($occurrence[1] > $currentHourOfMonth) { - break 2; - } elseif ($occurrence[1] < $currentHourOfMonth) { - continue; - } - if ($occurrence[2] > $currentMinuteOfMonth) { - break 2; - } elseif ($occurrence[2] < $currentMinuteOfMonth) { - continue; - } - if ($occurrence[3] > $currentSecondOfMonth) { + if ($advancedToNewMonth || $this->isOccurrenceAfter($occurrence, [$currentDayOfMonth, $currentHourOfMonth, $currentMinuteOfMonth, $currentSecondOfMonth])) { + $selectedOccurrence = $occurrence; break 2; } } @@ -884,12 +865,12 @@ protected function nextYearly($amount = 1): void $amount = 1; $currentMonth = 1; } - } while (!in_array($currentMonth, $this->byMonth)); + } while (!in_array((string) $currentMonth, $this->byMonth, true)); $this->currentDate = $this->currentDate->setDate( (int) $currentYear, - (int) $currentMonth, - (int) $currentDayOfMonth + $currentMonth, + $currentDayOfMonth ); // To prevent running this forever (better: until we hit the max date of DateTimeImmutable) we simply @@ -905,8 +886,8 @@ protected function nextYearly($amount = 1): void $this->currentDate = $this->currentDate->setDate( (int) $currentYear, (int) $currentMonth, - (int) $occurrence[0] - )->setTime($occurrence[1], $occurrence[2], $occurrence[3]); + (int) $selectedOccurrence[0] + )->setTime($selectedOccurrence[1], $selectedOccurrence[2], $selectedOccurrence[3]); return; } @@ -918,10 +899,10 @@ protected function nextYearly($amount = 1): void $currentYear += $this->interval; $currentMonth = 1; } - } while (!in_array($currentMonth, $this->byMonth)); + } while (!in_array((string) $currentMonth, $this->byMonth, true)); $this->currentDate = $this->currentDate->setDate( (int) $currentYear, - (int) $currentMonth, + $currentMonth, (int) $currentDayOfMonth )->modify($this->startTime()); } @@ -943,13 +924,14 @@ protected function parseRRule($rrule): void } foreach ($rrule as $key => $value) { - $key = strtoupper($key); + $key = strtoupper((string) $key); switch ($key) { case 'FREQ': - $value = strtolower($value); + $value = strtolower((string) $value); if (!in_array( $value, - ['secondly', 'minutely', 'hourly', 'daily', 'weekly', 'monthly', 'yearly'] + ['secondly', 'minutely', 'hourly', 'daily', 'weekly', 'monthly', 'yearly'], + true )) { throw new InvalidDataException('Unknown value for FREQ='.strtoupper($value)); } @@ -997,7 +979,7 @@ protected function parseRRule($rrule): void case 'BYDAY': $value = (array) $value; foreach ($value as $part) { - if (!preg_match('#^ (-|\+)? ([1-5])? (MO|TU|WE|TH|FR|SA|SU) $# xi', $part)) { + if (!preg_match('#^ (-|\+)? ([1-5])? (MO|TU|WE|TH|FR|SA|SU) $#xi', (string) $part)) { throw new InvalidDataException('Invalid part in BYDAY clause: '.$part); } } @@ -1020,7 +1002,7 @@ protected function parseRRule($rrule): void case 'BYYEARDAY': $this->byYearDay = (array) $value; foreach ($this->byYearDay as $byYearDay) { - if (!is_numeric($byYearDay) || (int) $byYearDay < -366 || 0 == (int) $byYearDay || (int) $byYearDay > 366) { + if (!is_numeric($byYearDay) || (int) $byYearDay < -366 || 0 === (int) $byYearDay || (int) $byYearDay > 366) { throw new InvalidDataException('BYYEARDAY in RRULE must have value(s) from 1 to 366, or -366 to -1!'); } } @@ -1029,7 +1011,7 @@ protected function parseRRule($rrule): void case 'BYWEEKNO': $this->byWeekNo = (array) $value; foreach ($this->byWeekNo as $byWeekNo) { - if (!is_numeric($byWeekNo) || (int) $byWeekNo < -53 || 0 == (int) $byWeekNo || (int) $byWeekNo > 53) { + if (!is_numeric($byWeekNo) || (int) $byWeekNo < -53 || 0 === (int) $byWeekNo || (int) $byWeekNo > 53) { throw new InvalidDataException('BYWEEKNO in RRULE must have value(s) from 1 to 53, or -53 to -1!'); } } @@ -1049,7 +1031,7 @@ protected function parseRRule($rrule): void break; case 'WKST': - $this->weekStart = strtoupper($value); + $this->weekStart = strtoupper((string) $value); break; default: @@ -1107,7 +1089,7 @@ protected function getMonthlyOccurrences(): array // that point and add it to the results. if ($this->byDay) { foreach ($this->byDay as $day) { - $dayName = $this->dayNames[$this->dayMap[substr($day, -2)]]; + $dayName = $this->dayNames[$this->dayMap[substr((string) $day, -2)]]; // Dayname will be something like 'wednesday'. Now we need to find // all wednesdays in this month. @@ -1128,8 +1110,8 @@ protected function getMonthlyOccurrences(): array // So now we have 'all wednesdays' for month. It is however // possible that the user only really wanted the 1st, 2nd or last // wednesday. - if (strlen($day) > 2) { - $offset = (int) substr($day, 0, -2); + if (strlen((string) $day) > 2) { + $offset = (int) substr((string) $day, 0, -2); if ($offset > 0) { // It is possible that the day does not exist, such as a @@ -1164,7 +1146,7 @@ protected function getMonthlyOccurrences(): array $byMonthDayResults[] = $monthDay; } else { // Negative values - $byMonthDayResults[] = $startDate->format('t') + 1 + $monthDay; + $byMonthDayResults[] = (int) $startDate->format('t') + 1 + $monthDay; } } } @@ -1182,19 +1164,8 @@ protected function getMonthlyOccurrences(): array $result = $this->addDailyOccurences($result); $result = array_unique($result, SORT_REGULAR); - $sortLex = function ($a, $b) { - if ($a[0] != $b[0]) { - return $a[0] - $b[0]; - } - if ($a[1] != $b[1]) { - return $a[1] - $b[1]; - } - if ($a[2] != $b[2]) { - return $a[2] - $b[2]; - } - - return $a[3] - $b[3]; - }; + // BYHOUR/BYMINUTE/BYSECOND values are numeric strings, so compare the tuples as integers. + $sortLex = static fn (array $a, array $b): int => array_map(intval(...), $a) <=> array_map(intval(...), $b); usort($result, $sortLex); // The last thing that needs checking is the BYSETPOS. If it's set, it @@ -1232,9 +1203,9 @@ protected function addDailyOccurences(array $result): array $minute = (int) $this->currentDate->format('i'); $second = (int) $this->currentDate->format('s'); foreach ($result as $day) { - $seconds = $this->bySecond ? $this->bySecond : [$second]; - $minutes = $this->byMinute ? $this->byMinute : [$minute]; - $hours = $this->byHour ? $this->byHour : [$hour]; + $seconds = $this->ruleValuesOrCurrent($this->bySecond, $second); + $minutes = $this->ruleValuesOrCurrent($this->byMinute, $minute); + $hours = $this->ruleValuesOrCurrent($this->byHour, $hour); foreach ($hours as $h) { foreach ($minutes as $m) { foreach ($seconds as $s) { @@ -1277,7 +1248,7 @@ protected function getDays(): array // The day may be preceded with a positive (+n) or // negative (-n) integer. However, this does not make // sense in 'weekly' so we ignore it here. - $recurrenceDays[] = $this->dayMap[substr($byDay, -2)]; + $recurrenceDays[] = $this->dayMap[substr((string) $byDay, -2)]; } return $recurrenceDays; diff --git a/lib/Splitter/VCard.php b/lib/Splitter/VCard.php index 40775a335..a802dbe75 100644 --- a/lib/Splitter/VCard.php +++ b/lib/Splitter/VCard.php @@ -22,13 +22,6 @@ */ class VCard implements SplitterInterface { - /** - * File handle. - * - * @var resource - */ - protected $input; - /** * Persistent parser. */ @@ -42,10 +35,12 @@ class VCard implements SplitterInterface * @param resource $input * @param int $options parser options, see the OPTIONS constants */ - public function __construct($input, int $options = 0) + public function __construct(/** + * File handle. + */ + protected $input, int $options = 0) { - $this->input = $input; - $this->parser = new MimeDir($input, $options); + $this->parser = new MimeDir($this->input, $options); } /** @@ -64,7 +59,7 @@ public function getNext(): ?Component if (!$object instanceof Component\VCard) { throw new VObject\ParseException('The supplied input contained non-VCARD data.'); } - } catch (VObject\EofException $e) { + } catch (VObject\EofException) { return null; } diff --git a/lib/TimeZoneUtil.php b/lib/TimeZoneUtil.php index b75a6310d..0c3bf8e57 100644 --- a/lib/TimeZoneUtil.php +++ b/lib/TimeZoneUtil.php @@ -50,9 +50,7 @@ private function __construct() private static function getInstance(): self { - if (null === self::$instance) { - self::$instance = new self(); - } + self::$instance ??= new self(); return self::$instance; } diff --git a/lib/TimezoneGuesser/FindFromOffsetName.php b/lib/TimezoneGuesser/FindFromOffsetName.php index 0916f1283..efefcc13a 100644 --- a/lib/TimezoneGuesser/FindFromOffsetName.php +++ b/lib/TimezoneGuesser/FindFromOffsetName.php @@ -44,7 +44,7 @@ public function find(string $tzid, ?bool $failIfUncertain = false): ?\DateTimeZo $tzid = new \DateTimeZone($tzid); return new \DateTimeZone(self::$offsetTimezones[$tzid->getName()]) ?? null; - } catch (\Exception $e) { + } catch (\Exception) { return null; } } diff --git a/lib/TimezoneGuesser/FindFromTimezoneIdentifier.php b/lib/TimezoneGuesser/FindFromTimezoneIdentifier.php index 4c2c6a5a3..bd306ad39 100644 --- a/lib/TimezoneGuesser/FindFromTimezoneIdentifier.php +++ b/lib/TimezoneGuesser/FindFromTimezoneIdentifier.php @@ -52,13 +52,13 @@ public function find(string $tzid, ?bool $failIfUncertain = false): ?\DateTimeZo try { if ( - in_array($tzid, $tzIdentifiers) + in_array($tzid, $tzIdentifiers, true) || preg_match('/^GMT(\+|-)([0-9]{4})$/', $tzid, $matches) - || in_array($tzid, $this->getIdentifiersBC()) + || in_array($tzid, $this->getIdentifiersBC(), true) ) { return new \DateTimeZone($tzid); } - } catch (\Exception $e) { + } catch (\Exception) { } return null; diff --git a/lib/TimezoneGuesser/FindFromTimezoneMap.php b/lib/TimezoneGuesser/FindFromTimezoneMap.php index 6df87de8d..78a3a8d2d 100644 --- a/lib/TimezoneGuesser/FindFromTimezoneMap.php +++ b/lib/TimezoneGuesser/FindFromTimezoneMap.php @@ -27,7 +27,7 @@ public function find(string $tzid, ?bool $failIfUncertain = false): ?\DateTimeZo if ($this->hasTzInMap($tzid)) { try { return new \DateTimeZone($this->getTzFromMap($tzid)); - } catch (\Exception $e) { + } catch (\Exception) { return null; } } @@ -43,7 +43,7 @@ public function find(string $tzid, ?bool $failIfUncertain = false): ?\DateTimeZo if ($this->hasTzInMap($tzidAlternate)) { try { return new \DateTimeZone($this->getTzFromMap($tzidAlternate)); - } catch (\Exception $e) { + } catch (\Exception) { return null; } } diff --git a/lib/TimezoneGuesser/GuessFromCustomizedTimeZone.php b/lib/TimezoneGuesser/GuessFromCustomizedTimeZone.php index f1f4f6899..56d872864 100644 --- a/lib/TimezoneGuesser/GuessFromCustomizedTimeZone.php +++ b/lib/TimezoneGuesser/GuessFromCustomizedTimeZone.php @@ -51,7 +51,7 @@ public function guess(VTimeZone $vtimezone, ?bool $failIfUncertain = false): ?\D // check standard $timestamp = $standardIterator->current()->getTimestamp(); $transitions = $tz->getTransitions($timestamp + $day, $timestamp + $day + 1); - if (empty($transitions)) { + if (false === $transitions || [] === $transitions) { continue; } @@ -68,7 +68,7 @@ public function guess(VTimeZone $vtimezone, ?bool $failIfUncertain = false): ?\D // check daylight $timestamp = $daylightIterator->current()->getTimestamp(); $transitions = $tz->getTransitions($timestamp + $day, $timestamp + $day + 1); - if (empty($transitions)) { + if (false === $transitions || [] === $transitions) { continue; } diff --git a/lib/TimezoneGuesser/GuessFromLicEntry.php b/lib/TimezoneGuesser/GuessFromLicEntry.php index fbd846e0f..82cfb0481 100644 --- a/lib/TimezoneGuesser/GuessFromLicEntry.php +++ b/lib/TimezoneGuesser/GuessFromLicEntry.php @@ -27,7 +27,7 @@ public function guess(VTimeZone $vtimezone, ?bool $failIfUncertain = false): ?\D // Libical generators may specify strings like // "SystemV/EST5EDT". For those we must remove the // SystemV part. - if ('SystemV/' === substr($lic, 0, 8)) { + if (str_starts_with($lic, 'SystemV/')) { $lic = substr($lic, 8); } diff --git a/lib/TimezoneGuesser/GuessFromMsTzId.php b/lib/TimezoneGuesser/GuessFromMsTzId.php index 392333cb0..82060bd27 100644 --- a/lib/TimezoneGuesser/GuessFromMsTzId.php +++ b/lib/TimezoneGuesser/GuessFromMsTzId.php @@ -105,7 +105,7 @@ public function guess(VTimeZone $vtimezone, ?bool $failIfUncertain = false): ?\D $cdoId = (int) $vtimezone->{'X-MICROSOFT-CDO-TZID'}->getValue(); // 2 can mean both Europe/Lisbon and Europe/Sarajevo. - if (2 === $cdoId && false !== strpos((string) $vtimezone->TZID, 'Sarajevo')) { + if (2 === $cdoId && str_contains((string) $vtimezone->TZID, 'Sarajevo')) { return new \DateTimeZone('Europe/Sarajevo'); } diff --git a/lib/VCardConverter.php b/lib/VCardConverter.php index ff8fe3f81..39969d558 100644 --- a/lib/VCardConverter.php +++ b/lib/VCardConverter.php @@ -38,10 +38,10 @@ public function convert(Component\VCard $input, int $targetVersion): Component\V return clone $input; } - if (!in_array($inputVersion, [Document::VCARD21, Document::VCARD30, Document::VCARD40])) { + if (!in_array($inputVersion, [Document::VCARD21, Document::VCARD30, Document::VCARD40], true)) { throw new \InvalidArgumentException('Only vCard 2.1, 3.0 and 4.0 are supported for the input data'); } - if (!in_array($targetVersion, [Document::VCARD30, Document::VCARD40])) { + if (!in_array($targetVersion, [Document::VCARD30, Document::VCARD40], true)) { throw new \InvalidArgumentException('You can only use vCard 3.0 or 4.0 for the target version'); } @@ -69,7 +69,7 @@ public function convert(Component\VCard $input, int $targetVersion): Component\V protected function convertProperty(Component\VCard $input, Component\VCard $output, Property $property, int $targetVersion): void { // Skipping these, those are automatically added. - if (in_array($property->name, ['VERSION', 'PRODID'])) { + if (in_array($property->name, ['VERSION', 'PRODID'], true)) { return; } @@ -93,7 +93,7 @@ protected function convertProperty(Component\VCard $input, Component\VCard $outp ); if (Document::VCARD30 === $targetVersion) { - if ($property instanceof Uri && in_array($property->name, ['PHOTO', 'LOGO', 'SOUND'])) { + if ($property instanceof Uri && in_array($property->name, ['PHOTO', 'LOGO', 'SOUND'], true)) { /** @var Uri $newProperty */ $newProperty = $this->convertUriToBinary($output, $newProperty); } elseif ($property instanceof Property\VCard\DateAndOrTime) { @@ -111,7 +111,7 @@ protected function convertProperty(Component\VCard $input, Component\VCard $outp $newProperty['X-APPLE-OMIT-YEAR'] = '1604'; } - if ('ANNIVERSARY' == $newProperty->name) { + if ('ANNIVERSARY' === $newProperty->name) { // Microsoft non-standard anniversary $newProperty->name = 'X-ANNIVERSARY'; @@ -127,7 +127,7 @@ protected function convertProperty(Component\VCard $input, Component\VCard $outp $output->add('ITEM'.$x.'.X-ABLABEL', '_$!!$_'); } } elseif ('KIND' === $property->name) { - switch (strtolower($property->getValue())) { + switch (strtolower((string) $property->getValue())) { case 'org': // vCard 3.0 does not have an equivalent to KIND:ORG, // but apple has an extension that means the same @@ -149,7 +149,7 @@ protected function convertProperty(Component\VCard $input, Component\VCard $outp } } elseif (Document::VCARD40 === $targetVersion) { // These properties were removed in vCard 4.0 - if (in_array($property->name, ['NAME', 'MAILER', 'LABEL', 'CLASS'])) { + if (in_array($property->name, ['NAME', 'MAILER', 'LABEL', 'CLASS'], true)) { return; } @@ -171,12 +171,12 @@ protected function convertProperty(Component\VCard $input, Component\VCard $outp } switch ($property->name) { case 'X-ABSHOWAS': - if ('COMPANY' === strtoupper($property->getValue())) { + if ('COMPANY' === strtoupper((string) $property->getValue())) { $newProperty = $output->createProperty('KIND', 'ORG'); } break; case 'X-ADDRESSBOOKSERVER-KIND': - if ('GROUP' === strtoupper($property->getValue())) { + if ('GROUP' === strtoupper((string) $property->getValue())) { $newProperty = $output->createProperty('KIND', 'GROUP'); } break; @@ -274,10 +274,11 @@ protected function convertBinaryToUri(Component\VCard $output, Binary $newProper $newTypes = []; foreach ($parameters['TYPE']->getParts() as $typePart) { if (in_array( - strtoupper($typePart), - ['JPEG', 'PNG', 'GIF'] + strtoupper((string) $typePart), + ['JPEG', 'PNG', 'GIF'], + true )) { - $mimeType = 'image/'.strtolower($typePart); + $mimeType = 'image/'.strtolower((string) $typePart); } else { $newTypes[] = $typePart; } @@ -292,7 +293,7 @@ protected function convertBinaryToUri(Component\VCard $output, Binary $newProper } } - $newProperty->setValue('data:'.$mimeType.';base64,'.base64_encode($value)); + $newProperty->setValue('data:'.$mimeType.';base64,'.base64_encode((string) $value)); return $newProperty; } @@ -313,7 +314,7 @@ protected function convertUriToBinary(Component\VCard $output, Uri $newProperty) $value = $newProperty->getValue(); // Only converting data: uris - if ('data:' !== substr($value, 0, 5)) { + if (!str_starts_with((string) $value, 'data:')) { return $newProperty; } @@ -325,12 +326,12 @@ protected function convertUriToBinary(Component\VCard $output, Uri $newProperty) 'BINARY' ); - $mimeType = substr($value, 5, strpos($value, ',') - 5); + $mimeType = substr((string) $value, 5, strpos((string) $value, ',') - 5); if (strpos($mimeType, ';')) { $mimeType = substr($mimeType, 0, strpos($mimeType, ';')); - $newProperty->setValue(base64_decode(substr($value, strpos($value, ',') + 1))); + $newProperty->setValue(base64_decode(substr((string) $value, strpos((string) $value, ',') + 1), true)); } else { - $newProperty->setValue(substr($value, strpos($value, ',') + 1)); + $newProperty->setValue(substr((string) $value, strpos((string) $value, ',') + 1)); } unset($value); @@ -367,7 +368,7 @@ protected function convertParameters40(Property $newProperty, array $parameters) // that's now PREF=1. case 'TYPE': foreach ($param->getParts() as $paramPart) { - if ('PREF' === strtoupper($paramPart)) { + if ('PREF' === strtoupper((string) $paramPart)) { $newProperty->add('PREF', '1'); } else { $newProperty->add($param->name, $paramPart); @@ -402,7 +403,7 @@ protected function convertParameters30(Property $newProperty, array $parameters) case 'ENCODING': // This value only existed in vCard 2.1, and should be // removed for anything else. - if ('QUOTED-PRINTABLE' !== strtoupper($param->getValue())) { + if ('QUOTED-PRINTABLE' !== strtoupper((string) $param->getValue())) { $newProperty->add($param->name, $param->getParts()); } break; @@ -413,7 +414,7 @@ protected function convertParameters30(Property $newProperty, array $parameters) * Any other PREF numbers we'll drop. */ case 'PREF': - if ('1' == $param->getValue()) { + if ('1' === (string) $param->getValue()) { $newProperty->add('TYPE', 'PREF'); } break; diff --git a/rector.php b/rector.php new file mode 100644 index 000000000..bfb4215a9 --- /dev/null +++ b/rector.php @@ -0,0 +1,20 @@ +withPaths([ + __DIR__.'/lib', + __DIR__.'/tests', + ]) + // uncomment to reach your current PHP version + ->withPhpSets(false, true) + ->withRules([ + DataProviderAnnotationToAttributeRector::class, + ]) + ->withTypeCoverageLevel(0) + ->withDeadCodeLevel(0) + ->withCodeQualityLevel(0); diff --git a/tests/VObject/CliTest.php b/tests/VObject/CliTest.php index c57d25226..a75de69e9 100644 --- a/tests/VObject/CliTest.php +++ b/tests/VObject/CliTest.php @@ -2,6 +2,7 @@ namespace Sabre\VObject; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; /** @@ -154,7 +155,7 @@ public function testConvertJson(): void public function testConvertJCardPretty(): void { if (version_compare(PHP_VERSION, '5.4.0') < 0) { - $this->markTestSkipped('This test required PHP 5.4.0'); + self::markTestSkipped('This test required PHP 5.4.0'); } $inputStream = fopen('php://memory', 'r+'); @@ -272,44 +273,58 @@ public function testConvertMimeDir(): void ); } - public function testConvertDefaultFormats(): void + public static function provideFormats(): array { - $outputFile = $this->sabreTempDir.'bar.json'; - - self::assertEquals( - 2, - $this->cli->main(['vobject', 'convert', 'foo.json', $outputFile]) - ); - - self::assertEquals('json', $this->cli->inputFormat); - self::assertEquals('json', $this->cli->format); + return [ + ['foo.json', 'bar.json', 'json'], + ['foo.ics', 'bar.ics', 'mimedir'], + ]; } - public function testConvertDefaultFormats2(): void + #[DataProvider('provideFormats')] + public function testConvertDefaultFormats($inputFilename, $outputFilename, $format): void { - $outputFile = $this->sabreTempDir.'bar.ics'; + $triggeredWarning = null; - self::assertEquals( - 2, - $this->cli->main(['vobject', 'convert', 'foo.ics', $outputFile]) - ); + // Set an error handler to catch the native PHP Warning + set_error_handler(function (int $errno, string $errstr) use (&$triggeredWarning) { + $triggeredWarning = $errstr; - self::assertEquals('mimedir', $this->cli->inputFormat); - self::assertEquals('mimedir', $this->cli->format); + return true; // Prevents the error from propagating further + }, E_WARNING); + + $outputFile = $this->sabreTempDir.$outputFilename; + + try { + self::assertEquals( + 2, + $this->cli->main(['vobject', 'convert', $inputFilename, $outputFile]) + ); + } finally { + restore_error_handler(); + } + + self::assertNotNull($triggeredWarning, 'A PHP warning was expected but never triggered.'); + self::assertStringContainsString( + "fopen($inputFilename): Failed to open stream: No such file or directory", + $triggeredWarning + ); + self::assertEquals($format, $this->cli->inputFormat); + self::assertEquals($format, $this->cli->format); } public function testVCard3040(): void { $inputStream = fopen('php://memory', 'r+'); - fwrite($inputStream, <<cli->stdin = $inputStream; @@ -341,14 +356,14 @@ public function testVCard4030(): void { $inputStream = fopen('php://memory', 'r+'); - fwrite($inputStream, <<cli->stdin = $inputStream; @@ -380,14 +395,14 @@ public function testVCard4021(): void { $inputStream = fopen('php://memory', 'r+'); - fwrite($inputStream, <<cli->stdin = $inputStream; @@ -402,15 +417,15 @@ public function testValidate(): void { $inputStream = fopen('php://memory', 'r+'); - fwrite($inputStream, <<cli->stdin = $inputStream; @@ -426,12 +441,12 @@ public function testValidateFail(): void { $inputStream = fopen('php://memory', 'r+'); - fwrite($inputStream, <<cli->stdin = $inputStream; @@ -466,12 +481,12 @@ public function testRepair(): void { $inputStream = fopen('php://memory', 'r+'); - fwrite($inputStream, <<cli->stdin = $inputStream; diff --git a/tests/VObject/Component/AvailableTest.php b/tests/VObject/Component/AvailableTest.php index 98202ffcb..68c9d90f0 100644 --- a/tests/VObject/Component/AvailableTest.php +++ b/tests/VObject/Component/AvailableTest.php @@ -13,26 +13,26 @@ class AvailableTest extends TestCase { public function testAvailableComponent(): void { - $vcal = <<AVAILABLE); } public function testGetEffectiveStartEnd(): void { - $vcal = <<isInTimeRange($start, $end)); } - public function timeRangeTestData(): array + public static function timeRangeTestData(): array { $tests = []; diff --git a/tests/VObject/Component/VAvailabilityTest.php b/tests/VObject/Component/VAvailabilityTest.php index 67499e98e..d8040f851 100644 --- a/tests/VObject/Component/VAvailabilityTest.php +++ b/tests/VObject/Component/VAvailabilityTest.php @@ -14,12 +14,12 @@ class VAvailabilityTest extends TestCase { public function testVAvailabilityComponent(): void { - $vcal = <<VAVAILABILITY); @@ -27,14 +27,14 @@ public function testVAvailabilityComponent(): void public function testGetEffectiveStartEnd(): void { - $vcal = <<VAVAILABILITY->AVAILABLE); @@ -241,91 +241,91 @@ public function testRFCxxxSection3Part1AvailablePropRequired(): void { // UID, DTSTAMP and DTSTART are present. self::assertIsValid(Reader::read( - <<validate(); if ($validationResult) { - $messages = array_map(function ($item) { return $item['message']; }, $validationResult); - $this->fail('Failed to assert that the supplied document is a valid document. Validation messages: '.implode(', ', $messages)); + $messages = array_map(fn ($item) => $item['message'], $validationResult); + self::fail('Failed to assert that the supplied document is a valid document. Validation messages: '.implode(', ', $messages)); } self::assertEmpty($document->validate()); } @@ -425,17 +425,17 @@ protected function assertIsNotValid(VObject\Document $document): void protected function template(array $properties) { return $this->_template( - <<_template( - <<isInTimeRange($start, $end)); } - public function timeRangeTestData(): array + public static function timeRangeTestData(): array { $tests = []; diff --git a/tests/VObject/Component/VJournalTest.php b/tests/VObject/Component/VJournalTest.php index 98f478896..9741a16b6 100644 --- a/tests/VObject/Component/VJournalTest.php +++ b/tests/VObject/Component/VJournalTest.php @@ -2,14 +2,13 @@ namespace Sabre\VObject\Component; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Sabre\VObject\Reader; class VJournalTest extends TestCase { - /** - * @dataProvider timeRangeTestData - */ + #[DataProvider('timeRangeTestData')] public function testInTimeRange(VJournal $vtodo, \DateTime $start, \DateTime $end, bool $outcome): void { self::assertEquals($outcome, $vtodo->isInTimeRange($start, $end)); @@ -68,7 +67,7 @@ public function testValidateBroken(): void ); } - public function timeRangeTestData(): array + public static function timeRangeTestData(): array { $calendar = new VCalendar(); diff --git a/tests/VObject/Component/VTimeZoneTest.php b/tests/VObject/Component/VTimeZoneTest.php index 19a88cb74..bb8102d89 100644 --- a/tests/VObject/Component/VTimeZoneTest.php +++ b/tests/VObject/Component/VTimeZoneTest.php @@ -67,7 +67,7 @@ public function testGetEmptyTimeZone() $tz = new \DateTimeZone(date_default_timezone_get()); - $this->assertEquals( + self::assertEquals( $tz, $obj->VTIMEZONE->getTimeZone() ); diff --git a/tests/VObject/Component/VTodoTest.php b/tests/VObject/Component/VTodoTest.php index 899d93982..c8be4f692 100644 --- a/tests/VObject/Component/VTodoTest.php +++ b/tests/VObject/Component/VTodoTest.php @@ -2,20 +2,19 @@ namespace Sabre\VObject\Component; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Sabre\VObject\Reader; class VTodoTest extends TestCase { - /** - * @dataProvider timeRangeTestData - */ + #[DataProvider('timeRangeTestData')] public function testInTimeRange(VTodo $vtodo, \DateTime $start, \DateTime $end, bool $outcome): void { self::assertEquals($outcome, $vtodo->isInTimeRange($start, $end)); } - public function timeRangeTestData(): array + public static function timeRangeTestData(): array { $tests = []; diff --git a/tests/VObject/ComponentTest.php b/tests/VObject/ComponentTest.php index c48480983..a9be399b5 100644 --- a/tests/VObject/ComponentTest.php +++ b/tests/VObject/ComponentTest.php @@ -2,6 +2,7 @@ namespace Sabre\VObject; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Sabre\VObject\Component\VCalendar; use Sabre\VObject\Component\VCard; @@ -459,8 +460,9 @@ public function testRemoveNotFound(): void } /** - * @dataProvider ruleData + * @param string[] $componentList */ + #[DataProvider('ruleData')] public function testValidateRules(array $componentList, int $errorCount): void { $vcard = new VCard(); @@ -546,7 +548,7 @@ public function testValidateRepairShouldDeduplicatePropertiesWhenValuesAreEqual( self::assertCount(1, $component->GIR); } - public function ruleData(): array + public static function ruleData(): array { return [ [[], 2], diff --git a/tests/VObject/DateTimeParserTest.php b/tests/VObject/DateTimeParserTest.php index cdf0fe990..077d2e1fc 100644 --- a/tests/VObject/DateTimeParserTest.php +++ b/tests/VObject/DateTimeParserTest.php @@ -2,6 +2,7 @@ namespace Sabre\VObject; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class DateTimeParserTest extends TestCase @@ -167,8 +168,9 @@ public function testParseICalendarDateInvalidDate(): void } /** - * @dataProvider vcardDates + * @param array $output */ + #[DataProvider('vcardDates')] public function testVCardDate(string $input, array $output): void { self::assertEquals( @@ -189,7 +191,7 @@ public function testBadVCardTime(): void DateTimeParser::parseVCardTime('23:12:166'); } - public function vcardDates(): array + public static function vcardDates(): array { return [ [ diff --git a/tests/VObject/ITip/BrokerTester.php b/tests/VObject/ITip/BrokerTester.php index cc01ed3f9..43eb91814 100644 --- a/tests/VObject/ITip/BrokerTester.php +++ b/tests/VObject/ITip/BrokerTester.php @@ -40,6 +40,7 @@ public function parse($oldMessage, $newMessage, array $expected = [], string $cu $message->message->serialize() ); } else { + // @phpstan-ignore property.dynamicName self::assertEquals($val, $message->$key); } } @@ -59,8 +60,9 @@ public function process($input, $existingObject = null, $expected = false): void $vcal = Reader::read($input); $mainComponent = new VEvent($vcal, 'VEVENT'); - foreach ($vcal->getComponents() as $mainComponent) { - if ('VEVENT' === $mainComponent->name) { + foreach ($vcal->getComponents() as $nextComponent) { + if ('VEVENT' === $nextComponent->name) { + $mainComponent = $nextComponent; break; } } @@ -76,7 +78,7 @@ public function process($input, $existingObject = null, $expected = false): void $message->sender = $mainComponent->ATTENDEE->getValue(); $message->senderName = isset($mainComponent->ATTENDEE['CN']) ? $mainComponent->ATTENDEE['CN']->getValue() : null; $message->recipient = $mainComponent->ORGANIZER->getValue(); - $message->recipientName = isset($mainComponent->ORGANIZER['CN']) ? $mainComponent->ORGANIZER['CN'] : null; + $message->recipientName = $mainComponent->ORGANIZER['CN'] ?? null; } $broker = new Broker(); diff --git a/tests/VObject/ITip/BrokerTimezoneInParseEventInfoWithoutMasterTest.php b/tests/VObject/ITip/BrokerTimezoneInParseEventInfoWithoutMasterTest.php index e3f18f15e..c0afe4578 100644 --- a/tests/VObject/ITip/BrokerTimezoneInParseEventInfoWithoutMasterTest.php +++ b/tests/VObject/ITip/BrokerTimezoneInParseEventInfoWithoutMasterTest.php @@ -70,7 +70,6 @@ public function testTimezoneInParseEventInfoWithoutMaster(): void $broker = new Broker(); $reflectionMethod = new \ReflectionMethod($broker, 'parseEventInfo'); - $reflectionMethod->setAccessible(true); $data = $reflectionMethod->invoke($broker, $calendar); self::assertInstanceOf('DateTimeZone', $data['timezone']); self::assertEquals('Europe/Minsk', $data['timezone']->getName()); diff --git a/tests/VObject/InvalidValueParamTest.php b/tests/VObject/InvalidValueParamTest.php index 744fb193c..a73b7229d 100644 --- a/tests/VObject/InvalidValueParamTest.php +++ b/tests/VObject/InvalidValueParamTest.php @@ -26,7 +26,7 @@ public function testWorkaround() ICS; $doc = Reader::read($event); - $this->assertEquals("LOCATION:EXAMPLE\r\n", $doc->VEVENT->LOCATION->serialize()); + self::assertEquals("LOCATION:EXAMPLE\r\n", $doc->VEVENT->LOCATION->serialize()); } public function testInvalidValue() @@ -49,6 +49,6 @@ public function testInvalidValue() ICS; $doc = Reader::read($event); - $this->assertEquals("LOCATION:consectetur adipiscing elit\,sed do eiusmod tempor\r\n", $doc->VEVENT->LOCATION->serialize()); + self::assertEquals("LOCATION:consectetur adipiscing elit\,sed do eiusmod tempor\r\n", $doc->VEVENT->LOCATION->serialize()); } } diff --git a/tests/VObject/JCalTest.php b/tests/VObject/JCalTest.php index fa3479665..7624b8f84 100644 --- a/tests/VObject/JCalTest.php +++ b/tests/VObject/JCalTest.php @@ -97,7 +97,7 @@ public function testToJCal(): void 'sequence', new \stdClass(), 'integer', 5, ], [ - 'freebusy', new \stdClass(), 'period', ['2013-05-26T21:02:13', 'PT1H'], ['2013-06-26T12:00:00', '2013-06-26T13:00:00'], + 'freebusy', new \stdClass(), 'period', ['2013-05-26T21:02:13Z', 'PT1H'], ['2013-06-26T12:00:00Z', '2013-06-26T13:00:00Z'], ], [ 'url', new \stdClass(), 'uri', 'http://example.org/', diff --git a/tests/VObject/Parser/JsonTest.php b/tests/VObject/Parser/JsonTest.php index 392cc7c11..c50af87c4 100644 --- a/tests/VObject/Parser/JsonTest.php +++ b/tests/VObject/Parser/JsonTest.php @@ -261,7 +261,7 @@ public function testRoundTripJCal(): void 'sequence', new \stdClass(), 'integer', 5, ], [ - 'freebusy', new \stdClass(), 'period', ['2013-05-26T21:02:13', 'PT1H'], ['2013-06-26T12:00:00', '2013-06-26T13:00:00'], + 'freebusy', new \stdClass(), 'period', ['2013-05-26T21:02:13Z', 'PT1H'], ['2013-06-26T12:00:00Z', '2013-06-26T13:00:00Z'], ], [ 'url', new \stdClass(), 'uri', 'http://example.org/', @@ -330,7 +330,7 @@ public function testRoundTripJCal(): void ATTENDEE;CN=Dominik;PARTSTAT=DECLINED:mailto:dominik@example.org GEO:51.96668;7.61876 SEQUENCE:5 -FREEBUSY:20130526T210213/PT1H,20130626T120000/20130626T130000 +FREEBUSY:20130526T210213Z/PT1H,20130626T120000Z/20130626T130000Z URL;VALUE=URI:http://example.org/ TZOFFSETFROM:+0500 RRULE:FREQ=WEEKLY;BYDAY=MO,TU diff --git a/tests/VObject/Parser/MimeDirTest.php b/tests/VObject/Parser/MimeDirTest.php index f4e2ed11c..d2e2aef87 100644 --- a/tests/VObject/Parser/MimeDirTest.php +++ b/tests/VObject/Parser/MimeDirTest.php @@ -2,6 +2,7 @@ namespace Sabre\VObject\Parser; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Sabre\VObject\Component\VCalendar; use Sabre\VObject\ParseException; @@ -101,7 +102,7 @@ public function testDecodeUnsupportedInlineCharset(): void $mimeDir->parse($vcard); } - public function provideEmptyParserInput(): array + public static function provideEmptyParserInput(): array { return [ [null, 'No input provided to parse'], @@ -109,9 +110,7 @@ public function provideEmptyParserInput(): array ]; } - /** - * @dataProvider provideEmptyParserInput - */ + #[DataProvider('provideEmptyParserInput')] public function testParseEmpty($input, $expectedExceptionMessage): void { $this->expectException(ParseException::class); @@ -188,9 +187,8 @@ public function testParsingTwiceSameContent(): void /** * @covers \Sabre\VObject\Parser\MimeDir::readProperty - * - * @dataProvider provideBrokenVCalendar */ + #[DataProvider('provideBrokenVCalendar')] public function testBrokenMultilineContentDoesNotBreakImportWhenSetToIgnoreBrokenLines(string $vcalendar): void { $mimeDir = new MimeDir(null, MimeDir::OPTION_IGNORE_INVALID_LINES); @@ -201,10 +199,9 @@ public function testBrokenMultilineContentDoesNotBreakImportWhenSetToIgnoreBroke /** * @covers \Sabre\VObject\Parser\MimeDir::readProperty * - * @dataProvider provideBrokenVCalendar - * * @param string $vcalendar */ + #[DataProvider('provideBrokenVCalendar')] public function testBrokenMultilineContentDoesBreakImport($vcalendar): void { $mimeDir = new MimeDir(); @@ -212,7 +209,7 @@ public function testBrokenMultilineContentDoesBreakImport($vcalendar): void $mimeDir->parse($vcalendar); } - public function provideBrokenVCalendar(): array + public static function provideBrokenVCalendar(): array { return [[<<parse($iCal); + // @phpstan-ignore property.dynamicName self::assertEquals('test', $vevent->VEVENT->{0}->getValue()); } diff --git a/tests/VObject/Parser/UnfoldingTest.php b/tests/VObject/Parser/UnfoldingTest.php index 8d751ae7a..1bccfb116 100644 --- a/tests/VObject/Parser/UnfoldingTest.php +++ b/tests/VObject/Parser/UnfoldingTest.php @@ -36,7 +36,7 @@ public function testFixUnfoldingICS() $mimeDir = new MimeDir(); $vcard = $mimeDir->parse($vcard, Reader::OPTION_FIX_UNFOLDING); - $this->assertNotNull($vcard->children()[0]->{'X-APPLE-STRUCTURED-LOCATION'}->getValue()); + self::assertNotNull($vcard->children()[0]->{'X-APPLE-STRUCTURED-LOCATION'}->getValue()); } public function testNotFixUnfolding() @@ -94,6 +94,6 @@ public function testNotFixUnknownProperty() $vcard = (new MimeDir())->parse($vcard); - $this->assertNotNull($vcard->children()[0]->CONFERENCE->getValue()); + self::assertNotNull($vcard->children()[0]->CONFERENCE->getValue()); } } diff --git a/tests/VObject/Parser/XmlTest.php b/tests/VObject/Parser/XmlTest.php index 6491d087b..223b0f105 100644 --- a/tests/VObject/Parser/XmlTest.php +++ b/tests/VObject/Parser/XmlTest.php @@ -684,7 +684,7 @@ public function testRFC6321Section3Part6Part9(): void - 2011-05-17T12:00:00 + 2011-05-17T12:00:00Z P1H @@ -693,7 +693,7 @@ public function testRFC6321Section3Part6Part9(): void XML, 'BEGIN:VCALENDAR'."\n". - 'FREEBUSY:20110517T120000/P1H'."\n". + 'FREEBUSY:20110517T120000Z/P1H'."\n". 'END:VCALENDAR'."\n" ); @@ -705,8 +705,8 @@ public function testRFC6321Section3Part6Part9(): void - 2011-05-17T12:00:00 - 2012-05-17T12:00:00 + 2011-05-17T12:00:00Z + 2012-05-17T12:00:00Z @@ -714,7 +714,7 @@ public function testRFC6321Section3Part6Part9(): void XML, 'BEGIN:VCALENDAR'."\n". - 'FREEBUSY:20110517T120000/20120517T120000'."\n". + 'FREEBUSY:20110517T120000Z/20120517T120000Z'."\n". 'END:VCALENDAR'."\n" ); } @@ -2704,6 +2704,6 @@ protected function assertXMLReflexivelyEqualsToMimeDir(string $xml, string $mime self::assertXMLEqualsToMimeDir($xml, $mimedir); $component = VObject\Reader::read($mimedir); - self::assertXmlStringEqualsXmlString($xml, VObject\Writer::writeXML($component)); + self::assertXmlStringEqualsXmlString($xml, VObject\Writer::writeXml($component)); } } diff --git a/tests/VObject/Property/ICalendar/CalAddressTest.php b/tests/VObject/Property/ICalendar/CalAddressTest.php index b774f4fbc..a81656d25 100644 --- a/tests/VObject/Property/ICalendar/CalAddressTest.php +++ b/tests/VObject/Property/ICalendar/CalAddressTest.php @@ -2,13 +2,12 @@ namespace Sabre\VObject\Property\ICalendar; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class CalAddressTest extends TestCase { - /** - * @dataProvider values - */ + #[DataProvider('values')] public function testGetNormalizedValue(string $expected, string $input): void { $vobj = new \Sabre\VObject\Component\VCalendar(); @@ -20,7 +19,7 @@ public function testGetNormalizedValue(string $expected, string $input): void ); } - public function values(): array + public static function values(): array { return [ ['mailto:a@b.com', 'mailto:a@b.com'], diff --git a/tests/VObject/Property/ICalendar/DateTimeTest.php b/tests/VObject/Property/ICalendar/DateTimeTest.php index 3986ec32a..17563f0da 100644 --- a/tests/VObject/Property/ICalendar/DateTimeTest.php +++ b/tests/VObject/Property/ICalendar/DateTimeTest.php @@ -2,6 +2,7 @@ namespace Sabre\VObject\Property\ICalendar; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Sabre\VObject\Component\VCalendar; use Sabre\VObject\InvalidDataException; @@ -102,7 +103,7 @@ public function testSetDateTimeDATE(): void self::assertEquals('19850704', (string) $elem); self::assertNull($elem['TZID']); - self::assertEquals('DATE', (string) $elem['VALUE']); + self::assertEquals('DATE', $elem['VALUE']); self::assertFalse($elem->hasTime()); } @@ -318,12 +319,41 @@ public function testUpdateValueParameter(): void self::assertEquals("DTSTART;VALUE=DATE:20130607\r\n", $dtStart->serialize()); } - public function testValidate(): void + public static function validateDateTimeProvider(): array { - $exDate = $this->vcal->createProperty('EXDATE', '-00011130T143000Z'); + return [ + [ + '-00011130T143000Z', + 1, + 3, + ], + [ + '20260627T100000', + 0, + 0, + ], + [ + '20260627T100000Z', + 0, + 0, + ], + [ + '20260627T100000Z+0200', + 1, + 3, + ], + ]; + } + + #[DataProvider('validateDateTimeProvider')] + public function testValidate(string $invalidDateTime, int $expectedMessageCount, int $expectedMessageLevel): void + { + $exDate = $this->vcal->createProperty('EXDATE', $invalidDateTime); $messages = $exDate->validate(); - self::assertCount(1, $messages); - self::assertEquals(3, $messages[0]['level']); + self::assertCount($expectedMessageCount, $messages); + if ($expectedMessageCount > 0) { + self::assertEquals($expectedMessageLevel, $messages[0]['level']); + } } /** diff --git a/tests/VObject/Property/TextTest.php b/tests/VObject/Property/TextTest.php index 0fa320bfe..aadbd4141 100644 --- a/tests/VObject/Property/TextTest.php +++ b/tests/VObject/Property/TextTest.php @@ -66,14 +66,14 @@ public function testSerializeQuotedPrintableFold(): void public function testValidateMinimumPropValue(): void { - $vcard = <<validate()); diff --git a/tests/VObject/Property/VCard/DateAndOrTimeTest.php b/tests/VObject/Property/VCard/DateAndOrTimeTest.php index 8e2cb3207..b85e915f1 100644 --- a/tests/VObject/Property/VCard/DateAndOrTimeTest.php +++ b/tests/VObject/Property/VCard/DateAndOrTimeTest.php @@ -2,15 +2,14 @@ namespace Sabre\VObject\Property\VCard; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Sabre\VObject; use Sabre\VObject\Reader; class DateAndOrTimeTest extends TestCase { - /** - * @dataProvider dates - */ + #[DataProvider('dates')] public function testGetJsonValue(string $input, string $output): void { $vcard = new VObject\Component\VCard(); @@ -19,7 +18,7 @@ public function testGetJsonValue(string $input, string $output): void self::assertEquals([$output], $prop->getJsonValue()); } - public function dates(): array + public static function dates(): array { return [ [ diff --git a/tests/VObject/ReaderTest.php b/tests/VObject/ReaderTest.php index 336a291ab..f66efa574 100644 --- a/tests/VObject/ReaderTest.php +++ b/tests/VObject/ReaderTest.php @@ -318,7 +318,7 @@ public function testReadForgiving(): void $caught = false; try { Reader::read(implode("\r\n", $data)); - } catch (ParseException $e) { + } catch (ParseException) { $caught = true; } @@ -348,7 +348,7 @@ public function testReadWithInvalidLine(): void $caught = false; try { Reader::read(implode("\r\n", $data)); - } catch (ParseException $e) { + } catch (ParseException) { $caught = true; } diff --git a/tests/VObject/Recur/EventIterator/HandleRDateExpandTest.php b/tests/VObject/Recur/EventIterator/HandleRDateExpandTest.php index 4f434dd2a..aca783d3c 100644 --- a/tests/VObject/Recur/EventIterator/HandleRDateExpandTest.php +++ b/tests/VObject/Recur/EventIterator/HandleRDateExpandTest.php @@ -51,7 +51,7 @@ public function testExpand(): void new \DateTimeImmutable('2015-10-20', $utc), ]; - $result = array_map(function ($ev) {return $ev->DTSTART->getDateTime(); }, $result); + $result = array_map(fn ($ev) => $ev->DTSTART->getDateTime(), $result); self::assertEquals($expected, $result); } } diff --git a/tests/VObject/Recur/EventIterator/MainTest.php b/tests/VObject/Recur/EventIterator/MainTest.php index 022df4a3b..e966f1c38 100644 --- a/tests/VObject/Recur/EventIterator/MainTest.php +++ b/tests/VObject/Recur/EventIterator/MainTest.php @@ -33,7 +33,7 @@ public function testValues(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); self::assertTrue($it->isInfinite()); } @@ -58,7 +58,7 @@ public function testInvalidFreq(): void $ev->add($dtStart); $vcal->add($ev); - new EventIterator($vcal, (string) $ev->UID); + new EventIterator($vcal, $ev->UID); } /** @@ -252,7 +252,7 @@ public function testDailyByDayByHour(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); // Grabbing the next 12 items $max = 12; @@ -304,7 +304,7 @@ public function testDailyByHour(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); // Grabbing the next 12 items $max = 12; @@ -356,7 +356,7 @@ public function testDailyByDay(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); // Grabbing the next 12 items $max = 12; @@ -408,7 +408,7 @@ public function testWeekly(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); // Max is to prevent overflow $max = 12; @@ -458,7 +458,7 @@ public function testWeeklyByDayByHour(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); // Grabbing the next 12 items $max = 15; @@ -513,7 +513,7 @@ public function testWeeklyByDaySpecificHour(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); // Grabbing the next 12 items $max = 12; @@ -565,7 +565,7 @@ public function testWeeklyByDay(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); // Grabbing the next 12 items $max = 12; @@ -617,7 +617,7 @@ public function testMonthly(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); $max = 14; $result = []; @@ -661,7 +661,7 @@ public function testMonthlyEndOfMonth(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); $max = 14; $result = []; @@ -719,7 +719,7 @@ public function testMonthlyByMonthDay(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); $max = 14; $result = []; @@ -772,7 +772,7 @@ public function testMonthlyByDay(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); $max = 20; $result = []; @@ -827,7 +827,7 @@ public function testMonthlyByDayByMonthDay(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); $max = 20; $result = []; @@ -876,7 +876,7 @@ public function testMonthlyByDayBySetPos(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); $max = 20; $result = []; @@ -930,7 +930,7 @@ public function testYearly(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); $max = 20; $result = []; @@ -979,7 +979,7 @@ public function testYearlyLeapYear(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); $max = 20; $result = []; @@ -1021,7 +1021,7 @@ public function testYearlyByMonth(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); $max = 20; $result = []; @@ -1068,7 +1068,7 @@ public function testYearlyByMonthByDay(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); $max = 20; $result = []; @@ -1115,7 +1115,7 @@ public function testFastForward(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); // The idea is that we're fast-forwarding too far in the future, so // there will be no results left. @@ -1157,7 +1157,7 @@ public function testFastForwardAllDayEventThatStopAtTheStartTime(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); $it->fastForward(new \DateTimeImmutable('2011-04-05T000000', new \DateTimeZone('UTC'))); @@ -1199,7 +1199,7 @@ public function testComplexExclusions(): void $vcal->add($ev); - $it = new EventIterator($vcal, (string) $ev->UID); + $it = new EventIterator($vcal, $ev->UID); $max = 20; $result = []; diff --git a/tests/VObject/Recur/FastForwardBeforeTest.php b/tests/VObject/Recur/FastForwardBeforeTest.php index 0426cc5ec..8cb62f8d6 100644 --- a/tests/VObject/Recur/FastForwardBeforeTest.php +++ b/tests/VObject/Recur/FastForwardBeforeTest.php @@ -15,7 +15,7 @@ private function fastForward(RRuleIterator $ruleIterator, \DateTimeInterface $ff $ruleIterator->fastForwardBefore($ffDate); $ru = getrusage(); $endTime = $ru['ru_utime.tv_sec'] * 1000000 + $ru['ru_utime.tv_usec']; - $this->assertLessThan(self::FF_TIMEOUT, $endTime - $startTime); + self::assertLessThan(self::FF_TIMEOUT, $endTime - $startTime); } public function testFastForwardBeforeYearlyBasic() @@ -33,50 +33,50 @@ public function testFastForwardBeforeYearlyBasic() ->setDate(99998, 10, 23) ->setTime(0, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += $year; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); // It's a leap $expected += $year + 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += $year; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += $year; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += $year; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); // leap $expected += $year + 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += $year; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += $year; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += $year; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); // leap $expected += $year + 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); } @@ -97,42 +97,42 @@ public function testFastForwardBeforeYearlyByYearDay() ->setDate(99999, 1, 1) ->setTime(0, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 20th day $rrule->next(); $expected += 19 * $day; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 300th day $rrule->next(); $expected += 280 * $day; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 1st day $expected += 66 * $day; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 20th day $rrule->next(); $expected += 19 * $day; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 300th day $rrule->next(); $expected += 280 * $day; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 1st day (leap year, we have 366 days in this year) $rrule->next(); $expected += 67 * $day; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 20th day $rrule->next(); $expected += 19 * $day; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardBeforeYearlyByWeekNo() @@ -153,12 +153,12 @@ public function testFastForwardBeforeYearlyByWeekNo() ->setDate(99999, 1, 4) ->setTime(0, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 20st week $rrule->next(); $expected += $week * 19; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardBeforeYearlyAdvanced() @@ -174,43 +174,43 @@ public function testFastForwardBeforeYearlyAdvanced() ->setDate(10000, 1, 2) ->setTime(8, 30, 56) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 7 * 24 * 60 * 60 - 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 7 * 24 * 60 * 60 - 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 7 * 24 * 60 * 60 - 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 7 * 24 * 60 * 60 - 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // jump to 6th january 10002 $rrule->next(); @@ -218,11 +218,11 @@ public function testFastForwardBeforeYearlyAdvanced() ->setDate(10002, 1, 6) ->setTime(8, 30, 56) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardBeforeMonthlyBasic() @@ -238,36 +238,36 @@ public function testFastForwardBeforeMonthlyBasic() ->setDate(18000, 1, 23) ->setTime(22, 42, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // february $rrule->next(); $expected += 31 * 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // march $rrule->next(); $expected += 29 * 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // april $rrule->next(); $expected += 31 * 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // may $rrule->next(); $expected += 30 * 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // june $rrule->next(); $expected += 31 * 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // july $rrule->next(); $expected += 30 * 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // august $rrule->next(); $expected += 31 * 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardBeforeMonthly31thDay() @@ -283,49 +283,49 @@ public function testFastForwardBeforeMonthly31thDay() $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) ->setDate(18000, 1, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // march $rrule->next(); $expected = (new \DateTime('1970-01-31 00:00:00', new \DateTimeZone($timezone))) ->setDate(18000, 3, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // may $rrule->next(); $expected = (new \DateTime('1970-01-31 00:00:00', new \DateTimeZone($timezone))) ->setDate(18000, 5, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // july $rrule->next(); $expected = (new \DateTime('1970-01-31 00:00:00', new \DateTimeZone($timezone))) ->setDate(18000, 7, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // august $rrule->next(); $expected = (new \DateTime('1970-01-31 00:00:00', new \DateTimeZone($timezone))) ->setDate(18000, 8, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // october $rrule->next(); $expected = (new \DateTime('1970-01-31 00:00:00', new \DateTimeZone($timezone))) ->setDate(18000, 10, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // december $rrule->next(); $expected = (new \DateTime('1970-01-31 00:00:00', new \DateTimeZone($timezone))) ->setDate(18000, 12, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardBeforeMonthlyAdvanced() @@ -343,49 +343,49 @@ public function testFastForwardBeforeMonthlyAdvanced() $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) ->setDate(8000, 1, 3) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // tuesday $expected = (new \DateTime('1970-01-31 00:00:00', new \DateTimeZone($timezone))) ->setDate(8000, 1, 11) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // wednesday $expected = (new \DateTime('1970-01-31 00:00:00', new \DateTimeZone($timezone))) ->setDate(8000, 1, 19) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // thursday $expected = (new \DateTime('1970-01-31 00:00:00', new \DateTimeZone($timezone))) ->setDate(8000, 1, 27) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // monday march $expected = (new \DateTime('1970-01-31 00:00:00', new \DateTimeZone($timezone))) ->setDate(8000, 3, 6) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // tuesday $expected = (new \DateTime('1970-01-31 00:00:00', new \DateTimeZone($timezone))) ->setDate(8000, 3, 14) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // wednesday (this month starts on wednesday so that's just the next day) $expected = (new \DateTime('1970-01-31 00:00:00', new \DateTimeZone($timezone))) ->setDate(8000, 3, 15) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // thursday $expected += 8 * 24 * 60 * 60; @@ -393,7 +393,7 @@ public function testFastForwardBeforeMonthlyAdvanced() ->setDate(8000, 3, 23) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardBeforeDailyBasic() @@ -409,31 +409,31 @@ public function testFastForwardBeforeDailyBasic() $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) ->setDate(4000, 1, 1) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 24 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 24 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 24 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 24 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 24 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 24 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardBeforeDailyAdvanced() @@ -451,37 +451,37 @@ public function testFastForwardBeforeDailyAdvanced() ->setDate(4000, 1, 4) ->setTime(16, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 17:00 $expected += 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 18:00 $expected += 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 16:00 $expected += 10 * 24 * 60 * 60 - 2 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 17:00 $expected += 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 18:00 $expected += 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 16:00 $expected += 10 * 24 * 60 * 60 - 2 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardBeforeHourlyBasic() @@ -498,31 +498,31 @@ public function testFastForwardBeforeHourlyBasic() ->setDate(4000, 1, 2) ->setTime(1, 12, 34) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardBeforeNotInFrequency() @@ -540,7 +540,7 @@ public function testFastForwardBeforeNotInFrequency() ->setDate(2020, 2, 29) ->setTime(0, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // the next leap year $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) @@ -548,7 +548,7 @@ public function testFastForwardBeforeNotInFrequency() ->setTime(0, 0, 0) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardBeforeMultipleTimesBasic() @@ -559,12 +559,12 @@ public function testFastForwardBeforeMultipleTimesBasic() $expected = new \DateTime('2020-01-16 00:00:00', new \DateTimeZone('zulu')); $this->fastForward($rrule, $ffDate); - $this->assertEquals($expected->getTimestamp(), $rrule->current()->getTimestamp()); + self::assertEquals($expected->getTimestamp(), $rrule->current()->getTimestamp()); $this->fastForward($rrule, $ffDate); - $this->assertEquals($expected->getTimestamp(), $rrule->current()->getTimestamp()); + self::assertEquals($expected->getTimestamp(), $rrule->current()->getTimestamp()); $this->fastForward($rrule, $ffDate); - $this->assertEquals($expected->getTimestamp(), $rrule->current()->getTimestamp()); + self::assertEquals($expected->getTimestamp(), $rrule->current()->getTimestamp()); } } diff --git a/tests/VObject/Recur/FastForwardTest.php b/tests/VObject/Recur/FastForwardTest.php index 62effc4de..3c6a14c50 100644 --- a/tests/VObject/Recur/FastForwardTest.php +++ b/tests/VObject/Recur/FastForwardTest.php @@ -15,7 +15,7 @@ private function fastForward(RRuleIterator $ruleIterator, \DateTimeInterface $ff $ruleIterator->fastForward($ffDate); $ru = getrusage(); $endTime = $ru['ru_utime.tv_sec'] * 1000000 + $ru['ru_utime.tv_usec']; - $this->assertLessThan(self::FF_TIMEOUT, $endTime - $startTime); + self::assertLessThan(self::FF_TIMEOUT, $endTime - $startTime); } public function testFastForwardYearlyBasic() @@ -33,37 +33,37 @@ public function testFastForwardYearlyBasic() ->setDate(99999, 10, 23) ->setTime(0, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); // It's a leap $expected += $year + 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += $year; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += $year; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += $year; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); // leap $expected += $year + 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += $year; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += $year; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += $year; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); // leap $expected += $year + 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); } @@ -82,33 +82,33 @@ public function testFastForwardYearlyByYearDay() ->setDate(99999, 1, 1)// 20th day ->setTime(0, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); // 300th day $expected += 19 * $day; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); // 1st day $expected += 280 * $day; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 20th day $expected += 66 * $day; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 300th day $rrule->next(); $expected += 19 * $day; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 280 * $day; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); // 1st day (leap year, we have 366 days in this year) $expected += 67 * $day; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 19 * $day; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardYearlyByWeekNo() @@ -127,10 +127,10 @@ public function testFastForwardYearlyByWeekNo() ->setDate(99999, 1, 4)// 1st day ->setTime(0, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += $week * 19; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardYearlyAdvanced() @@ -146,43 +146,43 @@ public function testFastForwardYearlyAdvanced() ->setDate(10000, 1, 2) ->setTime(8, 30, 56) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 7 * 24 * 60 * 60 - 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 7 * 24 * 60 * 60 - 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 7 * 24 * 60 * 60 - 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 7 * 24 * 60 * 60 - 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // jump to 6th january 10002 $rrule->next(); @@ -190,11 +190,11 @@ public function testFastForwardYearlyAdvanced() ->setDate(10002, 1, 6) ->setTime(8, 30, 56) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $rrule->next(); $expected += 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardMonthlyBasic() @@ -210,36 +210,36 @@ public function testFastForwardMonthlyBasic() ->setDate(18000, 1, 23) ->setTime(22, 42, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // february $rrule->next(); $expected += 31 * 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // march $rrule->next(); $expected += 29 * 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // april $rrule->next(); $expected += 31 * 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // may $rrule->next(); $expected += 30 * 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // june $rrule->next(); $expected += 31 * 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // july $rrule->next(); $expected += 30 * 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // august $rrule->next(); $expected += 31 * 24 * 60 * 60; - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardMonthly31thDay() @@ -255,14 +255,14 @@ public function testFastForwardMonthly31thDay() $expected = (new \DateTime('midnight', new \DateTimeZone('America/New_York'))) ->setDate(18000, 1, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // march $rrule->next(); $expected = (new \DateTime('midnight', new \DateTimeZone('America/New_York'))) ->setDate(18000, 3, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // may $rrule->next(); @@ -270,35 +270,35 @@ public function testFastForwardMonthly31thDay() $expected = (new \DateTime('midnight', new \DateTimeZone('America/New_York'))) ->setDate(18000, 5, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // july $rrule->next(); $expected = (new \DateTime('midnight', new \DateTimeZone('America/New_York'))) ->setDate(18000, 7, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // august $rrule->next(); $expected = (new \DateTime('midnight', new \DateTimeZone('America/New_York'))) ->setDate(18000, 8, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // october $rrule->next(); $expected = (new \DateTime('midnight', new \DateTimeZone('America/New_York'))) ->setDate(18000, 10, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // december $rrule->next(); $expected = (new \DateTime('midnight', new \DateTimeZone('America/New_York'))) ->setDate(18000, 12, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardMonthlyAdvanced() @@ -315,56 +315,56 @@ public function testFastForwardMonthlyAdvanced() $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) ->setDate(8000, 1, 3) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // tuesday $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) ->setDate(8000, 1, 11) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // wednesday $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) ->setDate(8000, 1, 19) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // thursday $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) ->setDate(8000, 1, 27) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // monday march $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) ->setDate(8000, 3, 6) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // tuesday $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) ->setDate(8000, 3, 14) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // wednesday (this month starts on wednesday so that's just the next day) $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) ->setDate(8000, 3, 15) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // thursday $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) ->setDate(8000, 3, 23) ->getTimestamp(); $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardDailyBasic() @@ -380,31 +380,31 @@ public function testFastForwardDailyBasic() $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) ->setDate(4000, 1, 1) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 24 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 24 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 24 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 24 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 24 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); $expected += 24 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardDailyAdvanced() @@ -421,36 +421,36 @@ public function testFastForwardDailyAdvanced() ->setDate(4000, 1, 4) ->setTime(16, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 17:00 $expected += 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 18:00 $expected += 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 16:00 $expected += 10 * 24 * 60 * 60 - 2 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 17:00 $expected += 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 18:00 $expected += 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); // 16:00 $expected += 10 * 24 * 60 * 60 - 2 * 60 * 60; $rrule->next(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } } diff --git a/tests/VObject/Recur/FastForwardToEndTest.php b/tests/VObject/Recur/FastForwardToEndTest.php index 0b94f3945..2b1201b09 100644 --- a/tests/VObject/Recur/FastForwardToEndTest.php +++ b/tests/VObject/Recur/FastForwardToEndTest.php @@ -15,9 +15,9 @@ private function fastForwardToEnd(RRuleIterator $ruleIterator, $enfoceTiming = t $ruleIterator->fastForwardToEnd(); $ru = getrusage(); $endTime = $ru['ru_utime.tv_sec'] * 1000000 + $ru['ru_utime.tv_usec']; - $enfoceTiming && $this->assertLessThan(self::FF_TIMEOUT, $endTime - $startTime); - $this->assertTrue($ruleIterator->valid()); - $this->assertNotNull($ruleIterator->current()); + $enfoceTiming && self::assertLessThan(self::FF_TIMEOUT, $endTime - $startTime); + self::assertTrue($ruleIterator->valid()); + self::assertNotNull($ruleIterator->current()); } public function testFastForwardToEndWithoutEndYearlyBasic(): void @@ -42,7 +42,7 @@ public function testFastForwardToEndCountYearlyBasic(): void ->setDate(9746, 10, 23) ->setTime(0, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardToEndUntilYearlyBasic(): void @@ -57,7 +57,7 @@ public function testFastForwardToEndUntilYearlyBasic(): void ->setDate(9746, 10, 23) ->setTime(0, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardToEndCountYearlyByYearDay(): void @@ -73,7 +73,7 @@ public function testFastForwardToEndCountYearlyByYearDay(): void ->setDate(5303, 1, 20) ->setTime(0, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardToEndUntilYearlyByYearDay(): void @@ -88,7 +88,7 @@ public function testFastForwardToEndUntilYearlyByYearDay(): void ->setDate(5303, 1, 20) ->setTime(0, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } /* @@ -106,7 +106,7 @@ public function testFastForwardToEndCountYearlyByWeekNo() ->setDate(2019, 12, 30) ->setTime(0, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardToEndUntilYearlyByWeekNo() @@ -121,7 +121,7 @@ public function testFastForwardToEndUntilYearlyByWeekNo() ->setDate(2019, 12, 30) ->setTime(0, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } */ @@ -137,7 +137,7 @@ public function testFastForwardToEndCountYearlyAdvanced() ->setDate(4226, 1, 1) ->setTime(8, 30, 56) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardToEndUntilYearlyAdvanced() @@ -151,7 +151,7 @@ public function testFastForwardToEndUntilYearlyAdvanced() ->setDate(4218, 1, 25) ->setTime(8, 30, 56) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardToEndCountMonthlyBasic() @@ -166,7 +166,7 @@ public function testFastForwardToEndCountMonthlyBasic() ->setDate(2804, 1, 23) ->setTime(22, 42, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardToEndUntilMonthlyBasic() @@ -180,7 +180,7 @@ public function testFastForwardToEndUntilMonthlyBasic() ->setDate(2803, 12, 23) ->setTime(22, 42, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } /** @@ -197,7 +197,7 @@ public function testFastForwardToEndCountMonthly31thDay() $expected = (new \DateTime('midnight', new \DateTimeZone('America/New_York'))) ->setDate(3398, 10, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } /** @@ -213,7 +213,7 @@ public function testFastForwardToEndCountMonthly31thDayPHP81() $expected = (new \DateTime('midnight', new \DateTimeZone('America/New_York'))) ->setDate(3398, 7, 31); - $this->assertEquals($expected->getTimestamp(), $rrule->current()->getTimestamp()); + self::assertEquals($expected->getTimestamp(), $rrule->current()->getTimestamp()); } public function testFastForwardToEndUntilMonthly31thDay() @@ -226,7 +226,7 @@ public function testFastForwardToEndUntilMonthly31thDay() $expected = (new \DateTime('midnight', new \DateTimeZone('America/New_York'))) ->setDate(3398, 8, 31) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } /** @@ -244,7 +244,7 @@ public function testFastForwardToEndCountMonthlyAdvanced() $expected = (new \DateTime('midnight', new \DateTimeZone('America/New_York'))) ->setDate(2386, 9, 17) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardToEndUntilMonthlyAdvanced() @@ -258,7 +258,7 @@ public function testFastForwardToEndUntilMonthlyAdvanced() $expected = (new \DateTime('midnight', new \DateTimeZone('America/New_York'))) ->setDate(2386, 9, 9) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardToEndCountDailyBasic() @@ -273,7 +273,7 @@ public function testFastForwardToEndCountDailyBasic() $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) ->setDate(2244, 8, 6) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardToEndUntilDailyBasic() @@ -287,7 +287,7 @@ public function testFastForwardToEndUntilDailyBasic() $expected = (new \DateTime('midnight', new \DateTimeZone($timezone))) ->setDate(2244, 8, 6) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardToEndCountDailyAdvanced() @@ -304,7 +304,7 @@ public function testFastForwardToEndCountDailyAdvanced() ->setDate(2062, 1, 13) ->setTime(18, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardToEndUntilDailyAdvanced() @@ -320,7 +320,7 @@ public function testFastForwardToEndUntilDailyAdvanced() ->setDate(2062, 1, 13) ->setTime(18, 0, 0) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardToEndCountHourlyBasic() @@ -336,7 +336,7 @@ public function testFastForwardToEndCountHourlyBasic() ->setDate(1982, 3, 21) ->setTime(2, 12, 34) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } public function testFastForwardToEndUntilHourlyBasic() @@ -351,6 +351,6 @@ public function testFastForwardToEndUntilHourlyBasic() ->setDate(1982, 3, 21) ->setTime(2, 12, 34) ->getTimestamp(); - $this->assertEquals($expected, $rrule->current()->getTimestamp()); + self::assertEquals($expected, $rrule->current()->getTimestamp()); } } diff --git a/tests/VObject/Recur/RRuleIteratorTest.php b/tests/VObject/Recur/RRuleIteratorTest.php index 7ace7ae4f..8aa92ad1f 100644 --- a/tests/VObject/Recur/RRuleIteratorTest.php +++ b/tests/VObject/Recur/RRuleIteratorTest.php @@ -2,6 +2,7 @@ namespace Sabre\VObject\Recur; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Sabre\VObject\InvalidDataException; @@ -345,7 +346,7 @@ public function testInvalidByMonthDay(): void ); } - /** @dataProvider invalidFreqByCombinationProviders */ + #[DataProvider('invalidFreqByCombinationProviders')] public function testInvalidFreqByCombination(string $rule): void { $this->expectException(InvalidDataException::class); @@ -356,7 +357,7 @@ public function testInvalidFreqByCombination(string $rule): void ); } - public function invalidFreqByCombinationProviders(): iterable + public static function invalidFreqByCombinationProviders(): iterable { return [ ['FREQ=DAILY;BYWEEKNO=13,15,50'], @@ -1253,15 +1254,15 @@ public function parse( ?string $fastForward = null, string $tz = 'UTC', bool $runTillTheEnd = false, - bool $yearlySkipUpperLimit = true + bool $yearlySkipUpperLimit = true, ): void { $dt = new \DateTime($start, new \DateTimeZone($tz)); $parser = new RRuleIterator($rule, $dt, $yearlySkipUpperLimit); - $this->assertEquals($expectedFreq, $parser->getFrequency()); - $this->assertEquals($expectedCount, $parser->getCount()); - $this->assertEquals($expectedInterval, $parser->getInterval()); - $this->assertEquals($expectedUntil, $parser->getUntil()); + self::assertEquals($expectedFreq, $parser->getFrequency()); + self::assertEquals($expectedCount, $parser->getCount()); + self::assertEquals($expectedInterval, $parser->getInterval()); + self::assertEquals($expectedUntil, $parser->getUntil()); if ($fastForward) { $parser->fastForward(new \DateTime($fastForward)); diff --git a/tests/VObject/Splitter/ICalendarTest.php b/tests/VObject/Splitter/ICalendarTest.php index f5428e937..be913780a 100644 --- a/tests/VObject/Splitter/ICalendarTest.php +++ b/tests/VObject/Splitter/ICalendarTest.php @@ -94,6 +94,7 @@ public function testICalendarImportInvalidEvent(): void public function testICalendarImportMultipleValidEvents(): void { + $event = []; $event[] = << $item['message'], $messages ); - $this->fail('Validation errors: '.implode("\n", $messages)); + self::fail('Validation errors: '.implode("\n", $messages)); } else { self::assertEquals([], $messages); } @@ -217,6 +218,7 @@ public function testICalendarImportMultipleVTIMEZONESAndMultipleValidEvents(): v END:VTIMEZONE EOT; + $event = []; $event[] = <<expectException(ParseException::class); + $event = []; $event[] = <<getMessage(), 'Unknown or bad timezone')) { - $this->markTestSkipped($timezoneName.' is not (yet) supported in this PHP version. Update pecl/timezonedb'); + if (str_contains($e->getMessage(), 'Unknown or bad timezone')) { + self::markTestSkipped($timezoneName.' is not (yet) supported in this PHP version. Update pecl/timezonedb'); } else { throw $e; } } } - public function getMapping(): array + public static function getMapping(): array { $map = array_merge( include __DIR__.'/../../lib/timezonedata/windowszones.php', @@ -40,16 +39,12 @@ public function getMapping(): array // PHPUNit requires an array of arrays return array_map( - function ($value) { - return [$value]; - }, + fn ($value) => [$value], $map ); } - /** - * @dataProvider getMapping - */ + #[DataProvider('getMapping')] public function testSlashTZ($timezonename): void { $slashTimezone = '/'.$timezonename; @@ -200,9 +195,7 @@ public function testDeprecatedUnsupportedTimeZone(): void self::assertNotSame($ex->getName(), $tz->getName()); } - /** - * @dataProvider getPHPTimeZoneIdentifiers - */ + #[DataProvider('getPHPTimeZoneIdentifiers')] public function testTimeZoneIdentifiers(string $tzid): void { $tz = TimeZoneUtil::getTimeZone($tzid); @@ -211,9 +204,7 @@ public function testTimeZoneIdentifiers(string $tzid): void self::assertEquals($ex->getName(), $tz->getName()); } - /** - * @dataProvider getPHPTimeZoneBCIdentifiers - */ + #[DataProvider('getPHPTimeZoneBCIdentifiers')] public function testTimeZoneBCIdentifiers(string $tzid): void { /* @@ -224,8 +215,8 @@ public function testTimeZoneBCIdentifiers(string $tzid): void * that should be released in Feb 2023. */ $versionOfPHP = \phpversion(); - if ((('8.1.14' == $versionOfPHP) || ('8.2.1' == $versionOfPHP)) && \str_contains($tzid, '+')) { - $this->markTestSkipped("Timezone ids containing '+' do not work on PHP $versionOfPHP"); + if ((('8.1.14' === $versionOfPHP) || ('8.2.1' === $versionOfPHP)) && \str_contains($tzid, '+')) { + self::markTestSkipped("Timezone ids containing '+' do not work on PHP $versionOfPHP"); } $tz = TimeZoneUtil::getTimeZone($tzid); $ex = new \DateTimeZone($tzid); @@ -233,27 +224,21 @@ public function testTimeZoneBCIdentifiers(string $tzid): void self::assertEquals($ex->getName(), $tz->getName()); } - public function getPHPTimeZoneIdentifiers(): array + public static function getPHPTimeZoneIdentifiers(): array { // PHPUNit requires an array of arrays return array_map( - function ($value) { - return [$value]; - }, + fn ($value) => [$value], // FIXME remove the filter after finishing timezone migration - array_filter(\DateTimeZone::listIdentifiers(), static function (string $timezone) { - return 'Europe/Kyiv' !== $timezone; - }) + array_filter(\DateTimeZone::listIdentifiers(), static fn (string $timezone) => 'Europe/Kyiv' !== $timezone) ); } - public function getPHPTimeZoneBCIdentifiers(): array + public static function getPHPTimeZoneBCIdentifiers(): array { // PHPUNit requires an array of arrays return array_map( - function ($value) { - return [$value]; - }, + fn ($value) => [$value], include __DIR__.'/../../lib/timezonedata/php-bc.php' ); } @@ -427,9 +412,7 @@ public function testMicrosoftMap(): void self::assertEquals($ex->getName(), $tz->getName()); } - /** - * @dataProvider unSupportTimezoneProvider - */ + #[DataProvider('unSupportTimezoneProvider')] public function testPHPUnSupportTimeZone(string $origin, string $expected): void { $tz = TimeZoneUtil::getTimeZone($origin, null, true); @@ -437,7 +420,7 @@ public function testPHPUnSupportTimeZone(string $origin, string $expected): void self::assertEquals($ex->getName(), $tz->getName()); } - public function unSupportTimezoneProvider(): iterable + public static function unSupportTimezoneProvider(): iterable { yield 'America/Santa_Isabel' => [ 'origin' => 'America/Santa_Isabel', @@ -496,9 +479,7 @@ public function unSupportTimezoneProvider(): iterable } } - /** - * @dataProvider offsetTimeZoneProvider - */ + #[DataProvider('offsetTimeZoneProvider')] public function testOffsetTimeZones(string $origin, string $expected): void { $tz = TimeZoneUtil::getTimeZone($origin, null, true); @@ -506,7 +487,7 @@ public function testOffsetTimeZones(string $origin, string $expected): void self::assertEquals($ex->getName(), $tz->getName()); } - public function offsetTimeZoneProvider(): iterable + public static function offsetTimeZoneProvider(): iterable { yield 'UTC-05:00' => [ 'origin' => 'UTC-05:00', @@ -529,9 +510,7 @@ public function offsetTimeZoneProvider(): iterable ]; } - /** - * @dataProvider letterCaseTimeZoneProvider - */ + #[DataProvider('letterCaseTimeZoneProvider')] public function testDifferentLetterCaseTimeZone(string $origin, string $expected): void { $tz = TimeZoneUtil::getTimeZone($origin, null, true); @@ -539,7 +518,7 @@ public function testDifferentLetterCaseTimeZone(string $origin, string $expected self::assertEquals($ex->getName(), $tz->getName()); } - public function letterCaseTimeZoneProvider(): iterable + public static function letterCaseTimeZoneProvider(): iterable { yield 'case 1' => [ 'origin' => 'Europe/paris', @@ -562,9 +541,7 @@ public function letterCaseTimeZoneProvider(): iterable ]; } - /** - * @dataProvider outlookCitiesProvider - */ + #[DataProvider('outlookCitiesProvider')] public function testOutlookCities(string $origin, bool $failIfUncertain, string $expected): void { $tz = TimeZoneUtil::getTimeZone($origin, null, $failIfUncertain); @@ -572,7 +549,7 @@ public function testOutlookCities(string $origin, bool $failIfUncertain, string self::assertEquals($ex->getName(), $tz->getName()); } - public function outlookCitiesProvider(): iterable + public static function outlookCitiesProvider(): iterable { yield 'case 1' => [ 'origin' => 'TZID:(UTC+01:00) Bruxelles\, København\, Madrid\, Paris', @@ -599,9 +576,7 @@ public function outlookCitiesProvider(): iterable ]; } - /** - * @dataProvider versionTzProvider - */ + #[DataProvider('versionTzProvider')] public function testVersionTz(string $origin, bool $failIfUncertain, string $expected): void { $tz = TimeZoneUtil::getTimeZone($origin, null, $failIfUncertain); @@ -609,7 +584,7 @@ public function testVersionTz(string $origin, bool $failIfUncertain, string $exp self::assertEquals($ex->getName(), $tz->getName()); } - public function versionTzProvider(): iterable + public static function versionTzProvider(): iterable { yield 'case 1' => [ 'origin' => 'Eastern Standard Time 1', diff --git a/tests/VObject/TimezoneGuesser/FindFromTimezoneMapTest.php b/tests/VObject/TimezoneGuesser/FindFromTimezoneMapTest.php index dccc5b52c..4084faac3 100644 --- a/tests/VObject/TimezoneGuesser/FindFromTimezoneMapTest.php +++ b/tests/VObject/TimezoneGuesser/FindFromTimezoneMapTest.php @@ -4,6 +4,7 @@ namespace Sabre\VObject\TimezoneGuesser; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class FindFromTimezoneMapTest extends TestCase @@ -11,9 +12,8 @@ class FindFromTimezoneMapTest extends TestCase /** * Verify that previously-deprecated IANA names have been replaced with * their canonical successors and resolve correctly. - * - * @dataProvider updatedTimezoneProvider */ + #[DataProvider('updatedTimezoneProvider')] public function testUpdatedTimezonesResolve(string $mapKey, string $expectedOlson): void { $finder = new FindFromTimezoneMap(); @@ -23,7 +23,7 @@ public function testUpdatedTimezonesResolve(string $mapKey, string $expectedOlso self::assertSame($expectedOlson, $tz->getName()); } - public function updatedTimezoneProvider(): array + public static function updatedTimezoneProvider(): array { return [ // windowszones.php diff --git a/tests/VObject/VCardConverterTest.php b/tests/VObject/VCardConverterTest.php index 9c7c1ec38..b9786a80b 100644 --- a/tests/VObject/VCardConverterTest.php +++ b/tests/VObject/VCardConverterTest.php @@ -14,21 +14,21 @@ class VCardConverterTest extends TestCase */ public function testConvert30to40(): void { - $input = <<expectException(\InvalidArgumentException::class); - $input = <<expectException(\InvalidArgumentException::class); - $input = << + + - - - ../lib/ - - . + + + ../lib/ + +