protected function filterForeignModel(DataModel $foreignModel, DataModel\Collection $dataCollection = null)
{
$db = $this->parentModel->getDbo();
// Decide how to proceed, based on eager or lazy loading
if (is_object($dataCollection)) {
// Eager loaded relation
if (!empty($dataCollection)) {
// Get a list of local keys from the collection
$values = array();
/** @var $item DataModel */
foreach ($dataCollection as $item) {
$v = $item->getFieldValue($this->localKey, null);
if (!is_null($v)) {
$values[] = $v;
}
}
// Keep only unique values
$values = array_unique($values);
$values = array_map(function ($x) use(&$db) {
return $db->q($x);
}, $values);
// Get the foreign keys from the glue table
$query = $db->getQuery(true)->select(array($db->qn($this->pivotLocalKey), $db->qn($this->pivotForeignKey)))->from($db->qn($this->pivotTable))->where($db->qn($this->pivotLocalKey) . ' IN(' . implode(',', $values) . ')');
$db->setQuery($query);
$foreignKeysUnmapped = $db->loadRowList();
$this->foreignKeyMap = array();
$foreignKeys = array();
foreach ($foreignKeysUnmapped as $unmapped) {
$local = $unmapped[0];
$foreign = $unmapped[1];
if (!isset($this->foreignKeyMap[$local])) {
$this->foreignKeyMap[$local] = array();
}
$this->foreignKeyMap[$local][] = $foreign;
$foreignKeys[] = $foreign;
}
// Keep only unique values. However, the array keys are all screwed up. See below.
$foreignKeys = array_unique($foreignKeys);
// This looks stupid, but it's required to reset the array keys. Without it where() below fails.
$foreignKeys = array_merge($foreignKeys);
// Apply the filter
if (!empty($foreignKeys)) {
$foreignModel->where($this->foreignKey, 'in', $foreignKeys);
} else {
return false;
}
} else {
return false;
}
} else {
// Lazy loaded relation; get the single local key
$localKey = $this->parentModel->getFieldValue($this->localKey, null);
if (is_null($localKey)) {
return false;
}
$query = $db->getQuery(true)->select($db->qn($this->pivotForeignKey))->from($db->qn($this->pivotTable))->where($db->qn($this->pivotLocalKey) . ' = ' . $db->q($localKey));
$db->setQuery($query);
$foreignKeys = $db->loadColumn();
$this->foreignKeyMap[$localKey] = $foreignKeys;
// If there are no foreign keys (no foreign items assigned to our item) we return false which then causes
// the relation to return null, marking the lack of data.
if (empty($foreignKeys)) {
return false;
}
$foreignModel->where($this->foreignKey, 'in', $this->foreignKeyMap[$localKey]);
}
return true;
}