target = $target; } /** * Dynamically sets properties on the target. * * @param mixed $value */ public function __set(string $property, $value): void { // @phpstan-ignore-next-line $this->target->{$property} = $value; } /** * Dynamically pass properties gets to the target. * * @return mixed */ public function __get(string $property) { try { // @phpstan-ignore-next-line return $this->target->{$property}; } catch (Throwable $throwable) { Reflection::setPropertyValue($throwable, 'file', Backtrace::file()); Reflection::setPropertyValue($throwable, 'line', Backtrace::line()); if (Str::startsWith($message = $throwable->getMessage(), self::UNDEFINED_PROPERTY)) { /** @var ReflectionClass $reflection */ $reflection = (new ReflectionClass($this->target))->getParentClass(); Reflection::setPropertyValue($throwable, 'message', sprintf('Undefined property %s::$%s', $reflection->getName(), $property)); } throw $throwable; } } /** * Dynamically pass method calls to the target. * * @param array $arguments * * @return mixed */ public function __call(string $methodName, array $arguments) { $filename = Backtrace::file(); $line = Backtrace::line(); return (new HigherOrderMessage($filename, $line, $methodName, $arguments)) ->call($this->target); } }