ヤミRoot VoidGate
User / IP
:
216.73.216.143
Host / Server
:
146.88.233.70 / dev.loger.cm
System
:
Linux hybrid1120.fr.ns.planethoster.net 3.10.0-957.21.2.el7.x86_64 #1 SMP Wed Jun 5 14:26:44 UTC 2019 x86_64
Command
|
Upload
|
Create
Mass Deface
|
Jumping
|
Symlink
|
Reverse Shell
Ping
|
Port Scan
|
DNS Lookup
|
Whois
|
Header
|
cURL
:
/
home
/
logercm
/
dev.loger.cm
/
fixtures
/
assert
/
Viewing: friendsofphp.tar
proxy-manager-lts/src/ProxyManager/Autoloader/Autoloader.php 0000644 00000002105 15117764663 0020265 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Autoloader; use ProxyManager\FileLocator\FileLocatorInterface; use ProxyManager\Inflector\ClassNameInflectorInterface; use function class_exists; use function file_exists; class Autoloader implements AutoloaderInterface { protected $fileLocator; protected $classNameInflector; public function __construct(FileLocatorInterface $fileLocator, ClassNameInflectorInterface $classNameInflector) { $this->fileLocator = $fileLocator; $this->classNameInflector = $classNameInflector; } public function __invoke(string $className): bool { if (class_exists($className, false) || ! $this->classNameInflector->isProxyClassName($className)) { return false; } $file = $this->fileLocator->getProxyFileName($className); if (! file_exists($file)) { return false; } /* @noinspection PhpIncludeInspection */ /* @noinspection UsingInclusionOnceReturnValueInspection */ return (bool) require_once $file; } } proxy-manager-lts/src/ProxyManager/Autoloader/AutoloaderInterface.php 0000644 00000000622 15117764663 0022110 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Autoloader; /** * Basic autoloader utilities required to work with proxy files */ interface AutoloaderInterface { /** * Callback to allow the object to be handled as autoloader - tries to autoload the given class name * * @psalm-param class-string $className */ public function __invoke(string $className): bool; } proxy-manager-lts/src/ProxyManager/Exception/DisabledMethodException.php 0000644 00000000717 15117764663 0022563 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Exception; use BadMethodCallException; use function sprintf; /** * Exception for forcefully disabled methods */ class DisabledMethodException extends BadMethodCallException implements ExceptionInterface { public const NAME = self::class; public static function disabledMethod(string $method): self { return new self(sprintf('Method "%s" is forcefully disabled', $method)); } } proxy-manager-lts/src/ProxyManager/Exception/ExceptionInterface.php 0000644 00000000275 15117764663 0021612 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Exception; use Throwable; /** * Base exception class for the proxy manager */ interface ExceptionInterface extends Throwable { } proxy-manager-lts/src/ProxyManager/Exception/FileNotWritableException.php 0000644 00000002241 15117764663 0022737 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Exception; use Symfony\Component\Filesystem\Exception\IOException; use Throwable; use UnexpectedValueException; use function sprintf; /** * Exception for non writable files */ class FileNotWritableException extends UnexpectedValueException implements ExceptionInterface { /** * @deprecated */ public static function fromInvalidMoveOperation(string $fromPath, string $toPath): self { return new self(sprintf( 'Could not move file "%s" to location "%s": ' . 'either the source file is not readable, or the destination is not writable', $fromPath, $toPath )); } /** * @deprecated */ public static function fromNotWritableDirectory(string $directory): self { return new self(sprintf( 'Could not create temp file in directory "%s" ' . 'either the directory does not exist, or it is not writable', $directory )); } public static function fromPrevious(Throwable $previous): self { return new self($previous->getMessage(), 0, $previous); } } proxy-manager-lts/src/ProxyManager/Exception/InvalidProxiedClassException.php 0000644 00000003302 15117764663 0023613 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Exception; use InvalidArgumentException; use ReflectionClass; use ReflectionMethod; use function array_filter; use function array_map; use function implode; use function sprintf; /** * Exception for invalid proxied classes */ class InvalidProxiedClassException extends InvalidArgumentException implements ExceptionInterface { public static function interfaceNotSupported(ReflectionClass $reflection): self { return new self(sprintf('Provided interface "%s" cannot be proxied', $reflection->getName())); } public static function finalClassNotSupported(ReflectionClass $reflection): self { return new self(sprintf('Provided class "%s" is final and cannot be proxied', $reflection->getName())); } public static function abstractProtectedMethodsNotSupported(ReflectionClass $reflection): self { return new self(sprintf( 'Provided class "%s" has following protected abstract methods, and therefore cannot be proxied:' . "\n%s", $reflection->getName(), implode( "\n", array_map( static function (ReflectionMethod $reflectionMethod): string { return $reflectionMethod->getDeclaringClass()->getName() . '::' . $reflectionMethod->getName(); }, array_filter( $reflection->getMethods(), static function (ReflectionMethod $method): bool { return $method->isAbstract() && $method->isProtected(); } ) ) ) )); } } proxy-manager-lts/src/ProxyManager/Exception/InvalidProxyDirectoryException.php 0000644 00000000676 15117764663 0024234 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Exception; use InvalidArgumentException; use function sprintf; /** * Exception for invalid directories */ class InvalidProxyDirectoryException extends InvalidArgumentException implements ExceptionInterface { public static function proxyDirectoryNotFound(string $directory): self { return new self(sprintf('Provided directory "%s" does not exist', $directory)); } } proxy-manager-lts/src/ProxyManager/Exception/UnsupportedProxiedClassException.php 0000644 00000002422 15117764663 0024557 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Exception; use LogicException; use ProxyManager\ProxyGenerator\Util\Properties; use ReflectionClass; use ReflectionProperty; use function array_map; use function implode; use function sprintf; /** * Exception for invalid proxied classes */ class UnsupportedProxiedClassException extends LogicException implements ExceptionInterface { public static function unsupportedLocalizedReflectionProperty(ReflectionProperty $property): self { return new self( sprintf( 'Provided reflection property "%s" of class "%s" is private and cannot be localized in PHP 5.3', $property->getName(), $property->getDeclaringClass()->getName() ) ); } public static function nonReferenceableLocalizedReflectionProperties( ReflectionClass $class, Properties $properties ): self { return new self(sprintf( 'Cannot create references for following properties of class %s: %s', $class->getName(), implode(', ', array_map(static function (ReflectionProperty $property): string { return $property->getName(); }, $properties->getInstanceProperties())) )); } } proxy-manager-lts/src/ProxyManager/Factory/RemoteObject/Adapter/BaseAdapter.php 0000644 00000002340 15117764663 0023614 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Factory\RemoteObject\Adapter; use Laminas\Server\Client; use ProxyManager\Factory\RemoteObject\AdapterInterface; use function array_key_exists; /** * Remote Object base adapter */ abstract class BaseAdapter implements AdapterInterface { protected $client; /** * Service name mapping * * @var array<string, string> */ protected $map = []; /** * Constructor * * @param array<string, string> $map map of service names to their aliases */ public function __construct(Client $client, array $map = []) { $this->client = $client; $this->map = $map; } /** * {@inheritDoc} */ public function call(string $wrappedClass, string $method, array $params = []) { $serviceName = $this->getServiceName($wrappedClass, $method); if (array_key_exists($serviceName, $this->map)) { $serviceName = $this->map[$serviceName]; } return $this->client->call($serviceName, $params); } /** * Get the service name will be used by the adapter */ abstract protected function getServiceName(string $wrappedClass, string $method): string; } proxy-manager-lts/src/ProxyManager/Factory/RemoteObject/Adapter/JsonRpc.php 0000644 00000000465 15117764663 0023025 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Factory\RemoteObject\Adapter; /** * Remote Object JSON RPC adapter */ class JsonRpc extends BaseAdapter { protected function getServiceName(string $wrappedClass, string $method): string { return $wrappedClass . '.' . $method; } } proxy-manager-lts/src/ProxyManager/Factory/RemoteObject/Adapter/Soap.php 0000644 00000000430 15117764663 0022341 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Factory\RemoteObject\Adapter; /** * Remote Object SOAP adapter */ class Soap extends BaseAdapter { protected function getServiceName(string $wrappedClass, string $method): string { return $method; } } proxy-manager-lts/src/ProxyManager/Factory/RemoteObject/Adapter/XmlRpc.php 0000644 00000000463 15117764663 0022652 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Factory\RemoteObject\Adapter; /** * Remote Object XML RPC adapter */ class XmlRpc extends BaseAdapter { protected function getServiceName(string $wrappedClass, string $method): string { return $wrappedClass . '.' . $method; } } proxy-manager-lts/src/ProxyManager/Factory/RemoteObject/AdapterInterface.php 0000644 00000001046 15117764663 0023264 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Factory\RemoteObject; /** * Remote Object adapter interface */ interface AdapterInterface { /** * Call remote object * * @param array<int, mixed> $params * * Due to BC compliance, we cannot add a native `: mixed` return type declaration here * * phpcs:disable SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint * * @return mixed */ public function call(string $wrappedClass, string $method, array $params = []); } proxy-manager-lts/src/ProxyManager/Factory/AbstractBaseFactory.php 0000644 00000007760 15117764663 0021400 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Factory; use OutOfBoundsException; use ProxyManager\Configuration; use ProxyManager\Generator\ClassGenerator; use ProxyManager\ProxyGenerator\ProxyGeneratorInterface; use ProxyManager\Signature\Exception\InvalidSignatureException; use ProxyManager\Signature\Exception\MissingSignatureException; use ProxyManager\Version; use ReflectionClass; use function array_key_exists; use function assert; use function class_exists; use function is_a; use function serialize; use function sha1; /** * Base factory common logic */ abstract class AbstractBaseFactory { protected $configuration; /** * Cached checked class names * * @var array<string, string> * @psalm-var array<string, class-string> */ private $checkedClasses = []; public function __construct(?Configuration $configuration = null) { $this->configuration = $configuration ?? new Configuration(); } /** * Generate a proxy from a class name * * @param array<string, mixed> $proxyOptions * @psalm-param class-string<RealObjectType> $className * * @psalm-return class-string<RealObjectType> * * @throws InvalidSignatureException * @throws MissingSignatureException * @throws OutOfBoundsException * * @psalm-template RealObjectType of object */ protected function generateProxy(string $className, array $proxyOptions = []): string { $cacheKey = $proxyOptions ? sha1(serialize([$className, $proxyOptions])) : $className; if (array_key_exists($cacheKey, $this->checkedClasses)) { $generatedClassName = $this->checkedClasses[$cacheKey]; assert(is_a($generatedClassName, $className, true)); return $generatedClassName; } $proxyParameters = [ 'className' => $className, 'factory' => static::class, 'proxyManagerVersion' => Version::getVersion(), 'proxyOptions' => $proxyOptions, ]; $proxyClassName = $this ->configuration ->getClassNameInflector() ->getProxyClassName($className, $proxyParameters); if (! class_exists($proxyClassName)) { $this->generateProxyClass( $proxyClassName, $className, $proxyParameters, $proxyOptions ); } $this ->configuration ->getSignatureChecker() ->checkSignature(new ReflectionClass($proxyClassName), $proxyParameters); return $this->checkedClasses[$cacheKey] = $proxyClassName; } abstract protected function getGenerator(): ProxyGeneratorInterface; /** * Generates the provided `$proxyClassName` from the given `$className` and `$proxyParameters` * * @param array<string, mixed> $proxyParameters * @param array<string, mixed> $proxyOptions * @psalm-param class-string $proxyClassName * @psalm-param class-string $className */ private function generateProxyClass( string $proxyClassName, string $className, array $proxyParameters, array $proxyOptions = [] ): void { $className = $this->configuration->getClassNameInflector()->getUserClassName($className); $phpClass = new ClassGenerator($proxyClassName); /** @psalm-suppress TooManyArguments - generator interface was not updated due to BC compliance */ $this->getGenerator()->generate(new ReflectionClass($className), $phpClass, $proxyOptions); $phpClass = $this->configuration->getClassSignatureGenerator()->addSignature($phpClass, $proxyParameters); /** @psalm-suppress TooManyArguments - generator interface was not updated due to BC compliance */ $this->configuration->getGeneratorStrategy()->generate($phpClass, $proxyOptions); $autoloader = $this->configuration->getProxyAutoloader(); $autoloader($proxyClassName); } } proxy-manager-lts/src/ProxyManager/Factory/AccessInterceptorScopeLocalizerFactory.php 0000644 00000005761 15117764663 0025320 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Factory; use Closure; use OutOfBoundsException; use ProxyManager\Configuration; use ProxyManager\Proxy\AccessInterceptorInterface; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizerGenerator; use ProxyManager\ProxyGenerator\ProxyGeneratorInterface; use ProxyManager\Signature\Exception\InvalidSignatureException; use ProxyManager\Signature\Exception\MissingSignatureException; use function get_class; /** * Factory responsible of producing proxy objects */ class AccessInterceptorScopeLocalizerFactory extends AbstractBaseFactory { private $generator; public function __construct(?Configuration $configuration = null) { parent::__construct($configuration); $this->generator = new AccessInterceptorScopeLocalizerGenerator(); } /** * @param object $instance the object to be localized within the access interceptor * @param array<string, Closure> $prefixInterceptors an array (indexed by method name) of interceptor closures to be called * before method logic is executed * @param array<string, Closure> $suffixInterceptors an array (indexed by method name) of interceptor closures to be called * after method logic is executed * @psalm-param RealObjectType $instance * @psalm-param array<string, Closure( * RealObjectType&AccessInterceptorInterface<RealObjectType>=, * RealObjectType=, * string=, * array<string, mixed>=, * bool= * ) : mixed> $prefixInterceptors * @psalm-param array<string, Closure( * RealObjectType&AccessInterceptorInterface<RealObjectType>=, * RealObjectType=, * string=, * array<string, mixed>=, * mixed=, * bool= * ) : mixed> $suffixInterceptors * * @psalm-return RealObjectType&AccessInterceptorInterface<RealObjectType> * * @throws InvalidSignatureException * @throws MissingSignatureException * @throws OutOfBoundsException * * @psalm-template RealObjectType of object * @psalm-suppress MixedInferredReturnType We ignore type checks here, since `staticProxyConstructor` is not * interfaced (by design) */ public function createProxy( $instance, array $prefixInterceptors = [], array $suffixInterceptors = [] ): AccessInterceptorInterface { $proxyClassName = $this->generateProxy(get_class($instance)); /** * We ignore type checks here, since `staticProxyConstructor` is not interfaced (by design) * * @psalm-suppress MixedMethodCall * @psalm-suppress MixedReturnStatement */ return $proxyClassName::staticProxyConstructor($instance, $prefixInterceptors, $suffixInterceptors); } protected function getGenerator(): ProxyGeneratorInterface { return $this->generator; } } proxy-manager-lts/src/ProxyManager/Factory/AccessInterceptorValueHolderFactory.php 0000644 00000006263 15117764663 0024612 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Factory; use Closure; use OutOfBoundsException; use ProxyManager\Configuration; use ProxyManager\Proxy\AccessInterceptorInterface; use ProxyManager\Proxy\AccessInterceptorValueHolderInterface; use ProxyManager\Proxy\ValueHolderInterface; use ProxyManager\ProxyGenerator\AccessInterceptorValueHolderGenerator; use ProxyManager\ProxyGenerator\ProxyGeneratorInterface; use ProxyManager\Signature\Exception\InvalidSignatureException; use ProxyManager\Signature\Exception\MissingSignatureException; use function get_class; /** * Factory responsible of producing proxy objects */ class AccessInterceptorValueHolderFactory extends AbstractBaseFactory { private $generator; public function __construct(?Configuration $configuration = null) { parent::__construct($configuration); $this->generator = new AccessInterceptorValueHolderGenerator(); } /** * @param object $instance the object to be wrapped within the value holder * @param array<string, Closure> $prefixInterceptors an array (indexed by method name) of interceptor closures to be called * before method logic is executed * @param array<string, Closure> $suffixInterceptors an array (indexed by method name) of interceptor closures to be called * after method logic is executed * @psalm-param RealObjectType $instance * @psalm-param array<string, callable( * RealObjectType&AccessInterceptorInterface<RealObjectType>=, * RealObjectType=, * string=, * array<string, mixed>=, * bool= * ) : mixed> $prefixInterceptors * @psalm-param array<string, callable( * RealObjectType&AccessInterceptorInterface<RealObjectType>=, * RealObjectType=, * string=, * array<string, mixed>=, * mixed=, * bool= * ) : mixed> $suffixInterceptors * * @psalm-return RealObjectType&AccessInterceptorInterface<RealObjectType>&ValueHolderInterface<RealObjectType>&AccessInterceptorValueHolderInterface<RealObjectType> * * @throws InvalidSignatureException * @throws MissingSignatureException * @throws OutOfBoundsException * * @psalm-template RealObjectType of object * @psalm-suppress MixedInferredReturnType We ignore type checks here, since `staticProxyConstructor` is not * interfaced (by design) */ public function createProxy( $instance, array $prefixInterceptors = [], array $suffixInterceptors = [] ): AccessInterceptorValueHolderInterface { $proxyClassName = $this->generateProxy(get_class($instance)); /** * We ignore type checks here, since `staticProxyConstructor` is not interfaced (by design) * * @psalm-suppress MixedMethodCall * @psalm-suppress MixedReturnStatement */ return $proxyClassName::staticProxyConstructor($instance, $prefixInterceptors, $suffixInterceptors); } protected function getGenerator(): ProxyGeneratorInterface { return $this->generator; } } proxy-manager-lts/src/ProxyManager/Factory/LazyLoadingGhostFactory.php 0000644 00000010563 15117764663 0022257 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Factory; use Closure; use OutOfBoundsException; use ProxyManager\Configuration; use ProxyManager\Proxy\GhostObjectInterface; use ProxyManager\ProxyGenerator\LazyLoadingGhostGenerator; use ProxyManager\ProxyGenerator\ProxyGeneratorInterface; use ProxyManager\Signature\Exception\InvalidSignatureException; use ProxyManager\Signature\Exception\MissingSignatureException; /** * Factory responsible of producing ghost instances */ class LazyLoadingGhostFactory extends AbstractBaseFactory { private $generator; public function __construct(?Configuration $configuration = null) { parent::__construct($configuration); $this->generator = new LazyLoadingGhostGenerator(); } protected function getGenerator(): ProxyGeneratorInterface { return $this->generator; } /** * Creates a new lazy proxy instance of the given class with * the given initializer * * Please refer to the following documentation when using this method: * * @link https://github.com/Ocramius/ProxyManager/blob/master/docs/lazy-loading-ghost-object.md * * @param string $className name of the class to be proxied * @param Closure $initializer initializer to be passed to the proxy. The initializer closure should have following * signature: * * <code> * $initializer = function ( * GhostObjectInterface $proxy, * string $method, * array $parameters, * & $initializer, * array $properties * ) {}; * </code> * * Where: * - $proxy is the proxy instance on which the initializer is acting * - $method is the name of the method that triggered the lazy initialization * - $parameters are the parameters that were passed to $method * - $initializer by-ref initializer - should be assigned null in the initializer body * - $properties a by-ref map of the properties of the object, indexed by PHP * internal property name. Assign values to it to initialize the * object state * @param mixed[] $proxyOptions a set of options to be used when generating the proxy. Currently supports only * key "skippedProperties", which allows to skip lazy-loading of some properties. * "skippedProperties" is a string[], containing a list of properties referenced * via PHP's internal property name (i.e. "\0ClassName\0propertyName") * @psalm-param class-string<RealObjectType> $className * @psalm-param Closure( * RealObjectType&GhostObjectInterface<RealObjectType>=, * string=, * array<string, mixed>=, * ?Closure=, * array<string, mixed>= * ) : bool $initializer * @psalm-param array{skippedProperties?: array<int, string>} $proxyOptions * * @psalm-return RealObjectType&GhostObjectInterface<RealObjectType> * * @throws MissingSignatureException * @throws InvalidSignatureException * @throws OutOfBoundsException * * @psalm-template RealObjectType as object * @psalm-suppress MixedInferredReturnType We ignore type checks here, since `staticProxyConstructor` is not * interfaced (by design) */ public function createProxy( string $className, Closure $initializer, array $proxyOptions = [] ): GhostObjectInterface { $proxyClassName = $this->generateProxy($className, $proxyOptions); /** * We ignore type checks here, since `staticProxyConstructor` is not interfaced (by design) * * @psalm-suppress MixedMethodCall * @psalm-suppress MixedReturnStatement */ return $proxyClassName::staticProxyConstructor($initializer); } } proxy-manager-lts/src/ProxyManager/Factory/LazyLoadingValueHolderFactory.php 0000644 00000004100 15117764663 0023373 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Factory; use Closure; use ProxyManager\Configuration; use ProxyManager\Proxy\ValueHolderInterface; use ProxyManager\Proxy\VirtualProxyInterface; use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator; use ProxyManager\ProxyGenerator\ProxyGeneratorInterface; /** * Factory responsible of producing virtual proxy instances */ class LazyLoadingValueHolderFactory extends AbstractBaseFactory { private $generator; public function __construct(?Configuration $configuration = null) { parent::__construct($configuration); $this->generator = new LazyLoadingValueHolderGenerator(); } /** * @param array<string, mixed> $proxyOptions * @psalm-param class-string<RealObjectType> $className * @psalm-param Closure( * RealObjectType|null=, * RealObjectType&ValueHolderInterface<RealObjectType>&VirtualProxyInterface=, * string=, * array<string, mixed>=, * ?Closure= * ) : bool $initializer * @psalm-param array{skipDestructor?: bool, fluentSafe?: bool} $proxyOptions * * @psalm-return RealObjectType&ValueHolderInterface<RealObjectType>&VirtualProxyInterface * * @psalm-template RealObjectType of object * @psalm-suppress MixedInferredReturnType We ignore type checks here, since `staticProxyConstructor` is not * interfaced (by design) */ public function createProxy( string $className, Closure $initializer, array $proxyOptions = [] ): VirtualProxyInterface { $proxyClassName = $this->generateProxy($className, $proxyOptions); /** * We ignore type checks here, since `staticProxyConstructor` is not interfaced (by design) * * @psalm-suppress MixedMethodCall * @psalm-suppress MixedReturnStatement */ return $proxyClassName::staticProxyConstructor($initializer); } protected function getGenerator(): ProxyGeneratorInterface { return $this->generator; } } proxy-manager-lts/src/ProxyManager/Factory/NullObjectFactory.php 0000644 00000004035 15117764663 0021073 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Factory; use OutOfBoundsException; use ProxyManager\Configuration; use ProxyManager\Proxy\NullObjectInterface; use ProxyManager\ProxyGenerator\NullObjectGenerator; use ProxyManager\ProxyGenerator\ProxyGeneratorInterface; use ProxyManager\Signature\Exception\InvalidSignatureException; use ProxyManager\Signature\Exception\MissingSignatureException; use function get_class; use function is_object; /** * Factory responsible of producing proxy objects */ class NullObjectFactory extends AbstractBaseFactory { private $generator; public function __construct(?Configuration $configuration = null) { parent::__construct($configuration); $this->generator = new NullObjectGenerator(); } /** * @param object|string $instanceOrClassName the object to be wrapped or interface to transform to null object * @psalm-param RealObjectType|class-string<RealObjectType> $instanceOrClassName * * @psalm-return RealObjectType&NullObjectInterface * * @throws InvalidSignatureException * @throws MissingSignatureException * @throws OutOfBoundsException * * @psalm-template RealObjectType of object * @psalm-suppress MixedInferredReturnType We ignore type checks here, since `staticProxyConstructor` is not * interfaced (by design) */ public function createProxy($instanceOrClassName): NullObjectInterface { $className = is_object($instanceOrClassName) ? get_class($instanceOrClassName) : $instanceOrClassName; $proxyClassName = $this->generateProxy($className); /** * We ignore type checks here, since `staticProxyConstructor` is not interfaced (by design) * * @psalm-suppress MixedMethodCall * @psalm-suppress MixedReturnStatement */ return $proxyClassName::staticProxyConstructor(); } protected function getGenerator(): ProxyGeneratorInterface { return $this->generator; } } proxy-manager-lts/src/ProxyManager/Factory/RemoteObjectFactory.php 0000644 00000004377 15117764663 0021425 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Factory; use OutOfBoundsException; use ProxyManager\Configuration; use ProxyManager\Factory\RemoteObject\AdapterInterface; use ProxyManager\Proxy\RemoteObjectInterface; use ProxyManager\ProxyGenerator\ProxyGeneratorInterface; use ProxyManager\ProxyGenerator\RemoteObjectGenerator; use ProxyManager\Signature\Exception\InvalidSignatureException; use ProxyManager\Signature\Exception\MissingSignatureException; use function get_class; use function is_object; /** * Factory responsible of producing remote proxy objects */ class RemoteObjectFactory extends AbstractBaseFactory { protected $adapter; private $generator; /** * {@inheritDoc} * * @param AdapterInterface $adapter * @param Configuration $configuration */ public function __construct(AdapterInterface $adapter, ?Configuration $configuration = null) { parent::__construct($configuration); $this->adapter = $adapter; $this->generator = new RemoteObjectGenerator(); } /** * @psalm-param RealObjectType|class-string<RealObjectType> $instanceOrClassName * * @psalm-return RealObjectType&RemoteObjectInterface * * @throws InvalidSignatureException * @throws MissingSignatureException * @throws OutOfBoundsException * * @psalm-template RealObjectType of object * @psalm-suppress MixedInferredReturnType We ignore type checks here, since `staticProxyConstructor` is not * interfaced (by design) */ public function createProxy($instanceOrClassName): RemoteObjectInterface { $proxyClassName = $this->generateProxy( is_object($instanceOrClassName) ? get_class($instanceOrClassName) : $instanceOrClassName ); /** * We ignore type checks here, since `staticProxyConstructor` is not interfaced (by design) * * @psalm-suppress MixedMethodCall * @psalm-suppress MixedReturnStatement */ return $proxyClassName::staticProxyConstructor($this->adapter); } protected function getGenerator(): ProxyGeneratorInterface { return $this->generator ?? $this->generator = new RemoteObjectGenerator(); } } proxy-manager-lts/src/ProxyManager/FileLocator/FileLocator.php 0000644 00000001536 15117764663 0020504 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\FileLocator; use ProxyManager\Exception\InvalidProxyDirectoryException; use function realpath; use function str_replace; use const DIRECTORY_SEPARATOR; class FileLocator implements FileLocatorInterface { protected $proxiesDirectory; /** * @throws InvalidProxyDirectoryException */ public function __construct(string $proxiesDirectory) { $absolutePath = realpath($proxiesDirectory); if ($absolutePath === false) { throw InvalidProxyDirectoryException::proxyDirectoryNotFound($proxiesDirectory); } $this->proxiesDirectory = $absolutePath; } public function getProxyFileName(string $className): string { return $this->proxiesDirectory . DIRECTORY_SEPARATOR . str_replace('\\', '', $className) . '.php'; } } proxy-manager-lts/src/ProxyManager/FileLocator/FileLocatorInterface.php 0000644 00000000465 15117764663 0022325 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\FileLocator; /** * Basic autoloader utilities required to work with proxy files */ interface FileLocatorInterface { /** * Retrieves the file name for the given proxy */ public function getProxyFileName(string $className): string; } proxy-manager-lts/src/ProxyManager/Generator/Util/ClassGeneratorUtils.php 0000644 00000001343 15117764663 0022672 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Generator\Util; use Laminas\Code\Generator\ClassGenerator; use Laminas\Code\Generator\MethodGenerator; use ReflectionClass; /** * Util class to help to generate code */ final class ClassGeneratorUtils { public static function addMethodIfNotFinal( ReflectionClass $originalClass, ClassGenerator $classGenerator, MethodGenerator $generatedMethod ): bool { $methodName = $generatedMethod->getName(); if ($originalClass->hasMethod($methodName) && $originalClass->getMethod($methodName)->isFinal()) { return false; } $classGenerator->addMethodFromGenerator($generatedMethod); return true; } } proxy-manager-lts/src/ProxyManager/Generator/Util/IdentifierSuffixer.php 0000644 00000003122 15117764663 0022530 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Generator\Util; use Composer\InstalledVersions; use function class_exists; use function method_exists; use function preg_match; use function serialize; use function sha1; use function substr; /** * Utility class capable of generating * valid class/property/method identifiers * with a deterministic attached suffix, * in order to prevent property name collisions * and tampering from userland */ abstract class IdentifierSuffixer { public const VALID_IDENTIFIER_FORMAT = '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]+$/'; public const DEFAULT_IDENTIFIER = 'g'; final private function __construct() { } /** * Generates a valid unique identifier from the given name, * with a suffix attached to it */ public static function getIdentifier(string $name): string { /** @var string|null $salt */ static $salt; $salt = $salt ?? self::loadBaseHashSalt(); $suffix = substr(sha1($name . $salt), 0, 5); if (! preg_match(self::VALID_IDENTIFIER_FORMAT, $name)) { return self::DEFAULT_IDENTIFIER . $suffix; } return $name . $suffix; } private static function loadBaseHashSalt(): string { if (! class_exists(InstalledVersions::class)) { return self::class; } return sha1(serialize( method_exists(InstalledVersions::class, 'getAllRawData') ? InstalledVersions::getAllRawData() // Composer >= 2.0.14 : InstalledVersions::getRawData() )); } } proxy-manager-lts/src/ProxyManager/Generator/Util/ProxiedMethodReturnExpression.php 0000644 00000001773 15117764663 0024777 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Generator\Util; use ReflectionMethod; use ReflectionNamedType; /** * Utility class to generate return expressions in method, given a method signature. * * This is required since return expressions may be forbidden by the method signature (void). */ final class ProxiedMethodReturnExpression { public static function generate(string $returnedValueExpression, ?ReflectionMethod $originalMethod): string { $originalReturnType = $originalMethod === null ? null : $originalMethod->getReturnType(); if ($originalReturnType instanceof ReflectionNamedType && $originalReturnType->getName() === 'void') { return $returnedValueExpression . ";\nreturn;"; } if ($originalReturnType instanceof ReflectionNamedType && $originalReturnType->getName() === 'never') { return $returnedValueExpression . ';'; } return 'return ' . $returnedValueExpression . ';'; } } proxy-manager-lts/src/ProxyManager/Generator/Util/UniqueIdentifierGenerator.php 0000644 00000001767 15117764663 0024067 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Generator\Util; use function preg_match; use function str_replace; use function uniqid; /** * Utility class capable of generating unique * valid class/property/method identifiers */ abstract class UniqueIdentifierGenerator { public const VALID_IDENTIFIER_FORMAT = '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]+$/'; public const DEFAULT_IDENTIFIER = 'g'; /** * Generates a valid unique identifier from the given name * * @psalm-return class-string * * @psalm-suppress MoreSpecificReturnType */ public static function getIdentifier(string $name): string { /** * @psalm-suppress LessSpecificReturnStatement */ return str_replace( '.', '', uniqid( preg_match(self::VALID_IDENTIFIER_FORMAT, $name) ? $name : self::DEFAULT_IDENTIFIER, true ) ); } } proxy-manager-lts/src/ProxyManager/Generator/ClassGenerator.php 0000644 00000001100 15117764663 0020723 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Generator; use Laminas\Code\Generator\ClassGenerator as LaminasClassGenerator; /** * Class generator that ensures that interfaces/classes that are implemented/extended are FQCNs * * @internal do not use this in your code: it is only here for internal use * @deprecated this class was in use due to parent implementation not receiving prompt bugfixes, but * `laminas/laminas-code` is actively maintained and receives quick release iterations. */ class ClassGenerator extends LaminasClassGenerator { } proxy-manager-lts/src/ProxyManager/Generator/MagicMethodGenerator.php 0000644 00000004172 15117764663 0022053 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Generator; use Laminas\Code\Generator\MethodGenerator as LaminasMethodGenerator; use Laminas\Code\Generator\ParameterGenerator; use LogicException; use ReflectionClass; use ReflectionIntersectionType; use ReflectionNamedType; use ReflectionUnionType; use function get_class; use function implode; use function strtolower; /** * Method generator for magic methods */ class MagicMethodGenerator extends MethodGenerator { /** * @param ParameterGenerator[]|array[]|string[] $parameters */ public function __construct(ReflectionClass $originalClass, string $name, array $parameters = []) { parent::__construct( $name, $parameters, self::FLAG_PUBLIC ); $this->setReturnsReference(strtolower($name) === '__get'); if (! $originalClass->hasMethod($name)) { return; } $originalMethod = $originalClass->getMethod($name); $originalReturnType = $originalMethod->getReturnType(); $this->setReturnsReference($originalMethod->returnsReference()); if ($originalReturnType instanceof ReflectionNamedType) { $this->setReturnType(($originalReturnType->allowsNull() && $originalReturnType->getName() !== 'mixed' ? '?' : '') . $originalReturnType->getName()); } elseif ($originalReturnType instanceof ReflectionUnionType || $originalReturnType instanceof ReflectionIntersectionType) { $returnType = []; foreach ($originalReturnType->getTypes() as $type) { $returnType[] = $type->getName(); } $this->setReturnType(implode($originalReturnType instanceof ReflectionIntersectionType ? '&' : '|', $returnType)); } elseif ($originalReturnType) { throw new LogicException('Unexpected ' . get_class($type)); } } public function setBody($body): LaminasMethodGenerator { if ((string) $this->getReturnType() === 'void') { $body = preg_replace('/return ([^;]++;)/', '\1 return;', $body); } return parent::setBody($body); } } proxy-manager-lts/src/ProxyManager/Generator/MethodGenerator.php 0000644 00000007562 15117764663 0021120 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Generator; use Laminas\Code\Generator\DocBlockGenerator; use Laminas\Code\Generator\MethodGenerator as LaminasMethodGenerator; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Reflection\MethodReflection; use ReflectionException; use ReflectionMethod; use ReflectionParameter; /** * Method generator that fixes minor quirks in ZF2's method generator */ class MethodGenerator extends LaminasMethodGenerator { protected $hasTentativeReturnType = false; /** * @return static */ public static function fromReflectionWithoutBodyAndDocBlock(MethodReflection $reflectionMethod): self { /** @var static $method */ $method = static::copyMethodSignature($reflectionMethod); $method->setInterface(false); $method->setBody(''); if (\PHP_VERSION_ID < 80100) { return $method; } /** @var callable(ReflectionMethod) : ReflectionMethod $getPrototype */ $getPrototype = \Closure::fromCallable([new ReflectionMethod(ReflectionMethod::class, 'getPrototype'), 'invoke']); while (true) { if ($reflectionMethod->hasTentativeReturnType()) { $method->hasTentativeReturnType = true; break; } if ($reflectionMethod->isAbstract()) { break; } try { $reflectionMethod = $getPrototype($reflectionMethod); } catch (ReflectionException $e) { break; } } return $method; } public static function copyMethodSignature(MethodReflection $reflectionMethod): parent { $method = parent::copyMethodSignature($reflectionMethod); foreach ($reflectionMethod->getParameters() as $reflectionParameter) { $parameter = ParameterGenerator::fromReflection($reflectionParameter); $default = $parameter->getDefaultValue(); if ($default !== null) { $parameter->setDefaultValue(new ValueGenerator($default, $reflectionParameter)); } $method->setParameter($parameter); } return $method; } public function getDocBlock(): ?DocBlockGenerator { $docBlock = parent::getDocBlock(); if (! $this->hasTentativeReturnType) { return $docBlock; } if ($docBlock === null) { return new class ($this->getIndentation()) extends DocBlockGenerator { public function __construct(string $indentation) { $this->setIndentation($indentation); } public function generate(): string { return $this->getIndentation() . '#[\ReturnTypeWillChange]' . self::LINE_FEED; } }; } return new class ($docBlock) extends DocBlockGenerator { public function __construct(DocBlockGenerator $docBlock) { $this->setShortDescription($docBlock->getShortDescription()); $this->setLongDescription($docBlock->getLongDescription()); $this->setTags($docBlock->getTags()); $this->setWordWrap($docBlock->getWordWrap()); $this->setSourceDirty($docBlock->isSourceDirty()); $this->setIndentation($docBlock->getIndentation()); $this->setSourceContent($docBlock->getSourceContent()); } public function generate(): string { return parent::generate() . $this->getIndentation() . '#[\ReturnTypeWillChange]' . self::LINE_FEED; } }; } /** * {@inheritDoc} override needed to specify type in more detail */ public function getSourceContent(): ?string { return parent::getSourceContent(); } } proxy-manager-lts/src/ProxyManager/Generator/ValueGenerator.php 0000644 00000011031 15117764663 0020736 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Generator; use Laminas\Code\Generator\Exception\RuntimeException; use Laminas\Code\Generator\ValueGenerator as LaminasValueGenerator; use ReflectionParameter; use function explode; use function implode; use function in_array; use function preg_replace; use function preg_split; use function rtrim; use function substr; use function var_export; use const PREG_SPLIT_DELIM_CAPTURE; use const PREG_SPLIT_NO_EMPTY; /** * @internal do not use this in your code: it is only here for internal use */ class ValueGenerator extends LaminasValueGenerator { private $reflection; public function __construct($value, ?ReflectionParameter $reflection = null) { if ($value instanceof LaminasValueGenerator) { $this->value = $value->value; $this->type = $value->type; $this->arrayDepth = $value->arrayDepth; $this->outputMode = $value->outputMode; $this->allowedTypes = $value->allowedTypes; $this->constants = $value->constants; $this->isSourceDirty = $value->isSourceDirty; $this->indentation = $value->indentation; $this->sourceContent = $value->sourceContent; } else { parent::__construct($value, parent::TYPE_AUTO, parent::OUTPUT_SINGLE_LINE); } $this->reflection = $reflection; } public function generate(): string { try { return parent::generate(); } catch (RuntimeException $e) { if ($this->reflection) { $value = self::exportDefault($this->reflection); } else { $value = var_export($this->value, true); if (\PHP_VERSION_ID < 80200) { return self::fixVarExport($value); } } return $value; } } private static function fixVarExport(string $value): string { $parts = preg_split('{(\'(?:[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')}', $value, -1, PREG_SPLIT_DELIM_CAPTURE); foreach ($parts as $i => &$part) { if ($part === '' || $i % 2 !== 0) { continue; } $part = preg_replace('/(?(DEFINE)(?<V>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))(?<!\\\\)(?&V)(?:\\\\(?&V))*+::/', '\\\\$0', $part); } return implode('', $parts); } private static function exportDefault(\ReflectionParameter $param): string { $default = rtrim(substr(explode('$'.$param->name.' = ', (string) $param, 2)[1] ?? '', 0, -2)); if (in_array($default, ['<default>', 'NULL'], true)) { return 'null'; } if (str_ends_with($default, "...'") && preg_match("/^'(?:[^'\\\\]*+(?:\\\\.)*+)*+'$/", $default)) { return var_export($param->getDefaultValue(), true); } $regexp = "/(\"(?:[^\"\\\\]*+(?:\\\\.)*+)*+\"|'(?:[^'\\\\]*+(?:\\\\.)*+)*+')/"; $parts = preg_split($regexp, $default, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); $regexp = '/([\[\( ]|^)([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z0-9_\x7f-\xff]++)*+)(?!: )/'; $callback = (false !== strpbrk($default, "\\:('") && $class = $param->getDeclaringClass()) ? function ($m) use ($class) { switch ($m[2]) { case 'new': case 'false': case 'true': case 'null': return $m[1].$m[2]; case 'NULL': return $m[1].'null'; case 'self': return $m[1].'\\'.$class->name; case 'namespace\\parent': case 'parent': $m[1].(($parent = $class->getParentClass()) ? '\\'.$parent->name : 'parent'); default: return $m[1].'\\'.$m[2]; } } : function ($m) { switch ($m[2]) { case 'new': case 'false': case 'true': case 'null': return $m[1].$m[2]; case 'NULL': return $m[1].'null'; default: return $m[1].'\\'.$m[2]; } }; return implode('', array_map(function ($part) use ($regexp, $callback) { switch ($part[0]) { case '"': return $part; // for internal classes only case "'": return false !== strpbrk($part, "\\\0\r\n") ? '"'.substr(str_replace(['$', "\0", "\r", "\n"], ['\$', '\0', '\r', '\n'], $part), 1, -1).'"' : $part; default: return preg_replace_callback($regexp, $callback, $part); } }, $parts)); } } proxy-manager-lts/src/ProxyManager/GeneratorStrategy/BaseGeneratorStrategy.php 0000644 00000001102 15117764663 0024000 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\GeneratorStrategy; use Laminas\Code\Generator\ClassGenerator; /** * Generator strategy that generates the class body */ class BaseGeneratorStrategy implements GeneratorStrategyInterface { /** * {@inheritDoc} * * @psalm-suppress MixedInferredReturnType upstream has no declared type */ public function generate(ClassGenerator $classGenerator): string { /** @psalm-suppress MixedReturnStatement upstream has no declared type */ return $classGenerator->generate(); } } proxy-manager-lts/src/ProxyManager/GeneratorStrategy/EvaluatingGeneratorStrategy.php 0000644 00000002520 15117764663 0025232 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\GeneratorStrategy; use Laminas\Code\Generator\ClassGenerator; use Symfony\Component\Filesystem\Filesystem; use function ini_get; use function unlink; /** * Generator strategy that produces the code and evaluates it at runtime */ class EvaluatingGeneratorStrategy implements GeneratorStrategyInterface { /** @var bool flag indicating whether {@see eval} can be used */ private $canEval = true; /** * Constructor */ public function __construct() { // @codeCoverageIgnoreStart $this->canEval = ! ini_get('suhosin.executor.disable_eval'); // @codeCoverageIgnoreEnd } /** * Evaluates the generated code before returning it * * {@inheritDoc} */ public function generate(ClassGenerator $classGenerator): string { $code = $classGenerator->generate(); // @codeCoverageIgnoreStart if (! $this->canEval) { $fileName = __DIR__ . '/EvaluatingGeneratorStrategy.php.tmp'; (new Filesystem())->dumpFile($fileName, "<?php\n" . $code); /* @noinspection PhpIncludeInspection */ require $fileName; unlink($fileName); return $code; } // @codeCoverageIgnoreEnd eval($code); return $code; } } proxy-manager-lts/src/ProxyManager/GeneratorStrategy/FileWriterGeneratorStrategy.php 0000644 00000002602 15117764663 0025210 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\GeneratorStrategy; use Laminas\Code\Generator\ClassGenerator; use ProxyManager\Exception\FileNotWritableException; use ProxyManager\FileLocator\FileLocatorInterface; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; /** * Generator strategy that writes the generated classes to disk while generating them * * {@inheritDoc} */ class FileWriterGeneratorStrategy implements GeneratorStrategyInterface { protected $fileLocator; private $emptyErrorHandler; public function __construct(FileLocatorInterface $fileLocator) { $this->fileLocator = $fileLocator; } /** * Write generated code to disk and return the class code * * {@inheritDoc} * * @throws FileNotWritableException */ public function generate(ClassGenerator $classGenerator): string { $generatedCode = $classGenerator->generate(); $className = (string) $classGenerator->getNamespaceName() . '\\' . $classGenerator->getName(); $fileName = $this->fileLocator->getProxyFileName($className); try { (new Filesystem())->dumpFile($fileName, "<?php\n\n" . $generatedCode); return $generatedCode; } catch (IOException $e) { throw FileNotWritableException::fromPrevious($e); } } } proxy-manager-lts/src/ProxyManager/GeneratorStrategy/GeneratorStrategyInterface.php 0000644 00000000652 15117764663 0025037 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\GeneratorStrategy; use Laminas\Code\Generator\ClassGenerator; class_exists(\Zend\Code\Generator\ClassGenerator::class); /** * Generator strategy interface - defines basic behavior of class generators */ interface GeneratorStrategyInterface { /** * Generate the provided class */ public function generate(ClassGenerator $classGenerator): string; } proxy-manager-lts/src/ProxyManager/Inflector/Util/ParameterEncoder.php 0000644 00000000772 15117764663 0022161 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Inflector\Util; use function base64_encode; use function serialize; /** * Encodes parameters into a class-name safe string */ class ParameterEncoder { /** * Converts the given parameters into a set of characters that are safe to * use in a class name * * @param mixed[] $parameters */ public function encodeParameters(array $parameters): string { return base64_encode(serialize($parameters)); } } proxy-manager-lts/src/ProxyManager/Inflector/Util/ParameterHasher.php 0000644 00000000673 15117764663 0022014 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Inflector\Util; use function md5; use function serialize; /** * Converts given parameters into a likely unique hash */ class ParameterHasher { /** * Converts the given parameters into a likely-unique hash * * @param mixed[] $parameters */ public function hashParameters(array $parameters): string { return md5(serialize($parameters)); } } proxy-manager-lts/src/ProxyManager/Inflector/ClassNameInflector.php 0000644 00000004230 15117764663 0021531 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Inflector; use ProxyManager\Inflector\Util\ParameterHasher; use function is_int; use function ltrim; use function strlen; use function strrpos; use function substr; final class ClassNameInflector implements ClassNameInflectorInterface { private $proxyNamespace; /** @var int @TODO annotation still needed for phpstan to understand this */ private $proxyMarkerLength; private $proxyMarker; private $parameterHasher; public function __construct(string $proxyNamespace) { $this->proxyNamespace = $proxyNamespace; $this->proxyMarker = '\\' . self::PROXY_MARKER . '\\'; $this->proxyMarkerLength = strlen($this->proxyMarker); $this->parameterHasher = new ParameterHasher(); } /** * {@inheritDoc} * * @psalm-suppress MoreSpecificReturnType we ignore these issues because classes may not have been loaded yet */ public function getUserClassName(string $className): string { $className = ltrim($className, '\\'); $position = strrpos($className, $this->proxyMarker); if (! is_int($position)) { /** @psalm-suppress LessSpecificReturnStatement */ return $className; } /** @psalm-suppress LessSpecificReturnStatement */ return substr( $className, $this->proxyMarkerLength + $position, (int) strrpos($className, '\\') - ($position + $this->proxyMarkerLength) ); } /** * {@inheritDoc} * * @psalm-suppress MoreSpecificReturnType we ignore these issues because classes may not have been loaded yet */ public function getProxyClassName(string $className, array $options = []): string { /** @psalm-suppress LessSpecificReturnStatement */ return $this->proxyNamespace . $this->proxyMarker . $this->getUserClassName($className) . '\\Generated' . $this->parameterHasher->hashParameters($options); } public function isProxyClassName(string $className): bool { return strrpos($className, $this->proxyMarker) !== false; } } proxy-manager-lts/src/ProxyManager/Inflector/ClassNameInflectorInterface.php 0000644 00000003037 15117764663 0023356 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Inflector; use ProxyManager\Proxy\ProxyInterface; /** * Interface for a proxy- to user-class and user- to proxy-class name inflector */ interface ClassNameInflectorInterface { /** * Marker for proxy classes - classes containing this marker are considered proxies */ public const PROXY_MARKER = '__PM__'; /** * Retrieve the class name of a user-defined class * * @psalm-param class-string<RealClassName>|class-string<ProxyInterface<RealClassName>> $className * * @psalm-return class-string<RealClassName> * * @psalm-template RealClassName of object */ public function getUserClassName(string $className): string; /** * Retrieve the class name of the proxy for the given user-defined class name * * @param array<string, mixed> $options arbitrary options to be used for the generated class name * @psalm-param class-string<RealClassName>|class-string<ProxyInterface<RealClassName>> $className * * @psalm-return class-string<RealClassName&ProxyInterface> * * @psalm-template RealClassName of object */ public function getProxyClassName(string $className, array $options = []): string; /** * Retrieve whether the provided class name is a proxy * * @psalm-param class-string<RealClassName>|class-string<ProxyInterface<RealClassName>> $className * * @psalm-template RealClassName of object */ public function isProxyClassName(string $className): bool; } proxy-manager-lts/src/ProxyManager/Proxy/Exception/RemoteObjectException.php 0000644 00000000423 15117764663 0023410 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Proxy\Exception; use RuntimeException; /** * Remote object exception * * @deprecated this exception is not in use anymore, and should not be relied upon */ class RemoteObjectException extends RuntimeException { } proxy-manager-lts/src/ProxyManager/Proxy/AccessInterceptorInterface.php 0000644 00000004142 15117764663 0022454 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Proxy; use Closure; /** * Access interceptor object marker * * @psalm-template InterceptedObjectType of object */ interface AccessInterceptorInterface extends ProxyInterface { /** * Set or remove the prefix interceptor for a method * * @link https://github.com/Ocramius/ProxyManager/blob/master/docs/access-interceptor-value-holder.md * * A prefix interceptor should have a signature like following: * * <code> * $interceptor = function ($proxy, $instance, string $method, array $params, & $returnEarly) {}; * </code> * * @param string $methodName name of the intercepted method * @param Closure|null $prefixInterceptor interceptor closure or null to unset the currently active interceptor * @psalm-param null|Closure( * InterceptedObjectType&AccessInterceptorInterface=, * InterceptedObjectType=, * string=, * array<string, mixed>=, * bool= * ) : mixed $prefixInterceptor */ public function setMethodPrefixInterceptor(string $methodName, ?Closure $prefixInterceptor = null): void; /** * Set or remove the suffix interceptor for a method * * @link https://github.com/Ocramius/ProxyManager/blob/master/docs/access-interceptor-value-holder.md * * A prefix interceptor should have a signature like following: * * <code> * $interceptor = function ($proxy, $instance, string $method, array $params, $returnValue, & $returnEarly) {}; * </code> * * @param string $methodName name of the intercepted method * @param Closure|null $suffixInterceptor interceptor closure or null to unset the currently active interceptor * @psalm-param null|Closure( * InterceptedObjectType&AccessInterceptorInterface=, * InterceptedObjectType=, * string=, * array<string, mixed>=, * mixed=, * bool= * ) : mixed $suffixInterceptor */ public function setMethodSuffixInterceptor(string $methodName, ?Closure $suffixInterceptor = null): void; } proxy-manager-lts/src/ProxyManager/Proxy/AccessInterceptorValueHolderInterface.php 0000644 00000003320 15117764663 0024604 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Proxy; use Closure; /** * Aggregates AccessInterceptor and ValueHolderInterface, mostly for return type hinting * * @psalm-template InterceptedObjectType of object */ interface AccessInterceptorValueHolderInterface extends AccessInterceptorInterface, ValueHolderInterface { /** * {@inheritDoc} * * Definitions are duplicated here to allow templated definitions in this child type * * @psalm-param null|Closure( * InterceptedObjectType&AccessInterceptorInterface=, * InterceptedObjectType=, * string=, * array<string, mixed>=, * bool= * ) : mixed $prefixInterceptor */ public function setMethodPrefixInterceptor(string $methodName, ?Closure $prefixInterceptor = null): void; /** * {@inheritDoc} * * Definitions are duplicated here to allow templated definitions in this child type * * @param string $methodName name of the intercepted method * @param Closure|null $suffixInterceptor interceptor closure or null to unset the currently active interceptor * @psalm-param null|Closure( * InterceptedObjectType&AccessInterceptorInterface=, * InterceptedObjectType=, * string=, * array<string, mixed>=, * mixed=, * bool= * ) : mixed $suffixInterceptor */ public function setMethodSuffixInterceptor(string $methodName, ?Closure $suffixInterceptor = null): void; /** * {@inheritDoc} * * Definitions are duplicated here to allow templated definitions in this child type * * @psalm-return InterceptedObjectType|null */ public function getWrappedValueHolderValue(); } proxy-manager-lts/src/ProxyManager/Proxy/FallbackValueHolderInterface.php 0000644 00000000407 15117764663 0022666 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Proxy; /** * Fallback value holder object marker * * @deprecated this interface is not in use anymore, and should not be relied upon */ interface FallbackValueHolderInterface extends ProxyInterface { } proxy-manager-lts/src/ProxyManager/Proxy/GhostObjectInterface.php 0000644 00000003011 15117764663 0021241 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Proxy; use Closure; /** * Ghost object marker * * @psalm-template LazilyLoadedObjectType of object */ interface GhostObjectInterface extends LazyLoadingInterface { /** * {@inheritDoc} * * Definitions are duplicated here to allow templated definitions in this child type. * * @psalm-param null|Closure( * LazilyLoadedObjectType&GhostObjectInterface<LazilyLoadedObjectType>=, * string=, * array<string, mixed>=, * ?Closure=, * array<string, mixed>= * ) : bool $initializer * * @psalm-suppress ImplementedParamTypeMismatch Note that the closure signature below is slightly different * from the one declared in LazyLoadingInterface. */ public function setProxyInitializer(?Closure $initializer = null); /** * {@inheritDoc} * * Definitions are duplicated here to allow templated definitions in this child type * * @psalm-return null|Closure( * LazilyLoadedObjectType&GhostObjectInterface<LazilyLoadedObjectType>=, * string, * array<string, mixed>=, * ?Closure=, * array<string, mixed>= * ) : bool * * @psalm-suppress ImplementedReturnTypeMismatch Note that the closure signature below is slightly different * from the one declared in LazyLoadingInterface. */ public function getProxyInitializer(): ?Closure; } proxy-manager-lts/src/ProxyManager/Proxy/LazyLoadingInterface.php 0000644 00000003772 15117764663 0021261 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Proxy; use Closure; /** * Lazy loading object identifier * * @psalm-template LazilyLoadedObjectType of object */ interface LazyLoadingInterface extends ProxyInterface { /** * Set or unset the initializer for the proxy instance * * @link https://github.com/Ocramius/ProxyManager/blob/master/docs/lazy-loading-value-holder.md#lazy-initialization * * An initializer should have a signature like following: * * <code> * $initializer = function ( * & ?object $wrappedObject, * LazyLoadingInterface $proxy, * string $calledMethod, * array $callParameters, * & ?\Closure $initializer, * array $propertiesToBeSet = [] // works only on ghost objects * ) {}; * </code> * * @psalm-param null|Closure( * LazilyLoadedObjectType|null=, * LazilyLoadedObjectType&LazyLoadingInterface<LazilyLoadedObjectType>=, * string=, * array<string, mixed>=, * ?Closure=, * array<string, mixed>= * ) : bool $initializer * * Due to BC compliance, we cannot add a native `: void` return type declaration here * * phpcs:disable SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint * * @return void */ public function setProxyInitializer(?Closure $initializer = null); /** * @psalm-return null|Closure( * LazilyLoadedObjectType|null=, * LazilyLoadedObjectType&LazyLoadingInterface<LazilyLoadedObjectType>=, * string, * array<string, mixed>=, * ?Closure=, * array<string, mixed>= * ) : bool */ public function getProxyInitializer(): ?Closure; /** * Force initialization of the proxy * * @return bool true if the proxy could be initialized */ public function initializeProxy(): bool; /** * Retrieves current initialization status of the proxy */ public function isProxyInitialized(): bool; } proxy-manager-lts/src/ProxyManager/Proxy/NullObjectInterface.php 0000644 00000000227 15117764663 0021075 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Proxy; /** * Null object marker */ interface NullObjectInterface extends ProxyInterface { } proxy-manager-lts/src/ProxyManager/Proxy/ProxyInterface.php 0000644 00000000255 15117764663 0020156 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Proxy; /** * Base proxy marker * * @psalm-template DecoratedClassName of object */ interface ProxyInterface { } proxy-manager-lts/src/ProxyManager/Proxy/RemoteObjectInterface.php 0000644 00000000233 15117764663 0021413 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Proxy; /** * Remote object marker */ interface RemoteObjectInterface extends ProxyInterface { } proxy-manager-lts/src/ProxyManager/Proxy/SmartReferenceInterface.php 0000644 00000000374 15117764663 0021744 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Proxy; /** * Smart reference object marker * * @deprecated this interface is not in use anymore, and should not be relied upon */ interface SmartReferenceInterface extends ProxyInterface { } proxy-manager-lts/src/ProxyManager/Proxy/ValueHolderInterface.php 0000644 00000000560 15117764663 0021246 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Proxy; /** * Value holder marker * * @psalm-template WrappedValueHolderType of object */ interface ValueHolderInterface extends ProxyInterface { /** * @return object|null the wrapped value * @psalm-return WrappedValueHolderType|null */ public function getWrappedValueHolderValue(); } proxy-manager-lts/src/ProxyManager/Proxy/VirtualProxyInterface.php 0000644 00000000361 15117764663 0021523 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Proxy; /** * Virtual Proxy - a lazy initializing object wrapping around the proxied subject */ interface VirtualProxyInterface extends LazyLoadingInterface, ValueHolderInterface { } proxy-manager-lts/src/ProxyManager/ProxyGenerator/AccessInterceptor/MethodGenerator/MagicWakeup.php 0000644 00000001336 15117764663 0027770 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptor\MethodGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\Util\Properties; use ProxyManager\ProxyGenerator\Util\UnsetPropertiesGenerator; use ReflectionClass; /** * Magic `__wakeup` for lazy loading value holder objects */ class MagicWakeup extends MagicMethodGenerator { /** * Constructor */ public function __construct(ReflectionClass $originalClass) { parent::__construct($originalClass, '__wakeup'); $this->setBody(UnsetPropertiesGenerator::generateSnippet( Properties::fromReflectionClass($originalClass), 'this' )); } } src/ProxyManager/ProxyGenerator/AccessInterceptor/MethodGenerator/SetMethodPrefixInterceptor.php 0000644 00000002232 15117764663 0033001 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptor\MethodGenerator; use Closure; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; /** * Implementation for {@see \ProxyManager\Proxy\AccessInterceptorInterface::setMethodPrefixInterceptor} * for access interceptor objects */ class SetMethodPrefixInterceptor extends MethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(PropertyGenerator $prefixInterceptor) { parent::__construct('setMethodPrefixInterceptor'); $interceptor = new ParameterGenerator('prefixInterceptor'); $interceptor->setType(Closure::class); $interceptor->setDefaultValue(null); $this->setParameter(new ParameterGenerator('methodName', 'string')); $this->setParameter($interceptor); $this->setReturnType('void'); $this->setBody('$this->' . $prefixInterceptor->getName() . '[$methodName] = $prefixInterceptor;'); } } src/ProxyManager/ProxyGenerator/AccessInterceptor/MethodGenerator/SetMethodSuffixInterceptor.php 0000644 00000002232 15117764663 0033010 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptor\MethodGenerator; use Closure; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; /** * Implementation for {@see \ProxyManager\Proxy\AccessInterceptorInterface::setMethodSuffixInterceptor} * for access interceptor objects */ class SetMethodSuffixInterceptor extends MethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(PropertyGenerator $suffixInterceptor) { parent::__construct('setMethodSuffixInterceptor'); $interceptor = new ParameterGenerator('suffixInterceptor'); $interceptor->setType(Closure::class); $interceptor->setDefaultValue(null); $this->setParameter(new ParameterGenerator('methodName', 'string')); $this->setParameter($interceptor); $this->setReturnType('void'); $this->setBody('$this->' . $suffixInterceptor->getName() . '[$methodName] = $suffixInterceptor;'); } } src/ProxyManager/ProxyGenerator/AccessInterceptor/PropertyGenerator/MethodPrefixInterceptors.php 0000644 00000001532 15117764663 0033116 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptor\PropertyGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\Util\IdentifierSuffixer; /** * Property that contains the interceptor for operations to be executed before method execution */ class MethodPrefixInterceptors extends PropertyGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct() { parent::__construct(IdentifierSuffixer::getIdentifier('methodPrefixInterceptors')); $this->setDefaultValue([]); $this->setVisibility(self::VISIBILITY_PRIVATE); $this->setDocBlock('@var \\Closure[] map of interceptors to be called per-method before execution'); } } src/ProxyManager/ProxyGenerator/AccessInterceptor/PropertyGenerator/MethodSuffixInterceptors.php 0000644 00000001530 15117764663 0033123 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptor\PropertyGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\Util\IdentifierSuffixer; /** * Property that contains the interceptor for operations to be executed after method execution */ class MethodSuffixInterceptors extends PropertyGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct() { parent::__construct(IdentifierSuffixer::getIdentifier('methodSuffixInterceptors')); $this->setDefaultValue([]); $this->setVisibility(self::VISIBILITY_PRIVATE); $this->setDocBlock('@var \\Closure[] map of interceptors to be called per-method after execution'); } } ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/Util/InterceptorGenerator.php 0000644 00000006223 15117764663 0035435 0 ustar 00 proxy-manager-lts/src/ProxyManager <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\Util; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; use ProxyManager\Generator\Util\ProxiedMethodReturnExpression; use ReflectionMethod; use function array_keys; use function array_map; use function implode; use function str_replace; use function var_export; /** * Utility to create pre- and post- method interceptors around a given method body * * @private - this class is just here as a small utility for this component, don't use it in your own code */ class InterceptorGenerator { private const TEMPLATE = <<<'PHP' if (isset($this->{{$prefixInterceptorsName}}[{{$name}}])) { $returnEarly = false; $prefixReturnValue = $this->{{$prefixInterceptorsName}}[{{$name}}]->__invoke($this, $this, {{$name}}, {{$paramsString}}, $returnEarly); if ($returnEarly) { {{$prefixEarlyReturnExpression}} } } {{$methodBody}} if (isset($this->{{$suffixInterceptorsName}}[{{$name}}])) { $returnEarly = false; $suffixReturnValue = $this->{{$suffixInterceptorsName}}[{{$name}}]->__invoke($this, $this, {{$name}}, {{$paramsString}}, $returnValue, $returnEarly); if ($returnEarly) { {{$suffixEarlyReturnExpression}} } } {{$returnExpression}} PHP; /** * @param string $methodBody the body of the previously generated code. * It MUST assign the return value to a variable * `$returnValue` instead of directly returning */ public static function createInterceptedMethodBody( string $methodBody, MethodGenerator $method, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors, ?ReflectionMethod $originalMethod ): string { $replacements = [ '{{$name}}' => var_export($method->getName(), true), '{{$prefixInterceptorsName}}' => $prefixInterceptors->getName(), '{{$prefixEarlyReturnExpression}}' => ProxiedMethodReturnExpression::generate('$prefixReturnValue', $originalMethod), '{{$methodBody}}' => $methodBody, '{{$suffixInterceptorsName}}' => $suffixInterceptors->getName(), '{{$suffixEarlyReturnExpression}}' => ProxiedMethodReturnExpression::generate('$suffixReturnValue', $originalMethod), '{{$returnExpression}}' => ProxiedMethodReturnExpression::generate('$returnValue', $originalMethod), '{{$paramsString}}' => 'array(' . implode(', ', array_map( static function (ParameterGenerator $parameter): string { return var_export($parameter->getName(), true) . ' => ' . ($parameter->getPassedByReference() ? '&$' : '$') . $parameter->getName(); }, $method->getParameters() )) . ')', ]; return str_replace( array_keys($replacements), $replacements, self::TEMPLATE ); } } ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/BindProxyProperties.php 0000644 00000006003 15117764663 0034342 0 ustar 00 proxy-manager-lts/src <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Exception\UnsupportedProxiedClassException; use ProxyManager\Generator\MethodGenerator; use ProxyManager\ProxyGenerator\Util\Properties; use ReflectionClass; use function implode; use function var_export; /** * The `bindProxyProperties` method implementation for access interceptor scope localizers */ class BindProxyProperties extends MethodGenerator { /** * Constructor */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors ) { parent::__construct( 'bindProxyProperties', [ new ParameterGenerator('localizedObject', $originalClass->getName()), new ParameterGenerator('prefixInterceptors', 'array', []), new ParameterGenerator('suffixInterceptors', 'array', []), ], self::FLAG_PRIVATE, null, "@override constructor to setup interceptors\n\n" . '@param \\' . $originalClass->getName() . " \$localizedObject\n" . "@param \\Closure[] \$prefixInterceptors method interceptors to be used before method logic\n" . '@param \\Closure[] $suffixInterceptors method interceptors to be used before method logic' ); $localizedProperties = []; $properties = Properties::fromReflectionClass($originalClass); $nonReferenceableProperties = $properties ->onlyNonReferenceableProperties() ->onlyInstanceProperties(); if (! $nonReferenceableProperties->empty()) { throw UnsupportedProxiedClassException::nonReferenceableLocalizedReflectionProperties( $originalClass, $nonReferenceableProperties ); } foreach ($properties->getAccessibleProperties() as $property) { $propertyName = $property->getName(); $localizedProperties[] = '$this->' . $propertyName . ' = & $localizedObject->' . $propertyName . ';'; } foreach ($properties->getPrivateProperties() as $property) { $propertyName = $property->getName(); $localizedProperties[] = "\\Closure::bind(function () use (\$localizedObject) {\n " . '$this->' . $propertyName . ' = & $localizedObject->' . $propertyName . ";\n" . '}, $this, ' . var_export($property->getDeclaringClass()->getName(), true) . ')->__invoke();'; } $this->setBody( ($localizedProperties ? implode("\n\n", $localizedProperties) . "\n\n" : '') . '$this->' . $prefixInterceptors->getName() . " = \$prefixInterceptors;\n" . '$this->' . $suffixInterceptors->getName() . ' = $suffixInterceptors;' ); } } ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/InterceptedMethod.php 0000644 00000002727 15117764663 0033767 0 ustar 00 proxy-manager-lts/src <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use Laminas\Code\Reflection\MethodReflection; use ProxyManager\Generator\MethodGenerator; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\Util\InterceptorGenerator; use function implode; /** * Method with additional pre- and post- interceptor logic in the body */ class InterceptedMethod extends MethodGenerator { /** * @throws InvalidArgumentException */ public static function generateMethod( MethodReflection $originalMethod, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors ): self { $method = static::fromReflectionWithoutBodyAndDocBlock($originalMethod); $forwardedParams = []; foreach ($originalMethod->getParameters() as $parameter) { $forwardedParams[] = ($parameter->isVariadic() ? '...' : '') . '$' . $parameter->getName(); } $method->setBody(InterceptorGenerator::createInterceptedMethodBody( '$returnValue = parent::' . $originalMethod->getName() . '(' . implode(', ', $forwardedParams) . ');', $method, $prefixInterceptors, $suffixInterceptors, $originalMethod )); return $method; } } src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicClone.php 0000644 00000002146 15117764663 0032354 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\Util\InterceptorGenerator; use ProxyManager\ProxyGenerator\Util\GetMethodIfExists; use ReflectionClass; /** * Magic `__clone` for lazy loading ghost objects */ class MagicClone extends MagicMethodGenerator { /** * Constructor */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors ) { parent::__construct($originalClass, '__clone'); $parent = GetMethodIfExists::get($originalClass, '__clone'); $this->setBody(InterceptorGenerator::createInterceptedMethodBody( $parent ? '$returnValue = parent::__clone();' : '$returnValue = null;', $this, $prefixInterceptors, $suffixInterceptors, $parent )); } } src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicGet.php 0000644 00000003134 15117764664 0032032 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\Util\InterceptorGenerator; use ProxyManager\ProxyGenerator\Util\GetMethodIfExists; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; /** * Magic `__get` for lazy loading ghost objects */ class MagicGet extends MagicMethodGenerator { /** * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors ) { parent::__construct($originalClass, '__get', [new ParameterGenerator('name')]); $parent = GetMethodIfExists::get($originalClass, '__get'); $callParent = '$returnValue = & parent::__get($name);'; if (! $parent) { $callParent = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_GET, 'name', null, null, 'returnValue', $originalClass ); } $this->setBody(InterceptorGenerator::createInterceptedMethodBody( $callParent, $this, $prefixInterceptors, $suffixInterceptors, $parent )); } } src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicIsset.php 0000644 00000003157 15117764664 0032407 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\Util\InterceptorGenerator; use ProxyManager\ProxyGenerator\Util\GetMethodIfExists; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; /** * Magic `__isset` method for lazy loading ghost objects */ class MagicIsset extends MagicMethodGenerator { /** * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors ) { parent::__construct($originalClass, '__isset', [new ParameterGenerator('name')]); $parent = GetMethodIfExists::get($originalClass, '__isset'); $callParent = '$returnValue = & parent::__isset($name);'; if (! $parent) { $callParent = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_ISSET, 'name', null, null, 'returnValue', $originalClass ); } $this->setBody(InterceptorGenerator::createInterceptedMethodBody( $callParent, $this, $prefixInterceptors, $suffixInterceptors, $parent )); } } src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicSet.php 0000644 00000003266 15117764664 0032054 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\Util\InterceptorGenerator; use ProxyManager\ProxyGenerator\Util\GetMethodIfExists; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; /** * Magic `__set` for lazy loading ghost objects */ class MagicSet extends MagicMethodGenerator { /** * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors ) { parent::__construct( $originalClass, '__set', [new ParameterGenerator('name'), new ParameterGenerator('value')] ); $parent = GetMethodIfExists::get($originalClass, '__set'); $callParent = '$returnValue = & parent::__set($name, $value);'; if (! $parent) { $callParent = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_SET, 'name', 'value', null, 'returnValue', $originalClass ); } $this->setBody(InterceptorGenerator::createInterceptedMethodBody( $callParent, $this, $prefixInterceptors, $suffixInterceptors, $parent )); } } src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicSleep.php 0000644 00000002241 15117764664 0032361 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\Util\InterceptorGenerator; use ProxyManager\ProxyGenerator\Util\GetMethodIfExists; use ReflectionClass; /** * Magic `__sleep` for lazy loading ghost objects */ class MagicSleep extends MagicMethodGenerator { /** * Constructor */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors ) { parent::__construct($originalClass, '__sleep'); $parent = GetMethodIfExists::get($originalClass, '__sleep'); $callParent = $parent ? '$returnValue = & parent::__sleep();' : '$returnValue = array_keys((array) $this);'; $this->setBody(InterceptorGenerator::createInterceptedMethodBody( $callParent, $this, $prefixInterceptors, $suffixInterceptors, $parent )); } } src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicUnset.php 0000644 00000003157 15117764664 0032416 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\Util\InterceptorGenerator; use ProxyManager\ProxyGenerator\Util\GetMethodIfExists; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; /** * Magic `__unset` method for lazy loading ghost objects */ class MagicUnset extends MagicMethodGenerator { /** * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors ) { parent::__construct($originalClass, '__unset', [new ParameterGenerator('name')]); $parent = GetMethodIfExists::get($originalClass, '__unset'); $callParent = '$returnValue = & parent::__unset($name);'; if (! $parent) { $callParent = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_UNSET, 'name', null, null, 'returnValue', $originalClass ); } $this->setBody(InterceptorGenerator::createInterceptedMethodBody( $callParent, $this, $prefixInterceptors, $suffixInterceptors, $parent )); } } ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/StaticProxyConstructor.php 0000644 00000004133 15117764664 0035111 0 ustar 00 proxy-manager-lts/src/ProxyManager <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use ProxyManager\Generator\MethodGenerator; use ReflectionClass; /** * The `staticProxyConstructor` implementation for an access interceptor scope localizer proxy */ class StaticProxyConstructor extends MethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(ReflectionClass $originalClass) { parent::__construct('staticProxyConstructor', [], self::FLAG_PUBLIC | self::FLAG_STATIC); $localizedObject = new ParameterGenerator('localizedObject'); $prefix = new ParameterGenerator('prefixInterceptors'); $suffix = new ParameterGenerator('suffixInterceptors'); $localizedObject->setType($originalClass->getName()); $prefix->setDefaultValue([]); $suffix->setDefaultValue([]); $prefix->setType('array'); $suffix->setType('array'); $this->setParameter($localizedObject); $this->setParameter($prefix); $this->setParameter($suffix); $this->setReturnType($originalClass->getName()); $this->setDocBlock( "Constructor to setup interceptors\n\n" . '@param \\' . $originalClass->getName() . " \$localizedObject\n" . "@param \\Closure[] \$prefixInterceptors method interceptors to be used before method logic\n" . "@param \\Closure[] \$suffixInterceptors method interceptors to be used before method logic\n\n" . '@return self' ); $this->setBody( 'static $reflection;' . "\n\n" . '$reflection = $reflection ?? new \ReflectionClass(__CLASS__);' . "\n" . '$instance = $reflection->newInstanceWithoutConstructor();' . "\n\n" . '$instance->bindProxyProperties($localizedObject, $prefixInterceptors, $suffixInterceptors);' . "\n\n" . 'return $instance;' ); } } ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/Util/InterceptorGenerator.php 0000644 00000006560 15117764664 0034736 0 ustar 00 proxy-manager-lts/src/ProxyManager <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\Util; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; use ProxyManager\Generator\Util\ProxiedMethodReturnExpression; use ReflectionMethod; use function array_keys; use function implode; use function str_replace; use function var_export; /** * Utility to create pre- and post- method interceptors around a given method body * * @private - this class is just here as a small utility for this component, don't use it in your own code */ class InterceptorGenerator { private const TEMPLATE = <<<'PHP' if (isset($this->{{$prefixInterceptorsName}}[{{$name}}])) { $returnEarly = false; $prefixReturnValue = $this->{{$prefixInterceptorsName}}[{{$name}}]->__invoke($this, $this->{{$valueHolderName}}, {{$name}}, {{$paramsString}}, $returnEarly); if ($returnEarly) { {{$returnEarlyPrefixExpression}} } } {{$methodBody}} if (isset($this->{{$suffixInterceptorsName}}[{{$name}}])) { $returnEarly = false; $suffixReturnValue = $this->{{$suffixInterceptorsName}}[{{$name}}]->__invoke($this, $this->{{$valueHolderName}}, {{$name}}, {{$paramsString}}, $returnValue, $returnEarly); if ($returnEarly) { {{$returnEarlySuffixExpression}} } } {{$returnExpression}} PHP; /** * @param string $methodBody the body of the previously generated code. * It MUST assign the return value to a variable * `$returnValue` instead of directly returning */ public static function createInterceptedMethodBody( string $methodBody, MethodGenerator $method, PropertyGenerator $valueHolder, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors, ?ReflectionMethod $originalMethod ): string { $name = var_export($method->getName(), true); $valueHolderName = $valueHolder->getName(); $prefixInterceptorsName = $prefixInterceptors->getName(); $suffixInterceptorsName = $suffixInterceptors->getName(); $params = []; foreach ($method->getParameters() as $parameter) { $parameterName = $parameter->getName(); $symbol = $parameter->getPassedByReference() ? '&$' : '$'; $params[] = var_export($parameterName, true) . ' => ' . $symbol . $parameterName; } $paramsString = 'array(' . implode(', ', $params) . ')'; $replacements = [ '{{$prefixInterceptorsName}}' => $prefixInterceptorsName, '{{$name}}' => $name, '{{$valueHolderName}}' => $valueHolderName, '{{$paramsString}}' => $paramsString, '{{$returnEarlyPrefixExpression}}' => ProxiedMethodReturnExpression::generate('$prefixReturnValue', $originalMethod), '{{$methodBody}}' => $methodBody, '{{$suffixInterceptorsName}}' => $suffixInterceptorsName, '{{$returnEarlySuffixExpression}}' => ProxiedMethodReturnExpression::generate('$suffixReturnValue', $originalMethod), '{{$returnExpression}}' => ProxiedMethodReturnExpression::generate('$returnValue', $originalMethod), ]; return str_replace(array_keys($replacements), $replacements, self::TEMPLATE); } } src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/InterceptedMethod.php 0000644 00000003113 15117764664 0033252 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use Laminas\Code\Reflection\MethodReflection; use ProxyManager\Generator\MethodGenerator; use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\Util\InterceptorGenerator; use function implode; /** * Method with additional pre- and post- interceptor logic in the body */ class InterceptedMethod extends MethodGenerator { /** * @throws InvalidArgumentException */ public static function generateMethod( MethodReflection $originalMethod, PropertyGenerator $valueHolderProperty, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors ): self { $method = static::fromReflectionWithoutBodyAndDocBlock($originalMethod); $forwardedParams = []; foreach ($originalMethod->getParameters() as $parameter) { $forwardedParams[] = ($parameter->isVariadic() ? '...' : '') . '$' . $parameter->getName(); } $method->setBody(InterceptorGenerator::createInterceptedMethodBody( '$returnValue = $this->' . $valueHolderProperty->getName() . '->' . $originalMethod->getName() . '(' . implode(', ', $forwardedParams) . ');', $method, $valueHolderProperty, $prefixInterceptors, $suffixInterceptors, $originalMethod )); return $method; } } src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicClone.php 0000644 00000002717 15117764664 0031655 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ReflectionClass; use function array_keys; use function str_replace; /** * Magic `__clone` for lazy loading value holder objects */ class MagicClone extends MagicMethodGenerator { private const TEMPLATE = <<<'PHP' $this->{{$valueHolder}} = clone $this->{{$valueHolder}}; foreach ($this->{{$prefix}} as $key => $value) { $this->{{$prefix}}[$key] = clone $value; } foreach ($this->{{$suffix}} as $key => $value) { $this->{{$suffix}}[$key] = clone $value; } PHP; /** * Constructor */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $valueHolderProperty, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors ) { parent::__construct($originalClass, '__clone'); $valueHolder = $valueHolderProperty->getName(); $prefix = $prefixInterceptors->getName(); $suffix = $suffixInterceptors->getName(); $replacements = [ '{{$valueHolder}}' => $valueHolder, '{{$prefix}}' => $prefix, '{{$suffix}}' => $suffix, ]; $this->setBody(str_replace( array_keys($replacements), $replacements, self::TEMPLATE )); } } src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicGet.php 0000644 00000004040 15117764664 0031323 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\Util\InterceptorGenerator; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\GetMethodIfExists; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; /** * Magic `__get` for method interceptor value holder objects */ class MagicGet extends MagicMethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $valueHolder, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors, PublicPropertiesMap $publicProperties ) { parent::__construct($originalClass, '__get', [new ParameterGenerator('name')]); $parent = GetMethodIfExists::get($originalClass, '__get'); $valueHolderName = $valueHolder->getName(); $callParent = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_GET, 'name', null, $valueHolder, 'returnValue', $originalClass ); if (! $publicProperties->isEmpty()) { $callParent = 'if (isset(self::$' . $publicProperties->getName() . "[\$name])) {\n" . ' $returnValue = & $this->' . $valueHolderName . '->$name;' . "\n} else {\n " . $callParent . "\n}\n\n"; } $this->setBody(InterceptorGenerator::createInterceptedMethodBody( $callParent, $this, $valueHolder, $prefixInterceptors, $suffixInterceptors, $parent )); } } src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicIsset.php 0000644 00000004057 15117764664 0031703 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\Util\InterceptorGenerator; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\GetMethodIfExists; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; /** * Magic `__isset` for method interceptor value holder objects */ class MagicIsset extends MagicMethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $valueHolder, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors, PublicPropertiesMap $publicProperties ) { parent::__construct($originalClass, '__isset', [new ParameterGenerator('name')]); $parent = GetMethodIfExists::get($originalClass, '__isset'); $valueHolderName = $valueHolder->getName(); $callParent = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_ISSET, 'name', null, $valueHolder, 'returnValue', $originalClass ); if (! $publicProperties->isEmpty()) { $callParent = 'if (isset(self::$' . $publicProperties->getName() . "[\$name])) {\n" . ' $returnValue = isset($this->' . $valueHolderName . '->$name);' . "\n} else {\n " . $callParent . "\n}\n\n"; } $this->setBody(InterceptorGenerator::createInterceptedMethodBody( $callParent, $this, $valueHolder, $prefixInterceptors, $suffixInterceptors, $parent )); } } src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicSet.php 0000644 00000004173 15117764664 0031346 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\Util\InterceptorGenerator; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\GetMethodIfExists; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; /** * Magic `__set` for method interceptor value holder objects */ class MagicSet extends MagicMethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $valueHolder, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors, PublicPropertiesMap $publicProperties ) { parent::__construct( $originalClass, '__set', [new ParameterGenerator('name'), new ParameterGenerator('value')] ); $parent = GetMethodIfExists::get($originalClass, '__set'); $valueHolderName = $valueHolder->getName(); $callParent = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_SET, 'name', 'value', $valueHolder, 'returnValue', $originalClass ); if (! $publicProperties->isEmpty()) { $callParent = 'if (isset(self::$' . $publicProperties->getName() . "[\$name])) {\n" . ' $returnValue = ($this->' . $valueHolderName . '->$name = $value);' . "\n} else {\n " . $callParent . "\n}\n\n"; } $this->setBody(InterceptorGenerator::createInterceptedMethodBody( $callParent, $this, $valueHolder, $prefixInterceptors, $suffixInterceptors, $parent )); } } src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicUnset.php 0000644 00000004121 15117764664 0031702 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\Util\InterceptorGenerator; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\GetMethodIfExists; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; /** * Magic `__unset` for method interceptor value holder objects */ class MagicUnset extends MagicMethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $valueHolder, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors, PublicPropertiesMap $publicProperties ) { parent::__construct($originalClass, '__unset', [new ParameterGenerator('name')]); $parent = GetMethodIfExists::get($originalClass, '__unset'); $valueHolderName = $valueHolder->getName(); $callParent = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_UNSET, 'name', null, $valueHolder, 'returnValue', $originalClass ); if (! $publicProperties->isEmpty()) { $callParent = 'if (isset(self::$' . $publicProperties->getName() . "[\$name])) {\n" . ' unset($this->' . $valueHolderName . '->$name);' . "\n} else {\n " . $callParent . "\n}\n\n"; } $callParent .= '$returnValue = false;'; $this->setBody(InterceptorGenerator::createInterceptedMethodBody( $callParent, $this, $valueHolder, $prefixInterceptors, $suffixInterceptors, $parent )); } } ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/StaticProxyConstructor.php 0000644 00000005005 15117764664 0034404 0 ustar 00 proxy-manager-lts/src <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; use ProxyManager\ProxyGenerator\Util\Properties; use ProxyManager\ProxyGenerator\Util\UnsetPropertiesGenerator; use ReflectionClass; /** * The `staticProxyConstructor` implementation for access interceptor value holders */ class StaticProxyConstructor extends MethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $valueHolder, PropertyGenerator $prefixInterceptors, PropertyGenerator $suffixInterceptors ) { parent::__construct('staticProxyConstructor', [], self::FLAG_PUBLIC | self::FLAG_STATIC); $prefix = new ParameterGenerator('prefixInterceptors'); $suffix = new ParameterGenerator('suffixInterceptors'); $prefix->setDefaultValue([]); $suffix->setDefaultValue([]); $prefix->setType('array'); $suffix->setType('array'); $this->setParameter(new ParameterGenerator('wrappedObject')); $this->setParameter($prefix); $this->setParameter($suffix); $this->setReturnType($originalClass->getName()); $this->setDocBlock( "Constructor to setup interceptors\n\n" . '@param \\' . $originalClass->getName() . " \$wrappedObject\n" . "@param \\Closure[] \$prefixInterceptors method interceptors to be used before method logic\n" . "@param \\Closure[] \$suffixInterceptors method interceptors to be used before method logic\n\n" . '@return self' ); $this->setBody( 'static $reflection;' . "\n\n" . '$reflection = $reflection ?? new \ReflectionClass(__CLASS__);' . "\n" . '$instance = $reflection->newInstanceWithoutConstructor();' . "\n\n" . UnsetPropertiesGenerator::generateSnippet(Properties::fromReflectionClass($originalClass), 'instance') . '$instance->' . $valueHolder->getName() . " = \$wrappedObject;\n" . '$instance->' . $prefixInterceptors->getName() . " = \$prefixInterceptors;\n" . '$instance->' . $suffixInterceptors->getName() . " = \$suffixInterceptors;\n\n" . 'return $instance;' ); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/Assertion/CanProxyAssertion.php 0000644 00000004113 15117764664 0024463 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\Assertion; use BadMethodCallException; use ProxyManager\Exception\InvalidProxiedClassException; use ReflectionClass; use ReflectionMethod; use function array_filter; /** * Assertion that verifies that a class can be proxied */ final class CanProxyAssertion { /** * Disabled constructor: not meant to be instantiated * * @throws BadMethodCallException */ public function __construct() { throw new BadMethodCallException('Unsupported constructor.'); } /** * @throws InvalidProxiedClassException */ public static function assertClassCanBeProxied(ReflectionClass $originalClass, bool $allowInterfaces = true): void { self::isNotFinal($originalClass); self::hasNoAbstractProtectedMethods($originalClass); if ($allowInterfaces) { return; } self::isNotInterface($originalClass); } /** * @throws InvalidProxiedClassException */ private static function isNotFinal(ReflectionClass $originalClass): void { if ($originalClass->isFinal()) { throw InvalidProxiedClassException::finalClassNotSupported($originalClass); } } /** * @throws InvalidProxiedClassException */ private static function hasNoAbstractProtectedMethods(ReflectionClass $originalClass): void { $protectedAbstract = array_filter( $originalClass->getMethods(), static function (ReflectionMethod $method): bool { return $method->isAbstract() && $method->isProtected(); } ); if ($protectedAbstract) { throw InvalidProxiedClassException::abstractProtectedMethodsNotSupported($originalClass); } } /** * @throws InvalidProxiedClassException */ private static function isNotInterface(ReflectionClass $originalClass): void { if ($originalClass->isInterface()) { throw InvalidProxiedClassException::interfaceNotSupported($originalClass); } } } src/ProxyManager/ProxyGenerator/LazyLoading/MethodGenerator/StaticProxyConstructor.php 0000644 00000002705 15117764664 0031052 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoading\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; use ProxyManager\ProxyGenerator\Util\Properties; use ProxyManager\ProxyGenerator\Util\UnsetPropertiesGenerator; /** * The `staticProxyConstructor` implementation for lazy loading proxies */ class StaticProxyConstructor extends MethodGenerator { /** * Static constructor * * @throws InvalidArgumentException */ public function __construct(PropertyGenerator $initializerProperty, Properties $properties) { parent::__construct('staticProxyConstructor', [], self::FLAG_PUBLIC | self::FLAG_STATIC); $this->setParameter(new ParameterGenerator('initializer')); $this->setDocBlock("Constructor for lazy initialization\n\n@param \\Closure|null \$initializer"); $this->setBody( 'static $reflection;' . "\n\n" . '$reflection = $reflection ?? new \ReflectionClass(__CLASS__);' . "\n" . '$instance = $reflection->newInstanceWithoutConstructor();' . "\n\n" . UnsetPropertiesGenerator::generateSnippet($properties, 'instance') . '$instance->' . $initializerProperty->getName() . ' = $initializer;' . "\n\n" . 'return $instance;' ); } } src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/CallInitializer.php 0000644 00000023606 15117764664 0030402 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use LogicException; use ProxyManager\Generator\MethodGenerator; use ProxyManager\Generator\Util\IdentifierSuffixer; use ProxyManager\Generator\ValueGenerator; use ProxyManager\ProxyGenerator\Util\Properties; use ReflectionIntersectionType; use ReflectionNamedType; use ReflectionProperty; use ReflectionType; use ReflectionUnionType; use function array_map; use function assert; use function get_class; use function implode; use function sprintf; use function str_replace; use function var_export; /** * Implementation for {@see \ProxyManager\Proxy\LazyLoadingInterface::isProxyInitialized} * for lazy loading value holder objects */ class CallInitializer extends MethodGenerator { public function __construct( PropertyGenerator $initializerProperty, PropertyGenerator $initTracker, Properties $properties ) { $docBlock = <<<'DOCBLOCK' Triggers initialization logic for this ghost object @param string $methodName @param mixed[] $parameters @return mixed DOCBLOCK; parent::__construct( IdentifierSuffixer::getIdentifier('callInitializer'), [ new ParameterGenerator('methodName'), new ParameterGenerator('parameters', 'array'), ], self::FLAG_PRIVATE, null, $docBlock ); $initializer = $initializerProperty->getName(); $initialization = $initTracker->getName(); $bodyTemplate = <<<'PHP' if ($this->%s || ! $this->%s) { return; } $this->%s = true; %s %s $result = $this->%s->__invoke($this, $methodName, $parameters, $this->%s, $properties); %s$this->%s = false; return $result; PHP; $referenceableProperties = $properties->withoutNonReferenceableProperties(); $nonReferenceableProperties = $properties->onlyNonReferenceableProperties(); $this->setBody(sprintf( $bodyTemplate, $initialization, $initializer, $initialization, $this->propertiesInitializationCode($referenceableProperties), $this->propertiesReferenceArrayCode($referenceableProperties, $nonReferenceableProperties), $initializer, $initializer, $this->propertiesNonReferenceableCode($nonReferenceableProperties), $initialization )); } private function propertiesInitializationCode(Properties $properties): string { $scopedPropertyGroups = []; $nonScopedProperties = []; foreach ($properties->getInstanceProperties() as $property) { if ($property->isPrivate() || (\PHP_VERSION_ID >= 80100 && $property->isReadOnly())) { $scopedPropertyGroups[$property->getDeclaringClass()->getName()][$property->getName()] = $property; } else { $nonScopedProperties[] = $property; } } $assignments = []; foreach ($nonScopedProperties as $property) { $assignments[] = '$this->' . $property->getName() . ' = ' . $this->getExportedPropertyDefaultValue($property) . ';'; } foreach ($scopedPropertyGroups as $className => $scopedProperties) { $cacheKey = 'cache' . str_replace('\\', '_', $className); $assignments[] = 'static $' . $cacheKey . ";\n\n" . '$' . $cacheKey . ' ?? $' . $cacheKey . " = \\Closure::bind(static function (\$instance) {\n" . $this->getPropertyDefaultsAssignments($scopedProperties) . "\n" . '}, null, ' . var_export($className, true) . ");\n\n" . '$' . $cacheKey . "(\$this);\n\n"; } return implode("\n", $assignments) . "\n\n"; } /** * @param ReflectionProperty[] $properties */ private function getPropertyDefaultsAssignments(array $properties): string { return implode( "\n", array_map( function (ReflectionProperty $property): string { return ' $instance->' . $property->getName() . ' = ' . $this->getExportedPropertyDefaultValue($property) . ';'; }, $properties ) ); } private function propertiesReferenceArrayCode(Properties $properties, Properties $nonReferenceableProperties): string { $assignments = []; $nonReferenceablePropertiesDefinition = ''; foreach ($properties->getAccessibleProperties() as $propertyInternalName => $property) { $assignments[] = ' ' . var_export($propertyInternalName, true) . ' => & $this->' . $property->getName() . ','; } foreach ($nonReferenceableProperties->getInstanceProperties() as $propertyInternalName => $property) { $propertyAlias = $property->getName() . ($property->isPrivate() ? '_on_' . str_replace('\\', '_', $property->getDeclaringClass()->getName()) : ''); $propertyType = $property->getType(); assert($propertyType !== null); $nonReferenceablePropertiesDefinition .= sprintf(" public %s $%s;\n", self::getReferenceableType($propertyType), $propertyAlias); $assignments[] = sprintf(' %s => & $nonReferenceableProperties->%s,', var_export($propertyInternalName, true), $propertyAlias); } $code = $nonReferenceableProperties->empty() ? '' : sprintf("\$nonReferenceableProperties = new class() {\n%s};\n", $nonReferenceablePropertiesDefinition); $code .= "\$properties = [\n" . implode("\n", $assignments) . "\n];\n\n"; // must use assignments, as direct reference during array definition causes a fatal error (not sure why) foreach ($properties->getGroupedPrivateProperties() as $className => $classPrivateProperties) { $cacheKey = 'cacheFetch' . str_replace('\\', '_', $className); $code .= 'static $' . $cacheKey . ";\n\n" . '$' . $cacheKey . ' ?? $' . $cacheKey . " = \\Closure::bind(function (\$instance, array & \$properties) {\n" . $this->generatePrivatePropertiesAssignmentsCode($classPrivateProperties) . '}, null, ' . var_export($className, true) . ");\n\n" . '$' . $cacheKey . '($this, $properties);'; } return $code; } /** * @param array<string, ReflectionProperty> $properties indexed by internal name */ private function generatePrivatePropertiesAssignmentsCode(array $properties): string { $code = ''; foreach ($properties as $property) { $key = "\0" . $property->getDeclaringClass()->getName() . "\0" . $property->getName(); $code .= ' $properties[' . var_export($key, true) . '] = ' . '& $instance->' . $property->getName() . ";\n"; } return $code; } private function getExportedPropertyDefaultValue(ReflectionProperty $property): string { $name = $property->getName(); $defaults = $property->getDeclaringClass()->getDefaultProperties(); return (new ValueGenerator($defaults[$name] ?? null))->generate(); } private function propertiesNonReferenceableCode(Properties $properties): string { if ($properties->empty()) { return ''; } $code = []; $scopedPropertyGroups = []; foreach ($properties->getInstanceProperties() as $propertyInternalName => $property) { if (! $property->isPrivate() && (\PHP_VERSION_ID < 80100 || ! $property->isReadOnly())) { $propertyAlias = $property->getName() . ($property->isPrivate() ? '_on_' . str_replace('\\', '_', $property->getDeclaringClass()->getName()) : ''); $code[] = sprintf('isset($nonReferenceableProperties->%s) && $this->%s = $nonReferenceableProperties->%1$s;', $propertyAlias, $property->getName()); } else { $scopedPropertyGroups[$property->getDeclaringClass()->getName()][$propertyInternalName] = $property; } } foreach ($scopedPropertyGroups as $className => $scopedProperties) { $cacheKey = 'cacheAssign' . str_replace('\\', '_', $className); $code[] = 'static $' . $cacheKey . ";\n"; $code[] = '$' . $cacheKey . ' ?? $' . $cacheKey . ' = \Closure::bind(function ($instance, $nonReferenceableProperties) {'; foreach ($scopedProperties as $property) { $propertyAlias = $property->getName() . ($property->isPrivate() ? '_on_' . str_replace('\\', '_', $property->getDeclaringClass()->getName()) : ''); $code[] = sprintf(' isset($nonReferenceableProperties->%s) && $instance->%s = $nonReferenceableProperties->%1$s;', $propertyAlias, $property->getName()); } $code[] = '}, null, ' . var_export($className, true) . ");\n"; $code[] = '$' . $cacheKey . '($this, $nonReferenceableProperties);'; } return implode("\n", $code) . "\n"; } private static function getReferenceableType(ReflectionType $type): string { if ($type instanceof ReflectionNamedType) { return '?' . ($type->isBuiltin() ? '' : '\\') . $type->getName(); } if ($type instanceof ReflectionIntersectionType) { return self::getReferenceableType($type->getTypes()[0]); } if (! $type instanceof ReflectionUnionType) { throw new LogicException('Unexpected ' . get_class($type)); } $union = 'null'; foreach ($type->getTypes() as $subType) { $union .= '|' . ($subType->isBuiltin() ? '' : '\\') . $subType->getName(); } return $union; } } src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/GetProxyInitializer.php 0000644 00000001436 15117764664 0031305 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; /** * Implementation for {@see \ProxyManager\Proxy\LazyLoadingInterface::getProxyInitializer} * for lazy loading value holder objects */ class GetProxyInitializer extends MethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(PropertyGenerator $initializerProperty) { parent::__construct('getProxyInitializer'); $this->setReturnType('?\\Closure'); $this->setBody('return $this->' . $initializerProperty->getName() . ';'); } } src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/InitializeProxy.php 0000644 00000001736 15117764664 0030466 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\MethodGenerator as LaminasMethodGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; /** * Implementation for {@see \ProxyManager\Proxy\LazyLoadingInterface::initializeProxy} * for lazy loading ghost objects */ class InitializeProxy extends MethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(PropertyGenerator $initializerProperty, LaminasMethodGenerator $callInitializer) { parent::__construct('initializeProxy'); $this->setReturnType('bool'); $this->setBody( 'return $this->' . $initializerProperty->getName() . ' && $this->' . $callInitializer->getName() . '(\'initializeProxy\', []);' ); } } src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/IsProxyInitialized.php 0000644 00000001427 15117764664 0031123 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; /** * Implementation for {@see \ProxyManager\Proxy\LazyLoadingInterface::isProxyInitialized} * for lazy loading value holder objects */ class IsProxyInitialized extends MethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(PropertyGenerator $initializerProperty) { parent::__construct('isProxyInitialized'); $this->setReturnType('bool'); $this->setBody('return ! $this->' . $initializerProperty->getName() . ';'); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/MagicClone.php 0000644 00000001604 15117764664 0027375 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator; use Laminas\Code\Generator\MethodGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ReflectionClass; /** * Magic `__clone` for lazy loading ghost objects */ class MagicClone extends MagicMethodGenerator { /** * Constructor */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $initializerProperty, MethodGenerator $callInitializer ) { parent::__construct($originalClass, '__clone'); $this->setBody( '$this->' . $initializerProperty->getName() . ' && $this->' . $callInitializer->getName() . '(\'__clone\', []);' . ($originalClass->hasMethod('__clone') ? "\n\nparent::__clone();" : '') ); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/MagicGet.php 0000644 00000011347 15117764664 0027061 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\MethodGenerator; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\InitializationTracker; use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\PrivatePropertiesMap; use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\ProtectedPropertiesMap; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; use function implode; use function sprintf; /** * Magic `__get` for lazy loading ghost objects */ class MagicGet extends MagicMethodGenerator { private $callParentTemplate = <<<'PHP' $this->%s && ! $this->%s && $this->%s('__get', array('name' => $name)); if (isset(self::$%s[$name])) { return $this->$name; } if (isset(self::$%s[$name])) { if ($this->%s) { return $this->$name; } // check protected property access via compatible class $callers = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT, 2); $caller = isset($callers[1]) ? $callers[1] : []; $object = isset($caller['object']) ? $caller['object'] : ''; $expectedType = self::$%s[$name]; if ($object instanceof $expectedType) { return $this->$name; } $class = isset($caller['class']) ? $caller['class'] : ''; if ($class === $expectedType || is_subclass_of($class, $expectedType) || $class === 'ReflectionProperty') { return $this->$name; } } elseif (isset(self::$%s[$name])) { // check private property access via same class $callers = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT, 2); $caller = isset($callers[1]) ? $callers[1] : []; $class = isset($caller['class']) ? $caller['class'] : ''; static $accessorCache = []; if (isset(self::$%s[$name][$class])) { $cacheKey = $class . '#' . $name; $accessor = isset($accessorCache[$cacheKey]) ? $accessorCache[$cacheKey] : $accessorCache[$cacheKey] = \Closure::bind(static function & ($instance) use ($name) { %s }, null, $class); return $accessor($this); } if ($this->%s || 'ReflectionProperty' === $class) { $tmpClass = key(self::$%s[$name]); $cacheKey = $tmpClass . '#' . $name; $accessor = isset($accessorCache[$cacheKey]) ? $accessorCache[$cacheKey] : $accessorCache[$cacheKey] = \Closure::bind(static function & ($instance) use ($name) { %s }, null, $tmpClass); return $accessor($this); } } %s PHP; /** * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $initializerProperty, MethodGenerator $callInitializer, PublicPropertiesMap $publicProperties, ProtectedPropertiesMap $protectedProperties, PrivatePropertiesMap $privateProperties, InitializationTracker $initializationTracker ) { parent::__construct($originalClass, '__get', [new ParameterGenerator('name')]); $override = $originalClass->hasMethod('__get'); $parentAccess = 'return parent::__get($name);'; if (! $override) { $parentAccess = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_GET, 'name' ); } $readOnlyPropertyNames = $privateProperties->getReadOnlyPropertyNames(); if ($readOnlyPropertyNames) { $privateReturnCode = sprintf('\in_array($name, [\'%s\'], true) ? $value = $instance->$name : $value = & $instance->$name;', implode("', '", $readOnlyPropertyNames)); $privateReturnCode .= "\n\n return \$value;"; } else { $privateReturnCode = 'return $instance->$name;'; } $this->setBody(sprintf( $this->callParentTemplate, $initializerProperty->getName(), $initializationTracker->getName(), $callInitializer->getName(), $publicProperties->getName(), $protectedProperties->getName(), $initializationTracker->getName(), $protectedProperties->getName(), $privateProperties->getName(), $privateProperties->getName(), $privateReturnCode, $initializationTracker->getName(), $privateProperties->getName(), $privateReturnCode, $parentAccess )); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/MagicIsset.php 0000644 00000007531 15117764664 0027431 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\MethodGenerator; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\PrivatePropertiesMap; use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\ProtectedPropertiesMap; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; use function sprintf; /** * Magic `__isset` method for lazy loading ghost objects */ class MagicIsset extends MagicMethodGenerator { private $callParentTemplate = <<<'PHP' %s if (isset(self::$%s[$name])) { return isset($this->$name); } if (isset(self::$%s[$name])) { // check protected property access via compatible class $callers = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT, 2); $caller = isset($callers[1]) ? $callers[1] : []; $object = isset($caller['object']) ? $caller['object'] : ''; $expectedType = self::$%s[$name]; if ($object instanceof $expectedType) { return isset($this->$name); } $class = isset($caller['class']) ? $caller['class'] : ''; if ($class === $expectedType || is_subclass_of($class, $expectedType)) { return isset($this->$name); } } else { // check private property access via same class $callers = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT, 2); $caller = isset($callers[1]) ? $callers[1] : []; $class = isset($caller['class']) ? $caller['class'] : ''; static $accessorCache = []; if (isset(self::$%s[$name][$class])) { $cacheKey = $class . '#' . $name; $accessor = isset($accessorCache[$cacheKey]) ? $accessorCache[$cacheKey] : $accessorCache[$cacheKey] = \Closure::bind(static function ($instance) use ($name) { return isset($instance->$name); }, null, $class); return $accessor($this); } if ('ReflectionProperty' === $class) { $tmpClass = key(self::$%s[$name]); $cacheKey = $tmpClass . '#' . $name; $accessor = isset($accessorCache[$cacheKey]) ? $accessorCache[$cacheKey] : $accessorCache[$cacheKey] = \Closure::bind(static function ($instance) use ($name) { return isset($instance->$name); }, null, $tmpClass); return $accessor($this); } } %s PHP; /** * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $initializerProperty, MethodGenerator $callInitializer, PublicPropertiesMap $publicProperties, ProtectedPropertiesMap $protectedProperties, PrivatePropertiesMap $privateProperties ) { parent::__construct($originalClass, '__isset', [new ParameterGenerator('name')]); $override = $originalClass->hasMethod('__isset'); $parentAccess = 'return parent::__isset($name);'; if (! $override) { $parentAccess = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_ISSET, 'name' ); } $this->setBody(sprintf( $this->callParentTemplate, '$this->' . $initializerProperty->getName() . ' && $this->' . $callInitializer->getName() . '(\'__isset\', array(\'name\' => $name));', $publicProperties->getName(), $protectedProperties->getName(), $protectedProperties->getName(), $privateProperties->getName(), $privateProperties->getName(), $parentAccess )); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/MagicSet.php 0000644 00000010147 15117764664 0027072 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\MethodGenerator; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\PrivatePropertiesMap; use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\ProtectedPropertiesMap; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; use function sprintf; /** * Magic `__set` for lazy loading ghost objects */ class MagicSet extends MagicMethodGenerator { private $callParentTemplate = <<<'PHP' %s if (isset(self::$%s[$name])) { return ($this->$name = $value); } if (isset(self::$%s[$name])) { // check protected property access via compatible class $callers = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT, 2); $caller = isset($callers[1]) ? $callers[1] : []; $object = isset($caller['object']) ? $caller['object'] : ''; $expectedType = self::$%s[$name]; if ($object instanceof $expectedType) { return ($this->$name = $value); } $class = isset($caller['class']) ? $caller['class'] : ''; if ($class === $expectedType || is_subclass_of($class, $expectedType) || $class === 'ReflectionProperty') { return ($this->$name = $value); } } elseif (isset(self::$%s[$name])) { // check private property access via same class $callers = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT, 2); $caller = isset($callers[1]) ? $callers[1] : []; $class = isset($caller['class']) ? $caller['class'] : ''; static $accessorCache = []; if (isset(self::$%s[$name][$class])) { $cacheKey = $class . '#' . $name; $accessor = isset($accessorCache[$cacheKey]) ? $accessorCache[$cacheKey] : $accessorCache[$cacheKey] = \Closure::bind(static function ($instance, $value) use ($name) { return ($instance->$name = $value); }, null, $class); return $accessor($this, $value); } if ('ReflectionProperty' === $class) { $tmpClass = key(self::$%s[$name]); $cacheKey = $tmpClass . '#' . $name; $accessor = isset($accessorCache[$cacheKey]) ? $accessorCache[$cacheKey] : $accessorCache[$cacheKey] = \Closure::bind(static function ($instance, $value) use ($name) { return ($instance->$name = $value); }, null, $tmpClass); return $accessor($this, $value); } } %s PHP; /** * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $initializerProperty, MethodGenerator $callInitializer, PublicPropertiesMap $publicProperties, ProtectedPropertiesMap $protectedProperties, PrivatePropertiesMap $privateProperties ) { parent::__construct( $originalClass, '__set', [new ParameterGenerator('name'), new ParameterGenerator('value')] ); $override = $originalClass->hasMethod('__set'); $parentAccess = 'return parent::__set($name, $value);'; if (! $override) { $parentAccess = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_SET, 'name', 'value' ); } $this->setBody(sprintf( $this->callParentTemplate, '$this->' . $initializerProperty->getName() . ' && $this->' . $callInitializer->getName() . '(\'__set\', array(\'name\' => $name, \'value\' => $value));', $publicProperties->getName(), $protectedProperties->getName(), $protectedProperties->getName(), $privateProperties->getName(), $privateProperties->getName(), $privateProperties->getName(), $parentAccess )); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/MagicSleep.php 0000644 00000001661 15117764664 0027410 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator; use Laminas\Code\Generator\MethodGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ReflectionClass; /** * Magic `__sleep` for lazy loading ghost objects */ class MagicSleep extends MagicMethodGenerator { /** * Constructor */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $initializerProperty, MethodGenerator $callInitializer ) { parent::__construct($originalClass, '__sleep'); $this->setBody( '$this->' . $initializerProperty->getName() . ' && $this->' . $callInitializer->getName() . '(\'__sleep\', []);' . "\n\n" . ($originalClass->hasMethod('__sleep') ? 'return parent::__sleep();' : 'return array_keys((array) $this);') ); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/MagicUnset.php 0000644 00000007717 15117764664 0027446 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\MethodGenerator; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\PrivatePropertiesMap; use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\ProtectedPropertiesMap; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; use function sprintf; /** * Magic `__unset` method for lazy loading ghost objects */ class MagicUnset extends MagicMethodGenerator { private $callParentTemplate = <<<'PHP' %s if (isset(self::$%s[$name])) { unset($this->$name); return; } if (isset(self::$%s[$name])) { // check protected property access via compatible class $callers = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT, 2); $caller = isset($callers[1]) ? $callers[1] : []; $object = isset($caller['object']) ? $caller['object'] : ''; $expectedType = self::$%s[$name]; if ($object instanceof $expectedType) { unset($this->$name); return; } $class = isset($caller['class']) ? $caller['class'] : ''; if ($class === $expectedType || is_subclass_of($class, $expectedType) || $class === 'ReflectionProperty') { unset($this->$name); return; } } elseif (isset(self::$%s[$name])) { // check private property access via same class $callers = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT, 2); $caller = isset($callers[1]) ? $callers[1] : []; $class = isset($caller['class']) ? $caller['class'] : ''; static $accessorCache = []; if (isset(self::$%s[$name][$class])) { $cacheKey = $class . '#' . $name; $accessor = isset($accessorCache[$cacheKey]) ? $accessorCache[$cacheKey] : $accessorCache[$cacheKey] = \Closure::bind(static function ($instance) use ($name) { unset($instance->$name); }, null, $class); return $accessor($this); } if ('ReflectionProperty' === $class) { $tmpClass = key(self::$%s[$name]); $cacheKey = $tmpClass . '#' . $name; $accessor = isset($accessorCache[$cacheKey]) ? $accessorCache[$cacheKey] : $accessorCache[$cacheKey] = \Closure::bind(static function ($instance) use ($name) { unset($instance->$name); }, null, $tmpClass); return $accessor($this); } } %s PHP; /** * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $initializerProperty, MethodGenerator $callInitializer, PublicPropertiesMap $publicProperties, ProtectedPropertiesMap $protectedProperties, PrivatePropertiesMap $privateProperties ) { parent::__construct($originalClass, '__unset', [new ParameterGenerator('name')]); $override = $originalClass->hasMethod('__unset'); $parentAccess = 'return parent::__unset($name);'; if (! $override) { $parentAccess = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_UNSET, 'name' ); } $this->setBody(sprintf( $this->callParentTemplate, '$this->' . $initializerProperty->getName() . ' && $this->' . $callInitializer->getName() . '(\'__unset\', array(\'name\' => $name));', $publicProperties->getName(), $protectedProperties->getName(), $protectedProperties->getName(), $privateProperties->getName(), $privateProperties->getName(), $privateProperties->getName(), $parentAccess )); } } src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/SetProxyInitializer.php 0000644 00000001566 15117764664 0031325 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator; use Closure; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; /** * Implementation for {@see \ProxyManager\Proxy\LazyLoadingInterface::setProxyInitializer} * for lazy loading value holder objects */ class SetProxyInitializer extends MethodGenerator { /** * Constructor */ public function __construct(PropertyGenerator $initializerProperty) { parent::__construct( 'setProxyInitializer', [(new ParameterGenerator('initializer', Closure::class))->setDefaultValue(null)], self::FLAG_PUBLIC, '$this->' . $initializerProperty->getName() . ' = $initializer;' ); $this->setReturnType('void'); } } src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/SkipDestructor.php 0000644 00000001334 15117764664 0030302 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; /** * Destructor that skips the original destructor when the proxy is not initialized. */ class SkipDestructor extends MethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(PropertyGenerator $initializerProperty) { parent::__construct('__destruct'); $this->setBody( '$this->' . $initializerProperty->getName() . ' || parent::__destruct();' ); } } src/ProxyManager/ProxyGenerator/LazyLoadingGhost/PropertyGenerator/InitializationTracker.php 0000644 00000001463 15117764664 0032227 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\Util\IdentifierSuffixer; /** * Property that contains the initializer for a lazy object */ class InitializationTracker extends PropertyGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct() { parent::__construct(IdentifierSuffixer::getIdentifier('initializationTracker')); $this->setVisibility(self::VISIBILITY_PRIVATE); $this->setDocBlock('@var bool tracks initialization status - true while the object is initializing'); $this->setDefaultValue(false); } } src/ProxyManager/ProxyGenerator/LazyLoadingGhost/PropertyGenerator/InitializerProperty.php 0000644 00000001377 15117764664 0031760 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\Util\IdentifierSuffixer; /** * Property that contains the initializer for a lazy object */ class InitializerProperty extends PropertyGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct() { parent::__construct(IdentifierSuffixer::getIdentifier('initializer')); $this->setVisibility(self::VISIBILITY_PRIVATE); $this->setDocBlock('@var \\Closure|null initializer responsible for generating the wrapped object'); } } src/ProxyManager/ProxyGenerator/LazyLoadingGhost/PropertyGenerator/PrivatePropertiesMap.php 0000644 00000003530 15117764664 0032046 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\Util\IdentifierSuffixer; use ProxyManager\ProxyGenerator\Util\Properties; /** * Property that contains the initializer for a lazy object */ class PrivatePropertiesMap extends PropertyGenerator { public const KEY_DEFAULT_VALUE = 'defaultValue'; /** @var list<string> */ private $readOnlyPropertyNames = []; /** * Constructor * * @throws InvalidArgumentException */ public function __construct(Properties $properties) { parent::__construct( IdentifierSuffixer::getIdentifier('privateProperties') ); $this->setVisibility(self::VISIBILITY_PRIVATE); $this->setStatic(true); $this->setDocBlock( '@var array[][] visibility and default value of defined properties, indexed by property name and class name' ); $this->setDefaultValue($this->getMap($properties)); } /** * @return list<string> */ public function getReadOnlyPropertyNames(): array { return $this->readOnlyPropertyNames; } /** * @return array<string, array<class-string, bool>> */ private function getMap(Properties $properties): array { $map = []; foreach ($properties->getInstanceProperties() as $property) { if (\PHP_VERSION_ID >= 80100 && $property->isReadOnly()) { $this->readOnlyPropertyNames[] = $property->getName(); } elseif (! $property->isPrivate()) { continue; } $map[$property->getName()][$property->getDeclaringClass()->getName()] = true; } return $map; } } src/ProxyManager/ProxyGenerator/LazyLoadingGhost/PropertyGenerator/ProtectedPropertiesMap.php 0000644 00000002736 15117764664 0032374 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\Util\IdentifierSuffixer; use ProxyManager\ProxyGenerator\Util\Properties; /** * Property that contains the protected instance lazy-loadable properties of an object */ class ProtectedPropertiesMap extends PropertyGenerator { public const KEY_DEFAULT_VALUE = 'defaultValue'; /** * Constructor * * @throws InvalidArgumentException */ public function __construct(Properties $properties) { parent::__construct( IdentifierSuffixer::getIdentifier('protectedProperties') ); $this->setVisibility(self::VISIBILITY_PRIVATE); $this->setStatic(true); $this->setDocBlock( '@var string[][] declaring class name of defined protected properties, indexed by property name' ); $this->setDefaultValue($this->getMap($properties)); } /** @return string[] */ private function getMap(Properties $properties): array { $map = []; foreach ($properties->getProtectedProperties() as $property) { if (\PHP_VERSION_ID >= 80100 && $property->isReadOnly()) { continue; } $map[$property->getName()] = $property->getDeclaringClass()->getName(); } return $map; } } src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/GetProxyInitializer.php 0000644 00000001444 15117764664 0032432 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; /** * Implementation for {@see \ProxyManager\Proxy\LazyLoadingInterface::getProxyInitializer} * for lazy loading value holder objects */ class GetProxyInitializer extends MethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(PropertyGenerator $initializerProperty) { parent::__construct('getProxyInitializer'); $this->setReturnType('?\\Closure'); $this->setBody('return $this->' . $initializerProperty->getName() . ';'); } } src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/InitializeProxy.php 0000644 00000002230 15117764664 0031602 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; /** * Implementation for {@see \ProxyManager\Proxy\LazyLoadingInterface::initializeProxy} * for lazy loading value holder objects */ class InitializeProxy extends MethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(PropertyGenerator $initializerProperty, PropertyGenerator $valueHolderProperty) { parent::__construct('initializeProxy'); $this->setReturnType('bool'); $initializer = $initializerProperty->getName(); $valueHolder = $valueHolderProperty->getName(); $this->setBody( 'return $this->' . $initializer . ' && ($this->' . $initializer . '->__invoke($' . $valueHolder . ', $this, \'initializeProxy\', array(), $this->' . $initializer . ') || 1)' . ' && $this->' . $valueHolder . ' = $' . $valueHolder . ';' ); } } src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/IsProxyInitialized.php 0000644 00000001444 15117764664 0032250 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; /** * Implementation for {@see \ProxyManager\Proxy\LazyLoadingInterface::isProxyInitialized} * for lazy loading value holder objects */ class IsProxyInitialized extends MethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(PropertyGenerator $valueHolderProperty) { parent::__construct('isProxyInitialized'); $this->setReturnType('bool'); $this->setBody('return null !== $this->' . $valueHolderProperty->getName() . ';'); } } ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/LazyLoadingMethodInterceptor.php 0000644 00000004257 15117764664 0034247 0 ustar 00 proxy-manager-lts/src <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use Laminas\Code\Reflection\MethodReflection; use ProxyManager\Generator\MethodGenerator; use ProxyManager\Generator\Util\ProxiedMethodReturnExpression; use function implode; use function var_export; /** * Method decorator for lazy loading value holder objects */ class LazyLoadingMethodInterceptor extends MethodGenerator { /** * @throws InvalidArgumentException */ public static function generateMethod( MethodReflection $originalMethod, PropertyGenerator $initializerProperty, PropertyGenerator $valueHolderProperty ): self { $method = static::fromReflectionWithoutBodyAndDocBlock($originalMethod); $initializerName = $initializerProperty->getName(); $valueHolderName = $valueHolderProperty->getName(); $parameters = $originalMethod->getParameters(); $methodName = $originalMethod->getName(); $initializerParams = []; $forwardedParams = []; foreach ($parameters as $parameter) { $parameterName = $parameter->getName(); $variadicPrefix = $parameter->isVariadic() ? '...' : ''; $initializerParams[] = var_export($parameterName, true) . ' => $' . $parameterName; $forwardedParams[] = $variadicPrefix . '$' . $parameterName; } $method->setBody( '$this->' . $initializerName . ' && ($this->' . $initializerName . '->__invoke($' . $valueHolderName . ', $this, ' . var_export($methodName, true) . ', array(' . implode(', ', $initializerParams) . '), $this->' . $initializerName . ') || 1)' . ' && $this->' . $valueHolderName . ' = $' . $valueHolderName . ";\n\n" . ProxiedMethodReturnExpression::generate( '$this->' . $valueHolderName . '->' . $methodName . '(' . implode(', ', $forwardedParams) . ')', $originalMethod ) ); return $method; } } src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/MagicClone.php 0000644 00000002144 15117764664 0030444 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ReflectionClass; /** * Magic `__clone` for lazy loading value holder objects */ class MagicClone extends MagicMethodGenerator { /** * Constructor */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $initializerProperty, PropertyGenerator $valueHolderProperty ) { parent::__construct($originalClass, '__clone'); $initializer = $initializerProperty->getName(); $valueHolder = $valueHolderProperty->getName(); $this->setBody( '$this->' . $initializer . ' && ($this->' . $initializer . '->__invoke($' . $valueHolder . ', $this, \'__clone\', array(), $this->' . $initializer . ') || 1)' . ' && $this->' . $valueHolder . ' = $' . $valueHolder . ';' . "\n\n" . '$this->' . $valueHolder . ' = clone $this->' . $valueHolder . ';' ); } } src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/MagicGet.php 0000644 00000004522 15117764664 0030125 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; /** * Magic `__get` for lazy loading value holder objects */ class MagicGet extends MagicMethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $initializerProperty, PropertyGenerator $valueHolderProperty, PublicPropertiesMap $publicProperties ) { parent::__construct($originalClass, '__get', [new ParameterGenerator('name')]); $hasParent = $originalClass->hasMethod('__get'); $initializer = $initializerProperty->getName(); $valueHolder = $valueHolderProperty->getName(); $callParent = 'if (isset(self::$' . $publicProperties->getName() . "[\$name])) {\n" . ' return $this->' . $valueHolder . '->$name;' . "\n}\n\n"; if ($hasParent) { $this->setInitializerBody( $initializer, $valueHolder, $callParent . 'return $this->' . $valueHolder . '->__get($name);' ); return; } $this->setInitializerBody( $initializer, $valueHolder, $callParent . PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_GET, 'name', null, $valueHolderProperty, null, $originalClass ) ); } private function setInitializerBody(string $initializer, string $valueHolder, string $callParent): void { $this->setBody( '$this->' . $initializer . ' && ($this->' . $initializer . '->__invoke($' . $valueHolder . ', $this, \'__get\', [\'name\' => $name], $this->' . $initializer . ') || 1) && $this->' . $valueHolder . ' = $' . $valueHolder . ';' . "\n\n" . $callParent ); } } src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/MagicIsset.php 0000644 00000003622 15117764664 0030475 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; /** * Magic `__isset` method for lazy loading value holder objects */ class MagicIsset extends MagicMethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $initializerProperty, PropertyGenerator $valueHolderProperty, PublicPropertiesMap $publicProperties ) { parent::__construct($originalClass, '__isset', [new ParameterGenerator('name')]); $initializer = $initializerProperty->getName(); $valueHolder = $valueHolderProperty->getName(); $callParent = ''; if (! $publicProperties->isEmpty()) { $callParent = 'if (isset(self::$' . $publicProperties->getName() . "[\$name])) {\n" . ' return isset($this->' . $valueHolder . '->$name);' . "\n}\n\n"; } $callParent .= PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_ISSET, 'name', null, $valueHolderProperty, null, $originalClass ); $this->setBody( '$this->' . $initializer . ' && ($this->' . $initializer . '->__invoke($' . $valueHolder . ', $this, \'__isset\', array(\'name\' => $name), $this->' . $initializer . ') || 1) && $this->' . $valueHolder . ' = $' . $valueHolder . ';' . "\n\n" . $callParent ); } } src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/MagicSet.php 0000644 00000004310 15117764664 0030134 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; /** * Magic `__set` for lazy loading value holder objects */ class MagicSet extends MagicMethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $initializerProperty, PropertyGenerator $valueHolderProperty, PublicPropertiesMap $publicProperties ) { parent::__construct( $originalClass, '__set', [new ParameterGenerator('name'), new ParameterGenerator('value')] ); $hasParent = $originalClass->hasMethod('__set'); $initializer = $initializerProperty->getName(); $valueHolder = $valueHolderProperty->getName(); $callParent = ''; if (! $publicProperties->isEmpty()) { $callParent = 'if (isset(self::$' . $publicProperties->getName() . "[\$name])) {\n" . ' return ($this->' . $valueHolder . '->$name = $value);' . "\n}\n\n"; } $callParent .= $hasParent ? 'return $this->' . $valueHolder . '->__set($name, $value);' : PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_SET, 'name', 'value', $valueHolderProperty, null, $originalClass ); $this->setBody( '$this->' . $initializer . ' && ($this->' . $initializer . '->__invoke($' . $valueHolder . ', $this, ' . '\'__set\', array(\'name\' => $name, \'value\' => $value), $this->' . $initializer . ') || 1)' . ' && $this->' . $valueHolder . ' = $' . $valueHolder . ';' . "\n\n" . $callParent ); } } src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/MagicSleep.php 0000644 00000002142 15117764664 0030452 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ReflectionClass; use function var_export; /** * Magic `__sleep` for lazy loading value holder objects */ class MagicSleep extends MagicMethodGenerator { /** * Constructor */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $initializerProperty, PropertyGenerator $valueHolderProperty ) { parent::__construct($originalClass, '__sleep'); $initializer = $initializerProperty->getName(); $valueHolder = $valueHolderProperty->getName(); $this->setBody( '$this->' . $initializer . ' && ($this->' . $initializer . '->__invoke($' . $valueHolder . ', $this, \'__sleep\', array(), $this->' . $initializer . ') || 1) && $this->' . $valueHolder . ' = $' . $valueHolder . ';' . "\n\n" . 'return array(' . var_export($valueHolder, true) . ');' ); } } src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/MagicUnset.php 0000644 00000004125 15117764664 0030503 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\PublicScopeSimulator; use ReflectionClass; /** * Magic `__unset` method for lazy loading value holder objects */ class MagicUnset extends MagicMethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct( ReflectionClass $originalClass, PropertyGenerator $initializerProperty, PropertyGenerator $valueHolderProperty, PublicPropertiesMap $publicProperties ) { parent::__construct($originalClass, '__unset', [new ParameterGenerator('name')]); $hasParent = $originalClass->hasMethod('__unset'); $initializer = $initializerProperty->getName(); $valueHolder = $valueHolderProperty->getName(); $callParent = ''; if (! $publicProperties->isEmpty()) { $callParent = 'if (isset(self::$' . $publicProperties->getName() . "[\$name])) {\n" . ' unset($this->' . $valueHolder . '->$name);' . "\n\n return;" . "\n}\n\n"; } $callParent .= $hasParent ? 'return $this->' . $valueHolder . '->__unset($name);' : PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_UNSET, 'name', null, $valueHolderProperty, null, $originalClass ); $this->setBody( '$this->' . $initializer . ' && ($this->' . $initializer . '->__invoke($' . $valueHolder . ', $this, \'__unset\', array(\'name\' => $name), $this->' . $initializer . ') || 1) && $this->' . $valueHolder . ' = $' . $valueHolder . ';' . "\n\n" . $callParent ); } } src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/SetProxyInitializer.php 0000644 00000002115 15117764664 0032442 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator; use Closure; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; /** * Implementation for {@see \ProxyManager\Proxy\LazyLoadingInterface::setProxyInitializer} * for lazy loading value holder objects */ class SetProxyInitializer extends MethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(PropertyGenerator $initializerProperty) { parent::__construct('setProxyInitializer'); $initializerParameter = new ParameterGenerator('initializer'); $initializerParameter->setType(Closure::class); $initializerParameter->setDefaultValue(null); $this->setParameter($initializerParameter); $this->setBody('$this->' . $initializerProperty->getName() . ' = $initializer;'); $this->setReturnType('void'); } } src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/SkipDestructor.php 0000644 00000001466 15117764664 0031436 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; use ReflectionClass; /** * Destructor that skips the original destructor when the proxy is not initialized. */ class SkipDestructor extends MethodGenerator { /** * Constructor */ public function __construct( PropertyGenerator $initializerProperty, PropertyGenerator $valueHolderProperty ) { parent::__construct('__destruct'); $initializer = $initializerProperty->getName(); $valueHolder = $valueHolderProperty->getName(); $this->setBody( '$this->' . $initializer . ' || $this->' . $valueHolder . '->__destruct();' ); } } src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/PropertyGenerator/InitializerProperty.php 0000644 00000001405 15117764664 0033076 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingValueHolder\PropertyGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\Util\IdentifierSuffixer; /** * Property that contains the initializer for a lazy object */ class InitializerProperty extends PropertyGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct() { parent::__construct(IdentifierSuffixer::getIdentifier('initializer')); $this->setVisibility(self::VISIBILITY_PRIVATE); $this->setDocBlock('@var \\Closure|null initializer responsible for generating the wrapped object'); } } src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/PropertyGenerator/ValueHolderProperty.php 0000644 00000001757 15117764664 0033037 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\LazyLoadingValueHolder\PropertyGenerator; use Laminas\Code\Generator\DocBlockGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\Util\IdentifierSuffixer; use ReflectionClass; /** * Property that contains the wrapped value of a lazy loading proxy */ class ValueHolderProperty extends PropertyGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(ReflectionClass $type) { parent::__construct(IdentifierSuffixer::getIdentifier('valueHolder')); $docBlock = new DocBlockGenerator(); $docBlock->setWordWrap(false); $docBlock->setLongDescription('@var \\' . $type->getName() . '|null wrapped object, if the proxy is initialized'); $this->setDocBlock($docBlock); $this->setVisibility(self::VISIBILITY_PRIVATE); } } src/ProxyManager/ProxyGenerator/NullObject/MethodGenerator/NullObjectMethodInterceptor.php 0000644 00000002224 15117764664 0031554 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\NullObject\MethodGenerator; use Laminas\Code\Reflection\MethodReflection; use ProxyManager\Generator\MethodGenerator; use ProxyManager\Generator\Util\IdentifierSuffixer; use ReflectionNamedType; use function in_array; /** * Method decorator for null objects */ class NullObjectMethodInterceptor extends MethodGenerator { /** * @return static */ public static function generateMethod(MethodReflection $originalMethod): self { $method = static::fromReflectionWithoutBodyAndDocBlock($originalMethod); $returnType = $originalMethod->getReturnType(); $nullCast = $returnType instanceof ReflectionNamedType && ! $returnType->allowsNull() && in_array($returnType->getName(), ['array', 'float', 'int', 'string'], true) ? '(' . $returnType->getName() . ') ' : ''; if ($originalMethod->returnsReference() || $nullCast !== '') { $reference = IdentifierSuffixer::getIdentifier('ref'); $method->setBody('$' . $reference . ' = ' . $nullCast . "null;\nreturn \$" . $reference . ';'); } return $method; } } src/ProxyManager/ProxyGenerator/NullObject/MethodGenerator/StaticProxyConstructor.php 0000644 00000003235 15117764664 0030675 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\NullObject\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use ProxyManager\Generator\MethodGenerator; use ProxyManager\ProxyGenerator\Util\Properties; use ReflectionClass; use ReflectionProperty; use function array_map; use function implode; /** * The `staticProxyConstructor` implementation for null object proxies */ class StaticProxyConstructor extends MethodGenerator { /** * Constructor * * @param ReflectionClass $originalClass Reflection of the class to proxy * * @throws InvalidArgumentException */ public function __construct(ReflectionClass $originalClass) { parent::__construct('staticProxyConstructor', [], self::FLAG_PUBLIC | self::FLAG_STATIC); $nullableProperties = array_map( static function (ReflectionProperty $publicProperty): string { return '$instance->' . $publicProperty->getName() . ' = null;'; }, Properties::fromReflectionClass($originalClass) ->onlyNullableProperties() ->getPublicProperties() ); $this->setReturnType($originalClass->getName()); $this->setDocBlock('Constructor for null object initialization'); $this->setBody( 'static $reflection;' . "\n\n" . '$reflection = $reflection ?? new \ReflectionClass(__CLASS__);' . "\n" . '$instance = $reflection->newInstanceWithoutConstructor();' . "\n\n" . ($nullableProperties ? implode("\n", $nullableProperties) . "\n\n" : '') . 'return $instance;' ); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/PropertyGenerator/PublicPropertiesMap.php 0000644 00000002542 15117764664 0026511 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\PropertyGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\Util\IdentifierSuffixer; use ProxyManager\ProxyGenerator\Util\Properties; /** * Map of public properties that exist in the class being proxied */ class PublicPropertiesMap extends PropertyGenerator { /** @var array<string, bool> */ private $publicProperties = []; /** * @throws InvalidArgumentException */ public function __construct(Properties $properties, bool $skipReadOnlyProperties = false) { parent::__construct(IdentifierSuffixer::getIdentifier('publicProperties')); foreach ($properties->getPublicProperties() as $publicProperty) { if ($skipReadOnlyProperties && \PHP_VERSION_ID >= 80100 && $publicProperty->isReadOnly()) { continue; } $this->publicProperties[$publicProperty->getName()] = true; } $this->setDefaultValue($this->publicProperties); $this->setVisibility(self::VISIBILITY_PRIVATE); $this->setStatic(true); $this->setDocBlock('@var bool[] map of public properties of the parent class'); } public function isEmpty(): bool { return ! $this->publicProperties; } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicGet.php 0000644 00000001761 15117764664 0026220 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\RemoteObject\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ReflectionClass; use function var_export; /** * Magic `__get` for remote objects */ class MagicGet extends MagicMethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(ReflectionClass $originalClass, PropertyGenerator $adapterProperty) { parent::__construct($originalClass, '__get', [new ParameterGenerator('name')]); $this->setDocBlock('@param string $name'); $this->setBody( '$return = $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) . ', \'__get\', array($name));' . "\n\n" . 'return $return;' ); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicIsset.php 0000644 00000002014 15117764664 0026560 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\RemoteObject\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ReflectionClass; use function var_export; /** * Magic `__isset` method for remote objects */ class MagicIsset extends MagicMethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(ReflectionClass $originalClass, PropertyGenerator $adapterProperty) { parent::__construct($originalClass, '__isset', [new ParameterGenerator('name')]); $this->setDocBlock('@param string $name'); $this->setBody( '$return = $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) . ', \'__isset\', array($name));' . "\n\n" . 'return $return;' ); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicSet.php 0000644 00000002153 15117764664 0026230 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\RemoteObject\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ReflectionClass; use function var_export; /** * Magic `__set` for remote objects */ class MagicSet extends MagicMethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(ReflectionClass $originalClass, PropertyGenerator $adapterProperty) { parent::__construct( $originalClass, '__set', [new ParameterGenerator('name'), new ParameterGenerator('value')] ); $this->setDocBlock('@param string \$name\n@param mixed \$value'); $this->setBody( '$return = $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) . ', \'__set\', array($name, $value));' . "\n\n" . 'return $return;' ); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicUnset.php 0000644 00000002014 15117764664 0026567 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\RemoteObject\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ReflectionClass; use function var_export; /** * Magic `__unset` method for remote objects */ class MagicUnset extends MagicMethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(ReflectionClass $originalClass, PropertyGenerator $adapterProperty) { parent::__construct($originalClass, '__unset', [new ParameterGenerator('name')]); $this->setDocBlock('@param string $name'); $this->setBody( '$return = $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) . ', \'__unset\', array($name));' . "\n\n" . 'return $return;' ); } } src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/RemoteObjectMethod.php 0000644 00000004531 15117764664 0030202 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\RemoteObject\MethodGenerator; use Laminas\Code\Generator\PropertyGenerator; use Laminas\Code\Reflection\MethodReflection; use ProxyManager\Generator\MethodGenerator; use ProxyManager\Generator\Util\ProxiedMethodReturnExpression; use ProxyManager\Generator\ValueGenerator; use ReflectionClass; use function sprintf; use function strtr; use function var_export; /** * Method decorator for remote objects */ class RemoteObjectMethod extends MethodGenerator { private const TEMPLATE = <<<'PHP' $args = \func_get_args(); switch (\func_num_args()) {#DEFAULT_VALUES# } #PROXIED_RETURN# PHP; /** @return static */ public static function generateMethod( MethodReflection $originalMethod, PropertyGenerator $adapterProperty, ReflectionClass $originalClass ): self { $method = static::fromReflectionWithoutBodyAndDocBlock($originalMethod); $proxiedReturn = '$return = $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) . ', ' . var_export($originalMethod->getName(), true) . ', $args);' . "\n\n" . ProxiedMethodReturnExpression::generate('$return', $originalMethod); $defaultValues = self::getDefaultValuesForMethod($originalMethod); $method->setBody( strtr( self::TEMPLATE, [ '#PROXIED_RETURN#' => $proxiedReturn, '#DEFAULT_VALUES#' => $defaultValues, ] ) ); return $method; } private static function getDefaultValuesForMethod(MethodReflection $originalMethod): string { $defaultValues = ''; foreach ($originalMethod->getParameters() as $i => $parameter) { if ($parameter->isOptional() && $parameter->isDefaultValueAvailable()) { $default = new ValueGenerator($parameter->getDefaultValue(), $parameter); $defaultValues .= sprintf("\n case %d: \$args[] = %s;", $i, $default->generate()); continue; } if ($parameter->isVariadic()) { continue; } $defaultValues .= sprintf("\n case %d: \$args[] = null;", $i); } return $defaultValues; } } src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/StaticProxyConstructor.php 0000644 00000003345 15117764664 0031220 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\RemoteObject\MethodGenerator; use Laminas\Code\Generator\ParameterGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Factory\RemoteObject\AdapterInterface; use ProxyManager\Generator\MethodGenerator; use ProxyManager\ProxyGenerator\Util\Properties; use ProxyManager\ProxyGenerator\Util\UnsetPropertiesGenerator; use ReflectionClass; /** * The `staticProxyConstructor` implementation for remote object proxies */ class StaticProxyConstructor extends MethodGenerator { /** * Constructor * * @param ReflectionClass $originalClass Reflection of the class to proxy * @param PropertyGenerator $adapter Adapter property */ public function __construct(ReflectionClass $originalClass, PropertyGenerator $adapter) { $adapterName = $adapter->getName(); parent::__construct( 'staticProxyConstructor', [new ParameterGenerator($adapterName, AdapterInterface::class)], MethodGenerator::FLAG_PUBLIC | MethodGenerator::FLAG_STATIC, null, 'Constructor for remote object control\n\n' . '@param \\ProxyManager\\Factory\\RemoteObject\\AdapterInterface \$adapter' ); $body = 'static $reflection;' . "\n\n" . '$reflection = $reflection ?? new \ReflectionClass(__CLASS__);' . "\n" . '$instance = $reflection->newInstanceWithoutConstructor();' . "\n\n" . '$instance->' . $adapterName . ' = $' . $adapterName . ";\n\n" . UnsetPropertiesGenerator::generateSnippet(Properties::fromReflectionClass($originalClass), 'instance'); $this->setBody($body . "\n\nreturn \$instance;"); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/RemoteObject/PropertyGenerator/AdapterProperty.php0000644 00000001427 15117764664 0030270 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\RemoteObject\PropertyGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Factory\RemoteObject\AdapterInterface; use ProxyManager\Generator\Util\IdentifierSuffixer; /** * Property that contains the remote object adapter */ class AdapterProperty extends PropertyGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct() { parent::__construct(IdentifierSuffixer::getIdentifier('adapter')); $this->setVisibility(self::VISIBILITY_PRIVATE); $this->setDocBlock('@var \\' . AdapterInterface::class . ' Remote web service adapter'); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/Util/GetMethodIfExists.php 0000644 00000000737 15117764664 0023345 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\Util; use ReflectionClass; use ReflectionMethod; /** * Internal utility class - allows fetching a method from a given class, if it exists */ final class GetMethodIfExists { private function __construct() { } public static function get(ReflectionClass $class, string $method): ?ReflectionMethod { return $class->hasMethod($method) ? $class->getMethod($method) : null; } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/Util/Properties.php 0000644 00000016116 15117764664 0022140 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\Util; use ReflectionClass; use ReflectionProperty; use ReflectionType; use function array_filter; use function array_flip; use function array_key_exists; use function array_keys; use function array_map; use function array_merge; use function array_values; use function assert; /** * DTO containing the list of all non-static proxy properties and utility methods to access them * in various formats/collections */ final class Properties { /** @var ReflectionProperty[] */ private $properties; /** * @param ReflectionProperty[] $properties */ private function __construct(array $properties) { $this->properties = $properties; } public static function fromReflectionClass(ReflectionClass $reflection): self { $class = $reflection; $parentClasses = []; do { $parentClasses[] = $class; $class = $class->getParentClass(); } while ($class); return new self(array_merge( ...array_map(static function (ReflectionClass $class): array { return array_values(array_filter( $class->getProperties(), static function (ReflectionProperty $property) use ($class): bool { return $class->getName() === $property->getDeclaringClass()->getName() && ! $property->isStatic(); } )); }, $parentClasses) )); } /** * @param array<int, string> $excludedProperties */ public function filter(array $excludedProperties): self { $properties = $this->getInstanceProperties(); foreach ($excludedProperties as $propertyName) { unset($properties[$propertyName]); } return new self($properties); } public function onlyNonReferenceableProperties(): self { return new self(array_filter($this->properties, static function (ReflectionProperty $property): bool { if (\PHP_VERSION_ID < 70400 || ! $property->hasType()) { return false; } if (\PHP_VERSION_ID >= 80100 && $property->isReadOnly()) { return true; } $type = $property->getType(); assert($type instanceof ReflectionType); if ($type->allowsNull()) { return false; } return ! array_key_exists( $property->getName(), // https://bugs.php.net/bug.php?id=77673 array_flip(array_keys($property->getDeclaringClass()->getDefaultProperties())) ); })); } /** @deprecated Since PHP 7.4.1, all properties can be unset, regardless if typed or not */ public function onlyPropertiesThatCanBeUnset(): self { return $this; } /** * Properties that cannot be referenced are non-nullable typed properties that aren't initialised */ public function withoutNonReferenceableProperties(): self { return new self(array_filter($this->properties, static function (ReflectionProperty $property): bool { if (\PHP_VERSION_ID < 70400 || ! $property->hasType()) { return true; } if (\PHP_VERSION_ID >= 80100 && $property->isReadOnly()) { return false; } $type = $property->getType(); assert($type instanceof ReflectionType); if ($type->allowsNull()) { return true; } return array_key_exists( $property->getName(), // https://bugs.php.net/bug.php?id=77673 array_flip(array_keys($property->getDeclaringClass()->getDefaultProperties())) ); })); } public function onlyNullableProperties(): self { return new self(array_filter( $this->properties, static function (ReflectionProperty $property): bool { if (\PHP_VERSION_ID < 70400 || ! $property->hasType()) { return true; } $type = $property->getType(); return $type === null || $type->allowsNull(); } )); } public function onlyInstanceProperties(): self { return new self(array_values(array_merge($this->getAccessibleProperties(), $this->getPrivateProperties()))); } public function empty(): bool { return $this->properties === []; } /** * @return array<string, ReflectionProperty> indexed by the property internal visibility-aware name */ public function getPublicProperties(): array { $publicProperties = []; foreach ($this->properties as $property) { if (! $property->isPublic()) { continue; } $publicProperties[$property->getName()] = $property; } return $publicProperties; } /** * @return array<string, ReflectionProperty> indexed by the property internal visibility-aware name (\0*\0propertyName) */ public function getProtectedProperties(): array { $protectedProperties = []; foreach ($this->properties as $property) { if (! $property->isProtected()) { continue; } $protectedProperties["\0*\0" . $property->getName()] = $property; } return $protectedProperties; } /** * @return array<string, ReflectionProperty> indexed by the property internal visibility-aware name (\0ClassName\0propertyName) */ public function getPrivateProperties(): array { $privateProperties = []; foreach ($this->properties as $property) { if (! $property->isPrivate()) { continue; } $declaringClass = $property->getDeclaringClass()->getName(); $privateProperties["\0" . $declaringClass . "\0" . $property->getName()] = $property; } return $privateProperties; } /** * @return array<string, ReflectionProperty> indexed by the property internal visibility-aware name (\0*\0propertyName) */ public function getAccessibleProperties(): array { return array_merge($this->getPublicProperties(), $this->getProtectedProperties()); } /** * @return array<class-string, array<string, ReflectionProperty>> indexed by class name and property name */ public function getGroupedPrivateProperties(): array { $propertiesMap = []; foreach ($this->getPrivateProperties() as $property) { $propertiesMap[$property->getDeclaringClass()->getName()][$property->getName()] = $property; } return $propertiesMap; } /** * @return array<string, ReflectionProperty> indexed by the property internal visibility-aware name (\0*\0propertyName) */ public function getInstanceProperties(): array { return array_merge($this->getAccessibleProperties(), $this->getPrivateProperties()); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/Util/ProxiedMethodsFilter.php 0000644 00000004615 15117764664 0024111 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\Util; use ReflectionClass; use ReflectionMethod; use function array_filter; use function array_flip; use function array_key_exists; use function array_map; use function array_values; use function strtolower; /** * Utility class used to filter methods that can be proxied */ final class ProxiedMethodsFilter { /** * @internal */ public const DEFAULT_EXCLUDED = [ '__get', '__set', '__isset', '__unset', '__clone', '__sleep', '__wakeup', ]; /** * @param ReflectionClass $class reflection class from which methods should be extracted * @param array<int, string> $excluded methods to be ignored * * @return ReflectionMethod[] */ public static function getProxiedMethods(ReflectionClass $class, ?array $excluded = null): array { return self::doFilter($class, $excluded ?? self::DEFAULT_EXCLUDED); } /** * @param ReflectionClass $class reflection class from which methods should be extracted * @param array<int, string> $excluded methods to be ignored * * @return ReflectionMethod[] */ public static function getAbstractProxiedMethods(ReflectionClass $class, ?array $excluded = null): array { return self::doFilter($class, $excluded ?? self::DEFAULT_EXCLUDED, true); } /** * @param array<int, string> $excluded * * @return array<int, ReflectionMethod> */ private static function doFilter(ReflectionClass $class, array $excluded, bool $requireAbstract = false): array { $ignored = array_flip(array_map('strtolower', $excluded)); return array_values(array_filter( $class->getMethods(ReflectionMethod::IS_PUBLIC), static function (ReflectionMethod $method) use ($ignored, $requireAbstract): bool { return (! $requireAbstract || $method->isAbstract()) && ! ( array_key_exists(strtolower($method->getName()), $ignored) || self::methodCannotBeProxied($method) ); } )); } /** * Checks whether the method cannot be proxied */ private static function methodCannotBeProxied(ReflectionMethod $method): bool { return $method->isConstructor() || $method->isFinal() || $method->isStatic(); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/Util/PublicScopeSimulator.php 0000644 00000020222 15117764664 0024105 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\Util; use InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ReflectionClass; use function array_filter; use function array_map; use function implode; use function sprintf; use function var_export; /** * Generates code necessary to simulate a fatal error in case of unauthorized * access to class members in magic methods even when in child classes and dealing * with protected members. */ class PublicScopeSimulator { public const OPERATION_SET = 'set'; public const OPERATION_GET = 'get'; public const OPERATION_ISSET = 'isset'; public const OPERATION_UNSET = 'unset'; /** * Generates code for simulating access to a property from the scope that is accessing a proxy. * This is done by introspecting `debug_backtrace()` and then binding a closure to the scope * of the parent caller. * * @param string $operationType operation to execute: one of 'get', 'set', 'isset' or 'unset' * @param string $nameParameter name of the `name` parameter of the magic method * @param string|null $valueParameter name of the `value` parameter of the magic method, only to be * used with $operationType 'set' * @param PropertyGenerator $valueHolder name of the property containing the target object from which * to read the property. `$this` if none provided * @param string|null $returnPropertyName name of the property to which we want to assign the result of * the operation. Return directly if none provided * @param string|null $interfaceName name of the proxified interface if any * @psalm-param $operationType self::OPERATION_* * * @throws InvalidArgumentException */ public static function getPublicAccessSimulationCode( string $operationType, string $nameParameter, ?string $valueParameter = null, ?PropertyGenerator $valueHolder = null, ?string $returnPropertyName = null, ?ReflectionClass $originalClass = null ): string { $byRef = self::getByRefReturnValue($operationType); $target = '$this'; if ($valueHolder) { $target = '$this->' . $valueHolder->getName(); } $originalClassReflection = $originalClass === null ? 'new \\ReflectionClass(get_parent_class($this))' : 'new \\ReflectionClass(' . var_export($originalClass->getName(), true) . ')'; $accessorEvaluation = $returnPropertyName ? '$' . $returnPropertyName . ' = ' . $byRef . '$accessor();' : '$returnValue = ' . $byRef . '$accessor();' . "\n\n" . 'return $returnValue;'; if ($operationType === self::OPERATION_UNSET) { $accessorEvaluation = '$accessor();'; } return '$realInstanceReflection = ' . $originalClassReflection . ';' . "\n\n" . 'if (! $realInstanceReflection->hasProperty($' . $nameParameter . ')) {' . "\n" . ' $targetObject = ' . $target . ';' . "\n\n" . self::getUndefinedPropertyNotice($operationType, $nameParameter) . ' ' . self::getOperation($operationType, $nameParameter, $valueParameter) . "\n" . '}' . "\n\n" . '$targetObject = ' . self::getTargetObject($valueHolder) . ";\n" . '$accessor = function ' . $byRef . '() use (' . implode(', ', array_map( static function (string $parameterName): string { return '$' . $parameterName; }, array_filter(['targetObject', $nameParameter, $valueParameter]) )) . ') {' . "\n" . ' ' . self::getOperation($operationType, $nameParameter, $valueParameter) . "\n" . "};\n" . self::generateScopeReBind() . $accessorEvaluation; } /** * This will generate code that triggers a notice if access is attempted on a non-existing property * * @psalm-param $operationType self::OPERATION_* */ private static function getUndefinedPropertyNotice(string $operationType, string $nameParameter, ?string $interfaceName = null): string { if ($operationType !== self::OPERATION_GET) { return ''; } $code = ' $backtrace = debug_backtrace(false, 1);' . "\n" . ' trigger_error(' . "\n" . ' sprintf(' . "\n" . ' \'Undefined property: %s::$%s in %s on line %s\',' . "\n" . ' $realInstanceReflection->getName(),' . "\n" . ' $' . $nameParameter . ',' . "\n" . ' $backtrace[0][\'file\'],' . "\n" . ' $backtrace[0][\'line\']' . "\n" . ' ),' . "\n" . ' \E_USER_NOTICE' . "\n" . ' );' . "\n"; if ($interfaceName !== null) { $code = str_replace("\n ", "\n", substr($code, 4)); } return $code; } /** * Defines whether the given operation produces a reference. * * Note: if the object is a wrapper, the wrapped instance is accessed directly. If the object * is a ghost or the proxy has no wrapper, then an instance of the parent class is created via * on-the-fly unserialization * * @psalm-param $operationType self::OPERATION_* */ private static function getByRefReturnValue(string $operationType): string { return $operationType === self::OPERATION_GET || $operationType === self::OPERATION_SET ? '& ' : ''; } /** * Retrieves the logic to fetch the object on which access should be attempted */ private static function getTargetObject(?PropertyGenerator $valueHolder = null): string { if ($valueHolder) { return '$this->' . $valueHolder->getName(); } return '$realInstanceReflection->newInstanceWithoutConstructor()'; } /** * @psalm-param $operationType self::OPERATION_* * * @throws InvalidArgumentException */ private static function getOperation(string $operationType, string $nameParameter, ?string $valueParameter): string { if ($valueParameter !== null && $operationType !== self::OPERATION_SET) { throw new InvalidArgumentException( 'Parameter $valueParameter should be provided (only) when $operationType === "' . self::OPERATION_SET . '"' . self::class . '::OPERATION_SET' ); } switch ($operationType) { case self::OPERATION_GET: return 'return $targetObject->$' . $nameParameter . ';'; case self::OPERATION_SET: if ($valueParameter === null) { throw new InvalidArgumentException( 'Parameter $valueParameter should be provided (only) when $operationType === "' . self::OPERATION_SET . '"' . self::class . '::OPERATION_SET' ); } return '$targetObject->$' . $nameParameter . ' = $' . $valueParameter . ';' . "\n\n" . ' return $targetObject->$' . $nameParameter . ';'; case self::OPERATION_ISSET: return 'return isset($targetObject->$' . $nameParameter . ');'; case self::OPERATION_UNSET: return 'unset($targetObject->$' . $nameParameter . ');' . "\n\n" . ' return;'; } throw new InvalidArgumentException(sprintf('Invalid operation "%s" provided', $operationType)); } /** * Generates code to bind operations to the parent scope */ private static function generateScopeReBind(): string { return <<<'PHP' $backtrace = debug_backtrace(true, 2); $scopeObject = isset($backtrace[1]['object']) ? $backtrace[1]['object'] : new \ProxyManager\Stub\EmptyClassStub(); $accessor = $accessor->bindTo($scopeObject, get_class($scopeObject)); PHP; } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/Util/UnsetPropertiesGenerator.php 0000644 00000007125 15117764664 0025026 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\Util; use ReflectionClass; use ReflectionProperty; use function array_map; use function assert; use function implode; use function reset; use function sprintf; use function var_export; /** * Generates code necessary to unset all the given properties from a particular given instance string name */ final class UnsetPropertiesGenerator { private const CLOSURE_TEMPLATE = <<<'PHP' \Closure::bind(function (\%s $instance) { %s }, $%s, %s)->__invoke($%s); PHP; public static function generateSnippet(Properties $properties, string $instanceName): string { $scopedPropertyGroups = []; $nonScopedProperties = []; foreach ($properties->getInstanceProperties() as $propertyInternalName => $property) { if ($property->isPrivate() || (\PHP_VERSION_ID >= 80100 && $property->isReadOnly())) { $scopedPropertyGroups[$property->getDeclaringClass()->getName()][$property->getName()] = $property; } else { $nonScopedProperties[$propertyInternalName] = $property; } } return self::generateUnsetNonScopedPropertiesCode($nonScopedProperties, $instanceName) . self::generateUnsetScopedPropertiesCode($scopedPropertyGroups, $instanceName); } /** @param array<string, ReflectionProperty> $nonScopedProperties */ private static function generateUnsetNonScopedPropertiesCode(array $nonScopedProperties, string $instanceName): string { if (! $nonScopedProperties) { return ''; } return self::generateUnsetStatement($nonScopedProperties, $instanceName) . "\n\n"; } /** @param array<class-string, array<string, ReflectionProperty>> $scopedPropertyGroups */ private static function generateUnsetScopedPropertiesCode(array $scopedPropertyGroups, string $instanceName): string { if (! $scopedPropertyGroups) { return ''; } $unsetClosureCalls = []; foreach ($scopedPropertyGroups as $scopedProperties) { $firstProperty = reset($scopedProperties); assert($firstProperty instanceof ReflectionProperty); $unsetClosureCalls[] = self::generateUnsetClassScopedPropertiesBlock( $firstProperty->getDeclaringClass(), $scopedProperties, $instanceName ); } return implode("\n\n", $unsetClosureCalls) . "\n\n"; } /** @param array<string, ReflectionProperty> $properties */ private static function generateUnsetClassScopedPropertiesBlock( ReflectionClass $declaringClass, array $properties, string $instanceName ): string { $declaringClassName = $declaringClass->getName(); return sprintf( self::CLOSURE_TEMPLATE, $declaringClassName, self::generateUnsetStatement($properties, 'instance'), $instanceName, var_export($declaringClassName, true), $instanceName ); } /** @param array<string, ReflectionProperty> $properties */ private static function generateUnsetStatement(array $properties, string $instanceName): string { return 'unset(' . implode( ', ', array_map( static function (ReflectionProperty $property) use ($instanceName): string { return '$' . $instanceName . '->' . $property->getName(); }, $properties ) ) . ');'; } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/ValueHolder/MethodGenerator/Constructor.php 0000644 00000006163 15117764664 0026716 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\ValueHolder\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use Laminas\Code\Reflection\MethodReflection; use Laminas\Code\Reflection\ParameterReflection; use ProxyManager\Generator\MethodGenerator; use ProxyManager\ProxyGenerator\Util\Properties; use ProxyManager\ProxyGenerator\Util\UnsetPropertiesGenerator; use ReflectionClass; use ReflectionMethod; use function array_filter; use function array_map; use function implode; use function reset; use function var_export; /** * The `__construct` implementation for lazy loading proxies */ class Constructor extends MethodGenerator { /** * @throws InvalidArgumentException */ public static function generateMethod(ReflectionClass $originalClass, PropertyGenerator $valueHolder): self { $originalConstructor = self::getConstructor($originalClass); $constructor = $originalConstructor ? self::fromReflectionWithoutBodyAndDocBlock($originalConstructor) : new self('__construct'); $constructor->setBody( 'static $reflection;' . "\n\n" . 'if (! $this->' . $valueHolder->getName() . ') {' . "\n" . ' $reflection = $reflection ?? new \ReflectionClass(' . var_export($originalClass->getName(), true) . ");\n" . ' $this->' . $valueHolder->getName() . ' = $reflection->newInstanceWithoutConstructor();' . "\n" . UnsetPropertiesGenerator::generateSnippet(Properties::fromReflectionClass($originalClass), 'this') . '}' . ($originalConstructor ? self::generateOriginalConstructorCall($originalConstructor, $valueHolder) : '') ); return $constructor; } private static function generateOriginalConstructorCall( MethodReflection $originalConstructor, PropertyGenerator $valueHolder ): string { return "\n\n" . '$this->' . $valueHolder->getName() . '->' . $originalConstructor->getName() . '(' . implode( ', ', array_map( static function (ParameterReflection $parameter): string { return ($parameter->isVariadic() ? '...' : '') . '$' . $parameter->getName(); }, $originalConstructor->getParameters() ) ) . ');'; } private static function getConstructor(ReflectionClass $class): ?MethodReflection { $constructors = array_map( static function (ReflectionMethod $method): MethodReflection { return new MethodReflection( $method->getDeclaringClass()->getName(), $method->getName() ); }, array_filter( $class->getMethods(), static function (ReflectionMethod $method): bool { return $method->isConstructor(); } ) ); return reset($constructors) ?: null; } } src/ProxyManager/ProxyGenerator/ValueHolder/MethodGenerator/GetWrappedValueHolderValue.php 0000644 00000001402 15117764664 0031473 0 ustar 00 proxy-manager-lts <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\ValueHolder\MethodGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MethodGenerator; /** * Implementation for {@see \ProxyManager\Proxy\ValueHolderInterface::getWrappedValueHolderValue} * for lazy loading value holder objects */ class GetWrappedValueHolderValue extends MethodGenerator { /** * Constructor * * @throws InvalidArgumentException */ public function __construct(PropertyGenerator $valueHolderProperty) { parent::__construct('getWrappedValueHolderValue'); $this->setBody('return $this->' . $valueHolderProperty->getName() . ';'); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/ValueHolder/MethodGenerator/MagicSleep.php 0000644 00000001216 15117764664 0026374 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator\ValueHolder\MethodGenerator; use Laminas\Code\Generator\PropertyGenerator; use ProxyManager\Generator\MagicMethodGenerator; use ReflectionClass; use function var_export; /** * Magic `__sleep` for value holder objects */ class MagicSleep extends MagicMethodGenerator { /** * Constructor */ public function __construct(ReflectionClass $originalClass, PropertyGenerator $valueHolderProperty) { parent::__construct($originalClass, '__sleep'); $this->setBody('return array(' . var_export($valueHolderProperty->getName(), true) . ');'); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizerGenerator.php 0000644 00000011473 15117764664 0027216 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ClassGenerator; use Laminas\Code\Generator\MethodGenerator; use Laminas\Code\Reflection\MethodReflection; use ProxyManager\Exception\InvalidProxiedClassException; use ProxyManager\Generator\Util\ClassGeneratorUtils; use ProxyManager\Proxy\AccessInterceptorInterface; use ProxyManager\ProxyGenerator\AccessInterceptor\MethodGenerator\SetMethodPrefixInterceptor; use ProxyManager\ProxyGenerator\AccessInterceptor\MethodGenerator\SetMethodSuffixInterceptor; use ProxyManager\ProxyGenerator\AccessInterceptor\PropertyGenerator\MethodPrefixInterceptors; use ProxyManager\ProxyGenerator\AccessInterceptor\PropertyGenerator\MethodSuffixInterceptors; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\BindProxyProperties; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\InterceptedMethod; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\MagicClone; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\MagicGet; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\MagicIsset; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\MagicSet; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\MagicSleep; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\MagicUnset; use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\StaticProxyConstructor; use ProxyManager\ProxyGenerator\Assertion\CanProxyAssertion; use ProxyManager\ProxyGenerator\Util\ProxiedMethodsFilter; use ReflectionClass; use ReflectionMethod; use function array_map; use function array_merge; /** * Generator for proxies implementing {@see \ProxyManager\Proxy\ValueHolderInterface} * and localizing scope of the proxied object at instantiation * * {@inheritDoc} */ class AccessInterceptorScopeLocalizerGenerator implements ProxyGeneratorInterface { /** * {@inheritDoc} * * @return void * * @throws InvalidArgumentException * @throws InvalidProxiedClassException */ public function generate(ReflectionClass $originalClass, ClassGenerator $classGenerator) { CanProxyAssertion::assertClassCanBeProxied($originalClass, false); $classGenerator->setExtendedClass($originalClass->getName()); $classGenerator->setImplementedInterfaces([AccessInterceptorInterface::class]); $classGenerator->addPropertyFromGenerator($prefixInterceptors = new MethodPrefixInterceptors()); $classGenerator->addPropertyFromGenerator($suffixInterceptors = new MethodSuffixInterceptors()); array_map( static function (MethodGenerator $generatedMethod) use ($originalClass, $classGenerator): void { ClassGeneratorUtils::addMethodIfNotFinal($originalClass, $classGenerator, $generatedMethod); }, array_merge( array_map( $this->buildMethodInterceptor($prefixInterceptors, $suffixInterceptors), ProxiedMethodsFilter::getProxiedMethods( $originalClass, ['__get', '__set', '__isset', '__unset', '__clone', '__sleep'] ) ), [ new StaticProxyConstructor($originalClass), new BindProxyProperties($originalClass, $prefixInterceptors, $suffixInterceptors), new SetMethodPrefixInterceptor($prefixInterceptors), new SetMethodSuffixInterceptor($suffixInterceptors), new MagicGet($originalClass, $prefixInterceptors, $suffixInterceptors), new MagicSet($originalClass, $prefixInterceptors, $suffixInterceptors), new MagicIsset($originalClass, $prefixInterceptors, $suffixInterceptors), new MagicUnset($originalClass, $prefixInterceptors, $suffixInterceptors), new MagicSleep($originalClass, $prefixInterceptors, $suffixInterceptors), new MagicClone($originalClass, $prefixInterceptors, $suffixInterceptors), ] ) ); } private function buildMethodInterceptor( MethodPrefixInterceptors $prefixInterceptors, MethodSuffixInterceptors $suffixInterceptors ): callable { return static function (ReflectionMethod $method) use ($prefixInterceptors, $suffixInterceptors): InterceptedMethod { return InterceptedMethod::generateMethod( new MethodReflection($method->getDeclaringClass()->getName(), $method->getName()), $prefixInterceptors, $suffixInterceptors ); }; } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolderGenerator.php 0000644 00000014460 15117764664 0026511 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ClassGenerator; use Laminas\Code\Generator\MethodGenerator; use Laminas\Code\Reflection\MethodReflection; use ProxyManager\Exception\InvalidProxiedClassException; use ProxyManager\Generator\Util\ClassGeneratorUtils; use ProxyManager\Proxy\AccessInterceptorValueHolderInterface; use ProxyManager\ProxyGenerator\AccessInterceptor\MethodGenerator\MagicWakeup; use ProxyManager\ProxyGenerator\AccessInterceptor\MethodGenerator\SetMethodPrefixInterceptor; use ProxyManager\ProxyGenerator\AccessInterceptor\MethodGenerator\SetMethodSuffixInterceptor; use ProxyManager\ProxyGenerator\AccessInterceptor\PropertyGenerator\MethodPrefixInterceptors; use ProxyManager\ProxyGenerator\AccessInterceptor\PropertyGenerator\MethodSuffixInterceptors; use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\InterceptedMethod; use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\MagicClone; use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\MagicGet; use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\MagicIsset; use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\MagicSet; use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\MagicUnset; use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\StaticProxyConstructor; use ProxyManager\ProxyGenerator\Assertion\CanProxyAssertion; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\PropertyGenerator\ValueHolderProperty; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\Properties; use ProxyManager\ProxyGenerator\Util\ProxiedMethodsFilter; use ProxyManager\ProxyGenerator\ValueHolder\MethodGenerator\Constructor; use ProxyManager\ProxyGenerator\ValueHolder\MethodGenerator\GetWrappedValueHolderValue; use ProxyManager\ProxyGenerator\ValueHolder\MethodGenerator\MagicSleep; use ReflectionClass; use ReflectionMethod; use function array_map; use function array_merge; /** * Generator for proxies implementing {@see \ProxyManager\Proxy\ValueHolderInterface} * and {@see \ProxyManager\Proxy\AccessInterceptorInterface} * * {@inheritDoc} */ class AccessInterceptorValueHolderGenerator implements ProxyGeneratorInterface { /** * {@inheritDoc} * * @return void * * @throws InvalidArgumentException * @throws InvalidProxiedClassException */ public function generate(ReflectionClass $originalClass, ClassGenerator $classGenerator) { CanProxyAssertion::assertClassCanBeProxied($originalClass); $publicProperties = new PublicPropertiesMap(Properties::fromReflectionClass($originalClass)); $interfaces = [AccessInterceptorValueHolderInterface::class]; if ($originalClass->isInterface()) { $interfaces[] = $originalClass->getName(); } else { $classGenerator->setExtendedClass($originalClass->getName()); } $classGenerator->setImplementedInterfaces($interfaces); $classGenerator->addPropertyFromGenerator($valueHolder = new ValueHolderProperty($originalClass)); $classGenerator->addPropertyFromGenerator($prefixInterceptors = new MethodPrefixInterceptors()); $classGenerator->addPropertyFromGenerator($suffixInterceptors = new MethodSuffixInterceptors()); $classGenerator->addPropertyFromGenerator($publicProperties); array_map( static function (MethodGenerator $generatedMethod) use ($originalClass, $classGenerator): void { ClassGeneratorUtils::addMethodIfNotFinal($originalClass, $classGenerator, $generatedMethod); }, array_merge( array_map( $this->buildMethodInterceptor($prefixInterceptors, $suffixInterceptors, $valueHolder), ProxiedMethodsFilter::getProxiedMethods($originalClass) ), [ Constructor::generateMethod($originalClass, $valueHolder), new StaticProxyConstructor($originalClass, $valueHolder, $prefixInterceptors, $suffixInterceptors), new GetWrappedValueHolderValue($valueHolder), new SetMethodPrefixInterceptor($prefixInterceptors), new SetMethodSuffixInterceptor($suffixInterceptors), new MagicGet( $originalClass, $valueHolder, $prefixInterceptors, $suffixInterceptors, $publicProperties ), new MagicSet( $originalClass, $valueHolder, $prefixInterceptors, $suffixInterceptors, $publicProperties ), new MagicIsset( $originalClass, $valueHolder, $prefixInterceptors, $suffixInterceptors, $publicProperties ), new MagicUnset( $originalClass, $valueHolder, $prefixInterceptors, $suffixInterceptors, $publicProperties ), new MagicClone($originalClass, $valueHolder, $prefixInterceptors, $suffixInterceptors), new MagicSleep($originalClass, $valueHolder), new MagicWakeup($originalClass), ] ) ); } private function buildMethodInterceptor( MethodPrefixInterceptors $prefixes, MethodSuffixInterceptors $suffixes, ValueHolderProperty $valueHolder ): callable { return static function (ReflectionMethod $method) use ($prefixes, $suffixes, $valueHolder): InterceptedMethod { return InterceptedMethod::generateMethod( new MethodReflection($method->getDeclaringClass()->getName(), $method->getName()), $valueHolder, $prefixes, $suffixes ); }; } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/LazyLoadingGhostGenerator.php 0000644 00000016025 15117764664 0024157 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ClassGenerator; use Laminas\Code\Generator\MethodGenerator; use Laminas\Code\Reflection\MethodReflection; use ProxyManager\Exception\InvalidProxiedClassException; use ProxyManager\Generator\MethodGenerator as ProxyManagerMethodGenerator; use ProxyManager\Generator\Util\ClassGeneratorUtils; use ProxyManager\Proxy\GhostObjectInterface; use ProxyManager\ProxyGenerator\Assertion\CanProxyAssertion; use ProxyManager\ProxyGenerator\LazyLoading\MethodGenerator\StaticProxyConstructor; use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\CallInitializer; use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\GetProxyInitializer; use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\InitializeProxy; use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\IsProxyInitialized; use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicClone; use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicGet; use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicIsset; use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicSet; use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicSleep; use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicUnset; use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\SetProxyInitializer; use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\SkipDestructor; use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\InitializationTracker; use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\InitializerProperty; use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\PrivatePropertiesMap; use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\ProtectedPropertiesMap; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\Properties; use ProxyManager\ProxyGenerator\Util\ProxiedMethodsFilter; use ReflectionClass; use ReflectionMethod; use function array_map; use function array_merge; /** * Generator for proxies implementing {@see \ProxyManager\Proxy\GhostObjectInterface} * * {@inheritDoc} */ class LazyLoadingGhostGenerator implements ProxyGeneratorInterface { /** * {@inheritDoc} * * @psalm-param array{skippedProperties?: array<int, string>, skipDestructor?: bool} $proxyOptions * * @return void * * @throws InvalidProxiedClassException * @throws InvalidArgumentException */ public function generate(ReflectionClass $originalClass, ClassGenerator $classGenerator, array $proxyOptions = []) { CanProxyAssertion::assertClassCanBeProxied($originalClass, false); $filteredProperties = Properties::fromReflectionClass($originalClass) ->filter($proxyOptions['skippedProperties'] ?? []); $publicProperties = new PublicPropertiesMap($filteredProperties, true); $privateProperties = new PrivatePropertiesMap($filteredProperties); $protectedProperties = new ProtectedPropertiesMap($filteredProperties); $skipDestructor = ($proxyOptions['skipDestructor'] ?? false) && $originalClass->hasMethod('__destruct'); $classGenerator->setExtendedClass($originalClass->getName()); $classGenerator->setImplementedInterfaces([GhostObjectInterface::class]); $classGenerator->addPropertyFromGenerator($initializer = new InitializerProperty()); $classGenerator->addPropertyFromGenerator($initializationTracker = new InitializationTracker()); $classGenerator->addPropertyFromGenerator($publicProperties); $classGenerator->addPropertyFromGenerator($privateProperties); $classGenerator->addPropertyFromGenerator($protectedProperties); $init = new CallInitializer($initializer, $initializationTracker, $filteredProperties); array_map( static function (MethodGenerator $generatedMethod) use ($originalClass, $classGenerator): void { ClassGeneratorUtils::addMethodIfNotFinal($originalClass, $classGenerator, $generatedMethod); }, array_merge( $this->getAbstractProxiedMethods($originalClass, $skipDestructor), [ $init, new StaticProxyConstructor($initializer, $filteredProperties), new MagicGet( $originalClass, $initializer, $init, $publicProperties, $protectedProperties, $privateProperties, $initializationTracker ), new MagicSet( $originalClass, $initializer, $init, $publicProperties, $protectedProperties, $privateProperties ), new MagicIsset( $originalClass, $initializer, $init, $publicProperties, $protectedProperties, $privateProperties ), new MagicUnset( $originalClass, $initializer, $init, $publicProperties, $protectedProperties, $privateProperties ), new MagicClone($originalClass, $initializer, $init), new MagicSleep($originalClass, $initializer, $init), new SetProxyInitializer($initializer), new GetProxyInitializer($initializer), new InitializeProxy($initializer, $init), new IsProxyInitialized($initializer), ], $skipDestructor ? [new SkipDestructor($initializer)] : [] ) ); } /** * Retrieves all abstract methods to be proxied * * @return MethodGenerator[] */ private function getAbstractProxiedMethods(ReflectionClass $originalClass, bool $skipDestructor): array { $excludedMethods = ProxiedMethodsFilter::DEFAULT_EXCLUDED; if ($skipDestructor) { $excludedMethods[] = '__destruct'; } return array_map( static function (ReflectionMethod $method): ProxyManagerMethodGenerator { $generated = ProxyManagerMethodGenerator::fromReflectionWithoutBodyAndDocBlock( new MethodReflection($method->getDeclaringClass()->getName(), $method->getName()) ); $generated->setAbstract(false); return $generated; }, ProxiedMethodsFilter::getAbstractProxiedMethods($originalClass, $excludedMethods) ); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolderGenerator.php 0000644 00000016172 15117764664 0025310 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator; use InvalidArgumentException; use Laminas\Code\Generator\ClassGenerator; use Laminas\Code\Generator\MethodGenerator; use Laminas\Code\Reflection\MethodReflection; use ProxyManager\Exception\InvalidProxiedClassException; use ProxyManager\Generator\Util\ClassGeneratorUtils; use ProxyManager\Proxy\VirtualProxyInterface; use ProxyManager\ProxyGenerator\AccessInterceptor\MethodGenerator\MagicWakeup; use ProxyManager\ProxyGenerator\Assertion\CanProxyAssertion; use ProxyManager\ProxyGenerator\LazyLoading\MethodGenerator\StaticProxyConstructor; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator\GetProxyInitializer; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator\InitializeProxy; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator\IsProxyInitialized; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator\LazyLoadingMethodInterceptor; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator\MagicClone; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator\MagicGet; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator\MagicIsset; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator\MagicSet; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator\MagicSleep; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator\MagicUnset; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator\SetProxyInitializer; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator\SkipDestructor; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\PropertyGenerator\InitializerProperty; use ProxyManager\ProxyGenerator\LazyLoadingValueHolder\PropertyGenerator\ValueHolderProperty; use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap; use ProxyManager\ProxyGenerator\Util\Properties; use ProxyManager\ProxyGenerator\Util\ProxiedMethodsFilter; use ProxyManager\ProxyGenerator\ValueHolder\MethodGenerator\Constructor; use ProxyManager\ProxyGenerator\ValueHolder\MethodGenerator\GetWrappedValueHolderValue; use ReflectionClass; use ReflectionMethod; use function array_map; use function array_merge; use function func_get_arg; use function func_num_args; use function str_replace; use function substr; /** * Generator for proxies implementing {@see \ProxyManager\Proxy\VirtualProxyInterface} * * {@inheritDoc} */ class LazyLoadingValueHolderGenerator implements ProxyGeneratorInterface { /** * {@inheritDoc} * * @psalm-param array{skipDestructor?: bool, fluentSafe?: bool} $proxyOptions * * @return void * * @throws InvalidProxiedClassException * @throws InvalidArgumentException */ public function generate(ReflectionClass $originalClass, ClassGenerator $classGenerator/*, array $proxyOptions = []*/) { /** @psalm-var array{skipDestructor?: bool, fluentSafe?: bool} $proxyOptions */ $proxyOptions = func_num_args() >= 3 ? func_get_arg(2) : []; CanProxyAssertion::assertClassCanBeProxied($originalClass); $interfaces = [VirtualProxyInterface::class]; $publicProperties = new PublicPropertiesMap(Properties::fromReflectionClass($originalClass)); if ($originalClass->isInterface()) { $interfaces[] = $originalClass->getName(); } else { $classGenerator->setExtendedClass($originalClass->getName()); } $classGenerator->setImplementedInterfaces($interfaces); $classGenerator->addPropertyFromGenerator($valueHolder = new ValueHolderProperty($originalClass)); $classGenerator->addPropertyFromGenerator($initializer = new InitializerProperty()); $classGenerator->addPropertyFromGenerator($publicProperties); $skipDestructor = ($proxyOptions['skipDestructor'] ?? false) && $originalClass->hasMethod('__destruct'); $excludedMethods = ProxiedMethodsFilter::DEFAULT_EXCLUDED; if ($skipDestructor) { $excludedMethods[] = '__destruct'; } array_map( static function (MethodGenerator $generatedMethod) use ($originalClass, $classGenerator): void { ClassGeneratorUtils::addMethodIfNotFinal($originalClass, $classGenerator, $generatedMethod); }, array_merge( array_map( $this->buildLazyLoadingMethodInterceptor($initializer, $valueHolder, $proxyOptions['fluentSafe'] ?? false), ProxiedMethodsFilter::getProxiedMethods($originalClass, $excludedMethods) ), [ new StaticProxyConstructor($initializer, Properties::fromReflectionClass($originalClass)), Constructor::generateMethod($originalClass, $valueHolder), new MagicGet($originalClass, $initializer, $valueHolder, $publicProperties), new MagicSet($originalClass, $initializer, $valueHolder, $publicProperties), new MagicIsset($originalClass, $initializer, $valueHolder, $publicProperties), new MagicUnset($originalClass, $initializer, $valueHolder, $publicProperties), new MagicClone($originalClass, $initializer, $valueHolder), new MagicSleep($originalClass, $initializer, $valueHolder), new MagicWakeup($originalClass), new SetProxyInitializer($initializer), new GetProxyInitializer($initializer), new InitializeProxy($initializer, $valueHolder), new IsProxyInitialized($valueHolder), new GetWrappedValueHolderValue($valueHolder), ], $skipDestructor ? [new SkipDestructor($initializer, $valueHolder)] : [] ) ); } private function buildLazyLoadingMethodInterceptor( InitializerProperty $initializer, ValueHolderProperty $valueHolder, bool $fluentSafe ): callable { return static function (ReflectionMethod $method) use ($initializer, $valueHolder, $fluentSafe): LazyLoadingMethodInterceptor { $byRef = $method->returnsReference() ? '& ' : ''; $method = LazyLoadingMethodInterceptor::generateMethod( new MethodReflection($method->getDeclaringClass()->getName(), $method->getName()), $initializer, $valueHolder ); if ($fluentSafe) { $valueHolderName = '$this->' . $valueHolder->getName(); $body = $method->getBody(); $newBody = str_replace('return ' . $valueHolderName, 'if (' . $valueHolderName . ' === $returnValue = ' . $byRef . $valueHolderName, $body); if ($newBody !== $body) { $method->setBody( substr($newBody, 0, -1) . ') {' . "\n" . ' return $this;' . "\n" . '}' . "\n\n" . 'return $returnValue;' ); } } return $method; }; } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/NullObjectGenerator.php 0000644 00000003746 15117764664 0023004 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator; use Laminas\Code\Generator\ClassGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Reflection\MethodReflection; use ProxyManager\Exception\InvalidProxiedClassException; use ProxyManager\Generator\Util\ClassGeneratorUtils; use ProxyManager\Proxy\NullObjectInterface; use ProxyManager\ProxyGenerator\Assertion\CanProxyAssertion; use ProxyManager\ProxyGenerator\NullObject\MethodGenerator\NullObjectMethodInterceptor; use ProxyManager\ProxyGenerator\NullObject\MethodGenerator\StaticProxyConstructor; use ProxyManager\ProxyGenerator\Util\ProxiedMethodsFilter; use ReflectionClass; /** * Generator for proxies implementing {@see \ProxyManager\Proxy\NullObjectInterface} * * {@inheritDoc} */ class NullObjectGenerator implements ProxyGeneratorInterface { /** * {@inheritDoc} * * @throws InvalidProxiedClassException * @throws InvalidArgumentException */ public function generate(ReflectionClass $originalClass, ClassGenerator $classGenerator): void { CanProxyAssertion::assertClassCanBeProxied($originalClass); $interfaces = [NullObjectInterface::class]; if ($originalClass->isInterface()) { $interfaces[] = $originalClass->getName(); } else { $classGenerator->setExtendedClass($originalClass->getName()); } $classGenerator->setImplementedInterfaces($interfaces); foreach (ProxiedMethodsFilter::getProxiedMethods($originalClass, []) as $method) { $classGenerator->addMethodFromGenerator( NullObjectMethodInterceptor::generateMethod( new MethodReflection($method->getDeclaringClass()->getName(), $method->getName()) ) ); } ClassGeneratorUtils::addMethodIfNotFinal( $originalClass, $classGenerator, new StaticProxyConstructor($originalClass) ); } } proxy-manager-lts/src/ProxyManager/ProxyGenerator/ProxyGeneratorInterface.php 0000644 00000001450 15117764664 0023673 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator; use Laminas\Code\Generator\ClassGenerator; use ReflectionClass; class_exists(\Zend\Code\Generator\ClassGenerator::class); /** * Base interface for proxy generators - describes how a proxy generator should use * reflection classes to modify given class generators */ interface ProxyGeneratorInterface { /** * Apply modifications to the provided $classGenerator to proxy logic from $originalClass * * Due to BC compliance, we cannot add a native `: void` return type declaration here * * phpcs:disable SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint * * @return void */ public function generate(ReflectionClass $originalClass, ClassGenerator $classGenerator); } proxy-manager-lts/src/ProxyManager/ProxyGenerator/RemoteObjectGenerator.php 0000644 00000006517 15117764664 0023324 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\ProxyGenerator; use Laminas\Code\Generator\ClassGenerator; use Laminas\Code\Generator\Exception\InvalidArgumentException; use Laminas\Code\Generator\MethodGenerator; use Laminas\Code\Reflection\MethodReflection; use ProxyManager\Exception\InvalidProxiedClassException; use ProxyManager\Generator\Util\ClassGeneratorUtils; use ProxyManager\Proxy\RemoteObjectInterface; use ProxyManager\ProxyGenerator\Assertion\CanProxyAssertion; use ProxyManager\ProxyGenerator\RemoteObject\MethodGenerator\MagicGet; use ProxyManager\ProxyGenerator\RemoteObject\MethodGenerator\MagicIsset; use ProxyManager\ProxyGenerator\RemoteObject\MethodGenerator\MagicSet; use ProxyManager\ProxyGenerator\RemoteObject\MethodGenerator\MagicUnset; use ProxyManager\ProxyGenerator\RemoteObject\MethodGenerator\RemoteObjectMethod; use ProxyManager\ProxyGenerator\RemoteObject\MethodGenerator\StaticProxyConstructor; use ProxyManager\ProxyGenerator\RemoteObject\PropertyGenerator\AdapterProperty; use ProxyManager\ProxyGenerator\Util\ProxiedMethodsFilter; use ReflectionClass; use ReflectionMethod; use function array_map; use function array_merge; /** * Generator for proxies implementing {@see \ProxyManager\Proxy\RemoteObjectInterface} * * {@inheritDoc} */ class RemoteObjectGenerator implements ProxyGeneratorInterface { /** * {@inheritDoc} * * @return void * * @throws InvalidProxiedClassException * @throws InvalidArgumentException */ public function generate(ReflectionClass $originalClass, ClassGenerator $classGenerator) { CanProxyAssertion::assertClassCanBeProxied($originalClass); $interfaces = [RemoteObjectInterface::class]; if ($originalClass->isInterface()) { $interfaces[] = $originalClass->getName(); } else { $classGenerator->setExtendedClass($originalClass->getName()); } $classGenerator->setImplementedInterfaces($interfaces); $classGenerator->addPropertyFromGenerator($adapter = new AdapterProperty()); array_map( static function (MethodGenerator $generatedMethod) use ($originalClass, $classGenerator): void { ClassGeneratorUtils::addMethodIfNotFinal($originalClass, $classGenerator, $generatedMethod); }, array_merge( array_map( static function (ReflectionMethod $method) use ($adapter, $originalClass): RemoteObjectMethod { return RemoteObjectMethod::generateMethod( new MethodReflection($method->getDeclaringClass()->getName(), $method->getName()), $adapter, $originalClass ); }, ProxiedMethodsFilter::getProxiedMethods( $originalClass, ['__get', '__set', '__isset', '__unset'] ) ), [ new StaticProxyConstructor($originalClass, $adapter), new MagicGet($originalClass, $adapter), new MagicSet($originalClass, $adapter), new MagicIsset($originalClass, $adapter), new MagicUnset($originalClass, $adapter), ] ) ); } } proxy-manager-lts/src/ProxyManager/Signature/Exception/ExceptionInterface.php 0000644 00000000273 15117764664 0023552 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Signature\Exception; /** * Exception marker for exceptions from the signature sub-component */ interface ExceptionInterface { } proxy-manager-lts/src/ProxyManager/Signature/Exception/InvalidSignatureException.php 0000644 00000001455 15117764664 0025125 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Signature\Exception; use ReflectionClass; use UnexpectedValueException; use function count; use function sprintf; /** * Exception for invalid provided signatures */ class InvalidSignatureException extends UnexpectedValueException implements ExceptionInterface { /** @param mixed[] $parameters */ public static function fromInvalidSignature( ReflectionClass $class, array $parameters, string $signature, string $expected ): self { return new self(sprintf( 'Found signature "%s" for class "%s" does not correspond to expected signature "%s" for %d parameters', $signature, $class->getName(), $expected, count($parameters) )); } } proxy-manager-lts/src/ProxyManager/Signature/Exception/MissingSignatureException.php 0000644 00000001300 15117764664 0025135 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Signature\Exception; use ReflectionClass; use UnexpectedValueException; use function count; use function sprintf; /** * Exception for no found signatures */ class MissingSignatureException extends UnexpectedValueException implements ExceptionInterface { /** @param mixed[] $parameters */ public static function fromMissingSignature(ReflectionClass $class, array $parameters, string $expected): self { return new self(sprintf( 'No signature found for class "%s", expected signature "%s" for %d parameters', $class->getName(), $expected, count($parameters) )); } } proxy-manager-lts/src/ProxyManager/Signature/ClassSignatureGenerator.php 0000644 00000002100 15117764664 0022622 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Signature; use Laminas\Code\Exception\InvalidArgumentException; use Laminas\Code\Generator\ClassGenerator; use Laminas\Code\Generator\PropertyGenerator; /** * Applies a signature to a given class generator */ final class ClassSignatureGenerator implements ClassSignatureGeneratorInterface { private $signatureGenerator; public function __construct(SignatureGeneratorInterface $signatureGenerator) { $this->signatureGenerator = $signatureGenerator; } /** * {@inheritDoc} * * @throws InvalidArgumentException */ public function addSignature(ClassGenerator $classGenerator, array $parameters): ClassGenerator { $classGenerator->addPropertyFromGenerator(new PropertyGenerator( 'signature' . $this->signatureGenerator->generateSignatureKey($parameters), $this->signatureGenerator->generateSignature($parameters), PropertyGenerator::FLAG_STATIC | PropertyGenerator::FLAG_PRIVATE )); return $classGenerator; } } proxy-manager-lts/src/ProxyManager/Signature/ClassSignatureGeneratorInterface.php 0000644 00000000765 15117764664 0024462 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Signature; use Laminas\Code\Generator\ClassGenerator; class_exists(\Zend\Code\Generator\ClassGenerator::class); /** * Applies a signature to a given class generator */ interface ClassSignatureGeneratorInterface { /** * Applies a signature to a given class generator * * @param array<string, mixed> $parameters */ public function addSignature(ClassGenerator $classGenerator, array $parameters): ClassGenerator; } proxy-manager-lts/src/ProxyManager/Signature/SignatureChecker.php 0000644 00000002761 15117764664 0021267 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Signature; use ProxyManager\Signature\Exception\InvalidSignatureException; use ProxyManager\Signature\Exception\MissingSignatureException; use ReflectionClass; use function array_key_exists; use function is_string; /** * Generator for signatures to be used to check the validity of generated code */ final class SignatureChecker implements SignatureCheckerInterface { private $signatureGenerator; public function __construct(SignatureGeneratorInterface $signatureGenerator) { $this->signatureGenerator = $signatureGenerator; } /** * {@inheritDoc} */ public function checkSignature(ReflectionClass $class, array $parameters): void { $propertyName = 'signature' . $this->signatureGenerator->generateSignatureKey($parameters); $signature = $this->signatureGenerator->generateSignature($parameters); $defaultProperties = $class->getDefaultProperties(); if (! (array_key_exists($propertyName, $defaultProperties) && is_string($defaultProperties[$propertyName]))) { throw MissingSignatureException::fromMissingSignature($class, $parameters, $signature); } if ($defaultProperties[$propertyName] !== $signature) { throw InvalidSignatureException::fromInvalidSignature( $class, $parameters, $defaultProperties[$propertyName], $signature ); } } } proxy-manager-lts/src/ProxyManager/Signature/SignatureCheckerInterface.php 0000644 00000001207 15117764664 0023102 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Signature; use ProxyManager\Signature\Exception\InvalidSignatureException; use ProxyManager\Signature\Exception\MissingSignatureException; use ReflectionClass; /** * Generator for signatures to be used to check the validity of generated code */ interface SignatureCheckerInterface { /** * Checks whether the given signature is valid or not * * @param array<string, mixed> $parameters * * @throws InvalidSignatureException * @throws MissingSignatureException */ public function checkSignature(ReflectionClass $class, array $parameters): void; } proxy-manager-lts/src/ProxyManager/Signature/SignatureGenerator.php 0000644 00000001505 15117764664 0021644 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Signature; use ProxyManager\Inflector\Util\ParameterEncoder; use ProxyManager\Inflector\Util\ParameterHasher; final class SignatureGenerator implements SignatureGeneratorInterface { private $parameterEncoder; private $parameterHasher; public function __construct() { $this->parameterEncoder = new ParameterEncoder(); $this->parameterHasher = new ParameterHasher(); } /** * {@inheritDoc} */ public function generateSignature(array $parameters): string { return $this->parameterEncoder->encodeParameters($parameters); } /** * {@inheritDoc} */ public function generateSignatureKey(array $parameters): string { return $this->parameterHasher->hashParameters($parameters); } } proxy-manager-lts/src/ProxyManager/Signature/SignatureGeneratorInterface.php 0000644 00000001173 15117764664 0023466 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Signature; /** * Generator for signatures to be used to check the validity of generated code */ interface SignatureGeneratorInterface { /** * Generates a signature to be used to verify generated code validity * * @param array<string, mixed> $parameters */ public function generateSignature(array $parameters): string; /** * Generates a signature key to be looked up when verifying generated code validity * * @param array<string, mixed> $parameters */ public function generateSignatureKey(array $parameters): string; } proxy-manager-lts/src/ProxyManager/Stub/EmptyClassStub.php 0000644 00000000212 15117764664 0017724 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager\Stub; /** * Just an empty instantiable class */ final class EmptyClassStub { } proxy-manager-lts/src/ProxyManager/Configuration.php 0000644 00000010132 15117764664 0016676 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager; use ProxyManager\Autoloader\Autoloader; use ProxyManager\Autoloader\AutoloaderInterface; use ProxyManager\FileLocator\FileLocator; use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy; use ProxyManager\GeneratorStrategy\GeneratorStrategyInterface; use ProxyManager\Inflector\ClassNameInflector; use ProxyManager\Inflector\ClassNameInflectorInterface; use ProxyManager\Signature\ClassSignatureGenerator; use ProxyManager\Signature\ClassSignatureGeneratorInterface; use ProxyManager\Signature\SignatureChecker; use ProxyManager\Signature\SignatureCheckerInterface; use ProxyManager\Signature\SignatureGenerator; use ProxyManager\Signature\SignatureGeneratorInterface; use function sys_get_temp_dir; /** * Base configuration class for the proxy manager - serves as micro disposable DIC/facade */ class Configuration { public const DEFAULT_PROXY_NAMESPACE = 'ProxyManagerGeneratedProxy'; protected $proxiesTargetDir; protected $proxiesNamespace = self::DEFAULT_PROXY_NAMESPACE; protected $generatorStrategy; protected $proxyAutoloader; protected $classNameInflector; protected $signatureGenerator; protected $signatureChecker; protected $classSignatureGenerator; public function setProxyAutoloader(AutoloaderInterface $proxyAutoloader): void { $this->proxyAutoloader = $proxyAutoloader; } public function getProxyAutoloader(): AutoloaderInterface { return $this->proxyAutoloader ?? $this->proxyAutoloader = new Autoloader( new FileLocator($this->getProxiesTargetDir()), $this->getClassNameInflector() ); } public function setProxiesNamespace(string $proxiesNamespace): void { $this->proxiesNamespace = $proxiesNamespace; } public function getProxiesNamespace(): string { return $this->proxiesNamespace; } public function setProxiesTargetDir(string $proxiesTargetDir): void { $this->proxiesTargetDir = $proxiesTargetDir; } public function getProxiesTargetDir(): string { return $this->proxiesTargetDir ?? $this->proxiesTargetDir = sys_get_temp_dir(); } public function setGeneratorStrategy(GeneratorStrategyInterface $generatorStrategy): void { $this->generatorStrategy = $generatorStrategy; } public function getGeneratorStrategy(): GeneratorStrategyInterface { return $this->generatorStrategy ?? $this->generatorStrategy = new EvaluatingGeneratorStrategy(); } public function setClassNameInflector(ClassNameInflectorInterface $classNameInflector): void { $this->classNameInflector = $classNameInflector; } public function getClassNameInflector(): ClassNameInflectorInterface { return $this->classNameInflector ?? $this->classNameInflector = new ClassNameInflector($this->getProxiesNamespace()); } public function setSignatureGenerator(SignatureGeneratorInterface $signatureGenerator): void { $this->signatureGenerator = $signatureGenerator; } public function getSignatureGenerator(): SignatureGeneratorInterface { return $this->signatureGenerator ?? $this->signatureGenerator = new SignatureGenerator(); } public function setSignatureChecker(SignatureCheckerInterface $signatureChecker): void { $this->signatureChecker = $signatureChecker; } public function getSignatureChecker(): SignatureCheckerInterface { return $this->signatureChecker ?? $this->signatureChecker = new SignatureChecker($this->getSignatureGenerator()); } public function setClassSignatureGenerator(ClassSignatureGeneratorInterface $classSignatureGenerator): void { $this->classSignatureGenerator = $classSignatureGenerator; } public function getClassSignatureGenerator(): ClassSignatureGeneratorInterface { return $this->classSignatureGenerator ?? $this->classSignatureGenerator = new ClassSignatureGenerator($this->getSignatureGenerator()); } } proxy-manager-lts/src/ProxyManager/Version.php 0000644 00000003142 15117764664 0015517 0 ustar 00 <?php declare(strict_types=1); namespace ProxyManager; use Composer\InstalledVersions; use PackageVersions\Versions; use OutOfBoundsException; use function class_exists; /** * Version class * * Note that we cannot check the version at runtime via `git` because that would cause a lot of I/O operations. */ final class Version { /** * Private constructor - this class is not meant to be instantiated */ private function __construct() { } /** * Retrieves the package version in the format <detected-version>@<commit-hash>, * where the detected version is what composer could detect. * * @throws OutOfBoundsException * * @psalm-pure * * @psalm-suppress MixedOperand `composer-runtime-api:^2` has rough if no type declarations at all - we'll live with it * @psalm-suppress ImpureMethodCall `composer-runtime-api:^2` has rough if no type declarations at all - we'll live with it */ public static function getVersion(): string { if (class_exists(InstalledVersions::class) && InstalledVersions::isInstalled('friendsofphp/proxy-manager-lts')) { return InstalledVersions::getPrettyVersion('friendsofphp/proxy-manager-lts') . '@' . InstalledVersions::getReference('friendsofphp/proxy-manager-lts'); } if (class_exists(Versions::class)) { try { return Versions::getVersion('friendsofphp/proxy-manager-lts'); } catch (\OutOfBoundsException $e) { // no-op } } return '1@friendsofphp/proxy-manager-lts'; } } proxy-manager-lts/LICENSE 0000644 00000002041 15117764664 0011160 0 ustar 00 Copyright (c) 2013 Marco Pivetta Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. proxy-manager-lts/README.md 0000644 00000001352 15117764664 0011436 0 ustar 00 # FriendsOfPHP / Proxy Manager LTS This package is a fork of the excellent [`ocramius/proxy-manager`](https://github.com/Ocramius/ProxyManager/) library that adds long term support for a wider range of PHP versions. Unless they're caused by this very fork, please report issues and submit new features to the origin library. This fork: - maintains compatibility with PHP `>=7.1`; supporting new versions of PHP is considered as a bugfix; - won't bump the minimum supported version of PHP in a minor release; - does not depend on Composer 2, thus can be used with Composer 1 if you need more time to migrate; - uses a versioning policy that is friendly to progressive migrations while providing the latest improvements from the origin lib. proxy-manager-lts/composer.json 0000644 00000003370 15117764664 0012703 0 ustar 00 { "name": "friendsofphp/proxy-manager-lts", "description": "Adding support for a wider range of PHP versions to ocramius/proxy-manager", "type": "library", "license": "MIT", "homepage": "https://github.com/FriendsOfPHP/proxy-manager-lts", "keywords": [ "proxy", "proxy pattern", "service proxies", "lazy loading", "aop" ], "authors": [ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", "homepage": "https://ocramius.github.io/" }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" } ], "replace": { "ocramius/proxy-manager": "^2.1" }, "require": { "php": ">=7.1", "laminas/laminas-code": "~3.4.1|^4.0", "symfony/filesystem": "^4.4.17|^5.0|^6.0|^7.0" }, "conflict": { "zendframework/zend-stdlib": "<3.2.1", "laminas/laminas-stdlib": "<3.2.1" }, "require-dev": { "ext-phar": "*", "symfony/phpunit-bridge": "^5.4|^6.0|^7.0" }, "autoload": { "psr-4": { "ProxyManager\\": "src/ProxyManager" } }, "autoload-dev": { "psr-4": { "ProxyManagerTest\\": "tests/ProxyManagerTest", "ProxyManagerTestAsset\\": "tests/ProxyManagerTestAsset", "Laminas\\Server\\": "tests/Stubbed/Laminas/Server" } }, "minimum-stability": "dev", "extra": { "thanks": { "name": "ocramius/proxy-manager", "url": "https://github.com/Ocramius/ProxyManager" } } }
Coded With 💗 by
0x6ick