Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Start fixing Datetime widget.

- We will probably never use Day of the week selectors.
- Fix selected value handling. DateTime instances come with timezones.
  All other formats are naive and should be avoided anyways.
- Mark non-functioning tests as incomplete.
  • Loading branch information...
commit cfb201dbd9b344d6c48689d5b004e99f8d7ad56f 1 parent 84d5927
@markstory markstory authored
Showing with 97 additions and 111 deletions.
  1. +60 −92 src/View/Input/DateTime.php
  2. +37 −19 tests/TestCase/View/Input/DateTimeTest.php
View
152 src/View/Input/DateTime.php
@@ -14,6 +14,7 @@
*/
namespace Cake\View\Input;
+use Cake\View\Input\InputInterface;
use Cake\View\StringTemplate;
use Cake\Utility\Time;
@@ -23,14 +24,21 @@
* This class is intended as an internal implementation detail
* of Cake\View\Helper\FormHelper and is not intended for direct use.
*/
-class DateTime {
+class DateTime implements InputInterface {
+
+/**
+ * Select box widget.
+ *
+ * @var Cake\View\Input\Select;
+ */
+ protected $_select;
/**
* List of inputs that can be rendered
*
* @var array
*/
- public $selects = [
+ protected $_selects = [
'year',
'month',
'day',
@@ -47,28 +55,13 @@ class DateTime {
protected $_templates;
/**
- * Deconstructed date
- *
- * @var array
- */
- protected $_date = [
- 'year' => null,
- 'month' => null,
- 'day' => null,
- 'hour' => null,
- 'minute' => null,
- 'second' => null,
- ];
-
-/**
* Constructor
*
- * @param \Cake\View\StringTemplate $templates
- * @param \Cake\View\Input\SelectBox $SelectBox
- * @return \Cake\View\Input\DateTime
+ * @param Cake\View\StringTemplate $templates
+ * @param Cake\View\Input\SelectBox $selectBox
*/
- public function __construct(StringTemplate $templates, SelectBox $SelectBox) {
- $this->SelectBox = $SelectBox;
+ public function __construct($templates, $selectBox) {
+ $this->_select = $selectBox;
$this->_templates = $templates;
}
@@ -77,7 +70,7 @@ public function __construct(StringTemplate $templates, SelectBox $SelectBox) {
*
* - `name` - Set the input name.
* - `disabled` - Either true or an array of options to disable.
- * - `value` - A date time string, integer or DateTime object
+ * - `val` - A date time string, integer or DateTime object
* - `empty` - Set to true to add an empty option at the top of the
* option elements. Set to a string to define the display value of the
* empty option.
@@ -87,18 +80,17 @@ public function __construct(StringTemplate $templates, SelectBox $SelectBox) {
* - `hour` - Array of options for the hour select box.
* - `minute` - Array of options for the minute select box.
* - `second` - Array of options for the second select box.
- * - `timeZone` - Timezone string or DateTimeZone object.
*
* @param array $data Data to render with.
* @return string A generated select box.
* @throws \RuntimeException when the name attribute is empty.
*/
- public function render($data = []) {
+ public function render(array $data) {
$data += [
'name' => 'data',
'empty' => false,
'disabled' => null,
- 'value' => new \DateTime(),
+ 'val' => new \DateTime(),
'year' => [],
'month' => [
'names' => false,
@@ -109,19 +101,16 @@ public function render($data = []) {
'hour' => [],
'minute' => [],
'second' => [],
- 'timeZone' => null
];
- if (!empty($data['value'])) {
- $this->_deconstuctDate($data['value'], $data['timeZone']);
- }
+ $selected = $this->_deconstuctDate($data['val']);
$templateOptions = [];
- foreach ($this->selects as $select) {
+ foreach ($this->_selects as $select) {
if ($data[$select] !== false) {
$method = $select . 'Select';
- $data[$select]['name'] = $data['name'] . "['" . $select . "']";
- $data[$select]['value'] = $this->_date[$select];
+ $data[$select]['name'] = $data['name'] . "[" . $select . "]";
+ $data[$select]['val'] = $selected[$select];
$data[$select]['empty'] = $data['empty'];
$data[$select]['disabled'] = $data['disabled'];
$data[$select] += $data[$select];
@@ -129,7 +118,7 @@ public function render($data = []) {
}
unset($data[$select]);
}
- unset($data['name'], $data['empty'], $data['disabled'], $data['value'], $data['timeZone']);
+ unset($data['name'], $data['empty'], $data['disabled'], $data['val']);
$templateOptions['attrs'] = $this->_templates->formatAttributes($data);
return $this->_templates->format('dateWidget', $templateOptions);
}
@@ -137,18 +126,33 @@ public function render($data = []) {
/**
* Deconstructs the passed date value into all time units
*
- * @param string|integer|DateTime $date
- * @param string|DateTimeZone
+ * @param string|integer|array|DateTime $value
* @return array
*/
- protected function _deconstuctDate($date, $timeZone = null) {
- $this->_date = [
- 'year' => Time::format($date, '%Y', null, $timeZone),
- 'month' => Time::format($date, '%m', null, $timeZone),
- 'day' => Time::format($date, '%d', null, $timeZone),
- 'hour' => Time::format($date, '%H', null, $timeZone),
- 'minute' => Time::format($date, '%M', null, $timeZone),
- 'second' => Time::format($date, '%S', null, $timeZone),
+ protected function _deconstuctDate($value) {
+ if (is_string($value)) {
+ $date = new \DateTime($value);
+ } elseif (is_int($value)) {
+ $date = new \DateTime('@' . $value);
+ } elseif (is_array($value)) {
+ $date = new \DateTime();
+ if (isset($value['year'], $value['month'], $value['day'])) {
+ $date->setDate($value['year'], $value['month'], $value['day']);
+ }
+ if (isset($value['hour'], $value['minute'], $value['second'])) {
+ $date->setTime($value['hour'], $value['minute'], $value['second']);
+ }
+ } else {
+ $date = $value;
+ }
+
+ return [
+ 'year' => $date->format('Y'),
+ 'month' => $date->format('m'),
+ 'day' => $date->format('d'),
+ 'hour' => $date->format('H'),
+ 'minute' => $date->format('i'),
+ 'second' => $date->format('s')
];
}
@@ -161,7 +165,7 @@ protected function _deconstuctDate($date, $timeZone = null) {
public function yearSelect($options = []) {
$options += [
'name' => 'data[year]',
- 'value' => null,
+ 'val' => null,
'start' => date('Y', strtotime('-5 years')),
'end' => date('Y', strtotime('+5 years')),
'options' => []
@@ -171,7 +175,7 @@ public function yearSelect($options = []) {
$options['options'] = $this->_generateNumbers($options['start'], $options['end']);
}
- return $this->SelectBox->render($options);
+ return $this->_select->render($options);
}
/**
@@ -184,7 +188,7 @@ public function monthSelect($options = []) {
$options += [
'name' => 'data[month]',
'names' => false,
- 'value' => null,
+ 'val' => null,
'leadingZeroKey' => true,
'leadingZeroValue' => true
];
@@ -198,7 +202,7 @@ public function monthSelect($options = []) {
}
unset($options['leadingZeroKey'], $options['leadingZeroValue'], $options['names']);
- return $this->SelectBox->render($options);
+ return $this->_select->render($options);
}
/**
@@ -210,21 +214,14 @@ public function monthSelect($options = []) {
public function daySelect($options = []) {
$options += [
'name' => 'data[day]',
- 'names' => false,
- 'value' => null,
+ 'val' => null,
'leadingZeroKey' => true,
'leadingZeroValue' => true,
];
+ $options['options'] = $this->_generateNumbers(1, 31, $options);
- if ($options['names'] === true) {
- $options['options'] = $this->_getDayNames($options['leadingZeroKey']);
- } else {
- $options['options'] = $this->_generateNumbers(1, 7, $options);
- }
-
- $options['value'] = Time::format($options['value'], '%d');
unset($options['names'], $options['leadingZeroKey'], $options['leadingZeroValue']);
- return $this->SelectBox->render($options);
+ return $this->_select->render($options);
}
/**
@@ -236,14 +233,14 @@ public function daySelect($options = []) {
public function hourSelect($options = []) {
$options += [
'name' => 'data[hour]',
- 'value' => null,
+ 'val' => null,
'leadingZeroKey' => true,
'leadingZeroValue' => true,
'options' => $this->_generateNumbers(1, 24)
];
unset($options['leadingZeroKey'], $options['leadingZeroValue']);
- return $this->SelectBox->render($options);
+ return $this->_select->render($options);
}
/**
@@ -255,14 +252,14 @@ public function hourSelect($options = []) {
public function minuteSelect($options = []) {
$options += [
'name' => 'data[minute]',
- 'value' => null,
+ 'val' => null,
'leadingZeroKey' => true,
'leadingZeroValue' => true,
'options' => $this->_generateNumbers(1, 60)
];
unset($options['leadingZeroKey'], $options['leadingZeroValue']);
- return $this->SelectBox->render($options);
+ return $this->_select->render($options);
}
/**
@@ -274,14 +271,14 @@ public function minuteSelect($options = []) {
public function secondSelect($options = []) {
$options += [
'name' => 'data[second]',
- 'value' => null,
+ 'val' => null,
'leadingZeroKey' => true,
'leadingZeroValue' => true,
'options' => $this->_generateNumbers(1, 60)
];
unset($options['leadingZeroKey'], $options['leadingZeroValue']);
- return $this->SelectBox->render($options);
+ return $this->_select->render($options);
}
/**
@@ -318,35 +315,6 @@ protected function _getMonthNames($leadingZero = false) {
}
/**
- * Returns a translated list of day names
- *
- * @todo find a way to define the first day of week
- * @param boolean $leadingZero
- * @return array
- */
- protected function _getDayNames($leadingZero = true) {
- $days = [
- '01' => __d('cake', 'Monday'),
- '02' => __d('cake', 'Tuesday'),
- '03' => __d('cake', 'Wednesday'),
- '04' => __d('cake', 'Thursday'),
- '05' => __d('cake', 'Friday'),
- '06' => __d('cake', 'Saturday'),
- '07' => __d('cake', 'Sunday'),
- ];
-
- if ($leadingZero === false) {
- $i = 1;
- foreach ($days as $key => $name) {
- $days[$i++] = $name;
- unset($days[$key]);
- }
- }
-
- return $days;
- }
-
-/**
* Generates a range of numbers
*
* @param integer $start Start of the range of numbers to generate
View
56 tests/TestCase/View/Input/DateTimeTest.php
@@ -19,16 +19,15 @@
use Cake\View\StringTemplate;
class DateTime extends \Cake\View\Input\DateTime {
+
public function generateNumbers($start = 1, $end = 31, $options = []) {
return parent::_generateNumbers($start, $end, $options);
}
- public function getDayNames($leadingZero = true) {
- return parent::_getDayNames($leadingZero);
- }
+
}
/**
- * SelectBox test case
+ * DateTime input test case
*/
class DateTimeTest extends TestCase {
@@ -44,31 +43,45 @@ public function setUp() {
'selectMultiple' => '<select name="{{name}}[]" multiple="multiple"{{attrs}}>{{content}}</select>',
'option' => '<option value="{{value}}"{{attrs}}>{{text}}</option>',
'optgroup' => '<optgroup label="{{label}}"{{attrs}}>{{content}}</optgroup>',
- 'dateWidget' => '<div{{attrs}}>{{year}}-{{month}}-{{day}} {{hour}}:{{minute}}:{{second}}{{timeZone}}</div>'
+ 'dateWidget' => '<div{{attrs}}>{{year}}-{{month}}-{{day}} {{hour}}:{{minute}}:{{second}}</div>'
];
- $this->templates = new StringTemplate();
- $this->templates->add($templates);
- $this->SelectBox = new SelectBox($this->templates);
- $this->DateTime = new DateTime($this->templates, $this->SelectBox);
+ $this->templates = new StringTemplate($templates);
+ $this->selectBox = new SelectBox($this->templates);
+ $this->DateTime = new DateTime($this->templates, $this->selectBox);
}
/**
- * testRenderNoOptions
+ * Data provider for testing various acceptable selected values.
*
- * @return void
+ * @return array
*/
- public function testRenderNoOptions() {
- $result = $this->DateTime->render();
+ public static function selectedValuesProvider() {
+ $date = new \DateTime('2014-01-20 12:30:45');
+ return [
+ 'DateTime' => [$date],
+ 'string' => [$date->format('Y-m-d H:i:s')],
+ 'int' => [$date->getTimestamp()],
+ 'array' => [[
+ 'year' => '2014', 'month' => '01', 'day' => '20',
+ 'hour' => '12', 'minute' => '30', 'second' => '45',
+ ]]
+ ];
}
/**
- * testGetDayNames
+ * test rendering selected values.
*
+ * @dataProvider selectedValuesProvider
* @return void
*/
- public function testGetDayNames() {
- $result = $this->DateTime->getDayNames();
- $result = $this->DateTime->getDayNames(false);
+ public function testRenderSelected($selected) {
+ $result = $this->DateTime->render(['val' => $selected]);
+ $this->assertContains('<option value="2014" selected="selected">2014</option>', $result);
+ $this->assertContains('<option value="01" selected="selected">01</option>', $result);
+ $this->assertContains('<option value="20" selected="selected">20</option>', $result);
+ $this->assertContains('<option value="12" selected="selected">12</option>', $result);
+ $this->assertContains('<option value="30" selected="selected">30</option>', $result);
+ $this->assertContains('<option value="45" selected="selected">45</option>', $result);
}
/**
@@ -126,6 +139,7 @@ public function testGenerateNumbers() {
*/
public function testYearSelect() {
$result = $this->DateTime->yearSelect();
+ $this->markTestIncomplete();
}
/**
@@ -141,6 +155,7 @@ public function testMonthSelect() {
$result = $this->DateTime->monthSelect([
'names' => true,
]);
+ $this->markTestIncomplete();
}
/**
@@ -151,7 +166,7 @@ public function testMonthSelect() {
public function testDaySelect() {
$result = $this->DateTime->daySelect();
$expected = '<select name="data[day]"><option value="01" selected="selected">01</option><option value="02">02</option><option value="03">03</option><option value="04">04</option><option value="05">05</option><option value="06">06</option><option value="07">07</option></select>';
- $this->assertEquals($result, $expected);
+ $this->markTestIncomplete();
}
/**
@@ -161,6 +176,7 @@ public function testDaySelect() {
*/
public function testHourSelect() {
$result = $this->DateTime->hourSelect();
+ $this->markTestIncomplete();
}
/**
@@ -170,6 +186,7 @@ public function testHourSelect() {
*/
public function testMinuteSelect() {
$result = $this->DateTime->minuteSelect();
+ $this->markTestIncomplete();
}
/**
@@ -179,6 +196,7 @@ public function testMinuteSelect() {
*/
public function testSecondSelect() {
$result = $this->DateTime->secondSelect();
+ $this->markTestIncomplete();
}
-}
+}
Please sign in to comment.
Something went wrong with that request. Please try again.