From a2dd7856930e8d300a70a8af26cca79701e56882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lanvin?= <1701590+rlanvin@users.noreply.github.com> Date: Sun, 23 Jun 2024 09:24:58 +0200 Subject: [PATCH] Fix insufficient type detection for FREQ and WKST In some cases non-string types would end up passed to strtoupper which causes a deprecation warning from PHP 8.3. There might be other places where stricter type check is needed Ref #149 --- .github/workflows/tests.yml | 2 +- src/RRule.php | 36 ++++++++++++++++++++---------------- tests/RRuleTest.php | 9 ++++++++- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 22c18d8..9731094 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] + php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] name: PHP ${{ matrix.php }} steps: - name: Checkout diff --git a/src/RRule.php b/src/RRule.php index 8380c41..6602872 100755 --- a/src/RRule.php +++ b/src/RRule.php @@ -219,34 +219,38 @@ class RRule implements RRuleInterface $this->rule = $parts; // save original rule // WKST - $parts['WKST'] = strtoupper($parts['WKST']); - if (! array_key_exists($parts['WKST'], self::WEEKDAYS)) { + if (is_string($parts['WKST'])) { + $parts['WKST'] = strtoupper($parts['WKST']); + if (array_key_exists($parts['WKST'], self::WEEKDAYS)) { + $this->wkst = self::WEEKDAYS[$parts['WKST']]; + } + } + + if (!$this->wkst) { throw new \InvalidArgumentException( 'The WKST rule part must be one of the following: ' .implode(', ',array_keys(self::WEEKDAYS)) ); } - $this->wkst = self::WEEKDAYS[$parts['WKST']]; // FREQ if (is_integer($parts['FREQ'])) { - if ($parts['FREQ'] > self::SECONDLY || $parts['FREQ'] < self::YEARLY) { - throw new \InvalidArgumentException( - 'The FREQ rule part must be one of the following: ' - .implode(', ',array_keys(self::FREQUENCIES)) - ); + if ($parts['FREQ'] <= self::SECONDLY && $parts['FREQ'] >= self::YEARLY) { + $this->freq = $parts['FREQ']; } - $this->freq = $parts['FREQ']; } - else { // string + elseif (is_string($parts['FREQ'])) { $parts['FREQ'] = strtoupper($parts['FREQ']); - if (! array_key_exists($parts['FREQ'], self::FREQUENCIES)) { - throw new \InvalidArgumentException( - 'The FREQ rule part must be one of the following: ' - .implode(', ',array_keys(self::FREQUENCIES)) - ); + if (array_key_exists($parts['FREQ'], self::FREQUENCIES)) { + $this->freq = self::FREQUENCIES[$parts['FREQ']]; } - $this->freq = self::FREQUENCIES[$parts['FREQ']]; + } + + if (!$this->freq) { + throw new \InvalidArgumentException( + 'The FREQ rule part must be one of the following: ' + .implode(', ',array_keys(self::FREQUENCIES)) + ); } // INTERVAL diff --git a/tests/RRuleTest.php b/tests/RRuleTest.php index 9be5aa0..50e49ae 100644 --- a/tests/RRuleTest.php +++ b/tests/RRuleTest.php @@ -20,8 +20,12 @@ class RRuleTest extends TestCase array(array()), array(array('FOOBAR' => 'DAILY')), - array(array('FREQ' => 'foobar')), + 'invalid string freq' => [['FREQ' => 'foobar']], 'Invalid integer frequency' => [['FREQ' => 42]], + 'Array freq' => [['FREQ' => array()]], + 'null freq' => [['FREQ' => null]], + 'object freq' => [['FREQ' => new Stdclass()]], + array(array('FREQ' => 'DAILY', 'INTERVAL' => -1)), array(array('FREQ' => 'DAILY', 'INTERVAL' => 1.5)), array(array('FREQ' => 'DAILY', 'UNTIL' => 'foobar')), @@ -87,6 +91,9 @@ class RRuleTest extends TestCase array(array('FREQ' => 'MONTHLY', 'BYSECOND' => 61)), 'Invalid WKST' => [['FREQ' => 'DAILY', 'WKST' => 'XX']], + 'Null WKST' => [['FREQ' => 'DAILY', 'WKST' => null]], + 'Array WKST' => [['FREQ' => 'DAILY', 'WKST' => array()]], + 'Object WKST' => [['FREQ' => 'DAILY', 'WKST' => new stdClass()]], 'Invalid DTSTART (invalid date)' => [['FREQ' => 'DAILY', 'DTSTART' => new stdClass()]] );