/** * Find a related recordset. * @param Garp_Model $model The model that spawned this data * @param Garp_Db_Row $row The row object * @param Garp_Util_Configuration $options Various relation options * @return String The name of the method. */ protected function _getRelatedRowset(Garp_Model $model, Garp_Db_Table_Row $row, Garp_Util_Configuration $options) { /** * An optional passed SELECT object will be passed by reference after every query. * This results in an error when 'clone' is not used, because correlation names will be * used twice (since they were set during the first iteration). Using 'clone' makes sure * a brand new SELECT object is used every time that hasn't been soiled by a possible * previous query. */ $conditions = is_null($options['conditions']) ? null : clone $options['conditions']; $otherModel = $options['modelClass']; if (!$otherModel instanceof Zend_Db_Table_Abstract) { $otherModel = new $otherModel(); } /** * Do not cache related queries. The "outside" query should be the only * query that's cached. */ $originalCacheQueriesFlag = $otherModel->getCacheQueries(); $otherModel->setCacheQueries(false); $modelName = get_class($otherModel); $relatedRowset = null; // many to many if (!empty($options['bindingModel'])) { $relatedRowset = $row->findManyToManyRowset($otherModel, $options['bindingModel'], $options['rule2'], $options['rule'], $conditions); } else { /** * 'mode' is used to clear ambiguity with homophilic relationships. For example, * a Model_Doc can have have child Docs and one parent Doc. The conditionals below can never tell * which method to call (findParentRow or findDependentRowset) from the referenceMap. * Therefore, we can help the decision-making by passing "mode". This can either be * "parent" or "dependent", which will then force a call to findParentRow and findDependentRowset, * respectively. */ if (is_null($options['mode'])) { // belongs to try { $model->getReference($modelName, $options['rule']); $relatedRowset = $row->findParentRow($otherModel, $options['rule'], $conditions); } catch (Exception $e) { if (!Garp_Content_Relation_Manager::isInvalidReferenceException($e)) { throw $e; } try { // one to many - one to one // The following line triggers an exception if no reference is available $otherModel->getReference(get_class($model), $options['rule']); $relatedRowset = $row->findDependentRowset($otherModel, $options['rule'], $conditions); } catch (Exception $e) { if (!Garp_Content_Relation_Manager::isInvalidReferenceException($e)) { throw $e; } $bindingModel = $model->getBindingModel($modelName); $relatedRowset = $row->findManyToManyRowset($otherModel, $bindingModel, $options['rule2'], $options['rule'], $conditions); } } } else { switch ($options['mode']) { case 'parent': $relatedRowset = $row->findParentRow($otherModel, $options['rule'], $conditions); break; case 'dependent': $relatedRowset = $row->findDependentRowset($otherModel, $options['rule'], $conditions); break; default: throw new Garp_Model_Exception('Invalid value for "mode" given. Must be either "parent" or ' . '"dependent", but "' . $options['mode'] . '" was given.'); break; } } } // Reset the cacheQueries value. It's a static property, // so leaving it FALSE will affect all future fetch() calls to this // model. Not good. $otherModel->setCacheQueries($originalCacheQueriesFlag); return $relatedRowset; }