|
23 | 23 | use umi\orm\manager\TObjectManagerAware; |
24 | 24 | use umi\orm\metadata\field\IField; |
25 | 25 | use umi\orm\metadata\field\relation\ManyToManyRelationField; |
| 26 | +use umi\orm\metadata\field\special\FormulaField; |
26 | 27 | use umi\orm\metadata\IMetadata; |
27 | 28 | use umi\orm\metadata\IObjectType; |
28 | 29 | use umi\orm\object\IObject; |
@@ -414,81 +415,46 @@ public function persistNewObject(IObject $object) |
414 | 415 | /** |
415 | 416 | * {@inheritdoc} |
416 | 417 | */ |
417 | | - public function persistModifiedObject(IObject $object) |
| 418 | + public function persistRecalculatedObject(IObject $object, array $formulaProperties) |
418 | 419 | { |
419 | 420 | if (!$this->contains($object)) { |
420 | 421 | throw new NotAllowedOperationException($this->translate( |
421 | 422 | 'Cannot persist modified object. Object from another collection given.' |
422 | 423 | )); |
423 | 424 | } |
424 | | - |
425 | | - $modifiedProperties = $object->getModifiedProperties(); |
426 | | - if (!count($modifiedProperties)) { |
427 | | - return; |
| 425 | + if (count($formulaProperties)) { |
| 426 | + $this->executeUpdate($object, $formulaProperties); |
428 | 427 | } |
| 428 | + } |
429 | 429 |
|
430 | | - $dataSource = $this->getMetadata()->getCollectionDataSource(); |
431 | | - $identifyColumnName = $this->getIdentifyField()->getColumnName(); |
| 430 | + /** |
| 431 | + * {@inheritdoc} |
| 432 | + */ |
| 433 | + public function persistModifiedObject(IObject $object) |
| 434 | + { |
| 435 | + if (!$this->contains($object)) { |
| 436 | + throw new NotAllowedOperationException($this->translate( |
| 437 | + 'Cannot persist modified object. Object from another collection given.' |
| 438 | + )); |
| 439 | + } |
432 | 440 |
|
433 | | - $updateBuilder = $dataSource->update(); |
| 441 | + $modifiedProperties = []; |
| 442 | + $formulaProperties = []; |
434 | 443 |
|
435 | | - foreach ($modifiedProperties as $property) { |
436 | | - if ($this->getMetadata()->getFieldExists($property->getName())) { |
437 | | - $field = $this->getMetadata()->getField($property->getName()); |
438 | | - $field->persistProperty($object, $property, $updateBuilder); |
| 444 | + foreach ($object->getModifiedProperties()as $property) { |
| 445 | + if ($property->getField() instanceof FormulaField) { |
| 446 | + $formulaProperties[] = $property; |
| 447 | + } else { |
| 448 | + $modifiedProperties[] = $property; |
439 | 449 | } |
440 | 450 | } |
441 | 451 |
|
442 | | - if ($updateBuilder->getUpdatePossible()) { |
443 | | - |
444 | | - $versionProperty = $object->getProperty(IObject::FIELD_VERSION); |
445 | | - $version = (int) ($versionProperty->getPersistedDbValue() ? : $versionProperty->getDbValue()); |
446 | | - $newVersion = $version + 1; |
447 | | - $versionProperty->setValue($newVersion); |
448 | | - |
449 | | - $versionColumnName = $this->getVersionField()->getColumnName(); |
450 | | - |
451 | | - $this->getVersionField()->persistProperty($object, $versionProperty, $updateBuilder); |
452 | | - |
453 | | - $updateBuilder->where() |
454 | | - ->expr($identifyColumnName, '=', ':objectId'); |
455 | | - $updateBuilder->bindValue( |
456 | | - ':objectId', |
457 | | - $object->getId(), |
458 | | - $this->getIdentifyField()->getDataType() |
459 | | - ); |
460 | | - |
461 | | - $updateBuilder->where()->expr($versionColumnName, '=', ':' . $versionColumnName); |
462 | | - $updateBuilder->bindValue(':' . $versionColumnName, $version, $this->getVersionField()->getDataType()); |
463 | | - |
464 | | - $result = $updateBuilder->execute(); |
465 | | - |
466 | | - if ($result->rowCount() != 1) { |
467 | | - |
468 | | - $selectBuilder = $dataSource->select($versionColumnName); |
469 | | - $selectBuilder->where() |
470 | | - ->expr($identifyColumnName, '=', ':objectId'); |
471 | | - $selectBuilder->bindValue( |
472 | | - ':objectId', |
473 | | - $object->getId(), |
474 | | - $this->getIdentifyField()->getDataType() |
475 | | - ); |
476 | | - |
477 | | - $selectResult = $selectBuilder->execute(); |
478 | | - $selectResultRow = $selectResult->fetch(); |
479 | | - |
480 | | - if (is_array($selectResultRow) && $selectResultRow[$versionColumnName] != $version) { |
481 | | - throw new RuntimeException($this->translate( |
482 | | - 'Cannot modify object with id "{id}" and type "{type}". Object is out of date.', |
483 | | - ['id' => $object->getId(), 'type' => $object->getTypePath()] |
484 | | - )); |
485 | | - } |
| 452 | + if ($formulaProperties) { |
| 453 | + $this->getObjectPersister()->storeRecalculatedObject($object, $formulaProperties); |
| 454 | + } |
486 | 455 |
|
487 | | - throw new RuntimeException($this->translate( |
488 | | - 'Cannot modify object with id "{id}" and type "{type}". Database row is not modified.', |
489 | | - ['id' => $object->getId(), 'type' => $object->getTypePath()] |
490 | | - )); |
491 | | - } |
| 456 | + if (count($modifiedProperties)) { |
| 457 | + $this->executeUpdate($object, $modifiedProperties); |
492 | 458 | } |
493 | 459 | } |
494 | 460 |
|
@@ -542,4 +508,86 @@ protected function getRequiredField($fieldName) |
542 | 508 |
|
543 | 509 | return $this->metadata->getField($fieldName); |
544 | 510 | } |
| 511 | + |
| 512 | + /** |
| 513 | + * Запускает обновление объекта по указанным свойствам |
| 514 | + * @param IObject $object |
| 515 | + * @param IProperty[] $properties |
| 516 | + * @throws RuntimeException если обновление не прошло |
| 517 | + */ |
| 518 | + protected function executeUpdate(IObject $object, array $properties) |
| 519 | + { |
| 520 | + $dataSource = $this->getMetadata()->getCollectionDataSource(); |
| 521 | + $identifyColumnName = $this->getIdentifyField()->getColumnName(); |
| 522 | + $updateBuilder = $dataSource->update(); |
| 523 | + |
| 524 | + foreach ($properties as $property) { |
| 525 | + if ($this->getMetadata()->getFieldExists($property->getName())) { |
| 526 | + $field = $this->getMetadata()->getField($property->getName()); |
| 527 | + $field->persistProperty($object, $property, $updateBuilder); |
| 528 | + } |
| 529 | + } |
| 530 | + |
| 531 | + if ($updateBuilder->getUpdatePossible()) { |
| 532 | + |
| 533 | + $versionProperty = $object->getProperty(IObject::FIELD_VERSION); |
| 534 | + $version = (int) ($versionProperty->getPersistedDbValue() ? : $versionProperty->getDbValue()); |
| 535 | + $newVersion = $version + 1; |
| 536 | + $versionProperty->setValue($newVersion); |
| 537 | + |
| 538 | + $versionColumnName = $this->getVersionField() |
| 539 | + ->getColumnName(); |
| 540 | + |
| 541 | + $this->getVersionField() |
| 542 | + ->persistProperty($object, $versionProperty, $updateBuilder); |
| 543 | + |
| 544 | + $updateBuilder->where() |
| 545 | + ->expr($identifyColumnName, '=', ':objectId'); |
| 546 | + $updateBuilder->bindValue( |
| 547 | + ':objectId', |
| 548 | + $object->getId(), |
| 549 | + $this->getIdentifyField() |
| 550 | + ->getDataType() |
| 551 | + ); |
| 552 | + |
| 553 | + $updateBuilder->where() |
| 554 | + ->expr($versionColumnName, '=', ':' . $versionColumnName); |
| 555 | + $updateBuilder->bindValue( |
| 556 | + ':' . $versionColumnName, |
| 557 | + $version, |
| 558 | + $this->getVersionField() |
| 559 | + ->getDataType() |
| 560 | + ); |
| 561 | + |
| 562 | + $result = $updateBuilder->execute(); |
| 563 | + |
| 564 | + if ($result->rowCount() != 1) { |
| 565 | + |
| 566 | + $selectBuilder = $dataSource->select($versionColumnName); |
| 567 | + $selectBuilder->where() |
| 568 | + ->expr($identifyColumnName, '=', ':objectId'); |
| 569 | + $selectBuilder->bindValue( |
| 570 | + ':objectId', |
| 571 | + $object->getId(), |
| 572 | + $this->getIdentifyField() |
| 573 | + ->getDataType() |
| 574 | + ); |
| 575 | + |
| 576 | + $selectResult = $selectBuilder->execute(); |
| 577 | + $selectResultRow = $selectResult->fetch(); |
| 578 | + |
| 579 | + if (is_array($selectResultRow) && $selectResultRow[$versionColumnName] != $version) { |
| 580 | + throw new RuntimeException($this->translate( |
| 581 | + 'Cannot modify object with id "{id}" and type "{type}". Object is out of date.', |
| 582 | + ['id' => $object->getId(), 'type' => $object->getTypePath()] |
| 583 | + )); |
| 584 | + } |
| 585 | + |
| 586 | + throw new RuntimeException($this->translate( |
| 587 | + 'Cannot modify object with id "{id}" and type "{type}". Database row is not modified.', |
| 588 | + ['id' => $object->getId(), 'type' => $object->getTypePath()] |
| 589 | + )); |
| 590 | + } |
| 591 | + } |
| 592 | + } |
545 | 593 | } |
0 commit comments