* > */ private static $handlers = []; public function __construct() { self::$handlers = []; } /** * @param class-string $class * @psalm-suppress PossiblyUnusedParam * * @return void */ public function registerClass(string $class) { if (version_compare(PHP_VERSION, '7.1.0') >= 0) { /** * @psalm-suppress UndefinedMethod * * @var \Closure */ $callable = \Closure::fromCallable([$class, 'doesPropertyExist']); } else { $callable = (new \ReflectionClass($class))->getMethod('doesPropertyExist')->getClosure(new $class); if (!$callable) { throw new \UnexpectedValueException('Callable must not be null'); } } foreach ($class::getClassLikeNames() as $fq_classlike_name) { /** @psalm-suppress MixedTypeCoercion */ $this->registerClosure($fq_classlike_name, $callable); } } /** * @param \Closure( * string, * string, * bool, * ?StatementsSource=, * ?Context=, * ?CodeLocation= * ) : ?bool $c * * @return void */ public function registerClosure(string $fq_classlike_name, \Closure $c) { self::$handlers[strtolower($fq_classlike_name)][] = $c; } public function has(string $fq_classlike_name) : bool { return isset(self::$handlers[strtolower($fq_classlike_name)]); } /** * @param array $call_args * * @return ?bool */ public function doesPropertyExist( string $fq_classlike_name, string $property_name, bool $read_mode, StatementsSource $source = null, Context $context = null, CodeLocation $code_location = null ) { foreach (self::$handlers[strtolower($fq_classlike_name)] as $property_handler) { $property_exists = $property_handler( $fq_classlike_name, $property_name, $read_mode, $source, $context, $code_location ); if ($property_exists !== null) { return $property_exists; } } return null; } }