diff --git a/composer.json b/composer.json index b380a304d8..dfb75326fe 100644 --- a/composer.json +++ b/composer.json @@ -60,7 +60,9 @@ }, "require-release": { "php": ">=7.4 <8.2", - "atk4/data": "~4.0.0" + "atk4/data": "~4.0.0", + "symfony/filesystem": "^4.4 || ^5.3", + "symfony/http-foundation": "^4.4 || ^5.3" }, "require-dev": { "behat/mink-extension": "^2.3.1", diff --git a/demos/_includes/DemoLookup.php b/demos/_includes/DemoLookup.php index 443427b767..b707f8f147 100644 --- a/demos/_includes/DemoLookup.php +++ b/demos/_includes/DemoLookup.php @@ -43,7 +43,6 @@ protected function initQuickNewRecord() $form = \Atk4\Ui\Form::addTo($page); $entity = $this->model->createEntity(); - $form->setModel($entity, $this->plus['fields'] ?? null); $form->onSubmit(function (\Atk4\Ui\Form $form) { diff --git a/demos/_unit-test/callback.php b/demos/_unit-test/callback.php index 455a945b84..e077fe1b91 100644 --- a/demos/_unit-test/callback.php +++ b/demos/_unit-test/callback.php @@ -18,7 +18,7 @@ $vp->cb->triggerOnReload = false; $form = Form::addTo($vp); -$form->setModel($m->tryLoadAny(), [$m->fieldName()->name]); +$form->setModel($m->loadAny(), [$m->fieldName()->name]); $form->getControl($m->fieldName()->name)->caption = 'TestName'; $table = \Atk4\Ui\Table::addTo($app); diff --git a/demos/collection/crud.php b/demos/collection/crud.php index b1ec5bea65..7623c6eda9 100644 --- a/demos/collection/crud.php +++ b/demos/collection/crud.php @@ -4,7 +4,6 @@ namespace Atk4\Ui\Demos; -use Atk4\Data\Model; use Atk4\Ui\Form; /** @var \Atk4\Ui\App $app */ diff --git a/demos/data-action/jsactions2.php b/demos/data-action/jsactions2.php index 37e9ce06e0..3da9cee39d 100644 --- a/demos/data-action/jsactions2.php +++ b/demos/data-action/jsactions2.php @@ -12,7 +12,7 @@ require_once __DIR__ . '/../init-app.php'; $country = new Country($app->db); -$entity = $country->tryLoadAny(); +$entity = $country->loadAny(); $countryId = $entity->getId(); // Model actions for this file are setup in DemoActionUtil. diff --git a/demos/form-control/lookup.php b/demos/form-control/lookup.php index f39c530f40..a3719cc78c 100644 --- a/demos/form-control/lookup.php +++ b/demos/form-control/lookup.php @@ -44,7 +44,8 @@ . '; ' . $form->model->ref('country2')->get(Country::hinting()->fieldName()->name) . '; ' - . (new Country($form->getApp()->db))->tryLoad($form->model->get('country3'))->get(Country::hinting()->fieldName()->name); + . (new Country($form->getApp()->db))->load($form->model->get('country3')) + ->get(Country::hinting()->fieldName()->name); $view = new \Atk4\Ui\Message('Select:'); // need in behat test. $view->invokeInit(); diff --git a/demos/form/form3.php b/demos/form/form3.php index d1339bdba8..f912847786 100644 --- a/demos/form/form3.php +++ b/demos/form/form3.php @@ -27,13 +27,8 @@ ->on('click', new JsReload($seg, ['m' => 'stat'])); $form = Form::addTo($seg, ['layout' => [Form\Layout\Columns::class]]); -$form->setModel(( - isset($_GET['m']) ? ( - $_GET['m'] === 'country' ? new Country($app->db) : ( - $_GET['m'] === 'file' ? new File($app->db) : new Stat($app->db) - ) - ) : new Stat($app->db) -)->tryLoadAny()); +$modelClass = ['country' => Country::class, 'file' => File::class][$_GET['m'] ?? ''] ?? Stat::class; +$form->setModel((new $modelClass($app->db))->loadAny()); $form->onSubmit(function (Form $form) { $errors = []; diff --git a/demos/interactive/card.php b/demos/interactive/card.php index 4d6f0b642d..ce7098184d 100644 --- a/demos/interactive/card.php +++ b/demos/interactive/card.php @@ -48,16 +48,14 @@ $cardStat = \Atk4\Ui\Card::addTo($deck, ['useTable' => true]); $cardStat->addContent(new \Atk4\Ui\Header(['Project Info'])); -$stat = (new Stat($app->db))->tryLoadAny(); - +$stat = (new Stat($app->db))->loadAny(); $cardStat->setModel($stat, [$stat->fieldName()->project_name, $stat->fieldName()->project_code, $stat->fieldName()->client_name, $stat->fieldName()->start_date]); $btn = $cardStat->addButton(new \Atk4\Ui\Button(['Email Client'])); $cardStat = \Atk4\Ui\Card::addTo($deck, ['useLabel' => true]); $cardStat->addContent(new \Atk4\Ui\Header(['Project Info'])); -$stat = (new Stat($app->db))->tryLoadAny(); - +$stat = (new Stat($app->db))->loadAny(); $cardStat->setModel($stat, [$stat->fieldName()->project_name, $stat->fieldName()->project_code, $stat->fieldName()->client_name, $stat->fieldName()->start_date]); $cardStat->addButton(new \Atk4\Ui\Button(['Email Client'])); diff --git a/demos/interactive/cardtable.php b/demos/interactive/cardtable.php index 1c817ab11a..452e00970c 100644 --- a/demos/interactive/cardtable.php +++ b/demos/interactive/cardtable.php @@ -9,4 +9,4 @@ \Atk4\Ui\Header::addTo($app, ['Card displays read-only data of a single record']); -\Atk4\Ui\CardTable::addTo($app)->setModel((new Stat($app->db))->tryLoadAny()); +\Atk4\Ui\CardTable::addTo($app)->setModel((new Stat($app->db))->loadAny()); diff --git a/demos/interactive/console.php b/demos/interactive/console.php index 175a15cbe3..371fd5da50 100644 --- a/demos/interactive/console.php +++ b/demos/interactive/console.php @@ -112,7 +112,7 @@ public function generateReport() $console = \Atk4\Ui\Console::addTo($tab, ['event' => false]); $console->set(function ($console) { - $model = $_SESSION['data']; + $model = $_SESSION['atk4_ui_console_demo']; $console->output('Executing process...'); $console->info(var_export($model->get(), true)); sleep(1); @@ -123,7 +123,7 @@ public function generateReport() $console->js(true)->hide(); $form->onSubmit(function (\Atk4\Ui\Form $form) use ($console) { - $_SESSION['data'] = $form->model; // only option is to store model in session here in demo + $_SESSION['atk4_ui_console_demo'] = $form->model; // only option is to store model in session here in demo return [ $console->js()->show(), diff --git a/demos/others/sticky2.php b/demos/others/sticky2.php index 2025ebc5a8..cb5ecdfebb 100644 --- a/demos/others/sticky2.php +++ b/demos/others/sticky2.php @@ -16,7 +16,7 @@ $frame->stickyGet('name'); // frame will generate URL with sticky parameter - \Atk4\Ui\Label::addTo($frame, ['Name:', 'detail' => $_GET['name'], 'black'])->link($frame->url()); + \Atk4\Ui\Label::addTo($frame, ['Name:', 'detail' => $_GET['name'], 'class.black' => true])->link($frame->url()); // app still generates URL without localized sticky \Atk4\Ui\Label::addTo($frame, ['Reset', 'iconRight' => 'close', 'class.black' => true])->link($app->url()); diff --git a/demos/tutorial/actions.php b/demos/tutorial/actions.php index 93851980e9..0d347696fb 100644 --- a/demos/tutorial/actions.php +++ b/demos/tutorial/actions.php @@ -62,14 +62,14 @@ Demo::addTo($page)->setCodeAndCall(function (View $owner) { $country = new Country($owner->getApp()->db); - $country->addUserAction('send_message', function () { - return 'sent'; + $country->addUserAction('send_message', function (Country $entity) { + return 'sent to ' . $entity->get($entity->fieldName()->name); }); - $country = $country->tryLoadAny(); + $country = $country->loadAny(); $card = \Atk4\Ui\Card::addTo($owner); $card->setModel($country, [$country->fieldName()->iso]); - $card->addClickAction($country->getUserAction('send_message')); + $card->addClickAction($country->getModel()->getUserAction('send_message')); }); }); diff --git a/demos/tutorial/intro.php b/demos/tutorial/intro.php index 0f9372a758..a57815b264 100644 --- a/demos/tutorial/intro.php +++ b/demos/tutorial/intro.php @@ -141,25 +141,26 @@ protected function init(): void */ session_start(); - $model = new DemoInvoice(new Persistence\Array_($_SESSION['x'] ?? []), ['dateFormat' => $owner->getApp()->uiPersistence->dateFormat]); + $model = new DemoInvoice(new Persistence\Array_($_SESSION['atk4_ui_intro_demo'] ?? []), ['dateFormat' => $owner->getApp()->uiPersistence->dateFormat]); $model->onHook(\Atk4\Data\Model::HOOK_AFTER_SAVE, function (Model $model) { - $_SESSION['x'][$model->getId()] = $model->get(); + $_SESSION['atk4_ui_intro_demo'][$model->getId()] = (clone $model->getModel())->addCondition($model->idField, $model->getId())->export(null, null, false)[$model->getId()]; }); Header::addTo($owner, ['Set invoice data:']); $form = \Atk4\Ui\Form::addTo($owner); - $model = $model->tryLoad(1); - $form->setModel($model); - if (!$model->isLoaded()) { + $entity = $model->tryLoad(1); + if ($entity === null) { // set default data - $model->setMulti([ + $entity = $model->createEntity(); + $entity->setMulti([ 'id' => 1, 'reference' => 'Inv-' . random_int(1000, 9999), 'date' => new \DateTime(), ]); - $model->save(); + $entity->save(); } + $form->setModel($entity); $form->onSubmit(function (Form $form) { $form->model->save(); @@ -203,14 +204,14 @@ protected function init(): void Demo::addTo($page)->setCodeAndCall(function (View $owner) { session_start(); - $model = new DemoInvoice(new Persistence\Array_($_SESSION['x'] ?? []), ['dateFormat' => $owner->getApp()->uiPersistence->dateFormat]); + $model = new DemoInvoice(new Persistence\Array_($_SESSION['atk4_ui_intro_demo'] ?? []), ['dateFormat' => $owner->getApp()->uiPersistence->dateFormat]); $model->onHook(\Atk4\Data\Model::HOOK_AFTER_SAVE, function (Model $model) { - $_SESSION['x'][$model->getId()] = $model->get(); + $_SESSION['atk4_ui_intro_demo'][$model->getId()] = (clone $model->getModel())->addCondition($model->idField, $model->getId())->export(null, null, false)[$model->getId()]; }); Header::addTo($owner, ['Record display in Card View using model data.']); $model = $model->tryLoad(1); - if ($model->isLoaded()) { + if ($model !== null) { \Atk4\Ui\Card::addTo($owner, ['useLabel' => true]) ->setModel($model); } else { @@ -230,5 +231,5 @@ protected function init(): void $wizard->addFinish(function ($page) use ($wizard) { PromotionText::addTo($page); \Atk4\Ui\Button::addTo($wizard, ['Exit demo', 'class.primary' => true, 'icon' => 'left arrow'], ['Left']) - ->link('/demos/index.php'); + ->link('../'); }); diff --git a/docs/app.rst b/docs/app.rst index 3093f12ec2..270d60fa49 100644 --- a/docs/app.rst +++ b/docs/app.rst @@ -74,8 +74,6 @@ active. (See :ref:`system_pattern`):: $this->db->setApp($this);           // My App class provides access to a currently logged user and currently selected system. - $this->user = new User($this->db); - $this->company = new Company($this->db); session_start(); // App class may be used for pages that do not require authentication @@ -85,13 +83,14 @@ active. (See :ref:`system_pattern`):: return; } - // Load User from database based on session data + // Load user from database based on session data if (isset($_SESSION['user_id'])) { - $this->user = $this->user->tryLoad($_SESSION['user_id']); + $user = new User($this->db); + $this->user = $user->tryLoad($_SESSION['user_id']); }           // Make sure user is valid - if (!$this->user->isLoaded()) { + if ($this->user === null) { $this->initLayout([\Atk4\Ui\Layout\Centered::class]); Message::addTo($this, ['Login Required', 'type' => 'error']); Button::addTo($this, ['Login', 'class.primary' => true])->link('index.php'); diff --git a/src/App.php b/src/App.php index b62ba21592..979d011671 100644 --- a/src/App.php +++ b/src/App.php @@ -604,9 +604,10 @@ public function loadTemplate($filename) return $template->loadFromFile($filename); } - $dir = is_array($this->templateDir) ? $this->templateDir : [$this->templateDir]; - foreach ($dir as $td) { - if ($t = $template->tryLoadFromFile($td . '/' . $filename)) { + $dirs = is_array($this->templateDir) ? $this->templateDir : [$this->templateDir]; + foreach ($dirs as $dir) { + $t = $template->tryLoadFromFile($dir . '/' . $filename); + if ($t !== false) { return $t; } } diff --git a/src/Form/Control/DropdownCascade.php b/src/Form/Control/DropdownCascade.php index 1e6ea73472..4ac5934442 100644 --- a/src/Form/Control/DropdownCascade.php +++ b/src/Form/Control/DropdownCascade.php @@ -79,7 +79,7 @@ public function getNewValues($id): array return [['value' => '', 'text' => $this->empty, 'name' => $this->empty]]; } - $model = $this->cascadeFrom->model->tryLoad($id)->ref($this->reference); + $model = $this->cascadeFrom->model->load($id)->ref($this->reference); $values = []; foreach ($model as $k => $row) { if ($this->renderRowFunction) { diff --git a/src/Form/Control/Lookup.php b/src/Form/Control/Lookup.php index c19ee66269..a6bc3b3119 100644 --- a/src/Form/Control/Lookup.php +++ b/src/Form/Control/Lookup.php @@ -414,15 +414,10 @@ protected function renderView(): void if ($this->entityField && $this->entityField->get()) { $idField = $this->idField ?: $this->model->idField; - $this->model = $this->model->tryLoadBy($idField, $this->entityField->get()); + $this->model = $this->model->loadBy($idField, $this->entityField->get()); - if ($this->model->isLoaded()) { - $row = $this->renderRow($this->model); - - $chain->dropdown('set value', $row['value'])->dropdown('set text', $row['title']); - } else { - $this->entityField->setNull(); - } + $row = $this->renderRow($this->model); + $chain->dropdown('set value', $row['value'])->dropdown('set text', $row['title']); } $this->js(true, $chain); diff --git a/src/Form/Control/Multiline.php b/src/Form/Control/Multiline.php index 3606e00165..32b95019ea 100644 --- a/src/Form/Control/Multiline.php +++ b/src/Form/Control/Multiline.php @@ -344,7 +344,7 @@ public function saveRows(): self $currentIds = array_column($model->export(), $model->idField); foreach ($this->rowData as $row) { - $entity = $model->tryLoad($row[$model->idField] ?? null); + $entity = $row[$model->idField] !== null ? $model->load($row[$model->idField]) : $model->createEntity(); foreach ($row as $fieldName => $value) { if ($fieldName === '__atkml') { continue; @@ -568,11 +568,11 @@ protected function getLookupProps(Field $field): array public function setLookupOptionValue(Field $field, string $value) { $model = $field->getReference()->refModel($this->model); - $rec = $model->tryLoadBy($field->getReference()->getTheirFieldName(), $value); - if ($rec->isLoaded()) { + $entity = $model->tryLoadBy($field->getReference()->getTheirFieldName(), $value); + if ($entity !== null) { $option = [ 'key' => $value, - 'text' => $rec->get($model->titleField), + 'text' => $entity->get($model->titleField), 'value' => $value, ]; foreach ($this->fieldDefs as $key => $component) { @@ -787,7 +787,7 @@ private function getExpressionValues(Model $model): array foreach ($dummyFields as $field) { $dummyModel->addExpression($field['name'], ['expr' => $field['expr'], 'type' => $model->getField($field['name'])->type]); } - $values = $dummyModel->tryLoadAny()->get(); + $values = $dummyModel->loadAny()->get(); unset($values[$model->idField]); foreach ($values as $f => $value) { diff --git a/src/Form/Control/ScopeBuilder.php b/src/Form/Control/ScopeBuilder.php index ec1caa1282..c07453e004 100644 --- a/src/Form/Control/ScopeBuilder.php +++ b/src/Form/Control/ScopeBuilder.php @@ -715,11 +715,11 @@ protected static function getOption(string $type, string $value, Condition $cond $reference = $condField->getReference(); $model = $reference->refModel($condField->getOwner()); $fieldName = $reference->getTheirFieldName(); - $rec = $model->tryLoadBy($fieldName, $value); - if ($rec->isLoaded()) { + $entity = $model->tryLoadBy($fieldName, $value); + if ($entity !== null) { $option = [ 'key' => $value, - 'text' => $rec->get($model->titleField), + 'text' => $entity->get($model->titleField), 'value' => $value, ]; } diff --git a/src/UserAction/ConfirmationExecutor.php b/src/UserAction/ConfirmationExecutor.php index 9c11c4011d..4ab3190070 100644 --- a/src/UserAction/ConfirmationExecutor.php +++ b/src/UserAction/ConfirmationExecutor.php @@ -117,9 +117,10 @@ public function executeModelAction() { $id = $this->stickyGet($this->name); if ($id && $this->action->appliesTo === Model\UserAction::APPLIES_TO_SINGLE_RECORD) { - $this->action = $this->action->getActionForEntity($this->action->getModel()->tryLoad($id)); + $this->action = $this->action->getActionForEntity($this->action->getModel()->load($id)); } elseif (!$this->action->isOwnerEntity() - && in_array($this->action->appliesTo, [Model\UserAction::APPLIES_TO_NO_RECORDS, Model\UserAction::APPLIES_TO_SINGLE_RECORD], true)) { + && in_array($this->action->appliesTo, [Model\UserAction::APPLIES_TO_NO_RECORDS, Model\UserAction::APPLIES_TO_SINGLE_RECORD], true) + ) { $this->action = $this->action->getActionForEntity($this->action->getModel()->createEntity()); } diff --git a/src/UserAction/JsCallbackExecutor.php b/src/UserAction/JsCallbackExecutor.php index e42555adce..ee23340479 100644 --- a/src/UserAction/JsCallbackExecutor.php +++ b/src/UserAction/JsCallbackExecutor.php @@ -62,9 +62,10 @@ public function executeModelAction(array $args = []) // may be id is passed as 'id' or model->idField within $post args. $id = $_POST['c0'] ?? $_POST['id'] ?? $_POST[$this->action->getModel()->idField] ?? null; if ($id && $this->action->appliesTo === Model\UserAction::APPLIES_TO_SINGLE_RECORD) { - $this->action = $this->action->getActionForEntity($this->action->getModel()->tryLoad($id)); + $this->action = $this->action->getActionForEntity($this->action->getModel()->load($id)); } elseif (!$this->action->isOwnerEntity() - && in_array($this->action->appliesTo, [Model\UserAction::APPLIES_TO_NO_RECORDS, Model\UserAction::APPLIES_TO_SINGLE_RECORD], true)) { + && in_array($this->action->appliesTo, [Model\UserAction::APPLIES_TO_NO_RECORDS, Model\UserAction::APPLIES_TO_SINGLE_RECORD], true) + ) { $this->action = $this->action->getActionForEntity($this->action->getModel()->createEntity()); } diff --git a/src/UserAction/ModalExecutor.php b/src/UserAction/ModalExecutor.php index 4d583a41a1..17fdef2c5d 100644 --- a/src/UserAction/ModalExecutor.php +++ b/src/UserAction/ModalExecutor.php @@ -97,9 +97,10 @@ public function executeModelAction(): void { $id = $this->stickyGet($this->name); if ($id && $this->action->appliesTo === Model\UserAction::APPLIES_TO_SINGLE_RECORD) { - $this->action = $this->action->getActionForEntity($this->action->getModel()->tryLoad($id)); + $this->action = $this->action->getActionForEntity($this->action->getModel()->load($id)); } elseif (!$this->action->isOwnerEntity() - && in_array($this->action->appliesTo, [Model\UserAction::APPLIES_TO_NO_RECORDS, Model\UserAction::APPLIES_TO_SINGLE_RECORD], true)) { + && in_array($this->action->appliesTo, [Model\UserAction::APPLIES_TO_NO_RECORDS, Model\UserAction::APPLIES_TO_SINGLE_RECORD], true) + ) { $this->action = $this->action->getActionForEntity($this->action->getModel()->createEntity()); } diff --git a/src/UserAction/PanelExecutor.php b/src/UserAction/PanelExecutor.php index 3176dd05a5..410f30857d 100644 --- a/src/UserAction/PanelExecutor.php +++ b/src/UserAction/PanelExecutor.php @@ -104,9 +104,10 @@ public function executeModelAction(): void { $id = $this->stickyGet($this->name); if ($id && $this->action->appliesTo === Model\UserAction::APPLIES_TO_SINGLE_RECORD) { - $this->action = $this->action->getActionForEntity($this->action->getModel()->tryLoad($id)); + $this->action = $this->action->getActionForEntity($this->action->getModel()->load($id)); } elseif (!$this->action->isOwnerEntity() - && in_array($this->action->appliesTo, [Model\UserAction::APPLIES_TO_NO_RECORDS, Model\UserAction::APPLIES_TO_SINGLE_RECORD], true)) { + && in_array($this->action->appliesTo, [Model\UserAction::APPLIES_TO_NO_RECORDS, Model\UserAction::APPLIES_TO_SINGLE_RECORD], true) + ) { $this->action = $this->action->getActionForEntity($this->action->getModel()->createEntity()); } diff --git a/src/UserAction/VpExecutor.php b/src/UserAction/VpExecutor.php index fc1235f7a1..1d62fe6148 100644 --- a/src/UserAction/VpExecutor.php +++ b/src/UserAction/VpExecutor.php @@ -115,9 +115,10 @@ public function executeModelAction(): void { $id = $this->stickyGet($this->name); if ($id && $this->action->appliesTo === Model\UserAction::APPLIES_TO_SINGLE_RECORD) { - $this->action = $this->action->getActionForEntity($this->action->getModel()->tryLoad($id)); + $this->action = $this->action->getActionForEntity($this->action->getModel()->load($id)); } elseif (!$this->action->isOwnerEntity() - && in_array($this->action->appliesTo, [Model\UserAction::APPLIES_TO_NO_RECORDS, Model\UserAction::APPLIES_TO_SINGLE_RECORD], true)) { + && in_array($this->action->appliesTo, [Model\UserAction::APPLIES_TO_NO_RECORDS, Model\UserAction::APPLIES_TO_SINGLE_RECORD], true) + ) { $this->action = $this->action->getActionForEntity($this->action->getModel()->createEntity()); }