コード例 #1
0
 /**
  * Generate and write the database manipulation for all changed fields
  *
  * @param string $baseTable Base table
  * @param string $now Timestamp to use for the current time
  * @param bool $isNewRecord If this is a new record
  */
 protected function writeManipulation($baseTable, $now, $isNewRecord)
 {
     // Generate database manipulations for each class
     $manipulation = array();
     foreach ($this->getClassAncestry() as $class) {
         if (self::has_own_table($class)) {
             $this->prepareManipulationTable($baseTable, $now, $isNewRecord, $manipulation, $class);
         }
     }
     // Allow extensions to extend this manipulation
     $this->extend('augmentWrite', $manipulation);
     // New records have their insert into the base data table done first, so that they can pass the
     // generated ID on to the rest of the manipulation
     if ($isNewRecord) {
         $manipulation[$baseTable]['command'] = 'update';
     }
     // Perform the manipulation
     DB::manipulate($manipulation);
 }
コード例 #2
0
ファイル: DataObject.php プロジェクト: nomidi/sapphire
 /**
  * Writes all changes to this object to the database.
  *  - It will insert a record whenever ID isn't set, otherwise update.
  *  - All relevant tables will be updated.
  *  - $this->onBeforeWrite() gets called beforehand.
  *  - Extensions such as Versioned will ammend the database-write to ensure that a version is saved.
  * 
  *  @uses DataExtension->augmentWrite()
  *
  * @param boolean $showDebug Show debugging information
  * @param boolean $forceInsert Run INSERT command rather than UPDATE, even if record already exists
  * @param boolean $forceWrite Write to database even if there are no changes
  * @param boolean $writeComponents Call write() on all associated component instances which were previously
  * 					retrieved through {@link getComponent()}, {@link getComponents()} or {@link getManyManyComponents()}
  * 					(Default: false)
  *
  * @return int The ID of the record
  * @throws ValidationException Exception that can be caught and handled by the calling function
  */
 public function write($showDebug = false, $forceInsert = false, $forceWrite = false, $writeComponents = false)
 {
     $firstWrite = false;
     $this->brokenOnWrite = true;
     $isNewRecord = false;
     if (self::get_validation_enabled()) {
         $valid = $this->validate();
         if (!$valid->valid()) {
             // Used by DODs to clean up after themselves, eg, Versioned
             $this->extend('onAfterSkippedWrite');
             throw new ValidationException($valid, "Validation error writing a {$this->class} object: " . $valid->message() . ".  Object not written.", E_USER_WARNING);
             return false;
         }
     }
     $this->onBeforeWrite();
     if ($this->brokenOnWrite) {
         user_error("{$this->class} has a broken onBeforeWrite() function.  Make sure that you call parent::onBeforeWrite().", E_USER_ERROR);
     }
     // New record = everything has changed
     if ($this->ID && is_numeric($this->ID) && !$forceInsert) {
         $dbCommand = 'update';
         // Update the changed array with references to changed obj-fields
         foreach ($this->record as $k => $v) {
             if (is_object($v) && method_exists($v, 'isChanged') && $v->isChanged()) {
                 $this->changed[$k] = true;
             }
         }
     } else {
         $dbCommand = 'insert';
         $this->changed = array();
         foreach ($this->record as $k => $v) {
             $this->changed[$k] = 2;
         }
         $firstWrite = true;
     }
     // No changes made
     if ($this->changed) {
         foreach ($this->getClassAncestry() as $ancestor) {
             if (self::has_own_table($ancestor)) {
                 $ancestry[] = $ancestor;
             }
         }
         // Look for some changes to make
         if (!$forceInsert) {
             unset($this->changed['ID']);
         }
         $hasChanges = false;
         foreach ($this->changed as $fieldName => $changed) {
             if ($changed) {
                 $hasChanges = true;
                 break;
             }
         }
         if ($hasChanges || $forceWrite || !$this->record['ID']) {
             // New records have their insert into the base data table done first, so that they can pass the
             // generated primary key on to the rest of the manipulation
             $baseTable = $ancestry[0];
             if ((!isset($this->record['ID']) || !$this->record['ID']) && isset($ancestry[0])) {
                 DB::query("INSERT INTO \"{$baseTable}\" (\"Created\") VALUES (" . DB::getConn()->now() . ")");
                 $this->record['ID'] = DB::getGeneratedID($baseTable);
                 $this->changed['ID'] = 2;
                 $isNewRecord = true;
             }
             // Divvy up field saving into a number of database manipulations
             $manipulation = array();
             if (isset($ancestry) && is_array($ancestry)) {
                 foreach ($ancestry as $idx => $class) {
                     $classSingleton = singleton($class);
                     foreach ($this->record as $fieldName => $fieldValue) {
                         if (isset($this->changed[$fieldName]) && $this->changed[$fieldName] && ($fieldType = $classSingleton->hasOwnTableDatabaseField($fieldName))) {
                             $fieldObj = $this->dbObject($fieldName);
                             if (!isset($manipulation[$class])) {
                                 $manipulation[$class] = array();
                             }
                             // if database column doesn't correlate to a DBField instance...
                             if (!$fieldObj) {
                                 $fieldObj = DBField::create_field('Varchar', $this->record[$fieldName], $fieldName);
                             }
                             // Both CompositeDBFields and regular fields need to be repopulated
                             $fieldObj->setValue($this->record[$fieldName], $this->record);
                             if ($class != $baseTable || $fieldName != 'ID') {
                                 $fieldObj->writeToManipulation($manipulation[$class]);
                             }
                         }
                     }
                     // Add the class name to the base object
                     if ($idx == 0) {
                         $manipulation[$class]['fields']["LastEdited"] = "'" . SS_Datetime::now()->Rfc2822() . "'";
                         if ($dbCommand == 'insert') {
                             $manipulation[$class]['fields']["Created"] = "'" . SS_Datetime::now()->Rfc2822() . "'";
                             //echo "<li>$this->class - " .get_class($this);
                             $manipulation[$class]['fields']["ClassName"] = DB::getConn()->prepStringForDB($this->class);
                         }
                     }
                     // In cases where there are no fields, this 'stub' will get picked up on
                     if (self::has_own_table($class)) {
                         $manipulation[$class]['command'] = $dbCommand;
                         $manipulation[$class]['id'] = $this->record['ID'];
                     } else {
                         unset($manipulation[$class]);
                     }
                 }
             }
             $this->extend('augmentWrite', $manipulation);
             // New records have their insert into the base data table done first, so that they can pass the
             // generated ID on to the rest of the manipulation
             if (isset($isNewRecord) && $isNewRecord && isset($manipulation[$baseTable])) {
                 $manipulation[$baseTable]['command'] = 'update';
             }
             DB::manipulate($manipulation);
             $this->onAfterWrite();
             $this->changed = null;
         } elseif ($showDebug) {
             echo "<b>Debug:</b> no changes for DataObject<br />";
             // Used by DODs to clean up after themselves, eg, Versioned
             $this->extend('onAfterSkippedWrite');
         }
         // Clears the cache for this object so get_one returns the correct object.
         $this->flushCache();
         if (!isset($this->record['Created'])) {
             $this->record['Created'] = SS_Datetime::now()->Rfc2822();
         }
         $this->record['LastEdited'] = SS_Datetime::now()->Rfc2822();
     } else {
         // Used by DODs to clean up after themselves, eg, Versioned
         $this->extend('onAfterSkippedWrite');
     }
     // Write relations as necessary
     if ($writeComponents) {
         $this->writeComponents(true);
     }
     return $this->record['ID'];
 }
