Your IP : 172.70.80.238


Current Path : /var/www/element/data/www/revenuestory.ru/bitrix/modules/main/classes/general/
Upload File :
Current File : /var/www/element/data/www/revenuestory.ru/bitrix/modules/main/classes/general/access.php

<?php
/**
 * Bitrix Framework
 * @package bitrix
 * @subpackage main
 * @copyright 2001-2013 Bitrix
 */

use Bitrix\Main;

IncludeModuleLangFile(__FILE__);

class CAccess
{
	const CACHE_DIR = "access_check";

	protected static $arAuthProviders = [];
	protected static $arChecked = [];
	protected $arParams = false;

	public function __construct($arParams=false)
	{
		$this->arParams = $arParams;

		if(empty(static::$arAuthProviders))
		{
			foreach(GetModuleEvents("main", "OnAuthProvidersBuildList", true) as $arEvent)
			{
				$res = ExecuteModuleEventEx($arEvent);
				if(is_array($res))
				{
					if(!is_array($res[0]))
						$res = array($res);
					foreach($res as $provider)
						static::$arAuthProviders[$provider["ID"]] = $provider;
				}
			}
			sortByColumn(static::$arAuthProviders, "SORT");
		}
	}

	protected static function NeedToRecalculate($provider, $USER_ID)
	{
		global $DB, $CACHE_MANAGER;

		$USER_ID = intval($USER_ID);

		if(!isset(static::$arChecked[$provider][$USER_ID]))
		{
			$cacheId = static::GetCheckCacheId($provider, $USER_ID);

			if (CACHED_b_user_access_check !== false && $CACHE_MANAGER->Read(CACHED_b_user_access_check, $cacheId, static::CACHE_DIR))
			{
				static::$arChecked[$provider][$USER_ID] = $CACHE_MANAGER->Get($cacheId);
			}
			else
			{
				$res = $DB->Query("
					select 'x'
					from b_user_access_check
					where USER_ID = ".$USER_ID."
						and PROVIDER_ID = '".$DB->ForSql($provider)."'
				");

				static::$arChecked[$provider][$USER_ID] = ($res->Fetch()? true : false);

				if (CACHED_b_user_access_check !== false)
				{
					$CACHE_MANAGER->Set($cacheId, static::$arChecked[$provider][$USER_ID]);
				}
			}
		}

		return (static::$arChecked[$provider][$USER_ID]);
	}

	public function UpdateCodes($arParams=false)
	{
		global $USER;

		$USER_ID = 0;
		if(is_array($arParams) && isset($arParams["USER_ID"]))
			$USER_ID = intval($arParams["USER_ID"]);
		elseif(is_object($USER) && $USER->IsAuthorized())
			$USER_ID = intval($USER->GetID());

		if($USER_ID > 0)
		{
			$connection = \Bitrix\Main\Application::getConnection();
			$clearCache = false;

			foreach (static::$arAuthProviders as $providerId => $providerDescription)
			{
				/** @var CGroupAuthProvider $provider For example*/
				$provider = new $providerDescription["CLASS"];

				if(is_callable([$provider, "UpdateCodes"]))
				{
					//do we need to recalculate codes for the user?
					if(static::NeedToRecalculate($providerId, $USER_ID))
					{
						$name = "access.{$providerId}.{$USER_ID}";

						if($connection->lock($name))
						{
							//should clear codes cache for the user
							$clearCache = true;

							//remove old codes
							static::DeleteCodes($providerId, $USER_ID);

							//call provider to insert access codes
							$provider->UpdateCodes($USER_ID);

							//update cache for checking
							static::UpdateStat($providerId, $USER_ID);

							$connection->unlock($name);
						}
					}
				}
			}

			if ($clearCache)
			{
				static::ClearCache($USER_ID);
			}
		}
	}

	/**
	 * @param int $userId
	 * @param string $provider
	 * @param string $code
	 */
	public static function AddCode($userId, $provider, $code)
	{
		$userId = (int)$userId;

		$connection = Main\Application::getConnection();
		$helper = $connection->getSqlHelper();

		$connection->query("
			INSERT INTO b_user_access (USER_ID, PROVIDER_ID, ACCESS_CODE)
			VALUES ({$userId}, '{$helper->forSql($provider)}', '{$helper->forSql($code)}')
		");

		static::ClearCache($userId);
	}

	/**
	 * @param int $userId
	 * @param string $provider
	 * @param string $code
	 */
	public static function RemoveCode($userId, $provider, $code)
	{
		$userId = (int)$userId;

		$connection = Main\Application::getConnection();
		$helper = $connection->getSqlHelper();

		$connection->query("
			DELETE FROM b_user_access
			WHERE USER_ID = {$userId}
				AND PROVIDER_ID = '{$helper->forSql($provider)}'
				AND ACCESS_CODE = '{$helper->forSql($code)}'
		");

		static::ClearCache($userId);
	}

	/**
	 * @param int $userId User ID.
	 */
	public static function ClearCache($userId)
	{
		global $CACHE_MANAGER;

		$CACHE_MANAGER->Clean(static::GetCodesCacheId($userId), static::CACHE_DIR);
	}

	public static function RecalculateForUser($userId, $provider)
	{
		global $DB, $CACHE_MANAGER;
		$userId = intval($userId);

		$DB->Query("
			INSERT IGNORE INTO b_user_access_check (USER_ID, PROVIDER_ID)
			SELECT ID, '{$DB->ForSQL($provider)}'
			FROM b_user
			WHERE ID = {$userId}"
		);

		$CACHE_MANAGER->Clean(static::GetCheckCacheId($provider, $userId), static::CACHE_DIR);

		static::$arChecked[$provider][$userId] = true;
	}

	public static function RecalculateForProvider($provider)
	{
		global $DB, $CACHE_MANAGER;

		$DB->Query("
			INSERT IGNORE INTO b_user_access_check (USER_ID, PROVIDER_ID)
			SELECT USER_ID, PROVIDER_ID
			FROM b_user_access
			WHERE PROVIDER_ID = '{$DB->ForSQL($provider)}'
				AND USER_ID > 0
			GROUP BY USER_ID, PROVIDER_ID 
		");

		$CACHE_MANAGER->CleanDir(static::CACHE_DIR);

		if(is_array(static::$arChecked[$provider]))
		{
			foreach(static::$arChecked[$provider] as $userId => $dummy)
			{
				static::$arChecked[$provider][$userId] = true;
			}
		}
	}

	protected static function GetCheckCacheId($provider, $userId)
	{
		return "access_check_".$provider."_".$userId;
	}

	protected static function GetCodesCacheId($userId)
	{
		return "access_codes".$userId;
	}

	protected static function DeleteCodes($providerId, $userId)
	{
		$userId = (int)$userId;

		$connection = Main\Application::getConnection();
		$helper = $connection->getSqlHelper();

		$connection->query("
			delete from b_user_access 
			where user_id = {$userId} 
				and provider_id = '{$helper->forSql($providerId)}'
		");
	}

	protected static function UpdateStat($provider, $userId)
	{
		global $DB, $CACHE_MANAGER;
		$userId = intval($userId);

		$DB->Query("
			delete from b_user_access_check 
			where user_id = {$userId} 
				and provider_id = '{$DB->ForSql($provider)}'
		");
		$CACHE_MANAGER->Clean(static::GetCheckCacheId($provider, $userId), static::CACHE_DIR);

		static::$arChecked[$provider][$userId] = false;
	}

	public static function GetUserCodes($USER_ID, $arFilter=array())
	{
		global $DB;

		$access = new CAccess();
		$access->UpdateCodes(array('USER_ID' => $USER_ID));

		$arWhere = array();
		foreach($arFilter as $key=>$val)
		{
			$key = strtoupper($key);
			switch($key)
			{
				case "ACCESS_CODE":
					if(!is_array($val))
						$val = array($val);
					$arIn = array();
					foreach($val as $code)
						if(trim($code) <> '')
							$arIn[] = "'".$DB->ForSQL(trim($code))."'";
					if(!empty($arIn))
						$arWhere[] = "access_code in(".implode(",", $arIn).")";
					break;
				case "PROVIDER_ID":
					$arWhere[] = "provider_id='".$DB->ForSQL($val)."'";
					break;
			}
		}

		$sWhere = '';
		if(!empty($arWhere))
			$sWhere = " and ".implode(" and ", $arWhere);

		return $DB->Query("select * from b_user_access where user_id=".intval($USER_ID).$sWhere);
	}

	public static function GetUserCodesArray($USER_ID, $arFilter=array())
	{
		global $CACHE_MANAGER;
		$USER_ID = intval($USER_ID);

		$useCache = (empty($arFilter) && CACHED_b_user_access_check !== false);

		$cacheId = static::GetCodesCacheId($USER_ID);
		if ($useCache && $CACHE_MANAGER->Read(CACHED_b_user_access_check, $cacheId, static::CACHE_DIR))
		{
			return $CACHE_MANAGER->Get($cacheId);
		}
		else
		{
			$arCodes = array();
			$res = CAccess::GetUserCodes($USER_ID, $arFilter);
			while($arRes = $res->Fetch())
				$arCodes[] = $arRes["ACCESS_CODE"];

			if ($useCache)
				$CACHE_MANAGER->Set($cacheId, $arCodes);

			return $arCodes;
		}
	}

	public function GetFormHtml($arParams=false)
	{
		$arHtml = array();
		foreach(static::$arAuthProviders as $provider)
		{
			$cl = new $provider["CLASS"];
			if(is_callable(array($cl, "GetFormHtml")))
			{
				$res = call_user_func_array(array($cl, "GetFormHtml"), array($this->arParams));
				if($res !== false)
					$arHtml[$provider["ID"]] = array("NAME"=>$provider["NAME"], "HTML"=>$res["HTML"], "SELECTED"=>$res["SELECTED"]);
			}
		}
		return $arHtml;
	}

	public function AjaxRequest($arParams)
	{
		if(array_key_exists($arParams["provider"], static::$arAuthProviders))
		{
			$cl = new static::$arAuthProviders[$arParams["provider"]]["CLASS"];
			if(is_callable(array($cl, "AjaxRequest")))
			{
				CUtil::JSPostUnescape();
				return call_user_func_array(array($cl, "AjaxRequest"), array($this->arParams));
			}
		}
		return false;
	}

	public function GetNames($arCodes, $bSort=false)
	{
		$arResult = array();

		if(!is_array($arCodes) || empty($arCodes))
			return $arResult;

		foreach(static::$arAuthProviders as $provider)
		{

			$cl = new $provider["CLASS"];
			if(is_callable(array($cl, "GetNames")))
			{
				$res = call_user_func_array(array($cl, "GetNames"), array($arCodes));
				if(is_array($res))
				{
					foreach ($res as $codeId => $codeValues)
					{
						$codeValues['provider_id'] = $provider['ID'];
						$arResult[$codeId] = $codeValues;
					}
				}
			}
		}

		if($bSort)
			uasort($arResult, array('CAccess', 'CmpNames'));

		return $arResult;
	}

	public static function CmpNames($a, $b)
	{
		$c = strcmp($a["provider"], $b["provider"]);
		if($c <> 0)
			return $c;

		return strcmp($a["name"], $b["name"]);
	}

	public function GetProviderNames()
	{
		$arResult = array();
		foreach(static::$arAuthProviders as $ID=>$provider)
		{
			$arResult[$ID] = array(
				"name" => (isset($provider["PROVIDER_NAME"])? $provider["PROVIDER_NAME"] : $ID),
				"prefixes" => (isset($provider["PREFIXES"])? $provider["PREFIXES"] : array()),
			);
		}
		return $arResult;
	}

	public static function GetProviders()
	{
		return array(
			array(
				"ID" => "group",
				"NAME" => GetMessage("access_groups"),
				"PROVIDER_NAME" => GetMessage("access_group"),
				"SORT" => 100,
				"CLASS" => "CGroupAuthProvider",
			),
			array(
				"ID" => "user",
				"NAME" => GetMessage("access_users"),
				"PROVIDER_NAME" => GetMessage("access_user"),
				"SORT" => 200,
				"CLASS" => "CUserAuthProvider",
			),
			array(
				"ID" => "other",
				"NAME" => GetMessage("access_other"),
				"PROVIDER_NAME" => "",
				"SORT" => 1000,
				"CLASS" => "COtherAuthProvider",
			),
		);
	}

	public static function OnUserDelete($USER_ID)
	{
		global $DB, $CACHE_MANAGER;
		$USER_ID = intval($USER_ID);

		$DB->Query("delete from b_user_access where user_id=".$USER_ID);
		$DB->Query("delete from b_user_access_check where user_id=".$USER_ID);

		//all providers for one user
		foreach(static::$arChecked as $provider => $dummy)
		{
			unset(static::$arChecked[$provider][$USER_ID]);
			$CACHE_MANAGER->Clean(static::GetCheckCacheId($provider, $USER_ID), static::CACHE_DIR);
		}

		static::ClearCache($USER_ID);

		return true;
	}

	public static function SaveLastRecentlyUsed($arLRU)
	{
		foreach($arLRU as $provider=>$arRecent)
		{
			if(is_array($arRecent))
			{
				$arLastRecent = CUserOptions::GetOption("access_dialog_recent", $provider, array());

				$arItems = array_keys($arRecent);
				$arItems = array_unique(array_merge($arItems, $arLastRecent));
				$arItems = array_slice($arItems, 0, 20);

				CUserOptions::SetOption("access_dialog_recent", $provider, $arItems);
			}
		}
	}

	public static function GetLastRecentlyUsed($provider)
	{
		$res = CUserOptions::GetOption("access_dialog_recent", $provider, array());
		if(!is_array($res))
			$res = array();
		return $res;
	}
}

AddEventHandler("main", "OnAuthProvidersBuildList", array("CAccess", "GetProviders"));