diff --git a/.travis.yml b/.travis.yml index 0902d63d5..6d9b0109f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,8 @@ php: - 7.0 - 7.1 - 7.2 + - 7.3 + - 7.4 before_install: # turn off XDebug diff --git a/examples/basic-example.php b/examples/basic-example.php index cc870d835..9e5291ca9 100644 --- a/examples/basic-example.php +++ b/examples/basic-example.php @@ -122,7 +122,7 @@ Nette Forms basic example - +

Nette Forms basic example

diff --git a/examples/custom-control.php b/examples/custom-control.php index 012a32e41..6ab26ccce 100644 --- a/examples/custom-control.php +++ b/examples/custom-control.php @@ -139,7 +139,7 @@ public static function validateDate(Nette\Forms\IControl $control) Nette Forms custom control example - +

Nette Forms custom control example

diff --git a/examples/custom-rendering.php b/examples/custom-rendering.php index b98022406..6ac92d341 100644 --- a/examples/custom-rendering.php +++ b/examples/custom-rendering.php @@ -116,7 +116,7 @@ background: #EEE; } - +

Nette Forms custom rendering example

diff --git a/examples/custom-validator.php b/examples/custom-validator.php index 94f057a95..6f384af18 100644 --- a/examples/custom-validator.php +++ b/examples/custom-validator.php @@ -47,7 +47,7 @@ public static function divisibilityValidator($item, $arg) Nette Forms custom validator example - + +

Nette Forms and HTML5

diff --git a/examples/live-validation.php b/examples/live-validation.php index d66437359..5fe93dbc1 100644 --- a/examples/live-validation.php +++ b/examples/live-validation.php @@ -50,7 +50,7 @@ Nette Forms live validation example - + +

Nette Forms localization example

