Remove memory cache singleton
Remove memory cache singleton

<?php <?php
/** /**
* Cache to manage objects in process memory * Cache to manage objects in process memory
* *
* @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 Cache * @subpackage Cache
*/ */
class GitPHP_MemoryCache class GitPHP_MemoryCache
{ {
/** /**
* Stores the singleton instance  
*  
* @var GitPHP_MemoryCache  
*/  
protected static $instance;  
   
/**  
* Stores the objects in this cache * Stores the objects in this cache
* *
* @var array * @var array
*/ */
protected $objects = array(); protected $objects = array();
   
/** /**
* Whether the cache will automatically manage the number of items * Whether the cache will automatically manage the number of items
* *
* @var boolean * @var boolean
*/ */
protected $autoManaged = true; protected $autoManaged = true;
   
/** /**
* Stores the last project that stored into this cache * Stores the last project that stored into this cache
* *
* @var string * @var string
*/ */
protected $lastProject; protected $lastProject;
   
/** /**
* Size of cache * Size of cache
* *
* @var int * @var int
*/ */
protected $size; protected $size;
   
/** /**
* Returns the singleton instance  
*  
* @return GitPHP_MemoryCache instance of cache class  
*/  
public static function GetInstance()  
{  
if (!self::$instance) {  
self::$instance = new GitPHP_MemoryCache(GitPHP_Config::GetInstance()->GetValue('objectmemory', 0));  
}  
return self::$instance;  
}  
   
/**  
* Releases the singleton instance  
*/  
public static function DestroyInstance()  
{  
self::$instance = null;  
}  
   
/**  
* Class constructor * Class constructor
* *
* @param int $size size of cache * @param int $size size of cache
*/ */
private function __construct($size = 0) public function __construct($size = 0)
{ {
$this->size = $size; $this->size = $size;
} }
   
/** /**
* Gets the size of this cache * Gets the size of this cache
* *
* @return int size * @return int size
*/ */
public function GetSize() public function GetSize()
{ {
return $this->size; return $this->size;
} }
   
/** /**
* Sets the size of this cache * Sets the size of this cache
* *
* @param int $size size * @param int $size size
*/ */
public function SetSize($size) public function SetSize($size)
{ {
if ($this->size != $size) { if ($this->size != $size) {
$oldSize = $this->size; $oldSize = $this->size;
$this->size = $size; $this->size = $size;
if (($size > 0) && ($size < $oldSize)) { if (($size > 0) && ($size < $oldSize)) {
$this->Evict(); $this->Evict();
} }
} }
} }
   
/** /**
* Gets whether this cache is auto managing its size * Gets whether this cache is auto managing its size
* *
* @return bool true if automanaged * @return bool true if automanaged
*/ */
public function GetAutoManaged() public function GetAutoManaged()
{ {
return $this->autoManaged; return $this->autoManaged;
} }
   
/** /**
* Sets whether this cache should auto manage its size * Sets whether this cache should auto manage its size
* *
* @param bool $autoManaged true if cache should automanage * @param bool $autoManaged true if cache should automanage
*/ */
public function SetAutoManaged($autoManaged) public function SetAutoManaged($autoManaged)
{ {
if (!$this->autoManaged && $autoManaged && (count($this->objects) > 0)) { if (!$this->autoManaged && $autoManaged && (count($this->objects) > 0)) {
end($this->objects); end($this->objects);
$lastKey = key($this->objects); $lastKey = key($this->objects);
if ($lastKey) { if ($lastKey) {
$this->lastProject = $this->ExtractProject($lastKey); $this->lastProject = $this->ExtractProject($lastKey);
} }
} }
$this->autoManaged = $autoManaged; $this->autoManaged = $autoManaged;
} }
   
/** /**
* Gets an object from the cache * Gets an object from the cache
* *
* @param string $key cache key * @param string $key cache key
* @return mixed object from cache if found * @return mixed object from cache if found
*/ */
public function Get($key) public function Get($key)
{ {
if (empty($key)) if (empty($key))
return null; return null;
   
if (!isset($this->objects[$key])) if (!isset($this->objects[$key]))
return null; return null;
   
$object = $this->objects[$key]; $object = $this->objects[$key];
   
/* /*
* unset and reset to move to end of associative array * unset and reset to move to end of associative array
* (indicate as most recently used) * (indicate as most recently used)
*/ */
unset($this->objects[$key]); unset($this->objects[$key]);
$this->objects[$key] = $object; $this->objects[$key] = $object;
   
return $object; return $object;
} }
   
/** /**
* Sets an object into the cache * Sets an object into the cache
* *
* @param string $key cache key * @param string $key cache key
* @param mixed $object object to cache * @param mixed $object object to cache
*/ */
public function Set($key, $object) public function Set($key, $object)
{ {
if (empty($key)) if (empty($key))
return; return;
   
if ($this->autoManaged) { if ($this->autoManaged) {
$project = $this->ExtractProject($key); $project = $this->ExtractProject($key);
if (empty($this->lastProject) || ($this->lastProject != $project)) { if (empty($this->lastProject) || ($this->lastProject != $project)) {
if (count($this->objects) > 0) { if (count($this->objects) > 0) {
$this->Clear(); $this->Clear();
} }
$this->lastProject = $project; $this->lastProject = $project;
} }
} }
   
if (isset($this->objects[$key])) { if (isset($this->objects[$key])) {
/* /*
* unset so resetting will move to end of associative array * unset so resetting will move to end of associative array
* (indicate as most recently used) * (indicate as most recently used)
*/ */
unset($this->objects[$key]); unset($this->objects[$key]);
} else { } else {
$this->Evict(); $this->Evict();
} }
   
$this->objects[$key] = $object; $this->objects[$key] = $object;
} }
   
/** /**
* Gets the count of items in this cache * Gets the count of items in this cache
* *
* @return int count * @return int count
*/ */
public function GetCount() public function GetCount()
{ {
return count($this->objects); return count($this->objects);
} }
   
/** /**
* Clear the cache * Clear the cache
*/ */
public function Clear() public function Clear()
{ {
$this->objects = array(); $this->objects = array();
$this->lastProject = ''; $this->lastProject = '';
} }
   
/** /**
* Evicts items from the cache down to the size limit * Evicts items from the cache down to the size limit
*/ */
private function Evict() private function Evict()
{ {
if ($this->size < 1) { if ($this->size < 1) {
return; return;
} }
   
while (count($this->objects) >= $this->size) { while (count($this->objects) >= $this->size) {
array_shift($this->objects); array_shift($this->objects);
} }
} }
   
/** /**
* Extracts the project from a key * Extracts the project from a key
* *
* @param string $key cache key * @param string $key cache key
*/ */
private function ExtractProject($key) private function ExtractProject($key)
{ {
if (empty($key)) if (empty($key))
return ''; return '';
   
if (strncmp($key, 'project|', 8) != 0) { if (strncmp($key, 'project|', 8) != 0) {
return ''; return '';
} }
   
strtok($key, '|'); strtok($key, '|');
   
$project = strtok('|'); $project = strtok('|');
   
return $project; return $project;
} }
   
} }
   
