/** * Adds an existing record to a relationship. * @param $record a Dataface_RelatedRecord object to be added. */ function addExistingRelatedRecord(&$record, $secure = false) { if ($secure && !$record->_record->checkPermission('add existing related record', array('relationship' => $record->_relationshipName))) { // Use security to check to see if we are allowed to delete this // record. //print_r( $record->_record->getPermissions(array('relationship'=>$record->_relationshipName)));exit; //echo $record->_record->_table->getDelegate()->getRoles($record->_record); //print_r($record->_record->vals());exit; return Dataface_Error::permissionDenied(df_translate('scripts.Dataface.IO.addExistingRelatedRecord.PERMISSION_DENIED', 'Could not add record "' . $record->getTitle() . '" to relationship "' . $record->_relationshipName . '" of record "' . $record->_record->getTitle() . '" because you have insufficient permissions.', array('title' => $record->getTitle(), 'relationship' => $record->_relationshipName, 'parent' => $record->_record->getTitle()))); } $builder = new Dataface_QueryBuilder($this->_table->tablename); //We are often missing the values from the domain table so we will load them //here $domainRec = $record->toRecord($record->_relationship->getDomainTable()); $domainRec2 = df_get_record_by_id($domainRec->getId()); //$record->setValues(array_merge($domainRec2->vals(), $record->vals())); foreach ($domainRec2->vals() as $dreckey => $drecval) { if (!$record->val($dreckey)) { $record->setValue($dreckey, $drecval); } } // fire the "before" events if ($this->fireTriggers) { $res = $this->fireBeforeAddRelatedRecord($record); if (PEAR::isError($res)) { return $res; } $res = $this->fireBeforeAddExistingRelatedRecord($record); if (PEAR::isError($res)) { return $res; } } // It makes sense for us to fire beforeSave, afterSave, beforeInsert, and afterInsert // events here for the records that are being inserted. To do this we will need to extract // Dataface_Record objects for all of the tables that will have records inserted. In this // case we are not updated any records because relationships are created by adding a record // to the join table. This means that we are also NOT adding a record to the domain table. // i.e., we should only fire these events for the join table. $drecords =& $record->toRecords(); // $drecords is an array of Dataface_Record objects if (count($drecords) > 1) { // If there is only one record then it is for the domain table - which we don't actually // change. foreach (array_keys($drecords) as $recordIndex) { $currentRecord =& $drecords[$recordIndex]; if (isset($this->insertids[$currentRecord->_table->tablename])) { $idfield =& $currentRecord->_table->getAutoIncrementField(); if ($idfield) { $currentRecord->setValue($idfield, $this->insertids[$currentRecord->_table->tablename]); } unset($idfield); } unset($currentRecord); if ($drecords[$recordIndex]->_table->tablename === $record->_relationship->getDomainTable()) { continue; } // We don't do anything for the domain table because it is not being updated. $rio = new Dataface_IO($drecords[$recordIndex]->_table->tablename); $drec_snapshot = $drecords[$recordIndex]->strvals(); $res = $rio->fireBeforeSave($drecords[$recordIndex]); if (PEAR::isError($res)) { return $res; } $res = $rio->fireBeforeInsert($drecords[$recordIndex]); if (PEAR::isError($res)) { return $res; } $drec_post_snapshot = $drecords[$recordIndex]->strvals(); foreach ($drec_post_snapshot as $ss_key => $ss_val) { if ($drec_snapshot[$ss_key] != $ss_val) { $drecords[$recordIndex]->setValue($ss_key, $ss_val); } } unset($drec_post_snapshot); unset($drec_snapshot); unset($rio); } } if (count($drecords) > 1) { $sql = $builder->addExistingRelatedRecord($record); if (PEAR::isError($sql)) { return $sql; } // Actually add the related record $res = $this->performSQL($sql); if (PEAR::isError($res)) { return $res; } // If there is only one record then it is for the domain table - which we don't actually // change. foreach (array_keys($drecords) as $recordIndex) { if ($drecords[$recordIndex]->_table->tablename === $record->_relationship->getDomainTable()) { continue; } // We don't do anything for the domain table because it is not being updated. $rio = new Dataface_IO($drecords[$recordIndex]->_table->tablename); $res = $rio->fireAfterInsert($drecords[$recordIndex]); if (PEAR::isError($res)) { return $res; } $res = $rio->fireAfterSave($drecords[$recordIndex]); if (PEAR::isError($res)) { return $res; } unset($rio); } } else { // This is a one to many relationship. We will handle this case // only when the foreign key is currently null. Otherwise we return // and error. $fkeys = $record->_relationship->getForeignKeyValues(); $fkeyvals = $record->getForeignKeyValues(); //print_r($fkeyvals);exit; if (isset($fkeys[$domainRec2->_table->tablename])) { $drecid = $domainRec2->getId(); unset($domainRec2); $domainRec2 = df_get_record_by_id($drecid); if (!$domainRec2) { return PEAR::raiseError("Tried to get record with id {$drecid} but it doesn't exist"); } else { if (PEAR::isError($domainRec2)) { return $domainRec2; } } foreach (array_keys($fkeys[$domainRec2->_table->tablename]) as $fkey) { //echo $fkey; if ($domainRec2->val($fkey)) { return PEAR::raiseError("Could not add existing related record '" . $domainRec2->getTitle() . "' because it can only belong to a single relationship and it already belongs to one."); } else { $domainRec2->setValue($fkey, $fkeyvals[$domainRec2->_table->tablename][$fkey]); } } //echo "About to save record";exit; $res = $domainRec2->save($secure); if (PEAR::raiseError($res)) { return $res; } } else { return PEAR::raiseError("Failed to add existing record because the domain table doesn't have any foreign keys in it."); } } // Fire the "after" events if ($this->fireTriggers) { $res2 = $this->fireAfterAddExistingRelatedRecord($record); if (PEAR::isError($res2)) { return $res2; } $res2 = $this->fireAfterAddRelatedRecord($record); if (PEAR::isError($res2)) { return $res2; } } return $res; }