Your IP : 18.188.63.107


Current Path : /home/bitrix/ext_www/dev.ballu.in.ua/bitrix/modules/main/classes/general/
Upload File :
Current File : /home/bitrix/ext_www/dev.ballu.in.ua/bitrix/modules/main/classes/general/update_b24.php

<?php

class CB24Updater
{
	private $arFileVersions = null;
	private $fileGenerateDate = 0;

	private $serverUniqID = "";
	private $isProcessingMain = false;

	const versionsFileNameConst = "/bitrix/modules/versions.php";
	private $versionsFileName = "";

	const versionsDatabaseFolderConst = "/bitrix/updates/bitrix24_clients/";
	private $versionsDatabaseFolder = "";

	private $updatersDir = "";

	public function __construct($isProcessingMain = false)
	{
		$this->serverUniqID = self::GetServerUniqID();
		$this->isProcessingMain = $isProcessingMain;

		$this->versionsFileName = $_SERVER["DOCUMENT_ROOT"].self::versionsFileNameConst;
		$this->versionsDatabaseFolder = $_SERVER["DOCUMENT_ROOT"].self::versionsDatabaseFolderConst;
		$this->updatersDir = $_SERVER["DOCUMENT_ROOT"].US_SAVE_UPDATERS_DIR."/";
	}

	private static function GetOption($name, $def = "")
	{
		return COption::GetOptionString('main', $name, $def);
	}

	private static function SetOption($name, $value = "")
	{
		COption::SetOptionString('main', $name, $value);
	}

	private static function GetServerUniqID()
	{
		$uniq = self::GetOption("server_uniq_id", "");
		if (strlen($uniq) <= 0)
		{
			$uniq = md5(uniqid(rand(), true));
			self::SetOption("server_uniq_id", $uniq);
		}
		return $uniq;
	}

