/**
  * @return string
  * @throws NotSupportedException
  */
 protected function resolveComponentAttributeStringContentForNestedAttribute()
 {
     $attributeAndRelationData = $this->componentForm->getAttributeAndRelationData();
     $count = 0;
     $moduleClassName = $this->componentForm->getModuleClassName();
     $modelClassName = $this->componentForm->getModelClassName();
     $onTableAliasName = null;
     $startingModelClassName = null;
     foreach ($attributeAndRelationData as $key => $relationOrAttribute) {
         $modelToReportAdapter = ModelRelationsAndAttributesToReportAdapter::make($moduleClassName, $modelClassName, $this->componentForm->getReportType());
         $modelAttributeToDataProviderAdapter = $this->makeModelAttributeToDataProviderAdapter($modelToReportAdapter, $relationOrAttribute);
         if ($this->shouldPrematurelyStopBuildingJoinsForAttribute($modelToReportAdapter, $modelAttributeToDataProviderAdapter)) {
             $attribute = 'id';
             $modelAttributeToDataProviderAdapter = $this->makeModelAttributeToDataProviderAdapter($modelToReportAdapter, $attribute);
             break;
         } elseif ($modelToReportAdapter->isReportedOnAsARelation($relationOrAttribute)) {
             $modelClassName = $modelToReportAdapter->getRelationModelClassName($relationOrAttribute);
             $moduleClassName = $modelToReportAdapter->getRelationModuleClassName($relationOrAttribute);
             if ($modelToReportAdapter->isInferredRelation($relationOrAttribute) || $modelToReportAdapter->isDerivedRelationsViaCastedUpModelRelation($relationOrAttribute)) {
                 static::resolveCastingHintForAttribute($modelToReportAdapter, $modelAttributeToDataProviderAdapter, $modelClassName, $modelToReportAdapter->resolveRealAttributeName($attributeAndRelationData[$key + 1]));
             }
             $modelAttributeToDataProviderAdapter->setCastingHintStartingModelClassName($startingModelClassName);
             $builder = new ModelJoinBuilder($modelAttributeToDataProviderAdapter, $this->joinTablesAdapter);
             $onTableAliasName = $builder->resolveJoins($onTableAliasName, ModelDataProviderUtil::resolveCanUseFromJoins($onTableAliasName));
             $startingModelClassName = $modelAttributeToDataProviderAdapter->getCastingHintModelClassNameForAttribute();
         } else {
             if ($count + 1 != count($attributeAndRelationData)) {
                 throw new NotSupportedException('The final element in array must be an attribute, not a relation');
             }
         }
         $count++;
     }
     $modelAttributeToDataProviderAdapter->setCastingHintStartingModelClassName($startingModelClassName);
     return $this->resolveFinalContent($modelAttributeToDataProviderAdapter, $onTableAliasName);
 }
 /**
  * @param User $user
  * @param RedBeanModelJoinTablesQueryAdapter $joinTablesAdapter
  * @param $where
  * @param $selectDistinct
  * @throws NotSupportedException
  */
 public static function resolveReadPermissionsOptimizationToSqlQuery(User $user, RedBeanModelJoinTablesQueryAdapter $joinTablesAdapter, &$where, &$selectDistinct)
 {
     assert('$where == null || is_string($where)');
     assert('is_bool($selectDistinct)');
     $modelClassName = get_called_class();
     $moduleClassName = $modelClassName::getModuleClassName();
     //Currently only adds munge if the module is securable and this model supports it.
     if (static::hasReadPermissionsOptimization() && $moduleClassName != null && is_subclass_of($moduleClassName, 'SecurableModule')) {
         $permission = PermissionsUtil::getActualPermissionDataForReadByModuleNameForUser($moduleClassName);
         if (($permission == Permission::NONE || $permission == Permission::DENY) && !static::bypassReadPermissionsOptimizationToSqlQueryBasedOnWhere($where)) {
             $quote = DatabaseCompatibilityUtil::getQuote();
             $modelAttributeToDataProviderAdapter = new OwnedSecurableItemIdToDataProviderAdapter($modelClassName, null);
             $builder = new ModelJoinBuilder($modelAttributeToDataProviderAdapter, $joinTablesAdapter);
             $ownedTableAliasName = $builder->resolveJoins();
             $ownerColumnName = static::getForeignKeyName('OwnedSecurableItem', 'owner');
             $mungeIds = AllPermissionsOptimizationUtil::getMungeIdsByUser($user);
             if ($where != null) {
                 $where = '(' . $where . ') and ';
             }
             if (count($mungeIds) > 0 && $permission == Permission::NONE) {
                 $extraOnQueryPart = " and {$quote}munge_id{$quote} in ('" . join("', '", $mungeIds) . "')";
                 $mungeTableName = ReadPermissionsOptimizationUtil::getMungeTableName($modelClassName);
                 $mungeTableAliasName = $joinTablesAdapter->addLeftTableAndGetAliasName($mungeTableName, 'securableitem_id', $ownedTableAliasName, 'securableitem_id', $extraOnQueryPart);
                 $where .= "({$quote}{$ownedTableAliasName}{$quote}.{$quote}{$ownerColumnName}{$quote} = {$user->id} OR ";
                 // Not Coding Standard
                 $where .= "{$quote}{$mungeTableName}{$quote}.{$quote}munge_id{$quote} IS NOT NULL)";
                 // Not Coding Standard
                 $selectDistinct = true;
                 //must use distinct since adding munge table query.
             } elseif ($permission == Permission::DENY) {
                 $where .= "{$quote}{$ownedTableAliasName}{$quote}.{$quote}{$ownerColumnName}{$quote} = {$user->id}";
                 // Not Coding Standard
             } else {
                 throw new NotSupportedException();
             }
         }
     }
 }
 /**
  * Add a sql string to the where array base on the $operatorType, $value and $tableAliasAndColumnNames concated
  * together.  How the sql string is built depends on if the value is a string or not.
  * @param string $operatorType
  * @param mixed $value
  * @param array $where
  * @param integer $whereKey
  * @param array $tableAliasAndColumnNames
  */
 protected static function addWherePartByClauseInformationForConcatedAttributes($operatorType, $value, &$where, $whereKey, $tableAliasAndColumnNames)
 {
     assert('is_string($operatorType)');
     assert('is_array($where)');
     assert('is_int($whereKey)');
     assert('is_array($tableAliasAndColumnNames) && count($tableAliasAndColumnNames) == 2');
     $quote = DatabaseCompatibilityUtil::getQuote();
     if (is_string($value) || is_array($value) && count($value) > 0 || $value !== null) {
         $first = ModelJoinBuilder::makeColumnNameWithTableAlias($tableAliasAndColumnNames[0][0], $tableAliasAndColumnNames[0][1]);
         $second = ModelJoinBuilder::makeColumnNameWithTableAlias($tableAliasAndColumnNames[1][0], $tableAliasAndColumnNames[1][1]);
         $concatedSqlPart = DatabaseCompatibilityUtil::concat(array($first, '\' \'', $second));
         $where[$whereKey] = "({$concatedSqlPart} " . DatabaseCompatibilityUtil::getOperatorAndValueWherePart($operatorType, $value) . ")";
     }
 }
 /**
  * @param RedBeanModelAttributeToDataProviderAdapter $modelAttributeToDataProviderAdapter
  * @param ModelJoinBuilder $builder
  * @return string
  */
 protected function resolvedTableAliasName(RedBeanModelAttributeToDataProviderAdapter $modelAttributeToDataProviderAdapter, ModelJoinBuilder $builder)
 {
     if ($modelAttributeToDataProviderAdapter->hasRelatedAttribute()) {
         return $builder->getTableAliasNameForRelatedModel();
     } else {
         return $builder->getTableAliasNameForBaseModel();
     }
 }
 /**
  * @param RedBeanModelAttributeToDataProviderAdapter $modelAttributeToDataProviderAdapter
  * @param null | string $onTableAliasName
  * @return string
  */
 protected function resolveSortAttributeContent(RedBeanModelAttributeToDataProviderAdapter $modelAttributeToDataProviderAdapter, $onTableAliasName = null)
 {
     assert('is_string($onTableAliasName) || $onTableAliasName == null');
     $builder = new ModelJoinBuilder($modelAttributeToDataProviderAdapter, $this->joinTablesAdapter);
     $tableAliasName = $builder->resolveJoins($onTableAliasName, ModelDataProviderUtil::resolveCanUseFromJoins($onTableAliasName));
     $resolvedSortColumnName = self::resolveSortColumnName($modelAttributeToDataProviderAdapter);
     $queryStringExtraPart = $this->getAttributeClauseQueryStringExtraPart($tableAliasName);
     return $this->resolveOrderByString($tableAliasName, $resolvedSortColumnName, $queryStringExtraPart);
 }
 public function __construct(RedBeanModelAttributeToDataProviderAdapter $modelAttributeToDataProviderAdapter, RedBeanModelJoinTablesQueryAdapter $joinTablesAdapter, $setDistinct = false, $wherePartColumnModifierType = null)
 {
     assert('is_string($wherePartColumnModifierType) || $wherePartColumnModifierType == null');
     parent::__construct($modelAttributeToDataProviderAdapter, $joinTablesAdapter, $setDistinct);
     $this->wherePartColumnModifierType = $wherePartColumnModifierType;
 }