Пример #1
0
 function handle(&$params)
 {
     $app =& Dataface_Application::getInstance();
     $record =& $app->getRecord();
     $context = array();
     if (!$record) {
         return PEAR::raiseError("No record is currently selected", DATAFACE_E_ERROR);
     }
     $history_tablename = $record->_table->tablename . '__history';
     if (!Dataface_Table::tableExists($history_tablename)) {
         $context['error'] = PEAR::raiseError("This record has no history yet recorded.", DATAFACE_E_NOTICE);
     } else {
         import('Dataface/HistoryTool.php');
         $history_tool = new Dataface_HistoryTool();
         $history_log = $history_tool->getHistoryLog($record);
         $context['log'] =& $history_log;
         // let's make a query string for the current record
         //current_record_qstr
         $keys = array_keys($record->_table->keys());
         $qstr = array();
         foreach ($keys as $key) {
             $qstr[] = urlencode('--__keys__[' . $key . ']') . '=' . urlencode($record->strval($key));
         }
         $context['current_record_qstr'] = implode('&', $qstr);
     }
     df_display($context, 'Dataface_RecordHistory.html');
 }
Пример #2
0
 function handle(&$params)
 {
     if (!@$_POST['history__id']) {
         return PEAR::raiseError("No history id specified", DATAFACE_E_ERROR);
     }
     $historyid = $_POST['history__id'];
     if (!preg_match('/\\d+/', $historyid)) {
         return PEAR::raiseError("Invalid history id provided.", DATAFACE_E_ERROR);
     }
     $app =& Dataface_Application::getInstance();
     $record =& $app->getRecord();
     if (!$record) {
         return PEAR::raiseError("No record was specified", DATAFACE_E_ERROR);
     }
     import("Dataface/HistoryTool.php");
     $ht = new Dataface_HistoryTool();
     $hrecord = $ht->getRecordById($record->_table->tablename, $historyid);
     // make sure that this history record matches the current record.
     $keys = array_keys($record->_table->keys());
     if ($record->strvals($keys) != $hrecord->strvals($keys)) {
         return PEAR::raiseError("Attempt to restore record history from unmatching history record.", DATAFACE_E_ERROR);
     }
     // Now that we are convinced that we have the correct record, we can restore it.
     if (@$_POST['-fieldname']) {
         $fieldname = $_POST['-fieldname'];
     } else {
         $fieldname = null;
     }
     $res = $ht->restore($record, $historyid, $fieldname, true);
     if (PEAR::isError($res)) {
         return $res;
     }
     $url = false;
     //$app->getPreviousUrl(true);
     if (@$_POST['-locationid']) {
         $url = DATAFACE_SITE_HREF . '?' . $app->decodeLocation($_POST['-locationid']);
     }
     if (!$url) {
         // If the url is not specified we will just create a url to return
         // to the specified record's history listing.
         $url = $record->getURL('-action=history');
     }
     if ($fieldname) {
         $msg = "Field '{$fieldname}' successfully restored to its value from '" . $hrecord->strval('history__modified') . "'.";
     } else {
         $msg = "Record successfully restored to its value from '" . $hrecord->strval('history__modified') . "'.";
     }
     $url .= "&--msg=" . urlencode($msg);
     header('Location: ' . $url);
     exit;
 }
Пример #3
0
 function handle(&$params)
 {
     $app =& Dataface_Application::getInstance();
     if (!@$_GET['history__id']) {
         return PEAR::raiseError('No history id supplied', DATAFACE_E_ERROR);
     }
     $historyid = $_GET['history__id'];
     $query =& $app->getQuery();
     $table = $query['-table'];
     import('Dataface/HistoryTool.php');
     $ht = new Dataface_HistoryTool();
     if (@$_GET['-show_changes']) {
         $record = $ht->getDiffs($table, $historyid);
     } else {
         $record = $ht->getRecordById($table, $historyid);
     }
     if (!$record) {
         return PEAR::raiseError("No history record for table {$table} with history id {$historyid} could be found", DATAFACE_E_ERROR);
     }
     if (PEAR::isError($record)) {
         return $record;
     }
     $context = array('history_record' => &$record);
     $context['table_record'] = new Dataface_Record($table, $record->vals());
     $t =& Dataface_Table::loadTable($table);
     $numfields = count($t->fields());
     $pts = 0;
     $ppf = array();
     foreach ($t->fields() as $field) {
         if ($t->isText($field['name'])) {
             $pts += 5;
             $ppf[$field['name']] = $pts;
         } else {
             $pts++;
             $ppf[$field['name']] = $pts;
         }
     }
     $firstField = null;
     $threshold = floatval(floatval($pts) / floatval(2));
     foreach ($t->fields() as $field) {
         if ($ppf[$field['name']] >= $threshold) {
             $firstField = $field['name'];
             break;
         }
     }
     $context['first_field_second_col'] = $firstField;
     $context['changes'] = @$_GET['-show_changes'];
     $context['table'] =& $t;
     df_display($context, 'Dataface_HistoryRecordDetails.html');
 }