	public function Lock()
	{
		global $DB;

		$uniq = $this->serverUniqID;

		if ($DB->type == "MYSQL")
		{
			$dbLock = $DB->Query("SELECT GET_LOCK('".$uniq."_DBUpdater', 0) as L", false, "File: ".__FILE__."<br>Line: ".__LINE__);
			$arLock = $dbLock->Fetch();
			if ($arLock["L"] == "1")
				return true;
			else
				return false;
		}
		elseif ($DB->type == "ORACLE")
		{
			$dbLock = $DB->Query("
				declare
					my_lock_id number;
					my_result number;
					lock_failed exception;
					pragma exception_init(lock_failed, -54);
				begin
					my_lock_id:=dbms_utility.get_hash_value(to_char('".$uniq."_DBUpdater'), 0, 1024);
					my_result:=dbms_lock.request(my_lock_id, dbms_lock.x_mode, 0, true);
					--  Return value:
					--    0 - success
					--    1 - timeout
					--    2 - deadlock
					--    3 - parameter error
					--    4 - already own lock specified by 'id' or 'lockhandle'
					--    5 - illegal lockhandle
					if(my_result<>0 and my_result<>4)then
						raise lock_failed;
					end if;
				end;
			", true);
			return ($dbLock !== false);
		}
		else
		{
			$i = 60;
			$DB->Query("DELETE FROM b_option WHERE MODULE_ID = 'main' AND NAME = '".$uniq."_DBUpdater' AND SITE_ID IS NULL AND DATEDIFF(SECOND, CONVERT(DATETIME, DESCRIPTION), GETDATE()) > ".$i, false, "File: ".__FILE__."<br>Line: ".__LINE__);
			$DB->Query("SET LOCK_TIMEOUT 1", false, "File: ".__FILE__."<br>Line: ".__LINE__);
			$dbLock = $DB->Query("INSERT INTO b_option(MODULE_ID, NAME, SITE_ID, VALUE, DESCRIPTION) VALUES ('main', '".$uniq."_DBUpdater', NULL,  NULL, CONVERT(VARCHAR(128), GETDATE()))", true);
			$DB->Query("SET LOCK_TIMEOUT -1", false, "File: ".__FILE__."<br>Line: ".__LINE__);
			return ($dbLock !== false);
		}
	}

	public function UnLock()
	{
		global $DB;

		$uniq = $this->serverUniqID;

		if ($DB->type == "MYSQL")
		{
			$dbLock = $DB->Query("SELECT RELEASE_LOCK('".$uniq."_DBUpdater') as L", false, "File: ".__FILE__."<br>Line: ".__LINE__);
			$arLock = $dbLock->Fetch();
			if($arLock["L"] == "0")
				return false;
			else
				return true;
		}
		elseif ($DB->type == "ORACLE")
		{
			return true;
		}
		else
		{
			$DB->Query("DELETE FROM b_option WHERE MODULE_ID = 'main' AND NAME = '".$uniq."_DBUpdater' AND SITE_ID IS NULL", false, "File: ".__FILE__."<br>Line: ".__LINE__);
			return true;
		}
	}

	private static function GetDatabaseVersions()
	{
		global $DB;

		$arDBVersions = array();

		$dbResult = $DB->Query("SELECT VALUE FROM b_option WHERE MODULE_ID='main' AND NAME='BITRIX24_VERSIONS' AND SITE_ID IS NULL", true);
		if ($arResult = $dbResult->Fetch())
		{
			$val = $arResult["VALUE"];
			if (strlen($val) > 0)
			{
				$arDBVersions = unserialize($val);
				if (!is_array($arDBVersions))
					$arDBVersions = array();
			}
		}

		return $arDBVersions;
	}

	private static function SetDatabaseVersions($arDBVersions)
	{
		if(is_array($arDBVersions))
			self::SetOption("BITRIX24_VERSIONS", serialize($arDBVersions));
	}

	private function InitializeFileData()
	{
		$generationDate = 0;
		$arVersions = array();

		if (file_exists($this->versionsFileName))
		{
			include($this->versionsFileName);
			if (!is_array($arVersions))
				$arVersions = array();
		}

		if (count($arVersions) <= 0)
		{
			include_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/classes/general/update_client.php");

			$errorMessage = "";
			$arVersions = CUpdateClient::GetCurrentModules($errorMessage, false);
			$generationDate = time();
			if (strlen($errorMessage) <= 0)
			{
				$f = fopen($this->versionsFileName, "w");
				fwrite($f, "<"."?\n");
				fwrite($f, "\$generationDate = ".$generationDate.";\n");
				fwrite($f, "\$arVersions = array(\n");
				foreach ($arVersions as $moduleId => $version)
					fwrite($f, "\t\"".htmlspecialchars($moduleId)."\" => \"".htmlspecialchars($version)."\",\n");
				fwrite($f, ");\n");
				fwrite($f, "?".">");
				fclose($f);
			}
		}

		$this->fileGenerateDate = $generationDate;
		$this->arFileVersions = $arVersions;
	}

	private function GetFileVersions()
	{
		if (is_null($this->arFileVersions))
			$this->InitializeFileData();

		return $this->arFileVersions;
	}

	private function GetFileGenerateDate()
	{
		if ($this->fileGenerateDate <= 0)
			$this->InitializeFileData();

		return $this->fileGenerateDate;
	}

	private function GetDatabaseGenerationDate()
	{
		return self::GetOption("BITRIX24_GENERATION_DATE_".($this->isProcessingMain ? "M" : "N"), 0);
	}

	public function PreCheckUpdates()
	{
		$generationDate = $this->GetFileGenerateDate();
		$dbGenerationDate = $this->GetDatabaseGenerationDate();

		if ($dbGenerationDate >= $generationDate)
			return false;

		return true;
	}

	private function Collect4PreCheckUpdates($generationDate)
	{
		self::SetOption("BITRIX24_GENERATION_DATE_".($this->isProcessingMain ? "M" : "N"), $generationDate);
	}

	public function CheckUpdates()
	{
		$arDBVersions = self::GetDatabaseVersions();
		if (count($arDBVersions) <= 0)
		{
			$this->CollectDatabaseVersions("ALL");
			$arDBVersions = self::GetDatabaseVersions();
		}

		$arFileVersions = $this->GetFileVersions();

		$arResult = array();
		foreach ($arFileVersions as $moduleId => $version)
		{
			if ($this->isProcessingMain && $moduleId != "main" || !$this->isProcessingMain && $moduleId == "main")
				continue;

			if (CUpdateClient::CompareVersions($version, $arDBVersions[$moduleId]) > 0)
				$arResult[$moduleId] = $arDBVersions[$moduleId];
		}

		return $arResult;
	}

	public function UpdateFromVersion($moduleId, $dbVersion)
	{
		if (strlen($moduleId) <= 0)
			return;

		$errorMessage = "";

		if (file_exists($this->updatersDir.$moduleId) && is_dir($this->updatersDir.$moduleId))
		{
			$arUpdaters = array();

			if ($handle = @opendir($this->updatersDir.$moduleId))
			{
				while (false !== ($dir = readdir($handle)))
				{
					if ($dir == "." || $dir == "..")
						continue;

					if (substr($dir, 0, 7) == "updater")
					{
						if (is_file($this->updatersDir.$moduleId."/".$dir))
						{
							$num = substr($dir, 7, strlen($dir) - 11);
							if (substr($dir, strlen($dir) - 9) == "_post.php")
								$num = substr($dir, 7, strlen($dir) - 16);

							$arUpdaters[] = array("/".$dir, Trim($num));
						}
						elseif (file_exists($this->updatersDir.$moduleId."/".$dir."/index.php"))
						{
							$num = substr($dir, 7);
							if (substr($dir, strlen($dir) - 5) == "_post")
								$num = substr($dir, 7, strlen($dir) - 12);

							$arUpdaters[] = array("/".$dir."/index.php", Trim($num));
						}
					}
				}
				closedir($handle);
			}

			$ni1 = count($arUpdaters);
			for ($i1 = 0; $i1 < $ni1 - 1; $i1++)
			{
				for ($j1 = $i1 + 1; $j1 < $ni1; $j1++)
				{
					if (CUpdateClient::CompareVersions($arUpdaters[$i1][1], $arUpdaters[$j1][1]) > 0)
					{
						$tmp1 = $arUpdaters[$i1];
						$arUpdaters[$i1] = $arUpdaters[$j1];
						$arUpdaters[$j1] = $tmp1;
					}
				}
			}

			for ($i1 = 0; $i1 < $ni1; $i1++)
			{
				if (CUpdateClient::CompareVersions($arUpdaters[$i1][1], $dbVersion) <= 0)
					continue;

				$errorMessageTmp = "";

				syslog(LOG_INFO, $_SERVER["HTTP_HOST"]."\tstart\t".$moduleId.$arUpdaters[$i1][0]);

				CUpdateClient::RunUpdaterScript($this->updatersDir.$moduleId.$arUpdaters[$i1][0], $errorMessageTmp, "", $moduleId);

				syslog(LOG_INFO, $_SERVER["HTTP_HOST"]."\tend\t".$moduleId.$arUpdaters[$i1][0]."\t".$errorMessageTmp);

				if (strlen($errorMessageTmp) > 0)
					$errorMessage .= str_replace("#MODULE#", $moduleId, str_replace("#VER#", $arUpdaters[$i1][1], GetMessage("SUPP_UK_UPDN_ERR"))).": ".$errorMessageTmp.".";

				$this->CollectDatabaseVersions("MODULE", $moduleId, $arUpdaters[$i1][1]);
			}
		}

		if (strlen($errorMessage) > 0)
			CUpdateClient::AddMessage2Log("Database update error (".$moduleId."-".$dbVersion."): ".$errorMessage, "DUE");
		else
			CUpdateClient::AddMessage2Log("Database updated successfully (".$moduleId."-".$dbVersion.")", "DUS");
	}

	public function CollectDatabaseVersions($type, $moduleId = null, $version = null)
	{
		$arDBVersions = self::GetDatabaseVersions();
		$arFileVersions = $this->GetFileVersions();
		switch ($type)
		{
		case "MODULE":
			if (isset($moduleId) && isset($version))
			{
				//Only one selected module
				$arDBVersions[$moduleId] = $version;
				self::SetDatabaseVersions($arDBVersions);
			}
			break;

		case "HIT":
			if ($this->isProcessingMain)
			{
				//Main only
				$arDBVersions["main"] = $arFileVersions["main"];
				self::SetDatabaseVersions($arDBVersions);
			}
			else
			{
				//All except main
				$arFileVersions["main"] = $arDBVersions["main"];
				self::SetDatabaseVersions($arFileVersions);
			}
			$this->Collect4PreCheckUpdates($this->GetFileGenerateDate());
			break;

		default:
			//All
			self::SetDatabaseVersions($arFileVersions);
			$this->Collect4PreCheckUpdates($this->GetFileGenerateDate());
			break;
		}
	}
}