/** * Uses the constructor represented by this Constructor object to create * and initialize a new instance of the constructor's declaring class, * with the specified initialization parameters. * * Example: * <code> * $constructor= XPClass::forName('util.Binford')->getConstructor(); * * $instance= $constructor->newInstance(); * $instance= $constructor->newInstance([6100]); * </code> * * @param var[] args * @return lang.Generic * @throws lang.IllegalAccessException in case the constructor is not public or if it is abstract * @throws lang.reflect.TargetInvocationException in case the constructor throws an exception */ public function newInstance(array $args = []) { $class = new \ReflectionClass($this->_class); if ($class->isAbstract()) { throw new IllegalAccessException('Cannot instantiate abstract class ' . XPClass::nameOf($this->_class)); } // Check modifiers. If caller is an instance of this class, allow private and // protected constructor invocation (which the PHP reflection API does not). $m = $this->_reflect->getModifiers(); $public = $m & MODIFIER_PUBLIC; if (!$public && !$this->accessible) { $t = debug_backtrace(0, 2); $decl = $this->_reflect->getDeclaringClass()->getName(); if ($m & MODIFIER_PROTECTED) { $allow = $t[1]['class'] === $decl || is_subclass_of($t[1]['class'], $decl); } else { $allow = $t[1]['class'] === $decl; } if (!$allow) { throw new IllegalAccessException(sprintf('Cannot invoke %s constructor of class %s from scope %s', Modifiers::stringOf($this->getModifiers()), XPClass::nameOf($this->_class), $t[1]['class'])); } } // For non-public constructors: Use setAccessible() / invokeArgs() combination try { if ($public) { return $class->newInstanceArgs($args); } $instance = unserialize('O:' . strlen($this->_class) . ':"' . $this->_class . '":0:{}'); $this->_reflect->setAccessible(true); $this->_reflect->invokeArgs($instance, $args); return $instance; } catch (\lang\SystemExit $e) { throw $e; } catch (\lang\Throwable $e) { throw new TargetInvocationException(XPClass::nameOf($this->_class) . '::<init>', $e); } catch (\Exception $e) { throw new TargetInvocationException(XPClass::nameOf($this->_class) . '::<init>', new \lang\XPException($e->getMessage())); } catch (\BaseException $e) { throw new TargetInvocationException(XPClass::nameOf($this->_class) . '::' . $this->_reflect->getName(), new \lang\Error($e->getMessage())); } }
/** * Invokes the underlying method represented by this Method object, * on the specified object with the specified parameters. * * Example: * ```php * $method= XPClass::forName('lang.Object')->getMethod('toString'); * $str= $method->invoke(new Object()); * ``` * * Example (passing arguments) * ```php * $method= XPClass::forName('lang.types.String')->getMethod('concat'); * $str= $method->invoke(new String('Hello'), ['World']); * ``` * * Example (static invokation): * ```php * $method= XPClass::forName('util.log.Logger')->getMethod('getInstance'); * $log= $method->invoke(null); * ``` * * @param lang.Object $obj * @param var[] $args default [] * @return var * @throws lang.IllegalArgumentException in case the passed object is not an instance of the declaring class * @throws lang.IllegalAccessException in case the method is not public or if it is abstract * @throws lang.reflect.TargetInvocationException for any exception raised from the invoked method */ public function invoke($obj, $args = []) { if (null !== $obj && !$obj instanceof $this->_class) { throw new IllegalArgumentException(sprintf('Passed argument is not a %s class (%s)', XPClass::nameOf($this->_class), \xp::typeOf($obj))); } // Check modifiers. If caller is an instance of this class, allow // protected method invocation (which the PHP reflection API does // not). $m = $this->_reflect->getModifiers(); if ($m & MODIFIER_ABSTRACT) { throw new IllegalAccessException(sprintf('Cannot invoke abstract %s::%s', XPClass::nameOf($this->_class), $this->_reflect->getName())); } $public = $m & MODIFIER_PUBLIC; if (!$public && !$this->accessible) { $t = debug_backtrace(0, 2); $decl = $this->_reflect->getDeclaringClass()->getName(); if ($m & MODIFIER_PROTECTED) { $allow = $t[1]['class'] === $decl || is_subclass_of($t[1]['class'], $decl); } else { $allow = $t[1]['class'] === $decl; } if (!$allow) { throw new IllegalAccessException(sprintf('Cannot invoke %s %s::%s from scope %s', Modifiers::stringOf($this->getModifiers()), XPClass::nameOf($this->_class), $this->_reflect->getName(), $t[1]['class'])); } } try { if (!$public) { $this->_reflect->setAccessible(true); } return $this->_reflect->invokeArgs($obj, (array) $args); } catch (\lang\SystemExit $e) { throw $e; } catch (\lang\Throwable $e) { throw new TargetInvocationException(XPClass::nameOf($this->_class) . '::' . $this->_reflect->getName(), $e); } catch (\Exception $e) { throw new TargetInvocationException(XPClass::nameOf($this->_class) . '::' . $this->_reflect->getName(), new \lang\XPException($e->getMessage())); } catch (\Throwable $e) { throw new TargetInvocationException(XPClass::nameOf($this->_class) . '::' . $this->_reflect->getName(), new \lang\Error($e->getMessage())); } }
public function staticModifierString() { $this->assertEquals('public static', \lang\reflect\Modifiers::stringOf(MODIFIER_STATIC)); }
/** * Retrieve string representation. Examples: * * <pre> * public lang.XPClass getClass() * public static util.Date now() * public open(string $mode) throws io.FileNotFoundException, io.IOException * </pre> * * @return string */ public function toString() { $signature = ''; foreach ($this->getParameters() as $param) { if ($param->isOptional()) { $signature .= ', [' . $param->getTypeName() . ' $' . $param->getName() . '= ' . str_replace("\n", ' ', \xp::stringOf($param->getDefaultValue())) . ']'; } else { $signature .= ', ' . $param->getTypeName() . ' $' . $param->getName(); } } if ($exceptions = $this->getExceptionNames()) { $throws = ' throws ' . implode(', ', $exceptions); } else { $throws = ''; } return sprintf('%s %s %s(%s)%s', Modifiers::stringOf($this->getModifiers()), $this->getReturnTypeName(), $this->getName(), substr($signature, 2), $throws); }
/** * Creates a string representation of this field * * @return string */ public function toString() { return sprintf('%s %s %s::$%s', Modifiers::stringOf($this->getModifiers()), $this->getTypeName(), $this->getDeclaringClass()->getName(), $this->getName()); }