1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-18 03:20:59 +01:00

Prepare Projects schema for subprojects

Summary:
Ref T10010. This does some cleanups on the schema:

  - `viewPolicy`, `editPolicy` and `joinPolicy` were nullable, but should never be `null`. Set them to defaults if they're null, then make the column non-nullable.
  - Rename `phrictionSlug` to `primarySlug` and stop adding and removing trailing slashes from it.
  - Add new columns to support milestones and non-milestone subprojects.
  - Drop very old subprojectPHIDs column. This hasn't done anything in the UI for years and years, and isn't particularly realistic to migrate forward.

The new columns aren't reachable from the UI.

Test Plan:
  - Applied patches.
  - Grepped for `phrictionSlug`.
  - Grepped for `subprojectPHIDs`.
  - Created tasks.
  - Edited tasks.
  - Verified existing tasks still had primary slugs.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10010

Differential Revision: https://secure.phabricator.com/D14825
This commit is contained in:
epriestley 2015-12-19 08:08:26 -08:00
parent 3f8e5c9620
commit aeae0e7028
13 changed files with 105 additions and 40 deletions

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_project.project
ADD COLUMN primarySlug VARCHAR(128) COLLATE {$COLLATE_TEXT};

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_project.project
ADD UNIQUE KEY `key_primaryslug` (primarySlug);

View file

@ -0,0 +1,2 @@
UPDATE {$NAMESPACE}_project.project
SET primarySlug = TRIM(TRAILING "/" FROM phrictionSlug);

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_project.project
DROP KEY `phrictionSlug`;

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_project.project
DROP COLUMN phrictionSlug;

View file

@ -0,0 +1,28 @@
<?php
$app = PhabricatorApplication::getByClass('PhabricatorProjectApplication');
$view_policy = $app->getPolicy(ProjectDefaultViewCapability::CAPABILITY);
$edit_policy = $app->getPolicy(ProjectDefaultEditCapability::CAPABILITY);
$join_policy = $app->getPolicy(ProjectDefaultJoinCapability::CAPABILITY);
$table = new PhabricatorProject();
$conn_w = $table->establishConnection('w');
queryfx(
$conn_w,
'UPDATE %T SET viewPolicy = %s WHERE viewPolicy IS NULL',
$table->getTableName(),
$view_policy);
queryfx(
$conn_w,
'UPDATE %T SET editPolicy = %s WHERE editPolicy IS NULL',
$table->getTableName(),
$edit_policy);
queryfx(
$conn_w,
'UPDATE %T SET joinPolicy = %s WHERE joinPolicy IS NULL',
$table->getTableName(),
$join_policy);

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_project.project
CHANGE viewPolicy viewPolicy VARBINARY(64) NOT NULL;

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_project.project
CHANGE editPolicy editPolicy VARBINARY(64) NOT NULL;

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_project.project
CHANGE joinPolicy joinPolicy VARBINARY(64) NOT NULL;

View file

@ -0,0 +1,17 @@
ALTER TABLE {$NAMESPACE}_project.project
ADD parentProjectPHID VARBINARY(64);
ALTER TABLE {$NAMESPACE}_project.project
ADD hasWorkboard BOOL NOT NULL;
ALTER TABLE {$NAMESPACE}_project.project
ADD hasMilestones BOOL NOT NULL;
ALTER TABLE {$NAMESPACE}_project.project
ADD hasSubprojects BOOL NOT NULL;
ALTER TABLE {$NAMESPACE}_project.project
ADD milestoneNumber INT UNSIGNED;
ALTER TABLE {$NAMESPACE}_project.project
ADD UNIQUE KEY `key_milestone` (parentProjectPHID, milestoneNumber);

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_project.project
DROP subprojectPHIDs;

View file

