diff --git a/src/Utils/DateTime.php b/src/Utils/DateTime.php index 60f102a3e..876ca6122 100644 --- a/src/Utils/DateTime.php +++ b/src/Utils/DateTime.php @@ -15,7 +15,7 @@ /** * DateTime. */ -class DateTime extends \DateTime implements \JsonSerializable +class DateTime extends \DateTimeImmutable implements \JsonSerializable { use Nette\SmartObject; @@ -28,13 +28,13 @@ class DateTime extends \DateTime implements \JsonSerializable /** day in seconds */ const DAY = 24 * self::HOUR; - /** week in seconds */ + /** @deprecated */ const WEEK = 7 * self::DAY; - /** average month in seconds */ + /** @deprecated */ const MONTH = 2629800; - /** average year in seconds */ + /** @deprecated */ const YEAR = 31557600; @@ -50,6 +50,7 @@ public static function from($time) } elseif (is_numeric($time)) { if ($time <= self::YEAR) { + trigger_error(__METHOD__ . '() and relative timestamp is deprecated.', E_USER_DEPRECATED); $time += time(); } return (new static('@' . $time))->setTimeZone(new \DateTimeZone(date_default_timezone_get())); @@ -85,6 +86,7 @@ public function __toString(): string */ public function modifyClone(string $modify = '') { + trigger_error(__METHOD__ . '() is deprecated, use modify()', E_USER_DEPRECATED); $dolly = clone $this; return $modify ? $dolly->modify($modify) : $dolly; } @@ -117,7 +119,7 @@ public function getTimestamp() * @param string The format the $time parameter should be in * @param string String representing the time * @param string|\DateTimeZone desired timezone (default timezone is used if NULL is passed) - * @return static|FALSE + * @return static|NULL */ public static function createFromFormat($format, $time, $timezone = NULL) { @@ -132,7 +134,7 @@ public static function createFromFormat($format, $time, $timezone = NULL) } $date = parent::createFromFormat($format, $time, $timezone); - return $date ? static::from($date) : FALSE; + return $date ? static::from($date) : NULL; } @@ -144,4 +146,60 @@ public function jsonSerialize(): string return $this->format('c'); } + + /********************* immutable usage detector ****************d*g**/ + + + public function __destruct() + { + $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); + if (isset($trace[0]['file'], $trace[1]['function']) && $trace[0]['file'] === __FILE__ && $trace[1]['function'] !== 'from') { + trigger_error(__CLASS__ . ' is immutable now, check how it is used in ' . $trace[1]['file'] . ':' . $trace[1]['line'], E_USER_WARNING); + } + } + + + public function add($interval) + { + return parent::add($interval); + } + + + public function modify($modify) + { + return parent::modify($modify); + } + + + public function setDate($year, $month, $day) + { + return parent::setDate($year, $month, $day); + } + + + public function setISODate($year, $week, $day = 1) + { + return parent::setISODate($year, $week, $day); + } + + + public function setTime($hour, $minute, $second = 0, $micro = 0) + { + return PHP_VERSION_ID < 70100 + ? parent::setTime($hour, $minute, $second) + : parent::setTime($hour, $minute, $second, $micro); + } + + + public function setTimezone($timezone) + { + return parent::setTimezone($timezone); + } + + + public function sub($interval) + { + return parent::sub($interval); + } + } diff --git a/src/Utils/Strings.php b/src/Utils/Strings.php index c25919a79..d66f66f38 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -353,51 +353,51 @@ public static function reverse(string $s): string /** * Returns part of $haystack before $nth occurence of $needle (negative value means searching from the end). - * @return string|FALSE returns FALSE if the needle was not found + * @return string|NULL returns NULL if the needle was not found */ public static function before(string $haystack, string $needle, int $nth = 1) { $pos = self::pos($haystack, $needle, $nth); - return $pos === FALSE - ? FALSE + return $pos === NULL + ? NULL : substr($haystack, 0, $pos); } /** * Returns part of $haystack after $nth occurence of $needle (negative value means searching from the end). - * @return string|FALSE returns FALSE if the needle was not found + * @return string|NULL returns NULL if the needle was not found */ public static function after(string $haystack, string $needle, int $nth = 1) { $pos = self::pos($haystack, $needle, $nth); - return $pos === FALSE - ? FALSE + return $pos === NULL + ? NULL : substr($haystack, $pos + strlen($needle)); } /** * Returns position of $nth occurence of $needle in $haystack (negative value means searching from the end). - * @return int|FALSE offset in characters or FALSE if the needle was not found + * @return int|NULL offset in characters or NULL if the needle was not found */ public static function indexOf(string $haystack, string $needle, int $nth = 1) { $pos = self::pos($haystack, $needle, $nth); - return $pos === FALSE - ? FALSE + return $pos === NULL + ? NULL : self::length(substr($haystack, 0, $pos)); } /** * Returns position of $nth occurence of $needle in $haystack. - * @return int|FALSE offset in bytes or FALSE if the needle was not found + * @return int|NULL offset in bytes or NULL if the needle was not found */ private static function pos(string $haystack, string $needle, int $nth = 1) { if (!$nth) { - return FALSE; + return NULL; } elseif ($nth > 0) { if (strlen($needle) === 0) { return 0; @@ -416,7 +416,7 @@ private static function pos(string $haystack, string $needle, int $nth = 1) $pos--; } } - return $pos; + return $pos === FALSE ? NULL : $pos; } diff --git a/tests/Utils/DateTime.createFromFormat.phpt b/tests/Utils/DateTime.createFromFormat.phpt index 2ae02822f..9a2ddc845 100644 --- a/tests/Utils/DateTime.createFromFormat.phpt +++ b/tests/Utils/DateTime.createFromFormat.phpt @@ -1,7 +1,7 @@ format('Y-m-d H:i:s.u')); @@ -26,4 +26,4 @@ Assert::error(function () { DateTime::createFromFormat('Y-m-d H:i:s', '2050-08-13 11:40:00', 5); }, Nette\InvalidArgumentException::class, 'Invalid timezone given'); -Assert::false(DateTime::createFromFormat('Y-m-d', '2014-10')); +Assert::null(DateTime::createFromFormat('Y-m-d', '2014-10')); diff --git a/tests/Utils/DateTime.from.phpt b/tests/Utils/DateTime.from.phpt index ff8f31b19..4dbf1ff83 100644 --- a/tests/Utils/DateTime.from.phpt +++ b/tests/Utils/DateTime.from.phpt @@ -24,6 +24,6 @@ Assert::same(is_int(2544000000) ? 2544000000 : '2544000000', DateTime::from(2544 Assert::same('1978-05-05 00:00:00', (string) DateTime::from('1978-05-05')); -Assert::type('DateTime', DateTime::from(new DateTime('1978-05-05'))); +Assert::type(DateTime::class, DateTime::from(new \DateTime('1978-05-05'))); Assert::same('1978-05-05 12:00:00.123450', DateTime::from(new DateTime('1978-05-05 12:00:00.12345'))->format('Y-m-d H:i:s.u')); diff --git a/tests/Utils/DateTime.immutable.check.phpt b/tests/Utils/DateTime.immutable.check.phpt new file mode 100644 index 000000000..a56d3fa9b --- /dev/null +++ b/tests/Utils/DateTime.immutable.check.phpt @@ -0,0 +1,26 @@ +setTimestamp(254400000); +}); + +Assert::noError(function () { + $x = DateTime::from(254400000)->format('U'); +}); + +Assert::error(function () { + $x = DateTime::from(254400000); + $x->setTimestamp(254400000); +}, E_USER_WARNING, 'Nette\Utils\DateTime is immutable now, check how it is used in ' . __FILE__ . ':' . (__LINE__ - 1)); diff --git a/tests/Utils/DateTime.modifyClone.phpt b/tests/Utils/DateTime.modifyClone.phpt deleted file mode 100644 index b3c3f7d07..000000000 --- a/tests/Utils/DateTime.modifyClone.phpt +++ /dev/null @@ -1,27 +0,0 @@ -modifyClone(); -Assert::type(DateTime::class, $dolly); -Assert::notSame($date, $dolly); -Assert::same((string) $date, (string) $dolly); - - -$dolly2 = $date->modifyClone('+1 hour'); -Assert::type(DateTime::class, $dolly2); -Assert::notSame($date, $dolly2); -Assert::notSame((string) $date, (string) $dolly2); diff --git a/tests/Utils/Strings.after().phpt b/tests/Utils/Strings.after().phpt index e333ed5ce..eae7621da 100644 --- a/tests/Utils/Strings.after().phpt +++ b/tests/Utils/Strings.after().phpt @@ -27,10 +27,10 @@ test(function () { Assert::same('c', Strings::after($foo, '789', 3)); Assert::same('a123456789b123456789c', Strings::after($foo, '9', -3)); Assert::same('a123456789b123456789c', Strings::after($foo, '789', -3)); - Assert::false(Strings::after($foo, '9', 0)); - Assert::false(Strings::after($foo, 'not-in-string')); - Assert::false(Strings::after($foo, 'b', -2)); - Assert::false(Strings::after($foo, 'b', 2)); + Assert::null(Strings::after($foo, '9', 0)); + Assert::null(Strings::after($foo, 'not-in-string')); + Assert::null(Strings::after($foo, 'b', -2)); + Assert::null(Strings::after($foo, 'b', 2)); }); diff --git a/tests/Utils/Strings.before().phpt b/tests/Utils/Strings.before().phpt index 1866dcfa2..68eff6cfc 100644 --- a/tests/Utils/Strings.before().phpt +++ b/tests/Utils/Strings.before().phpt @@ -26,10 +26,10 @@ test(function () { Assert::same('0123456789a123456789b123456', Strings::before($foo, '789', 3)); Assert::same('012345678', Strings::before($foo, '9', -3)); Assert::same('0123456', Strings::before($foo, '789', -3)); - Assert::false(Strings::before($foo, '9', 0)); - Assert::false(Strings::before($foo, 'not-in-string')); - Assert::false(Strings::before($foo, 'b', -2)); - Assert::false(Strings::before($foo, 'b', 2)); + Assert::null(Strings::before($foo, '9', 0)); + Assert::null(Strings::before($foo, 'not-in-string')); + Assert::null(Strings::before($foo, 'b', -2)); + Assert::null(Strings::before($foo, 'b', 2)); }); diff --git a/tests/Utils/Strings.indexOf().phpt b/tests/Utils/Strings.indexOf().phpt index eceae79d9..8738b0386 100644 --- a/tests/Utils/Strings.indexOf().phpt +++ b/tests/Utils/Strings.indexOf().phpt @@ -27,10 +27,10 @@ test(function () { Assert::same(27, Strings::indexOf($foo, '789', 3)); Assert::same(9, Strings::indexOf($foo, '9', -3)); Assert::same(7, Strings::indexOf($foo, '789', -3)); - Assert::false(Strings::indexOf($foo, '9', 0)); - Assert::false(Strings::indexOf($foo, 'not-in-string')); - Assert::false(Strings::indexOf($foo, 'b', -2)); - Assert::false(Strings::indexOf($foo, 'b', 2)); + Assert::null(Strings::indexOf($foo, '9', 0)); + Assert::null(Strings::indexOf($foo, 'not-in-string')); + Assert::null(Strings::indexOf($foo, 'b', -2)); + Assert::null(Strings::indexOf($foo, 'b', 2)); });