Your IP : 52.15.224.97


Current Path : /var/www/www-root/data/www/info.monolith-realty.ru/bitrix/modules/scale/lib/
Upload File :
Current File : /var/www/www-root/data/www/info.monolith-realty.ru/bitrix/modules/scale/lib/action.php

<?php
namespace Bitrix\Scale;

use Bitrix\Main\IO\File;
use \Bitrix\Main\Localization\Loc;
Loc::loadMessages(__FILE__);

/**
 * Class Action
 * @package Bitrix\Scale
 */
class Action
{
	protected $id = "";
	protected $userParams = array();
	protected $freeParams = array();
	protected $actionParams = array();
	protected $serverHostname = "";

	protected $shellAdapter = null;
	protected $result = array();
	protected $logLevel = Logger::LOG_LEVEL_INFO;

	/**
	 * @param string $actionId
	 * @param array $actionParams
	 * @param string $serverHostname
	 * @param array $userParams
	 * @param array $freeParams
	 * @throws \Bitrix\Main\ArgumentNullException
	 * @throws \Bitrix\Main\ArgumentTypeException
	 * @throws \Exception
	 */
	public function __construct($actionId, $actionParams, $serverHostname="", $userParams = array(), $freeParams = array())
	{
		if($actionId == '')
			throw new \Bitrix\Main\ArgumentNullException("actionId");

		if(!is_array($actionParams) || empty($actionParams))
			throw new \Exception("Params of action ".$actionId." are not defined correctly!");

		if(!isset($actionParams["START_COMMAND_TEMPLATE"]) || $actionParams["START_COMMAND_TEMPLATE"] == '')
			throw new \Exception("Required param START_COMMAND_TEMPLATE of action ".$actionId." are not defined!");

		if(!is_array($userParams))
			throw new \Bitrix\Main\ArgumentTypeException("userParams", "array");

		if(!is_array($freeParams))
			throw new \Bitrix\Main\ArgumentTypeException("freeParams", "array");

		$this->id = $actionId;
		$this->userParams = $userParams;
		$this->freeParams = $freeParams;
		$this->actionParams = $actionParams;
		$this->serverHostname = $serverHostname;
		$this->shellAdapter = new ShellAdapter;

		if(isset($actionParams["LOG_LEVEL"]))
			$this->logLevel = $actionParams["LOG_LEVEL"];
	}

	protected function getServerParams()
	{
		return  ServersData::getServer($this->serverHostname);
	}

	/**
	 * Makes command for shell action execution
	 * @param array $inputParams
	 * @return string - command to execute
	 * @throws \Bitrix\Main\ArgumentTypeException
	 */
	protected function makeStartCommand($inputParams = array())
	{
		if(!is_array($inputParams))
			throw new \Bitrix\Main\ArgumentTypeException("inputParams", "array");

		$retStr = $this->actionParams["START_COMMAND_TEMPLATE"];

		foreach ($this->userParams as $key => $paramValue)
		{
			if($this->actionParams['USER_PARAMS'][$key]['THROUGH_FILE'] == 'Y')
			{
				if($paramValue <> '')
				{
					$tmpDir = Helper::getTmpDir();
					$tmpFile = $tmpDir.'/.'.randString();
					$res = File::putFileContents($tmpFile, $paramValue);

					if($res === false)
						return '';

					$paramValue = $tmpFile;
				}
			}

			$retStr = str_replace('##USER_PARAMS:'.$key.'##', $paramValue, $retStr);
		}

		if($this->serverHostname <> '' && $this->serverHostname != "global")
		{
			$serverParams = $this->getServerParams();
			$serverParams["hostname"] = $this->serverHostname;

			if(is_array($serverParams))
			{
				foreach ($serverParams as $key => $paramValue)
				{
					if(is_string($paramValue))
					{
						$retStr = str_replace('##SERVER_PARAMS:' . $key . '##', $paramValue, $retStr);
					}
				}
			}
		}

		if(!empty($inputParams))
			foreach ($inputParams as $key => $paramValue)
				$retStr = str_replace('##INPUT_PARAMS:'.$key.'##', $paramValue, $retStr);

		if(isset($this->actionParams["CODE_PARAMS"]) && is_array($this->actionParams["CODE_PARAMS"]))
		{
			foreach($this->actionParams["CODE_PARAMS"] as $paramId => $paramCode)
			{
				$res = eval($paramCode);
				$retStr = str_replace('##CODE_PARAMS:'.$paramId.'##', $res, $retStr);
			}
		}

		foreach ($this->freeParams as $key => $paramValue)
			$retStr = str_replace('##'.$key.'##', $paramValue, $retStr);

		return $retStr;
	}

