Attach logger to projectlist as observer
Attach logger to projectlist as observer

<?php <?php
/** /**
* Debug logging class * Debug logging class
* *
* @author Christopher Han <xiphux@gmail.com> * @author Christopher Han <xiphux@gmail.com>
* @copyright Copyright (c) 2010 Christopher Han * @copyright Copyright (c) 2010 Christopher Han
* @package GitPHP * @package GitPHP
*/ */
class GitPHP_DebugLog class GitPHP_DebugLog implements GitPHP_Observer_Interface
{ {
/** /**
* Stores the singleton instance * Stores the singleton instance
* *
* @var GitPHP_DebugLog * @var GitPHP_DebugLog
*/ */
protected static $instance; protected static $instance;
   
/** /**
* Stores whether logging is enabled * Stores whether logging is enabled
* *
* @var boolean * @var boolean
*/ */
protected $enabled = false; protected $enabled = false;
   
/** /**
* Stores whether benchmarking is enabled * Stores whether benchmarking is enabled
* *
* @var boolean * @var boolean
*/ */
protected $benchmark = false; protected $benchmark = false;
   
/** /**
* Stores the starting instant * Stores the starting instant
* *
* @var float * @var float
*/ */
protected $startTime; protected $startTime;
   
/** /**
* Stores the starting memory * Stores the starting memory
* *
* @var int * @var int
*/ */
protected $startMem; protected $startMem;
   
/** /**
* Stores the log entries * Stores the log entries
* *
* @var string[] * @var string[]
*/ */
protected $entries = array(); protected $entries = array();
   
/** /**
* Returns the singleton instance * Returns the singleton instance
* *
* @return GitPHP_DebugLog instance of logging class * @return GitPHP_DebugLog instance of logging class
*/ */
public static function GetInstance() public static function GetInstance()
{ {
if (!self::$instance) { if (!self::$instance) {
$config = GitPHP_Config::GetInstance(); $config = GitPHP_Config::GetInstance();
self::$instance = new GitPHP_DebugLog($config->GetValue('debug', false), $config->GetValue('benchmark', false)); self::$instance = new GitPHP_DebugLog($config->GetValue('debug', false), $config->GetValue('benchmark', false));
} }
   
return self::$instance; return self::$instance;
} }
   
/** /**
* Releases the singleton instance * Releases the singleton instance
*/ */
public static function DestroyInstance() public static function DestroyInstance()
{ {
self::$instance = null; self::$instance = null;
} }
   
/** /**
* Constructor * Constructor
* *
* @param boolean $enabled whether log should be enabled * @param boolean $enabled whether log should be enabled
* @param boolean $benchmark whether benchmarking should be enabled * @param boolean $benchmark whether benchmarking should be enabled
*/ */
private function __construct($enabled = false, $benchmark = false) private function __construct($enabled = false, $benchmark = false)
{ {
$this->startTime = microtime(true); $this->startTime = microtime(true);
$this->startMem = memory_get_usage(); $this->startMem = memory_get_usage();
   
$this->enabled = $enabled; $this->enabled = $enabled;
$this->benchmark = $benchmark; $this->benchmark = $benchmark;
} }
   
/** /**
* Sets start time * Sets start time
* *
* @param float $start starting microtime * @param float $start starting microtime
*/ */
public function SetStartTime($start) public function SetStartTime($start)
{ {
$this->startTime = $start; $this->startTime = $start;
} }
   
/** /**
* Sets start memory * Sets start memory
* *
* @param integer $start starting memory * @param integer $start starting memory
*/ */
public function SetStartMemory($start) public function SetStartMemory($start)
{ {
$this->startMem = $start; $this->startMem = $start;
} }
   
/** /**
* Log an entry * Log an entry
* *
* @param string $message message to log * @param string $message message to log
*/ */
public function Log($message) public function Log($message)
{ {
if (!$this->enabled) if (!$this->enabled)
return; return;
   
$entry = array(); $entry = array();
if ($this->benchmark) { if ($this->benchmark) {
$entry['time'] = microtime(true); $entry['time'] = microtime(true);
$entry['mem'] = memory_get_usage(); $entry['mem'] = memory_get_usage();
} }
   
$entry['msg'] = $message; $entry['msg'] = $message;
$this->entries[] = $entry; $this->entries[] = $entry;
} }
   
/** /**
* Gets whether logging is enabled * Gets whether logging is enabled
* *
* @return boolean true if logging is enabled * @return boolean true if logging is enabled
*/ */
public function GetEnabled() public function GetEnabled()
{ {
return $this->enabled; return $this->enabled;
} }
   
/** /**
* Sets whether logging is enabled * Sets whether logging is enabled
* *
* @param boolean $enable true if logging is enabled * @param boolean $enable true if logging is enabled
*/ */
public function SetEnabled($enable) public function SetEnabled($enable)
{ {
$this->enabled = $enable; $this->enabled = $enable;
} }
   
/** /**
* Gets whether benchmarking is enabled * Gets whether benchmarking is enabled
* *
* @return boolean true if benchmarking is enabled * @return boolean true if benchmarking is enabled
*/ */
public function GetBenchmark() public function GetBenchmark()
{ {
return $this->benchmark; return $this->benchmark;
} }
   
/** /**
* Sets whether benchmarking is enabled * Sets whether benchmarking is enabled
* *
* @param boolean $bench true if benchmarking is enabled * @param boolean $bench true if benchmarking is enabled
*/ */
public function SetBenchmark($bench) public function SetBenchmark($bench)
{ {
$this->benchmark = $bench; $this->benchmark = $bench;
} }
   
/** /**
* Gets log entries * Gets log entries
* *
* @return string[] log entries * @return string[] log entries
*/ */
public function GetEntries() public function GetEntries()
{ {
$data = array(); $data = array();
if ($this->enabled) { if ($this->enabled) {
   
if ($this->benchmark) { if ($this->benchmark) {
$endTime = microtime(true); $endTime = microtime(true);
$endMem = memory_get_usage(); $endMem = memory_get_usage();
   
$lastTime = $this->startTime; $lastTime = $this->startTime;
$lastMem = $this->startMem; $lastMem = $this->startMem;
   
$data[] = 'DEBUG: [' . $this->startTime . '] [' . $this->startMem . ' bytes] Start'; $data[] = 'DEBUG: [' . $this->startTime . '] [' . $this->startMem . ' bytes] Start';
   
} }
   
foreach ($this->entries as $entry) { foreach ($this->entries as $entry) {
if ($this->benchmark) { if ($this->benchmark) {
$data[] = 'DEBUG: [' . $entry['time'] . '] [' . ($entry['time'] - $this->startTime) . ' sec since start] [' . ($entry['time'] - $lastTime) . ' sec since last] [' . $entry['mem'] . ' bytes] [' . ($entry['mem'] - $this->startMem) . ' bytes since start] [' . ($entry['mem'] - $lastMem) . ' bytes since last] ' . $entry['msg']; $data[] = 'DEBUG: [' . $entry['time'] . '] [' . ($entry['time'] - $this->startTime) . ' sec since start] [' . ($entry['time'] - $lastTime) . ' sec since last] [' . $entry['mem'] . ' bytes] [' . ($entry['mem'] - $this->startMem) . ' bytes since start] [' . ($entry['mem'] - $lastMem) . ' bytes since last] ' . $entry['msg'];
$lastTime = $entry['time']; $lastTime = $entry['time'];
$lastMem = $entry['mem']; $lastMem = $entry['mem'];
} else { } else {
$data[] = 'DEBUG: ' . $entry['msg']; $data[] = 'DEBUG: ' . $entry['msg'];
} }
} }
   
if ($this->benchmark) { if ($this->benchmark) {
$data[] = 'DEBUG: [' . $endTime . '] [' . ($endTime - $this->startTime) . ' sec since start] [' . ($endTime - $lastTime) . ' sec since last] [' . $endMem . ' bytes] [' . ($endMem - $this->startMem) . ' bytes since start] [' . ($endMem - $lastMem) . ' bytes since last] End'; $data[] = 'DEBUG: [' . $endTime . '] [' . ($endTime - $this->startTime) . ' sec since start] [' . ($endTime - $lastTime) . ' sec since last] [' . $endMem . ' bytes] [' . ($endMem - $this->startMem) . ' bytes since start] [' . ($endMem - $lastMem) . ' bytes since last] End';
} }
} }
   
return $data; return $data;
} }
   
  /**
  * Notify that observable object changed
  *
  * @param GitPHP_Observable_Interface $object object
  * @param int $changeType type of change
  * @param array $args argument array
  */
  public function ObjectChanged($object, $changeType, $args = array())
  {
  if ($changeType !== GitPHP_Observer_Interface::LoggableChange)
  return;
   
  if (!$this->enabled)
  return;
   
  if (!isset($args[0]) || empty($args[0]))
  return;
   
  $msg = $args[0];
   
  $this->Log($msg);
  }
   
} }
   
<?php <?php
/** /**
* Base class that all controllers extend * Base class that all controllers extend
* *
* @author Christopher Han <xiphux@gmail.com * @author Christopher Han <xiphux@gmail.com
* @copyright Copyright (c) 2010 Christopher Han * @copyright Copyright (c) 2010 Christopher Han
* @package GitPHP * @package GitPHP
* @subpackage Controller * @subpackage Controller
*/ */
abstract class GitPHP_ControllerBase abstract class GitPHP_ControllerBase
{ {
   
/** /**
* Config handler instance * Config handler instance
* *
* @var GitPHP_Config * @var GitPHP_Config
*/ */
protected $config; protected $config;
   
/** /**
* Smarty instance * Smarty instance
* *
* @var Smarty * @var Smarty
*/ */
protected $tpl; protected $tpl;
   
/** /**
* Project list * Project list
* *
* @var GitPHP_ProjectListBase * @var GitPHP_ProjectListBase
*/ */
protected $projectList; protected $projectList;
   
/** /**
* Current project * Current project
* *
* @var GitPHP_Project * @var GitPHP_Project
*/ */
protected $project; protected $project;
   
/** /**
* Flag if this is a multi project controller * Flag if this is a multi project controller
* *
* @var boolean * @var boolean
*/ */
protected $multiProject; protected $multiProject;
   
/** /**
* Parameters * Parameters
* *
* @var array * @var array
*/ */
protected $params = array(); protected $params = array();
   
/** /**
* HTTP Headers * HTTP Headers
* *
* @var string[] * @var string[]
*/ */
protected $headers = array(); protected $headers = array();
   
/** /**
* Flag to preserve whitespace in output (for non-html output) * Flag to preserve whitespace in output (for non-html output)
* *
* @var boolean * @var boolean
*/ */
protected $preserveWhitespace = false; protected $preserveWhitespace = false;
   
/** /**
* Constructor * Constructor
*/ */
public function __construct() public function __construct()
{ {
$this->config = GitPHP_Config::GetInstance(); $this->config = GitPHP_Config::GetInstance();
$this->InitializeProjectList(); $this->InitializeProjectList();
   
require_once(GITPHP_SMARTYDIR . 'Smarty.class.php'); require_once(GITPHP_SMARTYDIR . 'Smarty.class.php');
$this->tpl = new Smarty; $this->tpl = new Smarty;
$this->tpl->error_reporting = E_ALL & ~E_NOTICE; $this->tpl->error_reporting = E_ALL & ~E_NOTICE;
$this->tpl->merge_compiled_includes = true; $this->tpl->merge_compiled_includes = true;
$this->tpl->addPluginsDir(GITPHP_INCLUDEDIR . 'smartyplugins'); $this->tpl->addPluginsDir(GITPHP_INCLUDEDIR . 'smartyplugins');
   
if ($this->config->GetValue('cache', false)) { if ($this->config->GetValue('cache', false)) {
$this->tpl->caching = Smarty::CACHING_LIFETIME_SAVED; $this->tpl->caching = Smarty::CACHING_LIFETIME_SAVED;
if ($this->config->HasKey('cachelifetime')) { if ($this->config->HasKey('cachelifetime')) {
$this->tpl->cache_lifetime = $this->config->GetValue('cachelifetime'); $this->tpl->cache_lifetime = $this->config->GetValue('cachelifetime');
} }
   
$servers = $this->config->GetValue('memcache', null); $servers = $this->config->GetValue('memcache', null);
if (isset($servers) && is_array($servers) && (count($servers) > 0)) { if (isset($servers) && is_array($servers) && (count($servers) > 0)) {
$this->tpl->registerCacheResource('memcache', new GitPHP_CacheResource_Memcache($servers)); $this->tpl->registerCacheResource('memcache', new GitPHP_CacheResource_Memcache($servers));
$this->tpl->caching_type = 'memcache'; $this->tpl->caching_type = 'memcache';
} }
   
} }
   
if (isset($_GET['p'])) { if (isset($_GET['p'])) {
$project = $this->projectList->GetProject(str_replace(chr(0), '', $_GET['p'])); $project = $this->projectList->GetProject(str_replace(chr(0), '', $_GET['p']));
if (!$project) { if (!$project) {
throw new GitPHP_MessageException(sprintf(__('Invalid project %1$s'), $_GET['p']), true); throw new GitPHP_MessageException(sprintf(__('Invalid project %1$s'), $_GET['p']), true);
} }
$this->project = $project->GetProject(); $this->project = $project->GetProject();
} }
   
if (!($this->project || $this->multiProject)) { if (!($this->project || $this->multiProject)) {
throw new GitPHP_MessageException(__('Project is required'), true); throw new GitPHP_MessageException(__('Project is required'), true);
} }
   
if ($this->multiProject) { if ($this->multiProject) {
$this->projectList->LoadProjects(); $this->projectList->LoadProjects();
} }
   
if (isset($_GET['s'])) if (isset($_GET['s']))
$this->params['search'] = $_GET['s']; $this->params['search'] = $_GET['s'];
if (isset($_GET['st'])) if (isset($_GET['st']))
$this->params['searchtype'] = $_GET['st']; $this->params['searchtype'] = $_GET['st'];
   
$this->ReadQuery(); $this->ReadQuery();
} }
   
/** /**
* Initialize project list * Initialize project list
*/ */
protected function InitializeProjectList() protected function InitializeProjectList()
{ {
if (file_exists(GITPHP_CONFIGDIR . 'projects.conf.php')) { if (file_exists(GITPHP_CONFIGDIR . 'projects.conf.php')) {
$this->projectList = GitPHP_ProjectList::Instantiate(GITPHP_CONFIGDIR . 'projects.conf.php', false); $this->projectList = GitPHP_ProjectList::Instantiate(GITPHP_CONFIGDIR . 'projects.conf.php', false);
} else { } else {
$this->projectList = GitPHP_ProjectList::Instantiate(GITPHP_CONFIGDIR . 'gitphp.conf.php', true); $this->projectList = GitPHP_ProjectList::Instantiate(GITPHP_CONFIGDIR . 'gitphp.conf.php', true);
} }
   
  $this->projectList->AddObserver(GitPHP_DebugLog::GetInstance());
   
} }
   
/** /**
* Gets the project for this controller * Gets the project for this controller
* *
* @return GitPHP_Project|null project * @return GitPHP_Project|null project
*/ */
public function GetProject() public function GetProject()
{ {
if ($this->project) if ($this->project)
return $this->projectList->GetProject($this->project); return $this->projectList->GetProject($this->project);
return null; return null;
} }
   
/** /**
* Gets the template for this controller * Gets the template for this controller
* *
* @return string template filename * @return string template filename
*/ */
protected abstract function GetTemplate(); protected abstract function GetTemplate();
   
/** /**
* Gets the cache key for this controller * Gets the cache key for this controller
* *
* @return string cache key * @return string cache key
*/ */
protected abstract function GetCacheKey(); protected abstract function GetCacheKey();
   
/** /**
* Get the prefix for all cache keys * Get the prefix for all cache keys
* *
* @param boolean $projectKeys include project-specific key pieces * @param boolean $projectKeys include project-specific key pieces
* @return string cache key prefix * @return string cache key prefix
*/ */
private function GetCacheKeyPrefix($projectKeys = true) private function GetCacheKeyPrefix($projectKeys = true)
{ {
$cacheKeyPrefix = GitPHP_Resource::GetLocale(); $cacheKeyPrefix = GitPHP_Resource::GetLocale();
   
if ($this->projectList) { if ($this->projectList) {
$cacheKeyPrefix .= '|' . sha1(serialize($this->projectList->GetConfig())) . '|' . sha1(serialize($this->projectList->GetSettings())); $cacheKeyPrefix .= '|' . sha1(serialize($this->projectList->GetConfig())) . '|' . sha1(serialize($this->projectList->GetSettings()));
} }
if ($this->project && $projectKeys) { if ($this->project && $projectKeys) {
$cacheKeyPrefix .= '|' . sha1($this->project); $cacheKeyPrefix .= '|' . sha1($this->project);
} }
return $cacheKeyPrefix; return $cacheKeyPrefix;
} }
   
/** /**
* Get the full cache key * Get the full cache key
* *
* @return string full cache key * @return string full cache key
*/ */
protected function GetFullCacheKey() protected function GetFullCacheKey()
{ {
$cacheKey = $this->GetCacheKeyPrefix(); $cacheKey = $this->GetCacheKeyPrefix();
   
$subCacheKey = $this->GetCacheKey(); $subCacheKey = $this->GetCacheKey();
   
if (!empty($subCacheKey)) if (!empty($subCacheKey))
$cacheKey .= '|' . $subCacheKey; $cacheKey .= '|' . $subCacheKey;
   
if (strlen($cacheKey) > 100) { if (strlen($cacheKey) > 100) {
$cacheKey = sha1($cacheKey); $cacheKey = sha1($cacheKey);
} }
   
return $cacheKey; return $cacheKey;
} }
   
/** /**
* Gets the name of this controller's action * Gets the name of this controller's action
* *
* @param boolean $local true if caller wants the localized action name * @param boolean $local true if caller wants the localized action name
* @return string action name * @return string action name
*/ */
public abstract function GetName($local = false); public abstract function GetName($local = false);
   
/** /**
* Read query into parameters * Read query into parameters
*/ */
protected abstract function ReadQuery(); protected abstract function ReadQuery();
   
/** /**
* Set a parameter * Set a parameter
* *
* @param string $key key to set * @param string $key key to set
* @param mixed $value value to set * @param mixed $value value to set
*/ */
public function SetParam($key, $value) public function SetParam($key, $value)
{ {
if (empty($key)) if (empty($key))
return; return;
   
if (empty($value)) if (empty($value))
unset($this->params[$key]); unset($this->params[$key]);
   
$this->params[$key] = $value; $this->params[$key] = $value;
} }
   
/** /**
* Loads headers for this template * Loads headers for this template
*/ */
protected function LoadHeaders() protected function LoadHeaders()
{ {
} }
   
/** /**
* Loads data for this template * Loads data for this template
*/ */
protected abstract function LoadData(); protected abstract function LoadData();
   
/** /**
* Loads common data used by all templates * Loads common data used by all templates
*/ */
private function LoadCommonData() private function LoadCommonData()
{ {
global $gitphp_version, $gitphp_appstring; global $gitphp_version, $gitphp_appstring;
   
$this->tpl->assign('version', $gitphp_version); $this->tpl->assign('version', $gitphp_version);
   
$stylesheet = $this->config->GetValue('stylesheet', 'gitphpskin.css'); $stylesheet = $this->config->GetValue('stylesheet', 'gitphpskin.css');
if ($stylesheet == 'gitphp.css') { if ($stylesheet == 'gitphp.css') {
// backwards compatibility // backwards compatibility
$stylesheet = 'gitphpskin.css'; $stylesheet = 'gitphpskin.css';
} }
$this->tpl->assign('stylesheet', preg_replace('/\.css$/', '', $stylesheet)); $this->tpl->assign('stylesheet', preg_replace('/\.css$/', '', $stylesheet));
   
$this->tpl->assign('javascript', $this->config->GetValue('javascript', true)); $this->tpl->assign('javascript', $this->config->GetValue('javascript', true));
$this->tpl->assign('googlejs', $this->config->GetValue('googlejs', false)); $this->tpl->assign('googlejs', $this->config->GetValue('googlejs', false));
$this->tpl->assign('pagetitle', $this->config->GetValue('title', $gitphp_appstring)); $this->tpl->assign('pagetitle', $this->config->GetValue('title', $gitphp_appstring));
$this->tpl->assign('homelink', $this->config->GetValue('homelink', __('projects'))); $this->tpl->assign('homelink', $this->config->GetValue('homelink', __('projects')));
$this->tpl->assign('action', $this->GetName()); $this->tpl->assign('action', $this->GetName());
$this->tpl->assign('actionlocal', $this->GetName(true)); $this->tpl->assign('actionlocal', $this->GetName(true));
if ($this->project) if ($this->project)
$this->tpl->assign('project', $this->GetProject()); $this->tpl->assign('project', $this->GetProject());
if ($this->config->GetValue('search', true)) if ($this->config->GetValue('search', true))
$this->tpl->assign('enablesearch', true); $this->tpl->assign('enablesearch', true);
if ($this->config->GetValue('filesearch', true)) if ($this->config->GetValue('filesearch', true))
$this->tpl->assign('filesearch', true); $this->tpl->assign('filesearch', true);
if (isset($this->params['search'])) if (isset($this->params['search']))
$this->tpl->assign('search', $this->params['search']); $this->tpl->assign('search', $this->params['search']);
if (isset($this->params['searchtype'])) if (isset($this->params['searchtype']))
$this->tpl->assign('searchtype', $this->params['searchtype']); $this->tpl->assign('searchtype', $this->params['searchtype']);
$this->tpl->assign('currentlocale', GitPHP_Resource::GetLocale()); $this->tpl->assign('currentlocale', GitPHP_Resource::GetLocale());
$this->tpl->assign('supportedlocales', GitPHP_Resource::SupportedLocales()); $this->tpl->assign('supportedlocales', GitPHP_Resource::SupportedLocales());
   
$scripturl = $_SERVER['SCRIPT_NAME']; $scripturl = $_SERVER['SCRIPT_NAME'];
$fullscripturl = ''; $fullscripturl = '';
if (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on')) if (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on'))
$fullscripturl = 'https://'; $fullscripturl = 'https://';
else else
$fullscripturl = 'http://'; $fullscripturl = 'http://';
$fullscripturl .= $_SERVER['HTTP_HOST'] . $scripturl; $fullscripturl .= $_SERVER['HTTP_HOST'] . $scripturl;
   
if (GitPHP_Config::GetInstance()->HasKey('self')) { if (GitPHP_Config::GetInstance()->HasKey('self')) {
$selfurl = GitPHP_Config::GetInstance()->GetValue('self'); $selfurl = GitPHP_Config::GetInstance()->GetValue('self');
if (!empty($selfurl)) { if (!empty($selfurl)) {
if (substr($selfurl, -4) != '.php') { if (substr($selfurl, -4) != '.php') {
$selfurl = GitPHP_Util::AddSlash($selfurl); $selfurl = GitPHP_Util::AddSlash($selfurl);
} }
$fullscripturl = $selfurl; $fullscripturl = $selfurl;
} }
} }
$this->tpl->assign('scripturl', $scripturl); $this->tpl->assign('scripturl', $scripturl);
$this->tpl->assign('fullscripturl', $fullscripturl); $this->tpl->assign('fullscripturl', $fullscripturl);
   
$getvars = explode('&', $_SERVER['QUERY_STRING']); $getvars = explode('&', $_SERVER['QUERY_STRING']);
$getvarsmapped = array(); $getvarsmapped = array();
foreach ($getvars as $varstr) { foreach ($getvars as $varstr) {
$eqpos = strpos($varstr, '='); $eqpos = strpos($varstr, '=');
if ($eqpos > 0) { if ($eqpos > 0) {
$var = substr($varstr, 0, $eqpos); $var = substr($varstr, 0, $eqpos);
$val = substr($varstr, $eqpos + 1); $val = substr($varstr, $eqpos + 1);
if (!(empty($var) || empty($val))) { if (!(empty($var) || empty($val))) {
$getvarsmapped[$var] = urldecode($val); $getvarsmapped[$var] = urldecode($val);
} }
} }
} }
$this->tpl->assign('requestvars', $getvarsmapped); $this->tpl->assign('requestvars', $getvarsmapped);
   
$this->tpl->assign('snapshotformats', GitPHP_Archive::SupportedFormats()); $this->tpl->assign('snapshotformats', GitPHP_Archive::SupportedFormats());
} }
   
/** /**
* Renders any special headers * Renders any special headers
*/ */
public function RenderHeaders() public function RenderHeaders()
{ {
$this->LoadHeaders(); $this->LoadHeaders();
   
if (count($this->headers) > 0) { if (count($this->headers) > 0) {
foreach ($this->headers as $hdr) { foreach ($this->headers as $hdr) {
header($hdr); header($hdr);
} }
} }
} }
   
/** /**
* Renders the output * Renders the output
*/ */
public function Render() public function Render()
{ {
if (($this->config->GetValue('cache', false) == true) && ($this->config->GetValue('cacheexpire', true) === true)) if (($this->config->GetValue('cache', false) == true) && ($this->config->GetValue('cacheexpire', true) === true))
$this->CacheExpire(); $this->CacheExpire();
   
if (!$this->tpl->isCached($this->GetTemplate(), $this->GetFullCacheKey())) { if (!$this->tpl->isCached($this->GetTemplate(), $this->GetFullCacheKey())) {
$this->tpl->clearAllAssign(); $this->tpl->clearAllAssign();
if (GitPHP_DebugLog::GetInstance()->GetBenchmark()) if (GitPHP_DebugLog::GetInstance()->GetBenchmark())
GitPHP_DebugLog::GetInstance()->Log("Data load begin"); GitPHP_DebugLog::GetInstance()->Log("Data load begin");
$this->LoadCommonData(); $this->LoadCommonData();
$this->LoadData(); $this->LoadData();
if (GitPHP_DebugLog::GetInstance()->GetBenchmark()) if (GitPHP_DebugLog::GetInstance()->GetBenchmark())
GitPHP_DebugLog::GetInstance()->Log("Data load end"); GitPHP_DebugLog::GetInstance()->Log("Data load end");
} }
   
if (!$this->preserveWhitespace) { if (!$this->preserveWhitespace) {
//$this->tpl->loadFilter('output', 'trimwhitespace'); //$this->tpl->loadFilter('output', 'trimwhitespace');
} }
   
if (GitPHP_DebugLog::GetInstance()->GetBenchmark()) if (GitPHP_DebugLog::GetInstance()->GetBenchmark())
GitPHP_DebugLog::GetInstance()->Log("Smarty render begin"); GitPHP_DebugLog::GetInstance()->Log("Smarty render begin");
$this->tpl->display($this->GetTemplate(), $this->GetFullCacheKey()); $this->tpl->display($this->GetTemplate(), $this->GetFullCacheKey());
if (GitPHP_DebugLog::GetInstance()->GetBenchmark()) if (GitPHP_DebugLog::GetInstance()->GetBenchmark())
GitPHP_DebugLog::GetInstance()->Log("Smarty render end"); GitPHP_DebugLog::GetInstance()->Log("Smarty render end");
   
$this->tpl->clearAllAssign(); $this->tpl->clearAllAssign();
   
GitPHP_DebugLog::GetInstance()->Log('MemoryCache count: ' . $this->projectList->GetMemoryCache()->GetCount()); GitPHP_DebugLog::GetInstance()->Log('MemoryCache count: ' . $this->projectList->GetMemoryCache()->GetCount());
} }
   
/** /**
* Expires the cache * Expires the cache
* *
* @param boolean $expireAll expire the whole cache * @param boolean $expireAll expire the whole cache
*/ */
public function CacheExpire($expireAll = false) public function CacheExpire($expireAll = false)
{ {
if ($expireAll) { if ($expireAll) {
$this->tpl->clearAllCache(); $this->tpl->clearAllCache();
return; return;
} }
   
if (!$this->project) if (!$this->project)
return; return;
   
$epoch = $this->GetProject()->GetEpoch(); $epoch = $this->GetProject()->GetEpoch();
if (empty($epoch)) if (empty($epoch))
return; return;
   
$age = $this->GetProject()->GetAge(); $age = $this->GetProject()->GetAge();
   
$this->tpl->clearCache(null, $this->GetCacheKeyPrefix(), null, $age); $this->tpl->clearCache(null, $this->GetCacheKeyPrefix(), null, $age);
$this->tpl->clearCache('projectlist.tpl', $this->GetCacheKeyPrefix(false), null, $age); $this->tpl->clearCache('projectlist.tpl', $this->GetCacheKeyPrefix(false), null, $age);
} }
   
} }
   