コード例 #3
0
 /**
  * @param String $identifier Unique identifier for this fixture type
  * @param Array $data Map of property names to their values.
  * @param Array $fixtures Map of fixture names to an associative array of their in-memory
  *                        identifiers mapped to their database IDs. Used to look up
  *                        existing fixtures which might be referenced in the $data attribute
  *                        via the => notation.
  * @return DataObject
  */
 public function createObject($identifier, $data = null, $fixtures = null)
 {
     // We have to disable validation while we import the fixtures, as the order in
     // which they are imported doesnt guarantee valid relations until after the import is complete.
     $validationenabled = Config::inst()->get('DataObject', 'validation_enabled');
     Config::inst()->update('DataObject', 'validation_enabled', false);
     $this->invokeCallbacks('beforeCreate', array($identifier, &$data, &$fixtures));
     try {
         $class = $this->class;
         $obj = DataModel::inst()->{$class}->newObject();
         // If an ID is explicitly passed, then we'll sort out the initial write straight away
         // This is just in case field setters triggered by the population code in the next block
         // Call $this->write().  (For example, in FileTest)
         if (isset($data['ID'])) {
             $obj->ID = $data['ID'];
             // The database needs to allow inserting values into the foreign key column (ID in our case)
             $conn = DB::getConn();
             if (method_exists($conn, 'allowPrimaryKeyEditing')) {
                 $conn->allowPrimaryKeyEditing(ClassInfo::baseDataClass($class), true);
             }
             $obj->write(false, true);
             if (method_exists($conn, 'allowPrimaryKeyEditing')) {
                 $conn->allowPrimaryKeyEditing(ClassInfo::baseDataClass($class), false);
             }
         }
         // Populate defaults
         if ($this->defaults) {
             foreach ($this->defaults as $fieldName => $fieldVal) {
                 if (isset($data[$fieldName]) && $data[$fieldName] !== false) {
                     continue;
                 }
                 if (is_callable($fieldVal)) {
                     $obj->{$fieldName} = $fieldVal($obj, $data, $fixtures);
                 } else {
                     $obj->{$fieldName} = $fieldVal;
                 }
             }
         }
         // Populate overrides
         if ($data) {
             foreach ($data as $fieldName => $fieldVal) {
                 // Defer relationship processing
                 if ($obj->many_many($fieldName) || $obj->has_many($fieldName) || $obj->has_one($fieldName)) {
                     continue;
                 }
                 $this->setValue($obj, $fieldName, $fieldVal, $fixtures);
             }
         }
         $obj->write();
         // Save to fixture before relationship processing in case of reflexive relationships
         if (!isset($fixtures[$class])) {
             $fixtures[$class] = array();
         }
         $fixtures[$class][$identifier] = $obj->ID;
         // Populate all relations
         if ($data) {
             foreach ($data as $fieldName => $fieldVal) {
                 if ($obj->many_many($fieldName) || $obj->has_many($fieldName)) {
                     $parsedItems = array();
                     $items = preg_split('/ *, */', trim($fieldVal));
                     foreach ($items as $item) {
                         // Check for correct format: =><relationname>.<identifier>.
                         // Ignore if the item has already been replaced with a numeric DB identifier
                         if (!is_numeric($item) && !preg_match('/^=>[^\\.]+\\.[^\\.]+/', $item)) {
                             throw new InvalidArgumentException(sprintf('Invalid format for relation "%s" on class "%s" ("%s")', $fieldName, $class, $item));
                         }
                         $parsedItems[] = $this->parseValue($item, $fixtures);
                     }
                     $obj->write();
                     if ($obj->has_many($fieldName)) {
                         $obj->getComponents($fieldName)->setByIDList($parsedItems);
                     } elseif ($obj->many_many($fieldName)) {
                         $obj->getManyManyComponents($fieldName)->setByIDList($parsedItems);
                     }
                 } elseif ($obj->has_one($fieldName)) {
                     // Sets has_one with relation name
                     $obj->{$fieldName . 'ID'} = $this->parseValue($fieldVal, $fixtures);
                 } elseif ($obj->has_one(preg_replace('/ID$/', '', $fieldName))) {
                     // Sets has_one with database field
                     $obj->{$fieldName} = $this->parseValue($fieldVal, $fixtures);
                 }
             }
         }
         $obj->write();
         // If LastEdited was set in the fixture, set it here
         if ($data && array_key_exists('LastEdited', $data)) {
             $edited = $this->parseValue($data['LastEdited'], $fixtures);
             DB::manipulate(array($class => array("command" => "update", "id" => $obj->id, "fields" => array("LastEdited" => "'" . $edited . "'"))));
         }
     } catch (Exception $e) {
         Config::inst()->update('DataObject', 'validation_enabled', $validationenabled);
         throw $e;
     }
     Config::inst()->update('DataObject', 'validation_enabled', $validationenabled);
     $this->invokeCallbacks('afterCreate', array($obj, $identifier, &$data, &$fixtures));
     return $obj;
 }
