/** * Closes the logger process and writes the output file. * * @return void * @throws PHP_Depend_Log_NoLogOutputException If the no log target exists. */ public function close() { // Check for configured log file if ($this->logFile === null) { throw new PHP_Depend_Log_NoLogOutputException($this); } $bias = 0.1; $svg = new DOMDocument('1.0', 'UTF-8'); $svg->load(dirname(__FILE__) . '/chart.svg'); $bad = $svg->getElementById('jdepend.bad'); $good = $svg->getElementById('jdepend.good'); $layer = $svg->getElementById('jdepend.layer'); $legendTemplate = $svg->getElementById('jdepend.legend'); $max = 0; $min = 0; $items = array(); foreach ($this->code as $package) { if (!$package->isUserDefined()) { continue; } $metrics = $this->analyzer->getStats($package); if (count($metrics) === 0) { continue; } $size = $metrics['cc'] + $metrics['ac']; if ($size > $max) { $max = $size; } else { if ($min === 0 || $size < $min) { $min = $size; } } $items[] = array('size' => $size, 'abstraction' => $metrics['a'], 'instability' => $metrics['i'], 'distance' => $metrics['d'], 'name' => $package->getName()); } $diff = ($max - $min) / 10; // Sort items by size usort($items, create_function('$a, $b', 'return ($a["size"] - $b["size"]);')); foreach ($items as $item) { if ($item['distance'] < $bias) { $ellipse = $good->cloneNode(true); } else { $ellipse = $bad->cloneNode(true); } $r = 15; if ($diff !== 0) { $r = 5 + ($item['size'] - $min) / $diff; } $a = $r / 15; $e = 50 - $r + $item['abstraction'] * 320; $f = 20 - $r + 190 - $item['instability'] * 190; $transform = "matrix({$a}, 0, 0, {$a}, {$e}, {$f})"; $ellipse->removeAttribute('xml:id'); $ellipse->setAttribute('id', uniqid('pdepend_')); $ellipse->setAttribute('title', $item['name']); $ellipse->setAttribute('transform', $transform); $layer->appendChild($ellipse); $result = preg_match('#\\\\([^\\\\]+)$#', $item['name'], $found); if ($result && count($found)) { $angle = rand(0, 314) / 100 - 1.57; $legend = $legendTemplate->cloneNode(true); $legend->removeAttribute('xml:id'); $legend->setAttribute('x', $e + $r * (1 + cos($angle))); $legend->setAttribute('y', $f + $r * (1 + sin($angle))); $legend->nodeValue = $found[1]; $legendTemplate->parentNode->appendChild($legend); } } $bad->parentNode->removeChild($bad); $good->parentNode->removeChild($good); $legendTemplate->parentNode->removeChild($legendTemplate); $temp = PHP_Depend_Util_FileUtil::getSysTempDir(); $temp .= '/' . uniqid('pdepend_') . '.svg'; $svg->save($temp); PHP_Depend_Util_ImageConvert::convert($temp, $this->logFile); // Remove temp file unlink($temp); }
/** * Visits a package node. * * @param PHP_Depend_Code_Class $package The package class node. * * @return void * @see PHP_Depend_VisitorI::visitPackage() */ public function visitPackage(PHP_Depend_Code_Package $package) { if (!$package->isUserDefined()) { return; } $stats = $this->analyzer->getStats($package); if (count($stats) === 0) { return; } $doc = $this->packages->ownerDocument; $this->concreteClasses = $doc->createElement('ConcreteClasses'); $this->abstractClasses = $doc->createElement('AbstractClasses'); $packageXml = $doc->createElement('Package'); $packageXml->setAttribute('name', $package->getName()); $statsXml = $doc->createElement('Stats'); $statsXml->appendChild($doc->createElement('TotalClasses'))->appendChild($doc->createTextNode($stats['tc'])); $statsXml->appendChild($doc->createElement('ConcreteClasses'))->appendChild($doc->createTextNode($stats['cc'])); $statsXml->appendChild($doc->createElement('AbstractClasses'))->appendChild($doc->createTextNode($stats['ac'])); $statsXml->appendChild($doc->createElement('Ca'))->appendChild($doc->createTextNode($stats['ca'])); $statsXml->appendChild($doc->createElement('Ce'))->appendChild($doc->createTextNode($stats['ce'])); $statsXml->appendChild($doc->createElement('A'))->appendChild($doc->createTextNode($stats['a'])); $statsXml->appendChild($doc->createElement('I'))->appendChild($doc->createTextNode($stats['i'])); $statsXml->appendChild($doc->createElement('D'))->appendChild($doc->createTextNode($stats['d'])); $dependsUpon = $doc->createElement('DependsUpon'); foreach ($this->analyzer->getEfferents($package) as $efferent) { $efferentXml = $doc->createElement('Package'); $efferentXml->appendChild($doc->createTextNode($efferent->getName())); $dependsUpon->appendChild($efferentXml); } $usedBy = $doc->createElement('UsedBy'); foreach ($this->analyzer->getAfferents($package) as $afferent) { $afferentXml = $doc->createElement('Package'); $afferentXml->appendChild($doc->createTextNode($afferent->getName())); $usedBy->appendChild($afferentXml); } $packageXml->appendChild($statsXml); $packageXml->appendChild($this->concreteClasses); $packageXml->appendChild($this->abstractClasses); $packageXml->appendChild($dependsUpon); $packageXml->appendChild($usedBy); if (($cycles = $this->analyzer->getCycle($package)) !== null) { $cycleXml = $doc->createElement('Package'); $cycleXml->setAttribute('Name', $package->getName()); foreach ($cycles as $cycle) { $cycleXml->appendChild($doc->createElement('Package'))->appendChild($doc->createTextNode($cycle->getName())); } $this->cycles->appendChild($cycleXml); } foreach ($package->getTypes() as $type) { $type->accept($this); } if ($this->concreteClasses->firstChild === null && $this->abstractClasses->firstChild === null) { return; } $this->packages->appendChild($packageXml); }
/** * Tests the generated package metrics. * * @return void */ public function testGenerateMetrics() { $visitor = new PHP_Depend_Metrics_Dependency_Analyzer(); $packages = self::parseCodeResourceForTest(); $visitor->analyze($packages); $actual = array(); foreach ($packages as $package) { $actual[$package->getName()] = $visitor->getStats($package); } self::assertEquals($this->_input, $actual); }