<?php <?php
/** /**
* Manages creating and caching git object classes * Manages creating and caching git object classes
* *
* @author Christopher Han <xiphux@gmail.com> * @author Christopher Han <xiphux@gmail.com>
* @copyright Copyright (c) 2012 Christopher Han * @copyright Copyright (c) 2012 Christopher Han
* @package GitPHP * @package GitPHP
* @subpackage Git * @subpackage Git
*/ */
class GitPHP_GitObjectManager implements GitPHP_Observer_Interface class GitPHP_GitObjectManager implements GitPHP_Observer_Interface
{ {
/** /**
* The project * The project
* *
* @var GitPHP_Project * @var GitPHP_Project
*/ */
protected $project; protected $project;
   
/** /**
* Cache instance * Cache instance
* *
* @var GitPHP_Cache * @var GitPHP_Cache
*/ */
protected $cache = null; protected $cache = null;
   
/** /**
* MemoryCache instance * MemoryCache instance
* *
* @var GitPHP_MemoryCache * @var GitPHP_MemoryCache
*/ */
protected $memoryCache = null; protected $memoryCache = null;
   
/** /**
* Constructor * Constructor
* *
* @param GitPHP_Project $project project * @param GitPHP_Project $project project
*/ */
public function __construct($project) public function __construct($project)
{ {
if (!$project) if (!$project)
throw new Exception('Project is required'); throw new Exception('Project is required');
   
$this->project = $project; $this->project = $project;
} }
   
/** /**
* Gets the cache instance being used * Gets the cache instance being used
* *
* @return GitPHP_Cache|null cache instance * @return GitPHP_Cache|null cache instance
*/ */
public function GetCache() public function GetCache()
{ {
return $this->cache; return $this->cache;
} }
   
/** /**
* Set the cache instance to use * Set the cache instance to use
* *
* @param GitPHP_Cache|null $cache cache instance * @param GitPHP_Cache|null $cache cache instance
*/ */
public function SetCache($cache) public function SetCache($cache)
{ {
$this->cache = $cache; $this->cache = $cache;
} }
   
/** /**
* Gets the memory cache instance being used * Gets the memory cache instance being used
* *
* @return GitPHP_MemoryCache|null memory cache instance * @return GitPHP_MemoryCache|null memory cache instance
*/ */
public function GetMemoryCache() public function GetMemoryCache()
{ {
return $this->memoryCache; return $this->memoryCache;
} }
   
/** /**
* Sets the memory cache instance to use * Sets the memory cache instance to use
* *
* @param GitPHP_MemoryCache|null $memoryCache memory cache instance * @param GitPHP_MemoryCache|null $memoryCache memory cache instance
*/ */
public function SetMemoryCache($memoryCache) public function SetMemoryCache($memoryCache)
{ {
$this->memoryCache = $memoryCache; $this->memoryCache = $memoryCache;
} }
   
/** /**
* Get a commit * Get a commit
* *
* @param string $hash commit hash * @param string $hash commit hash
* @return GitPHP_Commit|null commit objet * @return GitPHP_Commit|null commit objet
*/ */
public function GetCommit($hash) public function GetCommit($hash)
{ {
if (!preg_match('/^[0-9A-Fa-f]{40}$/', $hash)) if (!preg_match('/^[0-9A-Fa-f]{40}$/', $hash))
return null; return null;
   
   
$key = GitPHP_Commit::CacheKey($this->project->GetProject(), $hash); $key = GitPHP_Commit::CacheKey($this->project->GetProject(), $hash);
   
$commit = null; $commit = null;
if ($this->memoryCache) if ($this->memoryCache)
$commit = $this->memoryCache->Get($key); $commit = $this->memoryCache->Get($key);
   
if (!$commit) { if (!$commit) {
   
if ($this->cache) { if ($this->cache) {
$commit = $this->cache->Get($key); $commit = $this->cache->Get($key);
} }
   
if ($commit) { if ($commit) {
$commit->SetProject($this->project); $commit->SetProject($this->project);
} else { } else {
$commit = new GitPHP_Commit($this->project, $hash); $commit = new GitPHP_Commit($this->project, $hash);
} }
$commit->AddObserver($this); $commit->AddObserver($this);
   
$commit->SetCompat($this->project->GetCompat()); $commit->SetCompat($this->project->GetCompat());
   
if ($this->memoryCache) if ($this->memoryCache)
$this->memoryCache->Set($key, $commit); $this->memoryCache->Set($key, $commit);
   
} }
   
return $commit; return $commit;
} }
   
/** /**
* Gets a single tag * Gets a single tag
* *
* @param string $tag tag to find * @param string $tag tag to find
* @param string $hash hash of tag, if known * @param string $hash hash of tag, if known
* @return GitPHP_Tag tag object * @return GitPHP_Tag tag object
*/ */
public function GetTag($tag, $hash = '') public function GetTag($tag, $hash = '')
{ {
if (empty($tag)) if (empty($tag))
return null; return null;
   
$key = GitPHP_Tag::CacheKey($this->project->GetProject(), $tag); $key = GitPHP_Tag::CacheKey($this->project->GetProject(), $tag);
   
$tagObj = null; $tagObj = null;
if ($this->memoryCache) if ($this->memoryCache)
$tagObj = $this->memoryCache->Get($key); $tagObj = $this->memoryCache->Get($key);
   
if (!$tagObj) { if (!$tagObj) {
   
if ($this->cache) { if ($this->cache) {
$tagObj = $this->cache->Get($key); $tagObj = $this->cache->Get($key);
} }
   
if ($tagObj) { if ($tagObj) {
$tagObj->SetProject($this->project); $tagObj->SetProject($this->project);
} else { } else {
$tagObj = new GitPHP_Tag($this->project, $tag, $hash); $tagObj = new GitPHP_Tag($this->project, $tag, $hash);
} }
$tagObj->AddObserver($this); $tagObj->AddObserver($this);
   
$tagObj->SetCompat($this->project->GetCompat()); $tagObj->SetCompat($this->project->GetCompat());
   
if ($this->memoryCache) if ($this->memoryCache)
$this->memoryCache->Set($key, $tagObj); $this->memoryCache->Set($key, $tagObj);
} }
   
return $tagObj; return $tagObj;
} }
   
/** /**
* Gets a single head * Gets a single head
* *
* @param string $head head to find * @param string $head head to find
* @param string $hash hash of head, if known * @param string $hash hash of head, if known
* @return GitPHP_Head head object * @return GitPHP_Head head object
*/ */
public function GetHead($head, $hash = '') public function GetHead($head, $hash = '')
{ {
if (empty($head)) if (empty($head))
return null; return null;
   
$key = GitPHP_Head::CacheKey($this->project->GetProject(), $head); $key = GitPHP_Head::CacheKey($this->project->GetProject(), $head);
   
$headObj = null; $headObj = null;
if ($this->memoryCache) if ($this->memoryCache)
$headObj = $this->memoryCache->Get($key); $headObj = $this->memoryCache->Get($key);
   
if (!$headObj) { if (!$headObj) {
$headObj = new GitPHP_Head($this->project, $head, $hash); $headObj = new GitPHP_Head($this->project, $head, $hash);
   
if ($this->memoryCache) if ($this->memoryCache)
$this->memoryCache->Set($key, $headObj); $this->memoryCache->Set($key, $headObj);
} }
   
return $headObj; return $headObj;
} }
   
/** /**
* Gets a blob * Gets a blob
* *
* @param string $hash blob hash * @param string $hash blob hash
* @return GitPHP_Blob blob object * @return GitPHP_Blob blob object
*/ */
public function GetBlob($hash) public function GetBlob($hash)
{ {
if (empty($hash)) if (empty($hash))
return null; return null;
   
$key = GitPHP_Blob::CacheKey($this->project->GetProject(), $hash); $key = GitPHP_Blob::CacheKey($this->project->GetProject(), $hash);
   
$blob = null; $blob = null;
if ($this->memoryCache) if ($this->memoryCache)
$blob = $this->memoryCache->Get($key); $blob = $this->memoryCache->Get($key);
   
if (!$blob) { if (!$blob) {
   
if ($this->cache) { if ($this->cache) {
$blob = $this->cache->Get($key); $blob = $this->cache->Get($key);
} }
   
if ($blob) { if ($blob) {
$blob->SetProject($this->project); $blob->SetProject($this->project);
} else { } else {
$blob = new GitPHP_Blob($this->project, $hash); $blob = new GitPHP_Blob($this->project, $hash);
} }
$blob->AddObserver($this); $blob->AddObserver($this);
   
$blob->SetCompat($this->project->GetCompat()); $blob->SetCompat($this->project->GetCompat());
   
if ($this->memoryCache) if ($this->memoryCache)
$this->memoryCache->Set($key, $blob); $this->memoryCache->Set($key, $blob);
} }
   
return $blob; return $blob;
} }
   
/** /**
* Gets a tree * Gets a tree
* *
* @param string $hash tree hash * @param string $hash tree hash
* @return GitPHP_Tree tree object * @return GitPHP_Tree tree object
*/ */
public function GetTree($hash) public function GetTree($hash)
{ {
if (empty($hash)) if (empty($hash))
return null; return null;
   
$key = GitPHP_Tree::CacheKey($this->project->GetProject(), $hash); $key = GitPHP_Tree::CacheKey($this->project->GetProject(), $hash);
$tree = null; $tree = null;
if ($this->memoryCache) if ($this->memoryCache)
$tree = $this->memoryCache->Get($key); $tree = $this->memoryCache->Get($key);
   
if (!$tree) { if (!$tree) {
   
if ($this->cache) { if ($this->cache) {
$tree = $this->cache->Get($key); $tree = $this->cache->Get($key);
} }
   
if ($tree) { if ($tree) {
$tree->SetProject($this->project); $tree->SetProject($this->project);
} else { } else {
$tree = new GitPHP_Tree($this->project, $hash); $tree = new GitPHP_Tree($this->project, $hash);
} }
$tree->AddObserver($this); $tree->AddObserver($this);
   
$tree->SetCompat($this->project->GetCompat()); $tree->SetCompat($this->project->GetCompat());
   
if ($this->memoryCache) if ($this->memoryCache)
$this->memoryCache->Set($key, $tree); $this->memoryCache->Set($key, $tree);
} }
   
return $tree; return $tree;
} }
   
/** /**
* Gets a file diff * Gets a file diff
* *
* @param string $fromHash source hash, can also be a diff-tree info line * @param string $fromHash source hash, can also be a diff-tree info line
* @param string $toHash target hash, required if $fromHash is a hash * @param string $toHash target hash, required if $fromHash is a hash
* @return GitPHP_FileDiff file diff object * @return GitPHP_FileDiff file diff object
*/ */
public function GetFileDiff($fromHash, $toHash = '') public function GetFileDiff($fromHash, $toHash = '')
{ {
$fileDiff = new GitPHP_FileDiff($this->project, $fromHash, $toHash); $fileDiff = new GitPHP_FileDiff($this->project, $fromHash, $toHash);
$fileDiff->SetCache($this->cache); $fileDiff->SetCache($this->cache);
return $fileDiff; return $fileDiff;
} }
   
/** /**
* Notify that observable object changed * Notify that observable object changed
* *
* @param GitPHP_Observable_Interface $object object * @param GitPHP_Observable_Interface $object object
* @param int $changeType type of change * @param int $changeType type of change
*/ * @param array $args argument array
public function ObjectChanged($object, $changeType) */
  public function ObjectChanged($object, $changeType, $args = array())
{ {
if (!$object) if (!$object)
return; return;
   
if ($changeType !== GitPHP_Observer_Interface::CacheableDataChange) if ($changeType !== GitPHP_Observer_Interface::CacheableDataChange)
return; return;
   
if (!$this->cache) if (!$this->cache)
return; return;
   
if (!(($object instanceof GitPHP_Observable_Interface) && ($object instanceof GitPHP_Cacheable_Interface))) if (!(($object instanceof GitPHP_Observable_Interface) && ($object instanceof GitPHP_Cacheable_Interface)))
return; return;
   
$this->cache->Set($object->GetCacheKey(), $object); $this->cache->Set($object->GetCacheKey(), $object);
} }
   
} }
   
