mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 23:02:42 +01:00
Migrate project membership to edges
Summary: - Store project members in edges. - Migrate existing members to edge storage. - Delete PhabricatorProjectAffiliation. - I left the actual underlying data around just in case something goes wrong; we can delete it evenutally. Test Plan: - Ran migration. - Created a new project. - Joined and left a project. - Added and removed project members. - Manually called PhabricatorOwnersOwner::loadAffiliatedUserPHIDs() to verify its behavior. Reviewers: vrana, btrahan Reviewed By: vrana CC: aran Maniphest Tasks: T603 Differential Revision: https://secure.phabricator.com/D3186
This commit is contained in:
parent
d5a0352fd7
commit
f9fcaa1f84
11 changed files with 164 additions and 165 deletions
49
resources/sql/patches/migrate-project-edges.php
Normal file
49
resources/sql/patches/migrate-project-edges.php
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo "Migrating project members to edges...\n";
|
||||||
|
foreach (new LiskMigrationIterator(new PhabricatorProject()) as $proj) {
|
||||||
|
$id = $proj->getID();
|
||||||
|
echo "Project {$id}: ";
|
||||||
|
|
||||||
|
$members = queryfx_all(
|
||||||
|
$proj->establishConnection('r'),
|
||||||
|
'SELECT userPHID FROM %T WHERE projectPHID = %s',
|
||||||
|
'project_affiliation',
|
||||||
|
$proj->getPHID());
|
||||||
|
|
||||||
|
if (!$members) {
|
||||||
|
echo "-\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$members = ipull($members, 'userPHID');
|
||||||
|
|
||||||
|
$editor = new PhabricatorEdgeEditor();
|
||||||
|
$editor->setSuppressEvents(true);
|
||||||
|
foreach ($members as $user_phid) {
|
||||||
|
$editor->addEdge(
|
||||||
|
$proj->getPHID(),
|
||||||
|
PhabricatorEdgeConfig::TYPE_PROJ_MEMBER,
|
||||||
|
$user_phid);
|
||||||
|
}
|
||||||
|
$editor->save();
|
||||||
|
echo "OKAY\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Done.\n";
|
|
@ -894,7 +894,6 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPolicyTestQuery' => 'applications/policy/__tests__/PhabricatorPolicyTestQuery.php',
|
'PhabricatorPolicyTestQuery' => 'applications/policy/__tests__/PhabricatorPolicyTestQuery.php',
|
||||||
'PhabricatorProfileHeaderView' => 'view/layout/PhabricatorProfileHeaderView.php',
|
'PhabricatorProfileHeaderView' => 'view/layout/PhabricatorProfileHeaderView.php',
|
||||||
'PhabricatorProject' => 'applications/project/storage/PhabricatorProject.php',
|
'PhabricatorProject' => 'applications/project/storage/PhabricatorProject.php',
|
||||||
'PhabricatorProjectAffiliation' => 'applications/project/storage/PhabricatorProjectAffiliation.php',
|
|
||||||
'PhabricatorProjectConstants' => 'applications/project/constants/PhabricatorProjectConstants.php',
|
'PhabricatorProjectConstants' => 'applications/project/constants/PhabricatorProjectConstants.php',
|
||||||
'PhabricatorProjectController' => 'applications/project/controller/PhabricatorProjectController.php',
|
'PhabricatorProjectController' => 'applications/project/controller/PhabricatorProjectController.php',
|
||||||
'PhabricatorProjectCreateController' => 'applications/project/controller/PhabricatorProjectCreateController.php',
|
'PhabricatorProjectCreateController' => 'applications/project/controller/PhabricatorProjectCreateController.php',
|
||||||
|
@ -1933,7 +1932,6 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPolicyTestQuery' => 'PhabricatorPolicyQuery',
|
'PhabricatorPolicyTestQuery' => 'PhabricatorPolicyQuery',
|
||||||
'PhabricatorProfileHeaderView' => 'AphrontView',
|
'PhabricatorProfileHeaderView' => 'AphrontView',
|
||||||
'PhabricatorProject' => 'PhabricatorProjectDAO',
|
'PhabricatorProject' => 'PhabricatorProjectDAO',
|
||||||
'PhabricatorProjectAffiliation' => 'PhabricatorProjectDAO',
|
|
||||||
'PhabricatorProjectController' => 'PhabricatorController',
|
'PhabricatorProjectController' => 'PhabricatorController',
|
||||||
'PhabricatorProjectCreateController' => 'PhabricatorProjectController',
|
'PhabricatorProjectCreateController' => 'PhabricatorProjectController',
|
||||||
'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',
|
'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',
|
||||||
|
|
|
@ -58,12 +58,13 @@ final class PhabricatorOwnersOwner extends PhabricatorOwnersDAO {
|
||||||
array());
|
array());
|
||||||
|
|
||||||
$users_in_project_phids = array();
|
$users_in_project_phids = array();
|
||||||
if (idx($all_phids, PhabricatorPHIDConstants::PHID_TYPE_PROJ)) {
|
$project_phids = idx($all_phids, PhabricatorPHIDConstants::PHID_TYPE_PROJ);
|
||||||
$users_in_project_phids = mpull(
|
if ($project_phids) {
|
||||||
id(new PhabricatorProjectAffiliation())->loadAllWhere(
|
$query = id(new PhabricatorEdgeQuery())
|
||||||
'projectPHID IN (%Ls)',
|
->withSourcePHIDs($project_phids)
|
||||||
idx($all_phids, PhabricatorPHIDConstants::PHID_TYPE_PROJ, array())),
|
->withEdgeTypes(array(PhabricatorEdgeConfig::TYPE_PROJ_MEMBER));
|
||||||
'getUserPHID');
|
$query->execute();
|
||||||
|
$users_in_project_phids = $query->getDestinationPHIDs();
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_unique(array_merge($users_in_project_phids, $user_phids));
|
return array_unique(array_merge($users_in_project_phids, $user_phids));
|
||||||
|
|
|
@ -35,12 +35,19 @@ final class PhabricatorProjectCreateController
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$xactions = array();
|
$xactions = array();
|
||||||
|
|
||||||
$xaction = new PhabricatorProjectTransaction();
|
$xaction = new PhabricatorProjectTransaction();
|
||||||
$xaction->setTransactionType(
|
$xaction->setTransactionType(
|
||||||
PhabricatorProjectTransactionType::TYPE_NAME);
|
PhabricatorProjectTransactionType::TYPE_NAME);
|
||||||
$xaction->setNewValue($request->getStr('name'));
|
$xaction->setNewValue($request->getStr('name'));
|
||||||
$xactions[] = $xaction;
|
$xactions[] = $xaction;
|
||||||
|
|
||||||
|
$xaction = new PhabricatorProjectTransaction();
|
||||||
|
$xaction->setTransactionType(
|
||||||
|
PhabricatorProjectTransactionType::TYPE_MEMBERS);
|
||||||
|
$xaction->setNewValue(array($user->getPHID()));
|
||||||
|
$xactions[] = $xaction;
|
||||||
|
|
||||||
$editor = new PhabricatorProjectEditor($project);
|
$editor = new PhabricatorProjectEditor($project);
|
||||||
$editor->setUser($user);
|
$editor->setUser($user);
|
||||||
$editor->applyTransactions($xactions);
|
$editor->applyTransactions($xactions);
|
||||||
|
@ -56,13 +63,6 @@ final class PhabricatorProjectCreateController
|
||||||
$profile->setProjectPHID($project->getPHID());
|
$profile->setProjectPHID($project->getPHID());
|
||||||
$profile->save();
|
$profile->save();
|
||||||
|
|
||||||
id(new PhabricatorProjectAffiliation())
|
|
||||||
->setUserPHID($user->getPHID())
|
|
||||||
->setProjectPHID($project->getPHID())
|
|
||||||
->setRole('Owner')
|
|
||||||
->setIsOwner(true)
|
|
||||||
->save();
|
|
||||||
|
|
||||||
if ($request->isAjax()) {
|
if ($request->isAjax()) {
|
||||||
return id(new AphrontAjaxResponse())
|
return id(new AphrontAjaxResponse())
|
||||||
->setContent(array(
|
->setContent(array(
|
||||||
|
|
|
@ -81,10 +81,12 @@ final class PhabricatorProjectListController
|
||||||
$profiles = mpull($profiles, null, 'getProjectPHID');
|
$profiles = mpull($profiles, null, 'getProjectPHID');
|
||||||
}
|
}
|
||||||
|
|
||||||
$affil_groups = array();
|
$edge_query = new PhabricatorEdgeQuery();
|
||||||
if ($projects) {
|
if ($projects) {
|
||||||
$affil_groups = PhabricatorProjectAffiliation::loadAllForProjectPHIDs(
|
$edge_query
|
||||||
$project_phids);
|
->withSourcePHIDs($project_phids)
|
||||||
|
->withEdgeTypes(array(PhabricatorEdgeConfig::TYPE_PROJ_MEMBER))
|
||||||
|
->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
$tasks = array();
|
$tasks = array();
|
||||||
|
@ -104,18 +106,17 @@ final class PhabricatorProjectListController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$rows = array();
|
$rows = array();
|
||||||
foreach ($projects as $project) {
|
foreach ($projects as $project) {
|
||||||
$phid = $project->getPHID();
|
$phid = $project->getPHID();
|
||||||
|
|
||||||
$profile = idx($profiles, $phid);
|
$profile = idx($profiles, $phid);
|
||||||
$affiliations = $affil_groups[$phid];
|
$members = $edge_query->getDestinationPHIDs(array($phid));
|
||||||
|
|
||||||
$group = idx($groups, $phid, array());
|
$group = idx($groups, $phid, array());
|
||||||
$task_count = count($group);
|
$task_count = count($group);
|
||||||
|
|
||||||
$population = count($affiliations);
|
$population = count($members);
|
||||||
|
|
||||||
if ($profile) {
|
if ($profile) {
|
||||||
$blurb = $profile->getBlurb();
|
$blurb = $profile->getBlurb();
|
||||||
|
|
|
@ -22,8 +22,8 @@ final class PhabricatorProjectEditor {
|
||||||
private $user;
|
private $user;
|
||||||
private $projectName;
|
private $projectName;
|
||||||
|
|
||||||
private $addAffiliations;
|
private $addEdges = array();
|
||||||
private $remAffiliations;
|
private $remEdges = array();
|
||||||
|
|
||||||
public function __construct(PhabricatorProject $project) {
|
public function __construct(PhabricatorProject $project) {
|
||||||
$this->project = $project;
|
$this->project = $project;
|
||||||
|
@ -67,22 +67,26 @@ final class PhabricatorProjectEditor {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$project->save();
|
$project->openTransaction();
|
||||||
|
$project->save();
|
||||||
|
|
||||||
foreach ($transactions as $xaction) {
|
$edge_type = PhabricatorEdgeConfig::TYPE_PROJ_MEMBER;
|
||||||
$xaction->setAuthorPHID($user->getPHID());
|
$editor = new PhabricatorEdgeEditor();
|
||||||
$xaction->setProjectID($project->getID());
|
$editor->setUser($this->user);
|
||||||
$xaction->save();
|
foreach ($this->remEdges as $phid) {
|
||||||
}
|
$editor->removeEdge($project->getPHID(), $edge_type, $phid);
|
||||||
|
}
|
||||||
|
foreach ($this->addEdges as $phid) {
|
||||||
|
$editor->addEdge($project->getPHID(), $edge_type, $phid);
|
||||||
|
}
|
||||||
|
$editor->save();
|
||||||
|
|
||||||
foreach ($this->remAffiliations as $affil) {
|
foreach ($transactions as $xaction) {
|
||||||
$affil->delete();
|
$xaction->setAuthorPHID($user->getPHID());
|
||||||
}
|
$xaction->setProjectID($project->getID());
|
||||||
|
$xaction->save();
|
||||||
foreach ($this->addAffiliations as $affil) {
|
}
|
||||||
$affil->setProjectPHID($project->getPHID());
|
$project->saveTransaction();
|
||||||
$affil->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($transactions as $xaction) {
|
foreach ($transactions as $xaction) {
|
||||||
$this->publishTransactionStory($project, $xaction);
|
$this->publishTransactionStory($project, $xaction);
|
||||||
|
@ -142,11 +146,10 @@ final class PhabricatorProjectEditor {
|
||||||
$xaction->setOldValue($project->getStatus());
|
$xaction->setOldValue($project->getStatus());
|
||||||
break;
|
break;
|
||||||
case PhabricatorProjectTransactionType::TYPE_MEMBERS:
|
case PhabricatorProjectTransactionType::TYPE_MEMBERS:
|
||||||
$affils = $project->loadAffiliations();
|
$member_phids = $project->loadMemberPHIDs();
|
||||||
$project->attachAffiliations($affils);
|
$project->attachMemberPHIDs($member_phids);
|
||||||
|
|
||||||
$old_value = mpull($affils, 'getUserPHID');
|
$old_value = array_values($member_phids);
|
||||||
$old_value = array_values($old_value);
|
|
||||||
$xaction->setOldValue($old_value);
|
$xaction->setOldValue($old_value);
|
||||||
|
|
||||||
$new_value = $xaction->getNewValue();
|
$new_value = $xaction->getNewValue();
|
||||||
|
@ -178,27 +181,8 @@ final class PhabricatorProjectEditor {
|
||||||
case PhabricatorProjectTransactionType::TYPE_MEMBERS:
|
case PhabricatorProjectTransactionType::TYPE_MEMBERS:
|
||||||
$old = array_fill_keys($xaction->getOldValue(), true);
|
$old = array_fill_keys($xaction->getOldValue(), true);
|
||||||
$new = array_fill_keys($xaction->getNewValue(), true);
|
$new = array_fill_keys($xaction->getNewValue(), true);
|
||||||
|
$this->addEdges = array_keys(array_diff_key($new, $old));
|
||||||
$add = array();
|
$this->remEdges = array_keys(array_diff_key($old, $new));
|
||||||
$rem = array();
|
|
||||||
|
|
||||||
foreach ($project->getAffiliations() as $affil) {
|
|
||||||
if (empty($new[$affil->getUserPHID()])) {
|
|
||||||
$rem[] = $affil;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($new as $phid => $ignored) {
|
|
||||||
if (empty($old[$phid])) {
|
|
||||||
$affil = new PhabricatorProjectAffiliation();
|
|
||||||
$affil->setRole('');
|
|
||||||
$affil->setUserPHID($phid);
|
|
||||||
$add[] = $affil;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->addAffiliations = $add;
|
|
||||||
$this->remAffiliations = $rem;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception("Unknown transaction type '{$type}'!");
|
throw new Exception("Unknown transaction type '{$type}'!");
|
||||||
|
|
|
@ -60,27 +60,26 @@ final class PhabricatorProjectQuery extends PhabricatorOffsetPagedQuery {
|
||||||
$table = new PhabricatorProject();
|
$table = new PhabricatorProject();
|
||||||
$conn_r = $table->establishConnection('r');
|
$conn_r = $table->establishConnection('r');
|
||||||
|
|
||||||
$where = $this->buildWhereClause($conn_r);
|
|
||||||
$joins = $this->buildJoinsClause($conn_r);
|
|
||||||
$order = 'ORDER BY name';
|
|
||||||
|
|
||||||
$data = queryfx_all(
|
$data = queryfx_all(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'SELECT p.* FROM %T p %Q %Q %Q %Q',
|
'SELECT p.* FROM %T p %Q %Q %Q %Q %Q',
|
||||||
$table->getTableName(),
|
$table->getTableName(),
|
||||||
$joins,
|
$this->buildJoinClause($conn_r),
|
||||||
$where,
|
$this->buildWhereClause($conn_r),
|
||||||
$order,
|
$this->buildGroupClause($conn_r),
|
||||||
|
'ORDER BY name',
|
||||||
$this->buildLimitClause($conn_r));
|
$this->buildLimitClause($conn_r));
|
||||||
|
|
||||||
$projects = $table->loadAllFromArray($data);
|
$projects = $table->loadAllFromArray($data);
|
||||||
|
|
||||||
if ($projects && $this->needMembers) {
|
if ($projects && $this->needMembers) {
|
||||||
$members = PhabricatorProjectAffiliation::loadAllForProjectPHIDs(
|
$members = id(new PhabricatorEdgeQuery())
|
||||||
mpull($projects, 'getPHID'));
|
->withSourcePHIDs(mpull($projects, 'getPHID'))
|
||||||
|
->withTypes(array(PhabricatorEdgeConfig::TYPE_PROJ_MEMBER))
|
||||||
|
->execute();
|
||||||
foreach ($projects as $project) {
|
foreach ($projects as $project) {
|
||||||
$project->attachAffiliations(
|
$phid = $project->getPHID();
|
||||||
array_values(idx($members, $project->getPHID(), array())));
|
$project->attachMemberPHIDs(array_keys($members[$phid]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,37 +92,25 @@ final class PhabricatorProjectQuery extends PhabricatorOffsetPagedQuery {
|
||||||
if ($this->status != self::STATUS_ANY) {
|
if ($this->status != self::STATUS_ANY) {
|
||||||
switch ($this->status) {
|
switch ($this->status) {
|
||||||
case self::STATUS_OPEN:
|
case self::STATUS_OPEN:
|
||||||
$where[] = qsprintf(
|
case self::STATUS_ACTIVE:
|
||||||
$conn_r,
|
$filter = array(
|
||||||
'status IN (%Ld)',
|
PhabricatorProjectStatus::STATUS_ACTIVE,
|
||||||
array(
|
);
|
||||||
PhabricatorProjectStatus::STATUS_ACTIVE,
|
|
||||||
));
|
|
||||||
break;
|
break;
|
||||||
case self::STATUS_CLOSED:
|
case self::STATUS_CLOSED:
|
||||||
$where[] = qsprintf(
|
|
||||||
$conn_r,
|
|
||||||
'status IN (%Ld)',
|
|
||||||
array(
|
|
||||||
PhabricatorProjectStatus::STATUS_ARCHIVED,
|
|
||||||
));
|
|
||||||
break;
|
|
||||||
case self::STATUS_ACTIVE:
|
|
||||||
$where[] = qsprintf(
|
|
||||||
$conn_r,
|
|
||||||
'status = %d',
|
|
||||||
PhabricatorProjectStatus::STATUS_ACTIVE);
|
|
||||||
break;
|
|
||||||
case self::STATUS_ARCHIVED:
|
case self::STATUS_ARCHIVED:
|
||||||
$where[] = qsprintf(
|
$filter = array(
|
||||||
$conn_r,
|
PhabricatorProjectStatus::STATUS_ARCHIVED,
|
||||||
'status = %d',
|
);
|
||||||
PhabricatorProjectStatus::STATUS_ARCHIVED);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
"Unknown project status '{$this->status}'!");
|
"Unknown project status '{$this->status}'!");
|
||||||
}
|
}
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'status IN (%Ld)',
|
||||||
|
$filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->ids) {
|
if ($this->ids) {
|
||||||
|
@ -140,20 +127,33 @@ final class PhabricatorProjectQuery extends PhabricatorOffsetPagedQuery {
|
||||||
$this->phids);
|
$this->phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->memberPHIDs) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'e.type = %s AND e.dst IN (%Ls)',
|
||||||
|
PhabricatorEdgeConfig::TYPE_PROJ_MEMBER,
|
||||||
|
$this->memberPHIDs);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->formatWhereClause($where);
|
return $this->formatWhereClause($where);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildJoinsClause($conn_r) {
|
private function buildGroupClause($conn_r) {
|
||||||
$affil_table = new PhabricatorProjectAffiliation();
|
if ($this->memberPHIDs) {
|
||||||
|
return 'GROUP BY p.id';
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildJoinClause($conn_r) {
|
||||||
$joins = array();
|
$joins = array();
|
||||||
|
|
||||||
if ($this->memberPHIDs) {
|
if ($this->memberPHIDs) {
|
||||||
$joins[] = qsprintf(
|
$joins[] = qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'JOIN %T member ON member.projectPHID = p.phid
|
'JOIN %T e ON e.src = p.phid',
|
||||||
AND member.userPHID in (%Ls)',
|
PhabricatorEdgeConfig::TABLE_NAME_EDGE);
|
||||||
$affil_table->getTableName(),
|
|
||||||
$this->memberPHIDs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return implode(' ', $joins);
|
return implode(' ', $joins);
|
||||||
|
|
|
@ -25,7 +25,8 @@ final class PhabricatorProject extends PhabricatorProjectDAO {
|
||||||
protected $subprojectPHIDs = array();
|
protected $subprojectPHIDs = array();
|
||||||
protected $phrictionSlug;
|
protected $phrictionSlug;
|
||||||
|
|
||||||
private $affiliations;
|
private $subprojectsNeedUpdate;
|
||||||
|
private $memberPHIDs;
|
||||||
|
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
|
@ -48,31 +49,25 @@ final class PhabricatorProject extends PhabricatorProjectDAO {
|
||||||
return $profile;
|
return $profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMemberPHIDs() {
|
public function attachMemberPHIDs(array $phids) {
|
||||||
return mpull($this->getAffiliations(), 'getUserPHID');
|
$this->memberPHIDs = $phids;
|
||||||
}
|
|
||||||
|
|
||||||
public function loadMemberPHIDs() {
|
|
||||||
return mpull($this->loadAffiliations(), 'getUserPHID');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAffiliations() {
|
|
||||||
if ($this->affiliations === null) {
|
|
||||||
throw new Exception('Attach affiliations first!');
|
|
||||||
}
|
|
||||||
return $this->affiliations;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function attachAffiliations(array $affiliations) {
|
|
||||||
assert_instances_of($affiliations, 'PhabricatorProjectAffiliation');
|
|
||||||
$this->affiliations = $affiliations;
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadAffiliations() {
|
public function getMemberPHIDs() {
|
||||||
$affils = PhabricatorProjectAffiliation::loadAllForProjectPHIDs(
|
if ($this->memberPHIDs === null) {
|
||||||
array($this->getPHID()));
|
throw new Exception("Call attachMemberPHIDs() first!");
|
||||||
return $affils[$this->getPHID()];
|
}
|
||||||
|
return $this->memberPHIDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadMemberPHIDs() {
|
||||||
|
if (!$this->getPHID()) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
return PhabricatorEdgeQuery::loadDestinationPHIDs(
|
||||||
|
$this->getPHID(),
|
||||||
|
PhabricatorEdgeConfig::TYPE_PROJ_MEMBER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setPhrictionSlug($slug) {
|
public function setPhrictionSlug($slug) {
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2012 Facebook, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
final class PhabricatorProjectAffiliation extends PhabricatorProjectDAO {
|
|
||||||
|
|
||||||
protected $projectPHID;
|
|
||||||
protected $userPHID;
|
|
||||||
protected $role;
|
|
||||||
protected $isOwner = 0;
|
|
||||||
|
|
||||||
public static function loadAllForProjectPHIDs($phids) {
|
|
||||||
if (!$phids) {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
$default = array_fill_keys($phids, array());
|
|
||||||
|
|
||||||
$affiliations = id(new PhabricatorProjectAffiliation())->loadAllWhere(
|
|
||||||
'projectPHID IN (%Ls) ORDER BY dateCreated',
|
|
||||||
$phids);
|
|
||||||
|
|
||||||
return mgroup($affiliations, 'getProjectPHID') + $default;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -38,6 +38,9 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
|
||||||
const TYPE_TASK_HAS_RELATED_DREV = 11;
|
const TYPE_TASK_HAS_RELATED_DREV = 11;
|
||||||
const TYPE_DREV_HAS_RELATED_TASK = 12;
|
const TYPE_DREV_HAS_RELATED_TASK = 12;
|
||||||
|
|
||||||
|
const TYPE_PROJ_MEMBER = 13;
|
||||||
|
const TYPE_MEMBER_OF_PROJ = 14;
|
||||||
|
|
||||||
const TYPE_TEST_NO_CYCLE = 9000;
|
const TYPE_TEST_NO_CYCLE = 9000;
|
||||||
|
|
||||||
public static function getInverse($edge_type) {
|
public static function getInverse($edge_type) {
|
||||||
|
@ -58,6 +61,9 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
|
||||||
|
|
||||||
self::TYPE_TASK_HAS_RELATED_DREV => self::TYPE_DREV_HAS_RELATED_TASK,
|
self::TYPE_TASK_HAS_RELATED_DREV => self::TYPE_DREV_HAS_RELATED_TASK,
|
||||||
self::TYPE_DREV_HAS_RELATED_TASK => self::TYPE_TASK_HAS_RELATED_DREV,
|
self::TYPE_DREV_HAS_RELATED_TASK => self::TYPE_TASK_HAS_RELATED_DREV,
|
||||||
|
|
||||||
|
self::TYPE_PROJ_MEMBER => self::TYPE_MEMBER_OF_PROJ,
|
||||||
|
self::TYPE_MEMBER_OF_PROJ => self::TYPE_PROJ_MEMBER,
|
||||||
);
|
);
|
||||||
|
|
||||||
return idx($map, $edge_type);
|
return idx($map, $edge_type);
|
||||||
|
|
|
@ -940,6 +940,10 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
||||||
'type' => 'sql',
|
'type' => 'sql',
|
||||||
'name' => $this->getPatchPath('symbolcontexts.sql'),
|
'name' => $this->getPatchPath('symbolcontexts.sql'),
|
||||||
),
|
),
|
||||||
|
'migrate-project-edges.php' => array(
|
||||||
|
'type' => 'php',
|
||||||
|
'name' => $this->getPatchPath('migrate-project-edges.php'),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue