/** * @param $onTableAliasName * @param bool $canUseFromJoins * @return null|string * @throws NotImplementedException */ protected function resolveJoinsForInferredRelation($onTableAliasName, $canUseFromJoins = true) { assert('is_string($onTableAliasName)'); assert('is_bool($canUseFromJoins)'); //First cast up $onTableAliasName = $this->resolveJoinsForInferredRelationThatIsCastedUp($onTableAliasName, $canUseFromJoins); //Second build relation across to the opposing model $onTableAliasName = $this->resolveJoinsForForARelationAttributeThatIsManyToMany($onTableAliasName); //Casting down should always be necessary since that is the whole point of using a referred relation $opposingRelationModelClassName = $this->modelAttributeToDataProviderAdapter->getRelationModelClassName(); if ($opposingRelationModelClassName != 'Item') { throw new NotImplementedException(); } $inferredRelationModelClassName = $this->modelAttributeToDataProviderAdapter->getInferredRelationModelClassName(); $onTableAliasName = $this->resolveAndProcessLeftJoinsForAttributeThatIsCastedDownOrUp($opposingRelationModelClassName, $inferredRelationModelClassName, $onTableAliasName); return $onTableAliasName; }
public function testAllMethodsOnAttributeOnSameModelAndRelatedAttribute() { $adapter = new RedBeanModelAttributeToDataProviderAdapter('I', 'j', 'jMember'); $this->assertEquals('I', $adapter->getModelClassName()); $this->assertEquals('j', $adapter->getAttribute()); $this->assertEquals('jMember', $adapter->getRelatedAttribute()); $this->assertEquals('i', $adapter->getModelTableName()); $this->assertEquals('I', $adapter->getAttributeModelClassName()); $this->assertEquals('i', $adapter->getAttributeTableName()); $this->assertEquals('j_id', $adapter->getColumnName()); $this->assertTrue($adapter->isRelation()); $this->assertTrue($adapter->hasRelatedAttribute()); $this->assertEquals('J', $adapter->getRelationModelClassName()); $this->assertEquals('J', $adapter->getRelatedAttributeModelClassName()); $this->assertEquals('j', $adapter->getRelationTableName()); $this->assertEquals('j', $adapter->getRelatedAttributeTableName()); $this->assertEquals('jmember', $adapter->getRelatedAttributeColumnName()); $this->assertFalse($adapter->isRelatedAttributeRelation()); }
/** * @param string $modelClassName * @param integer $clausePosition * @param array $clauseInformation * @param array $where * @param RedBeanModelJoinTablesQueryAdapter $joinTablesAdapter * @param null | string $onTableAliasName */ protected static function processMetadataContainingRelatedModelDataClause($modelClassName, $clausePosition, $clauseInformation, &$where, $joinTablesAdapter, $onTableAliasName = null) { assert('is_string($modelClassName) && $modelClassName != ""'); assert('$joinTablesAdapter instanceof RedBeanModelJoinTablesQueryAdapter'); assert('is_int($clausePosition)'); assert('is_array($clauseInformation["relatedModelData"]) && count($clauseInformation["relatedModelData"]) > 0'); assert('is_string($onTableAliasName) || $onTableAliasName == null'); $relatedAttributeName = null; if (isset($clauseInformation['relatedModelData']['attributeName'])) { $relatedAttributeName = $clauseInformation['relatedModelData']['attributeName']; } $modelAttributeToDataProviderAdapter = new RedBeanModelAttributeToDataProviderAdapter($modelClassName, $clauseInformation['attributeName'], $relatedAttributeName); $builder = new ModelWhereAndJoinBuilder($modelAttributeToDataProviderAdapter, $joinTablesAdapter, true); $builder->resolveJoins($onTableAliasName, self::resolveCanUseFromJoins($onTableAliasName)); $relationModelClassName = $modelAttributeToDataProviderAdapter->getRelationModelClassName(); //if there is no more relatedModelData then we know this is the end of the nested information. if (isset($clauseInformation['relatedModelData']['relatedModelData']) || isset($clauseInformation['relatedModelData']['concatedAttributeNames'])) { return static::processMetadataClause($relationModelClassName, $clausePosition, $clauseInformation['relatedModelData'], $where, $joinTablesAdapter, $onTableAliasName); } //Supporting the use of relatedAttributeName. Alternatively you can use relatedModelData to produce the same results. if (isset($clauseInformation['relatedModelData']['relatedAttributeName'])) { $modelAttributeToDataProviderAdapter = new RedBeanModelAttributeToDataProviderAdapter($relationModelClassName, $clauseInformation['relatedModelData']['attributeName'], $clauseInformation['relatedModelData']['relatedAttributeName']); $builder = new ModelWhereAndJoinBuilder($modelAttributeToDataProviderAdapter, $joinTablesAdapter, true, ArrayUtil::getArrayValue($clauseInformation['relatedModelData'], 'modifierType')); } $builder->resolveJoinsAndBuildWhere($clauseInformation['relatedModelData']['operatorType'], $clauseInformation['relatedModelData']['value'], $clausePosition, $where, $onTableAliasName); }
protected static function resolveJoinsForRelatedAttributeAndGetRelationAttributeTableAliasName(RedBeanModelAttributeToDataProviderAdapter $modelAttributeToDataProviderAdapter, RedBeanModelJoinTablesQueryAdapter $joinTablesAdapter, $onTableAliasName) { assert('$modelAttributeToDataProviderAdapter->getRelationType() != RedBeanModel::MANY_MANY'); assert('is_string($onTableAliasName)'); if ($modelAttributeToDataProviderAdapter->getRelationType() == RedBeanModel::HAS_MANY || $modelAttributeToDataProviderAdapter->getRelationType() == RedBeanModel::HAS_MANY_BELONGS_TO) { $onTableJoinIdName = 'id'; $tableJoinIdName = $onTableAliasName . '_id'; //HAS_MANY have the potential to produce more than one row per model, so we need //to signal the query to be distinct. if ($modelAttributeToDataProviderAdapter->getRelationType() == RedBeanModel::HAS_MANY) { $joinTablesAdapter->setSelectDistinctToTrue(); } } elseif ($modelAttributeToDataProviderAdapter->getRelationType() == RedBeanModel::HAS_ONE_BELONGS_TO) { $tableJoinIdName = $onTableAliasName . '_id'; $onTableJoinIdName = 'id'; } else { $onTableJoinIdName = $modelAttributeToDataProviderAdapter->getColumnName(); $tableJoinIdName = 'id'; } $relationTableAliasName = $joinTablesAdapter->addLeftTableAndGetAliasName($modelAttributeToDataProviderAdapter->getRelationTableName(), $onTableJoinIdName, $onTableAliasName, $tableJoinIdName); $relationAttributeTableAliasName = $relationTableAliasName; //the second left join check being performed is if you //are in a contact filtering on related account email as an example. if ($modelAttributeToDataProviderAdapter->getRelatedAttributeModelClassName() != $modelAttributeToDataProviderAdapter->getRelationModelClassName()) { $relationAttributeTableName = $modelAttributeToDataProviderAdapter->getRelatedAttributeTableName(); //Handling special scenario for casted down Person. Todo: Automatically determine a //casted down scenario instead of specifically looking for Person. if ($modelAttributeToDataProviderAdapter->getRelatedAttributeModelClassName() == 'Person') { $onTableJoinIdName = "{$relationAttributeTableName}_id"; } elseif (get_parent_class($modelAttributeToDataProviderAdapter->getRelationModelClassName()) == $modelAttributeToDataProviderAdapter->getRelatedAttributeModelClassName()) { $onTableJoinIdName = "{$relationAttributeTableName}_id"; } else { $onTableJoinIdName = "{$modelAttributeToDataProviderAdapter->getRelatedAttributeColumnName()}" . "_{$relationAttributeTableName}_id"; } $relationAttributeTableAliasName = $joinTablesAdapter->addLeftTableAndGetAliasName($relationAttributeTableName, $onTableJoinIdName, $relationTableAliasName); } return $relationAttributeTableAliasName; }
/** * @param RedBeanModelAttributeToDataProviderAdapter $modelAttributeToDataProviderAdapter * @return string */ protected function resolvedModelClassName(RedBeanModelAttributeToDataProviderAdapter $modelAttributeToDataProviderAdapter) { if ($modelAttributeToDataProviderAdapter->hasRelatedAttribute()) { return $modelAttributeToDataProviderAdapter->getRelationModelClassName(); } else { return $modelAttributeToDataProviderAdapter->getModelClassName(); } }