<?php <?php
/** /**
* Interface for observer objects * Interface for observer objects
* *
* @author Christopher Han <xiphux@gmail.com> * @author Christopher Han <xiphux@gmail.com>
* @copyright Copyright (c) 2012 Christopher Han * @copyright Copyright (c) 2012 Christopher Han
* @package GitPHP * @package GitPHP
* @subpackage Git * @subpackage Git
*/ */
interface GitPHP_Observer_Interface interface GitPHP_Observer_Interface
{ {
/** /**
* Change type for data that can be cached * Change type for data that can be cached
* *
* @const * @const
*/ */
const CacheableDataChange = 1; const CacheableDataChange = 1;
   
/** /**
  * Change type for logger message
  *
  * @const
  */
  const LoggableChange = 2;
   
  /**
* Notify that observable object changed * Notify that observable object changed
* *
* @param GitPHP_Observable_Interface $object object * @param GitPHP_Observable_Interface $object object
* @param int $changeType type of change * @param int $changeType type of change
  * @param array $args argument array
*/ */
public function ObjectChanged($object, $changeType); public function ObjectChanged($object, $changeType, $args = array());
} }
   
<?php <?php
/** /**
* Lists all projects in a multidimensional array * Lists all projects in a multidimensional array
* *
* @author Christopher Han <xiphux@gmail.com> * @author Christopher Han <xiphux@gmail.com>
* @copyright Copyright (c) 2010 Christopher Han * @copyright Copyright (c) 2010 Christopher Han
* @package GitPHP * @package GitPHP
* @subpackage Git\ProjectList * @subpackage Git\ProjectList
*/ */
class GitPHP_ProjectListArray extends GitPHP_ProjectListBase class GitPHP_ProjectListArray extends GitPHP_ProjectListBase
{ {
   
/** /**
* constructor * constructor
* *
* @param string $projectRoot project root * @param string $projectRoot project root
* @param mixed $projectArray array to read * @param mixed $projectArray array to read
* @throws Exception if parameter is not an array * @throws Exception if parameter is not an array
*/ */
public function __construct($projectRoot, $projectArray) public function __construct($projectRoot, $projectArray)
{ {
if (!is_array($projectArray)) { if (!is_array($projectArray)) {
throw new Exception('An array of projects is required'); throw new Exception('An array of projects is required');
} }
   
$this->projectConfig = $projectArray; $this->projectConfig = $projectArray;
   
parent::__construct($projectRoot); parent::__construct($projectRoot);
} }
   
/** /**
* Populates the internal list of projects * Populates the internal list of projects
*/ */
protected function PopulateProjects() protected function PopulateProjects()
{ {
foreach ($this->projectConfig as $proj => $projData) { foreach ($this->projectConfig as $proj => $projData) {
try { try {
if (is_string($projData)) { if (is_string($projData)) {
// Just flat array of project paths // Just flat array of project paths
$projObj = $this->InstantiateProject($projData); $projObj = $this->InstantiateProject($projData);
if ($projObj) { if ($projObj) {
$this->projects[$projData] = $projObj; $this->projects[$projData] = $projObj;
unset($projObj); unset($projObj);
} }
} else if (is_array($projData)) { } else if (is_array($projData)) {
if (is_string($proj) && !empty($proj)) { if (is_string($proj) && !empty($proj)) {
// Project key pointing to data array // Project key pointing to data array
$projObj = $this->InstantiateProject($proj); $projObj = $this->InstantiateProject($proj);
if ($projObj) { if ($projObj) {
$this->projects[$proj] = $projObj; $this->projects[$proj] = $projObj;
unset($projObj); unset($projObj);
} }
} else if (isset($projData['project'])) { } else if (isset($projData['project'])) {
// List of data arrays with projects inside // List of data arrays with projects inside
$projObj = $this->InstantiateProject($projData['project']); $projObj = $this->InstantiateProject($projData['project']);
if ($projObj) { if ($projObj) {
$this->projects[$projData['project']] = $projObj; $this->projects[$projData['project']] = $projObj;
unset($projObj); unset($projObj);
} }
} }
} }
} catch (Exception $e) { } catch (Exception $e) {
GitPHP_DebugLog::GetInstance()->Log($e->getMessage()); $this->Log($e->getMessage());
} }
} }
} }
   
/** /**
* Instantiates project object * Instantiates project object
* *
* @param string $proj project * @param string $proj project
* @return GitPHP_Project project * @return GitPHP_Project project
*/ */
protected function InstantiateProject($proj) protected function InstantiateProject($proj)
{ {
$found = false; $found = false;
$projectSettings = null; $projectSettings = null;
foreach ($this->projectConfig as $key => $projData) { foreach ($this->projectConfig as $key => $projData) {
if (is_string($projData) && ($projData == $proj)) { if (is_string($projData) && ($projData == $proj)) {
// Just flat array of project paths // Just flat array of project paths
$found = true; $found = true;
break; break;
} else if (is_array($projData)) { } else if (is_array($projData)) {
if (is_string($key) && !empty($key) && ($key == $proj)) { if (is_string($key) && !empty($key) && ($key == $proj)) {
// Project key pointing to data array // Project key pointing to data array
$found = true; $found = true;
$projectSettings = $projData; $projectSettings = $projData;
break; break;
} }
if (isset($projData['project']) && ($projData['project'] == $proj)) { if (isset($projData['project']) && ($projData['project'] == $proj)) {
// List of data arrays with projects inside // List of data arrays with projects inside
$found = true; $found = true;
$projectSettings = $projData; $projectSettings = $projData;
break; break;
} }
} }
} }
   
if (!$found) { if (!$found) {
return; return;
} }
   
$projectObj = new GitPHP_Project($this->projectRoot, $proj); $projectObj = new GitPHP_Project($this->projectRoot, $proj);
   
$this->InjectProjectDependencies($projectObj); $this->InjectProjectDependencies($projectObj);
   
$this->ApplyGlobalConfig($projectObj); $this->ApplyGlobalConfig($projectObj);
   
$this->ApplyGitConfig($projectObj); $this->ApplyGitConfig($projectObj);
   
if ($projectSettings != null) if ($projectSettings != null)
$this->ApplyProjectSettings($projectObj, $projectSettings); $this->ApplyProjectSettings($projectObj, $projectSettings);
   
if ($this->projectSettings && isset($this->projectSettings[$proj])) { if ($this->projectSettings && isset($this->projectSettings[$proj])) {
$this->ApplyProjectSettings($projectObj, $this->projectSettings[$proj]); $this->ApplyProjectSettings($projectObj, $this->projectSettings[$proj]);
} }
   
return $projectObj; return $projectObj;
} }
   
} }
   