コード例 #4
0
 protected function overrideField($obj, $fieldName, $value, $fixtures = null)
 {
     $table = ClassInfo::table_for_object_field(get_class($obj), $fieldName);
     $value = $this->parseValue($value, $fixtures);
     DB::manipulate(array($table => array("command" => "update", "id" => $obj->ID, "fields" => array($fieldName => $value))));
     $obj->{$fieldName} = $value;
 }
コード例 #5
0
 /**
  * Writes the fixture into the database directly using a database manipulation
  *
  * @param string $table
  * @param array $items
  */
 protected function writeSQL($table, $items)
 {
     foreach ($items as $identifier => $fields) {
         $manipulation = array($table => array("fields" => array(), "command" => "insert"));
         foreach ($fields as $fieldName => $fieldVal) {
             $manipulation[$table]["fields"][$fieldName] = "'" . $this->parseFixtureVal($fieldVal) . "'";
         }
         DB::manipulate($manipulation);
         $this->fixtureDictionary[$table][$identifier] = DB::getGeneratedID($table);
     }
 }
コード例 #6
0
ファイル: ManyManyList.php プロジェクト: tcaiger/mSupplyNZ
 /**
  * Add an item to this many_many relationship
  * Does so by adding an entry to the joinTable.
  *
  * @param mixed $item
  * @param array $extraFields A map of additional columns to insert into the joinTable.
  * Column names should be ANSI quoted.
  */
 public function add($item, $extraFields = array())
 {
     // Ensure nulls or empty strings are correctly treated as empty arrays
     if (empty($extraFields)) {
         $extraFields = array();
     }
     // Determine ID of new record
     if (is_numeric($item)) {
         $itemID = $item;
     } elseif ($item instanceof $this->dataClass) {
         $itemID = $item->ID;
     } else {
         throw new InvalidArgumentException("ManyManyList::add() expecting a {$this->dataClass} object, or ID value", E_USER_ERROR);
     }
     // Validate foreignID
     $foreignIDs = $this->getForeignID();
     if (empty($foreignIDs)) {
         throw new Exception("ManyManyList::add() can't be called until a foreign ID is set", E_USER_WARNING);
     }
     // Apply this item to each given foreign ID record
     if (!is_array($foreignIDs)) {
         $foreignIDs = array($foreignIDs);
     }
     foreach ($foreignIDs as $foreignID) {
         // Check for existing records for this item
         if ($foreignFilter = $this->foreignIDWriteFilter($foreignID)) {
             // With the current query, simply add the foreign and local conditions
             // The query can be a bit odd, especially if custom relation classes
             // don't join expected tables (@see Member_GroupSet for example).
             $query = new SQLQuery("*", "\"{$this->joinTable}\"");
             $query->addWhere($foreignFilter);
             $query->addWhere(array("\"{$this->joinTable}\".\"{$this->localKey}\"" => $itemID));
             $hasExisting = $query->count() > 0;
         } else {
             $hasExisting = false;
         }
         // Blank manipulation
         $manipulation = array($this->joinTable => array('command' => $hasExisting ? 'update' : 'insert', 'fields' => array()));
         if ($hasExisting) {
             $manipulation[$this->joinTable]['where'] = array("\"{$this->joinTable}\".\"{$this->foreignKey}\"" => $foreignID, "\"{$this->joinTable}\".\"{$this->localKey}\"" => $itemID);
         }
         if ($extraFields && $this->extraFields) {
             // Write extra field to manipluation in the same way
             // that DataObject::prepareManipulationTable writes fields
             foreach ($this->extraFields as $fieldName => $fieldSpec) {
                 // Skip fields without an assignment
                 if (array_key_exists($fieldName, $extraFields)) {
                     $fieldObject = Object::create_from_string($fieldSpec, $fieldName);
                     $fieldObject->setValue($extraFields[$fieldName]);
                     $fieldObject->writeToManipulation($manipulation[$this->joinTable]);
                 }
             }
         }
         $manipulation[$this->joinTable]['fields'][$this->localKey] = $itemID;
         $manipulation[$this->joinTable]['fields'][$this->foreignKey] = $foreignID;
         DB::manipulate($manipulation);
     }
 }
