Beispiel #1
0
 /**
  * Writes the values in the table to the database.
  *
  * @param tablename An optional tablename in case this record is not being placed in
  * 		the standard table.  For example, the record could be placed into an import
  * 		table.
  * @param array $keys Optional array of keys to look up record to write to.
  * @param string $tablename The name of the table to write to, if not this table.
  *							This is useful for writing to import tables or other 
  *							tables with identical schema.
  * @param boolean $secure Whether to check permissions or not.
  * @param boolean $forceNew If true, it forces an insert rather than an update.
  */
 function write(&$record, $keys = null, $tablename = null, $secure = false, $forceNew = false)
 {
     // The vetoSecurity flag allows us to make changes to a record without
     // the fields being filtered for security checks when they are saved.
     // Since we may want to change or add values to a record in the
     // beforeSave type triggers, and we probably don't want these changes
     // checked by security, we should use this flag to make all changes
     // in these triggers immune to security checks.
     // We return the veto setting to its former state after this method
     // finishes.
     //$oldVeto = $record->vetoSecurity;
     //$record->vetoSecurity = true;
     //$parentRecord =& $record->getParentRecord();
     $app =& Dataface_Application::getInstance();
     //$parentIO =& $this->getParentIO();
     if (!is_a($record, "Dataface_Record")) {
         throw new Exception(df_translate('scripts.Dataface.IO.write.ERROR_PARAMETER_1', "Dataface_IO::write() requires first parameter to be of type 'Dataface_Record' but received '" . get_class($record) . "\n<br>", array('class' => get_class($record))), E_USER_ERROR);
     }
     if ($tablename === null and $this->_altTablename !== null) {
         $tablename = $this->_altTablename;
     }
     if ($this->fireTriggers) {
         $res = $this->fireBeforeSave($record);
         if (PEAR::isError($res)) {
             //$record->vetoSecurity = $oldVeto;
             return $res;
         }
     }
     if (!$forceNew and $this->recordExists($record, $keys, $this->tablename($tablename))) {
         $res = $this->_update($record, $keys, $this->tablename($tablename), $secure);
     } else {
         $res = $this->_insert($record, $this->tablename($tablename), $secure);
     }
     if (PEAR::isError($res)) {
         if (Dataface_Error::isDuplicateEntry($res)) {
             /*
              * Duplicate entries we will propogate up so that the application can decide what to do.
              */
             //$record->vetoSecurity = $oldVeto;
             return $res;
         }
         $res->addUserInfo(df_translate('scripts.Dataface.IO.write.ERROR_SAVING', "Error while saving record of table '" . $this->_table->tablename . "' in Dataface_IO::write() ", array('tablename' => $this->_table->tablename, 'line' => 0, 'file' => '_')));
         //$record->vetoSecurity = $oldVeto;
         return $res;
     }
     $res = $this->saveTransients($record, $keys, $tablename, $secure);
     if (PEAR::isError($res)) {
         return $res;
     }
     if ($this->fireTriggers) {
         $res2 = $this->fireAfterSave($record);
         if (PEAR::isError($res2)) {
             //$record->vetoSecurity = $oldVeto;
             return $res2;
         }
     }
     if (isset($app->_conf['history']) and @$app->_conf['history']['enabled'] || !isset($app->_conf['history']['enabled'])) {
         // History is enabled ... let's save this record in our history.
         import('Dataface/HistoryTool.php');
         $historyTool = new Dataface_HistoryTool();
         $historyTool->logRecord($record, $this->getHistoryComments($record), $this->lang);
     }
     if (isset($app->_conf['_index']) and @$app->_conf['_index'][$record->table()->tablename]) {
         // If indexing is enabled, we index the record so that it is
         // searchable by natural language searching.
         // The Dataface_Index class takes care of whether or not this
         // record should be indexed.
         import('Dataface/Index.php');
         $index = new Dataface_Index();
         $index->indexRecord($record);
     }
     // It seems to me that we should be setting a new snapshot at this point.
     //$record->clearSnapshot();
     $record->setSnapshot();
     self::touchTable($this->_table->tablename);
     self::touchRecord($record);
     //$record->vetoSecurity = $oldVeto;
     return $res;
 }
