private function refreshMonitors($depth, &$missing = NULL, &$listeners = [])
{
if ($this instanceof IContainer) {
foreach ($this->getComponents() as $component) {
if ($component instanceof self) {
$component->refreshMonitors($depth + 1, $missing, $listeners);
}
}
}
if ($missing === NULL) {
// detaching
foreach ($this->monitors as $type => $rec) {
if (isset($rec[1]) && $rec[1] > $depth) {
if ($rec[3]) {
// monitored
$this->monitors[$type] = [NULL, NULL, NULL, TRUE];
$listeners[] = [$this, $rec[0]];
} else {
// not monitored, just randomly cached
unset($this->monitors[$type]);
}
}
}
} else {
// attaching
foreach ($this->monitors as $type => $rec) {
if (isset($rec[0])) {
// is in cache yet
continue;
} elseif (!$rec[3]) {
// not monitored, just randomly cached
unset($this->monitors[$type]);
} elseif (isset($missing[$type])) {
// known from previous lookup
$this->monitors[$type] = [NULL, NULL, NULL, TRUE];
} else {
$this->monitors[$type] = NULL;
// forces re-lookup
if ($obj = $this->lookup($type, FALSE)) {
$listeners[] = [$this, $obj];
} else {
$missing[$type] = TRUE;
}
$this->monitors[$type][3] = TRUE;
// mark as monitored
}
}
}
if ($depth === 0) {
// call listeners
$method = $missing === NULL ? 'detached' : 'attached';
$prev = [];
foreach ($listeners as $item) {
if (!in_array($item, $prev, TRUE)) {
$item[0]->{$method}($item[1]);
$prev[] = $item;
}
}
}
}