- move getProjectsWithLabelCounts to IDF_Views (where the other functions
reside as well) and make it static - refactor out the code from getProjects that determines which projects are visible by a user and use the same code to restrict the count that we calculate for all available project tags - calculating the project stats is now no longer O(5n) but simply O(5) when it comes to SQL queries (where n is the number of filtered projects); remove the member statistic since it makes no sense in this context
This commit is contained in:
parent
dd2fa6f902
commit
03404adf64
@ -5,6 +5,8 @@
|
|||||||
- Compatiblity fixes for PostgreSQL (fixes issue 800)
|
- Compatiblity fixes for PostgreSQL (fixes issue 800)
|
||||||
- Fix TOC generation in wiki (issue 803)
|
- Fix TOC generation in wiki (issue 803)
|
||||||
- Make the display of large files and diffs faster (fixes issue 804)
|
- Make the display of large files and diffs faster (fixes issue 804)
|
||||||
|
- Make the project list faster and its tag list more accurate by not
|
||||||
|
counting projects that are invisible to the current user
|
||||||
|
|
||||||
## Language and Translations
|
## Language and Translations
|
||||||
|
|
||||||
|
@ -52,31 +52,6 @@ class IDF_Forge
|
|||||||
$this->conf->setVal('project_labels', $labels);
|
$this->conf->setVal('project_labels', $labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProjectLabelsWithCounts() {
|
|
||||||
$sql = new Pluf_SQL('project IS NULL');
|
|
||||||
$tagList = Pluf::factory('IDF_Tag')->getList(array(
|
|
||||||
'filter' => $sql->gen(),
|
|
||||||
'view' => 'join_projects',
|
|
||||||
'order' => 'class ASC, lcname ASC'
|
|
||||||
));
|
|
||||||
|
|
||||||
$maxProjectCount = 0;
|
|
||||||
foreach ($tagList as $tag) {
|
|
||||||
$maxProjectCount = max($maxProjectCount, $tag->project_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
$tags = array();
|
|
||||||
foreach ($tagList as $tag) {
|
|
||||||
// group by class
|
|
||||||
if (!array_key_exists($tag->class, $tags)) {
|
|
||||||
$tags[$tag->class] = array();
|
|
||||||
}
|
|
||||||
$tag->rel_project_count = $tag->project_count / (double) $maxProjectCount;
|
|
||||||
$tags[$tag->class][] = $tag;
|
|
||||||
}
|
|
||||||
return $tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCustomForgePageEnabled($enabled) {
|
public function setCustomForgePageEnabled($enabled) {
|
||||||
$this->conf->setVal('custom_forge_page_enabled', $enabled);
|
$this->conf->setVal('custom_forge_page_enabled', $enabled);
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ class IDF_Views
|
|||||||
|
|
||||||
$projects = self::getProjects($request->user, $tag, $order);
|
$projects = self::getProjects($request->user, $tag, $order);
|
||||||
$stats = self::getProjectsStatistics($projects);
|
$stats = self::getProjectsStatistics($projects);
|
||||||
$projectLabels = IDF_Forge::instance()->getProjectLabelsWithCounts();
|
$projectLabels = self::getProjectLabelsWithCounts($request->user);
|
||||||
|
|
||||||
return Pluf_Shortcuts_RenderToResponse('idf/listProjects.html',
|
return Pluf_Shortcuts_RenderToResponse('idf/listProjects.html',
|
||||||
array('page_title' => __('Projects'),
|
array('page_title' => __('Projects'),
|
||||||
@ -371,6 +371,61 @@ class IDF_Views
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of ids of projects that are visible for the given user
|
||||||
|
*
|
||||||
|
* @param Pluf_User $user
|
||||||
|
*/
|
||||||
|
private static function getUserVisibleProjectIds($user)
|
||||||
|
{
|
||||||
|
$db =& Pluf::db();
|
||||||
|
// the administrator can see all projects
|
||||||
|
if ($user->administrator) {
|
||||||
|
$sql_results = $db->select(
|
||||||
|
'SELECT id FROM '.Pluf::f('db_table_prefix', '').'idf_projects'
|
||||||
|
);
|
||||||
|
foreach ($sql_results as $id) {
|
||||||
|
$ids[] = $id['id'];
|
||||||
|
}
|
||||||
|
return $ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
// anonymous users can only see non-private projects
|
||||||
|
$false = Pluf_DB_BooleanToDb(false, $db);
|
||||||
|
$sql_results = $db->select(
|
||||||
|
'SELECT id FROM '.$db->pfx.'idf_projects '.
|
||||||
|
'WHERE '.$db->qn('private').'='.$false
|
||||||
|
);
|
||||||
|
|
||||||
|
$ids = array();
|
||||||
|
foreach ($sql_results as $id) {
|
||||||
|
$ids[] = $id['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// registered users may additionally see private projects with which
|
||||||
|
// they're somehow affiliated
|
||||||
|
if (!$user->isAnonymous()) {
|
||||||
|
$perms = array(
|
||||||
|
Pluf_Permission::getFromString('IDF.project-member'),
|
||||||
|
Pluf_Permission::getFromString('IDF.project-owner'),
|
||||||
|
Pluf_Permission::getFromString('IDF.project-authorized-user')
|
||||||
|
);
|
||||||
|
$permSql = new Pluf_SQL(
|
||||||
|
"model_class='IDF_Project' AND owner_class='Pluf_User' ".
|
||||||
|
"AND owner_id=%s AND negative=".$false, $user->id
|
||||||
|
);
|
||||||
|
$rows = Pluf::factory('Pluf_RowPermission')->getList(array('filter' => $permSql->gen()));
|
||||||
|
if ($rows->count() > 0) {
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
if (in_array($row->model_id, $ids))
|
||||||
|
continue;
|
||||||
|
$ids[] = $row->model_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ids;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of projects accessible for the user and optionally filtered by tag.
|
* Returns a list of projects accessible for the user and optionally filtered by tag.
|
||||||
*
|
*
|
||||||
@ -381,37 +436,14 @@ class IDF_Views
|
|||||||
public static function getProjects($user, $tag = false, $order = 'name')
|
public static function getProjects($user, $tag = false, $order = 'name')
|
||||||
{
|
{
|
||||||
$db =& Pluf::db();
|
$db =& Pluf::db();
|
||||||
$false = Pluf_DB_BooleanToDb(false, $db);
|
|
||||||
$sql = new Pluf_SQL('1=1');
|
$sql = new Pluf_SQL('1=1');
|
||||||
if ($tag !== false) {
|
if ($tag !== false) {
|
||||||
$sql->SAnd(new Pluf_SQL('idf_tag_id=%s', $tag->id));
|
$sql->SAnd(new Pluf_SQL('idf_tag_id=%s', $tag->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($user->isAnonymous())
|
$projectIds = self::getUserVisibleProjectIds($user);
|
||||||
{
|
if (count($projectIds) > 0) {
|
||||||
$authSql = new Pluf_SQL($db->qn('private').'='.$false);
|
$sql->SAnd(new Pluf_SQL(sprintf($db->pfx.'idf_projects.id IN (%s)', implode(', ', $projectIds))));
|
||||||
$sql->SAnd($authSql);
|
|
||||||
} else
|
|
||||||
if (!$user->administrator) {
|
|
||||||
// grab the list of projects where the user is admin,
|
|
||||||
// member or authorized
|
|
||||||
$perms = array(
|
|
||||||
Pluf_Permission::getFromString('IDF.project-member'),
|
|
||||||
Pluf_Permission::getFromString('IDF.project-owner'),
|
|
||||||
Pluf_Permission::getFromString('IDF.project-authorized-user')
|
|
||||||
);
|
|
||||||
$permSql = new Pluf_SQL("model_class='IDF_Project' AND owner_class='Pluf_User' AND owner_id=%s AND negative=".$false, $user->id);
|
|
||||||
$rows = Pluf::factory('Pluf_RowPermission')->getList(array('filter' => $permSql->gen()));
|
|
||||||
|
|
||||||
$authSql = new Pluf_SQL($db->qn('private').'='.$false);
|
|
||||||
if ($rows->count() > 0) {
|
|
||||||
$ids = array();
|
|
||||||
foreach ($rows as $row) {
|
|
||||||
$ids[] = $row->model_id;
|
|
||||||
}
|
|
||||||
$authSql->SOr(new Pluf_SQL(sprintf($db->pfx.'idf_projects.id IN (%s)', implode(', ', $ids))));
|
|
||||||
}
|
|
||||||
$sql->SAnd($authSql);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$orderTypes = array(
|
$orderTypes = array(
|
||||||
@ -425,6 +457,46 @@ class IDF_Views
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of global tags each carrying the number of projects that have the
|
||||||
|
* particular tag set
|
||||||
|
*
|
||||||
|
* @param Pluf_User $user
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getProjectLabelsWithCounts($user) {
|
||||||
|
|
||||||
|
$sql = new Pluf_SQL('project IS NULL');
|
||||||
|
|
||||||
|
$projectIds = self::getUserVisibleProjectIds($user);
|
||||||
|
if (count($projectIds) > 0) {
|
||||||
|
$sql->SAnd(new Pluf_SQL(sprintf('idf_project_id IN (%s)', implode(', ', $projectIds))));
|
||||||
|
}
|
||||||
|
|
||||||
|
$tagList = Pluf::factory('IDF_Tag')->getList(array(
|
||||||
|
'filter' => $sql->gen(),
|
||||||
|
'view' => 'join_projects',
|
||||||
|
'order' => 'class ASC, lcname ASC'
|
||||||
|
));
|
||||||
|
|
||||||
|
$maxProjectCount = 0;
|
||||||
|
foreach ($tagList as $tag) {
|
||||||
|
$maxProjectCount = max($maxProjectCount, $tag->project_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tags = array();
|
||||||
|
foreach ($tagList as $tag) {
|
||||||
|
// group by class
|
||||||
|
if (!array_key_exists($tag->class, $tags)) {
|
||||||
|
$tags[$tag->class] = array();
|
||||||
|
}
|
||||||
|
$tag->rel_project_count = $tag->project_count / (double) $maxProjectCount;
|
||||||
|
$tags[$tag->class][] = $tag;
|
||||||
|
}
|
||||||
|
return $tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns statistics on a list of projects.
|
* Returns statistics on a list of projects.
|
||||||
*
|
*
|
||||||
@ -433,27 +505,30 @@ class IDF_Views
|
|||||||
*/
|
*/
|
||||||
public static function getProjectsStatistics($projects)
|
public static function getProjectsStatistics($projects)
|
||||||
{
|
{
|
||||||
// Init the return var
|
$projectIds = array();
|
||||||
$forgestats = array('downloads' => 0,
|
foreach ($projects as $project) {
|
||||||
'reviews' => 0,
|
$projectIds[] = $project->id;
|
||||||
'issues' => 0,
|
|
||||||
'docpages' => 0,
|
|
||||||
'commits' => 0);
|
|
||||||
|
|
||||||
// Count for each projects
|
|
||||||
foreach ($projects as $p) {
|
|
||||||
$pstats = $p->getStats();
|
|
||||||
$forgestats['downloads'] += $pstats['downloads'];
|
|
||||||
$forgestats['reviews'] += $pstats['reviews'];
|
|
||||||
$forgestats['issues'] += $pstats['issues'];
|
|
||||||
$forgestats['docpages'] += $pstats['docpages'];
|
|
||||||
$forgestats['commits'] += $pstats['commits'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count members
|
$forgestats = array();
|
||||||
$sql = new Pluf_SQL('first_name != %s', array('---'));
|
|
||||||
$forgestats['members'] = Pluf::factory('Pluf_User')
|
// count overall project stats
|
||||||
->getCount(array('filter' => $sql->gen()));
|
$forgestats['total'] = 0;
|
||||||
|
$what = array(
|
||||||
|
'downloads' => 'IDF_Upload',
|
||||||
|
'reviews' => 'IDF_Review',
|
||||||
|
'issues' => 'IDF_Issue',
|
||||||
|
'docpages' => 'IDF_Wiki_Page',
|
||||||
|
'commits' => 'IDF_Commit',
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($what as $key => $model) {
|
||||||
|
$count = Pluf::factory($model)->getCount(array(
|
||||||
|
'filter' => sprintf('project IN (%s)', implode(', ', $projectIds))
|
||||||
|
));
|
||||||
|
$forgestats[$key] = $count;
|
||||||
|
$forgestats['total'] += $count;
|
||||||
|
}
|
||||||
|
|
||||||
return $forgestats;
|
return $forgestats;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,6 @@
|
|||||||
|
|
||||||
<strong>{trans 'Filtered project stats'}</strong>
|
<strong>{trans 'Filtered project stats'}</strong>
|
||||||
<dl class="statistics smaller">
|
<dl class="statistics smaller">
|
||||||
<dt>{trans 'Members:'}</dt><dd>{$stats.members}</dd>
|
|
||||||
<dt>{trans 'Issues:'}</dt><dd>{$stats.issues}</dd>
|
<dt>{trans 'Issues:'}</dt><dd>{$stats.issues}</dd>
|
||||||
<dt>{trans 'Commits:'}</dt><dd>{$stats.commits}</dd>
|
<dt>{trans 'Commits:'}</dt><dd>{$stats.commits}</dd>
|
||||||
<dt>{trans 'Documentations:'}</dt><dd>{$stats.docpages}</dd>
|
<dt>{trans 'Documentations:'}</dt><dd>{$stats.docpages}</dd>
|
||||||
|
Loading…
Reference in New Issue
Block a user