com php-src: Fixed bug #65768: DateTimeImmutable::diff does not work: NEWS ext/date/php_date.c tests/classes/bug65768.ph pt
| From: | Nikita Popov | Date: | Fri, 29 Nov 2013 22:31:07 +0000 |
| Subject: | com php-src: Fixed bug #65768: DateTimeImmutable::diff does not work: NEWS ext/date/php_date.c tests/classes/bug65768.ph pt | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-74174@lists.php.net to get a copy of this message | ||
Commit: 5f09944662e09ea0b3f93cfab8702f188955e68c
Author: nikita2206 <inefedor@gmail.com> Tue, 29 Oct 2013 19:40:17 +0400
Committer: Nikita Popov <nikic@php.net> Fri, 29 Nov 2013 23:31:07 +0100
Parents: 967abd61537a2c7d0beebac9039aa068d518e4eb
Branches: PHP-5.5 PHP-5.6 master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=5f09944662e09ea0b3f93cfab8702f188955e68c
Log:
Fixed bug #65768: DateTimeImmutable::diff does not work
This commit also prevents user classes from directly implementing
DateTimeInterface, because ext/date relies on classes implementing
it to support certain internal structures.
Bugs:
https://bugs.php.net/65768
Changed paths:
M NEWS
M ext/date/php_date.c
A tests/classes/bug65768.phpt
Diff:
diff --git a/NEWS b/NEWS
index d16e8bd..55ee92e 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,7 @@ PHP NEWS
- Date:
. Fixed bug #66060 (Heap buffer over-read in DateInterval). (Remi)
+ . Fixed bug #65768 (DateTimeImmutable::diff does not work). (Nikita Nefedov)
?? ??? 2013, PHP 5.5..7
diff --git a/ext/date/php_date.c b/ext/date/php_date.c
index 742a2f6..cd3bf74 100644
--- a/ext/date/php_date.c
+++ b/ext/date/php_date.c
@@ -1989,12 +1989,25 @@ zend_object_iterator *date_object_period_get_iterator(zend_class_entry *ce,
zval
return (zend_object_iterator*)iterator;
}
+static int implement_date_interface_handler(zend_class_entry *interface, zend_class_entry
*implementor TSRMLS_DC)
+{
+ if (implementor->type == ZEND_USER_CLASS &&
+ !instanceof_function(implementor, date_ce_date TSRMLS_CC) &&
+ !instanceof_function(implementor, date_ce_immutable TSRMLS_CC)
+ ) {
+ zend_error(E_ERROR, "DateTimeInterface can't be implemented by user classes");
+ }
+
+ return SUCCESS;
+}
+
static void date_register_classes(TSRMLS_D)
{
zend_class_entry ce_date, ce_immutable, ce_timezone, ce_interval, ce_period, ce_interface;
INIT_CLASS_ENTRY(ce_interface, "DateTimeInterface", date_funcs_interface);
date_ce_interface = zend_register_internal_interface(&ce_interface TSRMLS_CC);
+ date_ce_interface->interface_gets_implemented = implement_date_interface_handler;
INIT_CLASS_ENTRY(ce_date, "DateTime", date_funcs_date);
ce_date.create_object = date_object_new_date;
@@ -3612,13 +3625,13 @@ PHP_FUNCTION(date_diff)
php_interval_obj *interval;
long absolute = 0;
- if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO|l",
&object1, date_ce_date, &object2, date_ce_date, &absolute) == FAILURE) {
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO|l",
&object1, date_ce_interface, &object2, date_ce_interface, &absolute) == FAILURE) {
RETURN_FALSE;
}
dateobj1 = (php_date_obj *) zend_object_store_get_object(object1 TSRMLS_CC);
dateobj2 = (php_date_obj *) zend_object_store_get_object(object2 TSRMLS_CC);
- DATE_CHECK_INITIALIZED(dateobj1->time, DateTime);
- DATE_CHECK_INITIALIZED(dateobj2->time, DateTime);
+ DATE_CHECK_INITIALIZED(dateobj1->time, DateTimeInterface);
+ DATE_CHECK_INITIALIZED(dateobj2->time, DateTimeInterface);
timelib_update_ts(dateobj1->time, NULL);
timelib_update_ts(dateobj2->time, NULL);
@@ -4396,7 +4409,7 @@ PHP_METHOD(DatePeriod, __construct)
zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
"OOl|l", &start, date_ce_interface, &interval, date_ce_interval, &recurrences,
&options) == FAILURE) {
- if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
"OOO|l", &start, date_ce_interface, &interval, date_ce_interval, &end,
date_ce_date, &options) == FAILURE) {
+ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
"OOO|l", &start, date_ce_interface, &interval, date_ce_interval, &end,
date_ce_interface, &options) == FAILURE) {
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
"s|l", &isostr, &isostr_len, &options) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "This constructor accepts either
(DateTimeInterface, DateInterval, int) OR (DateTimeInterface, DateInterval, DateTime) OR (string) as
arguments.");
zend_restore_error_handling(&error_handling TSRMLS_CC);
diff --git a/tests/classes/bug65768.phpt b/tests/classes/bug65768.phpt
new file mode 100644
index 0000000..17ec93c
--- /dev/null
+++ b/tests/classes/bug65768.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug #65768: date_diff accepts only DateTime instance even though docs say about DateTimeInterface
+--INI--
+date.timezone=Europe/London
+--FILE--
+<?php
+
+$dt1 = new DateTime("2010-10-20");
+$dti1 = new DateTimeImmutable("2010-10-25");
+$dti2 = new DateTimeImmutable("2010-10-28");
+
+$diff1 = $dt1->diff($dti1);
+echo $diff1->y, " ", $diff1->m, " ", $diff1->d, " ",
+ $diff1->h, " ", $diff1->i, " ", $diff1->s, "\n";
+
+$diff2 = $dti1->diff($dti2);
+echo $diff2->y, " ", $diff2->m, " ", $diff2->d, " ",
+ $diff2->h, " ", $diff2->i, " ", $diff2->s, "\n";
+
+$diff3 = date_diff($dt1, $dti2);
+echo $diff3->y, " ", $diff3->m, " ", $diff3->d, " ",
+ $diff3->h, " ", $diff3->i, " ", $diff3->s, "\n";
+
+class cdt1 extends DateTime implements DateTimeInterface {}
+
+class cdt2 extends DateTimeImmutable implements DateTimeInterface {}
+
+class cdt3 implements DateTimeInterface {}
+
+?>
+--EXPECTF--
+0 0 5 0 0 0
+0 0 3 0 0 0
+0 0 8 0 0 0
+
+Fatal error: DateTimeInterface can't be implemented by user classes in %sbug65768.php on line
%d