@ -11,19 +11,11 @@ final class PhabricatorPolicyDataTestCase extends PhabricatorTestCase {
public function testProjectPolicyMembership() {
$author = $this->generateNewTestUser();
$proj_a = id(new PhabricatorProject())
$proj_a = PhabricatorProject::initializeNewProject($author)
->setName('A')
->setAuthorPHID($author->getPHID())
->setIcon(PhabricatorProject::DEFAULT_ICON)
->setColor(PhabricatorProject::DEFAULT_COLOR)
->setIsMembershipLocked(0)
->save();
$proj_b = id(new PhabricatorProject())
$proj_b = PhabricatorProject::initializeNewProject($author)
->setName('B')
->setAuthorPHID($author->getPHID())
->setIcon(PhabricatorProject::DEFAULT_ICON)
->setColor(PhabricatorProject::DEFAULT_COLOR)
->setIsMembershipLocked(0)
->save();
$proj_a->setViewPolicy($proj_b->getPHID())->save();

View file

@ -12,8 +12,7 @@ final class PhabricatorProject extends PhabricatorProjectDAO
protected $name;
protected $status = PhabricatorProjectStatus::STATUS_ACTIVE;
protected $authorPHID;
protected $subprojectPHIDs = array();
protected $phrictionSlug;
protected $primarySlug;
protected $profileImagePHID;
protected $icon;
protected $color;
@ -24,6 +23,12 @@ final class PhabricatorProject extends PhabricatorProjectDAO
protected $joinPolicy;
protected $isMembershipLocked;
protected $parentProjectPHID;
protected $hasWorkboard;
protected $hasMilestones;
protected $hasSubprojects;
protected $milestoneNumber;
private $memberPHIDs = self::ATTACHABLE;
private $watcherPHIDs = self::ATTACHABLE;
private $sparseWatchers = self::ATTACHABLE;
@ -31,6 +36,7 @@ final class PhabricatorProject extends PhabricatorProjectDAO
private $customFields = self::ATTACHABLE;
private $profileImageFile = self::ATTACHABLE;
private $slugs = self::ATTACHABLE;
private $parentProject = self::ATTACHABLE;
const DEFAULT_ICON = 'fa-briefcase';
const DEFAULT_COLOR = 'blue';
@ -59,7 +65,10 @@ final class PhabricatorProject extends PhabricatorProjectDAO
->setJoinPolicy($join_policy)
->setIsMembershipLocked(0)
->attachMemberPHIDs(array())
->attachSlugs(array());
->attachSlugs(array())
->setHasWorkboard(0)
->setHasMilestones(0)
->setHasSubprojects(0);
}
public function getCapabilities() {
@ -132,24 +141,21 @@ final class PhabricatorProject extends PhabricatorProjectDAO
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'subprojectPHIDs' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(
'name' => 'sort128',
'status' => 'text32',
'phrictionSlug' => 'text128?',
'primarySlug' => 'text128?',
'isMembershipLocked' => 'bool',
'profileImagePHID' => 'phid?',
'icon' => 'text32',
'color' => 'text32',
'mailKey' => 'bytes20',
// T6203/NULLABILITY
// These are definitely wrong and should always exist.
'editPolicy' => 'policy?',
'viewPolicy' => 'policy?',
'joinPolicy' => 'policy?',
'joinPolicy' => 'policy',
'parentProjectPHID' => 'phid?',
'hasWorkboard' => 'bool',
'hasMilestones' => 'bool',
'hasSubprojects' => 'bool',
'milestoneNumber' => 'uint32?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null,
@ -163,14 +169,18 @@ final class PhabricatorProject extends PhabricatorProjectDAO
'key_color' => array(
'columns' => array('color'),
),
'phrictionSlug' => array(
'columns' => array('phrictionSlug'),
'unique' => true,
),
'name' => array(
'columns' => array('name'),
'unique' => true,
),
'key_milestone' => array(
'columns' => array('parentProjectPHID', 'milestoneNumber'),
'unique' => true,
),
'key_primaryslug' => array(
'columns' => array('primarySlug'),
'unique' => true,
),
),
) + parent::getConfiguration();
}
@ -189,19 +199,6 @@ final class PhabricatorProject extends PhabricatorProjectDAO
return $this->assertAttached($this->memberPHIDs);
}
public function setPrimarySlug($slug) {
$this->phrictionSlug = $slug.'/';
return $this;
}
// TODO - once we sever project => phriction automagicalness,
// migrate getPhrictionSlug to have no trailing slash and be called
// getPrimarySlug
public function getPrimarySlug() {
$slug = $this->getPhrictionSlug();
return rtrim($slug, '/');
}
public function isArchived() {
return ($this->getStatus() == PhabricatorProjectStatus::STATUS_ARCHIVED);
}
@ -313,6 +310,19 @@ final class PhabricatorProject extends PhabricatorProjectDAO
$this->saveTransaction();
}
public function isMilestone() {
return ($this->getMilestoneNumber() !== null);
}
public function getParentProject() {
return $this->assertAttached($this->parentProject);
}
public function attachParentProject(PhabricatorProject $project) {
$this->parentProject = $project;
return $this;
}
/* -( PhabricatorSubscribableInterface )----------------------------------- */