Exemplo n.º 1
0
 /**
  * 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'];
 }
Exemplo n.º 2
0
 /**
  * Augment a write-record request.
  * @param SQLQuery $manipulation Query to augment.
  */
 function augmentWrite(&$manipulation)
 {
     if (!$this->stat('enabled')) {
         return false;
     }
     if (($lang = self::current_lang()) && !self::is_default_lang()) {
         $tables = array_keys($manipulation);
         foreach ($tables as $table) {
             if (self::table_exists("{$table}_lang")) {
                 $manipulation["{$table}_lang"] = $manipulation[$table];
                 if ($manipulation[$table]['command'] == 'insert') {
                     $fakeID = $this->owner->ID;
                     // In an insert we've to populate our fields and generate a new id (since the passed one it's relative to $table)
                     $SessionOrigID = Session::get($this->owner->ID . '_originalLangID');
                     $manipulation["{$table}_lang"]['fields']['OriginalLangID'] = $this->owner->ID = $SessionOrigID ? $SessionOrigID : self::$creatingFromID;
                     $manipulation["{$table}_lang"]['RecordID'] = $manipulation["{$table}_lang"]['fields']['OriginalLangID'];
                     // populate lang field
                     $manipulation["{$table}_lang"]['fields']['Lang'] = "'{$lang}'";
                     // get a valid id, pre-inserting
                     DB::query("INSERT INTO {$table}_lang SET Created = NOW(), Lang = '{$lang}'");
                     $manipulation["{$table}_lang"]['id'] = $manipulation["{$table}_lang"]['fields']['ID'] = DB::getGeneratedID("{$table}_lang");
                     $manipulation["{$table}_lang"]['command'] = 'update';
                     // we don't have to insert anything in $table if we are inserting in $table_lang
                     unset($manipulation[$table]);
                     // now dataobjects may create a record before the real write in the base table, so we have to delete it - 20/08/2007
                     if (is_numeric($fakeID)) {
                         DB::query("DELETE FROM {$table} WHERE ID={$fakeID}");
                     }
                 } else {
                     if (!isset($manipulation[$table]['fields']['OriginalLangID'])) {
                         // for those updates that may become inserts populate these fields
                         $manipulation["{$table}_lang"]['fields']['OriginalLangID'] = $this->owner->ID;
                         $manipulation["{$table}_lang"]['fields']['Lang'] = "'{$lang}'";
                     }
                     $id = $manipulation["{$table}_lang"]['id'];
                     if (!$id) {
                         user_error("Couldn't find ID in manipulation", E_USER_ERROR);
                     }
                     if (isset($manipulation["{$table}_lang"]['where'])) {
                         $manipulation["{$table}_lang"]['where'] .= "AND (Lang = '{$lang}') AND (OriginalLangID = {$id})";
                     } else {
                         $manipulation["{$table}_lang"]['where'] = "(Lang = '{$lang}') AND (OriginalLangID = {$id})";
                     }
                     $realID = DB::query("SELECT ID FROM {$table}_lang WHERE (OriginalLangID = {$id}) AND (Lang = '{$lang}') LIMIT 1")->value();
                     $manipulation["{$table}_lang"]['id'] = $realID;
                     $manipulation["{$table}_lang"]['RecordID'] = $manipulation["{$table}_lang"]['fields']['OriginalLangID'];
                     // we could be updating non-translatable fields at the same time, so these will remain
                     foreach ($manipulation[$table]['fields'] as $field => $dummy) {
                         if ($this->isInAugmentedTable($field, $table)) {
                             unset($manipulation[$table]['fields'][$field]);
                         }
                     }
                     if (count($manipulation[$table]['fields']) == 0) {
                         unset($manipulation[$table]);
                     }
                 }
                 foreach ($manipulation["{$table}_lang"]['fields'] as $field => $dummy) {
                     if (!$this->isInAugmentedTable($field, $table)) {
                         unset($manipulation["{$table}_lang"]['fields'][$field]);
                     }
                 }
             }
         }
     }
 }
