function saveTransients(Dataface_Record $record, $keys = null, $tablename = null, $secure = false) { $app = Dataface_Application::getInstance(); // 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') { $tval_existing = array(); $tval_new = array(); $tval_new_existing = array(); $torder = 0; foreach ($tval as $trow) { if (!is_array($trow)) { continue; } $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); } // 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() and !$trelationship->supportsAddExisting()); // If it supports add existing, then we shouldn't delete the entire record. Just remove it // from the relationship. 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; } $mres = $this->removeRelatedRecord($drec, $tdelete_record, $secure); if (PEAR::isError($mres)) { throw new Exception($mres->getMessage()); } 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); } }