Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/vendor
/composer.lock
/tests/output
/.idea
27 changes: 24 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ In PHP this addon works with DateTime objects, in the browser it uses jqueryUI c
[![License](https://poser.pugx.org/voda/date-input/license)](https://packagist.org/packages/voda/date-input)


JS dependencies
JS dependencies (recomended)
---------------
* [jQuery](http://jquery.com/) and [jQueryUI](http://jqueryui.com/)
* [Timepicker addon](http://trentrichardson.com/examples/timepicker/) version 1.1.0 or newer
Expand All @@ -30,11 +30,28 @@ insert required javascript and style files into your layout (order of scripts is
<link rel="stylesheet" type="text/css" href="{$basePath}/styles/jquery-ui-timepicker-addon.css">
<link rel="stylesheet" type="text/css" href="{$basePath}/styles/dateInput.css">
```
register the addon in your bootstrap.php:
```

### Registering

#### Register the addon in your bootstrap.php

```php
Vodacek\Forms\Controls\DateInput::register();
```

#### Or use DI extension

config.neon:

```neon
extensions:
dateInput: Vodacek\Forms\Controls\Extension
```

### If you want use jQuery calendar (not necessary)

initialize the calendar using javascript:

```js
$(document).ready(function() {
$('input[data-dateinput-type]').dateinput({
Expand Down Expand Up @@ -71,4 +88,8 @@ $form->addDate('datetimeLocal', 'Local datetime', DateInput::TYPE_DATETIME_LOCAL
->setRequired()
->setDefaultValue(new DateTimeImmutable())
->addRule(Form::RANGE, null, array(new DateTimeImmutable('-2 years'), new DateTimeImmutable('+2 years')));

$form->addDate('date', 'Date', DateInput::TYPE_DATE);

$form->addDate('time', 'Time', DateInput::TYPE_TIME);
```
50 changes: 41 additions & 9 deletions src/DateInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@

use DateTimeInterface;
use Nette\Forms\Container;
use Nette\Forms\Control;
use Nette\Forms\Controls\BaseControl;
use Nette\Forms\Form;
use Nette\Forms\IControl;
use Nette\Forms\Validator;

/**
Expand All @@ -44,15 +44,18 @@
class DateInput extends BaseControl {

public const
TYPE_DATETIME_LOCAL = 'datetime-local',
TYPE_DATE = 'date',
TYPE_MONTH = 'month',
TYPE_TIME = 'time',
TYPE_WEEK = 'week';
TYPE_DATETIME_LOCAL = 'datetime-local',
TYPE_DATE = 'date',
TYPE_MONTH = 'month',
TYPE_TIME = 'time',
TYPE_WEEK = 'week';

/** @var string */
protected $type;

/** @var bool */
private $nullable;

/** @var array */
protected $range = ['min' => null, 'max' => null];

Expand All @@ -64,7 +67,7 @@ class DateInput extends BaseControl {

public static $defaultValidMessage = 'Please enter a valid date.';

private static $formats = [
public static $formats = [
self::TYPE_DATETIME_LOCAL => 'Y-m-d\TH:i:s',
self::TYPE_DATE => 'Y-m-d',
self::TYPE_MONTH => 'Y-m',
Expand Down Expand Up @@ -109,6 +112,11 @@ public function __construct(string $label = null, string $type = self::TYPE_DATE
}
}

/**
* Sets control's value.
* @return static
* @internal
*/
public function setValue($value = null) {
if ($value === null || $value instanceof DateTimeInterface) {
$this->value = $value;
Expand Down Expand Up @@ -136,6 +144,26 @@ public function setValue($value = null) {
return $this;
}

/**
* Returns control's value.
* @return mixed
*/
public function getValue()
{
$value = parent::getValue();
return $this->nullable && $value === '' ? null : $value;
}

/**
* Sets whether getValue() returns null instead of empty string.
* @return static
*/
public function setNullable(bool $value = true)
{
$this->nullable = $value;
return $this;
}

public function getControl() {
$control = parent::getControl();
$format = self::$formats[$this->type];
Expand Down Expand Up @@ -165,14 +193,14 @@ public function addRule($operation, $message = null, $arg = null) {
return parent::addRule($operation, $message, $arg);
}

public static function validateFilled(IControl $control): bool {
public static function validateFilled(Control $control): bool {
if (!$control instanceof self) {
throw new \InvalidArgumentException("Cant't validate control '".\get_class($control)."'.");
}
return ($control->value !== null || $control->submittedValue !== null);
}

private static function validateValid(IControl $control): bool {
private static function validateValid(Control $control): bool {
if (!$control instanceof self) {
throw new \InvalidArgumentException("Cant't validate control '".\get_class($control)."'.");
}
Expand Down Expand Up @@ -201,6 +229,10 @@ private function parseValue(string $value): ?DateTimeInterface {
}
} else {
$date = $this->createFromFormat('!'.self::$formats[$this->type], $value);
//try find in format without seconds
if(!$date && $this->type == self::TYPE_DATETIME_LOCAL) {
$date = $this->createFromFormat('!Y-m-d\TH:i', $value);
}
}
return $date;
}
Expand Down
23 changes: 23 additions & 0 deletions src/Extension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);

namespace Vodacek\Forms\Controls;

use Nette;

class Extension extends Nette\DI\CompilerExtension
{


/**
* @param Nette\PhpGenerator\ClassType $class
* @return void
*/
public function afterCompile(Nette\PhpGenerator\ClassType $class){
parent::afterCompile($class);
$init = $class->methods['initialize'];
/** @see DateInput::register() */
$init->addBody('Vodacek\Forms\Controls\DateInput::register();');
}

}
22 changes: 22 additions & 0 deletions tests/DateInput.validation.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,28 @@ test(static function() { // no value and valid value for required input
Assert::false($control->hasErrors());
});

test(static function() { // value and from browser come different format
$form = new Form();
$control = new DateInput('date', DateInput::TYPE_DATETIME_LOCAL);
$form->addComponent($control, 'date');
$control->setRequired();

$control->validate();
Assert::true($control->hasErrors());

$control->setValue('2022-04-01T15:15:15');
$control->validate();
Assert::false($control->hasErrors());

$control->setValue('2022-04-01T15:15:00');
$control->validate();
Assert::false($control->hasErrors());

$control->setValue('2022-04-01T15:15');
$control->validate();
Assert::false($control->hasErrors());
});

test(static function() { // invalid value
$form = new Form();
$control = new DateInput('date', DateInput::TYPE_DATETIME_LOCAL);
Expand Down