コード例 #7
0
 /**
  * Add an item to this many_many relationship
  * Does so by adding an entry to the joinTable.
  * @param $extraFields A map of additional columns to insert into the joinTable
  */
 function add($item, $extraFields = null)
 {
     if (is_numeric($item)) {
         $itemID = $item;
     } else {
         if ($item instanceof $this->dataClass) {
             $itemID = $item->ID;
         } else {
             throw new InvalidArgumentException("ManyManyList::add() expecting a {$this->dataClass} object, or ID value", E_USER_ERROR);
         }
     }
     // Validate foreignID
     if (!$this->foreignID) {
         throw new Exception("ManyManyList::add() can't be called until a foreign ID is set", E_USER_WARNING);
     }
     // Delete old entries, to prevent duplication
     $this->removeById($itemID);
     // Insert new entry/entries
     foreach ((array) $this->foreignID as $foreignID) {
         $manipulation = array();
         $manipulation[$this->joinTable]['command'] = 'insert';
         if ($extraFields) {
             foreach ($extraFields as $k => $v) {
                 $manipulation[$this->joinTable]['fields'][$k] = "'" . Convert::raw2sql($v) . "'";
             }
         }
         $manipulation[$this->joinTable]['fields'][$this->localKey] = $itemID;
         $manipulation[$this->joinTable]['fields'][$this->foreignKey] = $foreignID;
         DB::manipulate($manipulation);
     }
 }