Beispiel #2
0
 /**
  * Writes the values in the table to the database.
  *
  * @param tablename An optional tablename in case this record is not being placed in
  * 		the standard table.  For example, the record could be placed into an import
  * 		table.
  * @param array $keys Optional array of keys to look up record to write to.
  * @param string $tablename The name of the table to write to, if not this table.
  *							This is useful for writing to import tables or other 
  *							tables with identical schema.
  * @param boolean $secure Whether to check permissions or not.
  */
 function write(&$record, $keys = null, $tablename = null, $secure = false)
 {
     // The vetoSecurity flag allows us to make changes to a record without
     // the fields being filtered for security checks when they are saved.
     // Since we may want to change or add values to a record in the
     // beforeSave type triggers, and we probably don't want these changes
     // checked by security, we should use this flag to make all changes
     // in these triggers immune to security checks.
     // We return the veto setting to its former state after this method
     // finishes.
     //$oldVeto = $record->vetoSecurity;
     //$record->vetoSecurity = true;
     //$parentRecord =& $record->getParentRecord();
     $app =& Dataface_Application::getInstance();
     //$parentIO =& $this->getParentIO();
     if (!is_a($record, "Dataface_Record")) {
         trigger_error(df_translate('scripts.Dataface.IO.write.ERROR_PARAMETER_1', "Dataface_IO::write() requires first parameter to be 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;
     }
     if ($this->fireTriggers) {
         $res = $this->fireBeforeSave($record);
         if (PEAR::isError($res)) {
             //$record->vetoSecurity = $oldVeto;
             return $res;
         }
     }
     if ($this->recordExists($record, $keys, $this->tablename($tablename))) {
         $res = $this->_update($record, $keys, $this->tablename($tablename), $secure);
     } else {
         $res = $this->_insert($record, $this->tablename($tablename), $secure);
     }
     if (PEAR::isError($res)) {
         if (Dataface_Error::isDuplicateEntry($res)) {
             /*
              * Duplicate entries we will propogate up so that the application can decide what to do.
              */
             //$record->vetoSecurity = $oldVeto;
             return $res;
         }
         $res->addUserInfo(df_translate('scripts.Dataface.IO.write.ERROR_SAVING', "Error while saving record of table '" . $this->_table->tablename . "' in Dataface_IO::write() on line " . __LINE__ . " of file " . __FILE__, array('tablename' => $this->_table->tablename, 'line' => __LINE__, 'file' => __FILE__)));
         //$record->vetoSecurity = $oldVeto;
         return $res;
     }
     // Now we take care of the transient relationship fields.
     // Transient relationship fields aren't actually stored in the record
     // itself, they are stored as related records.
     foreach ($record->_table->transientFields() as $tfield) {
         if (!isset($tfield['relationship'])) {
             continue;
         }
         if (!$record->valueChanged($tfield['name'])) {
             continue;
         }
         $trelationship =& $record->_table->getRelationship($tfield['relationship']);
         if (!$trelationship or PEAR::isError($trelationship)) {
             // We couldn't find the specified relationship.
             //$record->vetoSecurity = $oldVeto;
             return $trelationship;
         }
         $orderCol = $trelationship->getOrderColumn();
         if (PEAR::isError($orderCol)) {
             $orderCol = null;
         }
         $tval = $record->getValue($tfield['name']);
         if ($tfield['widget']['type'] == 'grid') {
             //echo "here";exit;
             $tval_existing = array();
             $tval_new = array();
             $tval_new_existing = array();
             $torder = 0;
             foreach ($tval as $trow) {
                 $trow['__order__'] = $torder++;
                 if (isset($trow['__id__']) and preg_match('/^new:/', $trow['__id__'])) {
                     $tval_new_existing[] = $trow;
                 } else {
                     if (isset($trow['__id__']) and $trow['__id__'] != 'new') {
                         $tval_existing[$trow['__id__']] = $trow;
                     } else {
                         if (isset($trow['__id__']) and $trow['__id__'] == 'new') {
                             $tval_new[] = $trow;
                         }
                     }
                 }
             }
             // The transient field was loaded so we can go about saving the
             // changes/
             $trecords =& $record->getRelatedRecordObjects($tfield['relationship'], 'all');
             if (!is_array($trecords) or PEAR::isError($trecords)) {
                 error_log('Failed to get related records for record ' . $record->getId() . ' in its relationship ' . $tfield['relationship']);
                 unset($tval);
                 unset($orderCol);
                 unset($tval_new);
                 unset($torder);
                 unset($trelationship);
                 unset($tval_existing);
                 continue;
             }
             // Update the existing records in the relationship.
             // We use the __id__ parameter in each row for this.
             //echo "About to save related records";
             foreach ($trecords as $trec) {
                 $tid = $trec->getId();
                 if (isset($tval_existing[$tid])) {
                     $tmp = new Dataface_RelatedRecord($trec->_record, $tfield['relationship'], $trec->getValues());
                     $tmp->setValues($tval_existing[$tid]);
                     $changed = false;
                     foreach ($tval_existing[$tid] as $k1 => $v1) {
                         if ($tmp->isDirty($k1)) {
                             $changed = true;
                             break;
                         }
                     }
                     if ($changed) {
                         $trec->setValues($tval_existing[$tid]);
                         if ($orderCol) {
                             $trec->setValue($orderCol, $tval_existing[$tid]['__order__']);
                         }
                         //echo "Saving ";print_r($trec->vals());
                         $res_t = $trec->save($this->lang, $secure);
                         if (PEAR::isError($res_t)) {
                             return $res_t;
                             error_log('Failed to save related record ' . $trec->getId() . ' while saving transient field ' . $tfield['name'] . ' in record ' . $record->getId() . '. The error returned was : ' . $res_t->getMessage());
                         }
                     } else {
                         if ($orderCol and $record->checkPermission('reorder_related_records', array('relationship' => $tfield['relationship']))) {
                             $trec->setValue($orderCol, $tval_existing[$tid]['__order__']);
                             $res_t = $trec->save($this->lang, false);
                             // we don't need this to be secure
                             if (PEAR::isError($res_t)) {
                                 return $res_t;
                                 error_log('Failed to save related record ' . $trec->getId() . ' while saving transient field ' . $tfield['name'] . ' in record ' . $record->getId() . '. The error returned was : ' . $res_t->getMessage());
                             }
                         }
                     }
                     unset($tmp);
                 } else {
                 }
                 unset($trec);
                 unset($tid);
                 unset($res_t);
             }
             //exit;
             // Now add new records  (specified by __id__ field being 'new'
             foreach ($tval_new as $tval_to_add) {
                 $temp_rrecord = new Dataface_RelatedRecord($record, $tfield['relationship'], array());
                 $temp_rrecord->setValues($tval_to_add);
                 if ($orderCol) {
                     $temp_rrecord->setValue($orderCol, $tval_to_add['__order__']);
                 }
                 $res_t = $this->addRelatedRecord($temp_rrecord, $secure);
                 if (PEAR::isError($res_t)) {
                     error_log('Failed to save related record ' . $temp_rrecord->getId() . ' while saving transient field ' . $tfield['name'] . ' in record ' . $record->getId() . '. The error returned was : ' . $res_t->getMessage());
                 }
                 unset($temp_rrecord);
                 unset($res_t);
             }
             // Now add new existing records  (specified by __id__ field being 'new:<recordid>'
             foreach ($tval_new_existing as $tval_to_add) {
                 $tid = preg_replace('/^new:/', '', $tval_to_add['__id__']);
                 $temp_record = df_get_record_by_id($tid);
                 if (PEAR::isError($temp_record)) {
                     return $temp_record;
                 }
                 if (!$temp_record) {
                     return PEAR::raiseError("Failed to load existing record with ID {$tid}.");
                 }
                 $temp_rrecord = new Dataface_RelatedRecord($record, $tfield['relationship'], $temp_record->vals());
                 $temp_rrecord->setValues($tval_to_add);
                 if ($orderCol) {
                     $temp_rrecord->setValue($orderCol, $tval_to_add['__order__']);
                 }
                 $res_t = $this->addExistingRelatedRecord($temp_rrecord, $secure);
                 if (PEAR::isError($res_t)) {
                     error_log('Failed to save related record ' . $temp_rrecord->getId() . ' while saving transient field ' . $tfield['name'] . ' in record ' . $record->getId() . '. The error returned was : ' . $res_t->getMessage());
                 }
                 unset($temp_rrecord);
                 unset($res_t);
             }
             // Now we delete the records that were deleted
             // we use the __deleted__ field.
             if (isset($tval['__deleted__']) and is_array($tval['__deleted__']) and $trelationship->supportsRemove()) {
                 $tdelete_record = $trelationship->isOneToMany();
                 foreach ($tval['__deleted__'] as $del_id) {
                     if ($del_id == 'new') {
                         continue;
                     }
                     $drec = Dataface_IO::getByID($del_id);
                     if (PEAR::isError($drec) or !$drec) {
                         unset($drec);
                         continue;
                     }
                     $this->removeRelatedRecord($drec, $tdelete_record, $secure);
                     unset($drec);
                 }
             }
             unset($trecords);
         } else {
             if ($tfield['widget']['type'] == 'checkbox') {
                 // Load existing records in the relationship
                 $texisting =& $record->getRelatedRecordObjects($tfield['relationship'], 'all');
                 if (!is_array($texisting) or PEAR::isError($texisting)) {
                     error_log('Failed to get related records for record ' . $record->getId() . ' in its relationship ' . $tfield['relationship']);
                     unset($tval);
                     unset($orderCol);
                     unset($tval_new);
                     unset($torder);
                     unset($trelationship);
                     unset($tval_existing);
                     continue;
                 }
                 $texistingIds = array();
                 foreach ($texisting as $terec) {
                     $texistingIds[] = $terec->getId();
                 }
                 // Load currently checked records
                 $tchecked = array();
                 $tcheckedRecords = array();
                 $tcheckedIds = array();
                 $tcheckedId2ValsMap = array();
                 foreach ($tval as $trkey => $trval) {
                     // $trval is in the form key1=val1&size=key2=val2
                     parse_str($trval, $trquery);
                     $trRecord = new Dataface_RelatedRecord($record, $tfield['relationship'], $trquery);
                     $trRecords[] =& $trRecord;
                     $tcheckedIds[] = $tid = $trRecord->getId();
                     $checkedId2ValsMap[$tid] = $trquery;
                     unset($trRecord);
                     unset($trquery);
                 }
                 // Now we have existing ids in $texistingIds
                 // and checked ids in $tcheckedIds
                 // See which records we need to have removed
                 $tremoves = array_diff($texistingIds, $tcheckedIds);
                 $tadds = array_diff($tcheckedIds, $texistingIds);
                 foreach ($tremoves as $tid) {
                     $trec = df_get_record_by_id($tid);
                     $res = $this->removeRelatedRecord($trec, false, $secure);
                     if (PEAR::isError($res)) {
                         return $res;
                     }
                     unset($trec);
                 }
                 foreach ($tadds as $tid) {
                     $trecvals = $checkedId2ValsMap[$tid];
                     $trec = new Dataface_RelatedRecord($record, $tfield['relationship'], $trecvals);
                     $res = $this->addExistingRelatedRecord($trec, $secure);
                     if (PEAR::isError($res)) {
                         return $res;
                     }
                     unset($trec, $trecvals);
                 }
                 unset($tadds);
                 unset($tremoves);
                 unset($tcheckedIds, $tcheckedId2ValsMap);
                 unset($tcheckedRecords);
                 unset($tchecked);
                 unset($texistingIds);
                 unset($texisting);
             }
         }
         unset($tval);
         unset($trelationship);
     }
     if ($this->fireTriggers) {
         $res2 = $this->fireAfterSave($record);
         if (PEAR::isError($res2)) {
             //$record->vetoSecurity = $oldVeto;
             return $res2;
         }
     }
     if (isset($app->_conf['history']) and @$app->_conf['history']['enabled'] || !isset($app->_conf['history']['enabled'])) {
         // History is enabled ... let's save this record in our history.
         import('Dataface/HistoryTool.php');
         $historyTool = new Dataface_HistoryTool();
         $historyTool->logRecord($record, $this->getHistoryComments($record), $this->lang);
     }
     if (isset($app->_conf['_index']) and @$app->_conf['_index'][$record->table()->tablename]) {
         // If indexing is enabled, we index the record so that it is
         // searchable by natural language searching.
         // The Dataface_Index class takes care of whether or not this
         // record should be indexed.
         import('Dataface/Index.php');
         $index = new Dataface_Index();
         $index->indexRecord($record);
     }
     // It seems to me that we should be setting a new snapshot at this point.
     //$record->clearSnapshot();
     $record->setSnapshot();
     self::touchTable($this->_table->tablename);
     //$record->vetoSecurity = $oldVeto;
     return $res;
 }
Beispiel #3
0
 function test_restore_to_date()
 {
     $app =& Dataface_Application::getInstance();
     $record = df_get_record('HistoryToolTest', array('name' => 'Johnny'));
     $this->assertEquals('john.gif', $record->val('container_field'));
     $record->setValue('container_field', 'john2.gif');
     $record->save();
     $ht = new Dataface_HistoryTool();
     $hid = $ht->logRecord($record);
     $history1 = $ht->getRecordById('HistoryToolTest', $hid);
     $this->assertEquals(array('name' => 'Johnny', 'container_field' => 'john2.gif'), $history1->strvals(array('name', 'container_field')));
     $record->setValue('container_field', 'john3.gif');
     $record->save();
     $hid2 = $ht->logRecord($record);
     $history2 = $ht->getRecordById('HistoryToolTest', $hid2);
     $this->assertEquals(array('name' => 'Johnny', 'container_field' => 'john3.gif'), $history2->strvals(array('name', 'container_field')));
     $record2 = df_get_record('HistoryToolTest', array('name' => 'Johnny'));
     $this->assertEquals($record2->strvals(array('name', 'container_field')), $history2->strvals(array('name', 'container_field')));
     $sql = array();
     $sql[] = "update `HistoryToolTest__history` set `history__modified` = '2004-01-02' where `history__id` = '{$hid}'";
     foreach ($sql as $q) {
         $res = xf_db_query($q, $app->db());
         if (!$res) {
             trigger_error(xf_db_error($app->db()), E_USER_ERROR);
         }
     }
     $ht->restoreToDate($record, '2004-02-02');
     $record3 = df_get_record('HistoryToolTest', array('name' => 'Johnny'));
     $this->assertEquals(array('name' => 'Johnny', 'container_field' => 'john2.gif'), $record3->strvals(array('name', 'container_field')));
 }