in src/symbols/PhutilClassMapQuery.php [205:308]
private function loadMap() {
$ancestor = $this->ancestorClass;
if (!strlen($ancestor)) {
throw new PhutilInvalidStateException('setAncestorClass');
}
if (!class_exists($ancestor) && !interface_exists($ancestor)) {
throw new Exception(
pht(
'Trying to execute a class map query for descendants of class '.
'"%s", but no such class or interface exists.',
$ancestor));
}
$expand = $this->expandMethod;
$filter = $this->filterMethod;
$unique = $this->uniqueMethod;
$sort = $this->sortMethod;
if (strlen($expand)) {
if (!strlen($unique)) {
throw new Exception(
pht(
'Trying to execute a class map query for descendants of class '.
'"%s", but the query specifies an "expand method" ("%s") without '.
'specifying a "unique method". Class maps which support expansion '.
'must have unique keys.',
$ancestor,
$expand));
}
}
$objects = id(new PhutilSymbolLoader())
->setAncestorClass($ancestor)
->loadObjects();
// Apply the "expand" mechanism, if it is configured.
if (strlen($expand)) {
$list = array();
foreach ($objects as $object) {
foreach (call_user_func(array($object, $expand)) as $instance) {
$list[] = $instance;
}
}
} else {
$list = $objects;
}
// Apply the "unique" mechanism, if it is configured.
if (strlen($unique)) {
$map = array();
foreach ($list as $object) {
$key = call_user_func(array($object, $unique));
if ($key === null && $this->filterNull) {
continue;
}
if (empty($map[$key])) {
$map[$key] = $object;
continue;
}
throw new Exception(
pht(
'Two objects (of classes "%s" and "%s", descendants of ancestor '.
'class "%s") returned the same key from "%s" ("%s"), but each '.
'object in this class map must be identified by a unique key.',
get_class($object),
get_class($map[$key]),
$ancestor,
$unique.'()',
$key));
}
} else {
$map = $list;
}
// Apply the "filter" mechanism, if it is configured.
if (strlen($filter)) {
$map = mfilter($map, $filter);
}
// Apply the "sort" mechanism, if it is configured.
if (strlen($sort)) {
if ($map) {
// The "sort" method may return scalars (which we want to sort with
// "msort()"), or may return PhutilSortVector objects (which we want
// to sort with "msortv()").
$item = call_user_func(array(head($map), $sort));
// Since we may be early in the stack, use a string to avoid triggering
// autoload in old versions of PHP.
$vector_class = 'PhutilSortVector';
if ($item instanceof $vector_class) {
$map = msortv($map, $sort);
} else {
$map = msort($map, $sort);
}
}
}
return $map;
}