<?php <?php
/** /**
* Lists all projects in a multidimensional array (Legacy array format) * Lists all projects in a multidimensional array (Legacy array format)
* *
* @author Christopher Han <xiphux@gmail.com> * @author Christopher Han <xiphux@gmail.com>
* @copyright Copyright (c) 2010 Christopher Han * @copyright Copyright (c) 2010 Christopher Han
* @package GitPHP * @package GitPHP
* @subpackage Git\ProjectList * @subpackage Git\ProjectList
*/ */
class GitPHP_ProjectListArrayLegacy extends GitPHP_ProjectListBase class GitPHP_ProjectListArrayLegacy extends GitPHP_ProjectListBase
{ {
/** /**
* No category indicator * No category indicator
* *
* @const * @const
*/ */
const NoCategory = 'none'; const NoCategory = 'none';
   
/** /**
* constructor * constructor
* *
* @param string $projectRoot project root * @param string $projectRoot project root
* @param mixed $projectArray array to read * @param mixed $projectArray array to read
* @throws Exception if parameter is not an array * @throws Exception if parameter is not an array
*/ */
public function __construct($projectRoot, $projectArray) public function __construct($projectRoot, $projectArray)
{ {
if (!is_array($projectArray)) { if (!is_array($projectArray)) {
throw new Exception('An array of projects is required.'); throw new Exception('An array of projects is required.');
} }
   
$this->projectConfig = $projectArray; $this->projectConfig = $projectArray;
   
parent::__construct($projectRoot); parent::__construct($projectRoot);
} }
   
/** /**
* Populates the internal list of projects * Populates the internal list of projects
*/ */
protected function PopulateProjects() protected function PopulateProjects()
{ {
foreach ($this->projectConfig as $cat => $plist) { foreach ($this->projectConfig as $cat => $plist) {
if (is_array($plist)) { if (is_array($plist)) {
foreach ($plist as $pname => $ppath) { foreach ($plist as $pname => $ppath) {
try { try {
$projObj = $this->InstantiateProject($ppath); $projObj = $this->InstantiateProject($ppath);
if ($projObj) { if ($projObj) {
$this->projects[$ppath] = $projObj; $this->projects[$ppath] = $projObj;
unset($projObj); unset($projObj);
} }
} catch (Exception $e) { } catch (Exception $e) {
GitPHP_DebugLog::GetInstance()->Log($e->getMessage()); $this->Log($e->getMessage());
} }
} }
} }
} }
} }
   
/** /**
* Instantiates project object * Instantiates project object
* *
* @param string $proj project * @param string $proj project
* @return GitPHP_Project project * @return GitPHP_Project project
*/ */
protected function InstantiateProject($proj) protected function InstantiateProject($proj)
{ {
$found = false; $found = false;
$projectCat = GitPHP_ProjectListArrayLegacy::NoCategory; $projectCat = GitPHP_ProjectListArrayLegacy::NoCategory;
foreach ($this->projectConfig as $cat => $plist) { foreach ($this->projectConfig as $cat => $plist) {
if (is_array($plist) && (array_search($proj, $plist) !== false)) { if (is_array($plist) && (array_search($proj, $plist) !== false)) {
$found = true; $found = true;
$projectCat = $cat; $projectCat = $cat;
break; break;
} }
} }
   
if (!$found) { if (!$found) {
return; return;
} }
   
$projectObj = new GitPHP_Project($this->projectRoot, $proj); $projectObj = new GitPHP_Project($this->projectRoot, $proj);
   
$this->InjectProjectDependencies($projectObj); $this->InjectProjectDependencies($projectObj);
   
$this->ApplyGlobalConfig($projectObj); $this->ApplyGlobalConfig($projectObj);
   
$this->ApplyGitConfig($projectObj); $this->ApplyGitConfig($projectObj);
   
if ($projectCat != GitPHP_ProjectListArrayLegacy::NoCategory) if ($projectCat != GitPHP_ProjectListArrayLegacy::NoCategory)
$projectObj->SetCategory($projectCat); $projectObj->SetCategory($projectCat);
   
return $projectObj; return $projectObj;
} }
   
} }
   
