Created
September 11, 2011 13:28
-
-
Save jeffery/1209578 to your computer and use it in GitHub Desktop.
Script to visualize dependencies in a PHP project using PHP_Depend results
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env php | |
<?php | |
/** | |
* Usage: | |
* pdepend --jdepend-xml=/tmp/jdepend.xml /path/to/source | |
* | |
* ./dependencies.php /tmp/jdepend.xml -o /tmp/jdepend.svg | |
*/ | |
class Dependencies | |
{ | |
/** | |
* @var DOMDocument | |
*/ | |
protected $logFile = null; | |
/** | |
* @var string | |
*/ | |
protected $output = null; | |
protected $colors = array( | |
'#aaaaaa', | |
'#aaabbb', | |
'#bbbbbb', | |
'#bbbccc', | |
'#cccccc', | |
'#cccddd', | |
'#dddddd', | |
'#dddeee', | |
'#eeeeee', | |
'#eeefff', | |
'#ffffff' | |
); | |
public function __construct(array $options) | |
{ | |
if ($this->parseOptions($options)) { | |
$this->evaluate(); | |
} | |
} | |
protected function evaluate() | |
{ | |
$output = "digraph {\n" . | |
" rankdir = LR\n"; | |
$xpath = new DOMXPath($this->logFile); | |
$nodes = $xpath->query("//Packages/Package"); | |
$names = array(); | |
foreach ($nodes as $i => $node) { | |
$name = "p{$i}"; | |
$label = $node->getAttribute('name'); | |
$d = (int) 10 * round($node->getElementsByTagName("D")->item(0)->nodeValue, 1); | |
$options = sprintf( | |
'style=filled, fillcolor="%s", label="%s"', | |
$this->colors[$d], | |
str_replace('\\', '::', $label) | |
); | |
$output .= " {$name} [{$options}];\n"; | |
$names[$name] = $label; | |
} | |
foreach ($names as $name => $label) { | |
$nodes = $xpath->query("//Packages/Package[@name = '{$label}']/DependsUpon/Package"); | |
foreach ($nodes as $node) { | |
if (false === ($idx = array_search($node->nodeValue, $names))) { | |
continue; | |
} | |
if ($this->isCycle($label, $node->nodeValue)) { | |
$output .= " {$name} -> {$idx} [color=\"red\"];\n"; | |
} else { | |
$output .= " {$name} -> {$idx};\n"; | |
} | |
} | |
} | |
$output .= "}\n"; | |
$this->dumpOutput($output); | |
} | |
protected function isCycle($name0, $name1) | |
{ | |
$xpath = new DOMXPath($this->logFile); | |
return $xpath->query("//Packages/Package[ | |
@name = '{$name0}' | |
]/UsedBy/Package[ | |
text() = '{$name1}' | |
]")->length > 0; | |
} | |
protected function dumpOutput($output) | |
{ | |
if ($this->output) { | |
$this->dumpOutputToFile($output); | |
} else { | |
$this->dumpOutputToStdout($output); | |
} | |
} | |
protected function dumpOutputToFile($output) | |
{ | |
$file = $this->output; | |
$ext = pathinfo($file, PATHINFO_EXTENSION); | |
if ($ext === '') { | |
$ext = 'svg'; | |
$file .= '.svg'; | |
} | |
$dir = pathinfo($file, PATHINFO_DIRNAME); | |
if (false === file_exists($dir)) { | |
mkdir($dir, 0775, true); | |
} | |
$input = tempnam(sys_get_temp_dir(), 'dot_'); | |
file_put_contents($input, $output); | |
shell_exec( | |
sprintf( | |
'dot -T%s -o%s %s', | |
escapeshellarg($ext), | |
escapeshellarg($file), | |
escapeshellarg($input) | |
) | |
); | |
unlink($input); | |
} | |
protected function dumpOutputToStdout($output) | |
{ | |
echo $output; | |
} | |
protected function parseOptions(array $options) | |
{ | |
if (in_array('-h', $options) || in_array('--help', $options)) { | |
return $this->printHelp(); | |
} | |
$logFile = array_shift($options); | |
if (false === file_exists($logFile)) { | |
fwrite(STDERR, 'The specified log file "' . $logFile . '" not exists.' . PHP_EOL); | |
return $this->printHelp(); | |
} | |
$this->logFile = new DOMDocument(); | |
$this->logFile->load($logFile); | |
if (count($options) % 2 == 1) { | |
return $this->printHelp(); | |
} | |
for ($i = 0; $i < count($options); $i+=2) { | |
switch ($options[$i]) { | |
case '-o': | |
case '--output': | |
$this->output = $options[$i+1]; | |
break; | |
default: | |
fwrite(STDERR, 'Unknown option <' . $options[$i] . '>' . PHP_EOL); | |
return $this->printHelp(); | |
} | |
} | |
return true; | |
} | |
protected function printHelp() | |
{ | |
echo 'Usage: ', basename(__FILE__), ' <logfile>', | |
PHP_EOL, PHP_EOL, | |
' -o --output $O Write the generated image into this file. Otherwise ', PHP_EOL, | |
' output generated dot file on STDOUT.', | |
PHP_EOL, PHP_EOL, | |
' -h --help Displays this help text.', PHP_EOL; | |
return false; | |
} | |
public static function main(array $argv) | |
{ | |
$options = $argv; | |
array_shift($options); | |
new Dependencies($options); | |
} | |
} | |
Dependencies::main($argv); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment