|
7 | 7 | use Atk4\Core\Factory; |
8 | 8 | use Atk4\Data\Field; |
9 | 9 | use Atk4\Data\Model; |
| 10 | +use Atk4\Data\Model\EntityFieldPair; |
10 | 11 | use Atk4\Ui\Js\Jquery; |
11 | 12 | use Atk4\Ui\Js\JsChain; |
12 | 13 | use Atk4\Ui\Js\JsExpression; |
@@ -389,6 +390,40 @@ public function setModel(Model $model, array $columns = null): void |
389 | 390 | } |
390 | 391 | } |
391 | 392 |
|
| 393 | + public function setSource(array $data, $fields = null): Model |
| 394 | + { |
| 395 | + // mainly for CardTable to support different field type for different row 1/2 |
| 396 | + // related with https://github.com/atk4/data/blob/4.0.0/tests/Persistence/StaticTest.php#L142 |
| 397 | + $dataWithObjects = []; |
| 398 | + if (is_array(reset($data))) { |
| 399 | + foreach ($data as $rowKey => $row) { |
| 400 | + foreach ($row as $k => $v) { |
| 401 | + if ($v instanceof EntityFieldPair) { |
| 402 | + $dataWithObjects[$row['id']][$k] = $v; |
| 403 | + $data[$rowKey][$k] = null; |
| 404 | + } |
| 405 | + } |
| 406 | + } |
| 407 | + } |
| 408 | + |
| 409 | + $model = parent::setSource($data, $fields); |
| 410 | + |
| 411 | + foreach ($dataWithObjects as $id => $row) { |
| 412 | + $entity = $model->load($id); |
| 413 | + foreach ($row as $k => $v) { |
| 414 | + $model->getField($k)->type = 'atk4_local_object'; |
| 415 | + $entity->set($k, $v); |
| 416 | + } |
| 417 | + $entity->save(); |
| 418 | + } |
| 419 | + $model->onHook(Model::HOOK_BEFORE_LOAD, function () use ($dataWithObjects) { |
| 420 | + // useless hook, but make sure the $dataWithObjects is kept referenced from $model |
| 421 | + $count = count($dataWithObjects); |
| 422 | + }); |
| 423 | + |
| 424 | + return $model; |
| 425 | + } |
| 426 | + |
392 | 427 | protected function renderView(): void |
393 | 428 | { |
394 | 429 | if (!$this->columns) { |
@@ -420,8 +455,26 @@ protected function renderView(): void |
420 | 455 | // the same in Lister class |
421 | 456 | $modelBackup = $this->model; |
422 | 457 | try { |
423 | | - foreach ($this->model as $this->model) { |
424 | | - $this->currentRow = $this->model; |
| 458 | + foreach ($this->model as $entityOrig) { |
| 459 | + // mainly for CardTable to support different field type for different row 2/2 |
| 460 | + $entityCloned = (clone $entityOrig->getModel())->createEntity(); |
| 461 | + $entityCloned->setId($entityOrig->getId()); |
| 462 | + \Closure::bind(function () use ($entityOrig, $entityCloned) { |
| 463 | + foreach ($entityOrig->data as $k => $v) { |
| 464 | + $field = $entityCloned->getField($k); |
| 465 | + if ($field->type === 'atk4_local_object' && $v instanceof EntityFieldPair) { |
| 466 | + $field->type = $v->getField()->type; |
| 467 | + $field->enum = $v->getField()->enum; |
| 468 | + $field->values = $v->getField()->values; |
| 469 | + $field->ui = $v->getField()->ui; |
| 470 | + $v = $v->get(); |
| 471 | + } |
| 472 | + $entityCloned->data[$k] = $v; |
| 473 | + } |
| 474 | + }, null, Model::class)(); |
| 475 | + |
| 476 | + $this->model = $entityCloned; |
| 477 | + $this->currentRow = $entityCloned; // TODO we should either drop currentRow property or never update model property |
425 | 478 | if ($this->hook(self::HOOK_BEFORE_ROW) === false) { |
426 | 479 | continue; |
427 | 480 | } |
|
0 commit comments