2011-12-16 17:08:18 -08:00
|
|
|
<?php
|
|
|
|
|
2012-09-13 10:15:08 -07:00
|
|
|
final class PhabricatorProjectQuery
|
|
|
|
extends PhabricatorCursorPagedPolicyAwareQuery {
|
2011-12-16 17:08:18 -08:00
|
|
|
|
2012-01-17 16:29:35 -08:00
|
|
|
private $ids;
|
|
|
|
private $phids;
|
2012-08-07 11:54:24 -07:00
|
|
|
private $memberPHIDs;
|
2011-12-16 17:08:18 -08:00
|
|
|
|
2012-02-07 14:59:38 -08:00
|
|
|
private $status = 'status-any';
|
|
|
|
const STATUS_ANY = 'status-any';
|
|
|
|
const STATUS_OPEN = 'status-open';
|
|
|
|
const STATUS_CLOSED = 'status-closed';
|
|
|
|
const STATUS_ACTIVE = 'status-active';
|
|
|
|
const STATUS_ARCHIVED = 'status-archived';
|
|
|
|
|
2012-01-17 16:29:35 -08:00
|
|
|
private $needMembers;
|
|
|
|
|
|
|
|
public function withIDs(array $ids) {
|
|
|
|
$this->ids = $ids;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function withPHIDs(array $phids) {
|
|
|
|
$this->phids = $phids;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2012-02-07 14:59:38 -08:00
|
|
|
public function withStatus($status) {
|
|
|
|
$this->status = $status;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2012-08-07 11:54:24 -07:00
|
|
|
public function withMemberPHIDs(array $member_phids) {
|
|
|
|
$this->memberPHIDs = $member_phids;
|
2011-12-16 17:08:18 -08:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2012-01-17 16:29:35 -08:00
|
|
|
public function needMembers($need_members) {
|
|
|
|
$this->needMembers = $need_members;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2012-08-08 17:10:10 -07:00
|
|
|
protected function getPagingColumn() {
|
|
|
|
return 'name';
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getPagingValue($result) {
|
|
|
|
return $result->getName();
|
|
|
|
}
|
|
|
|
|
2012-08-11 07:05:45 -07:00
|
|
|
protected function getReversePaging() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-03-01 11:28:02 -08:00
|
|
|
protected function loadPage() {
|
2012-08-07 11:54:39 -07:00
|
|
|
$table = new PhabricatorProject();
|
2011-12-16 17:08:18 -08:00
|
|
|
$conn_r = $table->establishConnection('r');
|
|
|
|
|
2012-08-11 07:05:01 -07:00
|
|
|
// NOTE: Because visibility checks for projects depend on whether or not
|
|
|
|
// the user is a project member, we always load their membership. If we're
|
|
|
|
// loading all members anyway we can piggyback on that; otherwise we
|
|
|
|
// do an explicit join.
|
|
|
|
|
|
|
|
$select_clause = '';
|
|
|
|
if (!$this->needMembers) {
|
|
|
|
$select_clause = ', vm.dst viewerIsMember';
|
|
|
|
}
|
|
|
|
|
2011-12-16 17:08:18 -08:00
|
|
|
$data = queryfx_all(
|
|
|
|
$conn_r,
|
2012-08-11 07:05:01 -07:00
|
|
|
'SELECT p.* %Q FROM %T p %Q %Q %Q %Q %Q',
|
|
|
|
$select_clause,
|
2011-12-16 17:08:18 -08:00
|
|
|
$table->getTableName(),
|
2012-08-07 18:02:05 -07:00
|
|
|
$this->buildJoinClause($conn_r),
|
|
|
|
$this->buildWhereClause($conn_r),
|
|
|
|
$this->buildGroupClause($conn_r),
|
2012-08-11 07:05:01 -07:00
|
|
|
$this->buildOrderClause($conn_r),
|
2012-08-07 11:54:39 -07:00
|
|
|
$this->buildLimitClause($conn_r));
|
2011-12-16 17:08:18 -08:00
|
|
|
|
2012-01-17 16:29:35 -08:00
|
|
|
$projects = $table->loadAllFromArray($data);
|
|
|
|
|
2012-08-11 07:05:01 -07:00
|
|
|
if ($projects) {
|
|
|
|
$viewer_phid = $this->getViewer()->getPHID();
|
|
|
|
if ($this->needMembers) {
|
|
|
|
$etype = PhabricatorEdgeConfig::TYPE_PROJ_MEMBER;
|
|
|
|
$members = id(new PhabricatorEdgeQuery())
|
|
|
|
->withSourcePHIDs(mpull($projects, 'getPHID'))
|
|
|
|
->withEdgeTypes(array($etype))
|
|
|
|
->execute();
|
|
|
|
foreach ($projects as $project) {
|
|
|
|
$phid = $project->getPHID();
|
|
|
|
$project->attachMemberPHIDs(array_keys($members[$phid][$etype]));
|
|
|
|
$project->setIsUserMember(
|
|
|
|
$viewer_phid,
|
|
|
|
isset($members[$phid][$etype][$viewer_phid]));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
foreach ($data as $row) {
|
|
|
|
$projects[$row['id']]->setIsUserMember(
|
|
|
|
$viewer_phid,
|
|
|
|
($row['viewerIsMember'] !== null));
|
|
|
|
}
|
2012-01-17 16:29:35 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $projects;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function buildWhereClause($conn_r) {
|
|
|
|
$where = array();
|
|
|
|
|
2012-02-07 14:59:38 -08:00
|
|
|
if ($this->status != self::STATUS_ANY) {
|
|
|
|
switch ($this->status) {
|
|
|
|
case self::STATUS_OPEN:
|
|
|
|
case self::STATUS_ACTIVE:
|
2012-08-07 18:02:05 -07:00
|
|
|
$filter = array(
|
|
|
|
PhabricatorProjectStatus::STATUS_ACTIVE,
|
|
|
|
);
|
2012-02-07 14:59:38 -08:00
|
|
|
break;
|
2012-08-07 18:02:05 -07:00
|
|
|
case self::STATUS_CLOSED:
|
2012-02-07 14:59:38 -08:00
|
|
|
case self::STATUS_ARCHIVED:
|
2012-08-07 18:02:05 -07:00
|
|
|
$filter = array(
|
|
|
|
PhabricatorProjectStatus::STATUS_ARCHIVED,
|
|
|
|
);
|
2012-02-07 14:59:38 -08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new Exception(
|
|
|
|
"Unknown project status '{$this->status}'!");
|
|
|
|
}
|
2012-08-07 18:02:05 -07:00
|
|
|
$where[] = qsprintf(
|
|
|
|
$conn_r,
|
|
|
|
'status IN (%Ld)',
|
|
|
|
$filter);
|
2012-02-07 14:59:38 -08:00
|
|
|
}
|
|
|
|
|
2012-01-17 16:29:35 -08:00
|
|
|
if ($this->ids) {
|
|
|
|
$where[] = qsprintf(
|
|
|
|
$conn_r,
|
|
|
|
'id IN (%Ld)',
|
|
|
|
$this->ids);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->phids) {
|
|
|
|
$where[] = qsprintf(
|
|
|
|
$conn_r,
|
|
|
|
'phid IN (%Ls)',
|
|
|
|
$this->phids);
|
|
|
|
}
|
|
|
|
|
2012-08-07 18:02:05 -07:00
|
|
|
if ($this->memberPHIDs) {
|
|
|
|
$where[] = qsprintf(
|
|
|
|
$conn_r,
|
2012-08-11 07:05:01 -07:00
|
|
|
'e.dst IN (%Ls)',
|
2012-08-07 18:02:05 -07:00
|
|
|
$this->memberPHIDs);
|
|
|
|
}
|
|
|
|
|
2012-08-08 17:10:10 -07:00
|
|
|
$where[] = $this->buildPagingClause($conn_r);
|
|
|
|
|
2012-08-07 11:54:39 -07:00
|
|
|
return $this->formatWhereClause($where);
|
2011-12-16 17:08:18 -08:00
|
|
|
}
|
|
|
|
|
2012-08-07 18:02:05 -07:00
|
|
|
private function buildGroupClause($conn_r) {
|
|
|
|
if ($this->memberPHIDs) {
|
|
|
|
return 'GROUP BY p.id';
|
|
|
|
} else {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
}
|
2011-12-16 17:08:18 -08:00
|
|
|
|
2012-08-07 18:02:05 -07:00
|
|
|
private function buildJoinClause($conn_r) {
|
2011-12-16 17:08:18 -08:00
|
|
|
$joins = array();
|
2012-08-07 18:02:05 -07:00
|
|
|
|
2012-08-11 07:05:01 -07:00
|
|
|
if (!$this->needMembers) {
|
|
|
|
$joins[] = qsprintf(
|
|
|
|
$conn_r,
|
|
|
|
'LEFT JOIN %T vm ON vm.src = p.phid AND vm.type = %d AND vm.dst = %s',
|
|
|
|
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
|
|
|
|
PhabricatorEdgeConfig::TYPE_PROJ_MEMBER,
|
|
|
|
$this->getViewer()->getPHID());
|
|
|
|
}
|
|
|
|
|
2012-08-07 11:54:24 -07:00
|
|
|
if ($this->memberPHIDs) {
|
2011-12-16 17:08:18 -08:00
|
|
|
$joins[] = qsprintf(
|
|
|
|
$conn_r,
|
2012-08-11 07:05:01 -07:00
|
|
|
'JOIN %T e ON e.src = p.phid AND e.type = %d',
|
|
|
|
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
|
|
|
|
PhabricatorEdgeConfig::TYPE_PROJ_MEMBER);
|
2011-12-16 17:08:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return implode(' ', $joins);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|