Problem/Motivation

DateTimePlus doesn't initialize DateTimePlus::errors properly, and doesn't handle the errors from date_parse properly.

Contributor tasks needed
Task Novice task? Contributor instructions Complete?
Create a patch Instructions Done
Add automated tests Instructions Done
Update the patch to incorporate feedback from reviews (include an interdiff) Instructions Done
Manually test the patch Novice Instructions Done
Review patch to ensure that it fixes the issue, stays within scope, is properly documented, and follows coding standards Instructions Done

Comments

mpdonadio created an issue. See original summary.

mpdonadio’s picture

Status: Active » Needs review
Related issues: +#2824717: Add a format constraint to DateTimeItem to provide REST error message
StatusFileSize
new1.12 KB
mpdonadio’s picture

Status: Needs review » Needs work
  1. +++ b/core/lib/Drupal/Component/Datetime/DateTimePlus.php
    @@ -268,10 +268,11 @@ public function __construct($time = 'now', $timezone = NULL, $settings = []) {
    -          $this->errors[] = $test['errors'];
    +          $this->errors += array_values($test['errors']);
    

    This is the problem and the basic fix. Per http://php.net/manual/en/function.date-parse.php, $test['errors'] is an array, so we need to merge them in with anything else that may have been set during preparation. HEAD just pushes the errors array onto the errors, resulting in a multidimensional array.

  2. +++ b/core/lib/Drupal/Component/Datetime/DateTimePlus.php
    @@ -442,7 +443,7 @@ protected function prepareFormat($format) {
    -      $this->errors += $errors['errors'];
    +      $this->errors += array_values($errors['errors']);
    

    += is probably wrong here, and above. We need to ignore the keys and just tack on the values to the array. Need to be fixed.

This patch is going to come up green. The first point (1) fixed above should have triggered a notice w/o the patch, which would cause a test fail in HEAD; nothing in this patch will change that. I suspect we are only testing invalid input with the static factory methods, so this part of the constructor logic isn't being exercised properly with bad values in DateTimePlusTest. Hence the Needs Tests tag and setting this back to Needs Work.

(edited to actually make sense...)

goz’s picture

+++ b/core/lib/Drupal/Component/Datetime/DateTimePlus.php
@@ -268,10 +268,11 @@ public function __construct($time = 'now', $timezone = NULL, $settings = []) {
@@ -442,7 +443,7 @@ protected function prepareFormat($format) {

@@ -442,7 +443,7 @@ protected function prepareFormat($format) {
   public function checkErrors() {
     $errors = \DateTime::getLastErrors();
     if (!empty($errors['errors'])) {
-      $this->errors += $errors['errors'];
...
     }

We should not just use array_values() here. += merge arrays depending of keys. In case $errors = ['error 1', 'error 2']; and $errors['errors'] = ['error 2', 'error 3'];, $this->errors += array_values($errors['errors']); will still result to ['error 1', 'error 2']

Should use something like.

$this->errors = array_merge($this->errors, array_values($errors['errors']));

Tests should reproduce this case (+ 1 patch with only test which should fail)

goz’s picture

Issue summary: View changes
goz’s picture

Issue summary: View changes
goz’s picture

Issue summary: View changes
mpdonadio’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new1.46 KB
new2.63 KB

Still need to double check this fixes the problem I found in #2824717: Add a format constraint to DateTimeItem to provide REST error message, but here is the more better error merging with test coverage, which shows the problem.

Edit: Yes, this fixes the other issue. This is ready for review.

The last submitted patch, 8: 2858295-test-only.patch, failed testing.

wim leers’s picture

Status: Needs review » Reviewed & tested by the community
  1. +++ b/core/lib/Drupal/Component/Datetime/DateTimePlus.php
    @@ -268,10 +268,11 @@ public function __construct($time = 'now', $timezone = NULL, $settings = []) {
    -          $this->errors[] = $test['errors'];
    +          $this->errors = array_merge($this->errors, array_values($test['errors']));
    
    @@ -442,7 +443,7 @@ protected function prepareFormat($format) {
    -      $this->errors += $errors['errors'];
    +      $this->errors = array_merge($this->errors, array_values($errors['errors']));
    

    This is the bugfix. Makes sense.

  2. +++ b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php
    @@ -670,4 +670,45 @@ public function providerTestInvalidDateDiff() {
    +   * @return array
    

    Nit: string[]

goz’s picture

Issue summary: View changes

Looks good. Nice catch, thanks mpdonadio

goz’s picture

Issue summary: View changes

Miss to check one step in summary

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php
@@ -670,4 +670,45 @@ public function providerTestInvalidDateDiff() {
+    // Make sure all of the errors are unique strings.
+    $errors = $date->getErrors();
+    $this->assertEquals(FALSE, in_array(FALSE, array_map('is_string', $errors)));
+    $this->assertEquals(count($errors), count(array_unique($errors)));

Why are we not just asserting what $date->getErrors() returns? This seems a bit fragile.

Also the return of $date->getErrors() for ['YYYY-MM-DD'] is:

Array
(
    [0] => The timezone could not be found in the database
    [1] => Unexpected character
    [3] => Double timezone specification
)

The array indexing looks weird.

wim leers’s picture

Issue tags: +blocker, +API-First Initiative
mpdonadio’s picture

Status: Needs work » Needs review
StatusFileSize
new4.19 KB
new3.7 KB

Should address #13.

mpdonadio’s picture

StatusFileSize
new4.25 KB
new1001 bytes

Picking my own nits to make this consistent, and fix a phpcs warning on a changed hunk.

The last submitted patch, 15: 2858295-15.patch, failed testing.

wim leers’s picture

Status: Needs review » Needs work

Thanks!

  1. +++ b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php
    @@ -670,4 +670,96 @@ public function providerTestInvalidDateDiff() {
    +   *   A array of errors messages.
    

    Nit: s/errors messages/error messages/

  2. +++ b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php
    @@ -670,4 +670,96 @@ public function providerTestInvalidDateDiff() {
    +    // Make sure the parsed date/time has errors.
    +    $this->assertEquals(TRUE, $date->hasErrors());
    

    Nit: this comment seems pointless.

  3. +++ b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php
    @@ -670,4 +670,96 @@ public function providerTestInvalidDateDiff() {
    +    // Make sure all of the errors are unique strings.
    +    $this->assertEquals($errors, $date->getErrors());
    

    This comment seems wrong.

mpdonadio’s picture

Status: Needs work » Needs review
StatusFileSize
new4.14 KB
new975 bytes

I think that test method reads fine w/o the comments; the class methods have decent names on them so it is pretty apparent what is being tested now.

The last submitted patch, 16: 2858295-16.patch, failed testing.

wim leers’s picture

Status: Needs review » Reviewed & tested by the community

Exactly :)

Back to RTBC!

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/lib/Drupal/Component/Datetime/DateTimePlus.php
@@ -268,10 +268,11 @@ public function __construct($time = 'now', $timezone = NULL, $settings = []) {
-          $this->errors[] = $test['errors'];
+          $this->errors = array_merge($this->errors, array_values($test['errors']));

This looks weird. Why do we need to array_merge() after $this->errors = [];?

Can't we just do $this->errors = $test['errors'];?

mpdonadio’s picture

Status: Needs work » Needs review
StatusFileSize
new4.08 KB
new1.1 KB

#22 is addressed. Also can remove another array_values() b/c array_merge() rekeys numeric indexes.

Double checked this against #2824717: Add a format constraint to DateTimeItem to provide REST error message and it will unblock it.

chiranjeeb2410’s picture

Status: Needs review » Reviewed & tested by the community

@mpdonadio,

Changes look good and patch applies cleanly. Changing to RTBC.

alexpott’s picture

Version: 8.4.x-dev » 8.3.x-dev
Status: Reviewed & tested by the community » Patch (to be ported)

Committed ade0589 and pushed to 8.4.x. Thanks!

I'm pretty certain we should put this in 8.3.x - as we're in RC going to get a +1 from another committer before cherry-picking.

  • alexpott committed ade0589 on 8.4.x
    Issue #2858295 by mpdonadio, GoZ, Wim Leers, alexpott: DateTimePlus...
catch’s picture

+1 on cherry-picking back to 8.3.x.

  • alexpott committed 52e84ae on 8.3.x
    Issue #2858295 by mpdonadio, GoZ, Wim Leers, alexpott: DateTimePlus...
alexpott’s picture

Status: Patch (to be ported) » Fixed

Committed 52e84ae and pushed to 8.3.x. Thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.