Exemplo n.º 3
0
	/**
	 * Construct a child of this Folder with the given name.
	 * It does this without actually using the object model, as this starts messing
	 * with all the data.  Rather, it does a direct database insert.
	 */
	function constructChild($name) {
		// Determine the class name - File, Folder or Image
		$baseDir = $this->FullPath;
		if(is_dir($baseDir . $name)) {
			$className = "Folder";
		} else {
			$className = File::get_class_for_file_extension(pathinfo($name, PATHINFO_EXTENSION));
		}

		if(Member::currentUser()) $ownerID = Member::currentUser()->ID;
		else $ownerID = 0;
		
		$filename = Convert::raw2sql($this->Filename . $name);
		if($className == 'Folder' ) $filename .= '/';

		$name = Convert::raw2sql($name);
		
		DB::query("INSERT INTO \"File\" 
			(\"ClassName\", \"ParentID\", \"OwnerID\", \"Name\", \"Filename\", \"Created\", \"LastEdited\", \"Title\")
			VALUES ('$className', $this->ID, $ownerID, '$name', '$filename', " . DB::getConn()->now() . ',' . DB::getConn()->now() . ", '$name')");
			
		return DB::getGeneratedID("File");
	}
 /**
  * Construct a child, as Folder does, except that the child is not directly
  * owned by the dynamic template, but the folder object $subFolder under it.
  * @param String $name
  * @param String $subFolder
  * @return int	ID of file created.
  */
 function constructChildInFolder($name, $subFolder)
 {
     // Determine the class name - File, Folder or Image
     $baseDir = $subFolder->FullPath;
     if (is_dir($baseDir . $name)) {
         $className = "Folder";
     } else {
         // Could use getimagesize to get the type of the image
         $ext = strtolower(substr($name, strrpos($name, '.') + 1));
         switch ($ext) {
             case "gif":
             case "jpg":
             case "jpeg":
             case "png":
                 $className = "Image";
                 break;
             default:
                 $className = "File";
         }
     }
     if (Member::currentUser()) {
         $ownerID = Member::currentUser()->ID;
     } else {
         $ownerID = 0;
     }
     $filename = DB::getConn()->addslashes($subFolder->Filename . $name);
     if ($className == 'Folder') {
         $filename .= '/';
     }
     $name = DB::getConn()->addslashes($name);
     DB::query("INSERT INTO \"File\" \n\t\t\t(\"ClassName\", \"ParentID\", \"OwnerID\", \"Name\", \"Filename\", \"Created\", \"LastEdited\", \"Title\")\n\t\t\tVALUES ('{$className}', {$subFolder->ID}, {$ownerID}, '{$name}', '{$filename}', " . DB::getConn()->now() . ',' . DB::getConn()->now() . ", '{$name}')");
     return DB::getGeneratedID("File");
 }
 /**
  * 
  * @param string $name
  * @return number
  */
 public function constructChildSecuredWithSecuredFlag($name)
 {
     // Determine the class name - File, Folder or Image
     $baseDir = $this->owner->FullPath;
     if (is_dir($baseDir . $name)) {
         $className = "Folder";
     } else {
         $className = File::get_class_for_file_extension(pathinfo($name, PATHINFO_EXTENSION));
     }
     $ownerID = 0;
     if (Member::currentUser()) {
         $ownerID = Member::currentUser()->ID;
     }
     $filename = Convert::raw2sql($this->owner->Filename . $name);
     if ($className == 'Folder') {
         $filename .= '/';
     }
     $name = Convert::raw2sql($name);
     $secured = $this->owner->Secured ? '1' : '0';
     DB::query("INSERT INTO \"File\"\n\t\t\t(\"ClassName\",\"ParentID\",\"OwnerID\",\"Name\",\"Filename\",\"Created\",\"LastEdited\",\"Title\",\"Secured\")\n\t\t\tVALUES ('{$className}', " . $this->owner->ID . ", {$ownerID}, '{$name}', '{$filename}', " . DB::getConn()->now() . ',' . DB::getConn()->now() . ", '{$name}', '{$secured}')");
     return DB::getGeneratedID("File");
 }
 /**
  * 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);
     }
 }
Exemplo n.º 7
0
	/**
	 * Construct a child of this Folder with the given name.
	 * It does this without actually using the object model, as this starts messing
	 * with all the data.  Rather, it does a direct database insert.
	 */
	function constructChild($name) {
		// Determine the class name - File, Folder or Image
		$baseDir = $this->FullPath;
		if(is_dir($baseDir . $name)) {
			$className = "Folder";
		} else {
			// Could use getimagesize to get the type of the image
			$ext = strtolower(substr($name,strrpos($name,'.')+1));
			switch($ext) {
				case "gif": case "jpg": case "jpeg": case "png": $className = "Image"; break;
				default: $className = "File";
			}
		}

		if(Member::currentUser()) $ownerID = Member::currentUser()->ID;
		else $ownerID = 0;
		
		$filename = addslashes($this->Filename . $name);
		if($className == 'Folder' ) $filename .= '/';

		$name = addslashes($name);
		
		DB::query("INSERT INTO `File` SET
			ClassName = '$className', ParentID = $this->ID, OwnerID = $ownerID,
			Name = '$name', Filename = '$filename', Created = NOW(), LastEdited = NOW(),
			Title = '$name'");
			
		return DB::getGeneratedID("File");
	}
 public function importPass()
 {
     $query = $this->getRemoteObjectsQuery();
     $items = $this->task->query($query);
     $itemsCount = $items->numRecords();
     $this->task->message(" * Found {$itemsCount} items to import");
     $total = 0;
     $updated = 0;
     $inserted = 0;
     foreach ($items as $item) {
         $this->task->progress(++$total, $itemsCount);
         // Build select query for existing object
         $values = array();
         $select = new SQLQuery("ID", "\"{$this->tableName}\"");
         foreach ($this->fields as $field => $class) {
             $value = intval($item[$field]);
             $values[] = $value;
             $select->addWhere(sprintf("\"{$field}\" = %d", $value));
         }
         $values[] = $item['ID'];
         // Check for existing record
         if ($localID = DB::query($select->sql())->value()) {
             // Update local many_many record instead of making new row
             DB::query(sprintf('UPDATE "%s" SET "LegacyID" = %d WHERE "ID" = %d', $this->tableName, $item['ID'], $localID));
             $updated++;
         } else {
             // Insert mapping into the many_many table
             $insert = "INSERT INTO \"{$this->tableName}\" (";
             $insert .= '"' . implode('", "', array_keys($this->fields)) . '"';
             $insert .= ', LegacyID';
             $insert .= ') VALUES (';
             $insert .= implode(', ', $values);
             $insert .= ')';
             DB::query($insert);
             $localID = DB::getGeneratedID($this->tableName);
             $inserted++;
         }
         // Mark this relation as imported in the remote table
         $conn = $this->task->getRemoteConnection();
         $conn->query(sprintf('UPDATE "%s" SET "_ImportedID" = %d, "_ImportedDate" = NOW() WHERE "ID" = %d', $this->tableName, $localID, $item['ID']));
     }
     // Done!
     $this->task->message(" * Result: {$inserted} added, {$updated} updated");
 }
Exemplo n.º 9
0
 /**
  * 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'];
 }
 /**
  * Writes the fixture into the database directly using a database manipulation.
  * Does not use blueprints. Only supports tables with a primary key.
  *
  * @param String $table Existing database table name
  * @param String $identifier Unique identifier for this fixture type
  * @param Array $data Map of properties
  * @return Int Database identifier
  */
 public function createRaw($table, $identifier, $data)
 {
     $manipulation = array($table => array("fields" => array(), "command" => "insert"));
     foreach ($data as $fieldName => $fieldVal) {
         $manipulation[$table]["fields"][$fieldName] = "'" . $this->parseValue($fieldVal) . "'";
     }
     DB::manipulate($manipulation);
     $id = DB::getGeneratedID($table);
     $this->fixtures[$table][$identifier] = $id;
     return $id;
 }