function GetOperationPerm($type, $id, $feature, $operation)
 {
     global $arSocNetAllowedEntityTypes;
     $arSocNetFeaturesSettings = CSocNetAllowed::GetAllowedFeatures();
     $type = Trim($type);
     if (StrLen($type) <= 0 || !in_array($type, $arSocNetAllowedEntityTypes)) {
         $GLOBALS["APPLICATION"]->ThrowException(GetMessage("SONET_GF_ERROR_NO_ENTITY_TYPE"), "ERROR_EMPTY_TYPE");
         if (is_array($id)) {
             $arReturn = array();
             foreach ($id as $TmpGroupID) {
                 $arReturn[$TmpGroupID] = false;
             }
             return $arReturn;
         } else {
             return false;
         }
     }
     $feature = StrToLower(Trim($feature));
     if (StrLen($feature) <= 0) {
         $GLOBALS["APPLICATION"]->ThrowException(GetMessage("SONET_GF_EMPTY_FEATURE_ID"), "ERROR_EMPTY_FEATURE_ID");
         if (is_array($id)) {
             $arReturn = array();
             foreach ($id as $TmpGroupID) {
                 $arReturn[$TmpGroupID] = false;
             }
             return $arReturn;
         } else {
             return false;
         }
     }
     if (!array_key_exists($feature, $arSocNetFeaturesSettings) || !array_key_exists("allowed", $arSocNetFeaturesSettings[$feature]) || !in_array($type, $arSocNetFeaturesSettings[$feature]["allowed"])) {
         $GLOBALS["APPLICATION"]->ThrowException(GetMessage("SONET_GF_ERROR_NO_FEATURE_ID"), "ERROR_NO_FEATURE_ID");
         if (is_array($id)) {
             $arReturn = array();
             foreach ($id as $TmpGroupID) {
                 $arReturn[$TmpGroupID] = false;
             }
             return $arReturn;
         } else {
             return false;
         }
     }
     $operation = StrToLower(Trim($operation));
     if (!array_key_exists("operations", $arSocNetFeaturesSettings[$feature]) || !array_key_exists($operation, $arSocNetFeaturesSettings[$feature]["operations"])) {
         if (is_array($id)) {
             $arReturn = array();
             foreach ($id as $TmpGroupID) {
                 $arReturn[$TmpGroupID] = false;
             }
             return $arReturn;
         } else {
             return false;
         }
     }
     global $arSonetFeaturesPermsCache;
     if (!isset($arSonetFeaturesPermsCache) || !is_array($arSonetFeaturesPermsCache)) {
         $arSonetFeaturesPermsCache = array();
     }
     if (is_array($id)) {
         $arFeaturesPerms = array();
         $arGroupToGet = array();
         foreach ($id as $TmpGroupID) {
             $arFeaturesPerms[$TmpGroupID] = array();
             if (!array_key_exists($type . "_" . $TmpGroupID, $arSonetFeaturesPermsCache)) {
                 $arGroupToGet[] = $TmpGroupID;
             } else {
                 $arFeaturesPerms[$TmpGroupID] = $arSonetFeaturesPermsCache[$type . "_" . $TmpGroupID];
             }
         }
         if (!empty($arGroupToGet)) {
             $dbResult = CSocNetFeaturesPerms::GetList(array(), array("FEATURE_ENTITY_ID" => $arGroupToGet, "FEATURE_ENTITY_TYPE" => $type, "GROUP_FEATURE_ACTIVE" => "Y"), false, false, array("OPERATION_ID", "FEATURE_ENTITY_ID", "FEATURE_FEATURE", "ROLE"));
             while ($arResult = $dbResult->Fetch()) {
                 if (!array_key_exists($arResult["FEATURE_ENTITY_ID"], $arFeaturesPerms) || !array_key_exists($arResult["FEATURE_FEATURE"], $arFeaturesPerms[$arResult["FEATURE_ENTITY_ID"]])) {
                     $arFeaturesPerms[$arResult["FEATURE_ENTITY_ID"]][$arResult["FEATURE_FEATURE"]] = array();
                 }
                 $arFeaturesPerms[$arResult["FEATURE_ENTITY_ID"]][$arResult["FEATURE_FEATURE"]][$arResult["OPERATION_ID"]] = $arResult["ROLE"];
             }
         }
         $arReturn = array();
         foreach ($id as $TmpEntityID) {
             $arSonetFeaturesPermsCache[$type . "_" . $TmpGroupID] = $arFeaturesPerms[$TmpEntityID];
             if ($type == SONET_ENTITY_GROUP) {
                 if (!array_key_exists($feature, $arFeaturesPerms[$TmpEntityID])) {
                     $featureOperationPerms = $arSocNetFeaturesSettings[$feature]["operations"][$operation][SONET_ENTITY_GROUP];
                 } elseif (!array_key_exists($operation, $arFeaturesPerms[$TmpEntityID][$feature])) {
                     $featureOperationPerms = $arSocNetFeaturesSettings[$feature]["operations"][$operation][SONET_ENTITY_GROUP];
                 } else {
                     $featureOperationPerms = $arFeaturesPerms[$TmpEntityID][$feature][$operation];
                 }
             } else {
                 if (!array_key_exists($feature, $arFeaturesPerms[$TmpEntityID])) {
                     $featureOperationPerms = $arSocNetFeaturesSettings[$feature]["operations"][$operation][SONET_ENTITY_USER];
                 } elseif (!array_key_exists($operation, $arFeaturesPerms[$TmpEntityID][$feature])) {
                     $featureOperationPerms = $arSocNetFeaturesSettings[$feature]["operations"][$operation][SONET_ENTITY_USER];
                 } else {
                     $featureOperationPerms = $arFeaturesPerms[$TmpEntityID][$feature][$operation];
                 }
                 if ($featureOperationPerms == SONET_RELATIONS_TYPE_FRIENDS2) {
                     $featureOperationPerms = SONET_RELATIONS_TYPE_FRIENDS;
                 }
             }
             $arReturn[$TmpEntityID] = $featureOperationPerms;
         }
         return $arReturn;
     } else {
         $id = IntVal($id);
         if ($id <= 0) {
             $GLOBALS["APPLICATION"]->ThrowException(GetMessage("SONET_GF_EMPTY_ENTITY_ID"), "ERROR_EMPTY_ENTITY_ID");
             return false;
         }
         $arFeaturesPerms = array();
         if (array_key_exists($type . "_" . $id, $arSonetFeaturesPermsCache)) {
             $arFeaturesPerms = $arSonetFeaturesPermsCache[$type . "_" . $id];
         } else {
             $cache = new CPHPCache();
             $cache_time = 31536000;
             $cache_id = "entity_" . "_" . $type . "_" . $id;
             $cache_path = "/sonet/features_perms/" . $type . "_" . $id . "/";
             $arTmp = array();
             if ($cache->InitCache($cache_time, $cache_id, $cache_path)) {
                 $arCacheVars = $cache->GetVars();
                 $arTmp = $arCacheVars["RESULT"];
             } else {
                 $cache->StartDataCache($cache_time, $cache_id, $cache_path);
                 if (defined("BX_COMP_MANAGED_CACHE")) {
                     $GLOBALS["CACHE_MANAGER"]->StartTagCache($cache_path);
                 }
                 $dbResult = CSocNetFeaturesPerms::GetList(array(), array("FEATURE_ENTITY_ID" => $id, "FEATURE_ENTITY_TYPE" => $type, "GROUP_FEATURE_ACTIVE" => "Y"), false, false, array("ID", "OPERATION_ID", "FEATURE_ID", "FEATURE_FEATURE", "ROLE"));
                 while ($arResult = $dbResult->Fetch()) {
                     if (defined("BX_COMP_MANAGED_CACHE")) {
                         $GLOBALS["CACHE_MANAGER"]->RegisterTag("sonet_features2perms_" . $arResult["ID"]);
                     }
                     $arTmp[] = $arResult;
                 }
                 if (defined("BX_COMP_MANAGED_CACHE")) {
                     $dbResult = CSocNetFeatures::GetList(array(), array("ENTITY_ID" => $id, "ENTITY_TYPE" => $type), false, false, array("ID"));
                     while ($arResult = $dbResult->Fetch()) {
                         $GLOBALS["CACHE_MANAGER"]->RegisterTag("sonet_feature_" . $arResult["ID"]);
                     }
                 }
                 if (defined("BX_COMP_MANAGED_CACHE")) {
                     if ($type == SONET_ENTITY_GROUP) {
                         $GLOBALS["CACHE_MANAGER"]->RegisterTag("sonet_group_" . $id);
                         $GLOBALS["CACHE_MANAGER"]->RegisterTag("sonet_group");
                     } elseif ($type == SONET_ENTITY_USER) {
                         $GLOBALS["CACHE_MANAGER"]->RegisterTag("USER_CARD_" . intval($id / TAGGED_user_card_size));
                     }
                     $GLOBALS["CACHE_MANAGER"]->RegisterTag("sonet_features_" . $type . "_" . $id);
                 }
                 $arCacheData = array("RESULT" => $arTmp);
                 if (defined("BX_COMP_MANAGED_CACHE")) {
                     $GLOBALS["CACHE_MANAGER"]->EndTagCache();
                 }
                 $cache->EndDataCache($arCacheData);
             }
             foreach ($arTmp as $arResult) {
                 if (!array_key_exists($arResult["FEATURE_FEATURE"], $arFeaturesPerms)) {
                     $arFeaturesPerms[$arResult["FEATURE_FEATURE"]] = array();
                 }
                 $arFeaturesPerms[$arResult["FEATURE_FEATURE"]][$arResult["OPERATION_ID"]] = $arResult["ROLE"];
             }
             $arSonetFeaturesPermsCache[$type . "_" . $id] = $arFeaturesPerms;
         }
         if ($type == SONET_ENTITY_GROUP) {
             if (!array_key_exists($feature, $arFeaturesPerms)) {
                 $featureOperationPerms = $arSocNetFeaturesSettings[$feature]["operations"][$operation][SONET_ENTITY_GROUP];
             } elseif (!array_key_exists($operation, $arFeaturesPerms[$feature])) {
                 $featureOperationPerms = $arSocNetFeaturesSettings[$feature]["operations"][$operation][SONET_ENTITY_GROUP];
             } else {
                 $featureOperationPerms = $arFeaturesPerms[$feature][$operation];
             }
         } else {
             if (!array_key_exists($feature, $arFeaturesPerms)) {
                 $featureOperationPerms = $arSocNetFeaturesSettings[$feature]["operations"][$operation][SONET_ENTITY_USER];
             } elseif (!array_key_exists($operation, $arFeaturesPerms[$feature])) {
                 $featureOperationPerms = $arSocNetFeaturesSettings[$feature]["operations"][$operation][SONET_ENTITY_USER];
             } else {
                 $featureOperationPerms = $arFeaturesPerms[$feature][$operation];
             }
             if ($featureOperationPerms == SONET_RELATIONS_TYPE_FRIENDS2) {
                 $featureOperationPerms = SONET_RELATIONS_TYPE_FRIENDS;
             }
         }
         return $featureOperationPerms;
     }
 }