<?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);
} }
   
} }
   
/** /**
* 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());
} }
   
/** /**
* 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
  *
  * @var GitPHP_MemoryCache
  */
  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
  *
  * @return GitPHP_MemoryCache|null memory cache instance
  */
  public function GetMemoryCache()
  {
  return $this->memoryCache;
  }
   
  /**
  * Sets the memory cache instance to use
  *
  * @param GitPHP_MemoryCache|null $memoryCache memory cache instance
  */
  public function SetMemoryCache($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);
$memoryCache = GitPHP_MemoryCache::GetInstance();  
$commit = $memoryCache->Get($key); $commit = null;
  if ($this->memoryCache)
  $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());
   
$memoryCache->Set($key, $commit); if ($this->memoryCache)
  $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);
$memoryCache = GitPHP_MemoryCache::GetInstance();  
$tagObj = $memoryCache->Get($key); $tagObj = null;
  if ($this->memoryCache)
  $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());
   
$memoryCache->Set($key, $tagObj); if ($this->memoryCache)
  $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);
$memoryCache = GitPHP_MemoryCache::GetInstance();  
$headObj = $memoryCache->Get($key); $headObj = null;
  if ($this->memoryCache)
  $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);
   
$memoryCache->Set($key, $headObj); if ($this->memoryCache)
  $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);