<?php <?php
/** /**
* Base class that all projectlist classes extend * Base class that all projectlist classes extend
* *
* @author Christopher Han <xiphux@gmail.com> * @author Christopher Han <xiphux@gmail.com>
* @copyright Copyright (c) 2010 Christopher Han * @copyright Copyright (c) 2010 Christopher Han
* @package GitPHP * @package GitPHP
* @subpackage Git\ProjectList * @subpackage Git\ProjectList
*/ */
abstract class GitPHP_ProjectListBase implements Iterator abstract class GitPHP_ProjectListBase implements Iterator, GitPHP_Observable_Interface
{ {
/** /**
* Project name sort * Project name sort
* *
* @const * @const
*/ */
const ProjectSort = 'project'; const ProjectSort = 'project';
   
/** /**
* Project description sort * Project description sort
* *
* @const * @const
*/ */
const DescriptionSort = 'descr'; const DescriptionSort = 'descr';
   
/** /**
* Project owner sort * Project owner sort
* *
* @const * @const
*/ */
const OwnerSort = 'owner'; const OwnerSort = 'owner';
   
/** /**
* Project age sort * Project age sort
* *
* @const * @const
*/ */
const AgeSort = 'age'; const AgeSort = 'age';
   
/** /**
* Project list * Project list
* *
* @var GitPHP_Project[] * @var GitPHP_Project[]
*/ */
protected $projects; protected $projects;
   
/** /**
* Whether the list of projects has been loaded * Whether the list of projects has been loaded
* *
* @var boolean * @var boolean
*/ */
protected $projectsLoaded = false; protected $projectsLoaded = false;
   
/** /**
* The project configuration * The project configuration
* *
* @var string * @var string
*/ */
protected $projectConfig = null; protected $projectConfig = null;
   
/** /**
* Project settings * Project settings
* *
* @var array * @var array
*/ */
protected $projectSettings = null; protected $projectSettings = null;
   
/** /**
* The project root * The project root
* *
* @var string * @var string
*/ */
protected $projectRoot = null; protected $projectRoot = null;
   
/** /**
* Object cache instance for all projects * Object cache instance for all projects
* *
* @var GitPHP_Cache * @var GitPHP_Cache
*/ */
protected $cache = null; protected $cache = null;
   
/** /**
* Memory cache instance for all project * Memory cache instance for all projects
* *
* @var GitPHP_MemoryCache * @var GitPHP_MemoryCache
*/ */
protected $memoryCache = null; protected $memoryCache = null;
   
  /**
  * Observers
  *
  * @var GitPHP_Observer_Interface[]
  */
  protected $observers = array();
   
/** /**
* Constructor * Constructor
* *
* @param string $projectRoot project root * @param string $projectRoot project root
*/ */
public function __construct($projectRoot) public function __construct($projectRoot)
{ {
$this->projects = array(); $this->projects = array();
$this->projectRoot = GitPHP_Util::AddSlash($projectRoot); $this->projectRoot = GitPHP_Util::AddSlash($projectRoot);
if (empty($this->projectRoot)) { if (empty($this->projectRoot)) {
throw new GitPHP_MessageException(__('A projectroot must be set in the config'), true, 500); throw new GitPHP_MessageException(__('A projectroot must be set in the config'), true, 500);
} }
if (!is_dir($this->projectRoot)) { if (!is_dir($this->projectRoot)) {
throw new Exception(sprintf(__('%1$s is not a directory'), $this->projectRoot)); throw new Exception(sprintf(__('%1$s is not a directory'), $this->projectRoot));
} }
   
$this->memoryCache = new GitPHP_MemoryCache(GitPHP_Config::GetInstance()->GetValue('objectmemory', 0)); $this->memoryCache = new GitPHP_MemoryCache(GitPHP_Config::GetInstance()->GetValue('objectmemory', 0));
   
if (GitPHP_Config::GetInstance()->GetValue('objectcache', false)) { if (GitPHP_Config::GetInstance()->GetValue('objectcache', false)) {
$this->cache = new GitPHP_Cache(); $this->cache = new GitPHP_Cache();
$this->cache->SetServers(GitPHP_Config::GetInstance()->GetValue('memcache', null)); $this->cache->SetServers(GitPHP_Config::GetInstance()->GetValue('memcache', null));
$this->cache->SetEnabled(true); $this->cache->SetEnabled(true);
$this->cache->SetLifetime(GitPHP_Config::GetInstance()->GetValue('objectcachelifetime', 86400)); $this->cache->SetLifetime(GitPHP_Config::GetInstance()->GetValue('objectcachelifetime', 86400));
} }
} }
   
/** /**
* Get memory cache instance * Get memory cache instance
* *
* @access public * @access public
* @return GitPHP_MemoryCache|null * @return GitPHP_MemoryCache|null
*/ */
public function GetMemoryCache() public function GetMemoryCache()
{ {
return $this->memoryCache; return $this->memoryCache;
} }
   
/** /**
* Set memory cache instance * Set memory cache instance
* *
* @access public * @access public
* @param GitPHP_MemoryCache|null $memoryCache memory cache instance * @param GitPHP_MemoryCache|null $memoryCache memory cache instance
*/ */
public function SetMemoryCache($memoryCache) public function SetMemoryCache($memoryCache)
{ {
$this->memoryCache = $memoryCache; $this->memoryCache = $memoryCache;
} }
   
/** /**
* Get object cache instance * Get object cache instance
* *
* @access public * @access public
* @return GitPHP_Cache|null object cache * @return GitPHP_Cache|null object cache
*/ */
public function GetCache() public function GetCache()
{ {
return $this->cache; return $this->cache;
} }
   
/** /**
* Set object cache instance * Set object cache instance
* *
* @access public * @access public
* @param GitPHP_Cache|null $cache object cache instance * @param GitPHP_Cache|null $cache object cache instance
*/ */
public function SetCache($cache) public function SetCache($cache)
{ {
$this->cache = $cache; $this->cache = $cache;
} }
   
/** /**
* Test if the projectlist contains the given project * Test if the projectlist contains the given project
* *
* @return boolean true if project exists in list * @return boolean true if project exists in list
* @param string $project the project to find * @param string $project the project to find
*/ */
public function HasProject($project) public function HasProject($project)
{ {
if (empty($project)) if (empty($project))
return false; return false;
   
return isset($this->projects[$project]); return isset($this->projects[$project]);
} }
   
/** /**
* Gets a particular project * Gets a particular project
* *
* @return GitPHP_Project|null project object or null * @return GitPHP_Project|null project object or null
* @param string $project the project to find * @param string $project the project to find
*/ */
public function GetProject($project) public function GetProject($project)
{ {
if (empty($project)) if (empty($project))
return null; return null;
   
if (isset($this->projects[$project])) if (isset($this->projects[$project]))
return $this->projects[$project]; return $this->projects[$project];
   
if (!$this->projectsLoaded) { if (!$this->projectsLoaded) {
$projObj = $this->InstantiateProject($project); $projObj = $this->InstantiateProject($project);
$this->projects[$project] = $projObj; $this->projects[$project] = $projObj;
return $projObj; return $projObj;
} }
   
return null; return null;
} }
   
/** /**
* Instantiates a project object * Instantiates a project object
* *
* @param string $proj project * @param string $proj project
* @return return GitPHP_Project project object * @return return GitPHP_Project project object
*/ */
protected function InstantiateProject($proj) protected function InstantiateProject($proj)
{ {
$project = new GitPHP_Project(GitPHP_Util::AddSlash($this->projectRoot), $proj); $project = new GitPHP_Project(GitPHP_Util::AddSlash($this->projectRoot), $proj);
   
$this->InjectProjectDependencies($project); $this->InjectProjectDependencies($project);
   
$this->ApplyGlobalConfig($project); $this->ApplyGlobalConfig($project);
   
$this->ApplyGitConfig($project); $this->ApplyGitConfig($project);
   
if ($this->projectSettings && isset($this->projectSettings[$proj])) { if ($this->projectSettings && isset($this->projectSettings[$proj])) {
$this->ApplyProjectSettings($project, $this->projectSettings[$proj]); $this->ApplyProjectSettings($project, $this->projectSettings[$proj]);
} }
   
return $project; return $project;
} }
   
/** /**
* Inject project dependency objects * Inject project dependency objects
* *
* @param GitPHP_Project $project project object * @param GitPHP_Project $project project object
*/ */
protected function InjectProjectDependencies($project) protected function InjectProjectDependencies($project)
{ {
if (!$project) if (!$project)
return; return;
   
if ($this->memoryCache) { if ($this->memoryCache) {
$project->GetObjectManager()->SetMemoryCache($this->memoryCache); $project->GetObjectManager()->SetMemoryCache($this->memoryCache);
} }
   
if ($this->cache) { if ($this->cache) {
$project->GetObjectManager()->SetCache($this->cache); $project->GetObjectManager()->SetCache($this->cache);
} }
} }
   
/** /**
* Gets the config defined for this ProjectList * Gets the config defined for this ProjectList
* *
* @return mixed project config * @return mixed project config
*/ */
public function GetConfig() public function GetConfig()
{ {
return $this->projectConfig; return $this->projectConfig;
} }
   
/** /**
* Gets the settings applied to this projectlist * Gets the settings applied to this projectlist
* *
* @return array * @return array
*/ */
public function GetSettings() public function GetSettings()
{ {
return $this->projectSettings; return $this->projectSettings;
} }
   
/** /**
* Reads the project's git config settings and applies them to the project * Reads the project's git config settings and applies them to the project
* *
* @param GitPHP_Project $project project * @param GitPHP_Project $project project
*/ */
protected function ApplyGitConfig($project) protected function ApplyGitConfig($project)
{ {
if (!$project) if (!$project)
return; return;
   
$config = null; $config = null;
try { try {
$config = new GitPHP_GitConfig($project->GetPath() . '/config'); $config = new GitPHP_GitConfig($project->GetPath() . '/config');
} catch (Exception $e) { } catch (Exception $e) {
return; return;
} }
   
if ($config->HasValue('gitphp.owner')) { if ($config->HasValue('gitphp.owner')) {
$project->SetOwner($config->GetValue('gitphp.owner')); $project->SetOwner($config->GetValue('gitphp.owner'));
} else if ($config->HasValue('gitweb.owner')) { } else if ($config->HasValue('gitweb.owner')) {
$project->SetOwner($config->GetValue('gitweb.owner')); $project->SetOwner($config->GetValue('gitweb.owner'));
} }
   
if ($config->HasValue('gitphp.description')) { if ($config->HasValue('gitphp.description')) {
$project->SetDescription($config->GetValue('gitphp.description')); $project->SetDescription($config->GetValue('gitphp.description'));
} }
   
if ($config->HasValue('gitphp.category')) { if ($config->HasValue('gitphp.category')) {
$project->SetCategory($config->GetValue('gitphp.category')); $project->SetCategory($config->GetValue('gitphp.category'));
} }
   
if ($config->HasValue('gitphp.cloneurl')) { if ($config->HasValue('gitphp.cloneurl')) {
$project->SetCloneUrl($config->GetValue('gitphp.cloneurl')); $project->SetCloneUrl($config->GetValue('gitphp.cloneurl'));
} }
   
if ($config->HasValue('gitphp.pushurl')) { if ($config->HasValue('gitphp.pushurl')) {
$project->SetPushUrl($config->GetValue('gitphp.pushurl')); $project->SetPushUrl($config->GetValue('gitphp.pushurl'));
} }
   
if ($config->HasValue('gitphp.bugurl')) { if ($config->HasValue('gitphp.bugurl')) {
$project->SetBugUrl($config->GetValue('gitphp.bugurl')); $project->SetBugUrl($config->GetValue('gitphp.bugurl'));
} }
   
if ($config->HasValue('gitphp.bugpattern')) { if ($config->HasValue('gitphp.bugpattern')) {
$project->SetBugPattern($config->GetValue('gitphp.bugpattern')); $project->SetBugPattern($config->GetValue('gitphp.bugpattern'));
} }
   
if ($config->HasValue('gitphp.website')) { if ($config->HasValue('gitphp.website')) {
$project->SetWebsite($config->GetValue('gitphp.website')); $project->SetWebsite($config->GetValue('gitphp.website'));
} }
   
if ($config->HasValue('gitphp.compat')) { if ($config->HasValue('gitphp.compat')) {
$project->SetCompat($config->GetValue('gitphp.compat')); $project->SetCompat($config->GetValue('gitphp.compat'));
} }
   
if ($config->HasValue('core.abbrev')) { if ($config->HasValue('core.abbrev')) {
$project->SetAbbreviateLength($config->GetValue('core.abbrev')); $project->SetAbbreviateLength($config->GetValue('core.abbrev'));
} }
   
} }
   
/** /**
* Applies global config settings to a project * Applies global config settings to a project
* *
* @param GitPHP_Project $project project * @param GitPHP_Project $project project
*/ */
protected function ApplyGlobalConfig($project) protected function ApplyGlobalConfig($project)
{ {
if (!$project) if (!$project)
return; return;
   
$config = GitPHP_Config::GetInstance(); $config = GitPHP_Config::GetInstance();
   
if ($config->HasKey('cloneurl')) { if ($config->HasKey('cloneurl')) {
$project->SetCloneUrl(GitPHP_Util::AddSlash($config->GetValue('cloneurl'), false) . $project->GetProject()); $project->SetCloneUrl(GitPHP_Util::AddSlash($config->GetValue('cloneurl'), false) . $project->GetProject());
} }
   
if ($config->HasKey('pushurl')) { if ($config->HasKey('pushurl')) {
$project->SetPushUrl(GitPHP_Util::AddSlash($config->GetValue('pushurl'), false) . $project->GetProject()); $project->SetPushUrl(GitPHP_Util::AddSlash($config->GetValue('pushurl'), false) . $project->GetProject());
} }
   
if ($config->HasKey('bugpattern')) { if ($config->HasKey('bugpattern')) {
$project->SetBugPattern($config->GetValue('bugpattern')); $project->SetBugPattern($config->GetValue('bugpattern'));
} }
   
if ($config->HasKey('bugurl')) { if ($config->HasKey('bugurl')) {
$project->SetBugUrl($config->GetValue('bugurl')); $project->SetBugUrl($config->GetValue('bugurl'));
} }
   
if ($config->HasKey('compat')) { if ($config->HasKey('compat')) {
$project->SetCompat($config->GetValue('compat')); $project->SetCompat($config->GetValue('compat'));
} }
   
if ($config->HasKey('uniqueabbrev')) { if ($config->HasKey('uniqueabbrev')) {
$project->SetUniqueAbbreviation($config->GetValue('uniqueabbrev')); $project->SetUniqueAbbreviation($config->GetValue('uniqueabbrev'));
} }
} }
   
/** /**
* Loads all projects in the list * Loads all projects in the list
*/ */
public function LoadProjects() public function LoadProjects()
{ {
$this->PopulateProjects(); $this->PopulateProjects();
   
$this->projectsLoaded = true; $this->projectsLoaded = true;
   
$this->Sort(); $this->Sort();
   
$this->ApplySettings(); $this->ApplySettings();
} }
   
/** /**
* Populates the internal list of projects * Populates the internal list of projects
*/ */
abstract protected function PopulateProjects(); abstract protected function PopulateProjects();
   
/** /**
* Rewinds the iterator * Rewinds the iterator
* *
* @return GitPHP_Project * @return GitPHP_Project
*/ */
function rewind() function rewind()
{ {
return reset($this->projects); return reset($this->projects);
} }
   
/** /**
* Returns the current element in the array * Returns the current element in the array
* *
* @return GitPHP_Project * @return GitPHP_Project
*/ */
function current() function current()
{ {
return current($this->projects); return current($this->projects);
} }
   
/** /**
* Returns the current key * Returns the current key
* *
* @return string * @return string
*/ */
function key() function key()
{ {
return key($this->projects); return key($this->projects);
} }
   
/** /**
* Advance the pointer * Advance the pointer
* *
* @return GitPHP_Project * @return GitPHP_Project
*/ */
function next() function next()
{ {
return next($this->projects); return next($this->projects);
} }
   
/** /**
* Test for a valid pointer * Test for a valid pointer
* *
* @return boolean * @return boolean
*/ */
function valid() function valid()
{ {
return key($this->projects) !== null; return key($this->projects) !== null;
} }
   
/** /**
* Sorts the project list * Sorts the project list
* *
* @param string $sortBy sort method * @param string $sortBy sort method
*/ */
public function Sort($sortBy = GitPHP_ProjectListBase::ProjectSort) public function Sort($sortBy = GitPHP_ProjectListBase::ProjectSort)
{ {
switch ($sortBy) { switch ($sortBy) {
case GitPHP_ProjectListBase::DescriptionSort: case GitPHP_ProjectListBase::DescriptionSort:
uasort($this->projects, array('GitPHP_Project', 'CompareDescription')); uasort($this->projects, array('GitPHP_Project', 'CompareDescription'));
break; break;
case GitPHP_ProjectListBase::OwnerSort: case GitPHP_ProjectListBase::OwnerSort:
uasort($this->projects, array('GitPHP_Project', 'CompareOwner')); uasort($this->projects, array('GitPHP_Project', 'CompareOwner'));
break; break;
case GitPHP_ProjectListBase::AgeSort: case GitPHP_ProjectListBase::AgeSort:
uasort($this->projects, array('GitPHP_Project', 'CompareAge')); uasort($this->projects, array('GitPHP_Project', 'CompareAge'));
break; break;
case GitPHP_ProjectListBase::ProjectSort: case GitPHP_ProjectListBase::ProjectSort:
default: default:
uasort($this->projects, array('GitPHP_Project', 'CompareProject')); uasort($this->projects, array('GitPHP_Project', 'CompareProject'));
break; break;
} }
} }
   
/** /**
* Gets the count of projects * Gets the count of projects
* *
* @return integer number of projects * @return integer number of projects
*/ */
public function Count() public function Count()
{ {
return count($this->projects); return count($this->projects);
} }
   
/** /**
* Returns a filtered list of projects * Returns a filtered list of projects
* *
* @param string $pattern filter pattern * @param string $pattern filter pattern
* @return GitPHP_Project[] array of filtered projects * @return GitPHP_Project[] array of filtered projects
*/ */
public function Filter($pattern = null) public function Filter($pattern = null)
{ {
if (empty($pattern)) if (empty($pattern))
return $this->projects; return $this->projects;
   
$matches = array(); $matches = array();
   
foreach ($this->projects as $proj) { foreach ($this->projects as $proj) {
if ((stripos($proj->GetProject(), $pattern) !== false) || if ((stripos($proj->GetProject(), $pattern) !== false) ||
(stripos($proj->GetDescription(), $pattern) !== false) || (stripos($proj->GetDescription(), $pattern) !== false) ||
(stripos($proj->GetOwner(), $pattern) !== false)) { (stripos($proj->GetOwner(), $pattern) !== false)) {
$matches[] = $proj; $matches[] = $proj;
} }
} }
   
return $matches; return $matches;
} }
   
/** /**
* Applies override settings for a project * Applies override settings for a project
* *
* @param GitPHP_Project $project the project object * @param GitPHP_Project $project the project object
* @param array $projData project data array * @param array $projData project data array
*/ */
protected function ApplyProjectSettings($project, $projData) protected function ApplyProjectSettings($project, $projData)
{ {
if (!$project) if (!$project)
return; return;
   
if (isset($projData['category']) && is_string($projData['category'])) { if (isset($projData['category']) && is_string($projData['category'])) {
$project->SetCategory($projData['category']); $project->SetCategory($projData['category']);
} }
if (isset($projData['owner']) && is_string($projData['owner'])) { if (isset($projData['owner']) && is_string($projData['owner'])) {
$project->SetOwner($projData['owner']); $project->SetOwner($projData['owner']);
} }
if (isset($projData['description']) && is_string($projData['description'])) { if (isset($projData['description']) && is_string($projData['description'])) {
$project->SetDescription($projData['description']); $project->SetDescription($projData['description']);
} }
if (isset($projData['cloneurl']) && is_string($projData['cloneurl'])) { if (isset($projData['cloneurl']) && is_string($projData['cloneurl'])) {
$project->SetCloneUrl($projData['cloneurl']); $project->SetCloneUrl($projData['cloneurl']);
} }
if (isset($projData['pushurl']) && is_string($projData['pushurl'])) { if (isset($projData['pushurl']) && is_string($projData['pushurl'])) {
$project->SetPushUrl($projData['pushurl']); $project->SetPushUrl($projData['pushurl']);
} }
if (isset($projData['bugpattern']) && is_string($projData['bugpattern'])) { if (isset($projData['bugpattern']) && is_string($projData['bugpattern'])) {
$project->SetBugPattern($projData['bugpattern']); $project->SetBugPattern($projData['bugpattern']);
} }
if (isset($projData['bugurl']) && is_string($projData['bugurl'])) { if (isset($projData['bugurl']) && is_string($projData['bugurl'])) {
$project->SetBugUrl($projData['bugurl']); $project->SetBugUrl($projData['bugurl']);
} }
if (isset($projData['compat'])) { if (isset($projData['compat'])) {
$project->SetCompat($projData['compat']); $project->SetCompat($projData['compat']);
} }
if (isset($projData['website']) && is_string($projData['website'])) { if (isset($projData['website']) && is_string($projData['website'])) {
$project->SetWebsite($projData['website']); $project->SetWebsite($projData['website']);
} }
} }
   
/** /**
* Sets a list of settings for the project list * Sets a list of settings for the project list
* *
* @param array $settings the array of settings * @param array $settings the array of settings
*/ */
public function SetSettings($settings) public function SetSettings($settings)
{ {
if ((!$settings) || (count($settings) < 1)) if ((!$settings) || (count($settings) < 1))
return; return;
   
$this->projectSettings = $settings; $this->projectSettings = $settings;
   
$this->ApplySettings(); $this->ApplySettings();
} }
   
/** /**
* Applies project settings to project list * Applies project settings to project list
*/ */
protected function ApplySettings() protected function ApplySettings()
{ {
if (!$this->projectSettings) if (!$this->projectSettings)
return; return;
   
if (count($this->projects) > 0) { if (count($this->projects) > 0) {
foreach ($this->projectSettings as $proj => $setting) { foreach ($this->projectSettings as $proj => $setting) {
   
if (empty($proj)) { if (empty($proj)) {
if (isset($setting['project']) && !empty($setting['project'])) { if (isset($setting['project']) && !empty($setting['project'])) {
$proj = $setting['project']; $proj = $setting['project'];
} }
} }
   
if (!isset($this->projects[$proj])) if (!isset($this->projects[$proj]))
break; break;
   
$this->ApplyProjectSettings($this->projects[$proj], $setting); $this->ApplyProjectSettings($this->projects[$proj], $setting);
} }
} }
} }
   
  /**
  * Add a new observer
  *
  * @param GitPHP_Observer_Interface $observer observer
  */
  public function AddObserver($observer)
  {
  if (!$observer)
  return;
   
  if (array_search($observer, $this->observers) !== false)
  return;
   
  $this->observers[] = $observer;
  }
   
  /**
  * Remove an observer
  *
  * @param GitPHP_Observer_Interface $observer observer
  */
  public function RemoveObserver($observer)
  {
  if (!$observer)
  return;
   
  $key = array_search($observer, $this->observers);
   
  if ($key === false)
  return;
   
  unset($this->observers[$key]);
  }
   
  /**
  * Log a message to observers
  *
  * @param string $message message
  */
  protected function Log($message)
  {
  if (empty($message))
  return;
   
  foreach ($this->observers as $observer) {
  $observer->ObjectChanged($this, GitPHP_Observer_Interface::LoggableChange, array($message));
  }
  }
   
} }
   
<?php <?php
/** /**
* Lists all projects in a given directory * Lists all projects in a given directory
* *
* @author Christopher Han <xiphux@gmail.com> * @author Christopher Han <xiphux@gmail.com>
* @copyright Copyright (c) 2010 Christopher Han * @copyright Copyright (c) 2010 Christopher Han
* @package GitPHP * @package GitPHP
* @subpackage Git\ProjectList * @subpackage Git\ProjectList
*/ */
class GitPHP_ProjectListDirectory extends GitPHP_ProjectListBase class GitPHP_ProjectListDirectory extends GitPHP_ProjectListBase
{ {
   
/** /**
* Whether to only list exported projects * Whether to only list exported projects
* *
* @var boolean * @var boolean
*/ */
protected $exportedOnly = false; protected $exportedOnly = false;
   
/** /**
* Constructor * Constructor
* *
* @param string $projectRoot project root * @param string $projectRoot project root
* @param bool $exportedOnly whether to only allow exported projects * @param bool $exportedOnly whether to only allow exported projects
*/ */
public function __construct($projectRoot, $exportedOnly = false) public function __construct($projectRoot, $exportedOnly = false)
{ {
$this->exportedOnly = $exportedOnly; $this->exportedOnly = $exportedOnly;
   
parent::__construct($projectRoot); parent::__construct($projectRoot);
   
} }
   
/** /**
* Gets whether this list only allows exported projects * Gets whether this list only allows exported projects
* *
* @return boolean * @return boolean
*/ */
public function GetExportedOnly() public function GetExportedOnly()
{ {
return $this->exportedOnly; return $this->exportedOnly;
} }
/** /**
* Populates the internal list of projects * Populates the internal list of projects
*/ */
protected function PopulateProjects() protected function PopulateProjects()
{ {
$this->RecurseDir(GitPHP_Util::AddSlash($this->projectRoot)); $this->RecurseDir(GitPHP_Util::AddSlash($this->projectRoot));
} }
   
/** /**
* Recursively searches for projects * Recursively searches for projects
* *
* @param string $dir directory to recurse into * @param string $dir directory to recurse into
*/ */
private function RecurseDir($dir) private function RecurseDir($dir)
{ {
if (!(is_dir($dir) && is_readable($dir))) if (!(is_dir($dir) && is_readable($dir)))
return; return;
   
GitPHP_DebugLog::GetInstance()->Log(sprintf('Searching directory %1$s', $dir)); $this->Log(sprintf('Searching directory %1$s', $dir));
   
if ($dh = opendir($dir)) { if ($dh = opendir($dir)) {
$trimlen = strlen(GitPHP_Util::AddSlash($this->projectRoot)) + 1; $trimlen = strlen(GitPHP_Util::AddSlash($this->projectRoot)) + 1;
while (($file = readdir($dh)) !== false) { while (($file = readdir($dh)) !== false) {
$fullPath = $dir . '/' . $file; $fullPath = $dir . '/' . $file;
if ((strpos($file, '.') !== 0) && is_dir($fullPath)) { if ((strpos($file, '.') !== 0) && is_dir($fullPath)) {
if (is_file($fullPath . '/HEAD')) { if (is_file($fullPath . '/HEAD')) {
GitPHP_DebugLog::GetInstance()->Log(sprintf('Found project %1$s', $fullPath)); $this->Log(sprintf('Found project %1$s', $fullPath));
$projectPath = substr($fullPath, $trimlen); $projectPath = substr($fullPath, $trimlen);
if (!isset($this->projects[$projectPath])) { if (!isset($this->projects[$projectPath])) {
$project = $this->InstantiateProject($projectPath); $project = $this->InstantiateProject($projectPath);
if ($project) { if ($project) {
$this->projects[$projectPath] = $project; $this->projects[$projectPath] = $project;
unset($project); unset($project);
} }
} }
} else { } else {
$this->RecurseDir($fullPath); $this->RecurseDir($fullPath);
} }
} else { } else {
GitPHP_DebugLog::GetInstance()->Log(sprintf('Skipping %1$s', $fullPath)); $this->Log(sprintf('Skipping %1$s', $fullPath));
} }
} }
closedir($dh); closedir($dh);
} }
} }
   
/** /**
* Instantiates project object * Instantiates project object
* *
* @param string $proj project * @param string $proj project
* @return GitPHP_Project project * @return GitPHP_Project project
*/ */
protected function InstantiateProject($proj) protected function InstantiateProject($proj)
{ {
try { try {
   
$project = new GitPHP_Project($this->projectRoot, $proj); $project = new GitPHP_Project($this->projectRoot, $proj);
   
$this->InjectProjectDependencies($project); $this->InjectProjectDependencies($project);
   
$category = trim(dirname($proj)); $category = trim(dirname($proj));
if (!(empty($category) || (strpos($category, '.') === 0))) { if (!(empty($category) || (strpos($category, '.') === 0))) {
$project->SetCategory($category); $project->SetCategory($category);
} }
   
if ($this->exportedOnly && !$project->GetDaemonEnabled()) { if ($this->exportedOnly && !$project->GetDaemonEnabled()) {
GitPHP_DebugLog::GetInstance()->Log(sprintf('Project %1$s not enabled for export', $project->GetPath())); $this->Log(sprintf('Project %1$s not enabled for export', $project->GetPath()));
return null; return null;
} }
   
$this->ApplyGlobalConfig($project); $this->ApplyGlobalConfig($project);
   
$this->ApplyGitConfig($project); $this->ApplyGitConfig($project);
   
if ($this->projectSettings && isset($this->projectSettings[$proj])) { if ($this->projectSettings && isset($this->projectSettings[$proj])) {
$this->ApplyProjectSettings($project, $this->projectSettings[$proj]); $this->ApplyProjectSettings($project, $this->projectSettings[$proj]);
} }
   
return $project; return $project;
   
} catch (Exception $e) { } catch (Exception $e) {
GitPHP_DebugLog::GetInstance()->Log($e->getMessage()); $this->Log($e->getMessage());
} }
   
return null; return null;
} }
   
} }
   
