Registration by collision-safe key. */ private $registrations = array(); /** @var array> Registration keys by hook name. */ private $keysByHook = array(); /** * Object ids of every wrapper/marker closure currently registered. * * spl_object_id() recycles ids once an object is freed, which would make a * stale entry here answer "yes, mine" about an unrelated object. It cannot * go stale: the closure is reachable from its own registration for exactly * as long as the id is in this set, so the id cannot be reissued while the * set still holds it. * * @var array */ private $ownedCallbackIds = array(); /** @param Registration $registration */ public function add(string $key, array $registration): void { $this->forget($key); $this->registrations[$key] = $registration; $hook = $registration['hook']; $this->keysByHook[$hook][$key] = true; foreach (array('wrapper', 'before') as $field) { $callback = $registration[$field] ?? null; if (is_object($callback)) { $this->ownedCallbackIds[spl_object_id($callback)] = true; } } } public function forget(string $key): void { if (!array_key_exists($key, $this->registrations)) { return; } $registration = $this->registrations[$key]; $hook = $registration['hook']; unset($this->keysByHook[$hook][$key], $this->registrations[$key]); if (($this->keysByHook[$hook] ?? null) === array()) { unset($this->keysByHook[$hook]); } foreach (array('wrapper', 'before') as $field) { $callback = $registration[$field] ?? null; if (is_object($callback)) { unset($this->ownedCallbackIds[spl_object_id($callback)]); } } } /** @return Registration|null */ public function get(string $key): ?array { return $this->registrations[$key] ?? null; } /** @return array Registrations of one hook, keyed by key. */ public function forHook(string $hook): array { $found = array(); foreach (array_keys($this->keysByHook[$hook] ?? array()) as $key) { if (array_key_exists($key, $this->registrations)) { $found[$key] = $this->registrations[$key]; } } return $found; } /** @return array Every registration, keyed by key. */ public function all(): array { return $this->registrations; } /** * Is this WP_Hook entry's callable one of the closures we installed? * * @param mixed $callback */ public function ownsCallback($callback): bool { return is_object($callback) && isset($this->ownedCallbackIds[spl_object_id($callback)]); } public function clear(): void { $this->registrations = array(); $this->keysByHook = array(); $this->ownedCallbackIds = array(); } }