Skip to content

Instantly share code, notes, and snippets.

@dnahrebecki
Created February 16, 2022 13:39
Show Gist options
  • Save dnahrebecki/375b8a360441599bc3cfbb9eb8059442 to your computer and use it in GitHub Desktop.
Save dnahrebecki/375b8a360441599bc3cfbb9eb8059442 to your computer and use it in GitHub Desktop.
Command for generating LOC statistics for a Symfony project
<?php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Serializer\Encoder\CsvEncoder;
use Symfony\Component\Serializer\Serializer;
/**
* Make sure cloc is installed (@link https://github.com/AlDanial/cloc)
*/
class EstimateClocCommand extends Command
{
public const DEFAULT_OUTPUT_FILE = '/tmp/upgrade.csv';
public const DEFAULT_DEPTH = 0; // first level only
/** @var string */
protected static $defaultName = 'devtools:estimate:cloc';
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setDefinition($this->createDefinition())
->setDescription('Generate CLOC statistics.')
->addUsage('/var/www/oro/src --depth=2 --trimPath=/var/www/oro/src --outputFile=/tmp/results.csv');
}
/**
* {@inheritdoc}
*/
public function getNativeDefinition()
{
return $this->createDefinition();
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$io->newLine();
$directory = $input->getArgument('directory');
$omitCsv = $input->getOption('omitCsv');
$outputFilePath = $input->getOption('outputFile');
$depth = $input->getOption('depth');
$trimPath = $input->getOption('trimPath');
$finder = new Finder();
$finder->directories()->sortByName()->depth($depth)->in($directory);
if (!$finder->hasResults()) {
$io->error(sprintf('No directories in the path %s provided', $directory));
return;
}
$results = [];
$keys = ['directory', 'php_files', 'php_code', 'js_files', 'js_code', 'twig_files', 'twig_code', 'yaml_files', 'yaml_code'];
foreach ($finder as $dir) {
$currentDirectory = $trimPath ? str_replace($trimPath, '', $dir->getRealPath()) : $dir->getRealPath();
$io->text(sprintf('Processing %s...', $currentDirectory));
$jsonOutput = shell_exec(sprintf('cloc %s --json', $dir->getRealPath()));
$stats = json_decode($jsonOutput, true);
$dirResult = [
'directory' => $currentDirectory,
'php_files' => $stats['PHP']['nFiles'] ?? '-',
'php_code' => $stats['PHP']['code'] ?? '-',
'js_files' => $stats['JavaScript']['nFiles'] ?? '-',
'js_code' => $stats['JavaScript']['code'] ?? '-',
'twig_files' => $stats['Twig']['nFiles'] ?? '-',
'twig_code' => $stats['Twig']['code'] ?? '-',
'yaml_files' => $stats['YAML']['nFiles'] ?? '-',
'yaml_code' => $stats['YAML']['code'] ?? '-',
];
$results[] = $dirResult;
}
$io->table($keys, $results);
if ($omitCsv === false) {
$serializer = new Serializer([], [new CsvEncoder()]);
file_put_contents($outputFilePath, $serializer->encode($results, 'csv'));
}
}
/**
* {@inheritdoc}
*/
private function createDefinition()
{
// phpcs:disable
return new InputDefinition([
new InputArgument('directory', InputArgument::REQUIRED, 'Directory on which cloc performs calculations'),
new InputOption('omitCsv', null, InputOption::VALUE_NONE, 'Generate csv with results'),
new InputOption('outputFile', null, InputOption::VALUE_REQUIRED, 'Filepath for generating csv.', self::DEFAULT_OUTPUT_FILE),
new InputOption('depth', null, InputOption::VALUE_REQUIRED, 'How deeply directory should be traversed.', self::DEFAULT_DEPTH),
new InputOption('trimPath', null, InputOption::VALUE_OPTIONAL, 'Optionally trim part of a filepath'),
]);
// phpcs:enable
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment