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; }