New way of specifying projects and categories
New way of specifying projects and categories

This changes the way projects are specified with categories in an array.
There is a new config file in the config directory, projects.conf.php,
where the projects are listed using the git_projects array. In order to
make the transition easier for upgrading users without breaking
everything when they upgrade, this will allow a fallback to the legacy
method. If the file projects.conf.php exists, it will read that using
the new array format. If it doesn't exist, it will continue to use the
legacy array format that was specified in the main gitphp.conf.php.

This change was necessary because the previous format was limited to
only a single piece of metadata for a project - one category as a
string. Now, with this format, an arbitrary amount of metadata can be
specified for any project - so future enhancements can take advantage of
this and it will be very easy to add extra metadata.

This uses PHP's standard syntax for specifying multidimensional arrays.
It is admittedly more complicated than the old method because you have
to get all the syntax with commas and array() declarations correct,
which may be difficult for non-PHP programmers. I considered doing an
actual config file parser; however since this file is loaded every
single time you load any page, I wanted it to be as lightweight as
possible, and nothing is more lightweight than PHP's native syntax.

--- a/config/gitphp.conf.php.example
+++ b/config/gitphp.conf.php.example
@@ -20,41 +20,6 @@
 
 
 /*
- * git_projects
- * List of projects
- *
- * There are three ways to list projects:
- *
- * 1. Two dimensional array of projects with categories
- * First array index is the name of the category the projects
- * belong to, and the second array index is a human-readable
- * name for the project (not used, just for organizational
- * purposes), and the value is the path to the project
- * (minus the projectroot).
- * Any projects belonging to the special category "none"
- * will be listed without a category.
- */
-//$git_projects['Core']['FBX'] = 'core/fbx.git';
-//$git_projects['PHP']['gitphp'] = 'php/gitphp.git';
-//$git_projects['PHP']['MDB'] = 'php/mdb.git';
-//$git_projects['PHP']['xxcache'] = 'php/xxcache.git';
-//$git_projects['Websites']['bth'] = 'websites/bth.git';
-
-/*
- * 2. Path to file with list of projects
- * Points to a flat file with a list of projects,
- * one on each line. Can also read Gitosis project lists.
- */
-//$git_projects = '/git/projectlist.txt';
-
-/*
- * 3. Leave commented to read all projects in the project root
- */
-
-
-
-
-/*
  * cache
  * Turns on caching. If in doubt, leave it off
  * You will need to create a directory 'cache' and make it

--- /dev/null
+++ b/config/projects.conf.php.example
@@ -1,1 +1,65 @@
+<?php
+/**
+ * GitPHP Project config file
+ *
+ * Copy this example file to config/projects.conf.php
+ *
+ * @author Christopher Han <xiphux@gmail.com>
+ * @copyright Copyright (c) 2010 Christopher Han
+ * @package GitPHP
+ * @subpackage Config
+ */
 
+
+/*
+ * git_projects
+ * List of projects
+ *
+ * There are three ways to list projects:
+ *
+ * 1. Two dimensional array of projects with categories
+ *
+ * The top level is the full array of projects.
+ * Each project itself is an array with the following keys:
+ * 'project': the path to the project, minus the projectroot
+ * 'category': the category for the project. This is optional.
+ */
+//$git_projects = array(
+//	array(
+//		'project' => 'gentoo.git'
+//	),
+//	array(
+//		'project' => 'core/fbx.git',
+//		'category' => 'Core'
+//	),
+//	array(
+//		'project' => 'php/gitphp.git',
+//		'category' => 'PHP',
+//	),
+//	array(
+//		'project' => 'php/mdb.git',
+//		'category' => 'PHP'
+//	),
+//	array(
+//		'project' => 'php/xxcache.git',
+//		'category' => 'PHP'
+//	),
+//	array(
+//		'project' => 'websites/bth.git',
+//		'category' => 'Websites'
+//	)
+//);
+
+
+/*
+ * 2. Path to file with list of projects
+ * Points to a flat file with a list of projects,
+ * one on each line. Can also read Gitosis project lists.
+ */
+//$git_projects = '/git/projectlist.txt';
+
+/*
+ * 3. Leave commented to read all projects in the project root
+ */
+
+

--- a/include/git/ProjectList.class.php
+++ b/include/git/ProjectList.class.php
@@ -13,6 +13,7 @@
 require_once(GITPHP_GITOBJECTDIR . 'ProjectListDirectory.class.php');
 require_once(GITPHP_GITOBJECTDIR . 'ProjectListFile.class.php');
 require_once(GITPHP_GITOBJECTDIR . 'ProjectListArray.class.php');
