directory = isset($options['directory']) ? $options['directory'] : $this->builder->buildPath; $this->location = $this->builder->buildPath.'phan_tmp'; $this->ignore = isset($options['ignore']) && is_array($options['ignore']) ? $options['ignore'] : []; if (empty($this->ignore) && is_array($this->builder->ignore)) { $this->ignore = $this->builder->ignore; } $this->allowedWarnings = isset($options['allowed_warnings']) ? $options['allowed_warnings'] : 0; } /** * Executes Phan. * * @return bool */ public function execute() { if (!file_exists($this->location)) { mkdir($this->location, (0777 & ~umask()), true); } if (!is_writable($this->location)) { throw new \Exception(sprintf('The location %s is not writable or does not exist.', $this->location)); } // Find PHP files in a file $cmd = 'find -L %s -type f -name "**.php"'; foreach ($this->ignore as $ignore) { $cmd .= ' | grep -v '.$ignore; } $cmd .= ' > %s'; $this->builder->executeCommand($cmd, $this->directory, $this->location.'/phan.in'); $phan = $this->findBinary('phan'); // Launch Phan on PHP files with json output $cmd = $phan.' -f %s -i -m json -o %s'; $this->builder->executeCommand($cmd, $this->location.'/phan.in', $this->location.'/phan.out'); $warningCount = $this->processReport(file_get_contents($this->location.'/phan.out')); $this->build->storeMeta('phan-warnings', $warningCount); $success = true; if ($this->allowedWarnings != -1 && $warningCount > $this->allowedWarnings) { $success = false; } return $success; } /** * Process the Phan Json report. * * @param string $jsonString * * @return int * * @throws \Exception */ protected function processReport($jsonString) { $json = json_decode($jsonString, true); if ($json === false || !is_array($json)) { $this->builder->log($jsonString); throw new \Exception('Could not process the report generated by Phan.'); } $warnings = 0; foreach ($json as $data) { $this->build->reportError( $this->builder, 'phan', $data['check_name']."\n\n".$data['description'], $this->severity($data['severity']), $data['location']['path'] ?? '??', $data['location']['lines']['begin'] ?? 0, $data['location']['lines']['end'] ?? 0 ); $warnings++; } return $warnings; } /** * Transform severity from Phan to PHP-Censor. * * @param int $severity * * @return int */ protected function severity($severity) { if ($severity == 10) { return BuildError::SEVERITY_CRITICAL; } if ($severity == 5) { return BuildError::SEVERITY_NORMAL; } return BuildError::SEVERITY_LOW; } }