コード例 #8
0
ファイル: ManyManyList.php プロジェクト: normann/sapphire
 /**
  * Add an item to this many_many relationship
  * Does so by adding an entry to the joinTable.
  * @param $extraFields A map of additional columns to insert into the joinTable
  */
 public function add($item, $extraFields = null)
 {
     if (is_numeric($item)) {
         $itemID = $item;
     } else {
         if ($item instanceof $this->dataClass) {
             $itemID = $item->ID;
         } else {
             throw new InvalidArgumentException("ManyManyList::add() expecting a {$this->dataClass} object, or ID value", E_USER_ERROR);
         }
     }
     // Validate foreignID
     if (!$this->foreignID) {
         throw new Exception("ManyManyList::add() can't be called until a foreign ID is set", E_USER_WARNING);
     }
     if ($filter = $this->foreignIDFilter()) {
         $query = new SQLQuery("*", array("\"{$this->joinTable}\""));
         $query->setWhere($filter);
         $hasExisting = $query->count() > 0;
     } else {
         $hasExisting = false;
     }
     // Insert or update
     foreach ((array) $this->foreignID as $foreignID) {
         $manipulation = array();
         if ($hasExisting) {
             $manipulation[$this->joinTable]['command'] = 'update';
             $manipulation[$this->joinTable]['where'] = "\"{$this->joinTable}\".\"{$this->foreignKey}\" = " . "'" . Convert::raw2sql($foreignID) . "'" . " AND \"{$this->localKey}\" = {$itemID}";
         } else {
             $manipulation[$this->joinTable]['command'] = 'insert';
         }
         if ($extraFields) {
             foreach ($extraFields as $k => $v) {
                 if (is_null($v)) {
                     $manipulation[$this->joinTable]['fields'][$k] = 'NULL';
                 } else {
                     $manipulation[$this->joinTable]['fields'][$k] = "'" . Convert::raw2sql($v) . "'";
                 }
             }
         }
         $manipulation[$this->joinTable]['fields'][$this->localKey] = $itemID;
         $manipulation[$this->joinTable]['fields'][$this->foreignKey] = $foreignID;
         DB::manipulate($manipulation);
     }
 }
コード例 #9
0
 /**
  * Add an item to this many_many relationship. Does so by adding an entry
  * to the joinTable.
  *
  * @param mixed $item
  * @param array $extraFields A map of additional columns to insert into the
  *								joinTable
  */
 public function add($item, $extraFields = null)
 {
     if (is_numeric($item)) {
         $itemID = $item;
     } else {
         if ($item instanceof $this->dataClass) {
             $itemID = $item->ID;
         } else {
             throw new InvalidArgumentException("ManyManyList::add() expecting a {$this->dataClass} object, or ID value", E_USER_ERROR);
         }
     }
     $foreignIDs = $this->getForeignID();
     $foreignFilter = $this->foreignIDWriteFilter();
     // Validate foreignID
     if (!$foreignIDs) {
         throw new Exception("ManyManyList::add() can't be called until a foreign ID is set", E_USER_WARNING);
     }
     if ($foreignFilter) {
         $query = new SQLQuery("*", array("\"{$this->joinTable}\""));
         $query->setWhere($foreignFilter);
         $hasExisting = $query->count() > 0;
     } else {
         $hasExisting = false;
     }
     // Insert or update
     foreach ((array) $foreignIDs as $foreignID) {
         $manipulation = array();
         if ($hasExisting) {
             $manipulation[$this->joinTable]['command'] = 'update';
             $manipulation[$this->joinTable]['where'] = "\"{$this->joinTable}\".\"{$this->foreignKey}\" = " . "'" . Convert::raw2sql($foreignID) . "'" . " AND \"{$this->localKey}\" = {$itemID}";
         } else {
             $manipulation[$this->joinTable]['command'] = 'insert';
         }
         if ($extraFields) {
             foreach ($extraFields as $k => $v) {
                 if (is_null($v)) {
                     $manipulation[$this->joinTable]['fields'][$k] = 'NULL';
                 } else {
                     if (is_object($v) && $v instanceof DBField) {
                         // rely on writeToManipulation to manage the changes
                         // required for this field.
                         $working = array('fields' => array());
                         // create a new instance of the field so we can
                         // modify the field name to the correct version.
                         $field = DBField::create_field(get_class($v), $v);
                         $field->setName($k);
                         $field->writeToManipulation($working);
                         foreach ($working['fields'] as $extraK => $extraV) {
                             $manipulation[$this->joinTable]['fields'][$extraK] = $extraV;
                         }
                     } else {
                         $manipulation[$this->joinTable]['fields'][$k] = "'" . Convert::raw2sql($v) . "'";
                     }
                 }
             }
         }
         $manipulation[$this->joinTable]['fields'][$this->localKey] = $itemID;
         $manipulation[$this->joinTable]['fields'][$this->foreignKey] = $foreignID;
         DB::manipulate($manipulation);
     }
 }