+require_once(GITPHP_GITOBJECTDIR . 'ProjectListArrayLegacy.class.php');
 
 /**
  * ProjectList class
@@ -56,20 +57,25 @@
 	 * @access private
 	 * @static
 	 * @param string $file config file with git projects
+	 * @param boolean $legacy true if this is the legacy project config
 	 * @throws Exception if there was an error reading the file
 	 */
-	public static function Instantiate($file = null)
+	public static function Instantiate($file = null, $legacy = false)
 	{
 		if (self::$instance)
 			return;
 
 		if (!empty($file) && is_file($file) && include($file)) {
 			if (is_string($git_projects)) {
-					self::$instance = new GitPHP_ProjectListFile($git_projects);
-					return;
+				self::$instance = new GitPHP_ProjectListFile($git_projects);
+				return;
 			} else if (is_array($git_projects)) {
+				if ($legacy) {
+					self::$instance = new GitPHP_ProjectListArrayLegacy($git_projects);
+				} else {
 					self::$instance = new GitPHP_ProjectListArray($git_projects);
-					return;
+				}
+				return;
 			}
 		}
 

--- a/include/git/ProjectListArray.class.php
+++ b/include/git/ProjectListArray.class.php
@@ -54,13 +54,14 @@
 	 */
 	protected function PopulateProjects()
 	{
-		foreach ($this->projectConfig as $cat => $plist) {
-			if (is_array($plist)) {
-				foreach ($plist as $pname => $ppath) {
+		foreach ($this->projectConfig as $projData) {
+			if (is_array($projData)) {
+				if (isset($projData['project'])) {
 					try {
-						$projObj = new GitPHP_Project($ppath);
-						if ($cat != GITPHP_NO_CATEGORY)
-							$projObj->SetCategory($cat);
+						$projObj = new GitPHP_Project($projData['project']);
+						if (isset($projData['category']) && is_string($projData['category'])) {
+							$projObj->SetCategory($projData['category']);
+						}
 						$this->projects[] = $projObj;
 					} catch (Exception $e) {
 					}

--- /dev/null
+++ b/include/git/ProjectListArrayLegacy.class.php
@@ -1,1 +1,74 @@
+<?php
+/**
+ * GitPHP ProjectListArrayLegacy
+ *
+ * Lists all projects in a multidimensional array
+ * Legacy array format
+ *
+ * @author Christopher Han <xiphux@gmail.com>
+ * @copyright Copyright (c) 2010 Christopher Han
+ * @package GitPHP
+ * @subpackage Git
+ */
 
+require_once(GITPHP_GITOBJECTDIR . 'ProjectListBase.class.php');
+require_once(GITPHP_GITOBJECTDIR . 'Project.class.php');
+
+define('GITPHP_NO_CATEGORY', 'none');
+
+/**
+ * ProjectListArrayLegacy class
+ *
+ * @package GitPHP
+ * @subpackage Git
+ */
+class GitPHP_ProjectListArrayLegacy extends GitPHP_ProjectListBase
+{
+
+	/**
+	 * __construct
+	 *
+	 * constructor
+	 *
+	 * @param mixed $projectArray array to read
+	 * @throws Exception if parameter is not an array
+	 * @access public
+	 */
+	public function __construct($projectArray)
+	{
+		if (!is_array($projectArray)) {
+			throw new Exception('An array of projects is required.');
+		}
+
+		$this->projectConfig = $projectArray;
+
+		parent::__construct();
+	}
+
+	/**
+	 * PopulateProjects
+	 *
+	 * Populates the internal list of projects
+	 *
+	 * @access protected
+	 * @throws Exception if file cannot be read
+	 */
+	protected function PopulateProjects()
+	{
+		foreach ($this->projectConfig as $cat => $plist) {
+			if (is_array($plist)) {
+				foreach ($plist as $pname => $ppath) {
+					try {
+						$projObj = new GitPHP_Project($ppath);
+						if ($cat != GITPHP_NO_CATEGORY)
+							$projObj->SetCategory($cat);
+						$this->projects[] = $projObj;
+					} catch (Exception $e) {
+					}
+				}
+			}
+		}
+	}
+
+}
+

file:a/index.php -> file:b/index.php
--- a/index.php
+++ b/index.php
@@ -62,7 +62,11 @@
 	/*
 	 * Project list
 	 */
-	GitPHP_ProjectList::Instantiate(GITPHP_CONFIGDIR . 'gitphp.conf.php');
+	if (file_exists(GITPHP_CONFIGDIR . 'projects.conf.php')) {
+		GitPHP_ProjectList::Instantiate(GITPHP_CONFIGDIR . 'projects.conf.php', false);
+	} else {
+		GitPHP_ProjectList::Instantiate(GITPHP_CONFIGDIR . 'gitphp.conf.php', true);
+	}
 
 	$controller = GitPHP_Controller::GetController((isset($_GET['a']) ? $_GET['a'] : null));
 	if ($controller) {

comments