/** * Filters read access to the unknown property __META__. * * @param Doctrine_Record $record Record. * @param String $name Name of the unkown property. * * @return mixed * @throws Doctrine_Record_UnknownPropertyException If $name is not __META__. */ public function filterGet(Doctrine_Record $record, $name) { if ($name == '__META__') { $value = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS); $record->mapValue('__META__', $value); if ($record->state() == Doctrine_Record::STATE_CLEAN) { $record->state(Doctrine_Record::STATE_DIRTY); } return $value; } else { throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $name, get_class($record))); } }
/** * setDefaultValues * sets the default values for records internal data * * @param boolean $overwrite whether or not to overwrite the already set values * @return boolean */ public function assignDefaultValues($data, $overwrite = false) { $table = $this->_record->getTable(); if (!$table->hasDefaultValues()) { return false; } $modified = array(); foreach ($data as $column => $value) { $default = $table->getDefaultValueOf($column); if ($default === null) { $default = self::$_null; } if ($value === self::$_null || $overwrite) { $this->_record->rawSet($column, $default); $modified[] = $column; $this->_record->state(Doctrine_Record::STATE_TDIRTY); } } $this->_record->setModified($modified); }
/** * Dumps a record. * * This method returns an html representation of a given * record, containing keys, state and data. * * @param Doctrine_Record $record * @return string */ public static function getRecordAsString(Doctrine_Record $record) { $r[] = '<pre>'; $r[] = 'Component : ' . $record->getTable()->getComponentName(); $r[] = 'ID : ' . Doctrine::dump($record->identifier()); $r[] = 'References : ' . count($record->getReferences()); $r[] = 'State : ' . Doctrine_Lib::getRecordStateAsString($record->state()); $r[] = 'OID : ' . $record->getOID(); $r[] = 'data : ' . Doctrine::dump($record->getData(), false); $r[] = '</pre>'; return implode("\n", $r) . "<br />"; }
/** * saveRelatedLocalKeys * saves all related (through LocalKey) records to $record * * @throws PDOException if something went wrong at database level * @param Doctrine_Record $record */ public function saveRelatedLocalKeys(Doctrine_Record $record) { $state = $record->state(); $record->state($record->exists() ? Doctrine_Record::STATE_LOCKED : Doctrine_Record::STATE_TLOCKED); foreach ($record->getReferences() as $k => $v) { $rel = $record->getTable()->getRelation($k); $local = $rel->getLocal(); $foreign = $rel->getForeign(); if ($rel instanceof Doctrine_Relation_LocalKey) { // ONE-TO-ONE relationship $obj = $record->get($rel->getAlias()); // Protection against infinite function recursion before attempting to save if ($obj instanceof Doctrine_Record && $obj->isModified()) { $obj->save($this->conn); $id = array_values($obj->identifier()); if (!empty($id)) { foreach ((array) $rel->getLocal() as $k => $columnName) { $field = $record->getTable()->getFieldName($columnName); if (isset($id[$k]) && $id[$k] && $record->getTable()->hasField($field)) { $record->set($field, $id[$k]); } } } } } } $record->state($state); }
/** * saves the given record * * @param Doctrine_Record $record * @return void */ public function save(Doctrine_Record $record) { $event = new Doctrine_Event($record, Doctrine_Event::RECORD_SAVE); $record->preSave($event); $record->getTable()->getRecordListener()->preSave($event); if (!$event->skipOperation) { switch ($record->state()) { case Doctrine_Record::STATE_TDIRTY: case Doctrine_Record::STATE_TCLEAN: $this->insert($record); break; case Doctrine_Record::STATE_DIRTY: case Doctrine_Record::STATE_PROXY: $this->update($record); break; case Doctrine_Record::STATE_CLEAN: // do nothing break; } } $record->getTable()->getRecordListener()->postSave($event); $record->postSave($event); }
/** * Saves the given record and all associated records. * (The save() operation is always cascaded in 0.10/1.0). * * @param Doctrine_Record $record * @return void */ public function saveGraph(Doctrine_Record $record) { $record->assignInheritanceValues(); $conn = $this->getConnection(); $state = $record->state(); if ($state === Doctrine_Record::STATE_LOCKED || $state === Doctrine_Record::STATE_TLOCKED) { return false; } $record->state($record->exists() ? Doctrine_Record::STATE_LOCKED : Doctrine_Record::STATE_TLOCKED); try { $conn->beginInternalTransaction(); $record->state($state); $event = $record->invokeSaveHooks('pre', 'save'); $state = $record->state(); $isValid = true; if (!$event->skipOperation) { $this->saveRelatedLocalKeys($record); switch ($state) { case Doctrine_Record::STATE_TDIRTY: case Doctrine_Record::STATE_TCLEAN: $isValid = $this->insert($record); break; case Doctrine_Record::STATE_DIRTY: case Doctrine_Record::STATE_PROXY: $isValid = $this->update($record); break; case Doctrine_Record::STATE_CLEAN: // do nothing break; } if ($isValid) { // NOTE: what about referential integrity issues? foreach ($record->getPendingDeletes() as $pendingDelete) { $pendingDelete->delete(); } foreach ($record->getPendingUnlinks() as $alias => $ids) { if (!$ids) { $record->unlinkInDb($alias, array()); } else { $record->unlinkInDb($alias, array_keys($ids)); } } $record->resetPendingUnlinks(); $record->invokeSaveHooks('post', 'save', $event); } else { $conn->transaction->addInvalid($record); } $state = $record->state(); $record->state($record->exists() ? Doctrine_Record::STATE_LOCKED : Doctrine_Record::STATE_TLOCKED); if ($isValid) { $saveLater = $this->saveRelatedForeignKeys($record); foreach ($saveLater as $fk) { $alias = $fk->getAlias(); if ($record->hasReference($alias)) { $obj = $record->{$alias}; // check that the related object is not an instance of Doctrine_Null if ($obj && !$obj instanceof Doctrine_Null) { $obj->save($conn); } } } // save the MANY-TO-MANY associations $this->saveAssociations($record); } } $record->state($state); $conn->commit(); } catch (Exception $e) { // Make sure we roll back our internal transaction //$record->state($state); $conn->rollback(); throw $e; } $record->clearInvokedSaveHooks(); return true; }
/** * deletes this data access object and all the related composites * this operation is isolated by a transaction * * this event can be listened by the onPreDelete and onDelete listeners * * @return boolean true on success, false on failure */ public function delete(Doctrine_Record $record) { if (!$record->exists()) { return false; } $this->conn->beginTransaction(); $event = new Doctrine_Event($this, Doctrine_Event::RECORD_DELETE); $record->preDelete($event); $record->state(Doctrine_Record::STATE_LOCKED); $this->deleteComposites($record); $record->state(Doctrine_Record::STATE_TDIRTY); if (!$event->skipOperation) { $this->conn->transaction->addDelete($record); $record->state(Doctrine_Record::STATE_TCLEAN); } $record->postDelete($event); $this->conn->commit(); return true; }
/** * deletes given record and all the related composites * this operation is isolated by a transaction * * this event can be listened by the onPreDelete and onDelete listeners * * @return boolean true on success, false on failure */ public function delete(Doctrine_Record $record) { if (!$record->exists()) { return false; } $this->conn->beginTransaction(); $event = new Doctrine_Event($record, Doctrine_Event::RECORD_DELETE); $record->preDelete($event); $table = $record->getTable(); $table->getRecordListener()->preDelete($event); $state = $record->state(); $record->state(Doctrine_Record::STATE_LOCKED); $this->deleteComposites($record); if (!$event->skipOperation) { $record->state(Doctrine_Record::STATE_TDIRTY); if ($table->getOption('joinedParents')) { foreach ($table->getOption('joinedParents') as $parent) { $parentTable = $table->getConnection()->getTable($parent); $this->conn->delete($parentTable, $record->identifier()); } } $this->conn->delete($table, $record->identifier()); $record->state(Doctrine_Record::STATE_TCLEAN); } else { // return to original state $record->state($state); } $table->getRecordListener()->postDelete($event); $record->postDelete($event); $table->removeRecord($record); $this->conn->commit(); return true; }