$memoryCache = GitPHP_MemoryCache::GetInstance();  
$blob = $memoryCache->Get($key); $blob = null;
  if ($this->memoryCache)
  $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());
   
$memoryCache->Set($key, $blob); if ($this->memoryCache)
  $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);
$memoryCache = GitPHP_MemoryCache::GetInstance(); $tree = null;
$tree = $memoryCache->Get($key); if ($this->memoryCache)
  $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());
   
$memoryCache->Set($key, $tree); if ($this->memoryCache)
  $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
*/ */
public function ObjectChanged($object, $changeType) public function ObjectChanged($object, $changeType)
{ {
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
/** /**
* 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
{ {
/** /**
* 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
  *
  * @var GitPHP_MemoryCache
  */
  protected $memoryCache = null;
   
  /**
* 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));
   
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
  *
  * @access public
  * @return GitPHP_MemoryCache|null
  */
  public function GetMemoryCache()
  {
  return $this->memoryCache;
  }
   
  /**
  * Set memory cache instance
  *
  * @access public
  * @param GitPHP_MemoryCache|null $memoryCache memory cache instance
  */
  public function SetMemoryCache($memoryCache)
  {
  $this->memoryCache = $memoryCache;
  }
   
  /**
  * Get object cache instance
  *
  * @access public
  * @return GitPHP_Cache|null object cache
  */
  public function GetCache()
  {
  return $this->cache;
  }
   
  /**
  * Set object cache instance
  *
  * @access public
  * @param GitPHP_Cache|null $cache object cache instance
  */
  public function SetCache($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) {
  $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);
} }
} }
} }
   
} }
   
file:a/index.php -> file:b/index.php
<?php <?php
/** /**
* GitPHP * GitPHP
* *
* Index * Index
* *
* @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
*/ */
   
/** /**
* Use utf-8 encoding * Use utf-8 encoding
*/ */
if (function_exists('mb_internal_encoding')) { if (function_exists('mb_internal_encoding')) {
mb_internal_encoding("UTF-8"); mb_internal_encoding("UTF-8");
} }
   
/** /**
* Define start time / memory for benchmarking * Define start time / memory for benchmarking
*/ */
define('GITPHP_START_TIME', microtime(true)); define('GITPHP_START_TIME', microtime(true));
define('GITPHP_START_MEM', memory_get_usage()); define('GITPHP_START_MEM', memory_get_usage());
   
/** /**
* Define some paths * Define some paths
*/ */
define('GITPHP_BASEDIR', dirname(__FILE__) . '/'); define('GITPHP_BASEDIR', dirname(__FILE__) . '/');
define('GITPHP_CONFIGDIR', GITPHP_BASEDIR . 'config/'); define('GITPHP_CONFIGDIR', GITPHP_BASEDIR . 'config/');
define('GITPHP_INCLUDEDIR', GITPHP_BASEDIR . 'include/'); define('GITPHP_INCLUDEDIR', GITPHP_BASEDIR . 'include/');
define('GITPHP_LOCALEDIR', GITPHP_BASEDIR . 'locale/'); define('GITPHP_LOCALEDIR', GITPHP_BASEDIR . 'locale/');
define('GITPHP_CACHEDIR', GITPHP_BASEDIR . 'cache/'); define('GITPHP_CACHEDIR', GITPHP_BASEDIR . 'cache/');
define('GITPHP_LIBDIR', GITPHP_BASEDIR . 'lib/'); define('GITPHP_LIBDIR', GITPHP_BASEDIR . 'lib/');
define('GITPHP_SMARTYDIR', GITPHP_LIBDIR . 'smarty/libs/'); define('GITPHP_SMARTYDIR', GITPHP_LIBDIR . 'smarty/libs/');
define('GITPHP_GESHIDIR', GITPHP_LIBDIR . 'geshi/'); define('GITPHP_GESHIDIR', GITPHP_LIBDIR . 'geshi/');
   
include(GITPHP_INCLUDEDIR . 'version.php'); include(GITPHP_INCLUDEDIR . 'version.php');
   
require(GITPHP_INCLUDEDIR . 'AutoLoader.class.php'); require(GITPHP_INCLUDEDIR . 'AutoLoader.class.php');
   
spl_autoload_register(array('GitPHP_AutoLoader', 'AutoLoad')); spl_autoload_register(array('GitPHP_AutoLoader', 'AutoLoad'));
   
