From 2a84a1a61897da65da6f1b8170bd88396a646135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Fri, 13 Oct 2023 00:53:03 +0200 Subject: [PATCH] Drop Form::jsInput() shortcut method (#2120) --- demos/_unit-test/form-empty.php | 17 +++++++++++++++++ demos/form-control/multiline.php | 5 +++++ demos/form/form.php | 2 +- demos/init-db.php | 4 ++-- src/Form.php | 19 +++++++------------ src/Form/Control.php | 8 ++++---- src/View.php | 2 +- tests-behat/form.feature | 5 +++++ tests/AppTest.php | 9 +++++++++ tests/DemosTest.php | 10 ++++++++-- 10 files changed, 59 insertions(+), 22 deletions(-) create mode 100644 demos/_unit-test/form-empty.php diff --git a/demos/_unit-test/form-empty.php b/demos/_unit-test/form-empty.php new file mode 100644 index 0000000000..ec64d38ec5 --- /dev/null +++ b/demos/_unit-test/form-empty.php @@ -0,0 +1,17 @@ +onSubmit(static function (Form $form) { + return new JsToast('Post ' . ($form->getApp()->getRequest()->getParsedBody() === [] ? 'ok' : 'unexpected')); +}); diff --git a/demos/form-control/multiline.php b/demos/form-control/multiline.php index d723dcf56d..39406fb65a 100644 --- a/demos/form-control/multiline.php +++ b/demos/form-control/multiline.php @@ -9,6 +9,8 @@ use Atk4\Ui\Js\JsExpression; use Atk4\Ui\Js\JsFunction; use Atk4\Ui\Js\JsToast; +use Doctrine\DBAL\Platforms\PostgreSQLPlatform; +use SebastianBergmann\CodeCoverage\CodeCoverage; /** @var \Atk4\Ui\App $app */ require_once __DIR__ . '/../init-app.php'; @@ -24,6 +26,9 @@ $inventory->getField($inventory->fieldName()->box)->ui['multiline'] = [Form\Control\Multiline::TABLE_CELL => ['width' => 2]]; $inventory->getField($inventory->fieldName()->total_sql)->ui['multiline'] = [Form\Control\Multiline::TABLE_CELL => ['width' => 1, 'class' => 'blue']]; $inventory->getField($inventory->fieldName()->total_php)->ui['multiline'] = [Form\Control\Multiline::TABLE_CELL => ['width' => 1, 'class' => 'blue']]; +if ($app->db->getDatabasePlatform() instanceof PostgreSQLPlatform || class_exists(CodeCoverage::class, false)) { + $inventory->setOrder($inventory->idField); +} $form = Form::addTo($app); diff --git a/demos/form/form.php b/demos/form/form.php index 1c07948515..69d252c53c 100644 --- a/demos/form/form.php +++ b/demos/form/form.php @@ -198,7 +198,7 @@ } return new JsBlock([ - $form->jsInput('email')->val('john@gmail.com'), + $form->getControl('email')->jsInput()->val('john@gmail.com'), $form->getControl('is_accept_terms')->js()->checkbox('set checked'), ]); }); diff --git a/demos/init-db.php b/demos/init-db.php index dff846a72f..d1d01ca9d1 100644 --- a/demos/init-db.php +++ b/demos/init-db.php @@ -210,8 +210,8 @@ public function addField(string $name, $seed = []): Field * @property string $sys_name @Atk4\Field() * @property string $iso @Atk4\Field() * @property string $iso3 @Atk4\Field() - * @property string $numcode @Atk4\Field() - * @property string $phonecode @Atk4\Field() + * @property int $numcode @Atk4\Field() + * @property int $phonecode @Atk4\Field() */ class Country extends ModelWithPrefixedFields { diff --git a/src/Form.php b/src/Form.php index 5182e4f844..3a5f492970 100644 --- a/src/Form.php +++ b/src/Form.php @@ -348,17 +348,6 @@ public function addGroup($title = null) return $this->layout->addGroup($title); } - /** - * Returns JS Chain that targets INPUT element of a specified field. This method is handy - * if you wish to set a value to a certain field. - * - * @return Jquery - */ - public function jsInput(string $name): JsExpressionable - { - return $this->layout->getControl($name)->jsInput(); - } - // }}} // {{{ Internals @@ -443,7 +432,12 @@ protected function loadPost(): void foreach ($this->controls as $k => $control) { // save field value only if field was editable in form at all if (!$control->readOnly && !$control->disabled) { - $postRawValue = $postRawData[$k]; + $postRawValue = $postRawData[$k] ?? null; + if ($postRawValue === null) { + throw (new Exception('Form POST param does not exist')) + ->addMoreInfo('key', $k); + } + try { $control->set($this->getApp()->uiPersistence->typecastLoadField($control->entityField->getField(), $postRawValue)); } catch (\Exception $e) { @@ -527,6 +521,7 @@ public function setupAjaxSubmit(): void 'on' => 'submit', 'url' => $this->cb->getJsUrl(), 'method' => 'POST', + 'contentType' => 'application/x-www-form-urlencoded; charset=UTF-8', // remove once https://github.com/jquery/jquery/issues/5346 is fixed 'serializeForm' => true, ], $this->apiConfig)); diff --git a/src/Form/Control.php b/src/Form/Control.php index 467d481dbd..861e3d02b2 100644 --- a/src/Form/Control.php +++ b/src/Form/Control.php @@ -148,12 +148,12 @@ public function onChange($expr, $defaults = []): void * * $field->jsInput(true)->val(123); * - * @param bool|string $when - * @param JsExpressionable $action + * @param bool|string $when + * @param ($when is false ? null : JsExpressionable|null) $action * - * @return Jquery + * @return ($action is null ? Jquery : null) */ - public function jsInput($when = false, $action = null): JsExpressionable + public function jsInput($when = false, $action = null): ?JsExpressionable { return $this->js($when, $action, '#' . $this->name . '_input'); } diff --git a/src/View.php b/src/View.php index 56d51844d9..67621b9c79 100644 --- a/src/View.php +++ b/src/View.php @@ -749,7 +749,7 @@ public function getHtml() * * @return ($action is null ? Jquery : null) */ - public function js($when = false, $action = null, $selector = null) + public function js($when = false, $action = null, $selector = null): ?JsExpressionable { // binding on a specific event // TODO allow only boolean $when, otherwise user should use self::on() method diff --git a/tests-behat/form.feature b/tests-behat/form.feature index 4342e013fa..3d568f8903 100644 --- a/tests-behat/form.feature +++ b/tests-behat/form.feature @@ -84,3 +84,8 @@ Feature: Form When I click using selector "//label[text()='I am a developer']" Then I should not see "Check all language that apply" Then I should not see "Css" + + Scenario: empty POST + Given I am on "_unit-test/form-empty.php" + When I press button "Save" + Then Toast display should contain text "Post ok" diff --git a/tests/AppTest.php b/tests/AppTest.php index 2ae5ea9600..5cb57408cc 100644 --- a/tests/AppTest.php +++ b/tests/AppTest.php @@ -239,4 +239,13 @@ public function testUrl(string $requestUrl, array $appStickyGetArguments, array $expectedUrlAutoindex2 = $makeExpectedUrlFx('', '.html'); self::assertSame($expectedUrlAutoindex2, $app->url($page, $extraRequestUrlArgs)); } + + public function testTerminateNoContentTypeException(): void + { + $app = $this->createApp(); + + $this->expectException(Exception::class); + $this->expectExceptionMessage('Content type must be always set'); + $app->terminate(); + } } diff --git a/tests/DemosTest.php b/tests/DemosTest.php index 0a0a65d322..00747b6c9f 100644 --- a/tests/DemosTest.php +++ b/tests/DemosTest.php @@ -502,13 +502,13 @@ public function testDemoAssertJsonResponsePost(string $path, array $postData): v /** * @dataProvider provideDemoCallbackErrorCases */ - public function testDemoCallbackError(string $path, string $expectedExceptionMessage): void + public function testDemoCallbackError(string $path, string $expectedExceptionMessage, array $options = []): void { if (static::class === self::class) { $this->expectExceptionMessage($expectedExceptionMessage); } - $response = $this->getResponseFromRequest5xx($path); + $response = $this->getResponseFromRequest5xx($path, $options); self::assertSame(500, $response->getStatusCode()); self::assertSame('text/html', preg_replace('~;\s*charset=.+$~', '', $response->getHeaderLine('Content-Type'))); @@ -540,6 +540,12 @@ public function provideDemoCallbackErrorCases(): iterable '_unit-test/callback-nested.php?err_sub_loader2&' . Callback::URL_QUERY_TRIGGER_PREFIX . 'trigger_main_loader=callback&' . Callback::URL_QUERY_TRIGGER_PREFIX . 'trigger_sub_loader=callback&' . Callback::URL_QUERY_TARGET . '=trigger_sub_loader', 'Exception II from Sub Loader', ]; + + yield [ + '_unit-test/post.php?' . Callback::URL_QUERY_TRIGGER_PREFIX . 'test_submit=ajax&' . Callback::URL_QUERY_TARGET . '=test_submit', + 'Form POST param does not exist', + ['form_params' => []], + ]; } }