-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Add factory methods for DatePeriod and ReflectionMethod #6754
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4124,28 +4124,16 @@ static int date_period_initialize(timelib_time **st, timelib_time **et, timelib_ | |
return retval; | ||
} /* }}} */ | ||
|
||
/* {{{ Creates new DatePeriod object. */ | ||
PHP_METHOD(DatePeriod, __construct) | ||
{ | ||
php_period_obj *dpobj; | ||
php_date_obj *dateobj; | ||
zval *start, *end = NULL, *interval; | ||
zend_long recurrences = 0, options = 0; | ||
char *isostr = NULL; | ||
size_t isostr_len = 0; | ||
static void construct_date_period( | ||
INTERNAL_FUNCTION_PARAMETERS, zval *object, zval *start, zval *end, zval *interval, zend_long recurrences, | ||
zend_long options, char *isostr, size_t isostr_len | ||
) { | ||
php_period_obj *dpobj; | ||
php_date_obj *dateobj; | ||
timelib_time *clone; | ||
zend_error_handling error_handling; | ||
|
||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "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(), "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(), "s|l", &isostr, &isostr_len, &options) == FAILURE) { | ||
zend_type_error("DatePeriod::__construct() accepts (DateTimeInterface, DateInterval, int [, int]), or (DateTimeInterface, DateInterval, DateTime [, int]), or (string [, int]) as arguments"); | ||
RETURN_THROWS(); | ||
} | ||
} | ||
} | ||
|
||
dpobj = Z_PHPPERIOD_P(ZEND_THIS); | ||
dpobj = Z_PHPPERIOD_P(object); | ||
dpobj->current = NULL; | ||
|
||
if (isostr) { | ||
|
@@ -4225,7 +4213,90 @@ PHP_METHOD(DatePeriod, __construct) | |
|
||
dpobj->initialized = 1; | ||
} | ||
/* }}} */ | ||
|
||
PHP_METHOD(DatePeriod, createFromRecurrences) | ||
{ | ||
zval *start, *interval; | ||
zend_long recurrences, options = 0; | ||
zval object; | ||
|
||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "OOl|l", &start, date_ce_interface, &interval, date_ce_interval, &recurrences, &options) == FAILURE) { | ||
RETURN_THROWS(); | ||
} | ||
|
||
object_init_ex(&object, zend_get_called_scope(execute_data)); | ||
|
||
construct_date_period(INTERNAL_FUNCTION_PARAM_PASSTHRU, &object, start, NULL, interval, recurrences, options, NULL, 0); | ||
if (EG(exception)) { | ||
zval_ptr_dtor(&object); | ||
RETURN_THROWS(); | ||
} | ||
|
||
ZVAL_COPY_VALUE(return_value, &object); | ||
} | ||
|
||
PHP_METHOD(DatePeriod, createFromDates) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. other candidates I thought about: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I would prefer
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another suggestion would be to use |
||
{ | ||
zval *start, *end, *interval; | ||
zend_long options = 0; | ||
zval object; | ||
|
||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "OOO|l", &start, date_ce_interface, &interval, date_ce_interval, &end, date_ce_interface, &options) == FAILURE) { | ||
RETURN_THROWS(); | ||
} | ||
|
||
object_init_ex(&object, zend_get_called_scope(execute_data)); | ||
|
||
construct_date_period(INTERNAL_FUNCTION_PARAM_PASSTHRU, &object, start, end, interval, 0, options, NULL, 0); | ||
if (EG(exception)) { | ||
zval_ptr_dtor(&object); | ||
RETURN_THROWS(); | ||
} | ||
|
||
ZVAL_COPY_VALUE(return_value, &object); | ||
} | ||
|
||
PHP_METHOD(DatePeriod, createFromIso8601) | ||
{ | ||
char *isostr; | ||
size_t isostr_len; | ||
zend_long options = 0; | ||
zval object; | ||
|
||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &isostr, &isostr_len, &options) == FAILURE) { | ||
RETURN_THROWS(); | ||
} | ||
|
||
object_init_ex(&object, zend_get_called_scope(execute_data)); | ||
|
||
construct_date_period(INTERNAL_FUNCTION_PARAM_PASSTHRU, &object, NULL, NULL, NULL, 0, options, isostr, isostr_len); | ||
if (EG(exception)) { | ||
zval_ptr_dtor(&object); | ||
RETURN_THROWS(); | ||
} | ||
|
||
ZVAL_COPY_VALUE(return_value, &object); | ||
} | ||
|
||
/* Creates new DatePeriod object. */ | ||
PHP_METHOD(DatePeriod, __construct) | ||
{ | ||
zval *start, *end = NULL, *interval; | ||
zend_long recurrences = 0, options = 0; | ||
char *isostr = NULL; | ||
size_t isostr_len = 0; | ||
|
||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "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(), "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(), "s|l", &isostr, &isostr_len, &options) == FAILURE) { | ||
zend_type_error("DatePeriod::__construct() accepts (DateTimeInterface, DateInterval, int [, int]), or (DateTimeInterface, DateInterval, DateTime [, int]), or (string [, int]) as arguments"); | ||
RETURN_THROWS(); | ||
} | ||
} | ||
} | ||
|
||
construct_date_period(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_THIS, start, end, interval, recurrences, options, isostr, isostr_len); | ||
} | ||
|
||
/* {{{ Get start date. */ | ||
PHP_METHOD(DatePeriod, getStartDate) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -398,6 +398,12 @@ public static function __set_state(array $array) {} | |
|
||
class DatePeriod implements IteratorAggregate | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should decide what to do with the overloaded constructor:
Depending on the outcome, we could only have 2 factory methods, and the 3rd signature could be implemented by the constructor |
||
{ | ||
public static function createFromRecurrences(DateTimeInterface $start, DateInterval $interval, int $recurrences, int $options = 0): static {} | ||
|
||
public static function createFromDates(DateTimeInterface $start, DateInterval $interval, DateTimeInterface $end, int $options = 0): static {} | ||
|
||
public static function createFromIso8601(string $specification, int $options = 0): static {} | ||
|
||
/** | ||
* @param DateTimeInterface|string $start | ||
* @param DateInterval|int $interval | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
--TEST-- | ||
Test DatePeriod::createFromDates() | ||
--FILE-- | ||
<?php | ||
|
||
class MyDatePeriod extends DatePeriod | ||
{ | ||
} | ||
|
||
$start = new DateTime(); | ||
$end = new DateTime("+2 days"); | ||
$interval = new DateInterval("P1D"); | ||
|
||
$p1 = MyDatePeriod::createFromDates($start, $interval, $end); | ||
$p2 = new MyDatePeriod($start, $interval, $end); | ||
|
||
var_dump($p1::class); | ||
var_dump($p1 == $p2); | ||
|
||
?> | ||
--EXPECT-- | ||
string(12) "MyDatePeriod" | ||
bool(true) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--TEST-- | ||
Test DatePeriod::createFromIso8601() | ||
--FILE-- | ||
<?php | ||
|
||
class MyDatePeriod extends DatePeriod | ||
{ | ||
} | ||
|
||
$p1 = MyDatePeriod::createFromIso8601("R4/2012-07-01T00:00:00Z/P7D"); | ||
$p2 = new MyDatePeriod("R4/2012-07-01T00:00:00Z/P7D"); | ||
|
||
var_dump($p1::class); | ||
var_dump($p1 == $p2); | ||
|
||
try { | ||
MyDatePeriod::createFromIso8601(""); | ||
} catch (Exception $exception) { | ||
echo $exception->getMessage() . "\n"; | ||
} | ||
|
||
?> | ||
--EXPECT-- | ||
string(12) "MyDatePeriod" | ||
bool(true) | ||
DatePeriod::createFromIso8601(): Unknown or bad format () |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
--TEST-- | ||
Test DatePeriod::createFromRecurrences() | ||
--FILE-- | ||
<?php | ||
|
||
class MyDatePeriod extends DatePeriod | ||
{ | ||
} | ||
|
||
$start = new DateTime(); | ||
$interval = new DateInterval("P1D"); | ||
|
||
$p1 = MyDatePeriod::createFromRecurrences($start, $interval, 2); | ||
$p2 = new MyDatePeriod($start, $interval, 2); | ||
|
||
var_dump($p1::class); | ||
var_dump($p1 == $p2); | ||
|
||
try { | ||
MyDatePeriod::createFromRecurrences($start, $interval, 0); | ||
} catch (Exception $exception) { | ||
echo $exception->getMessage() . "\n"; | ||
} | ||
|
||
?> | ||
--EXPECT-- | ||
string(12) "MyDatePeriod" | ||
bool(true) | ||
DatePeriod::createFromRecurrences(): Recurrence count must be greater than 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer it if this initialisation function gets split as well. The old
__construct
should use the new (3) initialisation methods, which also makes it easier to clean up in for example PHP 9.0. It can also mean that error and bounds checking (for example, recurrences can't be negative) to the right and logical position.