function test_set_indexed_record() { $s = new Dataface_Record('Profiles', array()); $s->clearValues(); $s->setValue('id', 10); $this->assertEquals($s->getValue('addresses.city', 1), 'Springfield'); //$s->setValue('addresses.city', 'Houston', 1); //$this->assertEquals( $s->getValue('addresses.city', 1), 'Houston'); //$s->setValue('addresses.city', 'LA', array('id'=>2) ); //$this->assertEquals( $s->getValue('addresses.city', 1), 'LA'); //$this->assertEquals( $s->getValue('addresses.city', array('id'=>2)), 'LA'); }
/** * Returns true if the record currently represented in the Table already exists * in the database. * * @param tablename Alternative table where records may be stored. This is useful if we are reading form import or delete tables. * */ function recordExists(&$record, $keys = null, $tablename = null) { if (!is_a($record, "Dataface_Record")) { trigger_error(df_translate('scripts.Dataface.IO.recordExists.ERROR_PARAMETER_1', "In Dataface_IO::recordExists() the first argument is expected to be either a 'Dataface_Record' object or an array of key values, but received neither.\n<br>") . Dataface_Error::printStackTrace(), E_USER_ERROR); } if ($tablename === null and $this->_altTablename !== null) { $tablename = $this->_altTablename; } $tempRecordCreated = false; if ($record->snapshotExists()) { $tempRecord = new Dataface_Record($record->_table->tablename, $record->getSnapshot()); $tempRecordCreated = true; } else { $tempRecord =& $record; } if ($keys == null) { // Had to put in userialize(serialize(...)) because getValues() returns by reference // and we don't want to change actual values. $query = unserialize(serialize($tempRecord->getValues(array_keys($record->_table->keys())))); } else { $query = $keys; } $table_keys = array_keys($this->_table->keys()); foreach ($table_keys as $key) { if (!isset($query[$key]) or !$query[$key]) { //trigger_error("In Dataface_IO::recordExists()d attempt to determine if a record exists, not enough information was given. At least ALL of the keys of the table in question ('".$this->_table->tablename."') must be included in the provided Dataface_Record object (or query array), but some keys (notably '$key') are missing. Impossible to determine existence unless all key fields are provided.\n<br>".Dataface_Error::printStackTrace(), E_USER_ERROR); return false; } } foreach (array_keys($query) as $key) { $query[$key] = '=' . $this->_serializer->serialize($key, $tempRecord->getValue($key)); } $qb = new Dataface_QueryBuilder($this->_table->tablename, $query); $sql = $qb->select_num_rows(array(), $this->tablename($tablename)); $res = mysql_query($sql, $this->_table->db); // We just use regular mysql query to see if record exists because this should be sufficient //$res = $this->dbObj->query($sql, $this->_table->db, $this->lang); if (!$res || PEAR::isError($res)) { die("SQL error in {$sql} : " . mysql_error($this->_table->db) . Dataface_Error::printStackTrace()); } list($rows) = mysql_fetch_row($res); mysql_free_result($res); if ($rows > 1) { $err = PEAR::raiseError(Dataface_LanguageTool::translate('recordExists failure. Too many rows returned.', "Test for existence of record in recordExists() returned {$rows} records. \n\t\t\t\t\tIt should have max 1 record. \n\t\t\t\t\tThe query must be incorrect. \n\t\t\t\t\tThe query used was '{$sql}'. On line " . __LINE__ . " of file " . __FILE__, array('table' => $this->_table->tablename, 'line' => __LINE__, 'file' => __FILE__, 'sql' => $sql)), DATAFACE_E_IO_ERROR); trigger_error($err->toString() . "\n<br>" . Dataface_Error::printStackTrace()); } if ($tempRecordCreated) { $tempRecord->__destruct(); } return intval($rows) === 1; }
/** * Returns true if the record currently represented in the Table already exists * in the database. * * @param tablename Alternative table where records may be stored. This is useful if we are reading form import or delete tables. * */ function recordExists(&$record, $keys = null, $tablename = null) { $this->lastVersionNumber = null; if (!is_a($record, "Dataface_Record")) { throw new Exception(df_translate('scripts.Dataface.IO.recordExists.ERROR_PARAMETER_1', "In Dataface_IO::recordExists() the first argument is expected to be either a 'Dataface_Record' object or an array of key values, but received neither.\n<br>"), E_USER_ERROR); } if ($tablename === null and $this->_altTablename !== null) { $tablename = $this->_altTablename; } $tempRecordCreated = false; if ($record->snapshotExists()) { $tempRecord = new Dataface_Record($record->_table->tablename, $record->getSnapshot()); $tempRecordCreated = true; } else { $tempRecord =& $record; } if ($keys == null) { // Had to put in userialize(serialize(...)) because getValues() returns by reference // and we don't want to change actual values. $query = unserialize(serialize($tempRecord->getValues(array_keys($record->_table->keys())))); } else { $query = $keys; } $table_keys = array_keys($this->_table->keys()); foreach ($table_keys as $key) { if (!isset($query[$key]) or !$query[$key]) { return false; } } foreach (array_keys($query) as $key) { //$query[$key] = '='.$this->_serializer->serialize($key, $tempRecord->getValue($key) ); $query[$key] = $this->_serializer->serialize($key, $tempRecord->getValue($key)); } if ($tempRecordCreated) { $tempRecord->__destruct(); } //$qb = new Dataface_QueryBuilder($this->_table->tablename, $query); //$sql = $qb->select_num_rows(array(), $this->tablename($tablename)); if ($record->table()->isVersioned()) { $versionField = "`" . $record->table()->getVersionField() . "`"; } else { $versionField = "NULL"; } $sql = "select `" . $table_keys[0] . "`, {$versionField} from `" . $this->tablename($tablename) . "` where "; $where = array(); foreach ($query as $key => $val) { $where[] = '`' . $key . "`='" . addslashes($val) . "'"; } $sql .= implode(' AND ', $where) . ' limit 1'; $res = df_q($sql, $this->_table->db); $num = xf_db_num_rows($res); $row = xf_db_fetch_row($res); @xf_db_free_result($res); if ($num === 1) { // We have the correct number... // let's check the version $this->lastVersionNumber = intval($row[1]); return true; } if ($num > 1) { $err = PEAR::raiseError(Dataface_LanguageTool::translate('recordExists failure. Too many rows returned.', "Test for existence of record in recordExists() returned {$rows} records. \n\t\t\t\t\tIt should have max 1 record. \n\t\t\t\t\tThe query must be incorrect. \n\t\t\t\t\tThe query used was '{$sql}'. ", array('table' => $this->_table->tablename, 'line' => 0, 'file' => '_', 'sql' => $sql)), DATAFACE_E_IO_ERROR); throw new Exception($err->toString(), E_USER_ERROR); } return false; }
/** * Gets the value for a field. * * @param $fieldname The name of the field whose value we are retrieving. This may be either a relative * fieldname or an absolute column name. * @type string */ function getValue($fieldname) { $this->_initValues(); if (strpos($fieldname, '.') === false) { if (!array_key_exists($fieldname, $this->_values)) { // The key does not exist as a normal field -- so check if it is a calculated field. $tables = $this->_relationship->getDestinationTables(); $dt =& Dataface_Table::loadTable($this->_relationship->getDomainTable()); if ($dt->hasField($fieldname)) { echo "Domain table has {$fieldname}"; $tables = array($this->_relationship->getDomainTable()); } else { echo "Domain table doesn't have {$fieldname}"; } foreach (array_keys($tables) as $tkey) { if ($tables[$tkey]->hasField($fieldname)) { $tempRecord = new Dataface_Record($tables[$tkey]->tablename, $this->getValues()); return $tempRecord->getValue($fieldname); } } trigger_error("Attempt to get value for fieldname '{$fieldname}' that does not exist in related record of relationship '" . $this->_relationshipName . "'. Acceptable values include {" . implode(', ', array_keys($this->_values)) . "}.\n<br>" . Dataface_Error::printStackTrace(), E_USER_ERROR); } return $this->_values[$fieldname]; } else { list($table, $field) = explode('.', $fieldname); return $this->getValue($field); } }
function test_relationships() { $record = new Dataface_Record('Profiles', array()); $record->setValue('id', 10); $record->setValue('fname', 'John'); $table =& $this->table1; $this->table1->relationships(); // loads the relationships // make sure that the relationships were loaded properly $rels = array('appointments', 'degrees', 'addresses'); foreach ($rels as $rel) { $this->assertTrue(is_a($table->_relationships[$rel], 'Dataface_Relationship'), "Relationship {$rel} not loaded"); } //make sure the sql was loaded properly $appointments =& $table->getRelationship('appointments'); $this->assertEquals($appointments->_schema['sql'], "select * from Appointments where Appointments.profileid='\$id'"); $this->assertEquals($record->parseString($appointments->_schema['sql']), "select * from Appointments where Appointments.profileid='10'"); $this->assertEquals(count($appointments->_schema['tables']), 1); $this->assertEquals($appointments->_schema['tables'][0], 'Appointments'); $this->assertEquals(count($appointments->_schema['selected_tables']), 1); $this->assertEquals($appointments->_schema['selected_tables'][0], 'Appointments'); $this->assertEquals(count($appointments->_schema['columns']), 6); //(profileid, position, startdate, enddate, salary) $this->assertEquals($appointments->_schema['columns'][0], 'Appointments.id'); $this->assertEquals($appointments->_schema['columns'][1], 'Appointments.profileid'); $this->assertEquals($appointments->_schema['columns'][2], 'Appointments.position'); $this->assertEquals($appointments->_schema['columns'][3], 'Appointments.startdate'); $this->assertEquals($appointments->_schema['columns'][4], 'Appointments.enddate'); $this->assertEquals($appointments->_schema['columns'][5], 'Appointments.salary'); $degrees =& $table->getRelationship('degrees'); $this->assertEquals($degrees->_schema['sql'], "select name, institution from Degrees where Degrees.profileid='\$id'"); $this->assertEquals($record->parseString($degrees->_schema['sql']), "select name, institution from Degrees where Degrees.profileid='10'"); $this->assertEquals(count($degrees->_schema['tables']), 1); $this->assertEquals($degrees->_schema['tables'][0], 'Degrees'); $this->assertEquals(count($degrees->_schema['columns']), 2); $this->assertEquals($degrees->_schema['columns'][0], 'Degrees.name'); $this->assertEquals($degrees->_schema['columns'][1], 'Degrees.institution'); $courses =& $table->getRelationship('courses'); $this->assertEquals($courses->_schema['selected_tables'][0], 'Courses'); $this->assertEquals(count($courses->_schema['columns']), 4); $this->assertEquals($courses->_schema['sql'], "select Courses.* from Courses, Student_Courses where Courses.id=Student_Courses.courseid and Student_Courses.studentid='\$id'"); // try default get related... should only return 3 records unset($degrees); $degrees = $record->getRelatedRecords('degrees'); $this->assertEquals($degrees[0]['name'], 'Master of Technology'); $this->assertEquals(count($degrees), 3, 'Degrees relationship returned wrong number of records. Should be 3.'); foreach ($degrees as $degree) { $this->assertTrue(isset($degree['name']), 'name is not set for ' . $degree); $this->assertTrue(isset($degree['institution']), 'institution is not set for' . $degree); } // Explicitly request multiple records $degrees = $record->getRelatedRecords('degrees', true); $this->assertEquals($degrees[0]['name'], 'Master of Technology'); $this->assertEquals(count($degrees), 3, 'Degrees relationship returned wrong number of records. Should be 3.'); foreach ($degrees as $degree) { $this->assertTrue(isset($degree['name']), 'name is not set for ' . $degree); $this->assertTrue(isset($degree['institution']), 'institution is not set for' . $degree); } // Explicitly request single record $degrees = $record->getRelatedRecords('degrees', false); $this->assertEquals($degrees['name'], 'Master of Technology'); $this->assertTrue(isset($degrees['name']), 'name is not set for ' . $degree); $this->assertTrue(isset($degrees['institution']), 'institution is not set for' . $degree); // Try using getValue() $this->assertEquals($record->getValue('degrees.name'), 'Master of Technology'); // Try multiple values //$names = $record->getValue('degrees.name', true); //$this->assertEquals(3, count($names), 'Wrong number of names returned for getValue(degrees.name)'); //$this->assertEquals($names[0], 'Master of Technology'); //$this->assertEquals($names[1], 'PH.D of Technology'); //$this->assertEquals($names[2], 'Bachelor of Science'); // // Now we use a relationship that was defined directly with SQL //(profileid,line1,line2,line3,city,state,country,postalcode) $addresses =& $this->table1->getRelationship('addresses'); $this->assertEquals($addresses->_schema['sql'], "select * from Addresses where profileid='\$id'"); $this->assertEquals($record->parseString($addresses->_schema['sql']), "select * from Addresses where profileid='10'"); $this->assertEquals(count($addresses->_schema['tables']), 1); $this->assertEquals(count($addresses->_schema['columns']), 9); $this->assertEquals($addresses->_schema['tables'][0], 'Addresses'); $this->assertEquals($addresses->_schema['columns'][0], 'Addresses.id'); $this->assertEquals($addresses->_schema['columns'][1], 'Addresses.profileid'); $this->assertEquals($addresses->_schema['columns'][2], 'Addresses.line1'); $this->assertEquals($addresses->_schema['columns'][3], 'Addresses.line2'); $line1 = $record->getValue('addresses.line1'); $this->assertEquals($line1, '555 Elm St'); }
public function buildRecord(xatacard_layout_Schema $schema, Dataface_Record $rec) { //Now we populate the record $out = new xatacard_layout_Record(); $out->setSchema($schema); $out->setDataSource($this); $recordCache = array(); $recordCache[$rec->getId()] = $rec; $recordData = array('records' => array(), 'fields' => array()); $recordIdToIndex = array(); foreach ($schema->getFields() as $key => $value) { if (strpos($key, '/') !== false) { // this is a first class property of the record so we can just get it. $index = count($recordData['records']); $recordData['records'][$index] = array('id' => $rec->getId(), 'version' => $rec->getVersion()); $recordIdToIndex[$rec->getId()] = $index; $recordData['fields'][$key] = $recordIdToIndex[$rec->getId()]; $out->setValue($key, $rec->getValue($key)); } else { // this is a related record's property that we need to get from the related // records. $path = explode('/', $key); $crec = $rec; // As we're going to be going through related records // we need to mark the current record we are dealing /// with $fieldName = array_pop($path); // A flag to indicate if we should break the outer loop // after the inner loop finishes $shouldSkip = false; foreach ($path as $part) { $index = 0; if (preg_match('/^(.*)\\[(\\d+\\)]$/', $part, $matches)) { $index = intval($matches[2]); $part = $matches[1]; } $related = $crec->getRelatedRecord($part, $index); if (PEAR::isError($related)) { throw new Exception(sprintf("MySQL datasource failed to load record because there was an error retrieving a column from a related record. The field '%s' could not be retrieved because the following error: %s", $key, $related->getMessage())); } if (!$related) { // No related record could be found to satisfy this path. // This doesn't constitute an error. It just means that the // value should be blank. $out->setValue($key, null); $shouldSkip = true; break; } unset($crec); if (@$this->recordCache[$related->getId()]) { $crec = $this->recordCache[$related->getId()]; } else { $crec = $related->toRecord(); $this->recordCache[$related->getId()] = $crec; $index = count($recordData['records']); $recordData['records'][$index] = array('id' => $crec->getId(), 'version' => $rec->getVersion()); $recordIdToIndex[$crec->getId()] = $index; } unset($related); } if ($shouldSkip) { // Something occurred in the inner loop to // complete this step so we should skip the rest // of this stuff. continue; } if (!$crec) { // This should never happen throw new Exception(sprintf("MySQL datasource failed to load record because there was an error retrieving a related record required for one of the fields. The field '%s' could not be retrieved.", $key)); } $recordData['fields'][$key] = $recordIdToIndex[$crec->getId()]; $out->setValue($key, $crec->val($fieldName)); } } $cacheKeys = array_keys($recordCache); sort($cacheKeys); $versionstring = array(); foreach ($cacheKeys as $k) { $versionstring[] = $k . ':' . $recordCache[$k]->getVersion(); } $versionstring = implode(' ', $versionstring); $versionhash = md5($versionstring); $res = $this->query(sprintf("select `id` from `%s` where \n\t\t\t\tschema_id=%d and \n\t\t\t\tbase_record_id_hash='%s' and \n\t\t\t\tversion_hash='%s' and\n\t\t\t\t`lang`='%s'", str_replace('`', '', self::$RECORDS_TABLE), intval($schema->getId()), addslashes(md5($rec->getId())), addslashes($versionhash), addslashes($rec->lang))); if (xf_db_num_rows($res) >= 0) { $row = xf_db_fetch_row($res); $out->setId($row[0]); } else { $res = $this->query(sprintf("insert into `%s` (schema_id, base_record_id_hash, base_record_id, version_hash, `lang`, `record_data`)\n\t\t\t\tvalues (\n\t\t\t\t\t%d, '%s', '%s', '%s', '%s'\n\t\t\t\t)", intval($schema->getId()), addslashes(md5($rec->getId())), addslashes($rec->getid()), addslashes($versionhash), addslashes($rec->lang), addslashes(json_encode($recordData)))); $out->setId(xf_db_insert_id(df_db())); } $out->clearSnapshot(); return $out; }