diff --git a/examples/manual-rendering.php b/examples/manual-rendering.php index 8c91820c0..77066c354 100644 --- a/examples/manual-rendering.php +++ b/examples/manual-rendering.php @@ -28,9 +28,7 @@ 'f' => 'female', ]); -$form->addText('email') - ->setRequired(false) - ->addRule($form::EMAIL, 'Incorrect email address'); +$form->addEmail('email'); $form->addSubmit('submit'); @@ -48,7 +46,7 @@ Nette Forms manual form rendering - + diff --git a/src/Bridges/FormsLatte/FormMacros.php b/src/Bridges/FormsLatte/FormMacros.php index 91f8d7fad..9d1d4e2ba 100644 --- a/src/Bridges/FormsLatte/FormMacros.php +++ b/src/Bridges/FormsLatte/FormMacros.php @@ -52,7 +52,7 @@ public function macroForm(MacroNode $node, PhpWriter $writer) throw new CompileException('Did you mean
?'); } $name = $node->tokenizer->fetchWord(); - if ($name === false) { + if ($name == null) { // null or false throw new CompileException('Missing form name in ' . $node->getNotation()); } $node->replaced = true; @@ -75,7 +75,7 @@ public function macroFormContainer(MacroNode $node, PhpWriter $writer) throw new CompileException('Modifiers are not allowed in ' . $node->getNotation()); } $name = $node->tokenizer->fetchWord(); - if ($name === false) { + if ($name == null) { // null or false throw new CompileException('Missing name in ' . $node->getNotation()); } $node->tokenizer->reset(); diff --git a/src/Forms/Controls/SelectBox.php b/src/Forms/Controls/SelectBox.php index ed9e6de14..09b903baf 100644 --- a/src/Forms/Controls/SelectBox.php +++ b/src/Forms/Controls/SelectBox.php @@ -32,8 +32,11 @@ public function __construct($label = null, array $items = null) { parent::__construct($label, $items); $this->setOption('type', 'select'); - $this->addCondition(Nette\Forms\Form::BLANK) - ->addRule([$this, 'isOk'], Nette\Forms\Validator::$messages[self::VALID]); + $this->addCondition(function () { + return $this->prompt === false + && $this->options + && $this->control->size < 2; + })->addRule(Nette\Forms\Form::FILLED, Nette\Forms\Validator::$messages[self::VALID]); } diff --git a/src/Forms/Form.php b/src/Forms/Form.php index 7a6078a8c..c9219f590 100644 --- a/src/Forms/Form.php +++ b/src/Forms/Form.php @@ -239,7 +239,7 @@ public function isMethod($method) public function addProtection($errorMessage = null) { $control = new Controls\CsrfProtection($errorMessage); - $this->addComponent($control, self::PROTECTOR_ID, key($this->getComponents())); + $this->addComponent($control, self::PROTECTOR_ID, key((array) $this->getComponents())); return $control; } @@ -687,7 +687,7 @@ public function __toString() } catch (\Throwable $e) { } if (isset($e)) { - if (func_num_args()) { + if (func_num_args() || PHP_VERSION_ID >= 70400) { throw $e; } trigger_error('Exception in ' . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR); diff --git a/src/Forms/Validator.php b/src/Forms/Validator.php index 5b4272174..b44008c90 100644 --- a/src/Forms/Validator.php +++ b/src/Forms/Validator.php @@ -277,8 +277,14 @@ public static function validateUrl(IControl $control) */ public static function validatePattern(IControl $control, $pattern, $caseInsensitive = false) { - $value = $control->getValue() instanceof Nette\Http\FileUpload ? $control->getValue()->getName() : $control->getValue(); - return (bool) Strings::match($value, "\x01^(?:$pattern)\\z\x01u" . ($caseInsensitive ? 'i' : '')); + $regexp = "\x01^(?:$pattern)\\z\x01u" . ($caseInsensitive ? 'i' : ''); + foreach (static::toArray($control->getValue()) as $item) { + $value = $item instanceof Nette\Http\FileUpload ? $item->getName() : $item; + if (!Strings::match($value, $regexp)) { + return false; + } + } + return true; } diff --git a/tests/Forms/Controls.TestBase.validators.phpt b/tests/Forms/Controls.TestBase.validators.phpt index 6aad90fb5..9b07f1cef 100644 --- a/tests/Forms/Controls.TestBase.validators.phpt +++ b/tests/Forms/Controls.TestBase.validators.phpt @@ -118,6 +118,18 @@ test(function () { ]); Assert::false(Validator::validatePattern($control, '[4-6]+y')); Assert::true(Validator::validatePattern($control, '[1-3]+x')); + + $control = new MockUploadControl(null, true); + $control->value = [new FileUpload([ + 'name' => 'foo.jpg', 'size' => 1, 'tmp_name' => 'foo1', 'error' => UPLOAD_ERR_OK, 'type' => '', + ])]; + Assert::true(Validator::validatePattern($control, '.*jpg')); + + $control = new MockUploadControl(null, true); + $control->value = [new FileUpload([ + 'name' => 'bar.png', 'size' => 1, 'tmp_name' => 'bar1', 'error' => UPLOAD_ERR_OK, 'type' => '', + ])]; + Assert::false(Validator::validatePattern($control, '.*jpg')); }); diff --git a/tests/Forms/Helpers.exportRules.phpt b/tests/Forms/Helpers.exportRules.phpt index 90fad5880..15474a8ec 100644 --- a/tests/Forms/Helpers.exportRules.phpt +++ b/tests/Forms/Helpers.exportRules.phpt @@ -36,6 +36,18 @@ test(function () { }); +test(function () { + $form = new Form; + $input = $form->addText('text'); + $input->setRequired(true); + $input->addRule(Form::EMAIL); + Assert::same([ + ['op' => ':filled', 'msg' => 'This field is required.'], + ['op' => ':email', 'msg' => 'Please enter a valid email address.'], + ], Helpers::exportRules($input->getRules())); +}); + + test(function () { $form = new Form; $input = $form->addText('text');