コード例 #10
0
ファイル: DataObject.php プロジェクト: ramziammar/websites
 /**
  * Writes all changes to this object to the database.
  *  - It will insert a record whenever ID isn't set, otherwise update.
  *  - All relevant tables will be updated.
  *  - $this->onBeforeWrite() gets called beforehand.
  *  - Extensions such as Versioned will ammend the database-write to ensure that a version is saved.
  *  - Calls to {@link DataObjectLog} can be used to see everything that's been changed.
  *
  * @param boolean $showDebug Show debugging information
  * @param boolean $forceInsert Run INSERT command rather than UPDATE, even if record already exists
  * @param boolean $forceWrite Write to database even if there are no changes
  *
  * @return int The ID of the record
  */
 public function write($showDebug = false, $forceInsert = false, $forceWrite = false)
 {
     $firstWrite = false;
     $this->brokenOnWrite = true;
     $isNewRecord = false;
     $this->onBeforeWrite();
     if ($this->brokenOnWrite) {
         user_error("{$this->class} has a broken onBeforeWrite() function.  Make sure that you call parent::onBeforeWrite().", E_USER_ERROR);
     }
     // New record = everything has changed
     if ($this->ID && is_numeric($this->ID) && !$forceInsert) {
         $dbCommand = 'update';
     } else {
         $dbCommand = 'insert';
         $this->changed = array();
         foreach ($this->record as $k => $v) {
             $this->changed[$k] = 2;
         }
         $firstWrite = true;
     }
     // No changes made
     if ($this->changed) {
         foreach ($this->getClassAncestry() as $ancestor) {
             if (ClassInfo::hasTable($ancestor)) {
                 $ancestry[] = $ancestor;
             }
         }
         // Look for some changes to make
         unset($this->changed['ID']);
         $hasChanges = false;
         foreach ($this->changed as $fieldName => $changed) {
             if ($changed) {
                 $hasChanges = true;
                 break;
             }
         }
         if ($hasChanges || $forceWrite || !$this->record['ID']) {
             // New records have their insert into the base data table done first, so that they can pass the
             // generated primary key on to the rest of the manipulation
             if (!$this->record['ID'] && isset($ancestry[0])) {
                 $baseTable = $ancestry[0];
                 DB::query("INSERT INTO `{$baseTable}` SET Created = NOW()");
                 $this->record['ID'] = DB::getGeneratedID($baseTable);
                 $this->changed['ID'] = 2;
                 $isNewRecord = true;
             }
             // Divvy up field saving into a number of database manipulations
             if (isset($ancestry) && is_array($ancestry)) {
                 foreach ($ancestry as $idx => $class) {
                     $classSingleton = singleton($class);
                     foreach ($this->record as $fieldName => $value) {
                         if (isset($this->changed[$fieldName]) && $this->changed[$fieldName] && ($fieldType = $classSingleton->fieldExists($fieldName))) {
                             $manipulation[$class]['fields'][$fieldName] = $value ? "'" . addslashes($value) . "'" : singleton($fieldType)->nullValue();
                         }
                     }
                     // Add the class name to the base object
                     if ($idx == 0) {
                         $manipulation[$class]['fields']["LastEdited"] = "now()";
                         if ($dbCommand == 'insert') {
                             $manipulation[$class]['fields']["Created"] = "now()";
                             //echo "<li>$this->class - " .get_class($this);
                             $manipulation[$class]['fields']["ClassName"] = "'{$this->class}'";
                         }
                     }
                     // In cases where there are no fields, this 'stub' will get picked up on
                     if (ClassInfo::hasTable($class)) {
                         $manipulation[$class]['command'] = $dbCommand;
                         $manipulation[$class]['id'] = $this->record['ID'];
                     } else {
                         unset($manipulation[$class]);
                     }
                 }
             }
             $this->extend('augmentWrite', $manipulation);
             // New records have their insert into the base data table done first, so that they can pass the
             // generated ID on to the rest of the manipulation
             if (isset($isNewRecord) && $isNewRecord && isset($manipulation[$baseTable])) {
                 $manipulation[$baseTable]['command'] = 'update';
             }
             DB::manipulate($manipulation);
             if (isset($isNewRecord) && $isNewRecord) {
                 DataObjectLog::addedObject($this);
             } else {
                 DataObjectLog::changedObject($this);
             }
             $this->changed = null;
         } elseif ($showDebug) {
             echo "<b>Debug:</b> no changes for DataObject<br />";
         }
         // Clears the cache for this object so get_one returns the correct object.
         $this->flushCache();
         if (!isset($this->record['Created'])) {
             $this->record['Created'] = date('Y-m-d H:i:s');
         }
         $this->record['LastEdited'] = date('Y-m-d H:i:s');
     }
     // Write ComponentSets as necessary
     if ($this->components) {
         foreach ($this->components as $component) {
             $component->write($firstWrite);
         }
     }
     return $this->record['ID'];
 }