date_default_timezone_set('UTC'); date_default_timezone_set('UTC');
   
   
/* /*
* Set the locale based on the user's preference * Set the locale based on the user's preference
*/ */
if ((!isset($_COOKIE[GitPHP_Resource::LocaleCookie])) || empty($_COOKIE[GitPHP_Resource::LocaleCookie])) { if ((!isset($_COOKIE[GitPHP_Resource::LocaleCookie])) || empty($_COOKIE[GitPHP_Resource::LocaleCookie])) {
   
/* /*
* User's first time here, try by HTTP_ACCEPT_LANGUAGE * User's first time here, try by HTTP_ACCEPT_LANGUAGE
*/ */
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$httpAcceptLang = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); $httpAcceptLang = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
$preferredLocale = GitPHP_Resource::FindPreferredLocale($_SERVER['HTTP_ACCEPT_LANGUAGE']); $preferredLocale = GitPHP_Resource::FindPreferredLocale($_SERVER['HTTP_ACCEPT_LANGUAGE']);
if (!empty($preferredLocale)) { if (!empty($preferredLocale)) {
setcookie(GitPHP_Resource::LocaleCookie, $preferredLocale, time()+GitPHP_Resource::LocaleCookieLifetime); setcookie(GitPHP_Resource::LocaleCookie, $preferredLocale, time()+GitPHP_Resource::LocaleCookieLifetime);
GitPHP_Resource::Instantiate($preferredLocale); GitPHP_Resource::Instantiate($preferredLocale);
} }
} }
   
