Current Path : /var/www/www-root/data/www.catalog.monolith-realty.ru/bitrix/modules/perfmon/lib/php/ |
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; } } }