* @license PHP License * @package WB * @subpackage content */ /** * Load base class */ WBClass::load('WBContent' ,'WBCache'); /** * Content component: Subversion * * Display subversion logs etc * * CAUTION: * When using SSL, calling the subversion command mail fail because of unknown * SSL certificates. Normaly svn intercatively asks the user to accept or reject * the unknwon certificate. Since svn is called by the web-server there is no * user-interaction. (See the error log of your web-server.) * * To solve this problem, either select a suitable svn configuration dir (--config) * or simply login as web-server user (www-data on Debian linux), call "svn info"# * manually and accept the certificate. * * Please also note, that svn wants store certificates in ~/.subversion/. This mail * faile if the web-server does not have write permissions - which is most likely * the case. * * * @version 0.1.0 * @package WB * @subpackage content */ class WBContent_Subversion extends WBContent { /** * my parameter list * @var array */ protected $config = array( 'process' => 'log', 'ttl' => 1800, 'limit' => 20, 'repository' => 'https://gerd.exit0.net/svn/wombat/' ); /** * SVN command line tool * @var string */ protected $cmdSvn = 'svn'; /** * run * * run component * * @return array parameter list */ public function run() { // get SVN command $this->cmdSvn = WBParam::get('wb/svn/cmd', $this->cmdSvn); switch (strtolower($this->config['process'])) { case 'log'; default: $this->processLog(); break; } return $this->config; } /** * process log * */ protected function processLog() { $this->loadTemplates('log'); $cache = __CLASS__ . ':log:' . md5($this->config['repository'] . ':' . $this->config['limit']); $list = WBCache::get($cache); if(!$list) { $list = $this->getLog(); WBCache::set($cache, $list, array('ttl' => $this->config['ttl'])); } $this->tmpl->addRows('list_entry', $list); } /** * get SVN log * * Fetch log from serer and parse output * * @return array */ protected function getLog() { $list = array(); $cmd = sprintf('%s log -v -l %d %s', $this->cmdSvn, $this->config['limit'], $this->config['repository']); $ret = 0; $out = array(); exec($cmd, $out, $ret); if ($ret != 0) { WBClass::load('WBException_Exec'); $e = new WBException_Exec(1, __CLASS__); $e->setCommand($cmd, $ret, $out); throw $e; return $list; } /* * Parse SVN's output * * The following loop and switch/case statement represent a statemaching. */ $state = 'start'; $rec = array(); foreach ($out as $o) { switch ($state) { case 'files': if (empty($o)) { $rec['message'] = array(); $state = 'message'; break; } if (preg_match('/^\s+([MA]).?\s+(.+)$/', $o, $match)) { if ($match[1] == 'A') { $rec['added_files'][] = $match[2]; } else if ($match[1] == 'M') { $rec['modified_files'][] = $match[2]; } } break; case 'changed_path': if (preg_match('/^Changed paths/', $o)) { $rec['added'] = 0; $rec['added_files'] = array(); $rec['modified'] = 0; $rec['modified_files'] = array(); $state = 'files'; } break; case 'head': if (preg_match('/^r(\d+)\s+\|/', $o, $match)) { $rec['revision'] = $match[1]; $o = explode('|', $o); $o = array_map('trim',$o); $timestamp = explode(' (', $o[2]); $timestamp = $timestamp[0]; $rec['author'] = $o[1]; $rec['timestamp'] = gmdate('Y-m-d H:i:s', strtotime($timestamp)); $state = 'changed_path'; } break; case 'message': case 'start': default: if (strncmp($o, '----------', 10) == 0) { // save current record if (!empty($rec)) { $rec['modified'] = count($rec['modified_files']); $rec['modified_files'] = implode("\n", $rec['modified_files']); $rec['added'] = count($rec['added_files']); $rec['added_files'] = implode("\n", $rec['added_files']); $rec['message'] = implode("\n", $rec['message']); $list[] = $rec; } $state = 'head'; $rec = array(); } else if ($state == 'message') { $rec['message'][] = $o; } break; } } return $list; } /** * receive output * * fetch output of this content component * * @return string */ public function getString() { return $this->tmpl->getParsedTemplate('snippet'); } } ?>