public function testIsSpecialMergeTag()
 {
     $this->assertFalse(SpecialMergeTagsAdapter::isSpecialMergeTag('attribute', null));
     $this->assertFalse(SpecialMergeTagsAdapter::isSpecialMergeTag('attribute', 'something'));
     $this->assertFalse(SpecialMergeTagsAdapter::isSpecialMergeTag('modelURl', null));
     $this->assertFalse(SpecialMergeTagsAdapter::isSpecialMergeTag('modelURl', 'something'));
     $this->assertTrue(SpecialMergeTagsAdapter::isSpecialMergeTag('modelUrl', null));
     $this->assertFalse(SpecialMergeTagsAdapter::isSpecialMergeTag('modelUrl', 'something'));
 }
 protected static function resolveMergeTagToStandardOrRelatedAttribute($attributeAccessorString, $model, $language, $timeQualifier)
 {
     $attributeName = strtok($attributeAccessorString, '->');
     if (SpecialMergeTagsAdapter::isSpecialMergeTag($attributeName, $timeQualifier)) {
         return SpecialMergeTagsAdapter::resolve($attributeName, $model);
     } else {
         if (!$model->isAttribute($attributeName)) {
             return static::PROPERTY_NOT_FOUND;
         } elseif ($model->{$attributeName} instanceof CustomField) {
             $value = static::getAttributeValue($model->{$attributeName}, 'value', $timeQualifier);
             // TODO: @Shoaibi/@Jason: Low: need to apply localizations(Date/time/currency formats, ...) here besides translation
             if ($value) {
                 $value = Zurmo::t($model::getModuleClassName(), $value, array(), null, $language);
             }
             return $value;
         } elseif ($model->isRelation($attributeName)) {
             $model = $model->{$attributeName};
             if ($attributeName === $attributeAccessorString) {
                 $attributeAccessorString = null;
             } else {
                 $attributeAccessorString = str_replace($attributeName . '->', '', $attributeAccessorString);
             }
             if (empty($attributeAccessorString)) {
                 // If a user specific a relation merge tag but not a property, we assume he meant "value" property.
                 if (empty($timeQualifier)) {
                     return strval($model);
                 } else {
                     return static::PROPERTY_NOT_FOUND;
                 }
             }
             return static::resolveMergeTagToStandardOrRelatedAttribute($attributeAccessorString, $model, $language, $timeQualifier);
         } else {
             if ($attributeName === $attributeAccessorString) {
                 return static::getAttributeValue($model, $attributeName, $timeQualifier);
             } else {
                 return static::PROPERTY_NOT_FOUND;
             }
         }
     }
 }
 protected static function resolveMergeTagToStandardOrRelatedAttribute($attributeAccessorString, $model, $language, $timeQualifier, $errorOnFirstMissing, $params)
 {
     $attributeName = strtok($attributeAccessorString, '->');
     if (SpecialMergeTagsAdapter::isSpecialMergeTag($attributeName, $timeQualifier)) {
         return SpecialMergeTagsAdapter::resolve($attributeName, $model, $errorOnFirstMissing, $params);
     } else {
         if (!isset($model)) {
             return static::PROPERTY_NOT_FOUND;
         } elseif (!method_exists($model, 'isAttribute') || !$model->isAttribute($attributeName)) {
             if ($model instanceof Activity) {
                 $metadata = $model::getMetadata();
                 $activityItemsModelClassNamesData = $metadata['Activity']['activityItemsModelClassNames'];
                 foreach ($model->activityItems as $activityItem) {
                     if (ucfirst($attributeName) == get_class($activityItem)) {
                         $attributeAccessorString = str_replace($attributeName . '->', '', $attributeAccessorString);
                         return static::resolveMergeTagToStandardOrRelatedAttribute($attributeAccessorString, $activityItem, $language, $timeQualifier, $errorOnFirstMissing, $params);
                     }
                     if (get_class($activityItem) == 'Item' && array_search(ucfirst($attributeName), $activityItemsModelClassNamesData) !== false) {
                         try {
                             $modelDerivationPathToItem = RuntimeUtil::getModelDerivationPathToItem(ucfirst($attributeName));
                             $castedDownModel = $activityItem->castDown(array($modelDerivationPathToItem));
                             if (ucfirst($attributeName) == get_class($castedDownModel)) {
                                 $attributeAccessorString = str_replace($attributeName . '->', '', $attributeAccessorString);
                                 return static::resolveMergeTagToStandardOrRelatedAttribute($attributeAccessorString, $castedDownModel, $language, $timeQualifier, $errorOnFirstMissing, $params);
                             }
                         } catch (NotFoundException $e) {
                             //Do nothing
                         }
                     }
                     unset($activityItemsModelClassNamesData[get_class($activityItem)]);
                 }
                 foreach ($activityItemsModelClassNamesData as $relationModelClassName) {
                     if (ucfirst($attributeName) == $relationModelClassName) {
                         $model = new $relationModelClassName();
                         $attributeAccessorString = str_replace($attributeName . '->', '', $attributeAccessorString);
                         return static::resolveMergeTagToStandardOrRelatedAttribute($attributeAccessorString, $model, $language, $timeQualifier, $errorOnFirstMissing, $params);
                     }
                 }
             }
             return static::PROPERTY_NOT_FOUND;
         } elseif ($model->{$attributeName} instanceof CurrencyValue) {
             $model = $model->{$attributeName};
             if ($attributeName === $attributeAccessorString) {
                 $attributeAccessorString = null;
             } else {
                 $attributeAccessorString = str_replace($attributeName . '->', '', $attributeAccessorString);
             }
             if (empty($attributeAccessorString)) {
                 // If a user specific a relation merge tag but not a property, we assume he meant "value" property.
                 $currencyValueModel = $model;
                 $value = static::getAttributeValue($currencyValueModel, 'value', $timeQualifier);
                 return CLocale::getInstance($language)->getCurrencySymbol($currencyValueModel->currency->code) . $value;
                 // We can't use code below because it converts integer values in flat and also add slashes to '.' in float numbers
                 //return Yii::app()->numberFormatter->formatCurrency($value,
                 //    $currencyValueModel->currency->code);
             }
             return static::resolveMergeTagToStandardOrRelatedAttribute($attributeAccessorString, $model, $language, $timeQualifier, $errorOnFirstMissing, $params);
         } elseif ($model->{$attributeName} instanceof CustomField) {
             $value = static::getAttributeValue($model->{$attributeName}, 'value', $timeQualifier);
             // TODO: @Shoaibi/@Jason: Low: need to apply localizations(Date/time/currency formats, ...) here besides translation
             if ($value) {
                 $value = Zurmo::t($model::getModuleClassName(), $value, array(), null, $language);
             }
             return $value;
         } elseif ($model->isRelation($attributeName)) {
             $model = $model->{$attributeName};
             if ($attributeName === $attributeAccessorString) {
                 $attributeAccessorString = null;
             } else {
                 $attributeAccessorString = str_replace($attributeName . '->', '', $attributeAccessorString);
             }
             if (empty($attributeAccessorString)) {
                 // If a user specific a relation merge tag but not a property, we assume he meant "value" property.
                 if (empty($timeQualifier)) {
                     return strval($model);
                 } else {
                     return static::PROPERTY_NOT_FOUND;
                 }
             }
             if ($model instanceof RedBeanModels) {
                 $modelClassName = $model->getModelClassName();
                 if ($attributeAccessorString == lcfirst($modelClassName)) {
                     $values = array();
                     foreach ($model as $relatedModel) {
                         $values[] = strval($relatedModel);
                     }
                     return ArrayUtil::stringify($values);
                 }
             }
             return static::resolveMergeTagToStandardOrRelatedAttribute($attributeAccessorString, $model, $language, $timeQualifier, $errorOnFirstMissing, $params);
         } else {
             $attributeType = ModelAttributeToMixedTypeUtil::getType($model, $attributeName);
             //We don't have any accessor operator after the attributeName e.g. its the last in list
             if ($attributeName === $attributeAccessorString) {
                 $content = static::getAttributeValue($model, $attributeName, $timeQualifier);
                 if ($attributeType == 'DateTime') {
                     $content .= ' GMT';
                 }
                 return $content;
             } else {
                 return static::PROPERTY_NOT_FOUND;
             }
         }
     }
 }