Page MenuHomePhabricator

D9837.id23625.diff
No OneTemporary

D9837.id23625.diff

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
@@ -1554,6 +1554,7 @@
'PhabricatorEdgeGraph' => 'infrastructure/edges/util/PhabricatorEdgeGraph.php',
'PhabricatorEdgeQuery' => 'infrastructure/edges/query/PhabricatorEdgeQuery.php',
'PhabricatorEdgeTestCase' => 'infrastructure/edges/__tests__/PhabricatorEdgeTestCase.php',
+ 'PhabricatorEdgeType' => 'infrastructure/edges/type/PhabricatorEdgeType.php',
'PhabricatorEditor' => 'infrastructure/PhabricatorEditor.php',
'PhabricatorEmailLoginController' => 'applications/auth/controller/PhabricatorEmailLoginController.php',
'PhabricatorEmailVerificationController' => 'applications/auth/controller/PhabricatorEmailVerificationController.php',
@@ -1704,6 +1705,7 @@
'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/PhabricatorJavelinLinter.php',
'PhabricatorJumpNavHandler' => 'applications/search/engine/PhabricatorJumpNavHandler.php',
'PhabricatorKeyValueDatabaseCache' => 'applications/cache/PhabricatorKeyValueDatabaseCache.php',
+ 'PhabricatorLegacyEdgeType' => 'infrastructure/edges/type/PhabricatorLegacyEdgeType.php',
'PhabricatorLegalpadConfigOptions' => 'applications/legalpad/config/PhabricatorLegalpadConfigOptions.php',
'PhabricatorLegalpadPHIDTypeDocument' => 'applications/legalpad/phid/PhabricatorLegalpadPHIDTypeDocument.php',
'PhabricatorLipsumArtist' => 'applications/lipsum/image/PhabricatorLipsumArtist.php',
@@ -4393,6 +4395,7 @@
'PhabricatorEdgeGraph' => 'AbstractDirectedGraph',
'PhabricatorEdgeQuery' => 'PhabricatorQuery',
'PhabricatorEdgeTestCase' => 'PhabricatorTestCase',
+ 'PhabricatorEdgeType' => 'Phobject',
'PhabricatorEditor' => 'Phobject',
'PhabricatorEmailLoginController' => 'PhabricatorAuthController',
'PhabricatorEmailVerificationController' => 'PhabricatorAuthController',
@@ -4550,6 +4553,7 @@
'PhabricatorIteratedMD5PasswordHasher' => 'PhabricatorPasswordHasher',
'PhabricatorJavelinLinter' => 'ArcanistLinter',
'PhabricatorKeyValueDatabaseCache' => 'PhutilKeyValueCache',
+ 'PhabricatorLegacyEdgeType' => 'PhabricatorEdgeType',
'PhabricatorLegalpadConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorLegalpadPHIDTypeDocument' => 'PhabricatorPHIDType',
'PhabricatorLipsumGenerateWorkflow' => 'PhabricatorLipsumManagementWorkflow',
diff --git a/src/infrastructure/edges/constants/PhabricatorEdgeConfig.php b/src/infrastructure/edges/constants/PhabricatorEdgeConfig.php
--- a/src/infrastructure/edges/constants/PhabricatorEdgeConfig.php
+++ b/src/infrastructure/edges/constants/PhabricatorEdgeConfig.php
@@ -78,6 +78,13 @@
const TYPE_OBJECT_NEEDS_SIGNATURE = 49;
const TYPE_SIGNATURE_NEEDED_BY_OBJECT = 50;
+/* !!!! STOP !!!! STOP !!!! STOP !!!! STOP !!!! STOP !!!! STOP !!!! STOP !!!! */
+
+ // HEY! DO NOT ADD NEW CONSTANTS HERE!
+ // Instead, subclass PhabricatorEdgeType.
+
+/* !!!! STOP !!!! STOP !!!! STOP !!!! STOP !!!! STOP !!!! STOP !!!! STOP !!!! */
+
const TYPE_TEST_NO_CYCLE = 9000;
const TYPE_PHOB_HAS_ASANATASK = 80001;
@@ -89,6 +96,47 @@
const TYPE_PHOB_HAS_JIRAISSUE = 80004;
const TYPE_JIRAISSUE_HAS_PHOB = 80005;
+
+ /**
+ * Build @{class:PhabricatorLegacyEdgeType} objects for edge which have not
+ * yet been modernized. This allows code to act as though we've completed
+ * the edge type migration before we actually do all the work, by building
+ * these fake type objects.
+ *
+ * @param list<const> List of edge types that objects that objects should
+ * not be built for. This is used to avoid constructing duplicate objects
+ * for edge constants which have migrated and already have a real object.
+ * @return list<PhabricatorLegacyEdgeType> Real-looking edge type objects for
+ * unmigrated edge types.
+ */
+ public static function getLegacyTypes(array $exclude) {
+ $consts = array_merge(
+ range(1, 50),
+ array(9000),
+ range(80000, 80005));
+ $consts = array_diff($consts, $exclude);
+
+ $map = array();
+ foreach ($consts as $const) {
+ $prevent_cycles = self::shouldPreventCycles($const);
+ $inverse_constant = self::getInverse($const);
+
+ $map[$const] = id(new PhabricatorLegacyEdgeType())
+ ->setEdgeConstant($const)
+ ->setShouldPreventCycles($prevent_cycles)
+ ->setInverseEdgeConstant($inverse_constant)
+ ->setStrings(
+ array(
+ self::getAddStringForEdgeType($const),
+ self::getRemoveStringForEdgeType($const),
+ self::getEditStringForEdgeType($const),
+ self::getFeedStringForEdgeType($const),
+ ));
+ }
+
+ return $map;
+ }
+
public static function getInverse($edge_type) {
static $map = array(
self::TYPE_TASK_HAS_COMMIT => self::TYPE_COMMIT_HAS_TASK,
@@ -136,7 +184,7 @@
self::TYPE_DREV_HAS_COMMIT => self::TYPE_COMMIT_HAS_DREV,
self::TYPE_COMMIT_HAS_DREV => self::TYPE_DREV_HAS_COMMIT,
- self::TYPE_OBJECT_HAS_CONTRIBUTOR => self::TYPE_SUBSCRIBED_TO_OBJECT,
+ self::TYPE_OBJECT_HAS_CONTRIBUTOR => self::TYPE_CONTRIBUTED_TO_OBJECT,
self::TYPE_CONTRIBUTED_TO_OBJECT => self::TYPE_OBJECT_HAS_CONTRIBUTOR,
self::TYPE_TASK_HAS_MOCK => self::TYPE_MOCK_HAS_TASK,
diff --git a/src/infrastructure/edges/type/PhabricatorEdgeType.php b/src/infrastructure/edges/type/PhabricatorEdgeType.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/edges/type/PhabricatorEdgeType.php
@@ -0,0 +1,217 @@
+<?php
+
+/**
+ * Defines an edge type.
+ *
+ * Edges are typed, directed connections between two objects. They are used to
+ * represent most simple relationships, like when a user is subscribed to an
+ * object or an object is a member of a project.
+ *
+ * @task load Loading Types
+ */
+abstract class PhabricatorEdgeType extends Phobject {
+
+ abstract public function getEdgeConstant();
+
+ public function getInverseEdgeConstant() {
+ return null;
+ }
+
+ public function shouldPreventCycles() {
+ return false;
+ }
+
+ public function getTransactionAddString(
+ $actor,
+ $add_count,
+ $add_edges) {
+
+ return pht(
+ '%s added %s edge(s): %s.',
+ $actor,
+ $add_count,
+ $add_edges);
+ }
+
+ public function getTransactionRemoveString(
+ $actor,
+ $rem_count,
+ $rem_edges) {
+
+ return pht(
+ '%s removed %s edge(s): %s.',
+ $actor,
+ $rem_count,
+ $rem_edges);
+ }
+
+ public function getTransactionEditString(
+ $actor,
+ $total_count,
+ $add_count,
+ $add_edges,
+ $rem_count,
+ $rem_edges) {
+
+ return pht(
+ '%s edited %s edges, added %s: %s; removed %s: %s.',
+ $actor,
+ $total_count,
+ $add_count,
+ $add_edges,
+ $rem_count,
+ $rem_edges);
+ }
+
+ public function getFeedAddString(
+ $actor,
+ $object,
+ $add_count,
+ $add_edges) {
+
+ return pht(
+ '%s added %s edge(s) to %s: %s.',
+ $actor,
+ $add_count,
+ $object,
+ $add_edges);
+ }
+
+ public function getFeedRemoveString(
+ $actor,
+ $object,
+ $rem_count,
+ $rem_edges) {
+
+ return pht(
+ '%s removed %s edge(s) from %s: %s.',
+ $actor,
+ $rem_count,
+ $object,
+ $rem_edges);
+ }
+
+ public function getFeedEditString(
+ $actor,
+ $object,
+ $total_count,
+ $add_count,
+ $add_edges,
+ $rem_count,
+ $rem_edges) {
+
+ return pht(
+ '%s edited %s edges for %s, added %s: %s; removed %s: %s.',
+ $actor,
+ $total_count,
+ $object,
+ $add_count,
+ $add_edges,
+ $rem_count,
+ $rem_edges);
+ }
+
+
+/* -( Loading Types )------------------------------------------------------ */
+
+
+ /**
+ * @task load
+ */
+ public static function getAllTypes() {
+ static $type_map;
+
+ if ($type_map === null) {
+ $types = id(new PhutilSymbolLoader())
+ ->setAncestorClass(__CLASS__)
+ ->loadObjects();
+
+ $map = array();
+
+
+ // TODO: Remove this once everything is migrated.
+ $exclude = mpull($types, 'getEdgeConstant');
+ $map = PhabricatorEdgeConfig::getLegacyTypes($exclude);
+ unset($types['PhabricatorLegacyEdgeType']);
+
+
+ foreach ($types as $class => $type) {
+ $const = $type->getEdgeConstant();
+
+ if (!is_int($const) || ($const <= 0)) {
+ throw new Exception(
+ pht(
+ 'Edge type "%s" has an invalid edge constant. Edge constants '.
+ 'must be positive integers.',
+ $class));
+ }
+
+ if (isset($map[$const])) {
+ throw new Exception(
+ pht(
+ 'Two edge types ("%s", "%s") share the same edge constant '.
+ '(%d). Each edge type must have a unique constant.',
+ $class,
+ get_class($map[$const]),
+ $const));
+ }
+
+ $map[$const] = $type;
+ }
+
+ // Check that all the inverse edge definitions actually make sense. If
+ // edge type A says B is its inverse, B must exist and say that A is its
+ // inverse.
+
+ foreach ($map as $const => $type) {
+ $inverse = $type->getInverseEdgeConstant();
+ if ($inverse === null) {
+ continue;
+ }
+
+ if (empty($map[$inverse])) {
+ throw new Exception(
+ pht(
+ 'Edge type "%s" ("%d") defines an inverse type ("%d") which '.
+ 'does not exist.',
+ get_class($type),
+ $const,
+ $inverse));
+ }
+
+ $inverse_inverse = $map[$inverse]->getInverseEdgeConstant();
+ if ($inverse_inverse !== $const) {
+ throw new Exception(
+ pht(
+ 'Edge type "%s" ("%d") defines an inverse type ("%d"), but that '.
+ 'inverse type defines a different type ("%d") as its '.
+ 'inverse.',
+ get_class($type),
+ $const,
+ $inverse,
+ $inverse_inverse));
+ }
+ }
+
+ $type_map = $map;
+ }
+
+ return $type_map;
+ }
+
+
+ /**
+ * @task load
+ */
+ public static function getByConst($const) {
+ $type = idx(self::getAllTypes(), $const);
+
+ if (!$type) {
+ throw new Exception(
+ pht('Unknown edge constant "%s"!', $const));
+ }
+
+ return $type;
+ }
+
+}
diff --git a/src/infrastructure/edges/type/PhabricatorLegacyEdgeType.php b/src/infrastructure/edges/type/PhabricatorLegacyEdgeType.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/edges/type/PhabricatorLegacyEdgeType.php
@@ -0,0 +1,119 @@
+<?php
+
+/**
+ * Supports legacy edges. Do not use or extend this class!
+ *
+ * TODO: Move all edge constants out of @{class:PhabricatorEdgeConfig}, then
+ * throw this away.
+ */
+final class PhabricatorLegacyEdgeType extends PhabricatorEdgeType {
+
+ private $edgeConstant;
+ private $inverseEdgeConstant;
+ private $shouldPreventCycles;
+ private $strings;
+
+ public function getEdgeConstant() {
+ return $this->edgeConstant;
+ }
+
+ public function getInverseEdgeConstant() {
+ return $this->inverseEdgeConstant;
+ }
+
+ public function getShouldPreventCycles() {
+ return $this->shouldPreventCycles;
+ }
+
+ public function setEdgeConstant($edge_constant) {
+ $this->edgeConstant = $edge_constant;
+ return $this;
+ }
+
+ public function setInverseEdgeConstant($inverse_edge_constant) {
+ $this->inverseEdgeConstant = $inverse_edge_constant;
+ return $this;
+ }
+
+ public function setShouldPreventCycles($should_prevent_cycles) {
+ $this->shouldPreventCycles = $should_prevent_cycles;
+ return $this;
+ }
+
+ public function setStrings(array $strings) {
+ $this->strings = $strings;
+ return $this;
+ }
+
+ private function getString($idx, array $argv) {
+ array_unshift($argv, idx($this->strings, $idx, ''));
+
+ // TODO: Burn this class in a fire. Just hiding this from lint for now.
+ $pht_func = 'pht';
+ return call_user_func_array($pht_func, $argv);
+ }
+
+ public function getTransactionAddString(
+ $actor,
+ $add_count,
+ $add_edges) {
+
+ $args = func_get_args();
+ return $this->getString(0, $args);
+ }
+
+ public function getTransactionRemoveString(
+ $actor,
+ $rem_count,
+ $rem_edges) {
+
+ $args = func_get_args();
+ return $this->getString(1, $args);
+ }
+
+ public function getTransactionEditString(
+ $actor,
+ $total_count,
+ $add_count,
+ $add_edges,
+ $rem_count,
+ $rem_edges) {
+
+ $args = func_get_args();
+ return $this->getString(2, $args);
+ }
+
+ public function getFeedAddString(
+ $actor,
+ $object,
+ $add_count,
+ $add_edges) {
+
+ $args = func_get_args();
+ return $this->getString(3, $args);
+ }
+
+ public function getFeedRemoveString(
+ $actor,
+ $object,
+ $rem_count,
+ $rem_edges) {
+
+ $args = func_get_args();
+ return $this->getString(3, $args);
+ }
+
+ public function getFeedEditString(
+ $actor,
+ $object,
+ $total_count,
+ $add_count,
+ $add_edges,
+ $rem_count,
+ $rem_edges) {
+
+ $args = func_get_args();
+ return $this->getString(3, $args);
+ }
+
+}

File Metadata

Mime Type
text/plain
Expires
Mon, Mar 24, 8:16 AM (4 d, 12 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7703646
Default Alt Text
D9837.id23625.diff (13 KB)

Event Timeline