in src/symbols/PhutilSymbolLoader.php [165:283]
public function selectAndLoadSymbols() {
$map = array();
$bootloader = PhutilBootloader::getInstance();
if ($this->library) {
$libraries = array($this->library);
} else {
$libraries = $bootloader->getAllLibraries();
}
if ($this->type) {
$types = array($this->type);
} else {
$types = array(
'class',
'function',
);
}
$names = null;
if ($this->base) {
$names = $this->selectDescendantsOf(
$bootloader->getClassTree(),
$this->base);
}
$symbols = array();
foreach ($libraries as $library) {
$map = $bootloader->getLibraryMap($library);
foreach ($types as $type) {
if ($type == 'interface') {
$lookup_map = $map['class'];
} else {
$lookup_map = $map[$type];
}
// As an optimization, we filter the list of candidate symbols in
// several passes, applying a name-based filter first if possible since
// it is highly selective and guaranteed to match at most one symbol.
// This is the common case and we land here through `__autoload()` so
// it's worthwhile to micro-optimize a bit because this code path is
// very hot and we save 5-10ms per page for a very moderate increase in
// complexity.
if ($this->name) {
// If we have a name filter, just pick the matching name out if it
// exists.
if (isset($lookup_map[$this->name])) {
$filtered_map = array(
$this->name => $lookup_map[$this->name],
);
} else {
$filtered_map = array();
}
} else if ($names !== null) {
$filtered_map = array();
foreach ($names as $name => $ignored) {
if (isset($lookup_map[$name])) {
$filtered_map[$name] = $lookup_map[$name];
}
}
} else {
// Otherwise, start with everything.
$filtered_map = $lookup_map;
}
if ($this->pathPrefix) {
$len = strlen($this->pathPrefix);
foreach ($filtered_map as $name => $where) {
if (strncmp($where, $this->pathPrefix, $len) !== 0) {
unset($filtered_map[$name]);
}
}
}
foreach ($filtered_map as $name => $where) {
$symbols[$type.'$'.$name] = array(
'type' => $type,
'name' => $name,
'library' => $library,
'where' => $where,
);
}
}
}
if (!$this->suppressLoad) {
$caught = null;
foreach ($symbols as $symbol) {
try {
$this->loadSymbol($symbol);
} catch (Exception $ex) {
$caught = $ex;
}
}
if ($caught) {
// NOTE: We try to load everything even if we fail to load something,
// primarily to make it possible to remove functions from a libphutil
// library without breaking library startup.
throw $caught;
}
}
if ($this->concrete) {
// Remove 'abstract' classes.
foreach ($symbols as $key => $symbol) {
if ($symbol['type'] == 'class') {
$reflection = new ReflectionClass($symbol['name']);
if ($reflection->isAbstract()) {
unset($symbols[$key]);
}
}
}
}
return $symbols;
}