Renderer/Profiler/ProfilerModule.php
File `ProfilerModule.php` has 296 lines of code (exceeds 250 allowed). Consider refactoring.<?php namespace Phug\Renderer\Profiler; use Phug\Compiler\Event\CompileEvent;use Phug\Compiler\Event\ElementEvent;use Phug\Compiler\Event\NodeEvent;use Phug\Compiler\Event\OutputEvent;use Phug\CompilerEvent;use Phug\Event;use Phug\Formatter;use Phug\Formatter\Event\DependencyStorageEvent;use Phug\Formatter\Event\FormatEvent;use Phug\FormatterEvent;use Phug\Lexer\Event\EndLexEvent;use Phug\Lexer\Event\LexEvent;use Phug\Lexer\Event\TokenEvent;use Phug\LexerEvent;use Phug\Parser\Event\NodeEvent as ParserNodeEvent;use Phug\Parser\Event\ParseEvent;use Phug\Parser\NodeInterface;use Phug\ParserEvent;use Phug\Renderer\Event\HtmlEvent;use Phug\Renderer\Event\RenderEvent;use Phug\RendererEvent;use Phug\Util\AbstractModule;use Phug\Util\ModuleContainerInterface;use Phug\Util\SandBox;use SplObjectStorage; `ProfilerModule` has 23 functions (exceeds 20 allowed). Consider refactoring.class ProfilerModule extends AbstractModule{ /** * @var int */ private $startTime = 0; /** * @var int */ private $initialMemoryUsage = 0; /** * @var EventList */ private $events = null; /** * @var SplObjectStorage */ private $nodesRegister = null; /** * @var callable */ private $eventDump = null; /** * @var array */ private static $profilers = []; /** * @var int */ private static $profilersIndex = 0; public function __construct(EventList $events, ModuleContainerInterface $container) { parent::__construct($container); $this->events = $events; $this->initialize(); } public function initialize() { $this->startTime = microtime(true); $this->initialMemoryUsage = memory_get_usage(); $this->nodesRegister = new SplObjectStorage(); if (!$this->getContainer()->hasOption('profiler.dump_event')) { $this->getContainer()->setOption('profiler.dump_event', [$this, 'getEventDump']); } $this->eventDump = $this->getContainer()->getOption('profiler.dump_event'); if (in_array($this->eventDump, ['var_dump', 'print_r'], true)) { $function = $this->eventDump; $this->eventDump = function ($value) use ($function) { return $this->getFunctionDump($value, $function); }; } } public function reset() { $this->initialize(); $this->events->reset(); } public function kill() { $this->events->lock(); } public function isAlive() { return !$this->events->isLocked(); } /** * @return EventList */ public function getEvents() { return $this->events; } /** * Catch output of a dump function and return it as string. * * @param mixed $value * @param callable $function * * @return string */ public function getFunctionDump($value, $function = 'var_dump') { $sandBox = new SandBox(function () use ($function, $value) { $function($value); }); return $sandBox->getBuffer(); } /** * @param Event $event * * @return string */ public function getEventDump(Event $event) { $dump = new Dump($event); return $dump->dump(); } public function getDebugId($nodeId) { $index = static::$profilersIndex++; static::$profilers[$index] = [$this, $nodeId]; return $index; } /** * @param int|null $nodeId * * @throws ProfilerException * @throws ProfilerLocatedException */ public function recordDisplayEvent($nodeId) { if (!$this->isAlive()) { return; } /** @var Formatter $formatter */ $formatter = $this->getContainer(); if ($formatter->debugIdExists($nodeId)) { $event = new Event('display'); $this->appendNode($event, $formatter->getNodeFromDebugId($nodeId)); $this->record($event); } } /** * @param int|null $debugId * * @throws ProfilerException * @throws ProfilerLocatedException */ public static function recordProfilerDisplayEvent($debugId) { if (isset(static::$profilers[$debugId])) { /** @var ProfilerModule $profiler */ list($profiler, $nodeId) = static::$profilers[$debugId]; $profiler->recordDisplayEvent($nodeId); } } private function cleanupProfilerNodes() { static::$profilers = array_filter(static::$profilers, function ($params) { return $params[0] !== $this; }); } public function attachEvents() { parent::attachEvents(); $formatter = $this->getContainer(); if ($formatter instanceof Formatter) { $formatter->setOption('patterns.debug_comment', function ($nodeId) { return "\n".( $nodeId !== '' ? '\\'.static::class.'::recordProfilerDisplayEvent('. var_export($this->getDebugId($nodeId), true). ");\n" : '' )."// PUG_DEBUG:$nodeId\n"; }); } } Method `getEventListeners` has 30 lines of code (exceeds 25 allowed). Consider refactoring. public function getEventListeners() { $eventListeners = array_map(function (callable $eventListener) { return function (Event $event) use ($eventListener) { if ($this->isAlive() && $eventListener($event) !== false) { $this->record($event); } }; }, array_merge( [ RendererEvent::RENDER => function (RenderEvent $event) { $this->appendParam($event, '__link', $event); }, ], $this->getCompilerEventListeners(), $this->getFormatterEventListeners(), $this->getParserEventListeners(), $this->getLexerEventListeners() )); $eventListeners[RendererEvent::HTML] = function (HtmlEvent $event) { $this->appendParam($event, '__link', $event->getRenderEvent()); if ($this->isAlive()) { $this->record($event); } if ($event->getBuffer()) { $event->setBuffer($this->renderProfile().$event->getBuffer()); } if (is_string($event->getResult())) { $event->setResult($this->renderProfile().$event->getResult()); } }; return $eventListeners; } private function appendParam(Event $event, $key, $value) { $event->setParams(array_merge($event->getParams(), [ $key => $value, ])); } private function appendNode(Event $event, $node) { if ($node instanceof NodeInterface) { $this->appendParam($event, '__location', $node->getSourceLocation()); $this->appendParam($event, '__link', $node->getToken() ?: $node); } } private function getException(Event $event, $message) { $params = $event->getParams(); $this->kill(); return isset($params['__location']) ? new ProfilerLocatedException($params['__location'], $message) : new ProfilerException($message); } /** * @param Event $event * * @throws ProfilerException * @throws ProfilerLocatedException */Function `record` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. private function record(Event $event) { $time = microtime(true) - $this->startTime; $container = $this->getContainer(); $maxTime = $container->getOption('execution_max_time'); if ($maxTime > -1 && $time * 1000 > $maxTime) { throw $this->getException($event, 'execution_max_time of '.$maxTime.'ms exceeded.'); } $memoryLimit = $container->getOption('memory_limit'); if ($memoryLimit > -1 && memory_get_usage() - $this->initialMemoryUsage > $memoryLimit) { throw $this->getException($event, 'memory_limit of '.$memoryLimit.'B exceeded.'); } $this->appendParam($event, '__time', $time); if ($container->getOption('profiler.display') || $container->getOption('profiler.log')) { $this->events[] = $event; } } private function renderProfile() { $display = $this->getContainer()->getOption('profiler.display'); $log = $this->getContainer()->getOption('profiler.log'); if (!$display && !$log) { return ''; } $profile = new Profile( $this->events, $this->nodesRegister, $this->startTime, $this->initialMemoryUsage, $this->eventDump ); $profile->compose( $this->getContainer()->getOption('profiler.time_precision'), $this->getContainer()->getOption('profiler.line_height') ); $this->kill(); $render = $profile->render(); $this->cleanupProfilerNodes(); if ($log) { file_put_contents($log, $render); } return $display ? $render : ''; } private function getCompilerEventListeners() { return [ CompilerEvent::COMPILE => function (CompileEvent $event) { $this->appendParam($event, '__link', $event); }, CompilerEvent::ELEMENT => function (ElementEvent $event) { $this->appendNode($event, $event->getElement()->getOriginNode()); }, CompilerEvent::NODE => function (NodeEvent $event) { $this->appendNode($event, $event->getNode()); }, CompilerEvent::OUTPUT => function (OutputEvent $event) { $this->appendParam($event, '__link', $event->getCompileEvent()); }, ]; } private function getFormatterEventListeners() { return [ FormatterEvent::DEPENDENCY_STORAGE => function (DependencyStorageEvent $event) { $this->appendParam($event, '__link', $event->getDependencyStorage()); }, FormatterEvent::FORMAT => function (FormatEvent $event) { $this->appendNode($event, $event->getElement()->getOriginNode()); }, ]; } private function getParserEventListeners() { return [ ParserEvent::PARSE => function (ParseEvent $event) { $this->appendParam($event, '__link', $event); }, ParserEvent::DOCUMENT => function (ParserNodeEvent $event) { $this->appendNode($event, $event->getNode()); }, ParserEvent::STATE_ENTER => function (ParserNodeEvent $event) { $this->appendNode($event, $event->getNode()); }, ParserEvent::STATE_LEAVE => function (ParserNodeEvent $event) { $this->appendNode($event, $event->getNode()); }, ParserEvent::STATE_STORE => function (ParserNodeEvent $event) { $this->appendNode($event, $event->getNode()); }, ]; } private function getLexerEventListeners() { return [ LexerEvent::LEX => function (LexEvent $event) { $this->appendParam($event, '__link', $event); }, LexerEvent::END_LEX => function (EndLexEvent $event) { $this->appendParam($event, '__link', $event->getLexEvent()); }, LexerEvent::TOKEN => function (TokenEvent $event) { $token = $event->getToken(); $this->appendParam($event, '__location', $token->getSourceLocation()); $this->appendParam($event, '__link', $token); }, ]; }}