if (!GitPHP_Resource::Instantiated()) { if (!GitPHP_Resource::Instantiated()) {
/* /*
* Create a dummy cookie to prevent browser delay * Create a dummy cookie to prevent browser delay
*/ */
setcookie(GitPHP_Resource::LocaleCookie, 0, time()+GitPHP_Resource::LocaleCookieLifetime); setcookie(GitPHP_Resource::LocaleCookie, 0, time()+GitPHP_Resource::LocaleCookieLifetime);
} }
   
} else if (isset($_GET['l']) && !empty($_GET['l'])) { } else if (isset($_GET['l']) && !empty($_GET['l'])) {
   
/* /*
* User picked something * User picked something
*/ */
setcookie(GitPHP_Resource::LocaleCookie, $_GET['l'], time()+GitPHP_Resource::LocaleCookieLifetime); setcookie(GitPHP_Resource::LocaleCookie, $_GET['l'], time()+GitPHP_Resource::LocaleCookieLifetime);
GitPHP_Resource::Instantiate($_GET['l']); GitPHP_Resource::Instantiate($_GET['l']);
   
} else if (isset($_COOKIE[GitPHP_Resource::LocaleCookie]) && !empty($_COOKIE[GitPHP_Resource::LocaleCookie])) { } else if (isset($_COOKIE[GitPHP_Resource::LocaleCookie]) && !empty($_COOKIE[GitPHP_Resource::LocaleCookie])) {
   
/* /*
* Returning visitor with a preference * Returning visitor with a preference
*/ */
GitPHP_Resource::Instantiate($_COOKIE[GitPHP_Resource::LocaleCookie]); GitPHP_Resource::Instantiate($_COOKIE[GitPHP_Resource::LocaleCookie]);
   
} }
   
   
try { try {
   
/* /*
* Configuration * Configuration
*/ */
GitPHP_Config::GetInstance()->LoadConfig(GITPHP_CONFIGDIR . 'gitphp.conf.php'); GitPHP_Config::GetInstance()->LoadConfig(GITPHP_CONFIGDIR . 'gitphp.conf.php');
   
/* /*
* Use the default language in the config if user has no preference * Use the default language in the config if user has no preference
* with en_US as the fallback * with en_US as the fallback
*/ */
if (!GitPHP_Resource::Instantiated()) { if (!GitPHP_Resource::Instantiated()) {
GitPHP_Resource::Instantiate(GitPHP_Config::GetInstance()->GetValue('locale', 'en_US')); GitPHP_Resource::Instantiate(GitPHP_Config::GetInstance()->GetValue('locale', 'en_US'));
} }
   
/* /*
* Debug * Debug
*/ */
if (GitPHP_DebugLog::GetInstance()->GetEnabled()) { if (GitPHP_DebugLog::GetInstance()->GetEnabled()) {
GitPHP_DebugLog::GetInstance()->SetStartTime(GITPHP_START_TIME); GitPHP_DebugLog::GetInstance()->SetStartTime(GITPHP_START_TIME);
GitPHP_DebugLog::GetInstance()->SetStartMemory(GITPHP_START_MEM); GitPHP_DebugLog::GetInstance()->SetStartMemory(GITPHP_START_MEM);
} }
   
/* /*
* Check for required executables * Check for required executables
*/ */
if (!GitPHP_GitExe::GetInstance()->Valid()) { if (!GitPHP_GitExe::GetInstance()->Valid()) {
throw new GitPHP_MessageException(sprintf(__('Could not run the git executable "%1$s". You may need to set the "%2$s" config value.'), GitPHP_GitExe::GetInstance()->GetBinary(), 'gitbin'), true, 500); throw new GitPHP_MessageException(sprintf(__('Could not run the git executable "%1$s". You may need to set the "%2$s" config value.'), GitPHP_GitExe::GetInstance()->GetBinary(), 'gitbin'), true, 500);
} }
   
$controller = GitPHP_Controller::GetController((isset($_GET['a']) ? $_GET['a'] : null)); $controller = GitPHP_Controller::GetController((isset($_GET['a']) ? $_GET['a'] : null));
if ($controller) { if ($controller) {
$controller->RenderHeaders(); $controller->RenderHeaders();
$controller->Render(); $controller->Render();
} }
unset($controller); unset($controller);
   
} catch (Exception $e) { } catch (Exception $e) {
   
if (GitPHP_Config::GetInstance()->GetValue('debug', false)) { if (GitPHP_Config::GetInstance()->GetValue('debug', false)) {
throw $e; throw $e;
} }
   
if (!GitPHP_Resource::Instantiated()) { if (!GitPHP_Resource::Instantiated()) {
/* /*
* In case an error was thrown before instantiating * In case an error was thrown before instantiating
* the resource manager * the resource manager
*/ */
GitPHP_Resource::Instantiate('en_US'); GitPHP_Resource::Instantiate('en_US');
} }
   
$controller = new GitPHP_Controller_Message(); $controller = new GitPHP_Controller_Message();
$controller->SetParam('message', $e->getMessage()); $controller->SetParam('message', $e->getMessage());
if ($e instanceof GitPHP_MessageException) { if ($e instanceof GitPHP_MessageException) {
$controller->SetParam('error', $e->Error); $controller->SetParam('error', $e->Error);
$controller->SetParam('statuscode', $e->StatusCode); $controller->SetParam('statuscode', $e->StatusCode);
} else { } else {
$controller->SetParam('error', true); $controller->SetParam('error', true);
} }
$controller->RenderHeaders(); $controller->RenderHeaders();
$controller->Render(); $controller->Render();
   
unset($controller); unset($controller);
   
} }
   
GitPHP_DebugLog::GetInstance()->Log('MemoryCache count: ' . GitPHP_MemoryCache::GetInstance()->GetCount());  
   
GitPHP_MemoryCache::DestroyInstance();  
GitPHP_Resource::DestroyInstance(); GitPHP_Resource::DestroyInstance();
GitPHP_Config::DestroyInstance(); GitPHP_Config::DestroyInstance();
GitPHP_GitExe::DestroyInstance(); GitPHP_GitExe::DestroyInstance();
   
if (GitPHP_DebugLog::GetInstance()->GetEnabled()) { if (GitPHP_DebugLog::GetInstance()->GetEnabled()) {
$entries = GitPHP_DebugLog::GetInstance()->GetEntries(); $entries = GitPHP_DebugLog::GetInstance()->GetEntries();
foreach ($entries as $logline) { foreach ($entries as $logline) {
echo "<br />\n" . htmlspecialchars($logline, ENT_QUOTES, 'UTF-8', true); echo "<br />\n" . htmlspecialchars($logline, ENT_QUOTES, 'UTF-8', true);
} }
unset($logline); unset($logline);
unset($entries); unset($entries);
} }
   
GitPHP_DebugLog::DestroyInstance(); GitPHP_DebugLog::DestroyInstance();
   
?> ?>
   
comments