Changeset View
Changeset View
Standalone View
Standalone View
src/infrastructure/edges/type/PhabricatorEdgeType.php
- This file was added.
<?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 { | |||||
// TODO: Make this final after we remove PhabricatorLegacyEdgeType. | |||||
/* final */ public function getEdgeConstant() { | |||||
joshuaspence: Maybe make this `final`? | |||||
Not Done Inline ActionsWe can't until we get rid of LegacyEdgeType, but it would make sense afterward. I'm also not 100% sure this works yet, need to rebase a couple of diffs on top of it. :P epriestley: We can't until we get rid of LegacyEdgeType, but it would make sense afterward. I'm also not… | |||||
Not Done Inline ActionsAh of course. Mark with a TODO? joshuaspence: Ah of course. Mark with a TODO? | |||||
$class = new ReflectionClass($this); | |||||
$const = $class->getConstant('EDGECONST'); | |||||
if ($const === false) { | |||||
throw new Exception( | |||||
pht( | |||||
'EdgeType class "%s" must define an EDGECONST property.', | |||||
get_class($this))); | |||||
} | |||||
if (!is_int($const) || ($const <= 0)) { | |||||
throw new Exception( | |||||
pht( | |||||
Not Done Inline ActionsMaybe we should check here that EDGECONST is a positive integer as well. joshuaspence: Maybe we should check here that `EDGECONST` is a positive integer as well. | |||||
'EdgeType class "%s" has an invalid EDGECONST property. Edge '. | |||||
'constants must be positive integers.', | |||||
get_class($this))); | |||||
} | |||||
return $const; | |||||
} | |||||
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, | |||||
Not Done Inline Actionss/edge/edge(s)/ joshuaspence: `s/edge/edge(s)/` | |||||
$add_count, | |||||
$add_edges, | |||||
$rem_count, | |||||
$rem_edges) { | |||||
return pht( | |||||
'%s edited %s edge(s), 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) { | |||||
Not Done Inline ActionsNot sure how pht handles pluralisation but s/edge/edge(s)/. joshuaspence: Not sure how `pht` handles pluralisation but `s/edge/edge(s)/`. | |||||
return pht( | |||||
'%s removed %s edge(s) from %s: %s.', | |||||
$actor, | |||||
$rem_count, | |||||
$object, | |||||
$rem_edges); | |||||
} | |||||
public function getFeedEditString( | |||||
$actor, | |||||
$object, | |||||
$total_count, | |||||
Not Done Inline ActionsAs above. joshuaspence: As above. | |||||
$add_count, | |||||
$add_edges, | |||||
$rem_count, | |||||
$rem_edges) { | |||||
return pht( | |||||
'%s edited %s edge(s) 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; | |||||
Not Done Inline ActionsI prefer to throw more specific exceptions where possible... Perhaps LogicException? joshuaspence: I prefer to throw more specific exceptions where possible... Perhaps `LogicException`? | |||||
if ($type_map === null) { | |||||
$types = id(new PhutilSymbolLoader()) | |||||
->setAncestorClass(__CLASS__) | |||||
->loadObjects(); | |||||
$map = array(); | |||||
Not Done Inline ActionsAs above. joshuaspence: As above. | |||||
// 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(); | |||||
Not Done Inline ActionsOh that's right, you do it here. I wonder if there's any benefit doing it in getEdgeConstant. joshuaspence: Oh that's right, you do it here. I wonder if there's any benefit doing it in `getEdgeConstant`. | |||||
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; | |||||
} | |||||
Not Done Inline ActionsAs above. joshuaspence: As above. | |||||
// 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])) { | |||||
Not Done Inline ActionsAs above. joshuaspence: As above. | |||||
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)); | |||||
} | |||||
} | |||||
Not Done Inline ActionsI'm not a huge fan of this method name. joshuaspence: I'm not a huge fan of this method name. | |||||
$type_map = $map; | |||||
} | |||||
return $type_map; | |||||
} | |||||
/** | |||||
* @task load | |||||
*/ | |||||
public static function getByConstant($const) { | |||||
$type = idx(self::getAllTypes(), $const); | |||||
Not Done Inline ActionsMaybe rename to getByConstant for consistency with getInverseEdgeConstant() joshuaspence: Maybe rename to `getByConstant` for consistency with `getInverseEdgeConstant()` | |||||
if (!$type) { | |||||
throw new Exception( | |||||
pht('Unknown edge constant "%s"!', $const)); | |||||
} | |||||
return $type; | |||||
} | |||||
} |
Maybe make this final?