コード例 #11
0
 /**
  * Add an item to this many_many relationship
  * Does so by adding an entry to the joinTable.
  *
  * @param mixed $item
  * @param array $extraFields A map of additional columns to insert into the joinTable.
  * Column names should be ANSI quoted.
  */
 public function add($item, $extraFields = array())
 {
     // Ensure nulls or empty strings are correctly treated as empty arrays
     if (empty($extraFields)) {
         $extraFields = array();
     }
     // Determine ID of new record
     if (is_numeric($item)) {
         $itemID = $item;
     } elseif ($item instanceof $this->dataClass) {
         $itemID = $item->ID;
     } else {
         throw new InvalidArgumentException("ManyManyList::add() expecting a {$this->dataClass} object, or ID value", E_USER_ERROR);
     }
     // Validate foreignID
     $foreignIDs = $this->getForeignID();
     if (empty($foreignIDs)) {
         throw new Exception("ManyManyList::add() can't be called until a foreign ID is set", E_USER_WARNING);
     }
     // Apply this item to each given foreign ID record
     if (!is_array($foreignIDs)) {
         $foreignIDs = array($foreignIDs);
     }
     foreach ($foreignIDs as $foreignID) {
         // Check for existing records for this item
         if ($foreignFilter = $this->foreignIDWriteFilter($foreignID)) {
             // With the current query, simply add the foreign and local conditions
             // The query can be a bit odd, especially if custom relation classes
             // don't join expected tables (@see Member_GroupSet for example).
             $query = new SQLSelect("*", "\"{$this->joinTable}\"");
             $query->addWhere($foreignFilter);
             $query->addWhere(array("\"{$this->joinTable}\".\"{$this->localKey}\"" => $itemID));
             $hasExisting = $query->count() > 0;
         } else {
             $hasExisting = false;
         }
         $manipulation = array();
         if ($hasExisting) {
             $manipulation[$this->joinTable]['command'] = 'update';
             $manipulation[$this->joinTable]['where'] = array("\"{$this->joinTable}\".\"{$this->foreignKey}\"" => $foreignID, "\"{$this->joinTable}\".\"{$this->localKey}\"" => $itemID);
         } else {
             $manipulation[$this->joinTable]['command'] = 'insert';
         }
         if ($extraFields) {
             foreach ($extraFields as $fieldName => $fieldValue) {
                 if (is_null($fieldValue)) {
                     $manipulation[$this->joinTable]['fields'][$fieldName] = null;
                 } elseif ($fieldValue instanceof DBField) {
                     // rely on writeToManipulation to manage the changes
                     // required for this field.
                     $working = array('fields' => array());
                     // create a new instance of the field so we can
                     // modify the field name to the correct version.
                     $field = DBField::create_field(get_class($fieldValue), $fieldValue);
                     $field->setName($fieldName);
                     $field->writeToManipulation($working);
                     foreach ($working['fields'] as $extraName => $extraValue) {
                         $manipulation[$this->joinTable]['fields'][$extraName] = $extraValue;
                     }
                 } else {
                     $manipulation[$this->joinTable]['fields'][$fieldName] = $fieldValue;
                 }
             }
         }
         $manipulation[$this->joinTable]['fields'][$this->localKey] = $itemID;
         $manipulation[$this->joinTable]['fields'][$this->foreignKey] = $foreignID;
         DB::manipulate($manipulation);
     }
 }
