Add specific exception for project list file read failure
Add specific exception for project list file read failure

<?php <?php
/** /**
* Controller for displaying a message page * Controller for displaying a message page
* *
* @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
*/ */
class GitPHP_Controller_Message extends GitPHP_ControllerBase class GitPHP_Controller_Message extends GitPHP_ControllerBase
{ {
/** /**
* Constructor * Constructor
*/ */
public function __construct() public function __construct()
{ {
$this->config = GitPHP_Config::GetInstance(); $this->config = GitPHP_Config::GetInstance();
   
if (GitPHP_Resource::Instantiated() && (GitPHP_Resource::GetLocale() != 'en_US')); if (GitPHP_Resource::Instantiated() && (GitPHP_Resource::GetLocale() != 'en_US'));
$this->resource = GitPHP_Resource::GetInstance(); $this->resource = GitPHP_Resource::GetInstance();
   
$this->InitializeGitExe(false); $this->InitializeGitExe(false);
   
try { try {
$this->InitializeProjectList(); $this->InitializeProjectList();
} catch (Exception $e) { } catch (Exception $e) {
} }
   
try { try {
$this->InitializeSmarty(); $this->InitializeSmarty();
} catch (Exception $e) { } catch (Exception $e) {
} }
   
if (isset($_GET['p']) && $this->projectList) { if (isset($_GET['p']) && $this->projectList) {
$project = $this->projectList->GetProject(str_replace(chr(0), '', $_GET['p'])); $project = $this->projectList->GetProject(str_replace(chr(0), '', $_GET['p']));
if ($project) { if ($project) {
$this->project = $project->GetProject(); $this->project = $project->GetProject();
} }
} }
   
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();
} }
   
/** /**
* Gets the template for this controller * Gets the template for this controller
* *
* @return string template filename * @return string template filename
*/ */
protected function GetTemplate() protected function GetTemplate()
{ {
if ($this->project) if ($this->project)
return 'projectmessage.tpl'; return 'projectmessage.tpl';
return 'message.tpl'; return 'message.tpl';
} }
   
/** /**
* Gets the cache key for this controller * Gets the cache key for this controller
* *
* @return string cache key * @return string cache key
*/ */
protected function GetCacheKey() protected function GetCacheKey()
{ {
return sha1(serialize($this->params['exception'])); return sha1(serialize($this->params['exception']));
} }
   
/** /**
* 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 function GetName($local = false) public function GetName($local = false)
{ {
// This isn't a real controller // This isn't a real controller
return ''; return '';
} }
   
/** /**
* Read query into parameters * Read query into parameters
*/ */
protected function ReadQuery() protected function ReadQuery()
{ {
if (isset($_GET['h'])) if (isset($_GET['h']))
$this->params['hash'] = $_GET['h']; $this->params['hash'] = $_GET['h'];
else else
$this->params['hash'] = 'HEAD'; $this->params['hash'] = 'HEAD';
} }
   
/** /**
* Loads headers for this template * Loads headers for this template
*/ */
protected function LoadHeaders() protected function LoadHeaders()
{ {
if (($this->params['exception'] instanceof GitPHP_MessageException) && ($this->params['exception']->StatusCode)) { if (($this->params['exception'] instanceof GitPHP_MessageException) && ($this->params['exception']->StatusCode)) {
$partialHeader = $this->StatusCodeHeader($this->params['exception']->StatusCode); $partialHeader = $this->StatusCodeHeader($this->params['exception']->StatusCode);
if (!empty($partialHeader)) { if (!empty($partialHeader)) {
if (substr(php_sapi_name(), 0, 8) == 'cgi-fcgi') { if (substr(php_sapi_name(), 0, 8) == 'cgi-fcgi') {
/* /*
* FastCGI requires a different header * FastCGI requires a different header
*/ */
$this->headers[] = 'Status: ' . $partialHeader; $this->headers[] = 'Status: ' . $partialHeader;
} else { } else {
$this->headers[] = 'HTTP/1.1 ' . $partialHeader; $this->headers[] = 'HTTP/1.1 ' . $partialHeader;
} }
} }
} }
} }
   
/** /**
* Loads data for this template * Loads data for this template
*/ */
protected function LoadData() protected function LoadData()
{ {
$this->tpl->assign('message', $this->ExceptionToMessage($this->params['exception'])); $this->tpl->assign('message', $this->ExceptionToMessage($this->params['exception']));
if (($this->params['exception'] instanceof GitPHP_MessageException) && ($this->params['exception']->Error)) { if (($this->params['exception'] instanceof GitPHP_MessageException) && ($this->params['exception']->Error)) {
$this->tpl->assign('error', true); $this->tpl->assign('error', true);
} }
if ($this->project) { if ($this->project) {
try { try {
$co = $this->GetProject()->GetCommit($this->params['hash']); $co = $this->GetProject()->GetCommit($this->params['hash']);
if ($co) { if ($co) {
$this->tpl->assign('commit', $co); $this->tpl->assign('commit', $co);
} }
} catch (Exception $e) { } catch (Exception $e) {
} }
} }
} }
   
/** /**
* Gets the user-displayed message for an exception * Gets the user-displayed message for an exception
* *
* @param Exception $exception exception * @param Exception $exception exception
* @return string message * @return string message
*/ */
private function ExceptionToMessage($exception) private function ExceptionToMessage($exception)
{ {
if (!$exception) if (!$exception)
return; return;
   
if ($exception instanceof GitPHP_InvalidProjectParameterException) { if ($exception instanceof GitPHP_InvalidProjectParameterException) {
if ($this->resource) if ($this->resource)
return sprintf($this->resource->translate('Invalid project %1$s'), $exception->Project); return sprintf($this->resource->translate('Invalid project %1$s'), $exception->Project);
return sprintf('Invalid project %1$s', $exception->Project); return sprintf('Invalid project %1$s', $exception->Project);
} }
if ($exception instanceof GitPHP_MissingProjectParameterException) { if ($exception instanceof GitPHP_MissingProjectParameterException) {
if ($this->resource) if ($this->resource)
return $this->resource->translate('Project is required'); return $this->resource->translate('Project is required');
return 'Project is required'; return 'Project is required';
} }
   
if ($exception instanceof GitPHP_SearchDisabledException) { if ($exception instanceof GitPHP_SearchDisabledException) {
if ($exception->FileSearch) { if ($exception->FileSearch) {
if ($this->resource) if ($this->resource)
return $this->resource->translate('File search has been disabled'); return $this->resource->translate('File search has been disabled');
return 'File search has been disabled'; return 'File search has been disabled';
} else { } else {
if ($this->resource) if ($this->resource)
return $this->resource->translate('Search has been disabled'); return $this->resource->translate('Search has been disabled');
return 'Search has been disabled'; return 'Search has been disabled';
} }
} }
   
if ($exception instanceof GitPHP_InvalidSearchTypeException) { if ($exception instanceof GitPHP_InvalidSearchTypeException) {
if ($this->resource) if ($this->resource)
return $this->resource->translate('Invalid search type'); return $this->resource->translate('Invalid search type');
return 'Invalid search type'; return 'Invalid search type';
} }
   
if ($exception instanceof GitPHP_SearchLengthException) { if ($exception instanceof GitPHP_SearchLengthException) {
if ($this->resource) if ($this->resource)
return sprintf($this->resource->ngettext('You must enter search text of at least %1$d character', 'You must enter search text of at least %1$d characters', $exception->MinimumLength), $exception->MinimumLength); return sprintf($this->resource->ngettext('You must enter search text of at least %1$d character', 'You must enter search text of at least %1$d characters', $exception->MinimumLength), $exception->MinimumLength);
return sprintf($exception->MinimumLength == 1 ? 'You must enter search text of at least %1$d character' : 'You must enter search text of at least %1$d characters', $exception->MinimumLength); return sprintf($exception->MinimumLength == 1 ? 'You must enter search text of at least %1$d character' : 'You must enter search text of at least %1$d characters', $exception->MinimumLength);
} }
   
if ($exception instanceof GitPHP_InvalidHashException) { if ($exception instanceof GitPHP_InvalidHashException) {
if ($this->resource) if ($this->resource)
return sprintf($this->resource->translate('Invalid hash %1$s'), $exception->Hash); return sprintf($this->resource->translate('Invalid hash %1$s'), $exception->Hash);
return sprintf('Invalid hash %1$s', $exception->Hash); return sprintf('Invalid hash %1$s', $exception->Hash);
} }
   
if ($exception instanceof GitPHP_InvalidGitExecutableException) { if ($exception instanceof GitPHP_InvalidGitExecutableException) {
if ($this->resource) if ($this->resource)
return sprintf($this->resource->translate('Could not run the git executable "%1$s". You may need to set the "%2$s" config value.'), $exception->Executable, 'gitbin'); return sprintf($this->resource->translate('Could not run the git executable "%1$s". You may need to set the "%2$s" config value.'), $exception->Executable, 'gitbin');
return sprintf('Could not run the git executable "%1$s". You may need to set the "%2$s" config value.', $exception->Executable, 'gitbin'); return sprintf('Could not run the git executable "%1$s". You may need to set the "%2$s" config value.', $exception->Executable, 'gitbin');
} }
   
if ($exception instanceof GitPHP_MissingProjectrootException) { if ($exception instanceof GitPHP_MissingProjectrootException) {
if ($this->resource) if ($this->resource)
return $this->resource->translate('A projectroot must be set in the config'); return $this->resource->translate('A projectroot must be set in the config');
return 'A projectroot must be set in the config'; return 'A projectroot must be set in the config';
} }
   
if ($exception instanceof GitPHP_MissingMemcacheException) { if ($exception instanceof GitPHP_MissingMemcacheException) {
if ($this->resource) if ($this->resource)
return $this->resource->translate('The Memcached or Memcache PHP extension is required for Memcache support'); return $this->resource->translate('The Memcached or Memcache PHP extension is required for Memcache support');
return 'The Memcached or Memcache PHP extension is required for Memcache support'; return 'The Memcached or Memcache PHP extension is required for Memcache support';
} }
   
if (($exception instanceof GitPHP_InvalidDirectoryException) || ($exception instanceof GitPHP_InvalidDirectoryConfigurationException)) { if (($exception instanceof GitPHP_InvalidDirectoryException) || ($exception instanceof GitPHP_InvalidDirectoryConfigurationException)) {
if ($this->resource) if ($this->resource)
return sprintf($this->resource->translate('%1$s is not a directory'), $exception->Directory); return sprintf($this->resource->translate('%1$s is not a directory'), $exception->Directory);
return sprintf('%1$s is not a directory', $exception->Directory); return sprintf('%1$s is not a directory', $exception->Directory);
} }
   
if ($exception instanceof GitPHP_InvalidFileException) { if ($exception instanceof GitPHP_InvalidFileException) {
if ($this->resource) if ($this->resource)
return sprintf($this->resource->translate('%1$s is not a file'), $exception->File); return sprintf($this->resource->translate('%1$s is not a file'), $exception->File);
return sprintf('%1$s is not a file', $exception->File); return sprintf('%1$s is not a file', $exception->File);
} }
   
if ($exception instanceof GitPHP_InvalidGitRepositoryException) { if ($exception instanceof GitPHP_InvalidGitRepositoryException) {
if ($this->resource) if ($this->resource)
return sprintf($this->resource->translate('%1$s is not a git repository'), $exception->Repository); return sprintf($this->resource->translate('%1$s is not a git repository'), $exception->Repository);
return sprintf('%1$s is not a git repository', $exception->Repository); return sprintf('%1$s is not a git repository', $exception->Repository);
} }
   
  if ($exception instanceof GitPHP_ProjectListFileReadException) {
  if ($this->resource)
  return sprintf($this->resource->translate('Failed to open project list file %1$s'), $exception->File);
  return sprintf('Failed to open project list file %1$s', $exception->File);
  }
   
return $exception->getMessage(); return $exception->getMessage();
} }
   
/** /**
* Gets the header for an HTTP status code * Gets the header for an HTTP status code
* *
* @param integer $code status code * @param integer $code status code
* @return string header * @return string header
*/ */
private function StatusCodeHeader($code) private function StatusCodeHeader($code)
{ {
switch ($code) { switch ($code) {
case 500: case 500:
return '500 Internal Server Error'; return '500 Internal Server Error';
} }
} }
   
} }
   
  <?php
  /**
  * Custom exception when a project list file cannot be read
  *
  * @author Christopher Han <xiphux@gmail.com>
  * @copyright Copyright (c) 2012 Christopher Han
  * @package GitPHP
  * @subpackage Exception
  */
  class GitPHP_ProjectListFileReadException extends GitPHP_MessageException
  {
  /**
  * File
  *
  * @var string
  */
  public $File;
 
  /**
  * Constructor
  *
  * @param string $file file
  * @param string $message message
  * @param int $code exception code
  */
  public function __construct($file, $message = '', $code = 0)
  {
  $this->File = $file;
  if (empty($message))
  $message = sprintf('Failed to open project list file %1$s', $file);
  parent::__construct($message, true, 500, $code);
  }
  }
 
<?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 GitPHP_InvalidFileException($projectFile); throw new GitPHP_InvalidFileException($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->LoadProject($lineData['project']); $projObj = $this->LoadProject($lineData['project']);
if ($projObj) { if ($projObj) {
$this->projects[$lineData['project']] = $projObj; $this->projects[$lineData['project']] = $projObj;
unset($projObj); unset($projObj);
} }
} }
} }
} }
   
/** /**
* Loads a project * Loads a project
* *
* @param string $proj project * @param string $proj project
* @return GitPHP_Project project object * @return GitPHP_Project project object
*/ */
protected function LoadProject($proj) protected function LoadProject($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 {
$this->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->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]);
} }
   
$this->InjectProjectDependencies($projectObj); $this->InjectProjectDependencies($projectObj);
   
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 GitPHP_MessageException(sprintf(__('Failed to open project list file %1$s'), $this->projectConfig)); throw new GitPHP_ProjectListFileReadException($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;
} }
} }
} }
   
} }
   
comments