diff --git a/PHPCI/Builder.php b/PHPCI/Builder.php index 92b43e9d..4547564a 100644 --- a/PHPCI/Builder.php +++ b/PHPCI/Builder.php @@ -258,6 +258,11 @@ class Builder implements LoggerAwareInterface return $this->commandExecutor->getLastOutput(); } + public function logExecOutput($enableLog = true) + { + $this->commandExecutor->logExecOutput = $enableLog; + } + /** * Find a binary required by a plugin. * @param $binary diff --git a/PHPCI/Helper/CommandExecutor.php b/PHPCI/Helper/CommandExecutor.php index 2e88b938..dc284b6a 100644 --- a/PHPCI/Helper/CommandExecutor.php +++ b/PHPCI/Helper/CommandExecutor.php @@ -25,6 +25,9 @@ class CommandExecutor protected $lastOutput; + public $logExecOutput = true; + + /** * The path which findBinary will look in. * @var string @@ -80,7 +83,7 @@ class CommandExecutor $lastOutput = trim($lastOutput, '"'); } - if (!empty($this->lastOutput) && ($this->verbose|| $status != 0)) { + if ($this->logExecOutput && !empty($this->lastOutput) && ($this->verbose|| $status != 0)) { $this->logger->log($this->lastOutput); } diff --git a/PHPCI/Model/Build.php b/PHPCI/Model/Build.php index c5b0dc1a..edd8fd2c 100644 --- a/PHPCI/Model/Build.php +++ b/PHPCI/Model/Build.php @@ -157,4 +157,9 @@ class Build extends BuildBase return $config; } + + public function getFileLink($file, $line = null) + { + return null; + } } diff --git a/PHPCI/Model/Build/GithubBuild.php b/PHPCI/Model/Build/GithubBuild.php index 98d7a8eb..02118c60 100644 --- a/PHPCI/Model/Build/GithubBuild.php +++ b/PHPCI/Model/Build/GithubBuild.php @@ -93,4 +93,24 @@ class GithubBuild extends RemoteGitBuild return 'https://github.com/' . $this->getProject()->getReference() . '.git'; } } + + public function getCommitMessage() + { + $rtn = $this->data['commit_message']; + + $rtn = preg_replace('/\#([0-9]+)/', '#$1', $rtn); + $rtn = preg_replace('/\@([a-zA-Z0-9_]+)/', '@$1', $rtn); + + return $rtn; + } + + public function getFileLinkTemplate() + { + $link = 'https://github.com/' . $this->getProject()->getReference() . '/'; + $link .= 'blob/' . $this->getBranch() . '/'; + $link .= '{FILE}'; + $link .= '#L{LINE}'; + + return $link; + } } diff --git a/PHPCI/Plugin/PhpMessDetector.php b/PHPCI/Plugin/PhpMessDetector.php index f68d7aec..7745c363 100755 --- a/PHPCI/Plugin/PhpMessDetector.php +++ b/PHPCI/Plugin/PhpMessDetector.php @@ -124,7 +124,12 @@ class PhpMessDetector implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin $path = $this->path; } - $cmd = $phpmd . ' "%s" text %s %s %s'; + $cmd = $phpmd . ' "%s" xml %s %s %s'; + + // Disable exec output logging, as we don't want the XML report in the log: + $this->phpci->logExecOutput(false); + + // Run PHPMD: $this->phpci->executeCommand( $cmd, $path, @@ -133,9 +138,14 @@ class PhpMessDetector implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin $suffixes ); + // Re-enable exec output logging: + $this->phpci->logExecOutput(true); + $success = true; - $errors = count(array_filter(explode(PHP_EOL, trim($this->phpci->getLastOutput())))); + + list($errors, $data) = $this->processReport(trim($this->phpci->getLastOutput())); $this->build->storeMeta('phpmd-warnings', $errors); + $this->build->storeMeta('phpmd-data', $data); if ($this->allowed_warnings != -1 && $errors > $this->allowed_warnings) { $success = false; @@ -150,4 +160,38 @@ class PhpMessDetector implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin $this->{$key} = $options[$key]; } } + + protected function processReport($xml) + { + $xml = simplexml_load_string($xml); + + if ($xml === false) { + throw new \Exception('Could not process PHPMD report XML.'); + } + + $warnings = 0; + $data = array(); + + foreach ($xml->file as $file) { + $fileName = (string)$file['name']; + $fileName = str_replace($this->phpci->buildPath, '', $fileName); + + foreach ($file->violation as $violation) { + $warnings++; + $warning = array( + 'file' => $fileName, + 'line_start' => (int)$violation['beginline'], + 'line_end' => (int)$violation['endline'], + 'rule' => (string)$violation['rule'], + 'ruleset' => (string)$violation['ruleset'], + 'priority' => (int)$violation['priority'], + 'message' => (string)$violation, + ); + + $data[] = $warning; + } + } + + return array($warnings, $data); + } } diff --git a/public/assets/css/phpci.css b/public/assets/css/phpci.css index ce34fe82..6b09a8e7 100644 --- a/public/assets/css/phpci.css +++ b/public/assets/css/phpci.css @@ -57,11 +57,16 @@ td .label { #title { - border-bottom: 1px solid #ccc; - margin: -10px -10px 15px -10px; - padding: 10px; } + #title img { + border: 1px solid #fff; + border-radius: 50%; + box-shadow: 2px 2px 2px rgba(0,0,0,0.1); + margin-bottom: 15px; + margin-right: 15px; + } + #title h1 { font-size: 2em; @@ -69,6 +74,23 @@ td .label { padding: 0; } + #title h1 span { + font-weight: lighter; + margin-left: 15px; + } + + #title h1 label { + margin-top: -6px; + } + + #build-info { + margin-left: 100px; + } + .commit-message { + font-size: 1.2em; + margin-bottom: 10px; + } + h2 { color: #246; font-size: 1.8em; @@ -135,8 +157,13 @@ td .label { .ui-sortable-placeholder * { visibility: hidden; } -.ui-plugin { padding-top: 15px; } +.ui-plugin .panel-title { + cursor: move; +} +.panel-body table { + margin-bottom: 0; +} #loading { font-family: Roboto, Arial, Sans-Serif; diff --git a/public/assets/js/build-plugins/phpmd.js b/public/assets/js/build-plugins/phpmd.js new file mode 100644 index 00000000..56e8e995 --- /dev/null +++ b/public/assets/js/build-plugins/phpmd.js @@ -0,0 +1,69 @@ +var phpmdPlugin = PHPCI.UiPlugin.extend({ + id: 'build-phpmd-warnings', + css: 'col-lg-12 col-md-12 col-sm-12 col-xs-12', + title: 'PHP Mess Detector', + lastData: null, + displayOnUpdate: false, + + register: function() { + var self = this; + var query = PHPCI.registerQuery('phpmd-data', -1, {key: 'phpmd-data'}) + + $(window).on('phpmd-data', function(data) { + self.onUpdate(data); + }); + + $(window).on('build-updated', function(data) { + if (data.queryData.status > 1) { + self.displayOnUpdate = true; + query(); + } + }); + }, + + render: function() { + + return $('' + + '' + + '' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + + '
FileStartEndMessage
'); + }, + + onUpdate: function(e) { + if (this.lastData && this.lastData[0]) { + return; + } + + this.lastData = e.queryData; + + var errors = this.lastData[0].meta_value; + var tbody = $('#phpmd-data tbody'); + tbody.empty(); + + for (var i in errors) { + var file = errors[i].file; + + if (PHPCI.fileLinkTemplate) { + var fileLink = PHPCI.fileLinkTemplate.replace('{FILE}', file); + fileLink = fileLink.replace('{LINE}', errors[i].line_start); + + file = '' + file + ''; + } + + var row = $('' + + ''+file+'' + + ''+errors[i].line_start+'' + + ''+errors[i].line_end+'' + + ''+errors[i].message+''); + + tbody.append(row); + } + } +}); + +PHPCI.registerPlugin(new phpmdPlugin()); diff --git a/public/assets/js/phpci.js b/public/assets/js/phpci.js index 7cf07458..e4c29791 100644 --- a/public/assets/js/phpci.js +++ b/public/assets/js/phpci.js @@ -382,7 +382,7 @@ var PHPCIObject = Class.extend({ } $('#plugins').sortable({ - handle: '.title', + handle: '.panel-title', connectWith: '#plugins', update: self.storePluginOrder }); @@ -391,16 +391,13 @@ var PHPCIObject = Class.extend({ }, renderPlugin: function(plugin) { - var output = $('
').addClass('box-content').append(plugin.render()); + var output = $('
').addClass('panel-body').append(plugin.render()); var container = $('
').addClass('ui-plugin ' + plugin.css); var content = $('
').attr('id', plugin.id).append(output); - - if (plugin.box) { - content.addClass('box'); - } + content.addClass('panel'); if (plugin.title) { - content.prepend('

'+plugin.title+'

'); + content.prepend('

'+plugin.title+'

'); } content.append(output);