ソースを参照

Updated DateTimeWidget to show milliseconds for fractional types

Corey Taylor 6 年 前
コミット
c63778cbcc

+ 3 - 0
src/View/Helper/FormHelper.php

@@ -69,7 +69,9 @@ class FormHelper extends Helper
             'text' => 'textarea',
             'uuid' => 'string',
             'datetime' => 'datetime',
+            'datetimefractional' => 'datetime',
             'timestamp' => 'datetime',
+            'timestampfractional' => 'datetime',
             'date' => 'date',
             'time' => 'time',
             'year' => 'year',
@@ -2195,6 +2197,7 @@ class FormHelper extends Helper
         ];
         $options = $this->_initInputField($fieldName, $options);
         $options['type'] = 'datetime-local';
+        $options['fieldName'] = $fieldName;
 
         return $this->widget('datetime', $options);
     }

+ 36 - 4
src/View/Widget/DateTimeWidget.php

@@ -16,6 +16,7 @@ declare(strict_types=1);
  */
 namespace Cake\View\Widget;
 
+use Cake\Database\Schema\TableSchema;
 use Cake\View\Form\ContextInterface;
 use Cake\View\StringTemplate;
 use DateTime;
@@ -45,7 +46,7 @@ class DateTimeWidget implements WidgetInterface
      * @var string[]
      */
     protected $formatMap = [
-        'datetime-local' => 'Y-m-d\TH:i:s',
+        'datetime-local' => 'Y-m-d\TH:i:s.v',
         'date' => 'Y-m-d',
         'time' => 'H:i:s',
         'month' => 'Y-m',
@@ -53,6 +54,18 @@ class DateTimeWidget implements WidgetInterface
     ];
 
     /**
+     * Step size for various input types.
+     *
+     * If not set, defaults to browser default.
+     *
+     * @var string[]
+     */
+    protected $defaultStep = [
+        'datetime-local' => '1',
+        'time' => '1',
+    ];
+
+    /**
      * Constructor
      *
      * @param \Cake\View\StringTemplate $templates Templates list.
@@ -86,16 +99,35 @@ class DateTimeWidget implements WidgetInterface
             'val' => null,
             'type' => 'datetime-local',
             'escape' => true,
+            'step' => null,
             'timezone' => null,
             'templateVars' => [],
         ];
 
-        if ($data['type'] === 'datetime-local' || $data['type'] === 'time') {
-            $data += ['step' => '1'];
+        if (!isset($data['step'])) {
+            $step = null;
+            if (isset($this->defaultStep[$data['type']])) {
+                $step = $this->defaultStep[$data['type']];
+            }
+
+            if (isset($data['fieldName'])) {
+                $schemaType = $context->type($data['fieldName']);
+                if ($schemaType !== null) {
+                    $fractionalTypes = [
+                        TableSchema::TYPE_DATETIME_FRACTIONAL,
+                        TableSchema::TYPE_TIMESTAMP_FRACTIONAL,
+                    ];
+                    if (in_array($schemaType, $fractionalTypes)) {
+                        $step = '0.001';
+                    }
+                }
+            }
+
+            $data['step'] = $step;
         }
 
         $data['value'] = $this->formatDateTime($data['val'], $data);
-        unset($data['val'], $data['timezone']);
+        unset($data['val'], $data['timezone'], $data['fieldName']);
 
         return $this->_templates->format('input', [
             'name' => $data['name'],

+ 65 - 5
tests/TestCase/View/Helper/FormHelperTest.php

@@ -3437,7 +3437,7 @@ class FormHelperTest extends TestCase
                 'name' => 'prueba',
                 'id' => 'prueba',
                 'type' => 'datetime-local',
-                'value' => '2019-09-27T02:52:43',
+                'value' => '2019-09-27T02:52:43.000',
                 'step' => '1',
             ],
             '/div',
@@ -3477,6 +3477,37 @@ class FormHelperTest extends TestCase
     }
 
     /**
+     * testControlDatetimeStep method
+     *
+     * Test form->control() with datetime with custom step size.
+     *
+     * @return void
+     */
+    public function testControlDatetimeStep()
+    {
+        $result = $this->Form->control('prueba', [
+            'type' => 'datetime',
+            'value' => new FrozenTime('2019-09-27 02:52:43'),
+            'step' => '0.5',
+        ]);
+        $expected = [
+            'div' => ['class' => 'input datetime'],
+            'label' => ['for' => 'prueba'],
+            'Prueba',
+            '/label',
+            'input' => [
+                'name' => 'prueba',
+                'id' => 'prueba',
+                'type' => 'datetime-local',
+                'value' => '2019-09-27T02:52:43.000',
+                'step' => '0.5',
+            ],
+            '/div',
+        ];
+        $this->assertHtml($expected, $result);
+    }
+
+    /**
      * testControlCheckboxWithDisabledElements method
      *
      * Test generating checkboxes with disabled elements.
@@ -6034,7 +6065,7 @@ class FormHelperTest extends TestCase
             'input' => [
                 'type' => 'datetime-local',
                 'name' => 'date',
-                'value' => 'preg:/' . date('Y-m-d') . 'T\d{2}:\d{2}:\d{2}/',
+                'value' => 'preg:/' . date('Y-m-d') . 'T\d{2}:\d{2}:\d{2}\.\d{3}/',
                 'step' => '1',
             ],
         ];
@@ -6108,7 +6139,7 @@ class FormHelperTest extends TestCase
             'input' => [
                 'type' => 'datetime-local',
                 'name' => 'updated',
-                'value' => '2009-06-01T11:15:30',
+                'value' => '2009-06-01T11:15:30.000',
                 'step' => '1',
             ],
         ];
@@ -6121,7 +6152,7 @@ class FormHelperTest extends TestCase
             'input' => [
                 'type' => 'datetime-local',
                 'name' => 'updated',
-                'value' => '2009-06-01T11:15:30',
+                'value' => '2009-06-01T11:15:30.000',
                 'step' => '1',
             ],
         ];
@@ -7345,7 +7376,7 @@ class FormHelperTest extends TestCase
             'input' => [
                 'type' => 'datetime-local',
                 'name' => 'created',
-                'value' => 'preg:/' . date('Y-m-d') . 'T\d{2}:\d{2}:\d{2}/',
+                'value' => 'preg:/' . date('Y-m-d') . 'T\d{2}:\d{2}:\d{2}\.\d{3}/',
                 'step' => '1',
             ],
         ];
@@ -7354,6 +7385,35 @@ class FormHelperTest extends TestCase
     }
 
     /**
+     * testDateTimeWithFractional method
+     *
+     * Test that datetime() works with datetimefractional.
+     *
+     * @return void
+     */
+    public function testDateTimeWithFractional()
+    {
+        $this->Form->create([
+            'schema' => [
+                'created' => ['type' => 'datetimefractional'],
+            ],
+        ]);
+        $result = $this->Form->datetime('created', [
+            'val' => new FrozenTime('2019-09-27 02:52:43'),
+        ]);
+        $expected = [
+            'input' => [
+                'type' => 'datetime-local',
+                'name' => 'created',
+                'value' => '2019-09-27T02:52:43.000',
+                'step' => '0.001',
+            ],
+        ];
+
+        $this->assertHtml($expected, $result);
+    }
+
+    /**
      * testForMagicControlNonExistingNorValidated method
      *
      * @return void

+ 2 - 2
tests/TestCase/View/Widget/DateTimeWidgetTest.php

@@ -104,7 +104,7 @@ class DateTimeWidgetTest extends TestCase
             'input' => [
                 'type' => 'datetime-local',
                 'name' => '',
-                'value' => '2014-01-20T12:30:45',
+                'value' => '2014-01-20T12:30:45.000',
                 'step' => '1',
             ],
         ];
@@ -126,7 +126,7 @@ class DateTimeWidgetTest extends TestCase
             'input' => [
                 'type' => 'datetime-local',
                 'name' => '',
-                'value' => '2019-02-03T15:30:00',
+                'value' => '2019-02-03T15:30:00.000',
                 'step' => '1',
             ],
         ];