예제 #1
0
파일: DbMapper.php 프로젝트: matak/dbrecord
 /**
  * Update row.
  *
  * @throws Exception
  *
  * @return System\DbRecord\DbRecord
  */
 public function update(DbRecord $record)
 {
     if (!$record->isRecordExisting()) {
         throw new \Nette\InvalidStateException("Only existing row can be updated.");
     }
     $engine = $this->getConnection();
     if (!$engine->inTransaction()) {
         $doCommit = true;
         $engine->begin();
     }
     if ($record->isDirty()) {
         try {
             if (isset($record->belongsToCollection)) {
                 //	patrim do kolekce a již jsem uložen v databázi! logicky
                 //	predek uz musi met nastaveny PK ...
                 $collection = $record->belongsToCollection;
                 $localId = $collection->getAssociation()->getForeignId();
                 $collectionOwner = $collection->getBelongsToRecord();
                 $ownerId = $collection->getAssociation()->getLocalId();
                 if (!isset($collectionOwner->{$ownerId})) {
                     throw new \LogicException("Collection owner has not primary key, associations can not be updated! {$ownerId}");
                 }
                 //	... i ja musím mít nastaven relační klíč...
                 if (!isset($record->{$localId})) {
                     throw new \LogicException("Member of collection can not be save without known primary key of owner of collection! {$localId}");
                 }
                 //	... a musí být shodný s rodičem kolekce.
                 if ($record->{$localId} != $collectionOwner->{$ownerId}) {
                     throw new \LogicException("Member of collection has different id then owner of collection! [" . $record->{$localId} . " / " . $collectionOwner->{$ownerId} . "]");
                 }
             }
             $this->onBeforeUpdate($record);
             if (!$record->isValid(EntityValidator::VALIDATION_UPDATE)) {
                 $errors = $record->getErrors();
                 if (count($errors)) {
                     $msg = current($errors);
                     throw new Exception($msg[0]);
                 } else {
                     throw new Exception("Undefined validator exception!");
                 }
             }
             $this->onBeforeUpdateAfterValidation($record);
             $values = $record->getModifiedValues(true);
             $config = $this->getConfig();
             if ($config->isPrimaryAutoincrement()) {
                 $pk = $config->getPrimaryColumn();
                 unset($values[$pk . "%" . $config->getType($pk)]);
             }
             if (count($values)) {
                 $engine->update($record::table(), $values)->where('%and', $record->getPrimaryCondition())->execute();
             }
         } catch (\DibiException $e) {
             if ($engine->getDriver() instanceof \DibiMySqliDriver) {
                 switch ($e->getCode()) {
                     case \DibiMySqliDriver::ERROR_DUPLICATE_ENTRY:
                         if (preg_match('~Duplicate entry \'([^\']*)\' for key \'([^\']*)\'~', $e->getMessage(), $matches)) {
                             $msg = $record::validator()->translate('v/recordDuplicity', 1, array('{__ENTRY__}' => $matches[1], '{__KEY__}' => $matches[2]));
                             throw new Exception($msg, $e->getCode(), $e);
                         } else {
                             throw $e;
                         }
                         break;
                     default:
                         throw $e;
                 }
             } else {
                 throw new \LogicException('implementovane pouze pro mysql.');
             }
         }
         $record->clearModified();
     }
     foreach ($record->getAssociations() as $key => $associationObject) {
         // treba neexistuje, kdyz neni povinna vytvori se NULL
         if (!$associationObject) {
             continue;
         }
         $associationObject->save();
     }
     $this->onAfterUpdate($record);
     if (isset($doCommit)) {
         $engine->commit();
     }
     // set action / pravdepodobne probehla v poradku
     $record->lastAction('u');
     $record->setLastAffectedRows($engine->affectedRows());
     return $record;
 }