forked from jpetso/versioncontrol
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Moved repo cache into separate include file.
- Loading branch information
Showing
2 changed files
with
252 additions
and
251 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,251 @@ | ||
<?php | ||
|
||
final class VersioncontrolRepositoryCache { | ||
private static $instance; | ||
private $backends = array(); | ||
private $repoCache = array('id' => array(), 'name' => array(), 'vcs' => array()); | ||
/** | ||
* Internal state variable indicating whether or not all repositories have | ||
* been fetched (via VersioncontrolRepositoryCache::getInstance()->getAllRepositories()). | ||
* @var bool | ||
*/ | ||
private $allFetched = FALSE; | ||
|
||
private function __construct() { | ||
// TODO really oughtta make this better. | ||
$this->backends = versioncontrol_get_backends(); | ||
} | ||
|
||
/** | ||
* Return the singleton's instance of the VersioncontrolRepositoryCache. | ||
* | ||
* @return VersioncontrolRepositoryCache | ||
*/ | ||
public static function getInstance() { | ||
if (!self::$instance instanceof VersioncontrolRepositoryCache) { | ||
self::$instance = new VersioncontrolRepositoryCache(); | ||
} | ||
return self::$instance; | ||
} | ||
|
||
/** | ||
* Convenience function for retrieving one single repository by repository id. | ||
* | ||
* @static | ||
* @return | ||
* A single VersioncontroRepository array. | ||
* If no repository corresponds to the given repository id, NULL is returned. | ||
*/ | ||
public function getRepository($repo_id) { | ||
if (!array_key_exists($repo_id, $this->repoCache['id'])) { | ||
$backends = versioncontrol_get_backends(); | ||
$sql = "SELECT repo_id, name, vcs, root, authorization_method, url_backend, data FROM {versioncontrol_repositories} WHERE repo_id = %d"; | ||
if ($base_info = db_fetch_array(db_query($sql, $repo_id))) { | ||
// $this->cacheRepository(new $backends[$base_info['vcs']]['repo_class']($base_info)); | ||
$this->cacheRepository(new VersioncontrolRepository($base_info)); | ||
} | ||
else { | ||
$this->repoCache['id'][$repo_id] = FALSE; | ||
} | ||
} | ||
return $this->repoCache['id'][$repo_id]; | ||
} | ||
|
||
/** | ||
* Retrieve a set of repositories that match the given constraints. | ||
* | ||
* @static | ||
* @param $constraints | ||
* An optional array of constraints. Possible array elements are: | ||
* | ||
* - 'vcs': An array of strings, like array('cvs', 'svn', 'git'). | ||
* If given, only repositories for these backends will be returned. | ||
* - 'repo_ids': An array of repository ids. | ||
* If given, only the corresponding repositories will be returned. | ||
* - 'names': An array of repository names, like | ||
* array('Drupal CVS', 'Experimental SVN'). If given, | ||
* only repositories with these repository names will be returned. | ||
* - '[xxx]_specific': An array of VCS specific constraints. How this array | ||
* looks like is defined by the corresponding backend module | ||
* (versioncontrol_[xxx]). Other backend modules won't get to see this | ||
* constraint, so in theory you can provide one of those for each backend | ||
* in one single query. | ||
* | ||
* @return | ||
* An array of repositories where the key of each element is the repository | ||
* id. The corresponding value contains a VersioncontrolRepository object. | ||
* If not a single repository matches these constraints, | ||
* an empty array is returned. | ||
*/ | ||
public function getRepositories($constraints = array()) { | ||
$backends = versioncontrol_get_backends(); | ||
$auth_methods = versioncontrol_get_authorization_methods(); | ||
|
||
if (isset($constraints['repo_ids'])) { | ||
$repo_ids = array(); | ||
foreach ($constraints['repo_ids'] as $repo_id) { | ||
$repo_ids[] = (int) $repo_id; | ||
} | ||
$constraints['repo_ids'] = $repo_ids; | ||
} | ||
|
||
$constraints_serialized = serialize($constraints); | ||
if (isset($this->repoCache[$constraints_serialized])) { | ||
return $this->repoCache[$constraints_serialized]; | ||
} | ||
|
||
list($and_constraints, $params) = | ||
_versioncontrol_construct_repository_constraints($constraints, $backends); | ||
|
||
// All the constraints have been gathered, assemble them to a WHERE clause. | ||
$where = empty($and_constraints) ? '' : ' WHERE '. implode(' AND ', $and_constraints); | ||
|
||
$result = db_query('SELECT * FROM {versioncontrol_repositories} r'. $where, $params); | ||
|
||
// Sort the retrieved repositories by backend. | ||
$repositories_by_backend = array(); | ||
|
||
while ($repository = db_fetch_array($result)) { | ||
if (!isset($backends[$repository['vcs']])) { | ||
// don't include repositories for which no backend module exists | ||
continue; | ||
} | ||
|
||
if (!isset($repositories_by_backend[$repository['vcs']])) { | ||
$repositories_by_backend[$repository['vcs']] = array(); | ||
} | ||
$repository[$repository['vcs'] .'_specific'] = array(); | ||
$repositories_by_backend[$repository['vcs']][$repository['repo_id']] = $repository; | ||
} | ||
|
||
$repositories_by_backend = $this->_amend_repositories( | ||
$repositories_by_backend, $backends | ||
); | ||
|
||
// Add the fully assembled repositories to the result array. | ||
$result_repositories = array(); | ||
foreach ($repositories_by_backend as $vcs => $vcs_repositories) { | ||
foreach ($vcs_repositories as $repository) { | ||
// $vcs_repository = new VersioncontrolRepository($repository['repo_id'], $repository['name'], $repository['vcs'], $repository['root'], $repository['authorization_method'], $repository['url_backend'], $repository['data']); | ||
$vcs_repository = new VersioncontrolRepository($repository); | ||
//FIXME: another idea for this? | ||
$vcs_specific_key = $repository['vcs'] .'_specific'; | ||
$vcs_repository->$vcs_specific_key = $repository[$repository['vcs'] .'_specific']; | ||
$result_repositories[$repository['repo_id']] = $vcs_repository; | ||
} | ||
} | ||
|
||
$this->repoCache[$constraints_serialized] = $result_repositories; // cache the results | ||
return $result_repositories; | ||
} | ||
|
||
public function getAllRepositories($build = FALSE) { | ||
if (!$this->allFetched) { | ||
$this->allFetched = TRUE; | ||
$backends = versioncontrol_get_backends(); | ||
$excluded = ''; | ||
if (!empty($this->repoCache['id'])) { | ||
// Exclude any repos that have already been loaded & cached. | ||
$excluded = ' WHERE repo_id NOT IN (' . implode(', ', array_keys($this->repoCache['id'])) . ')'; | ||
} | ||
|
||
$result = db_query("SELECT repo_id, name, vcs, root, authorization_method, url_backend, data FROM {versioncontrol_repositories}$excluded"); | ||
while ($base_info = db_fetch_array($result)) { | ||
$base_info['data'] = empty($base_info['data']) ? '' : unserialize($base_info['data']); | ||
// TODO make this static. possibly do it with reflection. | ||
// $repository = new $backends[$base_info['vcs']]['repo_class']($base_info); | ||
$repository = new VersioncontrolRepository($base_info); | ||
if ($build) { | ||
$repository->build(); | ||
} | ||
$this->cacheRepository($repository); | ||
} | ||
} | ||
return $this->repoCache['id']; | ||
} | ||
|
||
private function cacheRepository(VersioncontrolRepository &$repository) { | ||
$this->repoCache['id'][$repository->repo_id] = &$repository; | ||
$this->repoCache['name'][$repository->name] = &$repository; | ||
$this->repoCache['vcs'][$repository->vcs][$repository->repo_id] = &$repository; | ||
} | ||
|
||
/** | ||
* Fetch VCS specific repository data additions, either by ourselves (if the | ||
* VERSIONCONTROL_FLAG_AUTOADD_REPOSITORIES flag has been set by the backend) | ||
* and/or by calling [vcs_backend]_alter_repositories(). | ||
* | ||
* @static | ||
* @param $repositories_by_backend | ||
* @param $backends | ||
* @param $constraints | ||
*/ | ||
private function _amend_repositories($repositories_by_backend, $backends, $constraints = array()) { | ||
foreach ($repositories_by_backend as $vcs => $vcs_repositories) { | ||
$is_autoadd = in_array(VERSIONCONTROL_FLAG_AUTOADD_REPOSITORIES, | ||
$backends[$vcs]['flags']); | ||
|
||
if ($is_autoadd) { | ||
$repo_ids = array(); | ||
foreach ($vcs_repositories as $repo_id => $repository) { | ||
$repo_ids[] = $repo_id; | ||
} | ||
$additions = $this->_dbGetAdditions( | ||
'versioncontrol_'. $vcs .'_repositories', 'repo_id', $repo_ids | ||
); | ||
|
||
foreach ($additions as $repo_id => $addition) { | ||
if (isset($vcs_repositories[$repo_id])) { | ||
$vcs_repositories[$repo_id][$vcs .'_specific'] = $addition; | ||
} | ||
} | ||
} | ||
|
||
$vcs_specific_constraints = isset($constraints[$vcs .'_specific']) | ||
? $constraints[$vcs .'_specific'] | ||
: array(); | ||
|
||
// Provide an opportunity for the backend to add its own stuff. | ||
if (versioncontrol_backend_implements($vcs, 'alter_repositories')) { | ||
$function = 'versioncontrol_'. $vcs .'_alter_repositories'; | ||
$function($vcs_repositories, $vcs_specific_constraints); | ||
} | ||
$repositories_by_backend[$vcs] = $vcs_repositories; | ||
} | ||
return $repositories_by_backend; | ||
} | ||
|
||
/** | ||
* Generate and execute a SELECT query for the given table base on the name | ||
* and given values of this table's primary key. This function basically | ||
* accomplishes the retrieval part of Version Control API's 'autoadd' feature. | ||
* In order to avoid unnecessary complexity, the primary key may not consist | ||
* of multiple columns and has to be a numeric value. | ||
*/ | ||
private function _dbGetAdditions($table_name, $primary_key_name, $keys) { | ||
$placeholders = array(); | ||
|
||
foreach ($keys as $key) { | ||
$placeholders[] = '%d'; | ||
} | ||
|
||
$result = db_query('SELECT * FROM {'. $table_name .'} | ||
WHERE '. $primary_key_name .' IN ('. | ||
implode(',', $placeholders) .')', $keys); | ||
|
||
$additions = array(); | ||
while ($addition = db_fetch_array($result)) { | ||
$primary_key = $addition[$primary_key_name]; | ||
unset($addition[$primary_key_name]); | ||
|
||
foreach ($addition as $key => $value) { | ||
if (!is_numeric($addition[$key])) { | ||
$addition[$key] = unserialize($addition[$key]); | ||
} | ||
} | ||
$additions[$primary_key] = $addition; | ||
} | ||
return $additions; | ||
|
||
} | ||
} |
Oops, something went wrong.