コード例 #12
0
 /**
  * Remove all fixtures previously defined through {@link createObject()}
  * or {@link createRaw()}, both from the internal fixture mapping and the database.
  * If the $class argument is set, limit clearing to items of this class.
  * 
  * @param String $class
  */
 public function clear($limitToClass = null)
 {
     $classes = $limitToClass ? array($limitToClass) : array_keys($this->fixtures);
     foreach ($classes as $class) {
         $ids = $this->fixtures[$class];
         foreach ($ids as $id => $dbId) {
             if (class_exists($class)) {
                 $class::get()->byId($dbId)->delete();
             } else {
                 $table = $class;
                 DB::manipulate(array($table => array("fields" => array('ID' => $dbId), "command" => "delete")));
             }
             unset($this->fixtures[$class][$id]);
         }
     }
 }
コード例 #13
0
 /**
  * Add an item to this many_many relationship.
  * Does so by adding an entry to the LinkSets on both parent objects.
  * 
  * @param $extraFields NOTE: Does not support extra fields
  */
 public function add($item, $extraFields = null)
 {
     if (is_numeric($item)) {
         $itemID = $item;
     } else {
         if ($item instanceof $this->dataClass) {
             $itemID = $item->ID;
         } else {
             throw new InvalidArgumentException("ManyManyList::add() expecting a {$this->dataClass} object, or ID value", E_USER_ERROR);
         }
     }
     // Validate foreignID, ID of the record that owns the LinkSet
     $foreignID = $this->getForeignID();
     if (!$foreignID) {
         throw new Exception("ManyManyList::add() can't be called until a foreign ID is set", E_USER_WARNING);
     }
     //@todo do we need to wrap these two dependent DB manipulations in a transaction?
     if ($itemID && $foreignID) {
         $manipulation = array();
         $tableName = $this->getParentClass();
         $componentName = $this->getComponentName();
         //Unfortunately need to use "set" command the first time
         $hasExisting = false;
         $parentItem = $tableName::get()->filter(array('ID' => $foreignID))->first();
         $hasExisting = $parentItem->{$componentName}()->exists();
         //We are updating a record's LinkSet
         $manipulation[$tableName]['command'] = 'update_container';
         $manipulation[$tableName]['id'] = $foreignID;
         //Use "set" command the first time we add entries to this list
         if ($hasExisting) {
             $manipulation[$tableName]['container_command'] = "add {$componentName}";
             $manipulation[$tableName]['container_values'] = '#' . $itemID;
         } else {
             $manipulation[$tableName]['container_command'] = "set {$componentName}";
             $manipulation[$tableName]['container_values'] = '[#' . $itemID . ']';
         }
         DB::manipulate($manipulation);
         //Get corresponding relation on the other object to update
         $belongsTableName = $this->dataClass;
         $belongsComponentName = null;
         //@todo probably cleaner way to do this
         $belongsManyMany = Config::inst()->get($this->dataClass, 'belongs_many_many', Config::UNINHERITED);
         if (is_array($belongsManyMany)) {
             foreach ($belongsManyMany as $componentName => $class) {
                 if ($class == $tableName) {
                     $belongsComponentName = $componentName;
                     break;
                 }
             }
         }
         $hasExisting = false;
         $parentItem = $belongsTableName::get()->filter(array('ID' => $itemID))->first();
         $hasExisting = $parentItem->{$belongsComponentName}()->exists();
         //We are updating a record's LinkSet
         $manipulation[$belongsTableName]['command'] = 'update_container';
         $manipulation[$belongsTableName]['id'] = $itemID;
         //Use "set" command the first time we add entries to this list
         if ($hasExisting) {
             $manipulation[$belongsTableName]['container_command'] = "add {$belongsComponentName}";
             $manipulation[$belongsTableName]['container_values'] = '#' . $foreignID;
         } else {
             $manipulation[$belongsTableName]['container_command'] = "set {$belongsComponentName}";
             $manipulation[$belongsTableName]['container_values'] = '[#' . $foreignID . ']';
         }
         DB::manipulate($manipulation);
     }
 }