diff --git a/core/Period/Range.php b/core/Period/Range.php index 19c347a1d8a..36c450c84d8 100644 --- a/core/Period/Range.php +++ b/core/Period/Range.php @@ -264,7 +264,13 @@ protected function generate() if (strpos($strDateEnd, '-') === false) { $timezone = $this->timezone; } + $endDate = Date::factory($strDateEnd, $timezone)->setTime("00:00:00"); + $maxAllowedEndDate = Date::factory(self::getMaxAllowedEndTimestamp()); + + if ($endDate->isLater($maxAllowedEndDate)) { + $endDate = $maxAllowedEndDate; + } } else { throw new Exception($this->translator->translate('General_ExceptionInvalidDateRange', array($this->strDate, ' \'lastN\', \'previousN\', \'YYYY-MM-DD,YYYY-MM-DD\''))); } @@ -587,4 +593,19 @@ public function getParentPeriodLabel() { return null; } + + /** + * Returns the max allowed end timestamp for a range. If an enddate after this timestamp is provided, Matomo will + * automatically lower the end date to the date returned by this method. + * The max supported timestamp is always set to end of the current year plus 10 years. + * + * @return int + * @api + */ + public static function getMaxAllowedEndTimestamp(): int + { + return strtotime( + date('Y-12-31 00:00:00', strtotime('+10 year', Date::getNowTimestamp())) + ); + } } diff --git a/tests/PHPUnit/Unit/DateTest.php b/tests/PHPUnit/Unit/DateTest.php index 76159efb765..cc3bcf26f52 100644 --- a/tests/PHPUnit/Unit/DateTest.php +++ b/tests/PHPUnit/Unit/DateTest.php @@ -126,15 +126,14 @@ public function testInvalidDateThrowsException($valueToTest) Date::factory($valueToTest); } - public function getInvalidDates(): array - { - return [ - ['0001-01-01'], - ['randomString'], - [null], - [''], - [['arrayValue']], - ]; + public function getInvalidDates(): iterable + { + yield 'valid format, earliest possible date' => ['0001-01-01']; + yield 'valid format, day before first website creation' => ['1991-08-05']; + yield 'ivalid string value' => ['randomString']; + yield 'empty string value' => ['']; + yield 'null value' => [null]; + yield 'array value' => [['arrayValue']]; } public function getTimezoneOffsets() diff --git a/tests/PHPUnit/Unit/Period/RangeTest.php b/tests/PHPUnit/Unit/Period/RangeTest.php index 23b23389e59..32b98129b05 100644 --- a/tests/PHPUnit/Unit/Period/RangeTest.php +++ b/tests/PHPUnit/Unit/Period/RangeTest.php @@ -404,6 +404,17 @@ public function testRangeMonthcomma1() $this->assertEquals('2006-12-01,2007-01-31', $range->getRangeString()); } + // test range date1,date2 + public function testRangeMonthcommaAfterMaxAllowedDate() + { + Date::$now = strtotime('2024-07-09'); + $range = new Range('month', '2024-01-01,2100-01-03'); + + // range should be limited to 2034, so includes 11 years + $this->assertEquals(11 * 12, $range->getNumberOfSubperiods()); + $this->assertEquals('2024-01-01,2034-12-31', $range->getRangeString()); + } + // test range WEEK public function testRangeWeek() { @@ -1215,6 +1226,28 @@ public function testCustomRangeBeforeIsAfterYearRight() $range->getPrettyString(); } + /** + * @dataProvider getAbnormalDateRanges + */ + public function testCustomRangeWithOutOfRangeDate($dateStr) + { + self::expectException(Exception::class); + + $range = new Range('range', $dateStr); + $range->getDateStart(); + } + + public function getAbnormalDateRanges(): iterable + { + yield 'range starts before first website creation' => [ + '1900-01-01,2021-01-01', + ]; + + yield 'range starts after it ends' => [ + '2024-01-01,2020-12-16', + ]; + } + public function testCustomRangeLastN() { $range = new Range('range', 'last4');