Your IP : 18.217.146.30


Current Path : /var/www/www-root/data/www.catalog.monolith-realty.ru/bitrix/modules/perfmon/lib/php/
Upload File :
Current File : /var/www/www-root/data/www.catalog.monolith-realty.ru/bitrix/modules/perfmon/lib/php/codetree.php

<?php
namespace Bitrix\Perfmon\Php;

class CodeTree
{
	protected $statements = [];
	protected $tree = [];

	/**
	 * @param array $statements Sequence of updater statements.
	 */
	public function __construct(array $statements)
	{
		$this->statements = [];
		foreach ($statements as $i => $statement)
		{
			$this->statements[$i] = clone $statement;
		}
		$this->tree = [];
	}

	/**
	 * Returns php code.
	 *
	 * @param int $level Alignment level.
	 *
	 * @return string
	 */
	public function getCode($level)
	{
		$tree = $this->getCodeTree();
		return $this->formatCodeTree($tree, $level);
	}

	/**
	 * @param array $result Nested arrays of structured code.
	 * @param int $level Alignment level.
	 *
	 * @return string
	 */
	protected function formatCodeTree($result, $level=0)
	{
		$code = '';
		foreach ($result as $stmt)
		{
			if (is_array($stmt) && isset($stmt['if']))
			{
				$code .= str_repeat("\t", $level) . 'if (' . implode(' && ', $stmt['if']) . ")\n";
				$code .= str_repeat("\t", $level) . "{\n";
				$code .= $this->formatCodeTree($stmt['body'], $level + 1);
				$code .= str_repeat("\t", $level) . "}\n";
			}
			else
			{
				$stmt = trim($stmt, "\n\t");
				$stmt = preg_replace("/\\n\\t+/", "\n", $stmt);
				$code .= str_repeat("\t", $level) . str_replace("\n\$", "\n" . str_repeat("\t", $level) . '$', $stmt) . "\n";
			}
		}
		return $code;
	}

	/**
	 * @return array
	 */
	public function getCodeTree()
	{
		if (!$this->tree)
		{
			$this->makeCodeTree($this->statements, $this->tree);
		}
		return $this->tree;
	}

	/**
	 * Adds one more line to the body.
	 *
	 * @param Statement[] $updaterSteps Plain array of updater steps.
	 * @param array $result Nested arrays of structured code.
	 *
	 * @return void
	 */
	protected function makeCodeTree(array $updaterSteps, &$result)
	{
		foreach ($updaterSteps as $i => $statement)
		{
			if (empty($statement->conditions))
			{
				$result[] = $statement->formatBodyLines(0);
				unset($updaterSteps[$i]);
			}
		}

		while ($updaterSteps)
		{
			$byPredicates = [];
			foreach ($updaterSteps as $i => $statement)
			{
				/**
				* @var Condition $condition
				*/
				foreach ($statement->conditions as $condition)
				{
					$predicate = $condition->getPredicate();
					if (!isset($byPredicates[$predicate]))
					{
						$byPredicates[$predicate] = [
							'predicate' => $predicate,
							'dep' => $statement->dependOn,
							'sort' => $this->getPredicateSort($predicate),
							'count' => 1,
						];
					}
					else
					{
						$byPredicates[$predicate]['count']++;
					}
				}
			}

			if ($byPredicates)
			{
				sortByColumn($byPredicates, [
					'dep' => SORT_ASC,
					'count' => SORT_DESC,
					'sort' => SORT_ASC,
				]);
				$mostPopular = key($byPredicates);
				$subSteps = [];
				$ifStatement = [
					'if' => [$mostPopular],
					'body' => [],
				];
				foreach ($updaterSteps as $i => $statement)
				{
					foreach ($statement->conditions as $j => $condition)
					{
						if ($condition->getPredicate() == $mostPopular)
						{
							unset($statement->conditions[$j]);
							$subSteps[] = $statement;
							unset($updaterSteps[$i]);
						}
					}
				}
				$this->makeCodeTree($subSteps, $ifStatement['body']);
				if (
					is_array($ifStatement['body'])
					&& count($ifStatement['body']) == 1
					&& is_array($ifStatement['body'][0])
					&& isset($ifStatement['body'][0]['if'])
					&& isset($ifStatement['body'][0]['body'])
					&& mb_strlen(implode(' && ', array_merge($ifStatement['if'], $ifStatement['body'][0]['if']))) < 100
				)
				{
					$ifStatement['if'] = array_merge($ifStatement['if'], $ifStatement['body'][0]['if']);
					$ifStatement['body'] = $ifStatement['body'][0]['body'];
				}
				$result[] = $ifStatement;
			}
		}
	}

	/**
	 * @param array $predicate Array describing predicate.
	 *
	 * @return int
	 */
	protected function getPredicateSort($predicate)
	{
		if (mb_strpos($predicate, 'CanUpdateDatabase'))
		{
			return 10;
		}
		elseif (mb_strpos($predicate, '->type'))
		{
			return 20;
		}
		elseif (mb_strpos($predicate, 'TableExists'))
		{
			return 30;
		}
		elseif (mb_strpos($predicate, 'IndexExists'))
		{
			return 60;
		}
		else
		{
			return 50;
		}
	}
}