Пример #4
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;
 }
Пример #5
0
 /**
  * Returns the changes for a given record in a particular language, since
  * a given version number.
  * @param Dataface_Record &$record The record we are interested in.
  * @param string $language 2-digit language code
  * @param float $version <major_version>.<minor_version>
  * @param string $fieldname Optional field name to get changes for.
  * @returns mixed Either a Dataface_Record object with the changes, or 
  *				a string with the changes for $fieldname.
  *
  */
 function getChanges(&$record, $version, $lang = null, $fieldname = null)
 {
     $app = Dataface_Application::getInstance();
     if (!isset($lang)) {
         $lang = $app->_conf['lang'];
     }
     list($major_version, $minor_version) = explode('.', $version);
     $trecord = $this->getTranslationRecord($record, $lang);
     import('Dataface/HistoryTool.php');
     $ht = new Dataface_HistoryTool();
     $hrecord = $ht->searchArchives($trecord, array('major_version' => $major_version, 'minor_version' => $minor_version), $lang);
     $modified = $hrecord->strval('history__modified');
     return $ht->getDiffsByDate($record, $modified, null, $lang, $fieldname);
 }
Пример #6
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;
 }
Пример #7
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')));
 }
 function handle(&$params)
 {
     $app =& Dataface_Application::getInstance();
     if (!@$_GET['history__id']) {
         return PEAR::raiseError('No history id supplied', DATAFACE_E_ERROR);
     }
     $historyid = $_GET['history__id'];
     $query =& $app->getQuery();
     $table = $query['-table'];
     $r = $app->getRecord();
     import('Dataface/HistoryTool.php');
     $ht = new Dataface_HistoryTool();
     if (@$_GET['-fromcurrent']) {
         $record = $ht->getDiffs($table, $historyid);
         $record->escapeOutput = false;
     } else {
         if (@$_GET['-show_changes']) {
             $thisVersion = $ht->getRecordById($table, $historyid);
             if (PEAR::isError($thisVersion)) {
                 return $thisVersion;
             } else {
                 if (!$thisVersion) {
                     return PEAR::raiseError('No history record found', DATAFACE_E_ERROR);
                 }
             }
             $mdate = $thisVersion->strval("history__modified");
             //echo "mdate: ".$mdate;
             $prevDate = date('Y-m-d H:i:s', strtotime('-1 second', strtotime($mdate)));
             //echo " prevdate: ".$prevDate.' ';
             $prevVersionId = $ht->getPreviousVersion($r, $prevDate, $thisVersion->val('history__language'), null, true);
             //echo "Prev: $prevVersionId";
             if (!$prevVersionId) {
                 $record = new Dataface_Record($table . '__history', array());
             } else {
                 $record = $ht->getDiffs($table, $prevVersionId, $historyid);
             }
             $record->escapeOutput = false;
         } else {
             $record = $ht->getRecordById($table, $historyid);
         }
     }
     if (!$record) {
         return PEAR::raiseError("No history record for table {$table} with history id {$historyid} could be found", DATAFACE_E_ERROR);
     }
     if (PEAR::isError($record)) {
         return $record;
     }
     $record->secureDisplay = false;
     $context = array('history_record' => &$record);
     $context['source_record'] = $app->getRecord();
     $t =& Dataface_Table::loadTable($table);
     $numfields = count($t->fields());
     $pts = 0;
     $ppf = array();
     $fields = $t->fields();
     $tmp = array();
     foreach ($fields as $k => $f) {
         if ($r->checkPermission('view', array('field' => $k))) {
             $tmp[$k] = $fields[$k];
         }
     }
     $fields = $tmp;
     $context['fields'] = $fields;
     foreach ($fields as $field) {
         if ($t->isText($field['name'])) {
             $pts += 5;
             $ppf[$field['name']] = $pts;
         } else {
             $pts++;
             $ppf[$field['name']] = $pts;
         }
     }
     $firstField = null;
     $threshold = floatval(floatval($pts) / floatval(2));
     foreach ($fields as $field) {
         if ($ppf[$field['name']] >= $threshold) {
             $firstField = $field['name'];
             break;
         }
     }
     $context['first_field_second_col'] = $firstField;
     $context['changes'] = @$_GET['-show_changes'];
     $context['table'] =& $t;
     df_display($context, 'Dataface_HistoryRecordDetails.html');
 }