/** * * Imports data into the supplied record's relationship. This makes use of this table's delegate * file to handle the importing. * * @param $record A Dataface_Record object whose relationship is to have records added to it. * @type Dataface_Record | null * * @param $data Either raw data that is to be imported, or the name of an Import table from which * data is to be imported. * @type Raw | string * * @param $importFilter The name of the import filter that should be used. * @type string * * @param $relationshipName The name of the relationship where these records should be added. * @type string * * @param $commit A boolean value indicating whether this import should be committed to the * database. If this is false, then the records will not actually be imported. They * will merely be stored in an import table. This must be explicitly set to true * for the import to succeed. * @type boolean * * @param defaultValues Array of default values of the form [Abs fieldname] -> [field value], where 'Abs fieldname' * is the absolute field name (ie: tablename.fieldname). All imported records will attain * these default values. * @type array([string] -> [mixed]) * * @return Case 1: The import succeeds. * Case 1.1: if commit = false return Import Table name where data is stored. * Case 1.2: If commit = true return array of Dataface_Record objects that were inserted. * Case 2: The import failed * return PEAR_Error object. * * * Usage: * ------- * $data = '<phonelist> * <listentry> * <name>John Smith</name><number>555-555-5555</number> * </listentry> * <listentry> * <name>Susan Moore</name><number>444-444-4444</number> * </listentry> * </phonelist>'; * * // assume that we have an import filter called 'XML_Filter' that can import the above data. * * $directory = new Dataface_Record('Directory', array('Name'=>'SFU Directory')); * // assume that the Directory table has a relationship called 'phonelist' and we want to * // import the above data into this relationship. * * $io = new Dataface_IO('Directory'); * $importTableName = $io->importData( $directory, // The record that owns the relationship where imported records will be added * $data, // The raw data to import * 'XML_Filter', // The name of the impot * 'phonelist' * ); * // Since we didn't set the $commit flag, the data has been imported into an import table * // whose name is stored now in $importTableName. * * // * // Now suppose we have confirmed that the import is what we want to do and we are ready to import * // the data into the database. * $records = $io->importData($directory, $importTableName, null, 'phonelist', true ); * * echo $records[0]->val('name'); // should output 'John Smith' * echo $records[0]->val('number'); // should output '555-555-5555' * echo $records[1]->val('name'); // should output 'Susan Moore' * echo $records[1]->val('number'); // should output '444-444-4444' * * // note that at this point the records in $records are already persisted to the database * */ function importData(&$record, $data, $importFilter = null, $relationshipName = null, $commit = false, $defaultValues = array()) { if ($relationshipName === null) { /* * No relationship is specified so our import table is just the current table. */ $table =& $this->_table; } else { /* * A relationship is specified so we are actually importing the records into the * domain table of the relationship. */ $relationship =& $this->_table->getRelationship($relationshipName); $tablename = $relationship->getDomainTable(); if (PEAR::isError($tablename)) { /* * This relationship does not have a domain table.. so we will just take the destination table. */ $destinationTables =& $relationship->getDestinationTables(); if (count($destinationTables) <= 0) { trigger_error(df_translate('scripts.Dataface.IO.importData.ERROR_NO_DESTINATION_TABLES', "Error occurred while attempting to parse import data into a table. The relationship '" . $relationship->getName() . "' of table '" . $this->_table->tablename . "' has not destination tables listed. It should have at least one.\n", array('relationship' => $relationship->getName(), 'table' => $this->_table->tablename)) . Dataface_Error::printStackTrace(), E_USER_ERROR); } $tablename = $destinationTables[0]->tablename; } if (PEAR::isError($tablename)) { trigger_error($tablename->toString() . Dataface_Error::printStackTrace(), E_USER_ERROR); } $table =& Dataface_Table::loadTable($tablename); $rel_io = new Dataface_IO($tablename); $io =& $rel_io; } if (!$commit) { // If data is provided, we must parse it and prepare it for // import $records = $table->parseImportData($data, $importFilter, $defaultValues); if (PEAR::isError($records)) { /* * The import didn't work with the specified import filter, so we will * try the other filters. */ $records = $table->parseImportData($data, null, $defaultValues); } if (PEAR::isError($records)) { /* * Apparently we have failed to import the data, so let's just * return the errors. */ return $records; } // Now we will load the values of the records into an array // so that we can store it in the session $importData = array('table' => $table->tablename, 'relationship' => $relationshipName, 'defaults' => $defaultValues, 'importFilter' => $importFilter, 'record' => null, 'rows' => array()); if (isset($record)) { $importData['record'] = $record->getId(); } foreach ($records as $r) { if (is_a($r, 'Dataface_ImportRecord')) { // The current record is actually an ImportRecord $importData['rows'][] = $r->toArray(); } else { $importData['rows'][] = $r->vals(array_keys($r->_table->fields(false, true))); unset($r); } } $dumpFile = tempnam(sys_get_temp_dir(), 'dataface_import'); $handle = fopen($dumpFile, "w"); if (!$handle) { trigger_error("Could not write import data to dump file {$dumpFile}", E_USER_ERROR); } fwrite($handle, serialize($importData)); fclose($handle); $_SESSION['__dataface__import_data__'] = $dumpFile; return $dumpFile; } if (!@$_SESSION['__dataface__import_data__']) { trigger_error("No import data to import", E_USER_ERROR); } $dumpFile = $_SESSION['__dataface__import_data__']; $importData = unserialize(file_get_contents($dumpFile)); if ($importData['table'] != $table->tablename) { return PEAR::raiseError("Unexpected table name in import data. Expected " . $table->tablename . " but received " . $importData['table']); } $inserted = array(); $i = 0; foreach ($importData['rows'] as $row) { if (isset($row['__CLASS__']) and isset($row['__CLASSPATH__'])) { // This row is an import record - not merely a Dataface_Record // object so it provides its own logic to import the records. import($row['__CLASSPATH__']); $class = $row['__CLASS__']; $importRecord = new $class($row); $res = $importRecord->commit($record, $relationshipName); if (PEAR::isError($res)) { return $res; } } else { $values = array(); foreach (array_keys($row) as $key) { if (!is_int($key)) { $values[$key] = $row[$key]; } } if ($relationshipName === null) { /* * These records are not being added to a relationship. They are just being added directly * into the table. */ $defaults = array(); // for absolute field name keys for default values, we will strip out the table name. foreach (array_keys($defaultValues) as $key) { if (strpos($key, '.') !== false) { list($tablename, $fieldname) = explode('.', $key); if ($tablename == $this->_table->tablename) { $defaults[$fieldname] = $defaultValues[$key]; } else { continue; } } else { $defaults[$key] = $defaultValues[$key]; } } $values = array_merge($defaults, $values); $insrecord = new Dataface_Record($this->_table->tablename, $values); $inserted[] =& $insrecord; $this->write($insrecord); $insrecord->__destruct(); unset($insrecord); } else { /* * The records are being added to a relationship so we need to make sure that we add the appropriate * entries to the "join" tables as well. */ foreach (array_keys($values) as $key) { $values[$table->tablename . '.' . $key] = $values[$key]; unset($values[$key]); } $values = array_merge($defaultValues, $values); /* * Let's check if all of the keys are set. If they are then the record already exists.. we * just need to update the record. * */ $rvalues = array(); foreach ($values as $valkey => $valval) { if (strpos($valkey, '.') !== false) { list($tablename, $fieldname) = explode('.', $valkey); if ($tablename == $table->tablename) { $rvalues[$fieldname] = $valval; } } } $rrecord = new Dataface_Record($table->tablename, array()); $rrecord->setValues($rvalues); // we set the values in a separate call because we want to be able to do an update // and setting values in the constructer sets the snapshot (ie: it will think that // no values have changed. if ($io->recordExists($rrecord)) { /* * The record already exists, so we update it and then add it to the relationship. * */ if (Dataface_PermissionsTool::edit($rrecord)) { /* * We only edit the record if we have permission to do so. */ $result = $io->write($rrecord); if (PEAR::isError($result)) { trigger_error($result->toString() . Dataface_Error::printStackTrace(), E_USER_ERROR); } } $relatedRecord = new Dataface_RelatedRecord($record, $relationshipName, $values); $inserted[] =& $relatedRecord; $qb = new Dataface_QueryBuilder($this->_table->tablename); $sql = $qb->addExistingRelatedRecord($relatedRecord); $res2 = $this->performSQL($sql); unset($relatedRecord); } else { $relatedRecord = new Dataface_RelatedRecord($record, $relationshipName, $values); $inserted[] =& $relatedRecord; $qb = new Dataface_QueryBuilder($this->_table->tablename); $sql = $qb->addRelatedRecord($relatedRecord); $res2 = $this->performSQL($sql); unset($relatedRecord); } unset($rrecord); } } unset($row); } @unlink($dumpFile); unset($_SESSION['__dataface__import_data__']); return $inserted; }
function test_add_existing_related_record_sql() { $s = new Dataface_Record('Profiles'); $builder = new Dataface_QueryBuilder('Profiles'); $existingRecord = new Dataface_RelatedRecord($s, 'addresses'); $s->setValue('id', 15); $res = $builder->addExistingRelatedRecord($existingRecord); if (PEAR::isError($res)) { echo $res->toString(); } else { //print_r($res); } $this->assertEquals(array('Addresses' => "INSERT INTO `Addresses` (`profileid`) VALUES ('15')"), $res); $existingCourse = new Dataface_RelatedRecord($s, 'courses', array('id' => 3)); $res = $builder->addExistingRelatedRecord($existingCourse); if (PEAR::isError($res)) { echo $res->toString(); } else { //print_r($res); } $this->assertEquals(array('Student_Courses' => "INSERT INTO `Student_Courses` (`studentid`,`courseid`) VALUES ('15','3')"), $res); }