	/**
	 * Starts the action execution
	 * @param array $inputParams - params from previously started actions
	 * @return int code returned by shell
	 * @throws \Bitrix\Main\ArgumentTypeException
	 * @throws \Exception
	 */
	public function start(array $inputParams = array())
	{
		if(!is_array($inputParams))
			throw new \Bitrix\Main\ArgumentTypeException("inputParams", "array");

		if(isset($this->actionParams["MODIFYERS"]) && is_array($this->actionParams["MODIFYERS"]))
		{
			$needMoreUserInfo = false;

			foreach($this->actionParams["MODIFYERS"] as $modifyerFunction)
			{
				if(is_callable($modifyerFunction))
				{
					try
					{
						$this->actionParams = call_user_func($modifyerFunction, $this->id, $this->actionParams, $this->serverHostname, $this->userParams);
					}
					catch(NeedMoreUserInfoException $e)
					{
						$this->actionParams = $e->getActionParams();
						$needMoreUserInfo = true;
					}
				}
			}

			if($needMoreUserInfo)
				throw new NeedMoreUserInfoException("Need more user's info", $this->actionParams);
		}

		$result = null;
		$output = '';
		$arOutput = array();
		$command = $this->makeStartCommand($inputParams);

		if($command <> '')
		{
			$result =  $this->shellAdapter->syncExec($command);
			$output = $this->shellAdapter->getLastOutput();
			$arOutput = array();

			if($output <> '')
			{
				$arOut = json_decode($output, true);

				if(is_array($arOut) && !empty($arOut))
					$arOutput = $arOut;
			}

			//error returned by shell
			$error = $this->shellAdapter->getLastError();

			//error returned by bitrix-env
			if(isset($arOutput["error"]) && intval($arOutput["error"]) > 0 && isset($arOutput["message"]) && $arOutput["message"] <> '')
				$error .= " ".$arOutput["message"];

			$this->makeLogRecords($command, $result, $output, $error);
		}
		else //$command == ''
		{
			$result = false;
			$error = 'Cant\'t create command for action execution';
		}

		$this->result = array(
			$this->id => array(
				"NAME" => isset($this->actionParams["NAME"]) ? $this->actionParams["NAME"] : "[".$this->id."]",
				"RESULT" => $result ? "OK" : "ERROR",
				"OUTPUT" => array(
					"TEXT" => $output,
					"DATA" => $arOutput
				),
				"ERROR" => $error
			)
		);

		return $result;
	}

	/**
	 * @return array Last command execution results
	 */
	public function getResult()
	{
		return  $this->result;
	}

	protected function makeLogRecords($command = "", $result = null, $output = "", $error = "")
	{
		if($command <> '')
		{
			//cut password data from log records
			$preg = "/(-p.*\s+|--mysql_password=.*\s+|--cluster_password=.*\s+|--replica_password=.*\s+|--password=.*\s+)/is";
			$command = preg_replace($preg, ' PASS_PARAMS ', $command);

			$this->log(
				($result ? Logger::LOG_LEVEL_INFO : Logger::LOG_LEVEL_ERROR),
				"SCALE_ACTION_STARTED",
				$this->actionParams["NAME"],
				$command
			);
		}

		if($result !== null)
		{
			$this->log(
				($result ? Logger::LOG_LEVEL_INFO : Logger::LOG_LEVEL_ERROR),
				"SCALE_ACTION_RESULT",
				$this->actionParams["NAME"],
				$result ? Loc::getMessage("SCALE_ACTION_RESULT_SUCCESS") : Loc::getMessage("SCALE_ACTION_RESULT_ERROR")
			);
		}

		if($output <> '')
		{
			$this->log(
				Logger::LOG_LEVEL_DEBUG,
				"SCALE_ACTION_OUTPUT",
				$this->actionParams["NAME"],
				$output
			);
		}

		if($error <> '')
		{
			$this->log(
				Logger::LOG_LEVEL_ERROR,
				"SCALE_ACTION_ERROR",
				$this->actionParams["NAME"],
				$error
			);
		}
	}

	protected function log($level, $auditType, $actionId, $description)
	{
		if($this->logLevel < $level)
			return false;

		return Logger::addRecord($level, $auditType, $actionId, $description);
	}
}