Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Limit date ranges that end far in the future #22592

Open
wants to merge 1 commit into
base: 5.x-dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions core/Period/Range.php
Original file line number Diff line number Diff line change
Expand Up @@ -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\'')));
}
Expand Down Expand Up @@ -587,4 +593,18 @@ 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
*/
public static function getMaxAllowedEndTimestamp(): int
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the method need to be public if not used elsewhere?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't and it might not even need to be static. But this new "Limit" is supposed to be something global for ranges. So it imho should be reusable if needed anywhere else.
We could actually even consider to mark this method as @api, so it will be shown in the documentation 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, ok, well if we want to have it in the API scope, then yeah, keep it public. With the static vs dynamic, it seemed to me we prefer dynamic in a lot of places, even just to get a single thing we instantiate a class.. so I could see that used here as well.

{
return strtotime(
date('Y-12-31 00:00:00', strtotime("+10 year", Date::$now ?? time()))
);
}
}
17 changes: 8 additions & 9 deletions tests/PHPUnit/Unit/DateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
33 changes: 33 additions & 0 deletions tests/PHPUnit/Unit/Period/RangeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down Expand Up @@ -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');
Expand Down
Loading