From: Morik Date: Sat, 7 Jan 2017 16:22:03 +0000 (+0100) Subject: Fix cronjob month calculation X-Git-Tag: 3.1.0_Alpha_1~517^2 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=7c69c6f7f12cd035db57b693bfc411a9130d5d3d;p=GitHub%2FWoltLab%2FWCF.git Fix cronjob month calculation The current calculation ignores given months, this is fixxed with this pull request. To detect any issues with the new implementation i'll run several tests without any differences with the currently used cronjobs used by the wsc. https://gist.github.com/Morik/27804aaa57916150dd08268cd8e224d8 Running those tests took quite a while but there have been no differences for all calculations without a month selection so this fix should have no problems with them. It also allows some exotic cronjobs like the 29. February etc. --- diff --git a/wcfsetup/install/files/lib/util/CronjobUtil.class.php b/wcfsetup/install/files/lib/util/CronjobUtil.class.php index 6cfca4e5e8..489f5067b1 100644 --- a/wcfsetup/install/files/lib/util/CronjobUtil.class.php +++ b/wcfsetup/install/files/lib/util/CronjobUtil.class.php @@ -138,14 +138,30 @@ final class CronjobUtil { * @param array $values */ protected static function calculateTime(array &$values) { - // calculation starts with month, thus start with - // month of $time (if within values) - $currentMonth = gmdate('n', self::$timeBase); - self::findKey($currentMonth, $values['month']); - self::calculateDay($values); } + /** + * Calculates the next month and year to match given criteria. + * + * @param integer $month + * @param integer $year + * @param array $values + */ + protected static function calculateMonth($month, $year, array &$values) { + $index = self::findKey($month, $values['month']); + + // swap to the next year if the next execution month is before the current month + if ($values['month'][$index] < $month) { + $year++; + } + + return [ + 'month' => $values['month'][$index], + 'year' => $year + ]; + } + /** * Calculates the day while adjusting month and year to match given criteria. * @@ -169,6 +185,21 @@ final class CronjobUtil { $month = gmdate('n', $timeBase); $year = gmdate('Y', $timeBase); + // calculate month of next execution and if its not the current one reset previous calculations + $dateMonth = self::calculateMonth($month, $year, $values); + if ($month != $dateMonth['month'] || $year != $dateMonth['year']) { + $day = 1; + $month = $dateMonth['month']; + $year = $dateMonth['year']; + + $timeBase = gmmktime(0, 0, 1, $month, $day, $year); + + if (!$addAnDay) { + self::calculateHour($values, $timeBase); + $addAnDay = true; + } + } + // calculate date of next execution based upon day of week $dateDow = self::calculateDow($month, $year, $values, $day); $dateDowTimestamp = gmmktime(0, 0, 1, $dateDow['month'], $dateDow['day'], $dateDow['year']); @@ -245,7 +276,8 @@ final class CronjobUtil { } // try next month - return self::calculateDow(++$month, $year, $values); + $nextMonth = self::calculateMonth(++$month, $year, $values); + return self::calculateDow($nextMonth['month'], $nextMonth['year'], $values); } /** @@ -271,7 +303,8 @@ final class CronjobUtil { } // try next month - return self::calculateDom(++$month, $year, $values); + $nextMonth = self::calculateMonth(++$month, $year, $values); + return self::calculateDom($nextMonth['month'], $nextMonth['year'], $values); } /**