/**
  * @see resolveAttributeIndexesByComponents
  * @param ComponentForReportForm $componentForm
  * @return array
  */
 protected static function resolveAttributeIndexesByComponent(ComponentForReportForm $componentForm)
 {
     $attributeIndexes = array();
     $modelClassName = $componentForm->getModelClassName();
     $moduleClassName = $componentForm->getModuleClassName();
     if (!$componentForm->hasRelatedData()) {
         static::resolveAttributeIndexes($modelClassName, $attributeIndexes);
     } else {
         $attributeIndexPrefix = null;
         foreach ($componentForm->attributeAndRelationData as $relationOrAttribute) {
             static::resolveAttributeIndexes($modelClassName, $attributeIndexes, $attributeIndexPrefix);
             $modelToReportAdapter = ModelRelationsAndAttributesToReportAdapter::make($moduleClassName, $modelClassName, $componentForm->getReportType());
             if ($modelToReportAdapter->isReportedOnAsARelation($relationOrAttribute)) {
                 $modelClassName = $modelToReportAdapter->getRelationModelClassName($relationOrAttribute);
                 $moduleClassName = $modelToReportAdapter->getRelationModuleClassName($relationOrAttribute);
                 $attributeIndexPrefix = $attributeIndexPrefix . $relationOrAttribute . FormModelUtil::RELATION_DELIMITER;
             }
         }
     }
     return $attributeIndexes;
 }
 /**
  * @return ModelRelationsAndAttributesToReportAdapter
  */
 protected function makeModelRelationsAndAttributesToReportAdapter()
 {
     return ModelRelationsAndAttributesToReportAdapter::make($this->filter->getResolvedAttributeModuleClassName(), $this->filter->getResolvedAttributeModelClassName(), $this->filter->getReportType());
 }
 /**
  * @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 array $attributeAndRelationData
  * @param $modelClassName
  * @return string $lastModelClassName
  */
 protected function resolvePenultimateModelClassNameFromData(array $attributeAndRelationData, $modelClassName)
 {
     assert(count($attributeAndRelationData) > 0);
     // Not Coding Standard
     array_pop($attributeAndRelationData);
     foreach ($attributeAndRelationData as $relationOrAttribute) {
         $lastModelClassName = $modelClassName;
         $modelToReportAdapter = ModelRelationsAndAttributesToReportAdapter::make($modelClassName::getModuleClassName(), $modelClassName, $this->reportType);
         if ($modelToReportAdapter->isReportedOnAsARelation($relationOrAttribute)) {
             $modelClassName = $modelToReportAdapter->getRelationModelClassName($relationOrAttribute);
         }
     }
     return $lastModelClassName;
 }
 public function actionGetAvailableSeriesAndRangesForChart($type, $id = null, $isBeingCopied = false)
 {
     $postData = PostUtil::getData();
     $savedReport = null;
     $report = null;
     $this->resolveSavedReportAndReportByPostData($postData, $savedReport, $report, $type, $id, (bool) $isBeingCopied);
     $moduleClassName = $report->getModuleClassName();
     $modelClassName = $moduleClassName::getPrimaryModelName();
     $modelToReportAdapter = ModelRelationsAndAttributesToReportAdapter::make($moduleClassName, $modelClassName, $report->getType());
     if (!$modelToReportAdapter instanceof ModelRelationsAndAttributesToSummationReportAdapter) {
         throw new NotSupportedException();
     }
     $seriesAttributesData = $modelToReportAdapter->getAttributesForChartSeries($report->getGroupBys(), $report->getDisplayAttributes());
     $rangeAttributesData = $modelToReportAdapter->getAttributesForChartRange($report->getDisplayAttributes());
     $dataAndLabels = array();
     $dataAndLabels['firstSeriesDataAndLabels'] = array('' => Zurmo::t('Core', '(None)'));
     $dataAndLabels['firstSeriesDataAndLabels'] = array_merge($dataAndLabels['firstSeriesDataAndLabels'], ReportUtil::makeDataAndLabelsForSeriesOrRange($seriesAttributesData));
     $dataAndLabels['firstRangeDataAndLabels'] = array('' => Zurmo::t('Core', '(None)'));
     $dataAndLabels['firstRangeDataAndLabels'] = array_merge($dataAndLabels['firstRangeDataAndLabels'], ReportUtil::makeDataAndLabelsForSeriesOrRange($rangeAttributesData));
     $dataAndLabels['secondSeriesDataAndLabels'] = array('' => Zurmo::t('Core', '(None)'));
     $dataAndLabels['secondSeriesDataAndLabels'] = array_merge($dataAndLabels['secondSeriesDataAndLabels'], ReportUtil::makeDataAndLabelsForSeriesOrRange($seriesAttributesData));
     $dataAndLabels['secondRangeDataAndLabels'] = array('' => Zurmo::t('Core', '(None)'));
     $dataAndLabels['secondRangeDataAndLabels'] = array_merge($dataAndLabels['secondRangeDataAndLabels'], ReportUtil::makeDataAndLabelsForSeriesOrRange($rangeAttributesData));
     echo CJSON::encode($dataAndLabels);
 }
 public function testGetFilterRulesByAttribute()
 {
     $model = new ReportModelTestItem();
     $rules = new ReportsTestReportRules();
     $adapter = new ModelRelationsAndAttributesToReportAdapter($model, $rules, Report::TYPE_ROWS_AND_COLUMNS);
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'string', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('string', 'value'));
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'boolean', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('boolean', 'value'));
     $exptected = array(array('value', 'type', 'type' => 'float'));
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('currencyValue', 'value'));
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'date', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('date', 'value'));
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'dateTime', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('dateTime', 'value'));
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'dropDown', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('dropDown', 'value'));
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'float', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('float', 'value'));
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'integer', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('integer', 'value'));
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'multiDropDown', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('multiDropDown', 'value'));
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'owner', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('owner', 'value'));
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'phone', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('phone', 'value'));
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'radioDropDown', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('radioDropDown', 'value'));
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'tagCloud', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('tagCloud', 'value'));
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'textArea', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('textArea', 'value'));
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'url', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('url', 'value'));
     $exptected = ModelAttributeRulesToDefaultValueMappingRuleUtil::getApplicableRulesByModelClassNameAndAttributeName(get_class($model), 'likeContactState', 'value', false, true, false);
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('likeContactState', 'value'));
     $model = new ReportModelTestItem12();
     $rules = new ReportsTestReportRules();
     $adapter = new ModelRelationsAndAttributesToReportAdapter($model, $rules, Report::TYPE_ROWS_AND_COLUMNS);
     $exptected = array(array('value', 'type', 'type' => 'string'));
     $this->assertEquals($exptected, $adapter->getFilterRulesByAttribute('emailAddress', 'value'));
 }
 /**
  * Sally cannot access notes, tasks, or contacts. User is always accessible regardless of right to access
  */
 public function testGetAllReportableRelationsAsANonElevatedUser()
 {
     Yii::app()->user->userModel = User::getByUsername('sally');
     $model = new Account();
     $rules = new AccountsReportRules();
     $report = new Report();
     $report->setType(Report::TYPE_ROWS_AND_COLUMNS);
     $report->setModuleClassName('AccountsModule');
     $adapter = new ModelRelationsAndAttributesToReportAdapter($model, $rules, $report->getType());
     $relations = $adapter->getSelectableRelationsData();
     $relations = $adapter->getSelectableRelationsDataResolvedForUserAccess(Yii::app()->user->userModel, $relations);
     $this->assertEquals(9, count($relations));
     $compareData = array('label' => 'Billing Address');
     $this->assertEquals($compareData, $relations['billingAddress']);
     $compareData = array('label' => 'Created By User');
     $this->assertEquals($compareData, $relations['createdByUser']);
     $compareData = array('label' => 'Meetings');
     $this->assertEquals($compareData, $relations['meetings']);
     $compareData = array('label' => 'Modified By User');
     $this->assertEquals($compareData, $relations['modifiedByUser']);
     $compareData = array('label' => 'Opportunities');
     $this->assertEquals($compareData, $relations['opportunities']);
     $compareData = array('label' => 'Owner');
     $this->assertEquals($compareData, $relations['owner']);
     $compareData = array('label' => 'Primary Email');
     $this->assertEquals($compareData, $relations['primaryEmail']);
     $compareData = array('label' => 'Shipping Address');
     $this->assertEquals($compareData, $relations['shippingAddress']);
     $compareData = array('label' => 'Secondary Email');
     $this->assertEquals($compareData, $relations['secondaryEmail']);
 }
 /**
  * @param ComponentForReportForm $componentForm
  * @return ModelRelationsAndAttributesToReportAdapter
  */
 protected static function makeModelToReportAdapterByComponentForm(ComponentForReportForm $componentForm)
 {
     return ModelRelationsAndAttributesToReportAdapter::make($componentForm->getResolvedAttributeModuleClassName(), $componentForm->getResolvedAttributeModelClassName(), $componentForm->getReportType());
 }
 /**
  * @depends testGetFilterValueElementType
  */
 public function testGetAvailableOperatorsType()
 {
     $model = new ReportModelTestItem();
     $rules = new ReportsTestReportRules();
     $adapter = new ModelRelationsAndAttributesToReportAdapter($model, $rules, Report::TYPE_ROWS_AND_COLUMNS);
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_STRING, $adapter->getAvailableOperatorsType('string'));
     $model = new ReportModelTestItem();
     $rules = new ReportsTestReportRules();
     $adapter = new ModelRelationsAndAttributesToReportAdapter($model, $rules, Report::TYPE_ROWS_AND_COLUMNS);
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_BOOLEAN, $adapter->getAvailableOperatorsType('boolean'));
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_NUMBER, $adapter->getAvailableOperatorsType('currencyValue'));
     $this->assertNull($adapter->getAvailableOperatorsType('date'));
     $this->assertNull($adapter->getAvailableOperatorsType('dateTime'));
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_DROPDOWN, $adapter->getAvailableOperatorsType('dropDown'));
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_NUMBER, $adapter->getAvailableOperatorsType('float'));
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_NUMBER, $adapter->getAvailableOperatorsType('integer'));
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_DROPDOWN, $adapter->getAvailableOperatorsType('multiDropDown'));
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_HAS_ONE, $adapter->getAvailableOperatorsType('owner__User'));
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_STRING, $adapter->getAvailableOperatorsType('phone'));
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_DROPDOWN, $adapter->getAvailableOperatorsType('radioDropDown'));
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_STRING, $adapter->getAvailableOperatorsType('string'));
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_DROPDOWN, $adapter->getAvailableOperatorsType('tagCloud'));
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_STRING, $adapter->getAvailableOperatorsType('textArea'));
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_STRING, $adapter->getAvailableOperatorsType('url'));
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_DROPDOWN, $adapter->getAvailableOperatorsType('likeContactState'));
     $model = new ReportModelTestItem();
     $rules = new ReportsAlternateStateTestReportRules();
     $adapter = new ModelRelationsAndAttributesToReportAdapter($model, $rules, Report::TYPE_ROWS_AND_COLUMNS);
     $this->assertEquals(ModelAttributeToReportOperatorTypeUtil::AVAILABLE_OPERATORS_TYPE_DROPDOWN, $adapter->getAvailableOperatorsType('likeContactState'));
 }
 /**
  * @param string $nodeId
  * @param ModelRelationsAndAttributesToReportAdapter $modelToReportAdapter
  * @param RedBeanModel $precedingModel
  * @param string $precedingRelation
  */
 protected function resolvePrecedingModelRelationAndAdapterByNodeId($nodeId, &$modelToReportAdapter, &$precedingModel, &$precedingRelation)
 {
     assert('$modelToReportAdapter instanceof ModelRelationsAndAttributesToReportAdapter');
     if ($nodeId == 'source') {
         return;
     }
     $relations = explode(FormModelUtil::RELATION_DELIMITER, $nodeId);
     $lastRelation = end($relations);
     foreach ($relations as $relation) {
         $relationModelClassName = $modelToReportAdapter->getRelationModelClassName($relation);
         $precedingRelation = $relation;
         if ($relation != $lastRelation) {
             $precedingModel = new $relationModelClassName(false);
         } elseif (count($relations) == 1) {
             $precedingModel = $modelToReportAdapter->getModel();
         }
         $modelToReportAdapter = $this->makeModelRelationsAndAttributesToReportAdapter($relationModelClassName::getModuleClassName(), $relationModelClassName);
     }
 }
 /**
  * Resolves for a given component whether the user has necessary rights to access the component information.
  * An example is if a component is account's opportunities and the current user cannot access the opportunities
  * module.
  * @param ComponentForReportForm $componentForm
  * @return bool
  */
 protected static function canCurrentUserAccessComponent(ComponentForReportForm $componentForm)
 {
     $modelClassName = $componentForm->getModelClassName();
     $moduleClassName = $componentForm->getModuleClassName();
     if (!$componentForm->hasRelatedData()) {
         return self::canCurrentUserCanAccessModule($moduleClassName);
     } else {
         foreach ($componentForm->attributeAndRelationData as $relationOrAttribute) {
             if (!self::canCurrentUserCanAccessModule($moduleClassName)) {
                 return false;
             }
             $modelToReportAdapter = ModelRelationsAndAttributesToReportAdapter::make($moduleClassName, $modelClassName, $componentForm->getReportType());
             if ($modelToReportAdapter->isReportedOnAsARelation($relationOrAttribute)) {
                 $modelClassName = $modelToReportAdapter->getRelationModelClassName($relationOrAttribute);
                 $moduleClassName = $modelToReportAdapter->getRelationModuleClassName($relationOrAttribute);
             }
         }
         return true;
     }
 }
 /**
  * @param string $attribute
  * @return string
  * @throws NotSupportedException if the attribute is an invalid display calculation
  */
 public function getDisplayElementType($attribute)
 {
     assert('is_string($attribute)');
     if ($this->isAttributeIndexOrDerivedTypeADisplayCalculation($attribute)) {
         if ($attribute == self::DISPLAY_CALCULATION_COUNT) {
             return 'Integer';
         }
         list($realAttribute, $notUsed) = explode(FormModelUtil::DELIMITER, $attribute);
         $attributeType = ModelAttributeToMixedTypeUtil::getType($this->model, $realAttribute);
         if ($attributeType == 'Decimal' || $attributeType == 'Integer') {
             return 'Decimal';
         } elseif ($attributeType == 'Date') {
             return 'Date';
         } elseif ($attributeType == 'DateTime') {
             return 'DateTime';
         } elseif ($this->model->isRelation($realAttribute) && $this->model->getRelationModelClassName($realAttribute) == 'CurrencyValue') {
             return 'CalculatedCurrencyValue';
         } else {
             throw new NotSupportedException();
         }
     } elseif ($this->isAttributeACalculatedGroupByModifier($attribute) && $this->getGroupByCalculationTypeByAttribute($attribute) == self::GROUP_BY_CALCULATION_MONTH) {
         return 'GroupByModifierMonth';
     } elseif ($this->isAttributeACalculatedGroupByModifier($attribute)) {
         return 'Text';
     }
     return parent::getDisplayElementType($attribute);
 }
 public static function forgetAll()
 {
     self::$derivedAttributesData = null;
     self::$attributesNotIncludingDerivedAttributesData = null;
     self::$inferredRelationsData = null;
     self::$dynamicallyDerivedAttributesData = null;
 }