/** * Check the files. * * @param array $files * @param bool $cache * * @return array */ public function lint($files = [], $cache = true) { if (empty($files)) { $files = $this->getFiles(); } $processCallback = is_callable($this->processCallback) ? $this->processCallback : function () { }; $errors = []; $running = []; $newCache = []; while (!empty($files) || !empty($running)) { for ($i = count($running); !empty($files) && $i < $this->procLimit; ++$i) { $file = array_shift($files); $filename = $file->getRealpath(); if (!isset($this->cache[$filename]) || $this->cache[$filename] !== md5_file($filename)) { $running[$filename] = new Lint(PHP_BINARY . ' -d error_reporting=E_ALL -d display_errors=On -l ' . escapeshellarg($filename)); $running[$filename]->start(); } else { $newCache[$filename] = $this->cache[$filename]; } } foreach ($running as $filename => $lintProcess) { if ($lintProcess->isRunning()) { continue; } unset($running[$filename]); if ($lintProcess->hasSyntaxError()) { $processCallback('error', $filename); $errors[$filename] = array_merge(['file' => $filename], $lintProcess->getSyntaxError()); } else { $newCache[$filename] = md5_file($filename); $processCallback('ok', $filename); } } $cache && Cache::put($newCache); } return $errors; }
/** * Executes the current command. * * This method is not abstract because you can use this class * as a concrete class. In this case, instead of defining the * execute() method, you set the code to execute by passing * a Closure to the setCode() method. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * * @throws LogicException When this abstract method is not implemented * * @return null|int null or 0 if everything went fine, or an error code * * @see setCode() */ protected function execute(InputInterface $input, OutputInterface $output) { $startTime = microtime(true); $startMemUsage = memory_get_usage(true); $output->writeln($this->getApplication()->getLongVersion() . " by overtrue and contributors.\n"); $options = $this->mergeOptions(); $verbosity = $output->getVerbosity(); if ($verbosity >= OutputInterface::VERBOSITY_DEBUG) { $output->writeln('Options: ' . json_encode($options)); } $linter = new Linter($options['path'], $options['exclude'], $options['extensions']); $linter->setProcessLimit($options['jobs']); if (!$input->getOption('no-cache') && Cache::isCached()) { $output->writeln('Using cache.'); $linter->setCache(Cache::get()); } $fileCount = count($linter->getFiles()); if ($fileCount <= 0) { $output->writeln('<info>Could not find files to lint</info>'); return 0; } $errors = $this->executeLint($linter, $output, $fileCount, !$input->getOption('no-cache')); $timeUsage = Helper::formatTime(microtime(true) - $startTime); $memUsage = Helper::formatMemory(memory_get_usage(true) - $startMemUsage); $code = 0; $errCount = count($errors); $output->writeln("\n\nTime: {$timeUsage}, Memory: {$memUsage}MB\n"); if ($errCount > 0) { $output->writeln('<error>FAILURES!</error>'); $output->writeln("<error>Files: {$fileCount}, Failures: {$errCount}</error>"); $this->showErrors($errors); $code = 1; } else { $output->writeln("<info>OK! (Files: {$fileCount}, Success: {$fileCount})</info>"); } return $code; }