|
| 1 | +<?php |
| 2 | + |
| 3 | +namespace TheSeer\phpDox\Generator\Enricher { |
| 4 | + |
| 5 | + use TheSeer\fDOM\fDOMDocument; |
| 6 | + use TheSeer\fDOM\fDOMElement; |
| 7 | + use TheSeer\fDOM\fDOMException; |
| 8 | + use TheSeer\phpDox\Generator\AbstractUnitObject; |
| 9 | + use TheSeer\phpDox\Generator\ClassStartEvent; |
| 10 | + use TheSeer\phpDox\Generator\InterfaceStartEvent; |
| 11 | + use TheSeer\phpDox\Generator\TraitStartEvent; |
| 12 | + |
| 13 | + class PHPCs extends AbstractEnricher implements ClassEnricherInterface, TraitEnricherInterface, InterfaceEnricherInterface { |
| 14 | + |
| 15 | + private $config; |
| 16 | + private $findings = NULL; |
| 17 | + const XMLNS = 'http://xml.phpdox.net/src#'; |
| 18 | + |
| 19 | + public function __construct(PHPCsConfig $config) { |
| 20 | + $this->config = $config; |
| 21 | + $this->loadFindings($config->getLogFilePath()); |
| 22 | + } |
| 23 | + |
| 24 | + /** |
| 25 | + * @return string |
| 26 | + */ |
| 27 | + public function getName() { |
| 28 | + return 'PHPCS XML'; |
| 29 | + } |
| 30 | + |
| 31 | + public function enrichClass(ClassStartEvent $event) { |
| 32 | + $this->enrichUnit($event->getClass()); |
| 33 | + } |
| 34 | + |
| 35 | + public function enrichInterface(InterfaceStartEvent $event) { |
| 36 | + $this->enrichUnit($event->getInterface()); |
| 37 | + } |
| 38 | + |
| 39 | + public function enrichTrait(TraitStartEvent $event) { |
| 40 | + $this->enrichUnit($event->getTrait()); |
| 41 | + } |
| 42 | + |
| 43 | + private function enrichUnit(AbstractUnitObject $ctx) { |
| 44 | + $file = $ctx->getSourceFile(); |
| 45 | + if (isset($this->findings[$file])) { |
| 46 | + $this->processFindings($ctx->asDom(), $this->findings[$file]); |
| 47 | + } |
| 48 | + } |
| 49 | + |
| 50 | + private function loadFindings($xmlFile) { |
| 51 | + $this->findings = array(); |
| 52 | + try { |
| 53 | + if (!file_exists($xmlFile)) { |
| 54 | + throw new EnricherException( |
| 55 | + sprintf('Logfile "%s" not found.', $xmlFile), |
| 56 | + EnricherException::LoadError |
| 57 | + ); |
| 58 | + } |
| 59 | + $dom = new fDOMDocument(); |
| 60 | + $dom->load($xmlFile); |
| 61 | + foreach($dom->query('/phpcs/file') as $file) { |
| 62 | + $this->findings[$file->getAttribute('name')] = $file->query('*'); |
| 63 | + } |
| 64 | + } catch (fDOMException $e) { |
| 65 | + throw new EnricherException( |
| 66 | + 'Parsing phpcs logfile failed: ' . $e->getMessage(), |
| 67 | + EnricherException::LoadError |
| 68 | + ); |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + private function processFindings(fDOMDocument $dom, \DOMNodeList $findings) { |
| 73 | + |
| 74 | + foreach($findings as $finding) { |
| 75 | + /** @var fDOMElement $finding */ |
| 76 | + $line = $finding->getAttribute('line'); |
| 77 | + $ref = $dom->queryOne(sprintf('//phpdox:*/*[@line = %d or (@start <= %d and @end >= %d)]', $line, $line, $line)); |
| 78 | + if (!$ref) { |
| 79 | + // One src file may contain multiple classes/traits/interfaces, so the |
| 80 | + // finding might not apply to the current object since findings are based on filenames |
| 81 | + // but we have individual objects - so we just ignore the finding for this context |
| 82 | + continue; |
| 83 | + } |
| 84 | + |
| 85 | + $enrichment = $this->getEnrichtmentContainer($ref, 'checkstyle'); |
| 86 | + $enrichFinding = $dom->createElementNS(self::XMLNS, $finding->tagName); |
| 87 | + $enrichment->appendChild($enrichFinding); |
| 88 | + foreach($finding->attributes as $attr) { |
| 89 | + if ($attr->localName == 'severity') { |
| 90 | + continue; |
| 91 | + } |
| 92 | + $enrichFinding->setAttributeNode($dom->importNode($attr, true)); |
| 93 | + } |
| 94 | + $enrichFinding->setAttribute('message', $finding->nodeValue); |
| 95 | + } |
| 96 | + |
| 97 | + } |
| 98 | + } |
| 99 | + |
| 100 | +} |
0 commit comments