Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14135309
D17952.id43179.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
17 KB
Referenced Files
None
Subscribers
None
D17952.id43179.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -3666,6 +3666,7 @@
'PhabricatorProjectSilenceController' => 'applications/project/controller/PhabricatorProjectSilenceController.php',
'PhabricatorProjectSilencedEdgeType' => 'applications/project/edge/PhabricatorProjectSilencedEdgeType.php',
'PhabricatorProjectSlug' => 'applications/project/storage/PhabricatorProjectSlug.php',
+ 'PhabricatorProjectSlugsTransaction' => 'applications/project/xaction/PhabricatorProjectSlugsTransaction.php',
'PhabricatorProjectStandardCustomField' => 'applications/project/customfield/PhabricatorProjectStandardCustomField.php',
'PhabricatorProjectStatus' => 'applications/project/constants/PhabricatorProjectStatus.php',
'PhabricatorProjectSubprojectWarningController' => 'applications/project/controller/PhabricatorProjectSubprojectWarningController.php',
@@ -9077,6 +9078,7 @@
'PhabricatorProjectSilenceController' => 'PhabricatorProjectController',
'PhabricatorProjectSilencedEdgeType' => 'PhabricatorEdgeType',
'PhabricatorProjectSlug' => 'PhabricatorProjectDAO',
+ 'PhabricatorProjectSlugsTransaction' => 'PhabricatorProjectTransactionType',
'PhabricatorProjectStandardCustomField' => array(
'PhabricatorProjectCustomField',
'PhabricatorStandardCustomFieldInterface',
diff --git a/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php b/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php
--- a/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php
+++ b/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php
@@ -362,7 +362,7 @@
$xactions = array();
$xactions[] = id(new PhabricatorProjectTransaction())
- ->setTransactionType(PhabricatorProjectTransaction::TYPE_SLUGS)
+ ->setTransactionType(PhabricatorProjectSlugsTransaction::TRANSACTIONTYPE)
->setNewValue(array($name));
$this->applyTransactions($project, $user, $xactions);
@@ -386,7 +386,7 @@
->setNewValue($name2);
$xactions[] = id(new PhabricatorProjectTransaction())
- ->setTransactionType(PhabricatorProjectTransaction::TYPE_SLUGS)
+ ->setTransactionType(PhabricatorProjectSlugsTransaction::TRANSACTIONTYPE)
->setNewValue(array($name2));
$this->applyTransactions($project, $user, $xactions);
@@ -416,7 +416,7 @@
$xactions = array();
$xactions[] = id(new PhabricatorProjectTransaction())
- ->setTransactionType(PhabricatorProjectTransaction::TYPE_SLUGS)
+ ->setTransactionType(PhabricatorProjectSlugsTransaction::TRANSACTIONTYPE)
->setNewValue(array($input, $input));
$this->applyTransactions($project, $user, $xactions);
@@ -448,7 +448,7 @@
$xactions = array();
$xactions[] = id(new PhabricatorProjectTransaction())
- ->setTransactionType(PhabricatorProjectTransaction::TYPE_SLUGS)
+ ->setTransactionType(PhabricatorProjectSlugsTransaction::TRANSACTIONTYPE)
->setNewValue(array($input));
$this->applyTransactions($project, $user, $xactions);
@@ -474,7 +474,7 @@
$xactions = array();
$xactions[] = id(new PhabricatorProjectTransaction())
- ->setTransactionType(PhabricatorProjectTransaction::TYPE_SLUGS)
+ ->setTransactionType(PhabricatorProjectSlugsTransaction::TRANSACTIONTYPE)
->setNewValue(array($input));
$caught = null;
@@ -605,7 +605,7 @@
->setNewValue($name);
$xactions[] = id(new PhabricatorProjectTransaction())
- ->setTransactionType(PhabricatorProjectTransaction::TYPE_SLUGS)
+ ->setTransactionType(PhabricatorProjectSlugsTransaction::TRANSACTIONTYPE)
->setNewValue(array($slug));
$this->applyTransactions($project, $user, $xactions);
diff --git a/src/applications/project/conduit/ProjectCreateConduitAPIMethod.php b/src/applications/project/conduit/ProjectCreateConduitAPIMethod.php
--- a/src/applications/project/conduit/ProjectCreateConduitAPIMethod.php
+++ b/src/applications/project/conduit/ProjectCreateConduitAPIMethod.php
@@ -64,7 +64,8 @@
if ($request->getValue('tags')) {
$xactions[] = id(new PhabricatorProjectTransaction())
- ->setTransactionType(PhabricatorProjectTransaction::TYPE_SLUGS)
+ ->setTransactionType(
+ PhabricatorProjectSlugsTransaction::TRANSACTIONTYPE)
->setNewValue($request->getValue('tags'));
}
diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
--- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
+++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
@@ -30,7 +30,6 @@
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
$types[] = PhabricatorTransactions::TYPE_JOIN_POLICY;
- $types[] = PhabricatorProjectTransaction::TYPE_SLUGS;
$types[] = PhabricatorProjectTransaction::TYPE_STATUS;
$types[] = PhabricatorProjectTransaction::TYPE_IMAGE;
$types[] = PhabricatorProjectTransaction::TYPE_ICON;
@@ -51,11 +50,6 @@
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
- case PhabricatorProjectTransaction::TYPE_SLUGS:
- $slugs = $object->getSlugs();
- $slugs = mpull($slugs, 'getSlug', 'getSlug');
- unset($slugs[$object->getPrimarySlug()]);
- return array_keys($slugs);
case PhabricatorProjectTransaction::TYPE_STATUS:
return $object->getStatus();
case PhabricatorProjectTransaction::TYPE_IMAGE:
@@ -105,8 +99,6 @@
return null;
}
return $value;
- case PhabricatorProjectTransaction::TYPE_SLUGS:
- return $this->normalizeSlugs($xaction->getNewValue());
}
return parent::getCustomTransactionNewValue($object, $xaction);
@@ -117,8 +109,6 @@
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
- case PhabricatorProjectTransaction::TYPE_SLUGS:
- return;
case PhabricatorProjectTransaction::TYPE_STATUS:
$object->setStatus($xaction->getNewValue());
return;
@@ -167,18 +157,6 @@
$new = $xaction->getNewValue();
switch ($xaction->getTransactionType()) {
- case PhabricatorProjectTransaction::TYPE_SLUGS:
- $old = $xaction->getOldValue();
- $new = $xaction->getNewValue();
- $add = array_diff($new, $old);
- $rem = array_diff($old, $new);
-
- foreach ($add as $slug) {
- $this->addSlug($object, $slug, true);
- }
-
- $this->removeSlugs($object, $rem);
- return;
case PhabricatorProjectTransaction::TYPE_STATUS:
case PhabricatorProjectTransaction::TYPE_IMAGE:
case PhabricatorProjectTransaction::TYPE_ICON:
@@ -278,65 +256,6 @@
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
- case PhabricatorProjectTransaction::TYPE_SLUGS:
- if (!$xactions) {
- break;
- }
-
- $slug_xaction = last($xactions);
-
- $new = $slug_xaction->getNewValue();
-
- $invalid = array();
- foreach ($new as $slug) {
- if (!PhabricatorSlug::isValidProjectSlug($slug)) {
- $invalid[] = $slug;
- }
- }
-
- if ($invalid) {
- $errors[] = new PhabricatorApplicationTransactionValidationError(
- $type,
- pht('Invalid'),
- pht(
- 'Hashtags must contain at least one letter or number. %s '.
- 'project hashtag(s) are invalid: %s.',
- phutil_count($invalid),
- implode(', ', $invalid)),
- $slug_xaction);
- break;
- }
-
- $new = $this->normalizeSlugs($new);
-
- if ($new) {
- $slugs_used_already = id(new PhabricatorProjectSlug())
- ->loadAllWhere('slug IN (%Ls)', $new);
- } else {
- // The project doesn't have any extra slugs.
- $slugs_used_already = array();
- }
-
- $slugs_used_already = mgroup($slugs_used_already, 'getProjectPHID');
- foreach ($slugs_used_already as $project_phid => $used_slugs) {
- if ($project_phid == $object->getPHID()) {
- continue;
- }
-
- $used_slug_strs = mpull($used_slugs, 'getSlug');
-
- $error = new PhabricatorApplicationTransactionValidationError(
- $type,
- pht('Invalid'),
- pht(
- '%s project hashtag(s) are already used by other projects: %s.',
- phutil_count($used_slug_strs),
- implode(', ', $used_slug_strs)),
- $slug_xaction);
- $errors[] = $error;
- }
-
- break;
case PhabricatorProjectTransaction::TYPE_PARENT:
case PhabricatorProjectTransaction::TYPE_MILESTONE:
if (!$xactions) {
@@ -674,7 +593,7 @@
->save();
}
- private function removeSlugs(PhabricatorProject $project, array $slugs) {
+ public function removeSlugs(PhabricatorProject $project, array $slugs) {
if (!$slugs) {
return;
}
@@ -696,7 +615,7 @@
}
}
- private function normalizeSlugs(array $slugs) {
+ public function normalizeSlugs(array $slugs) {
foreach ($slugs as $key => $slug) {
$slugs[$key] = PhabricatorSlug::normalizeProjectSlug($slug);
}
diff --git a/src/applications/project/engine/PhabricatorProjectEditEngine.php b/src/applications/project/engine/PhabricatorProjectEditEngine.php
--- a/src/applications/project/engine/PhabricatorProjectEditEngine.php
+++ b/src/applications/project/engine/PhabricatorProjectEditEngine.php
@@ -262,7 +262,8 @@
id(new PhabricatorStringListEditField())
->setKey('slugs')
->setLabel(pht('Additional Hashtags'))
- ->setTransactionType(PhabricatorProjectTransaction::TYPE_SLUGS)
+ ->setTransactionType(
+ PhabricatorProjectSlugsTransaction::TRANSACTIONTYPE)
->setDescription(pht('Additional project slugs.'))
->setConduitDescription(pht('Change project slugs.'))
->setConduitTypeDescription(pht('New list of slugs.'))
diff --git a/src/applications/project/storage/PhabricatorProjectTransaction.php b/src/applications/project/storage/PhabricatorProjectTransaction.php
--- a/src/applications/project/storage/PhabricatorProjectTransaction.php
+++ b/src/applications/project/storage/PhabricatorProjectTransaction.php
@@ -3,7 +3,6 @@
final class PhabricatorProjectTransaction
extends PhabricatorModularTransaction {
- const TYPE_SLUGS = 'project:slugs';
const TYPE_STATUS = 'project:status';
const TYPE_IMAGE = 'project:image';
const TYPE_ICON = 'project:icon';
@@ -134,8 +133,6 @@
return 'fa-photo';
case self::TYPE_MEMBERS:
return 'fa-user';
- case self::TYPE_SLUGS:
- return 'fa-tag';
}
return parent::getIcon();
}
@@ -212,33 +209,6 @@
}
break;
- case self::TYPE_SLUGS:
- $add = array_diff($new, $old);
- $rem = array_diff($old, $new);
-
- if ($add && $rem) {
- return pht(
- '%s changed project hashtag(s), added %d: %s; removed %d: %s.',
- $author_handle,
- count($add),
- $this->renderSlugList($add),
- count($rem),
- $this->renderSlugList($rem));
- } else if ($add) {
- return pht(
- '%s added %d project hashtag(s): %s.',
- $author_handle,
- count($add),
- $this->renderSlugList($add));
- } else if ($rem) {
- return pht(
- '%s removed %d project hashtag(s): %s.',
- $author_handle,
- count($rem),
- $this->renderSlugList($rem));
- }
- break;
-
case self::TYPE_MEMBERS:
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
@@ -380,36 +350,6 @@
$author_handle,
$object_handle);
}
-
- case self::TYPE_SLUGS:
- $add = array_diff($new, $old);
- $rem = array_diff($old, $new);
-
- if ($add && $rem) {
- return pht(
- '%s changed %s hashtag(s), added %d: %s; removed %d: %s.',
- $author_handle,
- $object_handle,
- count($add),
- $this->renderSlugList($add),
- count($rem),
- $this->renderSlugList($rem));
- } else if ($add) {
- return pht(
- '%s added %d %s hashtag(s): %s.',
- $author_handle,
- count($add),
- $object_handle,
- $this->renderSlugList($add));
- } else if ($rem) {
- return pht(
- '%s removed %d %s hashtag(s): %s.',
- $author_handle,
- count($rem),
- $object_handle,
- $this->renderSlugList($rem));
- }
-
}
return parent::getTitleForFeed();
@@ -418,8 +358,8 @@
public function getMailTags() {
$tags = array();
switch ($this->getTransactionType()) {
- case self::TYPE_NAME:
- case self::TYPE_SLUGS:
+ case PhabricatorProjectNameTransaction::TRANSACTIONTYPE:
+ case PhabricatorProjectSlugsTransaction::TRANSACTIONTYPE:
case self::TYPE_IMAGE:
case self::TYPE_ICON:
case self::TYPE_COLOR:
@@ -447,8 +387,4 @@
return $tags;
}
- private function renderSlugList($slugs) {
- return implode(', ', $slugs);
- }
-
}
diff --git a/src/applications/project/xaction/PhabricatorProjectSlugsTransaction.php b/src/applications/project/xaction/PhabricatorProjectSlugsTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/xaction/PhabricatorProjectSlugsTransaction.php
@@ -0,0 +1,165 @@
+<?php
+
+final class PhabricatorProjectSlugsTransaction
+ extends PhabricatorProjectTransactionType {
+
+ const TRANSACTIONTYPE = 'project:slugs';
+
+ public function generateOldValue($object) {
+ $slugs = $object->getSlugs();
+ $slugs = mpull($slugs, 'getSlug', 'getSlug');
+ unset($slugs[$object->getPrimarySlug()]);
+ return array_keys($slugs);
+ }
+
+ public function generateNewValue($object, $value) {
+ return $this->getEditor()->normalizeSlugs($value);
+ }
+
+ public function applyInternalEffects($object, $value) {
+ return;
+ }
+
+ public function applyExternalEffects($object, $value) {
+ $old = $this->getOldValue();
+ $new = $value;
+ $add = array_diff($new, $old);
+ $rem = array_diff($old, $new);
+
+ foreach ($add as $slug) {
+ $this->getEditor()->addSlug($object, $slug, true);
+ }
+
+ $this->getEditor()->removeSlugs($object, $rem);
+ }
+
+ public function getTitle() {
+ $old = $this->getOldValue();
+ $new = $this->getNewValue();
+
+ $add = array_diff($new, $old);
+ $rem = array_diff($old, $new);
+
+ if ($add && $rem) {
+ return pht(
+ '%s changed project hashtag(s), added %d: %s; removed %d: %s.',
+ $this->renderAuthor(),
+ count($add),
+ $this->renderSlugList($add),
+ count($rem),
+ $this->renderSlugList($rem));
+ } else if ($add) {
+ return pht(
+ '%s added %d project hashtag(s): %s.',
+ $this->renderAuthor(),
+ count($add),
+ $this->renderSlugList($add));
+ } else if ($rem) {
+ return pht(
+ '%s removed %d project hashtag(s): %s.',
+ $this->renderAuthor(),
+ count($rem),
+ $this->renderSlugList($rem));
+ }
+ break;
+ }
+
+ public function getTitleForFeed() {
+ $old = $this->getOldValue();
+ $new = $this->getNewValue();
+
+ $add = array_diff($new, $old);
+ $rem = array_diff($old, $new);
+
+ if ($add && $rem) {
+ return pht(
+ '%s changed %s hashtag(s), added %d: %s; removed %d: %s.',
+ $this->renderAuthor(),
+ $this->renderObject(),
+ count($add),
+ $this->renderSlugList($add),
+ count($rem),
+ $this->renderSlugList($rem));
+ } else if ($add) {
+ return pht(
+ '%s added %d %s hashtag(s): %s.',
+ $this->renderAuthor(),
+ count($add),
+ $this->renderObject(),
+ $this->renderSlugList($add));
+ } else if ($rem) {
+ return pht(
+ '%s removed %d %s hashtag(s): %s.',
+ $this->renderAuthor(),
+ count($rem),
+ $this->renderObject(),
+ $this->renderSlugList($rem));
+ }
+ }
+
+ public function getIcon() {
+ return 'fa-tag';
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ if (!$xactions) {
+ return $errors;
+ }
+
+ $slug_xaction = last($xactions);
+
+ $new = $slug_xaction->getNewValue();
+
+ $invalid = array();
+ foreach ($new as $slug) {
+ if (!PhabricatorSlug::isValidProjectSlug($slug)) {
+ $invalid[] = $slug;
+ }
+ }
+
+ if ($invalid) {
+ $errors[] = $this->newInvalidError(
+ pht(
+ 'Hashtags must contain at least one letter or number. %s '.
+ 'project hashtag(s) are invalid: %s.',
+ phutil_count($invalid),
+ implode(', ', $invalid)));
+
+ return $errors;
+ }
+
+ $new = $this->getEditor()->normalizeSlugs($new);
+
+ if ($new) {
+ $slugs_used_already = id(new PhabricatorProjectSlug())
+ ->loadAllWhere('slug IN (%Ls)', $new);
+ } else {
+ // The project doesn't have any extra slugs.
+ $slugs_used_already = array();
+ }
+
+ $slugs_used_already = mgroup($slugs_used_already, 'getProjectPHID');
+ foreach ($slugs_used_already as $project_phid => $used_slugs) {
+ if ($project_phid == $object->getPHID()) {
+ continue;
+ }
+
+ $used_slug_strs = mpull($used_slugs, 'getSlug');
+
+ $errors[] = $this->newInvalidError(
+ pht(
+ '%s project hashtag(s) are already used by other projects: %s.',
+ phutil_count($used_slug_strs),
+ implode(', ', $used_slug_strs)));
+ }
+
+ return $errors;
+ }
+
+ private function renderSlugList($slugs) {
+ return implode(', ', $slugs);
+ }
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Dec 3, 2:08 PM (21 h, 26 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6819605
Default Alt Text
D17952.id43179.diff (17 KB)
Attached To
Mode
D17952: Migrate Project slugs to modular transactions
Attached
Detach File
Event Timeline
Log In to Comment