Commit 15c02997 authored by alexpott's avatar alexpott

Issue #2910081 by mpdonadio, neclimdul, gambry, jhedstrom, alexpott:...

Issue #2910081 by mpdonadio, neclimdul, gambry, jhedstrom, alexpott: DateTimePlus calls should be chainable
parent 43c0eca7
......@@ -306,8 +306,25 @@ public function render() {
* Implements the magic __call method.
*
* Passes through all unknown calls onto the DateTime object.
*
* @param string $method
* The method to call on the decorated object.
* @param array $args
* Call arguments.
*
* @return mixed
* The return value from the method on the decorated object. If the proxied
* method call returns a DateTime object, then return the original
* DateTimePlus object, which allows function chaining to work properly.
* Otherwise, the value from the proxied method call is returned.
*
* @throws \Exception
* Thrown when the DateTime object is not set.
* @throws \BadMethodCallException
* Thrown when there is no corresponding method on the DateTime object to
* call.
*/
public function __call($method, $args) {
public function __call($method, array $args) {
// @todo consider using assert() as per https://www.drupal.org/node/2451793.
if (!isset($this->dateTimeObject)) {
throw new \Exception('DateTime object not set.');
......@@ -315,7 +332,10 @@ public function __call($method, $args) {
if (!method_exists($this->dateTimeObject, $method)) {
throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
}
return call_user_func_array([$this->dateTimeObject, $method], $args);
$result = call_user_func_array([$this->dateTimeObject, $method], $args);
return $result === $this->dateTimeObject ? $this : $result;
}
/**
......
......@@ -804,7 +804,6 @@ public function testValidateFormat() {
$date = DateTimePlus::createFromFormat('Y-m-d H:i:s', '11-03-31 17:44:00', 'UTC', ['validate_format' => TRUE]);
}
/**
* Tests setting the default time for date-only objects.
*/
......@@ -817,4 +816,52 @@ public function testDefaultDateTime() {
$this->assertEquals('12:00:00', $date->format('H:i:s'));
}
/**
* Tests that object methods are chainable.
*
* @covers ::__call
*/
public function testChainable() {
$date = new DateTimePlus('now', 'Australia/Sydney');
$date->setTimestamp(12345678);
$rendered = $date->render();
$this->assertEquals('1970-05-24 07:21:18 Australia/Sydney', $rendered);
$date->setTimestamp(23456789);
$rendered = $date->setTimezone(new \DateTimeZone('America/New_York'))->render();
$this->assertEquals('1970-09-29 07:46:29 America/New_York', $rendered);
$date = DateTimePlus::createFromFormat('Y-m-d H:i:s', '1970-05-24 07:21:18', new \DateTimeZone('Australia/Sydney'))
->setTimezone(new \DateTimeZone('America/New_York'));
$rendered = $date->render();
$this->assertInstanceOf(DateTimePlus::class, $date);
$this->assertEquals(12345678, $date->getTimestamp());
$this->assertEquals('1970-05-23 17:21:18 America/New_York', $rendered);
}
/**
* Tests that non-chainable methods work.
*
* @covers ::__call
*/
public function testChainableNonChainable() {
$datetime1 = new DateTimePlus('2009-10-11 12:00:00');
$datetime2 = new DateTimePlus('2009-10-13 12:00:00');
$interval = $datetime1->diff($datetime2);
$this->assertInstanceOf(\DateInterval::class, $interval);
$this->assertEquals('+2 days', $interval->format('%R%a days'));
}
/**
* Tests that chained calls to non-existent functions throw an exception.
*
* @covers ::__call
*/
public function testChainableNonCallable() {
$this->setExpectedException(\BadMethodCallException::class, 'Call to undefined method Drupal\Component\Datetime\DateTimePlus::nonexistent()');
$date = new DateTimePlus('now', 'Australia/Sydney');
$date->setTimezone(new \DateTimeZone('America/New_York'))->nonexistent();
}
}
......@@ -168,4 +168,48 @@ public function testDefaultDateTime() {
$this->assertEquals('12:00:00', $date->format('H:i:s'));
}
/**
* Tests that object methods are chainable.
*
* @covers ::__call
*/
public function testChainable() {
$tz = new \DateTimeZone(date_default_timezone_get());
$date = new DrupalDateTime('now', $tz, ['langcode' => 'en']);
$date->setTimestamp(12345678);
$rendered = $date->render();
$this->assertEquals('1970-05-24 07:21:18 Australia/Sydney', $rendered);
$date->setTimestamp(23456789);
$rendered = $date->setTimezone(new \DateTimeZone('America/New_York'))->render();
$this->assertEquals('1970-09-29 07:46:29 America/New_York', $rendered);
}
/**
* Tests that non-chainable methods work.
*
* @covers ::__call
*/
public function testChainableNonChainable() {
$tz = new \DateTimeZone(date_default_timezone_get());
$datetime1 = new DrupalDateTime('2009-10-11 12:00:00', $tz, ['langcode' => 'en']);
$datetime2 = new DrupalDateTime('2009-10-13 12:00:00', $tz, ['langcode' => 'en']);
$interval = $datetime1->diff($datetime2);
$this->assertInstanceOf(\DateInterval::class, $interval);
$this->assertEquals('+2 days', $interval->format('%R%a days'));
}
/**
* Tests that chained calls to non-existent functions throw an exception.
*
* @covers ::__call
*/
public function testChainableNonCallable() {
$this->setExpectedException(\BadMethodCallException::class, 'Call to undefined method Drupal\Core\Datetime\DrupalDateTime::nonexistent()');
$tz = new \DateTimeZone(date_default_timezone_get());
$date = new DrupalDateTime('now', $tz, ['langcode' => 'en']);
$date->setTimezone(new \DateTimeZone('America/New_York'))->nonexistent();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment