geshan/pdepend-analyzer

View on GitHub
src/Pdepend/Command/AnalyzerCommand.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

namespace Geshan\Pdepend\Command;

use Geshan\Pdepend\Service\Analyzer;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class AnalyzerCommand extends Command
{
    protected $analyzer;
    protected $logger;

    const MESSAGE_FILE_NOT_PROVIDED = 'File not provided';
    const MESSAGE_FILE_NOT_FOUND = 'File not found';
    const MESSAGE_PASSED = 'Hurray! There are no methods/functions which exceed ccn or npath limits';
    const MESSAGE_FAILED = 'There are method(s) which exceed ccn or npath limits';
    const MESSAGE_METRIC_NOT_EXCEEDED = 'There is no method exceeding %s limit.';
    const MESSAGE_METRIC_EXCEEDED = 'There are method(s) exceeding %s limit.';

    public function __construct(Analyzer $analyzer, LoggerInterface $logger)
    {
        parent::__construct('Summary Analyzer');

        $this->analyzer = $analyzer;
        $this->logger = $logger;
    }

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->setName('pdepend-analyze')
            ->setDescription('Parse summary.xml provided by Pdepend to check cyclomatic complexity and N-Path complexity.')
            ->setHelp(<<<EOT
'Needs a summary.xml fie generated by Pdepend to check reported cyclomatic complexity and N-Path complexity'
EOT
            )
            ->addOption('file', null, InputOption::VALUE_REQUIRED, 'needs the path of the summary.xml file')
            ->addOption('cyclomatic-complexity-limit', null, InputOption::VALUE_OPTIONAL, 'cyclomatic complexity number limit')
            ->addOption('npath-complexity-limit', null, InputOption::VALUE_OPTIONAL, 'npath complexity number limit');
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $filenameWithPath = $input->getOption('file');
        $exit = 1;

        $this->validateFile($output, $filenameWithPath);

        $output->writeln(sprintf('Executing pdepend summary analyze command with file <info>%s</info>', $filenameWithPath));
        $output->writeln(sprintf('<comment>ccn = Cyclomatic Complexity Number</comment>'));

        $methodsExceedingMetricLimit = $this->analyzer->analyze(
             $filenameWithPath,
             [
                Analyzer::CYCLOMATIC_COMPLEXITY_NUMBER => $input->getOption('cyclomatic-complexity-limit'),
                Analyzer::NPATH_COMPLEXITY_NUMBER      => $input->getOption('npath-complexity-limit'),
             ]
        );

        if ($this->analyzer->checkPassed($methodsExceedingMetricLimit)) {
            $exit = 0;
            $output->writeln(sprintf('<info>%s</info>', self::MESSAGE_PASSED));
        } else {
            $output->writeln(sprintf('<error>%s</error>', self::MESSAGE_FAILED));
            $this->showResultsAsTable($output, $methodsExceedingMetricLimit);
        }

        $output->writeln(sprintf('<info>Analyzer command done</info>'));
        exit($exit);
    }

    protected function validateFile(OutputInterface $output, $filenameWithPath)
    {
        if ($filenameWithPath === null) {
            $output->writeln(sprintf('<error>%s</error>', self::MESSAGE_FILE_NOT_PROVIDED));
            exit(2);
        }

        if (!file_exists($filenameWithPath)) {
            $output->writeln(sprintf('<error>%s</error>', self::MESSAGE_FILE_NOT_FOUND));
            exit(2);
        }
    }

    protected function showResultsAsTable(OutputInterface $output, array $methodsExceedingMetricLimit)
    {
        foreach ($methodsExceedingMetricLimit as $metricName => $methods) {
            if (count($methods) === 0) {
                $message = sprintf(self::MESSAGE_METRIC_NOT_EXCEEDED, $metricName);
                $output->writeln(sprintf('<info>%s</info>', $message));
            } else {
                $message = sprintf(self::MESSAGE_METRIC_EXCEEDED, $metricName);
                $output->writeln(sprintf('<error>%s</error>', $message));

                $table = new Table($output);
                $table->setHeaders(['No.', 'Method Name', sprintf('%s value', $metricName)]);
                $this->addMethodMetricsAsRows($table, $methods);
                $table->render();
            }
        }
    }

    protected function addMethodMetricsAsRows(Table $table, array $methods)
    {
        $counter = 1;

        foreach ($methods as $methodRow) {
            array_unshift($methodRow, $counter);
            $table->addRow($methodRow);
            $counter++;
        }
    }
}