/** * Verifies a reflection function or method * * @param php.ReflectionFunctionAbstract $value * @param [lang.Type] $signature * @param function(string): var $value A function to invoke when verification fails * @param php.ReflectionClass $class Class to get details from, optionally * @return var */ protected function verify($r, $signature, $false, $class = null) { if (null !== $signature && sizeof($signature) < $r->getNumberOfRequiredParameters()) { return $false('Required signature length mismatch, expecting ' . sizeof($signature) . ', have ' . $r->getNumberOfParameters()); } $details = $class ? XPClass::detailsForMethod($class->getName(), $r->getName()) : null; if (isset($details[DETAIL_RETURNS])) { $returns = Type::forName($details[DETAIL_RETURNS]); if (!$this->returns->equals($returns) && !$this->returns->isAssignableFrom($returns)) { return $false('Return type mismatch, expecting ' . $this->returns->getName() . ', have ' . $returns->getName()); } } if (null === $signature) { return true; } $params = $r->getParameters(); foreach ($signature as $i => $type) { if (!isset($params[$i])) { return $false('No parameter #' . ($i + 1)); } if (isset($details[DETAIL_ARGUMENTS][$i])) { $param = Type::forName($details[DETAIL_ARGUMENTS][$i]); if (!$type->isAssignableFrom($param)) { return $false('Parameter #' . ($i + 1) . ' not a ' . $param->getName() . ' type: ' . $type->getName()); } } else { $param = $params[$i]; if ($param->isArray()) { if (!$type->equals(Primitive::$ARRAY) && !$type instanceof ArrayType && !$type instanceof MapType) { return $false('Parameter #' . ($i + 1) . ' not an array type: ' . $type->getName()); } } else { if ($param->isCallable()) { if (!$type instanceof FunctionType) { return $false('Parameter #' . ($i + 1) . ' not a function type: ' . $type->getName()); } } else { if (null !== ($class = $param->getClass())) { if (!$type->isAssignableFrom(new XPClass($class))) { return $false('Parameter #' . ($i + 1) . ' not a ' . $class->getName() . ': ' . $type->getName()); } } } } } } return true; }
/** * Retrieve details for a specified class and field. Note: Results * from this method are cached! * * @param php.ReflectionClass $class * @param string method * @return array or NULL if not available */ public static function detailsForField($class, $field) { $details = self::detailsForClass(self::nameOf($class->name)); if (isset($details[0][$field])) { return $details[0][$field]; } foreach ($class->getTraitNames() as $trait) { $details = self::detailsForClass(self::nameOf($trait)); if (isset($details[0][$field])) { return $details[0][$field]; } } return null; }