Your IP : 3.145.108.151
<?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;
}
}
}