/** * Generates objects from special sql: * SELECT id as owner[id]... * * * * @param ADOResultSet $results a result set from Db->execute * @param array $included_associations just like in ->find(); $options['include']; but in fact unused * @param mixed $virtual_limit int or false; unsure if this works * @return array ObjectGraph as an array */ public function &_generateObjectGraphFromResultSet($results, $virtual_limit = false, $load_acts = true, $returns = 'default', $simulation_class = 'AkActiveRecordMock', $config = array()) { $return = array(); $owner = array(); $keys = array(); $record_counter = 0; while ($record = $results->FetchRow()) { $record_counter++; /** * implement limits here, config should have limits per association * need offset as well */ foreach ($record as $key => $value) { if (strstr($key, '@')) { $true = true; while ($true) { if (!isset($keys[$key])) { $pos = @strrpos($key, '@'); $length = @strpos(']', $key, $pos); $pk = @substr($key, $pos + 1, $length + 2); $kpos = @strpos(']', $key, $pos); $base = @substr($key, 0, $kpos + $pos - 1); $replace = $base . '[@' . $pk . ']'; $subkey = $replace . '[' . $pk . ']'; $keys[$key] = array('pos' => $pos, 'length' => $length, 'pk' => $pk, 'kpos' => $kpos, 'subkey' => $subkey, 'replace' => $replace, 'base' => $base); } else { $subkey = $keys[$key]['subkey']; $pos = $keys[$key]['pos']; $kpos = $keys[$key]['kpos']; $pk = $keys[$key]['pk']; $replace = $keys[$key]['replace']; $base = $keys[$key]['base']; } if (isset($record[$subkey])) { $id = $record[$subkey]; } else { $id = 0; } $key = str_replace($replace, $base . '[' . $id . ']', $key); if (!strstr($key, '@')) { $true = false; } } } $this->_addToOwner($owner, str_replace('owner[', '[', $key), $value, $returns, $config['__owner']); } unset($record); } if ($returns == 'default') { unset($keys); if (!empty($owner)) { $available_attributes = $this->getAvailableAttributes(); $available_attributes = array_keys($available_attributes); foreach ($owner as $id => $data) { if (!isset($diff)) { $diff = @array_diff(array_keys($data), $available_attributes); $nondiff = array(); foreach ($diff as $d) { $nondiff[$d] = null; } } $available = array_merge($data, $nondiff); $available['load_associations'] = false; $available['load_acts'] = $load_acts; $obj =& $this->instantiate($available, false, false); foreach (array_values($diff) as $rel) { $this->_setAssociations($rel, $data[$rel], $obj, $load_acts); } $obj->afterInstantiate(); $obj->notifyObservers('afterInstantiate'); $return[] =& $obj; } } else { $return = false; } } else { if ($returns == 'array') { $this->_reindexArray($owner); $return = $owner; } else { if ($returns == 'simulated') { include_once AK_LIB_DIR . DS . 'AkActiveRecord' . DS . 'AkActiveRecordMock.php'; $false = false; $return =& $this->_generateStdClasses($simulation_class, $owner, $this->getType(), $false, $false, $config); } } } return $return; }
/** * Pass hand-made sql directly to _db->execute and generate the OG with this method. * * @param ADOResultSet $results a result set from Db->execute * @param array $included_associations just like in ->find(); $options['include']; but in fact unused * @param mixed $virtual_limit int or false; unsure if this works * @return array ObjectGraph as an array */ function &_generateObjectGraphFromResultSet($results, $included_associations = array(), $virtual_limit = false) { $objects = array(); $i = 0; $associated_ids = $this->getAssociatedIds(); $number_of_associates = count($associated_ids); $_included_results = array(); // Used only in conjuntion with virtual limits for doing find('first',...include'=>... $object_associates_details = array(); $ids = array(); while ($record = $results->FetchRow()) { $this_item_attributes = array(); $associated_items = array(); foreach ($record as $column => $value) { if (!is_numeric($column)) { if (substr($column, 0, 8) == '__owner_') { $attribute_name = substr($column, 8); $this_item_attributes[$attribute_name] = $value; } elseif (preg_match('/^_(' . join('|', $associated_ids) . ')_(.+)/', $column, $match)) { $associated_items[$match[1]][$match[2]] = $value; } } } // We need to keep a pointer to unique parent elements in order to add associates to the first loaded item $e = null; $object_id = $this_item_attributes[$this->getPrimaryKey()]; if (!empty($virtual_limit)) { $_included_results[$object_id] = $object_id; if (count($_included_results) > $virtual_limit * $number_of_associates) { continue; } } if (!isset($ids[$object_id])) { $ids[$object_id] = $i; $attributes_for_instantation = $this->getOnlyAvailableAttributes($this_item_attributes); $attributes_for_instantation['load_associations'] = true; $objects[$i] =& $this->instantiate($attributes_for_instantation, false); } else { $e = $i; $i = $ids[$object_id]; } foreach ($associated_items as $association_id => $attributes) { if (count(array_diff($attributes, array(''))) > 0) { $object_associates_details[$i][$association_id][md5(serialize($attributes))] = $attributes; } } $i = !is_null($e) ? $e : $i + 1; } if (!empty($object_associates_details)) { foreach ($object_associates_details as $i => $object_associate_details) { foreach ($object_associate_details as $association_id => $associated_attributes) { foreach ($associated_attributes as $attributes) { if (count(array_diff($attributes, array(''))) > 0) { if (!method_exists($objects[$i]->{$association_id}, 'build')) { $handler_name = $this->getAssociatedHandlerName($association_id); $objects[$i]->{$handler_name}->build($attributes, false); } else { $objects[$i]->{$association_id}->build($attributes, false); $objects[$i]->{$association_id}->_newRecord = false; } } } } } } $result =& $objects; return $result; }