<?php <?php
/** /**
* Lists all projects in a given file * Lists all projects in a given file
* *
* @author Christopher Han <xiphux@gmail.com> * @author Christopher Han <xiphux@gmail.com>
* @copyright Copyright (c) 2010 Christopher Han * @copyright Copyright (c) 2010 Christopher Han
* @package GitPHP * @package GitPHP
* @subpackage Git\ProjectList * @subpackage Git\ProjectList
*/ */
class GitPHP_ProjectListFile extends GitPHP_ProjectListBase class GitPHP_ProjectListFile extends GitPHP_ProjectListBase
{ {
   
/** /**
* The contents of the project list file * The contents of the project list file
* *
* @var string[] * @var string[]
*/ */
protected $fileContents = array(); protected $fileContents = array();
   
/** /**
* Whether the file has been read * Whether the file has been read
* *
* @var boolean * @var boolean
*/ */
protected $fileRead = false; protected $fileRead = false;
/** /**
* constructor * constructor
* *
* @param string $projectRoot project root * @param string $projectRoot project root
* @param string $projectFile file to read * @param string $projectFile file to read
* @throws Exception if parameter is not a readable file * @throws Exception if parameter is not a readable file
*/ */
public function __construct($projectRoot, $projectFile) public function __construct($projectRoot, $projectFile)
{ {
if (!(is_string($projectFile) && is_file($projectFile))) { if (!(is_string($projectFile) && is_file($projectFile))) {
throw new Exception(sprintf(__('%1$s is not a file'), $projectFile)); throw new Exception(sprintf(__('%1$s is not a file'), $projectFile));
} }
   
$this->projectConfig = $projectFile; $this->projectConfig = $projectFile;
   
parent::__construct($projectRoot); parent::__construct($projectRoot);
} }
   
/** /**
* Populates the internal list of projects * Populates the internal list of projects
*/ */
protected function PopulateProjects() protected function PopulateProjects()
{ {
if (!$this->fileRead) if (!$this->fileRead)
$this->ReadFile(); $this->ReadFile();
   
foreach ($this->fileContents as $lineData) { foreach ($this->fileContents as $lineData) {
if (isset($lineData['project'])) { if (isset($lineData['project'])) {
$projObj = $this->InstantiateProject($lineData['project']); $projObj = $this->InstantiateProject($lineData['project']);
if ($projObj) { if ($projObj) {
$this->projects[$lineData['project']] = $projObj; $this->projects[$lineData['project']] = $projObj;
unset($projObj); unset($projObj);
} }
} }
} }
} }
   
/** /**
* Instantiates the project object * Instantiates the project object
* *
* @param string $proj project * @param string $proj project
* @return GitPHP_Project project object * @return GitPHP_Project project object
*/ */
protected function InstantiateProject($proj) protected function InstantiateProject($proj)
{ {
if (!$this->fileRead) if (!$this->fileRead)
$this->ReadFile(); $this->ReadFile();
   
$found = false; $found = false;
$owner = null; $owner = null;
foreach ($this->fileContents as $lineData) { foreach ($this->fileContents as $lineData) {
if (isset($lineData['project']) && ($lineData['project'] == $proj)) { if (isset($lineData['project']) && ($lineData['project'] == $proj)) {
$projectRoot = GitPHP_Util::AddSlash($this->projectRoot); $projectRoot = GitPHP_Util::AddSlash($this->projectRoot);
if (is_file($projectRoot . $proj . '/HEAD')) { if (is_file($projectRoot . $proj . '/HEAD')) {
$found = true; $found = true;
if (isset($lineData['owner'])) { if (isset($lineData['owner'])) {
$owner = $lineData['owner']; $owner = $lineData['owner'];
} }
} else { } else {
GitPHP_DebugLog::GetInstance()->Log(sprintf('%1$s is not a git project', $projectRoot . $proj)); $this->Log(sprintf('%1$s is not a git project', $projectRoot . $proj));
} }
break; break;
} }
} }
   
if (!$found) if (!$found)
return null; return null;
   
$projectObj = new GitPHP_Project($this->projectRoot, $proj); $projectObj = new GitPHP_Project($this->projectRoot, $proj);
   
$this->InjectProjectDependencies($projectObj); $this->InjectProjectDependencies($projectObj);
   
$this->ApplyGlobalConfig($projectObj); $this->ApplyGlobalConfig($projectObj);
   
$this->ApplyGitConfig($projectObj); $this->ApplyGitConfig($projectObj);
   
if (!empty($owner)) if (!empty($owner))
$projectObj->SetOwner($owner); $projectObj->SetOwner($owner);
   
if ($this->projectSettings && isset($this->projectSettings[$proj])) { if ($this->projectSettings && isset($this->projectSettings[$proj])) {
$this->ApplyProjectSettings($projectObj, $this->projectSettings[$proj]); $this->ApplyProjectSettings($projectObj, $this->projectSettings[$proj]);
} }
   
return $projectObj; return $projectObj;
} }
   
/** /**
* Reads the file contents * Reads the file contents
*/ */
protected function ReadFile() protected function ReadFile()
{ {
$this->fileRead = true; $this->fileRead = true;
   
$fileString = file_get_contents($this->projectConfig); $fileString = file_get_contents($this->projectConfig);
if ($fileString === false) { if ($fileString === false) {
throw new Exception(sprintf(__('Failed to open project list file %1$s'), $this->projectConfig)); throw new Exception(sprintf(__('Failed to open project list file %1$s'), $this->projectConfig));
} }
   
$this->fileContents = array(); $this->fileContents = array();
   
$fileLines = explode("\n", $fileString); $fileLines = explode("\n", $fileString);
foreach ($fileLines as $line) { foreach ($fileLines as $line) {
if (preg_match('/^([^\s]+)(\s.+)?$/', $line, $regs)) { if (preg_match('/^([^\s]+)(\s.+)?$/', $line, $regs)) {
$data = array(); $data = array();
$data['project'] = $regs[1]; $data['project'] = $regs[1];
$owner = trim($regs[2]); $owner = trim($regs[2]);
if (!empty($owner)) { if (!empty($owner)) {
$data['owner'] = $owner; $data['owner'] = $owner;
} }
$this->fileContents[] = $data; $this->fileContents[] = $data;
} }
} }
} }
   
} }
   
<?php <?php
/** /**
* Lists all projects in an scm-manager config file * Lists all projects in an scm-manager config file
* *
* @author Christopher Han <xiphux@gmail.com> * @author Christopher Han <xiphux@gmail.com>
* @copyright Copyright (c) 2011 Christopher Han * @copyright Copyright (c) 2011 Christopher Han
* @package GitPHP * @package GitPHP
* @subpackage Git\ProjectList * @subpackage Git\ProjectList
*/ */
class GitPHP_ProjectListScmManager extends GitPHP_ProjectListBase class GitPHP_ProjectListScmManager extends GitPHP_ProjectListBase
{ {
/** /**
* The contents of the project config file * The contents of the project config file
* *
* @var array * @var array
*/ */
protected $fileContents = array(); protected $fileContents = array();
   
/** /**
* Whether the file has been read * Whether the file has been read
* *
* @var boolean * @var boolean
*/ */
protected $fileRead = false; protected $fileRead = false;
/** /**
* constructor * constructor
* *
* @param string $projectRoot project root * @param string $projectRoot project root
* @param string $projectFile file to read * @param string $projectFile file to read
* @throws Exception if parameter is not a readable file * @throws Exception if parameter is not a readable file
*/ */
public function __construct($projectRoot, $projectFile) public function __construct($projectRoot, $projectFile)
{ {
if (!(is_string($projectFile) && is_file($projectFile))) { if (!(is_string($projectFile) && is_file($projectFile))) {
throw new Exception(sprintf(__('%1$s is not a file'), $projectFile)); throw new Exception(sprintf(__('%1$s is not a file'), $projectFile));
} }
   
$this->projectConfig = $projectFile; $this->projectConfig = $projectFile;
   
parent::__construct($projectRoot); parent::__construct($projectRoot);
} }
   
/** /**
* Populates the internal list of projects * Populates the internal list of projects
*/ */
protected function PopulateProjects() protected function PopulateProjects()
{ {
if (!$this->fileRead) if (!$this->fileRead)
$this->ReadFile(); $this->ReadFile();
   
foreach ($this->fileContents as $projData) { foreach ($this->fileContents as $projData) {
$projObj = $this->InstantiateProject($projData['name']); $projObj = $this->InstantiateProject($projData['name']);
if ($projObj) { if ($projObj) {
$this->projects[$projData['name']] = $projObj; $this->projects[$projData['name']] = $projObj;
unset($projObj); unset($projObj);
} }
} }
} }
   
/** /**
* Instantiates the project object * Instantiates the project object
* *
* @param string $proj project * @param string $proj project
* @return GitPHP_Project project object * @return GitPHP_Project project object
*/ */
protected function InstantiateProject($proj) protected function InstantiateProject($proj)
{ {
if (!$this->fileRead) if (!$this->fileRead)
$this->ReadFile(); $this->ReadFile();
   
$data = null; $data = null;
$found = false; $found = false;
   
foreach ($this->fileContents as $projData) { foreach ($this->fileContents as $projData) {
if (isset($projData) && ($proj == $projData['name'])) { if (isset($projData) && ($proj == $projData['name'])) {
$data = $projData; $data = $projData;
$found = true; $found = true;
break; break;
} }
} }
   
if (!$found) if (!$found)
return null; return null;
   
if (!(isset($data['type']) && ($data['type'] == 'git'))) { if (!(isset($data['type']) && ($data['type'] == 'git'))) {
GitPHP_DebugLog::GetInstance()->Log(sprintf('%1$s is not a git project', $proj)); $this->Log(sprintf('%1$s is not a git project', $proj));
return null; return null;
} }
   
if (!(isset($data['public']) && ($data['public'] == true))) { if (!(isset($data['public']) && ($data['public'] == true))) {
GitPHP_DebugLog::GetInstance()->Log(sprintf('%1$s is not public', $proj)); $this->Log(sprintf('%1$s is not public', $proj));
return null; return null;
} }
   
if (!is_file(GitPHP_Util::AddSlash($this->projectRoot) . $proj . '/HEAD')) { if (!is_file(GitPHP_Util::AddSlash($this->projectRoot) . $proj . '/HEAD')) {
GitPHP_DebugLog::GetInstance()->Log(sprintf('%1$s is not a git project', $proj)); $this->Log(sprintf('%1$s is not a git project', $proj));
} }
   
$projectObj = new GitPHP_Project($this->projectRoot, $proj); $projectObj = new GitPHP_Project($this->projectRoot, $proj);
   
$this->InjectProjectDependencies($projectObj); $this->InjectProjectDependencies($projectObj);
   
$this->ApplyGlobalConfig($projectObj); $this->ApplyGlobalConfig($projectObj);
   
$this->ApplyGitConfig($projectObj); $this->ApplyGitConfig($projectObj);
   
if (isset($data['owner']) && !empty($data['owner'])) { if (isset($data['owner']) && !empty($data['owner'])) {
$projectObj->SetOwner($data['owner']); $projectObj->SetOwner($data['owner']);
} }
   
if (isset($data['description']) && !empty($data['description'])) { if (isset($data['description']) && !empty($data['description'])) {
$projectObj->SetDescription($data['description']); $projectObj->SetDescription($data['description']);
} }
   
if ($this->projectSettings && isset($this->projectSettings[$proj])) { if ($this->projectSettings && isset($this->projectSettings[$proj])) {
$this->ApplyProjectSettings($projectObj, $this->projectSettings[$proj]); $this->ApplyProjectSettings($projectObj, $this->projectSettings[$proj]);
} }
   
return $projectObj; return $projectObj;
} }
   
/** /**
* Reads the file contents * Reads the file contents
*/ */
protected function ReadFile() protected function ReadFile()
{ {
$this->fileRead = true; $this->fileRead = true;
   
$use_errors = libxml_use_internal_errors(true); $use_errors = libxml_use_internal_errors(true);
   
$xml = simplexml_load_file($this->projectConfig); $xml = simplexml_load_file($this->projectConfig);
   
libxml_clear_errors(); libxml_clear_errors();
libxml_use_internal_errors($use_errors); libxml_use_internal_errors($use_errors);
   
if (!$xml) { if (!$xml) {
throw new Exception(sprintf('Could not load SCM manager config %1$s', $this->projectConfig)); throw new Exception(sprintf('Could not load SCM manager config %1$s', $this->projectConfig));
} }
   
foreach ($xml->repositories->repository as $repository) { foreach ($xml->repositories->repository as $repository) {
$name = trim($repository->name); $name = trim($repository->name);
if (empty($name)) if (empty($name))
continue; continue;
   
$data = array(); $data = array();
$data['name'] = $name; $data['name'] = $name;
$data['type'] = $repository->type; $data['type'] = $repository->type;
$data['public'] = ($repository->public == 'true'); $data['public'] = ($repository->public == 'true');
$owner = trim($repository->contact); $owner = trim($repository->contact);
if (!empty($owner)) if (!empty($owner))
$data['owner'] = $owner; $data['owner'] = $owner;
   
$description = trim($repository->description); $description = trim($repository->description);
if (!empty($description)) if (!empty($description))
$data['description'] = $description; $data['description'] = $description;
   
$this->fileContents[] = $data; $this->fileContents[] = $data;
   
} }
} }
   
/** /**
* Tests if this file is an SCM manager config file * Tests if this file is an SCM manager config file
* *
* @param string $file file * @param string $file file
* @returns true if file is an SCM manager config * @returns true if file is an SCM manager config
*/ */
public static function IsSCMManager($file) public static function IsSCMManager($file)
{ {
if (empty($file)) if (empty($file))
return false; return false;
   
if (!(is_string($file) && is_file($file))) if (!(is_string($file) && is_file($file)))
return false; return false;
   
$use_errors = libxml_use_internal_errors(true); $use_errors = libxml_use_internal_errors(true);
   
$xml = simplexml_load_file($file); $xml = simplexml_load_file($file);
   
libxml_clear_errors(); libxml_clear_errors();
libxml_use_internal_errors($use_errors); libxml_use_internal_errors($use_errors);
   
if (!$xml) if (!$xml)
return false; return false;
   
if ($xml->getName() !== 'repository-db') if ($xml->getName() !== 'repository-db')
return false; return false;
   
return true; return true;
} }
   
} }
   
comments