/** * Applies the relation filters to the foreign model when getData is called * * @param DataModel $foreignModel The foreign model you're operating on * @param DataModel\Collection $dataCollection If it's an eager loaded relation, the collection of loaded parent records * * @return boolean Return false to force an empty data collection */ protected function filterForeignModel(DataModel $foreignModel, DataModel\Collection $dataCollection = null) { // 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); // Apply the filter if (!empty($values)) { $foreignModel->where($this->foreignKey, 'in', $values); } 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; } $foreignModel->where($this->foreignKey, '==', $localKey); } return true; }
/** * Applies the relation filters to the foreign model when getData is called * * @param DataModel $foreignModel The foreign model you're operating on * @param DataModel\Collection $dataCollection If it's an eager loaded relation, the collection of loaded parent records * * @return boolean Return false to force an empty data collection */ 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) || $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; }