/** * @param tablename An optional tablename to update. This is useful if we are working from an update or delete table. */ function _update(&$record, $keys = null, $tablename = null, $secure = false) { if ($secure && !$record->checkPermission('edit')) { // Use security to check to see if we are allowed to delete this // record. return Dataface_Error::permissionDenied(df_translate('scripts.Dataface.IO._update.PERMISSION_DENIED', 'Could not update record "' . $record->getTitle() . '" from table "' . $record->_table->tablename . '" because you have insufficient permissions.', array('title' => $record->getTitle(), 'table' => $record->_table->tablename))); } if ($secure) { foreach (array_keys($record->_table->fields()) as $fieldname) { if ($record->valueChanged($fieldname) and !@$record->vetoFields[$fieldname] and !$record->checkPermission('edit', array('field' => $fieldname))) { // If this field's change doesn't have veto power and its value has changed, // we must make sure that the user has edit permission on this field. return Dataface_Error::permissionDenied(df_translate('scripts.Dataface.IO._update.PERMISSION_DENIED_FIELD', 'Could not update record "' . $record->getTitle() . '" in table "' . $record->_table->tablename . '" because you do not have permission to modify the "' . $fieldname . '" column.', array('title' => $record->getTitle(), 'table' => $record->_table->tablename, 'field' => $fieldname))); } } } // Step 1: Validate that the record already exists if (!is_a($record, 'Dataface_Record')) { trigger_error(df_translate('scripts.Dataface.IO._update.ERROR_PARAMETER_1', "In Dataface_IO::_update() the first argument is expected to be an object of type 'Dataface_Record' but received '" . get_class($record) . "'.\n<br>", array('class' => get_class($record))) . Dataface_Error::printStackTrace(), E_USER_ERROR); } if ($tablename === null and $this->_altTablename !== null) { $tablename = $this->_altTablename; } $exists = $this->recordExists($record, $keys, $this->tablename($tablename)); if (PEAR::isError($exists)) { $exists->addUserInfo(df_translate('scripts.Dataface.IO._update.ERROR_INCOMPLETE_INFORMATION', "Attempt to update record with incomplete information. On line " . __LINE__ . " of file " . __FILE__, array('line' => __LINE__, 'file' => __FILE__))); return $exists; } if (!$exists) { return PEAR::raiseError(df_translate('scripts.Dataface.IO._update.ERROR_RECORD_DOESNT_EXIST', "Attempt to update record that doesn't exist in _update() on line " . __LINE__ . " of file " . __FILE__, array('line' => __LINE__, 'file' => __FILE__)), DATAFACE_E_NO_RESULTS); } // Step 2: Load objects that we will need $s =& $this->_table; $delegate =& $s->getDelegate(); $qb = new Dataface_QueryBuilder($this->_table->tablename, $keys); if ($record->recordChanged(true)) { if ($this->fireTriggers) { $res = $this->fireBeforeUpdate($record); if (PEAR::isError($res)) { return $res; } } } $parentIO =& $this->getParentIO(); if (isset($parentIO)) { $parentRecord =& $record->getParentRecord(); $res = $parentIO->write($parentRecord, $parentRecord->snapshotKeys()); if (PEAR::isError($res)) { return $res; } } // we only want to update changed values $sql = $qb->update($record, $keys, $this->tablename($tablename)); if (PEAR::isError($sql)) { $sql->addUserInfo(df_translate('scripts.Dataface.IO._update.ERROR_GENERATING_SQL', "Error generating sql for update in IO::_update() on line " . __LINE__ . " of file " . __FILE__, array('line' => __LINE__, 'file' => __FILE__))); return $sql; } if (strlen($sql) > 0) { //$res = mysql_query($sql, $s->db); $res = $this->dbObj->query($sql, $s->db, $this->lang); if (!$res || PEAR::isError($res)) { if (in_array(mysql_errno($this->_table->db), array(MYSQL_ER_DUP_KEY, MYSQL_ER_DUP_ENTRY))) { /* * This is a duplicate entry. We will handle this as an exception rather than an error because * cases may arise in a database application when a duplicate entry will happen and the application * will want to handle it in a graceful way. Eg: If the user is entering a username that is the same * as an existing name. We don't want an ugle FATAL error to be thrown here. Rather we want to * notify the application that it is a duplicate entry. */ return Dataface_Error::duplicateEntry(df_translate('scripts.Dataface.IO._update.ERROR_DUPLICATE_ENTRY', "Duplicate entry into table '" . $s->tablename, array('tablename' => $s->tablename))); } trigger_error(df_translate('scripts.Dataface.IO._update.SQL_ERROR', "Failed to update due to sql error: ") . mysql_error($s->db) . Dataface_Error::printStackTrace(), E_USER_ERROR); } if ($this->fireTriggers) { $res2 = $this->fireAfterUpdate($record); if (PEAR::isError($res2)) { return $res2; } } } //$record->clearFlags(); return true; }
function test_query_builder_update_snapshot() { $builder = new Dataface_QueryBuilder('Profiles'); // test default update functionality. $s = new Dataface_Record('Profiles', array()); $s->clearValues(); $s->setValues(array('id' => 10, 'fname' => 'John', 'lname' => 'Smith', 'title' => 'President Financial Accounting', 'phone1' => '555-555-5555', 'description' => 'This is a description', 'favtime' => '14:23:56', 'dob' => '1978-12-27', 'datecreated' => '19991224060708', 'lastlogin' => '1978-12-27 14:45:23')); $s->setSnapshot(); $s->setValues(array('id' => 50, 'fname' => 'Susan', 'lname' => 'Moore', 'phone1' => '555-555-5556', 'description' => 'This is another description', 'favtime' => '14:23:57', 'dob' => '1978-12-28', 'datecreated' => '19991224060709', 'lastlogin' => '1978-12-28 14:45:24')); $this->assertEquals($builder->update($s), "UPDATE `Profiles` SET `id` = '50', `fname` = 'Susan', `lname` = 'Moore', `description` = 'This is another description', `dob` = '1978-12-28', `phone1` = '555-555-5556', `datecreated` = '19991224060709', `favtime` = '14:23:57', `lastlogin` = '1978-12-28 14:45:24' WHERE `Profiles`.`id` = '10' LIMIT 1"); }