pax_global_header00006660000000000000000000000064140750503240014512gustar00rootroot0000000000000052 comment=0534eb56d8ef81d4169adb27eb28461181c8a282 php-proxy-manager-2.11.1+1.0.5/000077500000000000000000000000001407505032400156075ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/.github/000077500000000000000000000000001407505032400171475ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/.github/FUNDING.yml000066400000000000000000000001001407505032400207530ustar00rootroot00000000000000github: [Ocramius] tidelift: "packagist/ocramius/proxy-manager" php-proxy-manager-2.11.1+1.0.5/.github/workflows/000077500000000000000000000000001407505032400212045ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/.github/workflows/phpunit.yml000066400000000000000000000023001407505032400234110ustar00rootroot00000000000000name: "PHPUnit tests" on: pull_request: push: jobs: phpunit: name: "PHPUnit tests" runs-on: ${{ matrix.operating-system }} strategy: matrix: php-version: - "7.1" - "7.2" - "7.3" - "7.4" - "8.0" operating-system: - "ubuntu-latest" steps: - name: "Checkout" uses: "actions/checkout@v2" - name: "Install PHP" uses: "shivammathur/setup-php@v2" with: coverage: "pcov" php-version: "${{ matrix.php-version }}" ini-values: memory_limit=-1 tools: composer:v2, cs2pr - name: "Cache dependencies" uses: "actions/cache@v2" with: path: | ~/.composer/cache vendor key: "php-${{ matrix.php-version }}" restore-keys: "php-${{ matrix.php-version }}" - name: "Test with lowest dependencies" run: "composer update --prefer-lowest --no-interaction --no-progress --no-suggest && vendor/bin/simple-phpunit" - name: "Test with highest dependencies" run: "composer update --no-interaction --no-progress --no-suggest && vendor/bin/simple-phpunit" php-proxy-manager-2.11.1+1.0.5/.gitignore000066400000000000000000000002101407505032400175700ustar00rootroot00000000000000vendor composer.phar composer.lock phpunit.xml phpmd.xml phpdox.xml clover.xml infectionlog.json infectionlog.txt .phpunit.result.cache php-proxy-manager-2.11.1+1.0.5/LICENSE000066400000000000000000000020411407505032400166110ustar00rootroot00000000000000Copyright (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. php-proxy-manager-2.11.1+1.0.5/README.md000066400000000000000000000013521407505032400170670ustar00rootroot00000000000000# 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. php-proxy-manager-2.11.1+1.0.5/composer.json000066400000000000000000000033551407505032400203370ustar00rootroot00000000000000{ "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": "http://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" }, "conflict": { "zendframework/zend-stdlib": "<3.2.1", "laminas/laminas-stdlib": "<3.2.1" }, "require-dev": { "ext-phar": "*", "symfony/phpunit-bridge": "^5.2|^6.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" } } } php-proxy-manager-2.11.1+1.0.5/phpunit.xml.dist000066400000000000000000000020451407505032400207630ustar00rootroot00000000000000 ./tests/ProxyManagerTest ./tests/language-feature-scripts ./src php-proxy-manager-2.11.1+1.0.5/src/000077500000000000000000000000001407505032400163765ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/000077500000000000000000000000001407505032400210125ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Autoloader/000077500000000000000000000000001407505032400231115ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Autoloader/Autoloader.php000066400000000000000000000021051407505032400257170ustar00rootroot00000000000000fileLocator = $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; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Autoloader/AutoloaderInterface.php000066400000000000000000000006221407505032400275420ustar00rootroot00000000000000proxyAutoloader = $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()); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Exception/000077500000000000000000000000001407505032400227505ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Exception/DisabledMethodException.php000066400000000000000000000007171407505032400302150ustar00rootroot00000000000000getMessage(), 0, $previous); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Exception/InvalidProxiedClassException.php000066400000000000000000000033021407505032400312450ustar00rootroot00000000000000getName())); } 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(); } ) ) ) )); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Exception/InvalidProxyDirectoryException.php000066400000000000000000000006761407505032400316660ustar00rootroot00000000000000getName(), $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())) )); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Factory/000077500000000000000000000000001407505032400224215ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Factory/AbstractBaseFactory.php000066400000000000000000000077761407505032400270410ustar00rootroot00000000000000 * @psalm-var array */ private $checkedClasses = []; public function __construct(?Configuration $configuration = null) { $this->configuration = $configuration ?? new Configuration(); } /** * Generate a proxy from a class name * * @param array $proxyOptions * * @throws InvalidSignatureException * @throws MissingSignatureException * @throws OutOfBoundsException * * @psalm-template RealObjectType of object * * @psalm-param class-string $className * * @psalm-return class-string */ 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 $proxyParameters * @param array $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); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Factory/AccessInterceptorScopeLocalizerFactory.php000066400000000000000000000057771407505032400327610ustar00rootroot00000000000000generator = new AccessInterceptorScopeLocalizerGenerator(); } /** * @param object $instance the object to be localized within the access interceptor * @param array $prefixInterceptors an array (indexed by method name) of interceptor closures to be called * before method logic is executed * @param array $suffixInterceptors an array (indexed by method name) of interceptor closures to be called * after method logic is executed * * @throws InvalidSignatureException * @throws MissingSignatureException * @throws OutOfBoundsException * * @psalm-template RealObjectType of object * * @psalm-param RealObjectType $instance * @psalm-param array=, * RealObjectType=, * string=, * array=, * bool= * ) : mixed> $prefixInterceptors * @psalm-param array=, * RealObjectType=, * string=, * array=, * mixed=, * bool= * ) : mixed> $suffixInterceptors * * @psalm-return RealObjectType&AccessInterceptorInterface * * @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; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Factory/AccessInterceptorValueHolderFactory.php000066400000000000000000000063011407505032400322350ustar00rootroot00000000000000generator = new AccessInterceptorValueHolderGenerator(); } /** * @param object $instance the object to be wrapped within the value holder * @param array $prefixInterceptors an array (indexed by method name) of interceptor closures to be called * before method logic is executed * @param array $suffixInterceptors an array (indexed by method name) of interceptor closures to be called * after method logic is executed * * @throws InvalidSignatureException * @throws MissingSignatureException * @throws OutOfBoundsException * * @psalm-template RealObjectType of object * * @psalm-param RealObjectType $instance * @psalm-param array=, * RealObjectType=, * string=, * array=, * bool= * ) : mixed> $prefixInterceptors * @psalm-param array=, * RealObjectType=, * string=, * array=, * mixed=, * bool= * ) : mixed> $suffixInterceptors * * @psalm-return RealObjectType&AccessInterceptorInterface&ValueHolderInterface&AccessInterceptorValueHolderInterface * * @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; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Factory/LazyLoadingGhostFactory.php000066400000000000000000000106561407505032400277140ustar00rootroot00000000000000generator = 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: * * * $initializer = function ( * GhostObjectInterface $proxy, * string $method, * array $parameters, * & $initializer, * array $properties * ) {}; * * * 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") * * @throws MissingSignatureException * @throws InvalidSignatureException * @throws OutOfBoundsException * * @psalm-template RealObjectType as object * * @psalm-param class-string $className * @psalm-param Closure( * RealObjectType&GhostObjectInterface=, * string=, * array=, * ?Closure=, * array= * ) : bool $initializer * @psalm-param array{skippedProperties?: array} $proxyOptions * * @psalm-return RealObjectType&GhostObjectInterface * * @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); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Factory/LazyLoadingValueHolderFactory.php000066400000000000000000000041161407505032400310340ustar00rootroot00000000000000generator = new LazyLoadingValueHolderGenerator(); } /** * @param array $proxyOptions * * @psalm-template RealObjectType of object * * @psalm-param class-string $className * @psalm-param Closure( * RealObjectType|null=, * RealObjectType&ValueHolderInterface&VirtualProxyInterface=, * string=, * array=, * ?Closure= * ) : bool $initializer * @psalm-param array{skipDestructor?: bool, fluentSafe?: bool} $proxyOptions * * @psalm-return RealObjectType&ValueHolderInterface&VirtualProxyInterface * * @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; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Factory/NullObjectFactory.php000066400000000000000000000040531407505032400265250ustar00rootroot00000000000000generator = new NullObjectGenerator(); } /** * @param object|string $instanceOrClassName the object to be wrapped or interface to transform to null object * * @throws InvalidSignatureException * @throws MissingSignatureException * @throws OutOfBoundsException * * @psalm-template RealObjectType of object * * @psalm-param RealObjectType|class-string $instanceOrClassName * * @psalm-return RealObjectType&NullObjectInterface * * @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; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Factory/RemoteObject/000077500000000000000000000000001407505032400250035ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Factory/RemoteObject/Adapter/000077500000000000000000000000001407505032400263635ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Factory/RemoteObject/Adapter/BaseAdapter.php000066400000000000000000000023401407505032400312460ustar00rootroot00000000000000 */ protected $map = []; /** * Constructor * * @param array $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; } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Factory/RemoteObject/Adapter/JsonRpc.php000066400000000000000000000004651407505032400304570ustar00rootroot00000000000000 $params * * @return mixed */ public function call(string $wrappedClass, string $method, array $params = []); } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Factory/RemoteObjectFactory.php000066400000000000000000000044761407505032400270570ustar00rootroot00000000000000adapter = $adapter; $this->generator = new RemoteObjectGenerator(); } /** * @param string|object $instanceOrClassName * * @throws InvalidSignatureException * @throws MissingSignatureException * @throws OutOfBoundsException * * @psalm-template RealObjectType of object * * @psalm-param RealObjectType|class-string $instanceOrClassName * * @psalm-return RealObjectType&RemoteObjectInterface * * @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(); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/FileLocator/000077500000000000000000000000001407505032400232155ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/FileLocator/FileLocator.php000066400000000000000000000015361407505032400261360ustar00rootroot00000000000000proxiesDirectory = $absolutePath; } public function getProxyFileName(string $className): string { return $this->proxiesDirectory . DIRECTORY_SEPARATOR . str_replace('\\', '', $className) . '.php'; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/FileLocator/FileLocatorInterface.php000066400000000000000000000004651407505032400277570ustar00rootroot00000000000000setReturnsReference(strtolower($name) === '__get'); if (! $originalClass->hasMethod($name)) { return; } $this->setReturnsReference($originalClass->getMethod($name)->returnsReference()); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Generator/MethodGenerator.php000066400000000000000000000021061407505032400265370ustar00rootroot00000000000000setInterface(false); $method->setBody(''); return $method; } /** * {@inheritDoc} override needed to specify type in more detail */ public function getDocBlock(): ?DocBlockGenerator { return parent::getDocBlock(); } /** * {@inheritDoc} override needed to specify type in more detail */ public function getSourceContent(): ?string { return parent::getSourceContent(); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Generator/Util/000077500000000000000000000000001407505032400236555ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Generator/Util/ClassGeneratorUtils.php000066400000000000000000000013431407505032400303240ustar00rootroot00000000000000getName(); if ($originalClass->hasMethod($methodName) && $originalClass->getMethod($methodName)->isFinal()) { return false; } $classGenerator->addMethodFromGenerator($generatedMethod); return true; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Generator/Util/IdentifierSuffixer.php000066400000000000000000000031221407505032400301620ustar00rootroot00000000000000= 2.0.14 : InstalledVersions::getRawData() )); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Generator/Util/ProxiedMethodReturnExpression.php000066400000000000000000000015151407505032400324230ustar00rootroot00000000000000getReturnType(); if ($originalReturnType instanceof ReflectionNamedType && $originalReturnType->getName() === 'void') { return $returnedValueExpression . ";\nreturn;"; } return 'return ' . $returnedValueExpression . ';'; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Generator/Util/UniqueIdentifierGenerator.php000066400000000000000000000017601407505032400315120ustar00rootroot00000000000000generate(); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/GeneratorStrategy/EvaluatingGeneratorStrategy.php000066400000000000000000000025201407505032400326640ustar00rootroot00000000000000canEval = ! 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, "fileLocator = $fileLocator; $this->emptyErrorHandler = static function (int $type, string $message, string $file, int $line) { if (error_reporting() & $type) { throw new \ErrorException($message, 0, $type, $file, $line); } }; } /** * 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); set_error_handler($this->emptyErrorHandler); try { (new Filesystem())->dumpFile($fileName, "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; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Inflector/ClassNameInflectorInterface.php000066400000000000000000000030211407505032400310010ustar00rootroot00000000000000|class-string> $className * @psalm-return class-string */ public function getUserClassName(string $className): string; /** * Retrieve the class name of the proxy for the given user-defined class name * * @param array $options arbitrary options to be used for the generated class name * * @psalm-template RealClassName of object * * @psalm-param class-string|class-string> $className * * @psalm-return class-string */ public function getProxyClassName(string $className, array $options = []): string; /** * Retrieve whether the provided class name is a proxy * * @psalm-template RealClassName of object * @psalm-param class-string|class-string> $className */ public function isProxyClassName(string $className): bool; } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Inflector/Util/000077500000000000000000000000001407505032400236545ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Inflector/Util/ParameterEncoder.php000066400000000000000000000007721407505032400276130ustar00rootroot00000000000000 * $interceptor = function ($proxy, $instance, string $method, array $params, & $returnEarly) {}; * * * @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=, * 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: * * * $interceptor = function ($proxy, $instance, string $method, array $params, $returnValue, & $returnEarly) {}; * * * @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=, * mixed=, * bool= * ) : mixed $suffixInterceptor */ public function setMethodSuffixInterceptor(string $methodName, ?Closure $suffixInterceptor = null): void; } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Proxy/AccessInterceptorValueHolderInterface.php000066400000000000000000000033271407505032400322450ustar00rootroot00000000000000=, * 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=, * 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(); } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Proxy/Exception/000077500000000000000000000000001407505032400240715ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Proxy/Exception/RemoteObjectException.php000066400000000000000000000004231407505032400310420ustar00rootroot00000000000000=, * string=, * array=, * ?Closure=, * array= * ) : bool $initializer */ public function setProxyInitializer(?Closure $initializer = null); /** * {@inheritDoc} * * Definitions are duplicated here to allow templated definitions in this child type * * @psalm-suppress ImplementedReturnTypeMismatch Note that the closure signature below is slightly different * from the one declared in LazyLoadingInterface. * @psalm-return null|Closure( * LazilyLoadedObjectType&GhostObjectInterface=, * string, * array=, * ?Closure=, * array= * ) : bool */ public function getProxyInitializer(): ?Closure; } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Proxy/LazyLoadingInterface.php000066400000000000000000000034671407505032400267140ustar00rootroot00000000000000 * $initializer = function ( * & ?object $wrappedObject, * LazyLoadingInterface $proxy, * string $calledMethod, * array $callParameters, * & ?\Closure $initializer, * array $propertiesToBeSet = [] // works only on ghost objects * ) {}; * * * @return void * * @psalm-param null|Closure( * LazilyLoadedObjectType|null=, * LazilyLoadedObjectType&LazyLoadingInterface=, * string=, * array=, * ?Closure=, * array= * ) : bool $initializer */ public function setProxyInitializer(?Closure $initializer = null); /** * @psalm-return null|Closure( * LazilyLoadedObjectType|null=, * LazilyLoadedObjectType&LazyLoadingInterface=, * string, * array=, * ?Closure=, * array= * ) : 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; } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Proxy/NullObjectInterface.php000066400000000000000000000002271407505032400265270ustar00rootroot00000000000000setBody(UnsetPropertiesGenerator::generateSnippet( Properties::fromReflectionClass($originalClass), 'this' )); } } SetMethodPrefixInterceptor.php000066400000000000000000000022321407505032400404330ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptor/MethodGeneratorsetType(Closure::class); $interceptor->setDefaultValue(null); $this->setParameter(new ParameterGenerator('methodName', 'string')); $this->setParameter($interceptor); $this->setReturnType('void'); $this->setBody('$this->' . $prefixInterceptor->getName() . '[$methodName] = $prefixInterceptor;'); } } SetMethodSuffixInterceptor.php000066400000000000000000000022321407505032400404420ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptor/MethodGeneratorsetType(Closure::class); $interceptor->setDefaultValue(null); $this->setParameter(new ParameterGenerator('methodName', 'string')); $this->setParameter($interceptor); $this->setReturnType('void'); $this->setBody('$this->' . $suffixInterceptor->getName() . '[$methodName] = $suffixInterceptor;'); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptor/PropertyGenerator/000077500000000000000000000000001407505032400331155ustar00rootroot00000000000000MethodPrefixInterceptors.php000066400000000000000000000015321407505032400405500ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptor/PropertyGeneratorsetDefaultValue([]); $this->setVisibility(self::VISIBILITY_PRIVATE); $this->setDocBlock('@var \\Closure[] map of interceptors to be called per-method before execution'); } } MethodSuffixInterceptors.php000066400000000000000000000015301407505032400405550ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptor/PropertyGeneratorsetDefaultValue([]); $this->setVisibility(self::VISIBILITY_PRIVATE); $this->setDocBlock('@var \\Closure[] map of interceptors to be called per-method after execution'); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/000077500000000000000000000000001407505032400322615ustar00rootroot00000000000000MethodGenerator/000077500000000000000000000000001407505032400352715ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizerBindProxyProperties.php000066400000000000000000000060031407505032400417740ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorgetName()), 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;' ); } } InterceptedMethod.php000066400000000000000000000027271407505032400414210ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorgetParameters() as $parameter) { $forwardedParams[] = ($parameter->isVariadic() ? '...' : '') . '$' . $parameter->getName(); } $method->setBody(InterceptorGenerator::createInterceptedMethodBody( '$returnValue = parent::' . $originalMethod->getName() . '(' . implode(', ', $forwardedParams) . ');', $method, $prefixInterceptors, $suffixInterceptors, $originalMethod )); return $method; } } MagicClone.php000066400000000000000000000021461407505032400400060ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorsetBody(InterceptorGenerator::createInterceptedMethodBody( $parent ? '$returnValue = parent::__clone();' : '$returnValue = null;', $this, $prefixInterceptors, $suffixInterceptors, $parent )); } } MagicGet.php000066400000000000000000000031341407505032400374630ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorsetBody(InterceptorGenerator::createInterceptedMethodBody( $callParent, $this, $prefixInterceptors, $suffixInterceptors, $parent )); } } MagicIsset.php000066400000000000000000000031571407505032400400400ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorsetBody(InterceptorGenerator::createInterceptedMethodBody( $callParent, $this, $prefixInterceptors, $suffixInterceptors, $parent )); } } MagicSet.php000066400000000000000000000032661407505032400375050ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorsetBody(InterceptorGenerator::createInterceptedMethodBody( $callParent, $this, $prefixInterceptors, $suffixInterceptors, $parent )); } } MagicSleep.php000066400000000000000000000022411407505032400400120ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorsetBody(InterceptorGenerator::createInterceptedMethodBody( $callParent, $this, $prefixInterceptors, $suffixInterceptors, $parent )); } } MagicUnset.php000066400000000000000000000031571407505032400400470ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorsetBody(InterceptorGenerator::createInterceptedMethodBody( $callParent, $this, $prefixInterceptors, $suffixInterceptors, $parent )); } } StaticProxyConstructor.php000066400000000000000000000041331407505032400425420ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorsetType($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;' ); } } Util/000077500000000000000000000000001407505032400362065ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorInterceptorGenerator.php000066400000000000000000000060321407505032400430650ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/Util{{$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->getName(); }, $method->getParameters())) . ')', ]; return str_replace( array_keys($replacements), $replacements, self::TEMPLATE ); } } AccessInterceptorScopeLocalizerGenerator.php000066400000000000000000000114731407505032400345700ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGeneratorsetExtendedClass($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 ); }; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/000077500000000000000000000000001407505032400315555ustar00rootroot00000000000000MethodGenerator/000077500000000000000000000000001407505032400345655ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolderInterceptedMethod.php000066400000000000000000000031131407505032400407030ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorgetParameters() 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; } } MagicClone.php000066400000000000000000000027171407505032400373060ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator{{$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 )); } } MagicGet.php000066400000000000000000000040401407505032400367540ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorgetName(); $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 )); } } MagicIsset.php000066400000000000000000000040571407505032400373340ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorgetName(); $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 )); } } MagicSet.php000066400000000000000000000041731407505032400367770ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorgetName(); $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 )); } } MagicUnset.php000066400000000000000000000041211407505032400373330ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorgetName(); $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 )); } } StaticProxyConstructor.php000066400000000000000000000050051407505032400420350ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorsetDefaultValue([]); $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;' ); } } Util/000077500000000000000000000000001407505032400355025ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorInterceptorGenerator.php000066400000000000000000000064401407505032400423640ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/Util{{$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(); $params[] = var_export($parameterName, true) . ' => $' . $parameter->getName(); } $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); } } AccessInterceptorValueHolderGenerator.php000066400000000000000000000144601407505032400340630ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGeneratorisInterface()) { $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 ); }; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/Assertion/000077500000000000000000000000001407505032400257515ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/Assertion/CanProxyAssertion.php000066400000000000000000000041131407505032400321140ustar00rootroot00000000000000isFinal()) { 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); } } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoading/000077500000000000000000000000001407505032400262175ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoading/MethodGenerator/000077500000000000000000000000001407505032400313065ustar00rootroot00000000000000StaticProxyConstructor.php000066400000000000000000000027051407505032400365030ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoading/MethodGeneratorsetParameter(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;' ); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/000077500000000000000000000000001407505032400272245ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/000077500000000000000000000000001407505032400323135ustar00rootroot00000000000000CallInitializer.php000066400000000000000000000131261407505032400360270ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGeneratorgetName(); $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); $this->%s = false; return $result; PHP; $referenceableProperties = $properties->withoutNonReferenceableProperties(); $this->setBody(sprintf( $bodyTemplate, $initialization, $initializer, $initialization, $this->propertiesInitializationCode($referenceableProperties), $this->propertiesReferenceArrayCode($referenceableProperties), $initializer, $initializer, $initialization )); } private function propertiesInitializationCode(Properties $properties): string { $assignments = []; foreach ($properties->getAccessibleProperties() as $property) { $assignments[] = '$this->' . $property->getName() . ' = ' . $this->getExportedPropertyDefaultValue($property) . ';'; } foreach ($properties->getGroupedPrivateProperties() as $className => $privateProperties) { $cacheKey = 'cache' . str_replace('\\', '_', $className); $assignments[] = 'static $' . $cacheKey . ";\n\n" . '$' . $cacheKey . ' ?? $' . $cacheKey . " = \\Closure::bind(static function (\$instance) {\n" . $this->getPropertyDefaultsAssignments($privateProperties) . "\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): string { $assignments = []; foreach ($properties->getAccessibleProperties() as $propertyInternalName => $property) { $assignments[] = ' ' . var_export($propertyInternalName, true) . ' => & $this->' . $property->getName() . ','; } $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) . '}, $this, ' . var_export($className, true) . ");\n\n" . '$' . $cacheKey . '($this, $properties);'; } return $code; } /** * @param array $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 var_export($defaults[$name] ?? null, true); } } GetProxyInitializer.php000066400000000000000000000014361407505032400367360ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGeneratorsetReturnType('?\\Closure'); $this->setBody('return $this->' . $initializerProperty->getName() . ';'); } } InitializeProxy.php000066400000000000000000000017361407505032400361170ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGeneratorsetReturnType('bool'); $this->setBody( 'return $this->' . $initializerProperty->getName() . ' && $this->' . $callInitializer->getName() . '(\'initializeProxy\', []);' ); } } IsProxyInitialized.php000066400000000000000000000014271407505032400365540ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGeneratorsetReturnType('bool'); $this->setBody('return ! $this->' . $initializerProperty->getName() . ';'); } } MagicClone.php000066400000000000000000000016041407505032400347470ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGeneratorsetBody( '$this->' . $initializerProperty->getName() . ' && $this->' . $callInitializer->getName() . '(\'__clone\', []);' . ($originalClass->hasMethod('__clone') ? "\n\nparent::__clone();" : '') ); } } MagicGet.php000066400000000000000000000103601407505032400344250ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator%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) { return $instance->$name; }, 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) { return $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, 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' ); } $this->setBody(sprintf( $this->callParentTemplate, $initializerProperty->getName(), $initializationTracker->getName(), $callInitializer->getName(), $publicProperties->getName(), $protectedProperties->getName(), $initializationTracker->getName(), $protectedProperties->getName(), $privateProperties->getName(), $privateProperties->getName(), $initializationTracker->getName(), $privateProperties->getName(), $parentAccess )); } } MagicIsset.php000066400000000000000000000075311407505032400350030ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator$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 )); } } MagicSet.php000066400000000000000000000101471407505032400344440ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator$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 )); } } MagicSleep.php000066400000000000000000000016611407505032400347620ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGeneratorsetBody( '$this->' . $initializerProperty->getName() . ' && $this->' . $callInitializer->getName() . '(\'__sleep\', []);' . "\n\n" . ($originalClass->hasMethod('__sleep') ? 'return parent::__sleep();' : 'return array_keys((array) $this);') ); } } MagicUnset.php000066400000000000000000000077171407505032400350200ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator$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 )); } } SetProxyInitializer.php000066400000000000000000000015441407505032400367520ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGeneratorsetDefaultValue(null)], self::FLAG_PUBLIC, '$this->' . $initializerProperty->getName() . ' = $initializer;' ); $this->setReturnType('void'); } } SkipDestructor.php000066400000000000000000000013341407505032400357330ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGeneratorsetBody( '$this->' . $initializerProperty->getName() . ' || parent::__destruct();' ); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/PropertyGenerator/000077500000000000000000000000001407505032400327175ustar00rootroot00000000000000InitializationTracker.php000066400000000000000000000014631407505032400376600ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/PropertyGeneratorsetVisibility(self::VISIBILITY_PRIVATE); $this->setDocBlock('@var bool tracks initialization status - true while the object is initializing'); $this->setDefaultValue(false); } } InitializerProperty.php000066400000000000000000000013771407505032400374110ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/PropertyGeneratorsetVisibility(self::VISIBILITY_PRIVATE); $this->setDocBlock('@var \\Closure|null initializer responsible for generating the wrapped object'); } } PrivatePropertiesMap.php000066400000000000000000000026131407505032400375000ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/PropertyGeneratorsetVisibility(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 array> */ private function getMap(Properties $properties): array { $map = []; foreach ($properties->getPrivateProperties() as $property) { $map[$property->getName()][$property->getDeclaringClass()->getName()] = true; } return $map; } } ProtectedPropertiesMap.php000066400000000000000000000025561407505032400400250ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/PropertyGeneratorsetVisibility(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) { $map[$property->getName()] = $property->getDeclaringClass()->getName(); } return $map; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingGhostGenerator.php000066400000000000000000000160171407505032400316110ustar00rootroot00000000000000, skipDestructor?: bool} $proxyOptions */ public function generate(ReflectionClass $originalClass, ClassGenerator $classGenerator, array $proxyOptions = []) { CanProxyAssertion::assertClassCanBeProxied($originalClass, false); $filteredProperties = Properties::fromReflectionClass($originalClass) ->filter($proxyOptions['skippedProperties'] ?? []); $publicProperties = new PublicPropertiesMap($filteredProperties); $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) ); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/000077500000000000000000000000001407505032400303525ustar00rootroot00000000000000MethodGenerator/000077500000000000000000000000001407505032400333625ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolderGetProxyInitializer.php000066400000000000000000000014441407505032400400630ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorsetReturnType('?\\Closure'); $this->setBody('return $this->' . $initializerProperty->getName() . ';'); } } InitializeProxy.php000066400000000000000000000022301407505032400372330ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorsetReturnType('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 . ';' ); } } IsProxyInitialized.php000066400000000000000000000014441407505032400377010ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorsetReturnType('bool'); $this->setBody('return null !== $this->' . $valueHolderProperty->getName() . ';'); } } LazyLoadingMethodInterceptor.php000066400000000000000000000042571407505032400417000ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorgetName(); $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; } } MagicClone.php000066400000000000000000000021441407505032400360750ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorgetName(); $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 . ';' ); } } MagicGet.php000066400000000000000000000045221407505032400355560ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorhasMethod('__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 ); } } MagicIsset.php000066400000000000000000000036221407505032400361260ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorgetName(); $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 ); } } MagicSet.php000066400000000000000000000043101407505032400355650ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorhasMethod('__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 ); } } MagicSleep.php000066400000000000000000000021421407505032400361030ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorgetName(); $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) . ');' ); } } MagicUnset.php000066400000000000000000000041251407505032400361340ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorhasMethod('__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 ); } } SetProxyInitializer.php000066400000000000000000000021151407505032400400730ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorsetType(Closure::class); $initializerParameter->setDefaultValue(null); $this->setParameter($initializerParameter); $this->setBody('$this->' . $initializerProperty->getName() . ' = $initializer;'); $this->setReturnType('void'); } } SkipDestructor.php000066400000000000000000000014661407505032400370670ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorgetName(); $valueHolder = $valueHolderProperty->getName(); $this->setBody( '$this->' . $initializer . ' || $this->' . $valueHolder . '->__destruct();' ); } } PropertyGenerator/000077500000000000000000000000001407505032400337665ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolderInitializerProperty.php000066400000000000000000000014051407505032400405270ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/PropertyGeneratorsetVisibility(self::VISIBILITY_PRIVATE); $this->setDocBlock('@var \\Closure|null initializer responsible for generating the wrapped object'); } } ValueHolderProperty.php000066400000000000000000000017571407505032400404700ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/PropertyGeneratorsetWordWrap(false); $docBlock->setLongDescription('@var \\' . $type->getName() . '|null wrapped object, if the proxy is initialized'); $this->setDocBlock($docBlock); $this->setVisibility(self::VISIBILITY_PRIVATE); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolderGenerator.php000066400000000000000000000161721407505032400327410ustar00rootroot00000000000000= 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; }; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/NullObject/000077500000000000000000000000001407505032400260435ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/NullObject/MethodGenerator/000077500000000000000000000000001407505032400311325ustar00rootroot00000000000000NullObjectMethodInterceptor.php000066400000000000000000000015041407505032400372050ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/NullObject/MethodGeneratorreturnsReference()) { $reference = IdentifierSuffixer::getIdentifier('ref'); $method->setBody("\$reference = null;\nreturn \$" . $reference . ';'); } return $method; } } StaticProxyConstructor.php000066400000000000000000000032351407505032400363260ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/NullObject/MethodGenerator' . $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;' ); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/NullObjectGenerator.php000066400000000000000000000037461407505032400304350ustar00rootroot00000000000000isInterface()) { $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) ); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/PropertyGenerator/000077500000000000000000000000001407505032400274755ustar00rootroot00000000000000PublicPropertiesMap.php000066400000000000000000000022531407505032400340620ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/PropertyGenerator */ private $publicProperties = []; /** * @throws InvalidArgumentException */ public function __construct(Properties $properties) { parent::__construct(IdentifierSuffixer::getIdentifier('publicProperties')); foreach ($properties->getPublicProperties() as $publicProperty) { $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; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/ProxyGeneratorInterface.php000066400000000000000000000011451407505032400313250ustar00rootroot00000000000000setDocBlock('@param string $name'); $this->setBody( '$return = $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) . ', \'__get\', array($name));' . "\n\n" . 'return $return;' ); } } MagicIsset.php000066400000000000000000000020141407505032400341320ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGeneratorsetDocBlock('@param string $name'); $this->setBody( '$return = $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) . ', \'__isset\', array($name));' . "\n\n" . 'return $return;' ); } } MagicSet.php000066400000000000000000000021531407505032400336020ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGeneratorsetDocBlock('@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;' ); } } MagicUnset.php000066400000000000000000000020141407505032400341410ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGeneratorsetDocBlock('@param string $name'); $this->setBody( '$return = $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) . ', \'__unset\', array($name));' . "\n\n" . 'return $return;' ); } } RemoteObjectMethod.php000066400000000000000000000050141407505032400356300ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) . ', ' . var_export($originalMethod->getName(), true) . ', $args);' . "\n\n" . ProxiedMethodReturnExpression::generate('$return', $originalMethod); $defaultValues = self::getDefaultValuesForMethod($originalMethod); $declaredParameterCount = count($originalMethod->getParameters()); $method->setBody( strtr( self::TEMPLATE, [ '#PROXIED_RETURN#' => $proxiedReturn, '#DEFAULT_VALUES#' => var_export($defaultValues, true), '#PARAMETER_COUNT#' => var_export($declaredParameterCount, true), ] ) ); return $method; } /** @psalm-return list */ private static function getDefaultValuesForMethod(MethodReflection $originalMethod): array { $defaultValues = []; foreach ($originalMethod->getParameters() as $parameter) { if ($parameter->isOptional() && $parameter->isDefaultValueAvailable()) { /** @psalm-var int|float|bool|array|string|null */ $defaultValues[] = $parameter->getDefaultValue(); continue; } if ($parameter->isVariadic()) { continue; } $defaultValues[] = null; } return $defaultValues; } } StaticProxyConstructor.php000066400000000000000000000033451407505032400366510ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGeneratorgetName(); 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;"); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/RemoteObject/PropertyGenerator/000077500000000000000000000000001407505032400320575ustar00rootroot00000000000000AdapterProperty.php000066400000000000000000000014271407505032400356420ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/RemoteObject/PropertyGeneratorsetVisibility(self::VISIBILITY_PRIVATE); $this->setDocBlock('@var \\' . AdapterInterface::class . ' Remote web service adapter'); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/RemoteObjectGenerator.php000066400000000000000000000065171407505032400307550ustar00rootroot00000000000000isInterface()) { $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), ] ) ); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/Util/000077500000000000000000000000001407505032400247175ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/Util/GetMethodIfExists.php000066400000000000000000000007371407505032400307760ustar00rootroot00000000000000hasMethod($method) ? $class->getMethod($method) : null; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/Util/Properties.php000066400000000000000000000152631407505032400275730ustar00rootroot00000000000000properties = $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 $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; } 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; } $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 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 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 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 indexed by the property internal visibility-aware name (\0*\0propertyName) */ public function getAccessibleProperties(): array { return array_merge($this->getPublicProperties(), $this->getProtectedProperties()); } /** * @return array> 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 indexed by the property internal visibility-aware name (\0*\0propertyName) */ public function getInstanceProperties(): array { return array_merge($this->getAccessibleProperties(), $this->getPrivateProperties()); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/Util/ProxiedMethodsFilter.php000066400000000000000000000046151407505032400315420ustar00rootroot00000000000000 $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 $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 $excluded * * @return array */ 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(); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/Util/PublicScopeSimulator.php000066400000000000000000000202311407505032400315360ustar00rootroot00000000000000' . $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()'; } /** * @throws InvalidArgumentException * * @psalm-param $operationType self::OPERATION_* */ 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; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/Util/UnsetPropertiesGenerator.php000066400000000000000000000060221407505032400324520ustar00rootroot00000000000000__invoke($%s); PHP; public static function generateSnippet(Properties $properties, string $instanceName): string { return self::generateUnsetAccessiblePropertiesCode($properties, $instanceName) . self::generateUnsetPrivatePropertiesCode($properties, $instanceName); } private static function generateUnsetAccessiblePropertiesCode(Properties $properties, string $instanceName): string { $accessibleProperties = $properties->getAccessibleProperties(); if (! $accessibleProperties) { return ''; } return self::generateUnsetStatement($accessibleProperties, $instanceName) . "\n\n"; } private static function generateUnsetPrivatePropertiesCode(Properties $properties, string $instanceName): string { $groups = $properties->getGroupedPrivateProperties(); if (! $groups) { return ''; } $unsetClosureCalls = []; foreach ($groups as $privateProperties) { $firstProperty = reset($privateProperties); assert($firstProperty instanceof ReflectionProperty); $unsetClosureCalls[] = self::generateUnsetClassPrivatePropertiesBlock( $firstProperty->getDeclaringClass(), $privateProperties, $instanceName ); } return implode("\n\n", $unsetClosureCalls) . "\n\n"; } /** @param array $properties */ private static function generateUnsetClassPrivatePropertiesBlock( 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 $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 ) ) . ');'; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/ValueHolder/000077500000000000000000000000001407505032400262145ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/ValueHolder/MethodGenerator/000077500000000000000000000000001407505032400313035ustar00rootroot00000000000000Constructor.php000066400000000000000000000062101407505032400342610ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/ValueHolder/MethodGeneratorsetBody( '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; } } GetWrappedValueHolderValue.php000066400000000000000000000014021407505032400371240ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/ValueHolder/MethodGeneratorsetBody('return $this->' . $valueHolderProperty->getName() . ';'); } } MagicSleep.php000066400000000000000000000012161407505032400337460ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/ProxyGenerator/ValueHolder/MethodGeneratorsetBody('return array(' . var_export($valueHolderProperty->getName(), true) . ');'); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Signature/000077500000000000000000000000001407505032400227535ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Signature/ClassSignatureGenerator.php000066400000000000000000000021001407505032400302530ustar00rootroot00000000000000signatureGenerator = $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; } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Signature/ClassSignatureGeneratorInterface.php000066400000000000000000000007651407505032400321130ustar00rootroot00000000000000 $parameters */ public function addSignature(ClassGenerator $classGenerator, array $parameters): ClassGenerator; } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Signature/Exception/000077500000000000000000000000001407505032400247115ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Signature/Exception/ExceptionInterface.php000066400000000000000000000002731407505032400312030ustar00rootroot00000000000000getName(), $expected, count($parameters) )); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Signature/Exception/MissingSignatureException.php000066400000000000000000000013001407505032400325660ustar00rootroot00000000000000getName(), $expected, count($parameters) )); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Signature/SignatureChecker.php000066400000000000000000000027611407505032400267200ustar00rootroot00000000000000signatureGenerator = $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 ); } } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Signature/SignatureCheckerInterface.php000066400000000000000000000012071407505032400305330ustar00rootroot00000000000000 $parameters * * @throws InvalidSignatureException * @throws MissingSignatureException */ public function checkSignature(ReflectionClass $class, array $parameters): void; } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Signature/SignatureGenerator.php000066400000000000000000000015051407505032400272750ustar00rootroot00000000000000parameterEncoder = 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); } } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Signature/SignatureGeneratorInterface.php000066400000000000000000000011731407505032400311170ustar00rootroot00000000000000 $parameters */ public function generateSignature(array $parameters): string; /** * Generates a signature key to be looked up when verifying generated code validity * * @param array $parameters */ public function generateSignatureKey(array $parameters): string; } php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Stub/000077500000000000000000000000001407505032400217275ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/src/ProxyManager/Stub/EmptyClassStub.php000066400000000000000000000002121407505032400253550ustar00rootroot00000000000000@, * 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'; } } php-proxy-manager-2.11.1+1.0.5/tests/000077500000000000000000000000001407505032400167515ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/000077500000000000000000000000001407505032400222255ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Assert.php000066400000000000000000000007041407505032400242000ustar00rootroot00000000000000getProperty($propertyName); $property->setAccessible(true); return $property->getValue($object); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Autoloader/000077500000000000000000000000001407505032400243245ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Autoloader/AutoloaderTest.php000066400000000000000000000105401407505032400277740ustar00rootroot00000000000000fileLocator = $this->createMock(FileLocatorInterface::class); $this->classNameInflector = $this->createMock(ClassNameInflectorInterface::class); $this->autoloader = new Autoloader($this->fileLocator, $this->classNameInflector); } /** * @covers \ProxyManager\Autoloader\Autoloader::__invoke */ public function testWillNotAutoloadUserClasses(): void { /** @var class-string $className */ $className = 'Foo\\' . UniqueIdentifierGenerator::getIdentifier('Bar'); $this ->classNameInflector ->expects(self::once()) ->method('isProxyClassName') ->with($className) ->willReturn(false); self::assertFalse($this->autoloadWithoutFurtherAutoloaders($className)); } /** * @covers \ProxyManager\Autoloader\Autoloader::__invoke */ public function testWillNotAutoloadNonExistingClass(): void { /** @var class-string $className */ $className = 'Foo\\' . UniqueIdentifierGenerator::getIdentifier('Bar'); $this ->classNameInflector ->expects(self::once()) ->method('isProxyClassName') ->with($className) ->willReturn(true); $this ->fileLocator ->expects(self::once()) ->method('getProxyFileName') ->willReturn(__DIR__ . '/non-existing'); self::assertFalse($this->autoloadWithoutFurtherAutoloaders($className)); } /** * @covers \ProxyManager\Autoloader\Autoloader::__invoke */ public function testWillNotAutoloadExistingClass(): void { self::assertFalse($this->autoloadWithoutFurtherAutoloaders(self::class)); } /** * @covers \ProxyManager\Autoloader\Autoloader::__invoke */ public function testWillAutoloadExistingFile(): void { $namespace = 'Foo'; $className = UniqueIdentifierGenerator::getIdentifier('Bar'); /** @var class-string $fqcn */ $fqcn = $namespace . '\\' . $className; $fileName = sys_get_temp_dir() . '/foo_' . uniqid('file', true) . '.php'; file_put_contents($fileName, 'classNameInflector ->expects(self::once()) ->method('isProxyClassName') ->with($fqcn) ->willReturn(true); $this ->fileLocator ->expects(self::once()) ->method('getProxyFileName') ->willReturn($fileName); self::assertTrue($this->autoloadWithoutFurtherAutoloaders($fqcn)); self::assertTrue(class_exists($fqcn, false)); } /** @psalm-param class-string $className */ private function autoloadWithoutFurtherAutoloaders(string $className): bool { $failingAutoloader = null; $failingAutoloader = function (string $className) use (& $failingAutoloader): void { spl_autoload_unregister($failingAutoloader); $this->fail(sprintf('Fallback autoloading was triggered to load "%s"', $className)); }; spl_autoload_register($failingAutoloader); $result = $this->autoloader->__invoke($className); spl_autoload_unregister($failingAutoloader); return $result; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ConfigurationTest.php000066400000000000000000000134021407505032400264050ustar00rootroot00000000000000configuration = new Configuration(); } /** * @covers \ProxyManager\Configuration::getProxiesNamespace * @covers \ProxyManager\Configuration::setProxiesNamespace */ public function testGetSetProxiesNamespace(): void { self::assertSame( 'ProxyManagerGeneratedProxy', $this->configuration->getProxiesNamespace(), 'Default setting check for BC' ); $this->configuration->setProxiesNamespace('foo'); self::assertSame('foo', $this->configuration->getProxiesNamespace()); } /** * @covers \ProxyManager\Configuration::getClassNameInflector * @covers \ProxyManager\Configuration::setClassNameInflector */ public function testSetGetClassNameInflector(): void { /** @noinspection UnnecessaryAssertionInspection */ self::assertInstanceOf(ClassNameInflectorInterface::class, $this->configuration->getClassNameInflector()); $inflector = $this->createMock(ClassNameInflectorInterface::class); $this->configuration->setClassNameInflector($inflector); self::assertSame($inflector, $this->configuration->getClassNameInflector()); } /** * @covers \ProxyManager\Configuration::getGeneratorStrategy */ public function testDefaultGeneratorStrategyNeedToBeAInstanceOfEvaluatingGeneratorStrategy(): void { self::assertInstanceOf(EvaluatingGeneratorStrategy::class, $this->configuration->getGeneratorStrategy()); } /** * @covers \ProxyManager\Configuration::getGeneratorStrategy * @covers \ProxyManager\Configuration::setGeneratorStrategy */ public function testSetGetGeneratorStrategy(): void { /** @noinspection UnnecessaryAssertionInspection */ self::assertInstanceOf(GeneratorStrategyInterface::class, $this->configuration->getGeneratorStrategy()); $strategy = $this->createMock(GeneratorStrategyInterface::class); $this->configuration->setGeneratorStrategy($strategy); self::assertSame($strategy, $this->configuration->getGeneratorStrategy()); } /** * @covers \ProxyManager\Configuration::getProxiesTargetDir * @covers \ProxyManager\Configuration::setProxiesTargetDir */ public function testSetGetProxiesTargetDir(): void { self::assertDirectoryExists($this->configuration->getProxiesTargetDir()); $this->configuration->setProxiesTargetDir(__DIR__); self::assertSame(__DIR__, $this->configuration->getProxiesTargetDir()); } /** * @covers \ProxyManager\Configuration::getProxyAutoloader * @covers \ProxyManager\Configuration::setProxyAutoloader */ public function testSetGetProxyAutoloader(): void { /** @noinspection UnnecessaryAssertionInspection */ self::assertInstanceOf(AutoloaderInterface::class, $this->configuration->getProxyAutoloader()); $autoloader = $this->createMock(AutoloaderInterface::class); $this->configuration->setProxyAutoloader($autoloader); self::assertSame($autoloader, $this->configuration->getProxyAutoloader()); } /** * @covers \ProxyManager\Configuration::getSignatureGenerator * @covers \ProxyManager\Configuration::setSignatureGenerator */ public function testSetGetSignatureGenerator(): void { /** @noinspection UnnecessaryAssertionInspection */ self::assertInstanceOf(SignatureCheckerInterface::class, $this->configuration->getSignatureChecker()); $signatureGenerator = $this->createMock(SignatureGeneratorInterface::class); $this->configuration->setSignatureGenerator($signatureGenerator); self::assertSame($signatureGenerator, $this->configuration->getSignatureGenerator()); } /** * @covers \ProxyManager\Configuration::getSignatureChecker * @covers \ProxyManager\Configuration::setSignatureChecker */ public function testSetGetSignatureChecker(): void { /** @noinspection UnnecessaryAssertionInspection */ self::assertInstanceOf(SignatureCheckerInterface::class, $this->configuration->getSignatureChecker()); $signatureChecker = $this->createMock(SignatureCheckerInterface::class); $this->configuration->setSignatureChecker($signatureChecker); self::assertSame($signatureChecker, $this->configuration->getSignatureChecker()); } /** * @covers \ProxyManager\Configuration::getClassSignatureGenerator * @covers \ProxyManager\Configuration::setClassSignatureGenerator */ public function testSetGetClassSignatureGenerator(): void { /** @noinspection UnnecessaryAssertionInspection */ self::assertInstanceOf( ClassSignatureGeneratorInterface::class, $this->configuration->getClassSignatureGenerator() ); $classSignatureGenerator = $this->createMock(ClassSignatureGeneratorInterface::class); $this->configuration->setClassSignatureGenerator($classSignatureGenerator); self::assertSame($classSignatureGenerator, $this->configuration->getClassSignatureGenerator()); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Exception/000077500000000000000000000000001407505032400241635ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Exception/DisabledMethodExceptionTest.php000066400000000000000000000013041407505032400322610ustar00rootroot00000000000000getMessage()); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Exception/FileNotWritableExceptionTest.php000066400000000000000000000013621407505032400324470ustar00rootroot00000000000000getMessage()); self::assertSame($previousException, $exception->getPrevious()); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Exception/InvalidProxiedClassExceptionTest.php000066400000000000000000000055131407505032400333260ustar00rootroot00000000000000getMessage() ); } public function testFinalClassNotSupported(): void { self::assertSame( 'Provided class "ProxyManagerTestAsset\FinalClass" is final and cannot be proxied', InvalidProxiedClassException::finalClassNotSupported( new ReflectionClass(FinalClass::class) )->getMessage() ); } public function testAbstractProtectedMethodsNotSupported(): void { self::assertSame( 'Provided class "ProxyManagerTestAsset\ClassWithAbstractProtectedMethod" has following protected abstract' . ' methods, and therefore cannot be proxied:' . "\n" . 'ProxyManagerTestAsset\ClassWithAbstractProtectedMethod::protectedAbstractMethod', InvalidProxiedClassException::abstractProtectedMethodsNotSupported( new ReflectionClass(ClassWithAbstractProtectedMethod::class) )->getMessage() ); } public function testProtectedMethodsNotSupported(): void { self::assertSame( 'Provided class "ProxyManagerTestAsset\ClassWithProtectedMethod" has following protected abstract' . ' methods, and therefore cannot be proxied:' . "\n", InvalidProxiedClassException::abstractProtectedMethodsNotSupported( new ReflectionClass(ClassWithProtectedMethod::class) )->getMessage() ); } public function testAbstractPublicMethodsNotSupported(): void { self::assertSame( 'Provided class "ProxyManagerTestAsset\ClassWithAbstractPublicMethod" has following protected abstract' . ' methods, and therefore cannot be proxied:' . "\n", InvalidProxiedClassException::abstractProtectedMethodsNotSupported( new ReflectionClass(ClassWithAbstractPublicMethod::class) )->getMessage() ); } } InvalidProxyDirectoryExceptionTest.php000066400000000000000000000014001407505032400336440ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ExceptiongetMessage()); } } UnsupportedProxiedClassExceptionTest.php000066400000000000000000000100571407505032400342100ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ExceptiongetMessage() ); } /** * @requires PHP 7.4 */ public function testNonReferenceableLocalizedReflectionProperties(): void { $reflectionClass = new ReflectionClass(ClassWithMixedTypedProperties::class); self::assertSame( 'Cannot create references for following properties of class ' . ClassWithMixedTypedProperties::class . ': publicBoolPropertyWithoutDefaultValue, publicNullableBoolPropertyWithoutDefaultValue, ' . 'publicIntPropertyWithoutDefaultValue, publicNullableIntPropertyWithoutDefaultValue, ' . 'publicFloatPropertyWithoutDefaultValue, publicNullableFloatPropertyWithoutDefaultValue, ' . 'publicStringPropertyWithoutDefaultValue, publicNullableStringPropertyWithoutDefaultValue, ' . 'publicArrayPropertyWithoutDefaultValue, publicNullableArrayPropertyWithoutDefaultValue, ' . 'publicIterablePropertyWithoutDefaultValue, publicNullableIterablePropertyWithoutDefaultValue, ' . 'publicObjectProperty, publicNullableObjectProperty, publicClassProperty, publicNullableClassProperty, ' . 'protectedBoolPropertyWithoutDefaultValue, protectedNullableBoolPropertyWithoutDefaultValue, ' . 'protectedIntPropertyWithoutDefaultValue, protectedNullableIntPropertyWithoutDefaultValue, ' . 'protectedFloatPropertyWithoutDefaultValue, protectedNullableFloatPropertyWithoutDefaultValue, ' . 'protectedStringPropertyWithoutDefaultValue, protectedNullableStringPropertyWithoutDefaultValue, ' . 'protectedArrayPropertyWithoutDefaultValue, protectedNullableArrayPropertyWithoutDefaultValue, ' . 'protectedIterablePropertyWithoutDefaultValue, protectedNullableIterablePropertyWithoutDefaultValue, ' . 'protectedObjectProperty, protectedNullableObjectProperty, protectedClassProperty, ' . 'protectedNullableClassProperty, privateBoolPropertyWithoutDefaultValue, ' . 'privateNullableBoolPropertyWithoutDefaultValue, privateIntPropertyWithoutDefaultValue, ' . 'privateNullableIntPropertyWithoutDefaultValue, privateFloatPropertyWithoutDefaultValue, ' . 'privateNullableFloatPropertyWithoutDefaultValue, privateStringPropertyWithoutDefaultValue, ' . 'privateNullableStringPropertyWithoutDefaultValue, privateArrayPropertyWithoutDefaultValue, ' . 'privateNullableArrayPropertyWithoutDefaultValue, privateIterablePropertyWithoutDefaultValue, ' . 'privateNullableIterablePropertyWithoutDefaultValue, privateObjectProperty, ' . 'privateNullableObjectProperty, privateClassProperty, privateNullableClassProperty', UnsupportedProxiedClassException::nonReferenceableLocalizedReflectionProperties( $reflectionClass, Properties::fromReflectionClass($reflectionClass) ->onlyNonReferenceableProperties() ->onlyInstanceProperties() )->getMessage() ); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Factory/000077500000000000000000000000001407505032400236345ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Factory/AbstractBaseFactoryTest.php000066400000000000000000000121441407505032400310750ustar00rootroot00000000000000createMock(Configuration::class); $this->generator = $this->createMock(ProxyGeneratorInterface::class); $this->classNameInflector = $this->createMock(ClassNameInflectorInterface::class); $this->generatorStrategy = $this->createMock(GeneratorStrategyInterface::class); $this->proxyAutoloader = $this->createMock(AutoloaderInterface::class); $this->signatureChecker = $this->createMock(SignatureCheckerInterface::class); $this->classSignatureGenerator = $this->createMock(ClassSignatureGeneratorInterface::class); $configuration ->method('getClassNameInflector') ->willReturn($this->classNameInflector); $configuration ->method('getGeneratorStrategy') ->willReturn($this->generatorStrategy); $configuration ->method('getProxyAutoloader') ->willReturn($this->proxyAutoloader); $configuration ->method('getSignatureChecker') ->willReturn($this->signatureChecker); $configuration ->method('getClassSignatureGenerator') ->willReturn($this->classSignatureGenerator); $this ->classNameInflector ->method('getUserClassName') ->willReturn('stdClass'); $this->factory = $this->getMockForAbstractClass(AbstractBaseFactory::class, [$configuration]); $this->factory->method('getGenerator')->willReturn($this->generator); } public function testGeneratesClass(): void { $generateProxy = new ReflectionMethod($this->factory, 'generateProxy'); $generateProxy->setAccessible(true); $generatedClass = UniqueIdentifierGenerator::getIdentifier('fooBar'); $this ->classNameInflector ->method('getProxyClassName') ->with('stdClass') ->willReturn($generatedClass); $this ->generatorStrategy ->expects(self::once()) ->method('generate') ->with(self::isInstanceOf(ClassGenerator::class)); $this ->proxyAutoloader ->expects(self::once()) ->method('__invoke') ->with($generatedClass) ->will(self::returnCallback(static function (string $className): bool { eval('class ' . $className . ' extends \\stdClass {}'); return true; })); $this->signatureChecker->expects(self::atLeastOnce())->method('checkSignature'); $this->classSignatureGenerator->expects(self::once())->method('addSignature')->will(self::returnArgument(0)); $this ->generator ->expects(self::once()) ->method('generate') ->with( self::callback(static function (ReflectionClass $reflectionClass): bool { return $reflectionClass->getName() === stdClass::class; }), self::isInstanceOf(ClassGenerator::class), ['some' => 'proxy', 'options' => 'here'] ); self::assertSame( $generatedClass, $generateProxy->invoke($this->factory, stdClass::class, ['some' => 'proxy', 'options' => 'here']) ); self::assertTrue(class_exists($generatedClass, false)); self::assertSame( $generatedClass, $generateProxy->invoke($this->factory, stdClass::class, ['some' => 'proxy', 'options' => 'here']) ); } } AccessInterceptorScopeLocalizerFactoryTest.php000066400000000000000000000161331407505032400347410ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Factoryconfig = $this->createMock(Configuration::class); $this->inflector = $this->createMock(ClassNameInflectorInterface::class); $this->signatureChecker = $this->createMock(SignatureCheckerInterface::class); $this->classSignatureGenerator = $this->createMock(ClassSignatureGeneratorInterface::class); $this ->config ->method('getClassNameInflector') ->willReturn($this->inflector); $this ->config ->method('getSignatureChecker') ->willReturn($this->signatureChecker); $this ->config ->method('getClassSignatureGenerator') ->willReturn($this->classSignatureGenerator); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory::__construct */ public static function testWithOptionalFactory(): void { $factory = new AccessInterceptorValueHolderFactory(); self::assertInstanceOf( Configuration::class, Assert::readAttribute( new AccessInterceptorValueHolderFactory(), 'configuration' ) ); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory::__construct * @covers \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory::createProxy * @covers \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory::getGenerator */ public function testWillSkipAutoGeneration(): void { $instance = new stdClass(); $this ->inflector ->expects(self::once()) ->method('getProxyClassName') ->with('stdClass') ->willReturn(AccessInterceptorValueHolderMock::class); $factory = new AccessInterceptorScopeLocalizerFactory($this->config); $prefixInterceptors = [ 'methodName' => static function (): void { self::fail('Not supposed to be called'); }, ]; $suffixInterceptors = [ 'methodName' => static function (): void { self::fail('Not supposed to be called'); }, ]; $proxy = $factory->createProxy($instance, $prefixInterceptors, $suffixInterceptors); self::assertSame($instance, $proxy->instance); self::assertSame($prefixInterceptors, $proxy->prefixInterceptors); self::assertSame($suffixInterceptors, $proxy->suffixInterceptors); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory::__construct * @covers \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory::createProxy * @covers \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory::getGenerator * * NOTE: serious mocking going on in here (a class is generated on-the-fly) - careful */ public function testWillTryAutoGeneration(): void { $instance = new stdClass(); $proxyClassName = UniqueIdentifierGenerator::getIdentifier('bar'); $generator = $this->createMock(GeneratorStrategyInterface::class); $autoloader = $this->createMock(AutoloaderInterface::class); $this->config->method('getGeneratorStrategy')->willReturn($generator); $this->config->method('getProxyAutoloader')->willReturn($autoloader); $generator ->expects(self::once()) ->method('generate') ->with( self::callback( static function (ClassGenerator $targetClass) use ($proxyClassName): bool { return $targetClass->getName() === $proxyClassName; } ) ); // simulate autoloading $autoloader ->expects(self::once()) ->method('__invoke') ->with($proxyClassName) ->willReturnCallback(static function () use ($proxyClassName): bool { eval( 'class ' . $proxyClassName . ' extends \\ProxyManagerTestAsset\\AccessInterceptorValueHolderMock {}' ); return true; }); $this ->inflector ->expects(self::once()) ->method('getProxyClassName') ->with('stdClass') ->willReturn($proxyClassName); $this ->inflector ->expects(self::once()) ->method('getUserClassName') ->with('stdClass') ->willReturn(LazyLoadingMock::class); $this->signatureChecker->expects(self::atLeastOnce())->method('checkSignature'); $this->classSignatureGenerator->expects(self::once())->method('addSignature')->will(self::returnArgument(0)); $factory = new AccessInterceptorScopeLocalizerFactory($this->config); $prefixInterceptors = [ 'methodName' => static function (): void { self::fail('Not supposed to be called'); }, ]; $suffixInterceptors = [ 'methodName' => static function (): void { self::fail('Not supposed to be called'); }, ]; $proxy = $factory->createProxy($instance, $prefixInterceptors, $suffixInterceptors); /** @noinspection UnnecessaryAssertionInspection */ self::assertInstanceOf($proxyClassName, $proxy); self::assertSame($instance, $proxy->instance); self::assertSame($prefixInterceptors, $proxy->prefixInterceptors); self::assertSame($suffixInterceptors, $proxy->suffixInterceptors); } } AccessInterceptorValueHolderFactoryTest.php000066400000000000000000000155531407505032400342420ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Factoryconfig = $this->createMock(Configuration::class); $this->inflector = $this->createMock(ClassNameInflectorInterface::class); $this->signatureChecker = $this->createMock(SignatureCheckerInterface::class); $this->classSignatureGenerator = $this->createMock(ClassSignatureGeneratorInterface::class); $this ->config ->method('getClassNameInflector') ->willReturn($this->inflector); $this ->config ->method('getSignatureChecker') ->willReturn($this->signatureChecker); $this ->config ->method('getClassSignatureGenerator') ->willReturn($this->classSignatureGenerator); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\AccessInterceptorValueHolderFactory::__construct */ public static function testWithOptionalFactory(): void { self::assertInstanceOf( Configuration::class, Assert::readAttribute(new AccessInterceptorValueHolderFactory(), 'configuration') ); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\AccessInterceptorValueHolderFactory::__construct * @covers \ProxyManager\Factory\AccessInterceptorValueHolderFactory::createProxy * @covers \ProxyManager\Factory\AccessInterceptorValueHolderFactory::getGenerator */ public function testWillSkipAutoGeneration(): void { $instance = new stdClass(); $this ->inflector ->expects(self::once()) ->method('getProxyClassName') ->with('stdClass') ->willReturn(AccessInterceptorValueHolderMock::class); $factory = new AccessInterceptorValueHolderFactory($this->config); $prefixInterceptors = [ 'methodName' => static function (): void { self::fail('Not supposed to be called'); }, ]; $suffixInterceptors = [ 'methodName' => static function (): void { self::fail('Not supposed to be called'); }, ]; $proxy = $factory->createProxy($instance, $prefixInterceptors, $suffixInterceptors); self::assertSame($instance, $proxy->instance); self::assertSame($prefixInterceptors, $proxy->prefixInterceptors); self::assertSame($suffixInterceptors, $proxy->suffixInterceptors); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\AccessInterceptorValueHolderFactory::__construct * @covers \ProxyManager\Factory\AccessInterceptorValueHolderFactory::createProxy * @covers \ProxyManager\Factory\AccessInterceptorValueHolderFactory::getGenerator * * NOTE: serious mocking going on in here (a class is generated on-the-fly) - careful */ public function testWillTryAutoGeneration(): void { $instance = new stdClass(); $proxyClassName = UniqueIdentifierGenerator::getIdentifier('bar'); $generator = $this->createMock(GeneratorStrategyInterface::class); $autoloader = $this->createMock(AutoloaderInterface::class); $this->config->method('getGeneratorStrategy')->will(self::returnValue($generator)); $this->config->method('getProxyAutoloader')->will(self::returnValue($autoloader)); $generator ->expects(self::once()) ->method('generate') ->with( self::callback( static function (ClassGenerator $targetClass) use ($proxyClassName): bool { return $targetClass->getName() === $proxyClassName; } ) ); // simulate autoloading $autoloader ->expects(self::once()) ->method('__invoke') ->with($proxyClassName) ->willReturnCallback(static function () use ($proxyClassName): bool { eval( 'class ' . $proxyClassName . ' extends \\ProxyManagerTestAsset\\AccessInterceptorValueHolderMock {}' ); return true; }); $this ->inflector ->expects(self::once()) ->method('getProxyClassName') ->with('stdClass') ->willReturn($proxyClassName); $this ->inflector ->expects(self::once()) ->method('getUserClassName') ->with('stdClass') ->willReturn(EmptyClass::class); $this->signatureChecker->expects(self::atLeastOnce())->method('checkSignature'); $this->classSignatureGenerator->expects(self::once())->method('addSignature')->will(self::returnArgument(0)); $factory = new AccessInterceptorValueHolderFactory($this->config); $prefixInterceptors = [ 'methodName' => static function (): void { self::fail('Not supposed to be called'); }, ]; $suffixInterceptors = [ 'methodName' => static function (): void { self::fail('Not supposed to be called'); }, ]; $proxy = $factory->createProxy($instance, $prefixInterceptors, $suffixInterceptors); self::assertInstanceOf($proxyClassName, $proxy); self::assertSame($instance, $proxy->instance); self::assertSame($prefixInterceptors, $proxy->prefixInterceptors); self::assertSame($suffixInterceptors, $proxy->suffixInterceptors); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Factory/LazyLoadingGhostFactoryTest.php000066400000000000000000000132601407505032400317610ustar00rootroot00000000000000config = $this->createMock(Configuration::class); $this->inflector = $this->createMock(ClassNameInflectorInterface::class); $this->signatureChecker = $this->createMock(SignatureCheckerInterface::class); $this->classSignatureGenerator = $this->createMock(ClassSignatureGeneratorInterface::class); $this ->config ->method('getClassNameInflector') ->willReturn($this->inflector); $this ->config ->method('getSignatureChecker') ->willReturn($this->signatureChecker); $this ->config ->method('getClassSignatureGenerator') ->willReturn($this->classSignatureGenerator); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\LazyLoadingGhostFactory::__construct */ public static function testWithOptionalFactory(): void { self::assertInstanceOf( Configuration::class, Assert::readAttribute(new LazyLoadingGhostFactory(), 'configuration') ); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\LazyLoadingGhostFactory::__construct * @covers \ProxyManager\Factory\LazyLoadingGhostFactory::createProxy */ public function testWillSkipAutoGeneration(): void { $className = UniqueIdentifierGenerator::getIdentifier('foo'); $this ->inflector ->expects(self::once()) ->method('getProxyClassName') ->with($className) ->willReturn(LazyLoadingMock::class); $factory = new LazyLoadingGhostFactory($this->config); $initializer = static function (): bool { return true; }; $proxy = $factory->createProxy($className, $initializer); self::assertSame($initializer, $proxy->getProxyInitializer()); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\LazyLoadingGhostFactory::__construct * @covers \ProxyManager\Factory\LazyLoadingGhostFactory::createProxy * @covers \ProxyManager\Factory\LazyLoadingGhostFactory::getGenerator * * NOTE: serious mocking going on in here (a class is generated on-the-fly) - careful */ public function testWillTryAutoGeneration(): void { /** @var class-string $className */ $className = UniqueIdentifierGenerator::getIdentifier('foo'); $proxyClassName = UniqueIdentifierGenerator::getIdentifier('bar'); $generator = $this->createMock(GeneratorStrategyInterface::class); $autoloader = $this->createMock(AutoloaderInterface::class); $this->config->method('getGeneratorStrategy')->willReturn($generator); $this->config->method('getProxyAutoloader')->willReturn($autoloader); $generator ->expects(self::once()) ->method('generate') ->with( self::callback( static function (ClassGenerator $targetClass) use ($proxyClassName): bool { return $targetClass->getName() === $proxyClassName; } ) ); // simulate autoloading $autoloader ->expects(self::once()) ->method('__invoke') ->with($proxyClassName) ->willReturnCallback(static function () use ($proxyClassName): bool { eval('class ' . $proxyClassName . ' extends \\ProxyManagerTestAsset\\LazyLoadingMock {}'); return true; }); $this ->inflector ->expects(self::once()) ->method('getProxyClassName') ->with($className) ->willReturn($proxyClassName); $this ->inflector ->expects(self::once()) ->method('getUserClassName') ->with($className) ->willReturn(LazyLoadingMock::class); $this->signatureChecker->expects(self::atLeastOnce())->method('checkSignature'); $this->classSignatureGenerator->expects(self::once())->method('addSignature')->will(self::returnArgument(0)); $factory = new LazyLoadingGhostFactory($this->config); $initializer = static function (): bool { return true; }; $proxy = $factory->createProxy($className, $initializer); self::assertSame($initializer, $proxy->getProxyInitializer()); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Factory/LazyLoadingValueHolderFactoryTest.php000066400000000000000000000136221407505032400331110ustar00rootroot00000000000000config = $this->createMock(Configuration::class); $this->inflector = $this->createMock(ClassNameInflectorInterface::class); $this->signatureChecker = $this->createMock(SignatureCheckerInterface::class); $this->classSignatureGenerator = $this->createMock(ClassSignatureGeneratorInterface::class); $this ->config ->method('getClassNameInflector') ->willReturn($this->inflector); $this ->config ->method('getSignatureChecker') ->willReturn($this->signatureChecker); $this ->config ->method('getClassSignatureGenerator') ->willReturn($this->classSignatureGenerator); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\LazyLoadingValueHolderFactory::__construct */ public static function testWithOptionalFactory(): void { self::assertInstanceOf( Configuration::class, Assert::readAttribute(new LazyLoadingValueHolderFactory(), 'configuration') ); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\LazyLoadingValueHolderFactory::__construct * @covers \ProxyManager\Factory\LazyLoadingValueHolderFactory::createProxy */ public function testWillSkipAutoGeneration(): void { $className = UniqueIdentifierGenerator::getIdentifier('foo'); $this ->inflector ->expects(self::once()) ->method('getProxyClassName') ->with($className) ->willReturn(LazyLoadingMock::class); $factory = new LazyLoadingValueHolderFactory($this->config); $initializer = static function (): bool { return true; }; $proxy = $factory->createProxy($className, $initializer); self::assertSame($initializer, $proxy->getProxyInitializer()); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\LazyLoadingValueHolderFactory::__construct * @covers \ProxyManager\Factory\LazyLoadingValueHolderFactory::createProxy * @covers \ProxyManager\Factory\LazyLoadingValueHolderFactory::getGenerator * * NOTE: serious mocking going on in here (a class is generated on-the-fly) - careful */ public function testWillTryAutoGeneration(): void { $className = UniqueIdentifierGenerator::getIdentifier('foo'); $proxyClassName = UniqueIdentifierGenerator::getIdentifier('bar'); $generator = $this->createMock(GeneratorStrategyInterface::class); $autoloader = $this->createMock(AutoloaderInterface::class); $this->config->method('getGeneratorStrategy')->will(self::returnValue($generator)); $this->config->method('getProxyAutoloader')->will(self::returnValue($autoloader)); $generator ->expects(self::once()) ->method('generate') ->with( self::callback( static function (ClassGenerator $targetClass) use ($proxyClassName): bool { return $targetClass->getName() === $proxyClassName; } ) ); // simulate autoloading $autoloader ->expects(self::once()) ->method('__invoke') ->with($proxyClassName) ->willReturnCallback(static function () use ($proxyClassName): bool { eval('class ' . $proxyClassName . ' extends \\ProxyManagerTestAsset\\LazyLoadingMock {}'); return true; }); $this ->inflector ->expects(self::once()) ->method('getProxyClassName') ->with($className) ->willReturn($proxyClassName); $this ->inflector ->expects(self::once()) ->method('getUserClassName') ->with($className) ->willReturn(EmptyClass::class); $this->signatureChecker->expects(self::atLeastOnce())->method('checkSignature'); $this->classSignatureGenerator->expects(self::once())->method('addSignature')->will(self::returnArgument(0)); $factory = new LazyLoadingValueHolderFactory($this->config); $initializer = static function (): bool { return true; }; $proxy = $factory->createProxy($className, $initializer); self::assertInstanceOf($proxyClassName, $proxy); self::assertSame($proxyClassName, get_class($proxy)); self::assertSame($initializer, $proxy->getProxyInitializer()); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Factory/NullObjectFactoryTest.php000066400000000000000000000115231407505032400306000ustar00rootroot00000000000000config = $this->createMock(Configuration::class); $this->inflector = $this->createMock(ClassNameInflectorInterface::class); $this->signatureChecker = $this->createMock(SignatureCheckerInterface::class); $this->classSignatureGenerator = $this->createMock(ClassSignatureGeneratorInterface::class); $this ->config ->method('getClassNameInflector') ->willReturn($this->inflector); $this ->config ->method('getSignatureChecker') ->willReturn($this->signatureChecker); $this ->config ->method('getClassSignatureGenerator') ->willReturn($this->classSignatureGenerator); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\NullObjectFactory::__construct * @covers \ProxyManager\Factory\NullObjectFactory::createProxy * @covers \ProxyManager\Factory\NullObjectFactory::getGenerator */ public function testWillSkipAutoGeneration(): void { $instance = new stdClass(); $this ->inflector ->expects(self::once()) ->method('getProxyClassName') ->with('stdClass') ->willReturn(NullObjectMock::class); (new NullObjectFactory($this->config))->createProxy($instance); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\NullObjectFactory::__construct * @covers \ProxyManager\Factory\NullObjectFactory::createProxy * @covers \ProxyManager\Factory\NullObjectFactory::getGenerator * * NOTE: serious mocking going on in here (a class is generated on-the-fly) - careful */ public function testWillTryAutoGeneration(): void { $instance = new stdClass(); $proxyClassName = UniqueIdentifierGenerator::getIdentifier('bar'); $generator = $this->createMock(GeneratorStrategyInterface::class); $autoloader = $this->createMock(AutoloaderInterface::class); $this->config->method('getGeneratorStrategy')->will(self::returnValue($generator)); $this->config->method('getProxyAutoloader')->will(self::returnValue($autoloader)); $generator ->expects(self::once()) ->method('generate') ->with( self::callback( static function (ClassGenerator $targetClass) use ($proxyClassName): bool { return $targetClass->getName() === $proxyClassName; } ) ); // simulate autoloading $autoloader ->expects(self::once()) ->method('__invoke') ->with($proxyClassName) ->willReturnCallback(static function () use ($proxyClassName): bool { eval('class ' . $proxyClassName . ' extends \\ProxyManagerTestAsset\\NullObjectMock {}'); return true; }); $this ->inflector ->expects(self::once()) ->method('getProxyClassName') ->with('stdClass') ->willReturn($proxyClassName); $this ->inflector ->expects(self::once()) ->method('getUserClassName') ->with('stdClass') ->willReturn(NullObjectMock::class); $this->signatureChecker->expects(self::atLeastOnce())->method('checkSignature'); $this->classSignatureGenerator->expects(self::once())->method('addSignature')->will(self::returnArgument(0)); $factory = new NullObjectFactory($this->config); $factory->createProxy($instance); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Factory/RemoteObject/000077500000000000000000000000001407505032400262165ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Factory/RemoteObject/Adapter/000077500000000000000000000000001407505032400275765ustar00rootroot00000000000000BaseAdapterTest.php000066400000000000000000000045771407505032400332600ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Factory/RemoteObject/AdaptergetMockBuilder(Client::class) ->setMethods(['call']) ->getMock(); $adapter = $this->getMockForAbstractClass( BaseAdapter::class, [$client] ); $client ->expects(self::once()) ->method('call') ->with('foobarbaz', ['tab' => 'taz']) ->willReturn('baz'); $adapter ->expects(self::once()) ->method('getServiceName') ->with('foo', 'bar') ->willReturn('foobarbaz'); self::assertSame('baz', $adapter->call('foo', 'bar', ['tab' => 'taz'])); } /** * {@inheritDoc} * * @covers \ProxyManager\Factory\RemoteObject\Adapter\BaseAdapter::__construct * @covers \ProxyManager\Factory\RemoteObject\Adapter\BaseAdapter::call * @covers \ProxyManager\Factory\RemoteObject\Adapter\Soap::getServiceName */ public function testBaseAdapterWithServiceMap(): void { $client = $this ->getMockBuilder(Client::class) ->setMethods(['call']) ->getMock(); $adapter = $this->getMockForAbstractClass( BaseAdapter::class, [$client, ['foobarbaz' => 'mapped']] ); $client ->expects(self::once()) ->method('call') ->with('mapped', ['tab' => 'taz']) ->willReturn('baz'); $adapter ->expects(self::once()) ->method('getServiceName') ->with('foo', 'bar') ->willReturn('foobarbaz'); self::assertSame('baz', $adapter->call('foo', 'bar', ['tab' => 'taz'])); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Factory/RemoteObject/Adapter/JsonRpcTest.php000066400000000000000000000020371407505032400325270ustar00rootroot00000000000000getMockBuilder(Client::class)->setMethods(['call'])->getMock(); $adapter = new JsonRpc($client); $client ->expects(self::once()) ->method('call') ->with('foo.bar', ['tab' => 'taz']) ->willReturn('baz'); self::assertSame('baz', $adapter->call('foo', 'bar', ['tab' => 'taz'])); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Factory/RemoteObject/Adapter/SoapTest.php000066400000000000000000000020111407505032400320430ustar00rootroot00000000000000getMockBuilder(Client::class)->setMethods(['call'])->getMock(); $adapter = new Soap($client); $client ->expects(self::once()) ->method('call') ->with('bar', ['tab' => 'taz']) ->willReturn('baz'); self::assertSame('baz', $adapter->call('foo', 'bar', ['tab' => 'taz'])); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Factory/RemoteObject/Adapter/XmlRpcTest.php000066400000000000000000000020061407505032400323520ustar00rootroot00000000000000getMockBuilder(Client::class)->setMethods(['call'])->getMock(); $adapter = new XmlRpc($client); $client ->expects(self::once()) ->method('call') ->with('foo.bar', ['taz']) ->willReturn('baz'); self::assertSame('baz', $adapter->call('foo', 'bar', ['taz'])); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Factory/RemoteObjectFactoryTest.php000066400000000000000000000115461407505032400311260ustar00rootroot00000000000000config = $this->createMock(Configuration::class); $this->inflector = $this->createMock(ClassNameInflectorInterface::class); $this->signatureChecker = $this->createMock(SignatureCheckerInterface::class); $this->classSignatureGenerator = $this->createMock(ClassSignatureGeneratorInterface::class); $this ->config ->method('getClassNameInflector') ->willReturn($this->inflector); $this ->config ->method('getSignatureChecker') ->willReturn($this->signatureChecker); $this ->config ->method('getClassSignatureGenerator') ->willReturn($this->classSignatureGenerator); } public function testWillSkipAutoGeneration(): void { $this ->inflector ->expects(self::once()) ->method('getProxyClassName') ->with(BaseInterface::class) ->willReturn(RemoteObjectMock::class); $adapter = $this->createMock(AdapterInterface::class); $factory = new RemoteObjectFactory($adapter, $this->config); $proxy = $factory->createProxy(BaseInterface::class); self::assertInstanceOf(RemoteObjectMock::class, $proxy); } /** * {@inheritDoc} * * NOTE: serious mocking going on in here (a class is generated on-the-fly) - careful */ public function testWillTryAutoGeneration(): void { $proxyClassName = UniqueIdentifierGenerator::getIdentifier('bar'); $generator = $this->createMock(GeneratorStrategyInterface::class); $autoloader = $this->createMock(AutoloaderInterface::class); $this->config->method('getGeneratorStrategy')->willReturn($generator); $this->config->method('getProxyAutoloader')->willReturn($autoloader); $generator ->expects(self::once()) ->method('generate') ->with( self::callback( static function (ClassGenerator $targetClass) use ($proxyClassName): bool { return $targetClass->getName() === $proxyClassName; } ) ); // simulate autoloading $autoloader ->expects(self::once()) ->method('__invoke') ->with($proxyClassName) ->willReturnCallback(static function () use ($proxyClassName): bool { eval( 'class ' . $proxyClassName . ' implements \ProxyManager\Proxy\RemoteObjectInterface {' . 'public static function staticProxyConstructor() : self { return new static(); }' . '}' ); return true; }); $this ->inflector ->expects(self::once()) ->method('getProxyClassName') ->with(BaseInterface::class) ->willReturn($proxyClassName); $this ->inflector ->expects(self::once()) ->method('getUserClassName') ->with(BaseInterface::class) ->willReturn('stdClass'); $this->signatureChecker->expects(self::atLeastOnce())->method('checkSignature'); $this->classSignatureGenerator->expects(self::once())->method('addSignature')->will(self::returnArgument(0)); $adapter = $this->createMock(AdapterInterface::class); $factory = new RemoteObjectFactory($adapter, $this->config); $factory->createProxy(BaseInterface::class); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/FileLocator/000077500000000000000000000000001407505032400244305ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/FileLocator/FileLocatorTest.php000066400000000000000000000022031407505032400302010ustar00rootroot00000000000000getProxyFileName('Foo\\Bar\\Baz')); self::assertSame(__DIR__ . DIRECTORY_SEPARATOR . 'Foo_Bar_Baz.php', $locator->getProxyFileName('Foo_Bar_Baz')); } /** * @covers \ProxyManager\FileLocator\FileLocator::__construct */ public function testRejectsNonExistingDirectory(): void { $this->expectException(InvalidProxyDirectoryException::class); new FileLocator(__DIR__ . '/non-existing'); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Functional/000077500000000000000000000000001407505032400243275ustar00rootroot00000000000000AccessInterceptorScopeLocalizerFunctionalTest.php000066400000000000000000000461701407505032400361330ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/FunctionalcreateProxy($instance); $this->assertProxySynchronized($instance, $proxy); $callback = [$proxy, $method]; self::assertIsCallable($callback); self::assertSame($expectedValue, $callback(...array_values($params))); $listener = $this->createMock(CallableInterface::class); $listener ->expects(self::once()) ->method('__invoke') ->with($proxy, $proxy, $method, $params, false); $proxy->setMethodPrefixInterceptor( $method, static function ( AccessInterceptorInterface $proxy, $instance, string $method, array $params, bool & $returnEarly ) use ($listener): void { $listener->__invoke($proxy, $instance, $method, $params, $returnEarly); } ); self::assertSame($expectedValue, $callback(...array_values($params))); $random = uniqid('', true); $proxy->setMethodPrefixInterceptor( $method, static function ( AccessInterceptorInterface $proxy, $instance, string $method, array $params, bool & $returnEarly ) use ($random): string { $returnEarly = true; return $random; } ); self::assertSame($random, $callback(...array_values($params))); $this->assertProxySynchronized($instance, $proxy); } /** * @param mixed[] $params * @param mixed $expectedValue * * @dataProvider getProxyMethods */ public function testMethodCallsWithSuffixListener( $instance, string $method, array $params, $expectedValue ): void { $proxy = (new AccessInterceptorScopeLocalizerFactory())->createProxy($instance); $callback = [$proxy, $method]; self::assertIsCallable($callback); $listener = $this->createMock(CallableInterface::class); $listener ->expects(self::once()) ->method('__invoke') ->with($proxy, $proxy, $method, $params, $expectedValue, false); $proxy->setMethodSuffixInterceptor( $method, /** @param mixed $returnValue */ static function ( AccessInterceptorInterface $proxy, $instance, string $method, array $params, $returnValue, bool & $returnEarly ) use ($listener): void { $listener->__invoke($proxy, $instance, $method, $params, $returnValue, $returnEarly); } ); self::assertSame($expectedValue, $callback(...array_values($params))); $random = uniqid('', true); $proxy->setMethodSuffixInterceptor( $method, /** @param mixed $returnValue */ static function ( AccessInterceptorInterface $proxy, $instance, string $method, array $params, $returnValue, bool & $returnEarly ) use ($random): string { $returnEarly = true; return $random; } ); self::assertSame($random, $callback(...array_values($params))); $this->assertProxySynchronized($instance, $proxy); } /** * @param mixed[] $params * @param mixed $expectedValue * * @dataProvider getProxyMethods */ public function testMethodCallsAfterUnSerialization( $instance, string $method, array $params, $expectedValue ): void { $proxy = unserialize(serialize((new AccessInterceptorScopeLocalizerFactory())->createProxy($instance))); assert($proxy instanceof AccessInterceptorInterface); $callback = [$proxy, $method]; self::assertIsCallable($callback); self::assertSame($expectedValue, $callback(...array_values($params))); $this->assertProxySynchronized($instance, $proxy); } /** * @param mixed[] $params * @param mixed $expectedValue * * @dataProvider getProxyMethods */ public function testMethodCallsAfterCloning( $instance, string $method, array $params, $expectedValue ): void { $proxy = (new AccessInterceptorScopeLocalizerFactory())->createProxy($instance); $cloned = clone $proxy; $callback = [$cloned, $method]; $this->assertProxySynchronized($instance, $proxy); self::assertIsCallable($callback); self::assertSame($expectedValue, $callback(...array_values($params))); $this->assertProxySynchronized($instance, $proxy); } /** * @param mixed $propertyValue * * @dataProvider getPropertyAccessProxies */ public function testPropertyReadAccess( $instance, AccessInterceptorInterface $proxy, string $publicProperty, $propertyValue ): void { self::assertSame($propertyValue, $proxy->$publicProperty); $this->assertProxySynchronized($instance, $proxy); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyWriteAccess($instance, AccessInterceptorInterface $proxy, string $publicProperty): void { $newValue = uniqid('value', true); $proxy->$publicProperty = $newValue; self::assertSame($newValue, $proxy->$publicProperty); $this->assertProxySynchronized($instance, $proxy); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyExistence($instance, AccessInterceptorInterface $proxy, string $publicProperty): void { self::assertSame(isset($instance->$publicProperty), isset($proxy->$publicProperty)); $this->assertProxySynchronized($instance, $proxy); $instance->$publicProperty = null; self::assertFalse(isset($proxy->$publicProperty)); $this->assertProxySynchronized($instance, $proxy); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyUnset($instance, AccessInterceptorInterface $proxy, string $publicProperty): void { self::markTestSkipped('It is currently not possible to synchronize properties un-setting'); unset($proxy->$publicProperty); self::assertFalse(isset($instance->$publicProperty)); self::assertFalse(isset($proxy->$publicProperty)); $this->assertProxySynchronized($instance, $proxy); } /** * Verifies that accessing a public property containing an array behaves like in a normal context */ public function testCanWriteToArrayKeysInPublicProperty(): void { $instance = new ClassWithPublicArrayPropertyAccessibleViaMethod(); $proxy = (new AccessInterceptorScopeLocalizerFactory())->createProxy($instance); $proxy->arrayProperty['foo'] = 'bar'; self::assertSame('bar', $proxy->getArrayProperty()['foo']); $proxy->arrayProperty = ['tab' => 'taz']; self::assertSame(['tab' => 'taz'], $proxy->arrayProperty); $this->assertProxySynchronized($instance, $proxy); } /** * Verifies that public properties retrieved via `__get` don't get modified in the object state */ public function testWillNotModifyRetrievedPublicProperties(): void { $instance = new ClassWithPublicProperties(); $proxy = (new AccessInterceptorScopeLocalizerFactory())->createProxy($instance); $variable = $proxy->property0; self::assertByRefVariableValueSame('property0', $variable); $variable = 'foo'; self::assertSame('property0', $proxy->property0); $this->assertProxySynchronized($instance, $proxy); self::assertByRefVariableValueSame('foo', $variable); } /** * Verifies that public properties references retrieved via `__get` modify in the object state */ public function testWillModifyByRefRetrievedPublicProperties(): void { $instance = new ClassWithPublicProperties(); $proxy = (new AccessInterceptorScopeLocalizerFactory())->createProxy($instance); $variable = & $proxy->property0; self::assertByRefVariableValueSame('property0', $variable); $variable = 'foo'; self::assertSame('foo', $proxy->property0); $this->assertProxySynchronized($instance, $proxy); self::assertByRefVariableValueSame('foo', $variable); } /** * @group 115 * @group 175 */ public function testWillBehaveLikeObjectWithNormalConstructor(): void { $instance = new ClassWithCounterConstructor(10); self::assertSame(10, $instance->amount, 'Verifying that test asset works as expected'); self::assertSame(10, $instance->getAmount(), 'Verifying that test asset works as expected'); $instance->__construct(3); self::assertSame(13, $instance->amount, 'Verifying that test asset works as expected'); self::assertSame(13, $instance->getAmount(), 'Verifying that test asset works as expected'); $proxyName = get_class( (new AccessInterceptorScopeLocalizerFactory()) ->createProxy(new ClassWithCounterConstructor(0)) ); /** @psalm-suppress UnsafeInstantiation it is allowed (by design) to instantiate these proxies */ $proxy = new $proxyName(15); self::assertSame(15, $proxy->amount, 'Verifying that the proxy constructor works as expected'); self::assertSame(15, $proxy->getAmount(), 'Verifying that the proxy constructor works as expected'); $proxy->__construct(5); self::assertSame(20, $proxy->amount, 'Verifying that the proxy constructor works as expected'); self::assertSame(20, $proxy->getAmount(), 'Verifying that the proxy constructor works as expected'); } /** * Generates a list of object | invoked method | parameters | expected result * * @return array|string>> */ public static function getProxyMethods(): array { $selfHintParam = new ClassWithSelfHint(); $empty = new EmptyClass(); return [ [ new BaseClass(), 'publicMethod', [], 'publicMethodDefault', ], [ new BaseClass(), 'publicTypeHintedMethod', ['param' => new stdClass()], 'publicTypeHintedMethodDefault', ], [ new BaseClass(), 'publicByReferenceMethod', [], 'publicByReferenceMethodDefault', ], [ new ClassWithSelfHint(), 'selfHintMethod', ['parameter' => $selfHintParam], $selfHintParam, ], [ new ClassWithParentHint(), 'parentHintMethod', ['parameter' => $empty], $empty, ], ]; } /** * Generates proxies and instances with a public property to feed to the property accessor methods * * @return array> */ public function getPropertyAccessProxies(): array { $instance = new BaseClass(); return [ [ $instance, (new AccessInterceptorScopeLocalizerFactory())->createProxy($instance), 'publicProperty', 'publicPropertyDefault', ], ]; } private function assertProxySynchronized($instance, AccessInterceptorInterface $proxy): void { $reflectionClass = new ReflectionClass($instance); foreach (Properties::fromReflectionClass($reflectionClass)->getInstanceProperties() as $property) { $property->setAccessible(true); self::assertSame( $property->getValue($instance), $property->getValue($proxy), 'Property "' . $property->getName() . '" is synchronized between instance and proxy' ); } } public function testWillForwardVariadicArguments(): void { $configuration = new Configuration(); $factory = new AccessInterceptorScopeLocalizerFactory($configuration); $targetObject = new ClassWithMethodWithVariadicFunction(); $object = $factory->createProxy( $targetObject, [ 'bar' => static function (): string { return 'Foo Baz'; }, ] ); self::assertNull($object->bar); self::assertNull($object->baz); $object->foo('Ocramius', 'Malukenho', 'Danizord'); self::assertSame('Ocramius', $object->bar); self::assertSame(['Malukenho', 'Danizord'], Assert::readAttribute($object, 'baz')); } /** * @group 265 */ public function testWillForwardVariadicByRefArguments(): void { $configuration = new Configuration(); $factory = new AccessInterceptorScopeLocalizerFactory($configuration); $targetObject = new ClassWithMethodWithByRefVariadicFunction(); $object = $factory->createProxy( $targetObject, [ 'bar' => static function (): string { return 'Foo Baz'; }, ] ); $parameters = ['a', 'b', 'c']; // first, testing normal variadic behavior (verifying we didn't screw up in the test asset) self::assertSame(['a', 'changed', 'c'], (new ClassWithMethodWithByRefVariadicFunction())->tuz(...$parameters)); self::assertSame(['a', 'changed', 'c'], $object->tuz(...$parameters)); self::assertSame(['a', 'changed', 'c'], $parameters, 'by-ref variadic parameter was changed'); } /** * This test documents a known limitation: `func_get_args()` (and similar) don't work in proxied APIs. * If you manage to make this test pass, then please do send a patch * * @group 265 */ public function testWillNotForwardDynamicArguments(): void { $object = (new AccessInterceptorScopeLocalizerFactory()) ->createProxy( new ClassWithDynamicArgumentsMethod(), [ 'dynamicArgumentsMethod' => static function (): string { return 'Foo Baz'; }, ] ); self::assertSame(['a', 'b'], (new ClassWithDynamicArgumentsMethod())->dynamicArgumentsMethod('a', 'b')); $this->expectException(ExpectationFailedException::class); self::assertSame(['a', 'b'], $object->dynamicArgumentsMethod('a', 'b')); } /** * @group 327 */ public function testWillInterceptAndReturnEarlyOnVoidMethod(): void { $skip = random_int(100, 200); $addMore = random_int(201, 300); $increment = random_int(301, 400); $object = (new AccessInterceptorScopeLocalizerFactory()) ->createProxy( new VoidCounter(), [ 'increment' => static function ( AccessInterceptorInterface $proxy, VoidCounter $instance, string $method, array $params, ?bool & $returnEarly ) use ($skip): void { if ($skip !== $params['amount']) { return; } $returnEarly = true; }, ], [ 'increment' => static function ( AccessInterceptorInterface $proxy, VoidCounter $instance, string $method, array $params, ?bool & $returnEarly ) use ($addMore): void { if ($addMore !== $params['amount']) { return; } $instance->counter += 1; }, ] ); $object->increment($skip); self::assertSame(0, $object->counter); $object->increment($increment); self::assertSame($increment, $object->counter); $object->increment($addMore); self::assertSame($increment + $addMore + 1, $object->counter); } /** * @group 574 * @requires PHP 7.4 */ public function testWillRefuseToGenerateReferencesToTypedPropertiesWithoutDefaultValues(): void { $instance = new ClassWithPublicStringNullableTypedProperty(); $factory = new AccessInterceptorScopeLocalizerFactory(); $this->expectException(UnsupportedProxiedClassException::class); $factory->createProxy($instance); } /** * @param mixed $expected * @param mixed $actual * * @psalm-template ExpectedType * @psalm-param ExpectedType $expected * @psalm-assert ExpectedType $actual */ private static function assertByRefVariableValueSame($expected, & $actual): void { self::assertSame($expected, $actual); } } AccessInterceptorValueHolderFunctionalTest.php000066400000000000000000000602351407505032400354250ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/FunctionalcreateProxy($instance); $callback = [$proxy, $method]; self::assertIsCallable($callback); self::assertSame($instance, $proxy->getWrappedValueHolderValue()); self::assertSame($expectedValue, $callback(...array_values($params))); $listener = $this->createMock(CallableInterface::class); $listener ->expects(self::once()) ->method('__invoke') ->with($proxy, $instance, $method, $params, false); $proxy->setMethodPrefixInterceptor( $method, static function ( AccessInterceptorInterface $proxy, $instance, string $method, array $params, bool & $returnEarly ) use ($listener): void { $listener->__invoke($proxy, $instance, $method, $params, $returnEarly); } ); self::assertSame($expectedValue, $callback(...array_values($params))); $random = uniqid('', true); $proxy->setMethodPrefixInterceptor( $method, static function ( AccessInterceptorInterface $proxy, $instance, string $method, array $params, bool & $returnEarly ) use ($random): string { $returnEarly = true; return $random; } ); self::assertSame($random, $callback(...array_values($params))); } /** * @param mixed[] $params * @param mixed $expectedValue * * @dataProvider getProxyMethods */ public function testMethodCallsWithSuffixListener( $instance, string $method, array $params, $expectedValue ): void { $proxy = (new AccessInterceptorValueHolderFactory())->createProxy($instance); $callback = [$proxy, $method]; self::assertIsCallable($callback); $listener = $this->createMock(CallableInterface::class); $listener ->expects(self::once()) ->method('__invoke') ->with($proxy, $instance, $method, $params, $expectedValue, false); $proxy->setMethodSuffixInterceptor( $method, /** @param mixed $returnValue */ static function ( AccessInterceptorInterface $proxy, $instance, string $method, array $params, $returnValue, bool & $returnEarly ) use ($listener): void { $listener->__invoke($proxy, $instance, $method, $params, $returnValue, $returnEarly); } ); self::assertSame($expectedValue, $callback(...array_values($params))); $random = uniqid('', true); $proxy->setMethodSuffixInterceptor( $method, /** @param mixed $returnValue */ static function ( AccessInterceptorInterface $proxy, $instance, string $method, array $params, $returnValue, bool & $returnEarly ) use ($random): string { $returnEarly = true; return $random; } ); self::assertSame($random, $callback(...array_values($params))); } /** * @param mixed[] $params * @param mixed $expectedValue * * @dataProvider getProxyMethods */ public function testMethodCallsAfterUnSerialization( $instance, string $method, array $params, $expectedValue ): void { $proxy = unserialize(serialize((new AccessInterceptorValueHolderFactory())->createProxy($instance))); assert($proxy instanceof AccessInterceptorValueHolderInterface); $callback = [$proxy, $method]; self::assertIsCallable($callback); self::assertSame($expectedValue, $callback(...array_values($params))); self::assertEquals($instance, $proxy->getWrappedValueHolderValue()); } /** * @param mixed[] $params * @param mixed $expectedValue * * @dataProvider getProxyMethods */ public function testMethodCallsAfterCloning( $instance, string $method, array $params, $expectedValue ): void { $proxy = (new AccessInterceptorValueHolderFactory())->createProxy($instance); $cloned = clone $proxy; $callback = [$cloned, $method]; self::assertIsCallable($callback); self::assertNotSame($proxy->getWrappedValueHolderValue(), $cloned->getWrappedValueHolderValue()); self::assertSame($expectedValue, $callback(...array_values($params))); self::assertEquals($instance, $cloned->getWrappedValueHolderValue()); } /** * @param mixed $propertyValue * * @dataProvider getPropertyAccessProxies */ public function testPropertyReadAccess( $instance, AccessInterceptorValueHolderInterface $proxy, string $publicProperty, $propertyValue ): void { self::assertSame($propertyValue, $proxy->$publicProperty); self::assertEquals($instance, $proxy->getWrappedValueHolderValue()); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyWriteAccess( $instance, AccessInterceptorValueHolderInterface $proxy, string $publicProperty ): void { $newValue = uniqid('', true); $proxy->$publicProperty = $newValue; self::assertSame($newValue, $proxy->$publicProperty); $wrappedValue = $proxy->getWrappedValueHolderValue(); self::assertNotNull($wrappedValue); self::assertSame($newValue, $wrappedValue->$publicProperty); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyExistence( $instance, AccessInterceptorValueHolderInterface $proxy, string $publicProperty ): void { self::assertSame(isset($instance->$publicProperty), isset($proxy->$publicProperty)); self::assertEquals($instance, $proxy->getWrappedValueHolderValue()); $propertyType = \PHP_VERSION_ID >= 70400 ? (new ReflectionProperty($instance, $publicProperty))->getType() : null; if ($propertyType !== null && ! $propertyType->allowsNull()) { return; } $proxy->getWrappedValueHolderValue()->$publicProperty = null; self::assertFalse(isset($proxy->$publicProperty)); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyUnset( $instance, AccessInterceptorValueHolderInterface $proxy, string $publicProperty ): void { $instance = $proxy->getWrappedValueHolderValue() ?? $instance; unset($proxy->$publicProperty); self::assertFalse(isset($instance->$publicProperty)); self::assertFalse(isset($proxy->$publicProperty)); } /** * Verifies that accessing a public property containing an array behaves like in a normal context */ public function testCanWriteToArrayKeysInPublicProperty(): void { $instance = new ClassWithPublicArrayPropertyAccessibleViaMethod(); $proxy = (new AccessInterceptorValueHolderFactory())->createProxy($instance); $proxy->arrayProperty['foo'] = 'bar'; self::assertSame('bar', $proxy->getArrayProperty()['foo']); $proxy->arrayProperty = ['tab' => 'taz']; self::assertSame(['tab' => 'taz'], $proxy->getArrayProperty()); } /** * Verifies that public properties retrieved via `__get` don't get modified in the object state */ public function testWillNotModifyRetrievedPublicProperties(): void { $instance = new ClassWithPublicProperties(); $proxy = (new AccessInterceptorValueHolderFactory())->createProxy($instance); $variable = $proxy->property0; self::assertByRefVariableValueSame('property0', $variable); $variable = 'foo'; self::assertSame('property0', $proxy->property0); self::assertByRefVariableValueSame('foo', $variable); } /** * Verifies that public properties references retrieved via `__get` modify in the object state */ public function testWillModifyByRefRetrievedPublicProperties(): void { $instance = new ClassWithPublicProperties(); $proxy = (new AccessInterceptorValueHolderFactory())->createProxy($instance); $variable = & $proxy->property0; self::assertByRefVariableValueSame('property0', $variable); $variable = 'foo'; self::assertSame('foo', $proxy->property0); self::assertByRefVariableValueSame('foo', $variable); } /** * @group 115 * @group 175 */ public function testWillBehaveLikeObjectWithNormalConstructor(): void { $instance = new ClassWithCounterConstructor(10); self::assertSame(10, $instance->amount, 'Verifying that test asset works as expected'); self::assertSame(10, $instance->getAmount(), 'Verifying that test asset works as expected'); $instance->__construct(3); self::assertSame(13, $instance->amount, 'Verifying that test asset works as expected'); self::assertSame(13, $instance->getAmount(), 'Verifying that test asset works as expected'); $proxyName = get_class( (new AccessInterceptorValueHolderFactory()) ->createProxy(new ClassWithCounterConstructor(0)) ); /** @psalm-suppress UnsafeInstantiation it is allowed (by design) to instantiate these proxies */ $proxy = new $proxyName(15); self::assertSame(15, $proxy->amount, 'Verifying that the proxy constructor works as expected'); self::assertSame(15, $proxy->getAmount(), 'Verifying that the proxy constructor works as expected'); $proxy->__construct(5); self::assertSame(20, $proxy->amount, 'Verifying that the proxy constructor works as expected'); self::assertSame(20, $proxy->getAmount(), 'Verifying that the proxy constructor works as expected'); } public function testWillForwardVariadicArguments(): void { $factory = new AccessInterceptorValueHolderFactory(); $targetObject = new ClassWithMethodWithVariadicFunction(); $object = $factory->createProxy( $targetObject, [ 'bar' => static function (): string { return 'Foo Baz'; }, ] ); self::assertNull($object->bar); self::assertNull($object->baz); $object->foo('Ocramius', 'Malukenho', 'Danizord'); self::assertSame('Ocramius', $object->bar); self::assertSame(['Malukenho', 'Danizord'], Assert::readAttribute($object, 'baz')); } /** * @group 265 */ public function testWillForwardVariadicByRefArguments(): void { $object = (new AccessInterceptorValueHolderFactory())->createProxy( new ClassWithMethodWithByRefVariadicFunction(), [ 'bar' => static function (): string { return 'Foo Baz'; }, ] ); $arguments = ['Ocramius', 'Malukenho', 'Danizord']; self::assertSame( ['Ocramius', 'changed', 'Danizord'], (new ClassWithMethodWithByRefVariadicFunction())->tuz(...$arguments), 'Verifying that the implementation of the test asset is correct before proceeding' ); self::assertSame(['Ocramius', 'changed', 'Danizord'], $object->tuz(...$arguments)); self::assertSame(['Ocramius', 'changed', 'Danizord'], $arguments, 'By-ref arguments were changed'); } /** * This test documents a known limitation: `func_get_args()` (and similars) don't work in proxied APIs. * If you manage to make this test pass, then please do send a patch * * @group 265 */ public function testWillNotForwardDynamicArguments(): void { $object = (new AccessInterceptorValueHolderFactory())->createProxy(new ClassWithDynamicArgumentsMethod()); self::assertSame(['a', 'b'], (new ClassWithDynamicArgumentsMethod())->dynamicArgumentsMethod('a', 'b')); $this->expectException(ExpectationFailedException::class); self::assertSame(['a', 'b'], $object->dynamicArgumentsMethod('a', 'b')); } /** * Generates a list of object | invoked method | parameters | expected result * * @return string[][]|object[][]|mixed[][] */ public function getProxyMethods(): array { $selfHintParam = new ClassWithSelfHint(); $empty = new EmptyClass(); return [ [ new BaseClass(), 'publicMethod', [], 'publicMethodDefault', ], [ new BaseClass(), 'publicTypeHintedMethod', ['param' => new stdClass()], 'publicTypeHintedMethodDefault', ], [ new BaseClass(), 'publicByReferenceMethod', [], 'publicByReferenceMethodDefault', ], [ new BaseClass(), 'publicMethod', [], 'publicMethodDefault', ], [ new ClassWithSelfHint(), 'selfHintMethod', ['parameter' => $selfHintParam], $selfHintParam, ], [ new ClassWithParentHint(), 'parentHintMethod', ['parameter' => $empty], $empty, ], ]; } /** * Generates proxies and instances with a public property to feed to the property accessor methods * * @return array> */ public function getPropertyAccessProxies(): array { $instance1 = new BaseClass(); $instance2 = new BaseClass(); $factory = new AccessInterceptorValueHolderFactory(); $serialized = unserialize(serialize($factory->createProxy($instance2))); assert($serialized instanceof AccessInterceptorValueHolderInterface); $tests = [ [ $instance1, $factory->createProxy($instance1), 'publicProperty', 'publicPropertyDefault', ], [ $instance2, $serialized, 'publicProperty', 'publicPropertyDefault', ], ]; if (\PHP_VERSION_ID < 70400) { return $tests; } $typedProperty = new ClassWithPublicStringTypedProperty(); $typedNullableProperty = new ClassWithPublicStringNullableTypedProperty(); $typedProperty->typedProperty = 'Typed property initialized value'; $typedNullableProperty->typedNullableProperty = 'Typed nullable property initialized value'; return array_merge($tests, [ [ $typedProperty, $factory->createProxy($typedProperty), 'typedProperty', 'Typed property initialized value', ], [ $typedNullableProperty, $factory->createProxy($typedNullableProperty), 'typedNullableProperty', 'Typed nullable property initialized value', ], ]); } /** * @group 276 * @dataProvider getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope */ public function testWillInterceptAccessToPropertiesViaFriendClassAccess( $callerObject, $realInstance, string $method, string $expectedValue, string $propertyName ): void { $proxy = (new AccessInterceptorValueHolderFactory())->createProxy($realInstance); $listener = $this->createMock(CallableInterface::class); $listener ->expects(self::once()) ->method('__invoke') ->with($proxy, $realInstance, '__get', ['name' => $propertyName]); $proxy->setMethodPrefixInterceptor( '__get', static function ($proxy, $instance, string $method, array $params, bool & $returnEarly) use ($listener): void { $listener->__invoke($proxy, $instance, $method, $params, $returnEarly); } ); $accessor = [$callerObject, $method]; assert(is_callable($accessor)); self::assertSame($expectedValue, $accessor($proxy)); } /** * @group 276 * @dataProvider getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope */ public function testWillInterceptAccessToPropertiesViaFriendClassAccessEvenIfDeSerialized( $callerObject, $realInstance, string $method, string $expectedValue, string $propertyName ): void { $proxy = unserialize(serialize((new AccessInterceptorValueHolderFactory())->createProxy($realInstance))); assert($proxy instanceof AccessInterceptorValueHolderInterface); $listener = $this->createMock(CallableInterface::class); $listener ->expects(self::once()) ->method('__invoke') ->with($proxy, $realInstance, '__get', ['name' => $propertyName]); $proxy->setMethodPrefixInterceptor( '__get', static function ($proxy, $instance, string $method, array $params, bool & $returnEarly) use ($listener): void { $listener->__invoke($proxy, $instance, $method, $params, $returnEarly); } ); $accessor = [$callerObject, $method]; assert(is_callable($accessor)); self::assertSame($expectedValue, $accessor($proxy)); } /** * @group 276 * @dataProvider getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope */ public function testWillInterceptAccessToPropertiesViaFriendClassAccessEvenIfCloned( $callerObject, $realInstance, string $method, string $expectedValue, string $propertyName ): void { $proxy = clone (new AccessInterceptorValueHolderFactory())->createProxy($realInstance); $listener = $this->createMock(CallableInterface::class); $listener ->expects(self::once()) ->method('__invoke') ->with($proxy, $realInstance, '__get', ['name' => $propertyName]); $proxy->setMethodPrefixInterceptor( '__get', static function ($proxy, $instance, string $method, array $params, bool & $returnEarly) use ($listener): void { $listener->__invoke($proxy, $instance, $method, $params, $returnEarly); } ); $accessor = [$callerObject, $method]; assert(is_callable($accessor)); self::assertSame($expectedValue, $accessor($proxy)); } public function getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope(): Generator { foreach ((new ReflectionClass(OtherObjectAccessClass::class))->getProperties() as $property) { $property->setAccessible(true); $propertyName = $property->getName(); $realInstance = new OtherObjectAccessClass(); $expectedValue = uniqid('', true); $property->setValue($realInstance, $expectedValue); // callee is an actual object yield OtherObjectAccessClass::class . '#$' . $propertyName => [ new OtherObjectAccessClass(), $realInstance, 'get' . ucfirst($propertyName), $expectedValue, $propertyName, ]; $realInstance = new OtherObjectAccessClass(); $expectedValue = uniqid('', true); $property->setValue($realInstance, $expectedValue); // callee is a proxy (not to be lazy-loaded!) yield '(proxy) ' . OtherObjectAccessClass::class . '#$' . $propertyName => [ (new AccessInterceptorValueHolderFactory())->createProxy(new OtherObjectAccessClass()), $realInstance, 'get' . ucfirst($propertyName), $expectedValue, $propertyName, ]; } } /** * @group 327 */ public function testWillInterceptAndReturnEarlyOnVoidMethod(): void { $skip = random_int(100, 200); $addMore = random_int(201, 300); $increment = random_int(301, 400); $object = (new AccessInterceptorValueHolderFactory())->createProxy( new VoidCounter(), [ 'increment' => static function ( AccessInterceptorInterface $proxy, VoidCounter $instance, string $method, array $params, ?bool & $returnEarly ) use ($skip): void { if ($skip !== $params['amount']) { return; } $returnEarly = true; }, ], [ 'increment' => static function ( AccessInterceptorInterface $proxy, VoidCounter $instance, string $method, array $params, ?bool & $returnEarly ) use ($addMore): void { if ($addMore !== $params['amount']) { return; } /** @noinspection IncrementDecrementOperationEquivalentInspection */ $instance->counter += 1; }, ] ); $object->increment($skip); self::assertSame(0, $object->counter); $object->increment($increment); self::assertSame($increment, $object->counter); $object->increment($addMore); self::assertSame($increment + $addMore + 1, $object->counter); } /** * @param mixed $expected * @param mixed $actual */ private static function assertByRefVariableValueSame($expected, & $actual): void { self::assertSame($expected, $actual); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Functional/FatalPreventionFunctionalTest.php000066400000000000000000000122341407505032400330260ustar00rootroot00000000000000 $generatorClass * @psalm-param class-string $className */ public function testCodeGeneration(string $generatorClass, string $className): void { $generatedClass = new ClassGenerator(uniqid('generated', true)); $generatorStrategy = new EvaluatingGeneratorStrategy(); $classGenerator = new $generatorClass(); $classSignatureGenerator = new ClassSignatureGenerator(new SignatureGenerator()); try { $classGenerator->generate(new ReflectionClass($className), $generatedClass); $classSignatureGenerator->addSignature($generatedClass, ['key' => 'eval tests']); $generatorStrategy->generate($generatedClass); } catch (ExceptionInterface $e) { // empty catch: this is actually a supported failure } catch (ReflectionException $e) { // empty catch: this is actually a supported failure } self::assertTrue(true, 'Code generation succeeded: proxy is valid or couldn\'t be generated at all'); } /** * @return string[][] * * @psalm-return array|class-string>> */ public function getTestedClasses(): array { return array_merge( [], ...array_map( function ($generator): array { return array_map( static function ($class) use ($generator): array { return [$generator, $class]; }, $this->getProxyTestedClasses() ); }, [ AccessInterceptorScopeLocalizerGenerator::class, AccessInterceptorValueHolderGenerator::class, LazyLoadingGhostGenerator::class, LazyLoadingValueHolderGenerator::class, NullObjectGenerator::class, RemoteObjectGenerator::class, ] ) ); } /** * @return string[] * * @psalm-return array * * @private (public only for PHP 5.3 compatibility) */ private function getProxyTestedClasses(): array { $skippedPaths = [ realpath(__DIR__ . '/../../../src'), realpath(__DIR__ . '/../../../vendor'), realpath(__DIR__ . '/../../ProxyManagerTest'), ]; return array_filter( get_declared_classes(), static function ($className) use ($skippedPaths): bool { $reflectionClass = new ReflectionClass($className); $fileName = $reflectionClass->getFileName(); if (! $fileName) { return false; } if ($reflectionClass->implementsInterface(ProxyInterface::class)) { return false; } $realPath = realpath($fileName); self::assertIsString($realPath); foreach ($skippedPaths as $skippedPath) { self::assertIsString($skippedPath); if (strpos($realPath, $skippedPath) === 0) { // skip classes defined within ProxyManager, vendor or the test suite return false; } } return true; } ); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Functional/LazyLoadingGhostFunctionalTest.php000066400000000000000000001547511407505032400331620ustar00rootroot00000000000000 $className * @psalm-param OriginalClass $instance */ public function testMethodCallsThatLazyLoadTheObject( string $className, $instance, string $method, array $params, $expectedValue ): void { $proxy = (new LazyLoadingGhostFactory()) ->createProxy($className, $this->createInitializer($className, $instance)); self::assertFalse($proxy->isProxyInitialized()); $callProxyMethod = [$proxy, $method]; $parameterValues = array_values($params); self::assertIsCallable($callProxyMethod); self::assertSame($expectedValue, $callProxyMethod(...$parameterValues)); self::assertTrue($proxy->isProxyInitialized()); } /** * @param mixed[] $params * @param mixed $expectedValue * * @dataProvider getProxyNonInitializingMethods * * @psalm-template OriginalClass * @psalm-param class-string $className * @psalm-param OriginalClass $instance */ public function testMethodCallsThatDoNotLazyLoadTheObject( string $className, $instance, string $method, array $params, $expectedValue ): void { $initializeMatcher = $this->createMock(CallableInterface::class); $initializeMatcher->expects(self::never())->method('__invoke'); // should not initialize the proxy $proxy = (new LazyLoadingGhostFactory())->createProxy( $className, $this->createInitializer($className, $instance, $initializeMatcher) ); self::assertFalse($proxy->isProxyInitialized()); $callProxyMethod = [$proxy, $method]; $parameterValues = array_values($params); self::assertIsCallable($callProxyMethod); self::assertSame($expectedValue, $callProxyMethod(...$parameterValues)); self::assertFalse($proxy->isProxyInitialized()); } /** * @param mixed[] $params * @param mixed $expectedValue * * @dataProvider getProxyMethods * * @psalm-template OriginalClass * @psalm-param class-string $className * @psalm-param OriginalClass $instance */ public function testMethodCallsAfterUnSerialization( string $className, $instance, string $method, array $params, $expectedValue ): void { $proxy = unserialize(serialize((new LazyLoadingGhostFactory())->createProxy( $className, $this->createInitializer($className, $instance) ))); assert($proxy instanceof GhostObjectInterface); self::assertTrue($proxy->isProxyInitialized()); $callProxyMethod = [$proxy, $method]; $parameterValues = array_values($params); self::assertIsCallable($callProxyMethod); self::assertSame($expectedValue, $callProxyMethod(...$parameterValues)); } /** * @param mixed[] $params * @param mixed $expectedValue * * @dataProvider getProxyMethods * * @psalm-template OriginalClass * @psalm-param class-string $className * @psalm-param OriginalClass $instance */ public function testMethodCallsAfterCloning( string $className, $instance, string $method, array $params, $expectedValue ): void { $proxy = (new LazyLoadingGhostFactory())->createProxy( $className, $this->createInitializer($className, $instance) ); $cloned = clone $proxy; self::assertTrue($cloned->isProxyInitialized()); $callProxyMethod = [$proxy, $method]; $parameterValues = array_values($params); self::assertIsCallable($callProxyMethod); self::assertSame($expectedValue, $callProxyMethod(...$parameterValues)); } /** * @param mixed $propertyValue * * @dataProvider getPropertyAccessProxies */ public function testPropertyReadAccess( $instance, GhostObjectInterface $proxy, string $publicProperty, $propertyValue ): void { self::assertSame($propertyValue, $proxy->$publicProperty); self::assertTrue($proxy->isProxyInitialized()); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyWriteAccess($instance, GhostObjectInterface $proxy, string $publicProperty): void { $newValue = uniqid('', true); $proxy->$publicProperty = $newValue; self::assertTrue($proxy->isProxyInitialized()); self::assertSame($newValue, $proxy->$publicProperty); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyExistence($instance, GhostObjectInterface $proxy, string $publicProperty): void { self::assertSame(isset($instance->$publicProperty), isset($proxy->$publicProperty)); self::assertTrue($proxy->isProxyInitialized()); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyAbsence($instance, GhostObjectInterface $proxy, string $publicProperty): void { $propertyType = \PHP_VERSION_ID >= 70400 ? (new ReflectionProperty($instance, $publicProperty))->getType() : null; if ($propertyType !== null && ! $propertyType->allowsNull()) { self::markTestSkipped('Non-nullable typed properties cannot be removed/unset'); } $proxy->$publicProperty = null; self::assertFalse(isset($proxy->$publicProperty)); self::assertTrue($proxy->isProxyInitialized()); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyUnset($instance, GhostObjectInterface $proxy, string $publicProperty): void { unset($proxy->$publicProperty); self::assertTrue($proxy->isProxyInitialized()); self::assertTrue(isset($instance->$publicProperty)); self::assertFalse(isset($proxy->$publicProperty)); } /** * Verifies that accessing a public property containing an array behaves like in a normal context */ public function testCanWriteToArrayKeysInPublicProperty(): void { $proxy = (new LazyLoadingGhostFactory())->createProxy( ClassWithPublicArrayProperty::class, $this->createInitializer(ClassWithPublicArrayProperty::class, new ClassWithPublicArrayProperty()) ); $proxy->arrayProperty['foo'] = 'bar'; self::assertByRefVariableValueSame('bar', $proxy->arrayProperty['foo']); $proxy->arrayProperty = ['tab' => 'taz']; self::assertSame(['tab' => 'taz'], $proxy->arrayProperty); } /** * Verifies that public properties retrieved via `__get` don't get modified in the object itself */ public function testWillNotModifyRetrievedPublicProperties(): void { $proxy = (new LazyLoadingGhostFactory())->createProxy( ClassWithPublicProperties::class, $this->createInitializer(ClassWithPublicProperties::class, new ClassWithPublicProperties()) ); $variable = $proxy->property0; self::assertByRefVariableValueSame('property0', $variable); $variable = 'foo'; self::assertSame('property0', $proxy->property0); self::assertByRefVariableValueSame('foo', $variable); } /** * Verifies that public properties references retrieved via `__get` modify in the object state */ public function testWillModifyByRefRetrievedPublicProperties(): void { $instance = new ClassWithPublicProperties(); $proxy = (new LazyLoadingGhostFactory())->createProxy( ClassWithPublicProperties::class, $this->createInitializer(ClassWithPublicProperties::class, $instance) ); $variable = & $proxy->property0; self::assertByRefVariableValueSame('property0', $variable); $variable = 'foo'; self::assertSame('foo', $proxy->property0); self::assertByRefVariableValueSame('foo', $variable); } public function testKeepsInitializerWhenNotOverwitten(): void { $initializer = static function (): bool { return true; }; $proxy = (new LazyLoadingGhostFactory())->createProxy( BaseClass::class, $initializer ); $proxy->initializeProxy(); self::assertSame($initializer, $proxy->getProxyInitializer()); } /** * Verifies that public properties are not being initialized multiple times */ public function testKeepsInitializedPublicProperties(): void { $proxy = (new LazyLoadingGhostFactory())->createProxy( BaseClass::class, static function ( $proxy, string $method, array $parameters, ?Closure & $initializer ): bool { $initializer = null; $proxy->publicProperty = 'newValue'; return true; } ); $proxy->initializeProxy(); self::assertSame('newValue', $proxy->publicProperty); $proxy->publicProperty = 'otherValue'; $proxy->initializeProxy(); self::assertSame('otherValue', $proxy->publicProperty); } /** * Verifies that properties' default values are preserved */ public function testPublicPropertyDefaultWillBePreserved(): void { $proxy = (new LazyLoadingGhostFactory())->createProxy( ClassWithPublicProperties::class, static function (): bool { return true; } ); self::assertSame('property0', $proxy->property0); } /** * Verifies that protected properties' default values are preserved */ public function testProtectedPropertyDefaultWillBePreserved(): void { $proxy = (new LazyLoadingGhostFactory())->createProxy( ClassWithProtectedProperties::class, static function (): bool { return true; } ); // Check protected property via reflection $reflectionProperty = new ReflectionProperty(ClassWithProtectedProperties::class, 'property0'); $reflectionProperty->setAccessible(true); self::assertSame('property0', $reflectionProperty->getValue($proxy)); } /** * Verifies that private properties' default values are preserved */ public function testPrivatePropertyDefaultWillBePreserved(): void { $proxy = (new LazyLoadingGhostFactory())->createProxy( ClassWithPrivateProperties::class, static function (): bool { return true; } ); // Check protected property via reflection $reflectionProperty = new ReflectionProperty(ClassWithPrivateProperties::class, 'property0'); $reflectionProperty->setAccessible(true); self::assertSame('property0', $reflectionProperty->getValue($proxy)); } /** * @group 159 * @group 192 */ public function testMultiLevelPrivatePropertiesDefaultsWillBePreserved(): void { $proxy = (new LazyLoadingGhostFactory())->createProxy( ClassWithCollidingPrivateInheritedProperties::class, static function (): bool { return true; } ); $childProperty = new ReflectionProperty(ClassWithCollidingPrivateInheritedProperties::class, 'property0'); $parentProperty = new ReflectionProperty(get_parent_class(ClassWithCollidingPrivateInheritedProperties::class), 'property0'); $childProperty->setAccessible(true); $parentProperty->setAccessible(true); self::assertSame('childClassProperty0', $childProperty->getValue($proxy)); self::assertSame('property0', $parentProperty->getValue($proxy)); } /** * @group 159 * @group 192 */ public function testMultiLevelPrivatePropertiesByRefInitialization(): void { $proxy = (new LazyLoadingGhostFactory())->createProxy( ClassWithCollidingPrivateInheritedProperties::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer, array $properties ): bool { $initializer = null; $properties["\0" . ClassWithCollidingPrivateInheritedProperties::class . "\0property0"] = 'foo'; $properties["\0" . get_parent_class(ClassWithCollidingPrivateInheritedProperties::class) . "\0property0"] = 'bar'; return true; } ); $childProperty = new ReflectionProperty(ClassWithCollidingPrivateInheritedProperties::class, 'property0'); $parentProperty = new ReflectionProperty(get_parent_class(ClassWithCollidingPrivateInheritedProperties::class), 'property0'); $childProperty->setAccessible(true); $parentProperty->setAccessible(true); self::assertSame('foo', $childProperty->getValue($proxy)); self::assertSame('bar', $parentProperty->getValue($proxy)); } /** * @group 159 * @group 192 * * Test designed to verify that the cached logic does take into account the fact that * proxies are different instances */ public function testGetPropertyFromDifferentProxyInstances(): void { $factory = new LazyLoadingGhostFactory(); $proxy1 = $factory->createProxy( ClassWithCollidingPrivateInheritedProperties::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer, array $properties ): bool { $initializer = null; $properties["\0" . ClassWithCollidingPrivateInheritedProperties::class . "\0property0"] = 'foo'; $properties["\0" . get_parent_class(ClassWithCollidingPrivateInheritedProperties::class) . "\0property0"] = 'bar'; return true; } ); $proxy2 = $factory->createProxy( ClassWithCollidingPrivateInheritedProperties::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer, array $properties ): bool { $initializer = null; $properties["\0" . ClassWithCollidingPrivateInheritedProperties::class . "\0property0"] = 'baz'; $properties["\0" . get_parent_class(ClassWithCollidingPrivateInheritedProperties::class) . "\0property0"] = 'tab'; return true; } ); $childProperty = new ReflectionProperty(ClassWithCollidingPrivateInheritedProperties::class, 'property0'); $parentProperty = new ReflectionProperty(get_parent_class(ClassWithCollidingPrivateInheritedProperties::class), 'property0'); $childProperty->setAccessible(true); $parentProperty->setAccessible(true); self::assertSame('foo', $childProperty->getValue($proxy1)); self::assertSame('bar', $parentProperty->getValue($proxy1)); self::assertSame('baz', $childProperty->getValue($proxy2)); self::assertSame('tab', $parentProperty->getValue($proxy2)); } /** * @group 159 * @group 192 * * Test designed to verify that the cached logic does take into account the fact that * proxies are different instances */ public function testSetPrivatePropertyOnDifferentProxyInstances(): void { $factory = new LazyLoadingGhostFactory(); $proxy1 = $factory->createProxy( ClassWithMixedPropertiesAndAccessorMethods::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer ): bool { $initializer = null; return true; } ); $proxy2 = $factory->createProxy( ClassWithMixedPropertiesAndAccessorMethods::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer ): bool { $initializer = null; return true; } ); $proxy1->set('privateProperty', 'private1'); $proxy2->set('privateProperty', 'private2'); self::assertSame('private1', $proxy1->get('privateProperty')); self::assertSame('private2', $proxy2->get('privateProperty')); } /** * @group 159 * @group 192 * * Test designed to verify that the cached logic does take into account the fact that * proxies are different instances */ public function testIssetPrivatePropertyOnDifferentProxyInstances(): void { $factory = new LazyLoadingGhostFactory(); $proxy1 = $factory->createProxy( ClassWithMixedPropertiesAndAccessorMethods::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer ): bool { $initializer = null; return true; } ); $proxy2 = $factory->createProxy( ClassWithMixedPropertiesAndAccessorMethods::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer, array $properties ): bool { $initializer = null; $properties["\0" . ClassWithMixedPropertiesAndAccessorMethods::class . "\0privateProperty"] = null; return true; } ); self::assertTrue($proxy1->has('privateProperty')); self::assertFalse($proxy2->has('privateProperty')); self::assertTrue($proxy1->has('privateProperty')); self::assertFalse($proxy2->has('privateProperty')); } /** * @group 159 * @group 192 * * Test designed to verify that the cached logic does take into account the fact that * proxies are different instances */ public function testUnsetPrivatePropertyOnDifferentProxyInstances(): void { $factory = new LazyLoadingGhostFactory(); $proxy1 = $factory->createProxy( ClassWithMixedPropertiesAndAccessorMethods::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer ): bool { $initializer = null; return true; } ); $proxy2 = $factory->createProxy( ClassWithMixedPropertiesAndAccessorMethods::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer ): bool { $initializer = null; return true; } ); self::assertTrue($proxy1->has('privateProperty')); $proxy2->remove('privateProperty'); self::assertFalse($proxy2->has('privateProperty')); self::assertTrue($proxy1->has('privateProperty')); $proxy1->remove('privateProperty'); self::assertFalse($proxy1->has('privateProperty')); self::assertFalse($proxy2->has('privateProperty')); } /** * @group 159 * @group 192 * * Test designed to verify that the cached logic does take into account the fact that * proxies are different instances */ public function testIssetPrivateAndProtectedPropertiesDoesCheckAgainstBooleanFalse(): void { $factory = new LazyLoadingGhostFactory(); $proxy1 = $factory->createProxy( ClassWithMixedPropertiesAndAccessorMethods::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer, array $properties ): bool { $initializer = null; $properties['publicProperty'] = false; $properties["\0*\0protectedProperty"] = false; $properties["\0" . ClassWithMixedPropertiesAndAccessorMethods::class . "\0privateProperty"] = false; return true; } ); $proxy2 = $factory->createProxy( ClassWithMixedPropertiesAndAccessorMethods::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer, array $properties ): bool { $initializer = null; $properties['publicProperty'] = null; $properties["\0*\0protectedProperty"] = null; $properties["\0" . ClassWithMixedPropertiesAndAccessorMethods::class . "\0privateProperty"] = null; return true; } ); self::assertTrue($proxy1->has('protectedProperty')); self::assertTrue($proxy1->has('publicProperty')); self::assertTrue($proxy1->has('privateProperty')); self::assertFalse($proxy2->has('protectedProperty')); self::assertFalse($proxy2->has('publicProperty')); self::assertFalse($proxy2->has('privateProperty')); } public function testByRefInitialization(): void { $proxy = (new LazyLoadingGhostFactory())->createProxy( ClassWithMixedProperties::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer, array $properties ): bool { $initializer = null; $properties["\0" . ClassWithMixedProperties::class . "\0privateProperty0"] = 'private0'; $properties["\0" . ClassWithMixedProperties::class . "\0privateProperty1"] = 'private1'; $properties["\0" . ClassWithMixedProperties::class . "\0privateProperty2"] = 'private2'; $properties["\0*\0protectedProperty0"] = 'protected0'; $properties["\0*\0protectedProperty1"] = 'protected1'; $properties["\0*\0protectedProperty2"] = 'protected2'; $properties['publicProperty0'] = 'public0'; $properties['publicProperty1'] = 'public1'; $properties['publicProperty2'] = 'public2'; return true; } ); $reflectionClass = new ReflectionClass(ClassWithMixedProperties::class); foreach (Properties::fromReflectionClass($reflectionClass)->getInstanceProperties() as $property) { $property->setAccessible(true); self::assertSame(str_replace('Property', '', $property->getName()), $property->getValue($proxy)); } } /** * @requires PHP 7.4 */ public function testByRefInitializationOfTypedProperties(): void { $proxy = (new LazyLoadingGhostFactory())->createProxy( ClassWithMixedTypedProperties::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer, array $properties ): bool { $initializer = null; $properties["\0" . ClassWithMixedTypedProperties::class . "\0privateStringProperty"] = 'private0'; $properties["\0*\0protectedStringProperty"] = 'protected0'; $properties['publicStringProperty'] = 'public0'; return true; } ); $reflectionClass = new ReflectionClass(ClassWithMixedTypedProperties::class); $properties = Properties::fromReflectionClass($reflectionClass)->getInstanceProperties(); $privateProperty = $properties["\0" . ClassWithMixedTypedProperties::class . "\0privateStringProperty"]; $protectedProperty = $properties["\0*\0protectedStringProperty"]; $privateProperty->setAccessible(true); $protectedProperty->setAccessible(true); self::assertSame('private0', $privateProperty->getValue($proxy)); self::assertSame('protected0', $properties["\0*\0protectedStringProperty"]->getValue($proxy)); self::assertSame('public0', $proxy->publicStringProperty); } /** * @group 115 * @group 175 */ public function testWillBehaveLikeObjectWithNormalConstructor(): void { $instance = new ClassWithCounterConstructor(10); self::assertSame(10, $instance->amount, 'Verifying that test asset works as expected'); self::assertSame(10, $instance->getAmount(), 'Verifying that test asset works as expected'); $instance->__construct(3); self::assertSame(13, $instance->amount, 'Verifying that test asset works as expected'); self::assertSame(13, $instance->getAmount(), 'Verifying that test asset works as expected'); $proxyName = get_class( (new LazyLoadingGhostFactory()) ->createProxy( ClassWithCounterConstructor::class, static function (): bool { return true; } ) ); /** @psalm-suppress UnsafeInstantiation it is allowed (by design) to instantiate these proxies */ $proxy = new $proxyName(15); self::assertSame(15, $proxy->amount, 'Verifying that the proxy constructor works as expected'); self::assertSame(15, $proxy->getAmount(), 'Verifying that the proxy constructor works as expected'); $proxy->__construct(5); self::assertSame(20, $proxy->amount, 'Verifying that the proxy constructor works as expected'); self::assertSame(20, $proxy->getAmount(), 'Verifying that the proxy constructor works as expected'); } /** * @requires PHP 7.4 */ public function testInitializeProxyWillReturnTrueOnSuccessfulInitialization(): void { $proxy = (new LazyLoadingGhostFactory())->createProxy( ClassWithMixedTypedProperties::class, $this->createInitializer( ClassWithMixedTypedProperties::class, new ClassWithMixedTypedProperties() ) ); self::assertTrue($proxy->initializeProxy()); self::assertTrue($proxy->isProxyInitialized()); self::assertFalse($proxy->initializeProxy()); } /** * @psalm-param (CallableInterface&Mock)|null $initializerMatcher * @psalm-return Closure( * GhostObjectInterface, * string, * array, * ?Closure * ) : bool */ private function createInitializer(string $className, $realInstance, ?Mock $initializerMatcher = null): Closure { if (! $initializerMatcher) { $initializerMatcher = $this->createMock(CallableInterface::class); $initializerMatcher ->expects(self::once()) ->method('__invoke') ->with(self::logicalAnd( self::isInstanceOf(GhostObjectInterface::class), self::isInstanceOf($className) )); } return static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer ) use ( $initializerMatcher, $realInstance ): bool { $initializer = null; $reflectionClass = new ReflectionClass($realInstance); foreach (Properties::fromReflectionClass($reflectionClass)->getInstanceProperties() as $property) { if (! self::isPropertyInitialized($realInstance, $property)) { continue; } $property->setAccessible(true); $property->setValue($proxy, $property->getValue($realInstance)); } $initializerMatcher->__invoke($proxy, $method, $params); return true; }; } /** * Generates a list of object | invoked method | parameters | expected result * * @return null[][]|string[][]|object[][]|mixed[][][] */ public function getProxyMethods(): array { $selfHintParam = new ClassWithSelfHint(); $empty = new EmptyClass(); return [ [ BaseClass::class, new BaseClass(), 'publicMethod', [], 'publicMethodDefault', ], [ BaseClass::class, new BaseClass(), 'publicTypeHintedMethod', [new stdClass()], 'publicTypeHintedMethodDefault', ], [ BaseClass::class, new BaseClass(), 'publicByReferenceMethod', [], 'publicByReferenceMethodDefault', ], [ ClassWithSelfHint::class, new ClassWithSelfHint(), 'selfHintMethod', ['parameter' => $selfHintParam], $selfHintParam, ], [ ClassWithParentHint::class, new ClassWithParentHint(), 'parentHintMethod', ['parameter' => $empty], $empty, ], [ ClassWithAbstractPublicMethod::class, new EmptyClass(), // EmptyClass just used to not make reflection explode when synchronizing properties 'publicAbstractMethod', [], null, ], [ ClassWithMethodWithByRefVariadicFunction::class, new ClassWithMethodWithByRefVariadicFunction(), 'tuz', ['Ocramius', 'Malukenho'], ['Ocramius', 'changed'], ], ]; } /** * Generates a list of object | invoked method | parameters | expected result for methods that cause lazy-loading * of a ghost object * * @return string[][]|object[][]|mixed[][][]|null[][] */ public function getProxyInitializingMethods(): array { return [ [ BaseClass::class, new BaseClass(), 'publicPropertyGetter', [], 'publicPropertyDefault', ], [ BaseClass::class, new BaseClass(), 'protectedPropertyGetter', [], 'protectedPropertyDefault', ], [ BaseClass::class, new BaseClass(), 'privatePropertyGetter', [], 'privatePropertyDefault', ], [ ClassWithMethodWithVariadicFunction::class, new ClassWithMethodWithVariadicFunction(), 'foo', ['Ocramius', 'Malukenho'], null, ], ]; } /** * Generates a list of object | invoked method | parameters | expected result for methods DON'T cause lazy-loading * * @return null[][]|string[][]|object[][]|mixed[][][] */ public function getProxyNonInitializingMethods(): array { return $this->getProxyMethods(); } /** * Generates proxies and instances with a public property to feed to the property accessor methods * * @return string[][]|object[][] */ public function getPropertyAccessProxies(): array { $instance1 = new BaseClass(); $instance2 = new BaseClass(); $factory = new LazyLoadingGhostFactory(); $serialized = unserialize(serialize($factory->createProxy( BaseClass::class, $this->createInitializer(BaseClass::class, $instance2) ))); assert($serialized instanceof GhostObjectInterface); $tests = [ [ $instance1, $factory->createProxy( BaseClass::class, $this->createInitializer(BaseClass::class, $instance1) ), 'publicProperty', 'publicPropertyDefault', ], [ $instance2, $serialized, 'publicProperty', 'publicPropertyDefault', ], ]; if (\PHP_VERSION_ID < 70400) { return $tests; } $typedProperty = new ClassWithPublicStringTypedProperty(); $typedNullableProperty = new ClassWithPublicStringNullableTypedProperty(); $typedProperty->typedProperty = 'Typed property initialized value'; $typedNullableProperty->typedNullableProperty = 'Typed nullable property initialized value'; return array_merge($tests, [ [ $typedProperty, $factory->createProxy( ClassWithPublicStringTypedProperty::class, $this->createInitializer(ClassWithPublicStringTypedProperty::class, $typedProperty) ), 'typedProperty', 'Typed property initialized value', ], [ $typedNullableProperty, $factory->createProxy( ClassWithPublicStringNullableTypedProperty::class, $this->createInitializer(ClassWithPublicStringNullableTypedProperty::class, $typedNullableProperty) ), 'typedNullableProperty', 'Typed nullable property initialized value', ], ]); } /** * @param mixed $expected * @param mixed[] $proxyOptions * * @dataProvider skipPropertiesFixture * * @psalm-param class-string $className * @psalm-param array{skippedProperties?: array} $proxyOptions */ public function testInitializationIsSkippedForSkippedProperties( string $className, string $propertyClass, string $propertyName, array $proxyOptions, $expected ): void { $ghostObject = (new LazyLoadingGhostFactory())->createProxy( $className, static function () use ($propertyName): bool { self::fail(sprintf('The Property "%s" was not expected to be lazy-loaded', $propertyName)); return true; }, $proxyOptions ); $property = new ReflectionProperty($propertyClass, $propertyName); $property->setAccessible(true); self::assertSame($expected, $property->getValue($ghostObject)); } /** * @param array $proxyOptions * * @dataProvider skipPropertiesFixture * * @psalm-param class-string $className * @psalm-param array{skippedProperties?: array} $proxyOptions */ public function testSkippedPropertiesAreNotOverwrittenOnInitialization( string $className, string $propertyClass, string $propertyName, array $proxyOptions ): void { $ghostObject = (new LazyLoadingGhostFactory())->createProxy( $className, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer ): bool { $initializer = null; return true; }, $proxyOptions ); $property = new ReflectionProperty($propertyClass, $propertyName); $property->setAccessible(true); $value = uniqid('', true); $property->setValue($ghostObject, $value); self::assertTrue($ghostObject->initializeProxy()); self::assertSame( $value, $property->getValue($ghostObject), 'Property should not be changed by proxy initialization' ); } /** * @group 265 */ public function testWillForwardVariadicByRefArguments(): void { $object = (new LazyLoadingGhostFactory())->createProxy( ClassWithMethodWithByRefVariadicFunction::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer ): bool { $initializer = null; return true; } ); $parameters = ['a', 'b', 'c']; // first, testing normal variadic behavior (verifying we didn't screw up in the test asset) self::assertSame(['a', 'changed', 'c'], (new ClassWithMethodWithByRefVariadicFunction())->tuz(...$parameters)); self::assertSame(['a', 'changed', 'c'], $object->tuz(...$parameters)); self::assertSame(['a', 'changed', 'c'], $parameters, 'by-ref variadic parameter was changed'); } /** * @group 265 */ public function testWillForwardDynamicArguments(): void { $object = (new LazyLoadingGhostFactory())->createProxy( ClassWithDynamicArgumentsMethod::class, static function (): bool { return true; } ); // first, testing normal variadic behavior (verifying we didn't screw up in the test asset) self::assertSame(['a', 'b'], (new ClassWithDynamicArgumentsMethod())->dynamicArgumentsMethod('a', 'b')); self::assertSame(['a', 'b'], $object->dynamicArgumentsMethod('a', 'b')); } /** * @return mixed[] in order: * - the class to be proxied * - the class owning the property to be checked * - the property name * - the options to be passed to the generator * - the expected value of the property */ public function skipPropertiesFixture(): array { return [ [ ClassWithPublicProperties::class, ClassWithPublicProperties::class, 'property9', [ 'skippedProperties' => ['property9'], ], 'property9', ], [ ClassWithProtectedProperties::class, ClassWithProtectedProperties::class, 'property9', [ 'skippedProperties' => ["\0*\0property9"], ], 'property9', ], [ ClassWithPrivateProperties::class, ClassWithPrivateProperties::class, 'property9', [ 'skippedProperties' => ["\0ProxyManagerTestAsset\\ClassWithPrivateProperties\0property9"], ], 'property9', ], [ ClassWithCollidingPrivateInheritedProperties::class, ClassWithCollidingPrivateInheritedProperties::class, 'property0', [ 'skippedProperties' => ["\0ProxyManagerTestAsset\\ClassWithCollidingPrivateInheritedProperties\0property0"], ], 'childClassProperty0', ], [ ClassWithCollidingPrivateInheritedProperties::class, ClassWithPrivateProperties::class, 'property0', [ 'skippedProperties' => ["\0ProxyManagerTestAsset\\ClassWithPrivateProperties\0property0"], ], 'property0', ], ]; } /** * @group 276 * @dataProvider getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope */ public function testWillLazyLoadMembersOfOtherProxiesWithTheSamePrivateScope( $callerObject, string $method, string $propertyIndex, string $expectedValue ): void { $proxy = (new LazyLoadingGhostFactory())->createProxy( OtherObjectAccessClass::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer, array $properties ) use ( $propertyIndex, $expectedValue ): bool { $initializer = null; $properties[$propertyIndex] = $expectedValue; return true; } ); $accessor = [$callerObject, $method]; self::assertIsCallable($accessor); self::assertFalse($proxy->isProxyInitialized()); self::assertSame($expectedValue, $accessor($proxy)); self::assertTrue($proxy->isProxyInitialized()); } /** * @group 276 * @dataProvider getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope */ public function testWillAccessMembersOfOtherDeSerializedProxiesWithTheSamePrivateScope( $callerObject, string $method, string $propertyIndex, string $expectedValue ): void { $proxy = unserialize(serialize( (new LazyLoadingGhostFactory())->createProxy( OtherObjectAccessClass::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer, array $properties ) use ( $propertyIndex, $expectedValue ): bool { $initializer = null; assert($proxy instanceof OtherObjectAccessClass && $proxy instanceof LazyLoadingInterface); $properties[$propertyIndex] = $expectedValue; return true; } ) )); self::assertInstanceOf(GhostObjectInterface::class, $proxy); $accessor = [$callerObject, $method]; self::assertIsCallable($accessor); self::assertTrue($proxy->isProxyInitialized()); self::assertSame($expectedValue, $accessor($proxy)); } /** * @group 276 * @dataProvider getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope */ public function testWillAccessMembersOfOtherClonedProxiesWithTheSamePrivateScope( $callerObject, string $method, string $propertyIndex, string $expectedValue ): void { $proxy = clone (new LazyLoadingGhostFactory())->createProxy( OtherObjectAccessClass::class, static function ( GhostObjectInterface $proxy, string $method, array $params, ?Closure & $initializer, array $properties ) use ( $propertyIndex, $expectedValue ): bool { $initializer = null; $properties[$propertyIndex] = $expectedValue; return true; } ); $accessor = [$callerObject, $method]; self::assertIsCallable($accessor); self::assertTrue($proxy->isProxyInitialized()); self::assertSame($expectedValue, $accessor($proxy)); } /** @return string[][]|object[][] */ public function getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope(): array { $factory = new LazyLoadingGhostFactory(); return [ OtherObjectAccessClass::class . '#$privateProperty' => [ new OtherObjectAccessClass(), 'getPrivateProperty', "\0" . OtherObjectAccessClass::class . "\0privateProperty", uniqid('', true), ], OtherObjectAccessClass::class . '#$protectedProperty' => [ new OtherObjectAccessClass(), 'getProtectedProperty', "\0*\0protectedProperty", uniqid('', true), ], OtherObjectAccessClass::class . '#$publicProperty' => [ new OtherObjectAccessClass(), 'getPublicProperty', 'publicProperty', uniqid('', true), ], '(proxy) ' . OtherObjectAccessClass::class . '#$privateProperty' => [ $factory->createProxy( OtherObjectAccessClass::class, static function (): bool { self::fail('Should never be initialized, as its values aren\'t accessed'); return true; } ), 'getPrivateProperty', "\0" . OtherObjectAccessClass::class . "\0privateProperty", uniqid('', true), ], '(proxy) ' . OtherObjectAccessClass::class . '#$protectedProperty' => [ $factory->createProxy( OtherObjectAccessClass::class, static function (): bool { self::fail('Should never be initialized, as its values aren\'t accessed'); return true; } ), 'getProtectedProperty', "\0*\0protectedProperty", uniqid('', true), ], '(proxy) ' . OtherObjectAccessClass::class . '#$publicProperty' => [ $factory->createProxy( OtherObjectAccessClass::class, static function (): bool { self::fail('Should never be initialized, as its values aren\'t accessed'); return true; } ), 'getPublicProperty', 'publicProperty', uniqid('', true), ], ]; } /** * @group 276 */ public function testFriendObjectWillNotCauseLazyLoadingOnSkippedProperty(): void { $proxy = (new LazyLoadingGhostFactory()) ->createProxy( OtherObjectAccessClass::class, static function (): bool { throw new BadMethodCallException('The proxy should never be initialized, as all properties are skipped'); }, [ 'skippedProperties' => [ "\0" . OtherObjectAccessClass::class . "\0privateProperty", "\0*\0protectedProperty", 'publicProperty', ], ] ); $privatePropertyValue = uniqid('', true); $protectedPropertyValue = uniqid('', true); $publicPropertyValue = uniqid('', true); $reflectionPrivateProperty = new ReflectionProperty(OtherObjectAccessClass::class, 'privateProperty'); $reflectionPrivateProperty->setAccessible(true); $reflectionPrivateProperty->setValue($proxy, $privatePropertyValue); $reflectionProtectedProperty = new ReflectionProperty(OtherObjectAccessClass::class, 'protectedProperty'); $reflectionProtectedProperty->setAccessible(true); $reflectionProtectedProperty->setValue($proxy, $protectedPropertyValue); $proxy->publicProperty = $publicPropertyValue; $friendObject = new OtherObjectAccessClass(); self::assertSame($privatePropertyValue, $friendObject->getPrivateProperty($proxy)); self::assertSame($protectedPropertyValue, $friendObject->getProtectedProperty($proxy)); self::assertSame($publicPropertyValue, $friendObject->getPublicProperty($proxy)); } public function testClonedSkippedPropertiesArePreserved(): void { $proxy = (new LazyLoadingGhostFactory()) ->createProxy( BaseClass::class, static function (GhostObjectInterface $proxy): bool { $proxy->setProxyInitializer(null); return true; }, [ 'skippedProperties' => [ "\0" . BaseClass::class . "\0privateProperty", "\0*\0protectedProperty", 'publicProperty', ], ] ); $reflectionPrivate = new ReflectionProperty(BaseClass::class, 'privateProperty'); $reflectionProtected = new ReflectionProperty(BaseClass::class, 'protectedProperty'); $reflectionPrivate->setAccessible(true); $reflectionProtected->setAccessible(true); $privateValue = uniqid('', true); $protectedValue = uniqid('', true); $publicValue = uniqid('', true); $reflectionPrivate->setValue($proxy, $privateValue); $reflectionProtected->setValue($proxy, $protectedValue); $proxy->publicProperty = $publicValue; self::assertFalse($proxy->isProxyInitialized()); $clone = clone $proxy; self::assertFalse($proxy->isProxyInitialized()); self::assertTrue($clone->isProxyInitialized()); self::assertSame($privateValue, $reflectionPrivate->getValue($proxy)); self::assertSame($privateValue, $reflectionPrivate->getValue($clone)); self::assertSame($protectedValue, $reflectionProtected->getValue($proxy)); self::assertSame($protectedValue, $reflectionProtected->getValue($clone)); self::assertSame($publicValue, $proxy->publicProperty); self::assertSame($publicValue, $clone->publicProperty); } /** * @group 327 */ public function testWillExecuteLogicInAVoidMethod(): void { $initialCounter = random_int(10, 1000); $proxy = (new LazyLoadingGhostFactory())->createProxy( VoidCounter::class, static function ( LazyLoadingInterface $proxy, string $method, array $params, ?Closure & $initializer, array $properties ) use ($initialCounter): bool { $initializer = null; $properties['counter'] = $initialCounter; return true; } ); $increment = random_int(1001, 10000); $proxy->increment($increment); self::assertSame($initialCounter + $increment, $proxy->counter); } private static function isPropertyInitialized($object, ReflectionProperty $property): bool { return array_key_exists( ($property->isProtected() ? "\0*\0" : '') . ($property->isPrivate() ? "\0" . $property->getDeclaringClass()->getName() . "\0" : '') . $property->getName(), (array) $object ); } /** * @param mixed $expected * @param mixed $actual */ private static function assertByRefVariableValueSame($expected, & $actual): void { self::assertSame($expected, $actual); } } LazyLoadingValueHolderFunctionalTest.php000066400000000000000000000621741407505032400342260ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Functional $className * @psalm-param OriginalClass $instance */ public function testMethodCalls(string $className, $instance, string $method, array $params, $expectedValue): void { $proxy = (new LazyLoadingValueHolderFactory())->createProxy( $className, $this->createInitializer($className, $instance) ); self::assertFalse($proxy->isProxyInitialized()); $callProxyMethod = [$proxy, $method]; assert(is_callable($callProxyMethod)); $parameterValues = array_values($params); self::assertSame($expectedValue, $callProxyMethod(...$parameterValues)); self::assertTrue($proxy->isProxyInitialized()); self::assertSame($instance, $proxy->getWrappedValueHolderValue()); } /** * @param mixed[] $params * @param mixed $expectedValue * * @dataProvider getProxyMethods * * @psalm-template OriginalClass * @psalm-param class-string $className * @psalm-param OriginalClass $instance */ public function testMethodCallsAfterUnSerialization( string $className, $instance, string $method, array $params, $expectedValue ): void { $proxy = unserialize(serialize((new LazyLoadingValueHolderFactory())->createProxy( $className, $this->createInitializer($className, $instance) ))); assert($proxy instanceof VirtualProxyInterface); self::assertTrue($proxy->isProxyInitialized()); $callProxyMethod = [$proxy, $method]; $parameterValues = array_values($params); self::assertIsCallable($callProxyMethod); self::assertSame($expectedValue, $callProxyMethod(...$parameterValues)); self::assertEquals($instance, $proxy->getWrappedValueHolderValue()); } /** * @param mixed[] $params * @param mixed $expectedValue * * @dataProvider getProxyMethods * * @psalm-template OriginalClass * @psalm-param class-string $className * @psalm-param OriginalClass $instance */ public function testMethodCallsAfterCloning( string $className, $instance, string $method, array $params, $expectedValue ): void { $proxy = (new LazyLoadingValueHolderFactory())->createProxy( $className, $this->createInitializer($className, $instance) ); $cloned = clone $proxy; self::assertTrue($cloned->isProxyInitialized()); self::assertNotSame($proxy->getWrappedValueHolderValue(), $cloned->getWrappedValueHolderValue()); $callProxyMethod = [$cloned, $method]; $parameterValues = array_values($params); self::assertIsCallable($callProxyMethod); self::assertSame($expectedValue, $callProxyMethod(...$parameterValues)); self::assertEquals($instance, $cloned->getWrappedValueHolderValue()); } /** * @param mixed $propertyValue * * @dataProvider getPropertyAccessProxies */ public function testPropertyReadAccess( $instance, VirtualProxyInterface $proxy, string $publicProperty, $propertyValue ): void { self::assertSame($propertyValue, $proxy->$publicProperty); self::assertTrue($proxy->isProxyInitialized()); self::assertEquals($instance, $proxy->getWrappedValueHolderValue()); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyWriteAccess($instance, VirtualProxyInterface $proxy, string $publicProperty): void { $newValue = uniqid('', true); $proxy->$publicProperty = $newValue; self::assertTrue($proxy->isProxyInitialized()); self::assertSame($newValue, $proxy->$publicProperty); $wrappedValue = $proxy->getWrappedValueHolderValue(); self::assertNotNull($wrappedValue); self::assertSame($newValue, $wrappedValue->$publicProperty); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyExistence($instance, VirtualProxyInterface $proxy, string $publicProperty): void { self::assertSame(isset($instance->$publicProperty), isset($proxy->$publicProperty)); self::assertTrue($proxy->isProxyInitialized()); self::assertEquals($instance, $proxy->getWrappedValueHolderValue()); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyAbsence($instance, VirtualProxyInterface $proxy, string $publicProperty): void { $propertyType = \PHP_VERSION_ID >= 70400 ? (new ReflectionProperty($instance, $publicProperty))->getType() : null; if ($propertyType !== null && ! $propertyType->allowsNull()) { self::markTestSkipped('Non-nullable typed properties cannot be removed/unset'); } $instance = $proxy->getWrappedValueHolderValue() ?? $instance; $instance->$publicProperty = null; self::assertFalse(isset($proxy->$publicProperty)); self::assertTrue($proxy->isProxyInitialized()); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyUnset($instance, VirtualProxyInterface $proxy, string $publicProperty): void { $instance = $proxy->getWrappedValueHolderValue() ?? $instance; unset($proxy->$publicProperty); self::assertTrue($proxy->isProxyInitialized()); self::assertFalse(isset($instance->$publicProperty)); self::assertFalse(isset($proxy->$publicProperty)); } /** * Verifies that accessing a public property containing an array behaves like in a normal context */ public function testCanWriteToArrayKeysInPublicProperty(): void { $proxy = (new LazyLoadingValueHolderFactory())->createProxy( ClassWithPublicArrayProperty::class, $this->createInitializer(ClassWithPublicArrayProperty::class, new ClassWithPublicArrayProperty()) ); $proxy->arrayProperty['foo'] = 'bar'; self::assertByRefVariableValueSame('bar', $proxy->arrayProperty['foo']); $proxy->arrayProperty = ['tab' => 'taz']; self::assertSame(['tab' => 'taz'], $proxy->arrayProperty); } /** * Verifies that public properties retrieved via `__get` don't get modified in the object itself */ public function testWillNotModifyRetrievedPublicProperties(): void { $proxy = (new LazyLoadingValueHolderFactory())->createProxy( ClassWithPublicProperties::class, $this->createInitializer(ClassWithPublicProperties::class, new ClassWithPublicProperties()) ); $variable = $proxy->property0; self::assertByRefVariableValueSame('property0', $variable); $variable = 'foo'; self::assertSame('property0', $proxy->property0); self::assertByRefVariableValueSame('foo', $variable); } /** * Verifies that public properties references retrieved via `__get` modify in the object state */ public function testWillModifyByRefRetrievedPublicProperties(): void { $proxy = (new LazyLoadingValueHolderFactory())->createProxy( ClassWithPublicProperties::class, $this->createInitializer(ClassWithPublicProperties::class, new ClassWithPublicProperties()) ); $variable = & $proxy->property0; self::assertByRefVariableValueSame('property0', $variable); $variable = 'foo'; self::assertSame('foo', $proxy->property0); self::assertByRefVariableValueSame('foo', $variable); } /** * @group 16 * * Verifies that initialization of a value holder proxy may happen multiple times */ public function testWillAllowMultipleProxyInitialization(): void { $counter = 0; $proxy = (new LazyLoadingValueHolderFactory())->createProxy( BaseClass::class, static function (& $wrappedInstance) use (& $counter): bool { $wrappedInstance = new BaseClass(); /** @var int $counter */ $wrappedInstance->publicProperty = (string) ($counter += 1); return true; } ); self::assertSame('1', $proxy->publicProperty); self::assertSame('2', $proxy->publicProperty); self::assertSame('3', $proxy->publicProperty); } /** * @group 115 * @group 175 */ public function testWillBehaveLikeObjectWithNormalConstructor(): void { $instance = new ClassWithCounterConstructor(10); self::assertSame(10, $instance->amount, 'Verifying that test asset works as expected'); self::assertSame(10, $instance->getAmount(), 'Verifying that test asset works as expected'); $instance->__construct(3); self::assertSame(13, $instance->amount, 'Verifying that test asset works as expected'); self::assertSame(13, $instance->getAmount(), 'Verifying that test asset works as expected'); $proxyName = get_class( (new LazyLoadingValueHolderFactory()) ->createProxy( ClassWithCounterConstructor::class, static function (): bool { return true; } ) ); /** @psalm-suppress UnsafeInstantiation it is allowed (by design) to instantiate these proxies */ $proxy = new $proxyName(15); self::assertSame(15, $proxy->amount, 'Verifying that the proxy constructor works as expected'); self::assertSame(15, $proxy->getAmount(), 'Verifying that the proxy constructor works as expected'); $proxy->__construct(5); self::assertSame(20, $proxy->amount, 'Verifying that the proxy constructor works as expected'); self::assertSame(20, $proxy->getAmount(), 'Verifying that the proxy constructor works as expected'); } /** * @group 265 */ public function testWillForwardVariadicByRefArguments(): void { $object = (new LazyLoadingValueHolderFactory())->createProxy( ClassWithMethodWithByRefVariadicFunction::class, static function (& $wrappedInstance): bool { $wrappedInstance = new ClassWithMethodWithByRefVariadicFunction(); return true; } ); $parameters = ['a', 'b', 'c']; // first, testing normal variadic behavior (verifying we didn't screw up in the test asset) self::assertSame(['a', 'changed', 'c'], (new ClassWithMethodWithByRefVariadicFunction())->tuz(...$parameters)); self::assertSame(['a', 'changed', 'c'], $object->tuz(...$parameters)); self::assertSame(['a', 'changed', 'c'], $parameters, 'by-ref variadic parameter was changed'); } /** * This test documents a known limitation: `func_get_args()` (and similars) don't work in proxied APIs. * If you manage to make this test pass, then please do send a patch * * @group 265 */ public function testWillNotForwardDynamicArguments(): void { $object = (new LazyLoadingValueHolderFactory())->createProxy( ClassWithDynamicArgumentsMethod::class, static function (& $wrappedInstance): bool { $wrappedInstance = new ClassWithDynamicArgumentsMethod(); return true; } ); self::assertSame(['a', 'b'], (new ClassWithDynamicArgumentsMethod())->dynamicArgumentsMethod('a', 'b')); $this->expectException(ExpectationFailedException::class); self::assertSame(['a', 'b'], $object->dynamicArgumentsMethod('a', 'b')); } /** * @return Closure( * TClass|null, * VirtualProxyInterface, * string, * array, * ?Closure * ) : bool * * @template TClass * @psalm-param (CallableInterface&Mock)|null $initializerMatcher * @psalm-param class-string $className * @psalm-param TClass $realInstance */ private function createInitializer(string $className, $realInstance, ?Mock $initializerMatcher = null): Closure { if (! $initializerMatcher) { $initializerMatcher = $this->createMock(CallableInterface::class); $initializerMatcher ->expects(self::once()) ->method('__invoke') ->with( self::logicalAnd( self::isInstanceOf(VirtualProxyInterface::class), self::isInstanceOf($className) ), $realInstance ); } return /** * @psalm-param ?TClass $wrappedObject */ static function ( & $wrappedObject, VirtualProxyInterface $proxy, string $method, array $params, ?Closure & $initializer ) use ( $initializerMatcher, $realInstance ): bool { $initializer = null; $wrappedObject = $realInstance; $initializerMatcher->__invoke($proxy, $wrappedObject, $method, $params); return true; }; } /** * Generates a list of object, invoked method, parameters, expected result * * @return string[][]|object[][]|bool[][]|mixed[][][] */ public function getProxyMethods(): array { $selfHintParam = new ClassWithSelfHint(); $empty = new EmptyClass(); return [ [ BaseClass::class, new BaseClass(), 'publicMethod', [], 'publicMethodDefault', ], [ BaseClass::class, new BaseClass(), 'publicTypeHintedMethod', [new stdClass()], 'publicTypeHintedMethodDefault', ], [ BaseClass::class, new BaseClass(), 'publicByReferenceMethod', [], 'publicByReferenceMethodDefault', ], [ BaseInterface::class, new BaseClass(), 'publicMethod', [], 'publicMethodDefault', ], [ ClassWithSelfHint::class, new ClassWithSelfHint(), 'selfHintMethod', ['parameter' => $selfHintParam], $selfHintParam, ], [ ClassWithParentHint::class, new ClassWithParentHint(), 'parentHintMethod', ['parameter' => $empty], $empty, ], [ ClassWithMethodWithVariadicFunction::class, new ClassWithMethodWithVariadicFunction(), 'buz', ['Ocramius', 'Malukenho'], ['Ocramius', 'Malukenho'], ], [ ClassWithMethodWithByRefVariadicFunction::class, new ClassWithMethodWithByRefVariadicFunction(), 'tuz', ['Ocramius', 'Malukenho'], ['Ocramius', 'changed'], ], [ ClassWithMagicMethods::class, new ClassWithMagicMethods(), '__get', ['parameterName'], 'parameterName', ], [ ClassWithMagicMethods::class, new ClassWithMagicMethods(), '__set', ['foo', 'bar'], ['foo' => 'bar'], ], [ ClassWithMagicMethods::class, new ClassWithMagicMethods(), '__isset', ['example'], true, ], [ ClassWithMagicMethods::class, new ClassWithMagicMethods(), '__isset', [''], false, ], [ ClassWithMagicMethods::class, new ClassWithMagicMethods(), '__unset', ['example'], true, ], ]; } /** * Generates proxies and instances with a public property to feed to the property accessor methods * * @return array> */ public function getPropertyAccessProxies(): array { $instance1 = new BaseClass(); $instance2 = new BaseClass(); $factory = new LazyLoadingValueHolderFactory(); $serialized = unserialize(serialize($factory->createProxy( BaseClass::class, $this->createInitializer(BaseClass::class, $instance2) ))); assert($serialized instanceof VirtualProxyInterface); $tests = [ [ $instance1, $factory->createProxy( BaseClass::class, $this->createInitializer(BaseClass::class, $instance1) ), 'publicProperty', 'publicPropertyDefault', ], [ $instance2, $serialized, 'publicProperty', 'publicPropertyDefault', ], ]; if (\PHP_VERSION_ID < 70400) { return $tests; } $typedProperty = new ClassWithPublicStringTypedProperty(); $typedNullableProperty = new ClassWithPublicStringNullableTypedProperty(); $typedProperty->typedProperty = 'Typed property initialized value'; $typedNullableProperty->typedNullableProperty = 'Typed nullable property initialized value'; return array_merge($tests, [ [ $typedProperty, $factory->createProxy( ClassWithPublicStringTypedProperty::class, $this->createInitializer(ClassWithPublicStringTypedProperty::class, $typedProperty) ), 'typedProperty', 'Typed property initialized value', ], [ $typedNullableProperty, $factory->createProxy( ClassWithPublicStringNullableTypedProperty::class, $this->createInitializer(ClassWithPublicStringNullableTypedProperty::class, $typedNullableProperty) ), 'typedNullableProperty', 'Typed nullable property initialized value', ], ]); } /** * @group 276 * @dataProvider getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope */ public function testWillLazyLoadMembersOfOtherProxiesWithTheSamePrivateScope( $callerObject, $realInstance, string $method, string $expectedValue ): void { $className = get_class($realInstance); $proxy = (new LazyLoadingValueHolderFactory())->createProxy( $className, $this->createInitializer($className, $realInstance) ); $accessor = [$callerObject, $method]; self::assertIsCallable($accessor); self::assertFalse($proxy->isProxyInitialized()); self::assertSame($expectedValue, $accessor($proxy)); self::assertTrue($proxy->isProxyInitialized()); } /** * @group 276 * @dataProvider getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope */ public function testWillFetchMembersOfOtherDeSerializedProxiesWithTheSamePrivateScope( $callerObject, $realInstance, string $method, string $expectedValue ): void { $className = get_class($realInstance); $proxy = unserialize(serialize((new LazyLoadingValueHolderFactory())->createProxy( $className, $this->createInitializer($className, $realInstance) ))); assert($proxy instanceof LazyLoadingInterface); $accessor = [$callerObject, $method]; assert(is_callable($accessor)); self::assertTrue($proxy->isProxyInitialized()); self::assertSame($expectedValue, $accessor($proxy)); } /** * @group 276 * @dataProvider getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope */ public function testWillFetchMembersOfOtherClonedProxiesWithTheSamePrivateScope( $callerObject, $realInstance, string $method, string $expectedValue ): void { $className = get_class($realInstance); $proxy = clone (new LazyLoadingValueHolderFactory())->createProxy( $className, $this->createInitializer($className, $realInstance) ); $accessor = [$callerObject, $method]; assert(is_callable($accessor)); self::assertTrue($proxy->isProxyInitialized()); self::assertSame($expectedValue, $accessor($proxy)); } /** * @group 327 */ public function testWillExecuteLogicInAVoidMethod(): void { $proxy = (new LazyLoadingValueHolderFactory())->createProxy( VoidCounter::class, $this->createInitializer(VoidCounter::class, new VoidCounter()) ); $increment = random_int(100, 1000); $proxy->increment($increment); self::assertSame($increment, $proxy->counter); } public function getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope(): Generator { foreach ((new ReflectionClass(OtherObjectAccessClass::class))->getProperties() as $property) { $propertyName = $property->getName(); $expectedValue = uniqid('', true); // callee is an actual object yield OtherObjectAccessClass::class . '#$' . $propertyName => [ new OtherObjectAccessClass(), $this->buildInstanceWithValues(new OtherObjectAccessClass(), [$propertyName => $expectedValue]), 'get' . ucfirst($propertyName), $expectedValue, ]; $expectedValue = uniqid('', true); // callee is a proxy (not to be lazy-loaded!) yield '(proxy) ' . OtherObjectAccessClass::class . '#$' . $propertyName => [ (new LazyLoadingValueHolderFactory())->createProxy( OtherObjectAccessClass::class, $this->createInitializer( OtherObjectAccessClass::class, new OtherObjectAccessClass() ) ), $this->buildInstanceWithValues(new OtherObjectAccessClass(), [$propertyName => $expectedValue]), 'get' . ucfirst($propertyName), $expectedValue, ]; } } /** @param array $values */ private function buildInstanceWithValues($instance, array $values) { foreach ($values as $property => $value) { $property = new ReflectionProperty($instance, $property); $property->setAccessible(true); $property->setValue($instance, $value); } return $instance; } /** * @param mixed $expected * @param mixed $actual */ private static function assertByRefVariableValueSame($expected, & $actual): void { self::assertSame($expected, $actual); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Functional/MultipleProxyGenerationTest.php000066400000000000000000000130331407505032400325510ustar00rootroot00000000000000createProxy($className, $initializer), $virtualProxyFactory->createProxy($className, $initializer), $accessInterceptorFactory->createProxy($object), ]; if ($className !== ClassWithMixedTypedProperties::class) { $generated[] = $accessInterceptorScopeLocalizerFactory->createProxy($object); } foreach ($generated as $key => $proxy) { self::assertInstanceOf($className, $proxy); foreach ($generated as $comparedKey => $comparedProxy) { if ($comparedKey === $key) { continue; } self::assertNotSame(get_class($comparedProxy), get_class($proxy)); } $proxyClass = get_class($proxy); /** * @psalm-suppress InvalidStringClass * @psalm-suppress MixedMethodCall */ self::assertInstanceOf($proxyClass, new $proxyClass(), 'Proxy can be instantiated via normal constructor'); } } /** * @return object[][] */ public function getTestedClasses(): array { $objects = [ [new BaseClass()], [new ClassWithMagicMethods()], [new ClassWithFinalMethods()], [new ClassWithFinalMagicMethods()], [new ClassWithByRefMagicMethods()], [new ClassWithMixedProperties()], [\PHP_VERSION_ID >= 70400 ? new ClassWithMixedTypedProperties() : null], [\PHP_VERSION_ID >= 70400 ? new ClassWithMixedReferenceableTypedProperties() : null], // [new ClassWithPublicStringTypedProperty()], // [new ClassWithPublicStringNullableTypedProperty()], [new ClassWithPrivateProperties()], [new ClassWithProtectedProperties()], [new ClassWithPublicProperties()], [new EmptyClass()], [new HydratedObject()], [new ClassWithSelfHint()], [new ClassWithParentHint()], [new ClassWithCollidingPrivateInheritedProperties()], [new ClassWithMethodWithVariadicFunction()], [new ClassWithMethodWithByRefVariadicFunction()], [new ScalarTypeHintedClass()], [new IterableTypeHintClass()], [new ObjectTypeHintClass()], [new ReturnTypeHintedClass()], [new VoidMethodTypeHintedClass()], ]; if (PHP_VERSION_ID >= 80000) { $objects[] = [new ClassWithPhp80TypedMethods()]; } return $objects; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Functional/NullObjectFunctionalTest.php000066400000000000000000000200551407505032400317660ustar00rootroot00000000000000createProxy($className); $this->assertNullMethodCall($proxy, $method, $params); } /** * @param mixed[] $params * * @dataProvider getProxyMethods * * @psalm-param class-string $className */ public function testMethodCallsAfterUnSerialization(string $className, string $method, array $params): void { $proxy = unserialize(serialize((new NullObjectFactory())->createProxy($className))); assert($proxy instanceof NullObjectInterface); $this->assertNullMethodCall($proxy, $method, $params); } /** * @param mixed[] $params * * @dataProvider getProxyMethods * * @psalm-param class-string $className */ public function testMethodCallsAfterCloning(string $className, string $method, array $params): void { $proxy = (new NullObjectFactory())->createProxy($className); $this->assertNullMethodCall(clone $proxy, $method, $params); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyReadAccess(NullObjectInterface $proxy, string $publicProperty): void { if (! $this->propertyHasDefaultNullableValue(new ReflectionProperty($proxy, $publicProperty))) { // Accessing a typed property without default value before initialization $this->expectException(Error::class); $this->expectExceptionMessageMatches('/must not be accessed before initialization/'); } self::assertNull($proxy->$publicProperty); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyWriteAccess(NullObjectInterface $proxy, string $publicProperty): void { $newValue = uniqid('', true); $proxy->$publicProperty = $newValue; self::assertSame($newValue, $proxy->$publicProperty); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyExistence(NullObjectInterface $proxy, string $publicProperty): void { if (! $this->propertyHasDefaultNullableValue(new ReflectionProperty($proxy, $publicProperty))) { // Accessing a typed property without default value before initialization $this->expectException(Error::class); $this->expectExceptionMessageMatches('/must not be accessed before initialization/'); } self::assertNull($proxy->$publicProperty); } /** * @dataProvider getPropertyAccessProxies */ public function testPropertyUnset(NullObjectInterface $proxy, string $publicProperty): void { unset($proxy->$publicProperty); self::assertFalse(isset($proxy->$publicProperty)); } /** * Generates a list of object | invoked method | parameters | expected result * * @return string[][]|null[][]|mixed[][][]|object[][] */ public function getProxyMethods(): array { $selfHintParam = new ClassWithSelfHint(); $empty = new EmptyClass(); return [ [ BaseClass::class, 'publicMethod', [], 'publicMethodDefault', ], [ BaseClass::class, 'publicTypeHintedMethod', ['param' => new stdClass()], 'publicTypeHintedMethodDefault', ], [ BaseClass::class, 'publicByReferenceMethod', [], 'publicByReferenceMethodDefault', ], [ BaseInterface::class, 'publicMethod', [], 'publicMethodDefault', ], [ ClassWithSelfHint::class, 'selfHintMethod', ['parameter' => $selfHintParam], $selfHintParam, ], [ ClassWithParentHint::class, 'parentHintMethod', ['parameter' => $empty], $empty, ], [ ClassWithMethodWithVariadicFunction::class, 'buz', ['Ocramius', 'Malukenho'], null, ], [ ClassWithMethodWithByRefVariadicFunction::class, 'tuz', ['Ocramius', 'Malukenho'], null, ], [ VoidCounter::class, 'increment', [random_int(10, 1000)], null, ], ]; } /** * Generates proxies and instances with a public property to feed to the property accessor methods * * @return array> */ public function getPropertyAccessProxies(): array { $factory = new NullObjectFactory(); $serialized = unserialize(serialize($factory->createProxy(BaseClass::class))); assert($serialized instanceof NullObjectInterface); $tests = [ [ $factory->createProxy(BaseClass::class), 'publicProperty', 'publicPropertyDefault', ], [ $serialized, 'publicProperty', 'publicPropertyDefault', ], ]; if (\PHP_VERSION_ID < 70400) { return $tests; } return array_merge($tests, [ [ $factory->createProxy(ClassWithPublicStringTypedProperty::class), 'typedProperty', 'Typed property initialized value', ], [ $factory->createProxy(ClassWithPublicStringNullableTypedProperty::class), 'typedNullableProperty', 'Typed nullable property initialized value', ], [ $factory->createProxy(ClassWithPublicStringNullableNullDefaultTypedProperty::class), 'typedNullableNullDefaultProperty', null, ], ]); } /** * @param mixed[] $parameters */ private function assertNullMethodCall(NullObjectInterface $proxy, string $methodName, array $parameters): void { $method = [$proxy, $methodName]; self::assertIsCallable($method); $parameterValues = array_values($parameters); self::assertNull($method(...$parameterValues)); } private function propertyHasDefaultNullableValue(ReflectionProperty $property): bool { $type = \PHP_VERSION_ID >= 70400 ? $property->getType() : null; return $type === null || $type->allowsNull(); } } PublicScopeSimulatorFunctionalTest.php000066400000000000000000000033021407505032400337520ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/FunctionaldoGet('publicProperty0')); self::assertSame('bar', $sut->doSet('publicProperty0', 'bar')); self::assertTrue($sut->doIsset('publicProperty0')); self::assertNull($sut->doUnset('publicProperty0')); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Functional/RemoteObjectFunctionalTest.php000066400000000000000000000324701407505032400323130ustar00rootroot00000000000000getMockBuilder(Client::class)->getMock(); $client ->method('call') ->with(self::stringEndsWith($method), $parametersExpectedByClient) ->willReturn($expectedValue); return new XmlRpcAdapter( $client, ['ProxyManagerTestAsset\RemoteProxy\Foo.foo' => 'ProxyManagerTestAsset\RemoteProxy\FooServiceInterface.foo'] ); } /** * @param mixed $expectedValue * @param mixed[] $params */ protected function getJsonRpcAdapter($expectedValue, string $method, array $params): JsonRpcAdapter { $client = $this->getMockBuilder(Client::class)->getMock(); $client ->method('call') ->with(self::stringEndsWith($method), $params) ->willReturn($expectedValue); return new JsonRpcAdapter( $client, ['ProxyManagerTestAsset\RemoteProxy\Foo.foo' => 'ProxyManagerTestAsset\RemoteProxy\FooServiceInterface.foo'] ); } /** * @param string|object $instanceOrClassName * @param array|mixed[] $passedParams * @param mixed[] $callParametersExpectedByAdapter * @param mixed $expectedValue * * @dataProvider getProxyMethods * * @psalm-template OriginalClass of object * @psalm-param class-string|OriginalClass $instanceOrClassName */ public function testXmlRpcMethodCalls( $instanceOrClassName, string $method, array $passedParams, array $callParametersExpectedByAdapter, $expectedValue ): void { $proxy = (new RemoteObjectFactory($this->getXmlRpcAdapter($expectedValue, $method, $callParametersExpectedByAdapter))) ->createProxy($instanceOrClassName); $callback = [$proxy, $method]; self::assertIsCallable($callback); self::assertSame($expectedValue, $callback(...$passedParams)); } /** * @param string|object $instanceOrClassName * @param array|mixed[] $passedParams * @param mixed[] $parametersForProxy * @param mixed $expectedValue * * @dataProvider getProxyMethods * * @psalm-template OriginalClass of object * @psalm-param class-string|OriginalClass $instanceOrClassName */ public function testJsonRpcMethodCalls( $instanceOrClassName, string $method, array $passedParams, array $parametersForProxy, $expectedValue ): void { $proxy = (new RemoteObjectFactory($this->getJsonRpcAdapter($expectedValue, $method, $parametersForProxy))) ->createProxy($instanceOrClassName); $callback = [$proxy, $method]; self::assertIsCallable($callback); self::assertSame($expectedValue, $callback(...$passedParams)); } /** * @param string|object $instanceOrClassName * @param mixed $propertyValue * * @dataProvider getPropertyAccessProxies * * @psalm-template OriginalClass of object * @psalm-param class-string|OriginalClass $instanceOrClassName */ public function testJsonRpcPropertyReadAccess($instanceOrClassName, string $publicProperty, $propertyValue): void { if (false !== strpos($instanceOrClassName, 'TypedProp') && \PHP_VERSION_ID < 70400) { self::markTestSkipped('PHP 7.4 required.'); } $proxy = (new RemoteObjectFactory($this->getJsonRpcAdapter($propertyValue, '__get', [$publicProperty]))) ->createProxy($instanceOrClassName); self::assertSame($propertyValue, $proxy->$publicProperty); } /** * Generates a list of object | invoked method | parameters | expected result * * @return string[][]|bool[][]|object[][]|mixed[][][] */ public function getProxyMethods(): array { $selfHintParam = new ClassWithSelfHint(); return [ [ FooServiceInterface::class, 'foo', [], [], 'bar remote', ], [ Foo::class, 'foo', [], [], 'bar remote', ], [ new Foo(), 'foo', [], [], 'bar remote', ], [ BazServiceInterface::class, 'baz', ['baz'], ['baz'], 'baz remote', ], [ new ClassWithSelfHint(), 'selfHintMethod', [$selfHintParam], [$selfHintParam], $selfHintParam, ], [ VariadicArgumentsServiceInterface::class, 'method', ['aaa', 1, 2, 3, 4, 5], ['aaa', 1, 2, 3, 4, 5], true, ], [ RemoteServiceWithDefaultsInterface::class, 'optionalNonNullable', ['aaa'], ['aaa', 'Optional parameter to be kept during calls'], 200, ], [ RemoteServiceWithDefaultsInterface::class, 'optionalNullable', ['aaa'], ['aaa', null], 200, ], 'when passing only the required parameters' => [ RemoteServiceWithDefaultsInterface::class, 'manyRequiredWithManyOptional', ['aaa', 100], [ 'aaa', 100, 'Optional parameter to be kept during calls', 100, 'Yet another optional parameter to be kept during calls', ], 200, ], 'when passing required params and one optional params' => [ RemoteServiceWithDefaultsInterface::class, 'manyRequiredWithManyOptional', ['aaa', 100, 'passed'], [ 'aaa', 100, 'passed', 100, 'Yet another optional parameter to be kept during calls', ], 200, ], 'when passing required params and some optional params' => [ RemoteServiceWithDefaultsInterface::class, 'manyRequiredWithManyOptional', ['aaa', 100, 'passed', 90], [ 'aaa', 100, 'passed', 90, 'Yet another optional parameter to be kept during calls', ], 200, ], 'when passing only required for method with optional and variadic params' => [ RemoteServiceWithDefaultsAndVariadicArguments::class, 'optionalWithVariadic', ['aaa'], [ 'aaa', 'Optional param to be kept on proxy call', ], 200, ], 'when passing required, optional and variadic params' => [ RemoteServiceWithDefaultsAndVariadicArguments::class, 'optionalWithVariadic', ['aaa', 'Optional param to be kept on proxy call', 10, 20, 30, 50, 90], [ 'aaa', 'Optional param to be kept on proxy call', 10, 20, 30, 50, 90, ], 200, ], ]; } /** * Generates proxies and instances with a public property to feed to the property accessor methods * * @return string[][] */ public function getPropertyAccessProxies(): array { return [ [ FooServiceInterface::class, 'publicProperty', 'publicProperty remote', ], [ ClassWithPublicStringTypedProperty::class, 'typedProperty', 'typedProperty remote', ], [ ClassWithPublicStringNullableTypedProperty::class, 'typedNullableProperty', 'typedNullableProperty remote', ], [ ClassWithPublicStringNullableNullDefaultTypedProperty::class, 'typedNullableNullDefaultProperty', 'typedNullableNullDefaultProperty remote', ], ]; } /** * @group 276 * @dataProvider getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope */ public function testWillInterceptAccessToPropertiesViaFriendClassAccess( $callerObject, $realInstance, string $method, string $expectedValue, string $propertyName ): void { $adapter = $this->createMock(AdapterInterface::class); $adapter ->expects(self::once()) ->method('call') ->with(get_class($realInstance), '__get', [$propertyName]) ->willReturn($expectedValue); $proxy = (new RemoteObjectFactory($adapter)) ->createProxy($realInstance); $accessor = [$callerObject, $method]; assert(is_callable($accessor)); self::assertSame($expectedValue, $accessor($proxy)); } /** * @group 276 * @dataProvider getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope */ public function testWillInterceptAccessToPropertiesViaFriendClassAccessEvenIfCloned( $callerObject, $realInstance, string $method, string $expectedValue, string $propertyName ): void { $adapter = $this->createMock(AdapterInterface::class); $adapter ->expects(self::once()) ->method('call') ->with(get_class($realInstance), '__get', [$propertyName]) ->willReturn($expectedValue); $proxy = clone (new RemoteObjectFactory($adapter)) ->createProxy($realInstance); $accessor = [$callerObject, $method]; assert(is_callable($accessor)); self::assertSame($expectedValue, $accessor($proxy)); } /** * @group 327 */ public function testWillExecuteLogicInAVoidMethod(): void { $adapter = $this->createMock(AdapterInterface::class); $increment = random_int(10, 1000); $adapter ->expects(self::once()) ->method('call') ->with(VoidCounter::class, 'increment', [$increment]) ->willReturn(random_int(10, 1000)); $proxy = clone (new RemoteObjectFactory($adapter)) ->createProxy(VoidCounter::class); $proxy->increment($increment); } public function getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope(): Generator { foreach ((new ReflectionClass(OtherObjectAccessClass::class))->getProperties() as $property) { $property->setAccessible(true); $propertyName = $property->getName(); $realInstance = new OtherObjectAccessClass(); $expectedValue = uniqid('', true); $property->setValue($realInstance, $expectedValue); yield OtherObjectAccessClass::class . '#$' . $propertyName => [ new OtherObjectAccessClass(), $realInstance, 'get' . ucfirst($propertyName), $expectedValue, $propertyName, ]; } } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Generator/000077500000000000000000000000001407505032400241535ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Generator/MagicMethodGeneratorTest.php000066400000000000000000000035201407505032400315540ustar00rootroot00000000000000generate()); } public function testGeneratesCorrectByValReturnValue(): void { $reflection = new ReflectionClass(ClassWithMagicMethods::class); $magicMethod = new MagicMethodGenerator($reflection, '__get', ['name']); self::assertStringMatchesFormat('%Apublic function __get(%A', $magicMethod->generate()); } public function testGeneratesByRefReturnValueWithNonExistingGetMethod(): void { $reflection = new ReflectionClass(EmptyClass::class); $magicMethod = new MagicMethodGenerator($reflection, '__get', ['name']); self::assertStringMatchesFormat('%Apublic function & __get(%A', $magicMethod->generate()); } public function testGeneratesByValReturnValueWithNonExistingNonGetMethod(): void { $reflection = new ReflectionClass(EmptyClass::class); $magicMethod = new MagicMethodGenerator($reflection, '__set', ['name']); self::assertStringMatchesFormat('%Apublic function __set(%A', $magicMethod->generate()); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Generator/MethodGeneratorTest.php000066400000000000000000000136051407505032400306200ustar00rootroot00000000000000isInterface()); } public function testGenerateSimpleMethod(): void { $methodGenerator = new MethodGenerator(); $methodGenerator->setReturnsReference(true); $methodGenerator->setName('methodName'); $methodGenerator->setVisibility('protected'); $methodGenerator->setBody('/* body */'); $methodGenerator->setDocBlock('docBlock'); $methodGenerator->setParameter(new ParameterGenerator('foo')); self::assertStringMatchesFormat( '%a/**%adocBlock%a*/%aprotected function & methodName($foo)%a{%a/* body */%a}', $methodGenerator->generate() ); } /** * Verify that building from reflection works */ public function testGenerateFromReflection(): void { $method = MethodGenerator::fromReflectionWithoutBodyAndDocBlock(new MethodReflection( self::class, __FUNCTION__ )); self::assertSame(__FUNCTION__, $method->getName()); self::assertSame(MethodGenerator::VISIBILITY_PUBLIC, $method->getVisibility()); self::assertFalse($method->isStatic()); self::assertNull($method->getDocBlock(), 'The docblock is ignored'); self::assertSame('', $method->getBody(), 'The body is ignored'); self::assertNull($method->getSourceContent(), 'The source content ignored'); self::assertTrue($method->isSourceDirty(), 'Dirty because the source cannot just be re-used when generating'); $method = MethodGenerator::fromReflectionWithoutBodyAndDocBlock(new MethodReflection( BaseClass::class, 'protectedMethod' )); self::assertSame(MethodGenerator::VISIBILITY_PROTECTED, $method->getVisibility()); $method = MethodGenerator::fromReflectionWithoutBodyAndDocBlock(new MethodReflection( BaseClass::class, 'privateMethod' )); self::assertSame(MethodGenerator::VISIBILITY_PRIVATE, $method->getVisibility()); } public function testGeneratedParametersFromReflection(): void { $method = MethodGenerator::fromReflectionWithoutBodyAndDocBlock(new MethodReflection( BaseClass::class, 'publicTypeHintedMethod' )); self::assertSame('publicTypeHintedMethod', $method->getName()); $parameters = $method->getParameters(); self::assertCount(1, $parameters); $param = $parameters['param']; self::assertSame(stdClass::class, $param->getType()); } /** * @dataProvider scalarTypeHintedMethods */ public function testGenerateMethodWithScalarTypeHinting(string $methodName, string $type): void { $method = MethodGenerator::fromReflectionWithoutBodyAndDocBlock(new MethodReflection( ScalarTypeHintedClass::class, $methodName )); self::assertSame($methodName, $method->getName()); $parameters = $method->getParameters(); self::assertCount(1, $parameters); $param = $parameters['param']; self::assertSame($type, $param->getType()); } /** @return string[][] */ public function scalarTypeHintedMethods(): array { return [ ['acceptString', 'string'], ['acceptInteger', 'int'], ['acceptBoolean', 'bool'], ['acceptFloat', 'float'], ]; } public function testGenerateMethodWithVoidReturnTypeHinting(): void { $method = MethodGenerator::fromReflectionWithoutBodyAndDocBlock(new MethodReflection( VoidMethodTypeHintedInterface::class, 'returnVoid' )); self::assertSame('returnVoid', $method->getName()); self::assertStringMatchesFormat('%a : void%a', $method->generate()); } /** * @dataProvider returnTypeHintsProvider */ public function testReturnTypeHintGeneration(string $methodName, string $expectedType): void { $method = MethodGenerator::fromReflectionWithoutBodyAndDocBlock(new MethodReflection( ReturnTypeHintedClass::class, $methodName )); self::assertSame($methodName, $method->getName()); self::assertStringMatchesFormat('%a : ' . $expectedType . '%a', $method->generate()); } /** * @return string[][] */ public static function returnTypeHintsProvider(): array { return [ ['returnString', 'string'], ['returnInteger', 'int'], ['returnBool', 'bool'], ['returnArray', 'array'], ['returnCallable', 'callable'], ['returnSelf', '\\' . ReturnTypeHintedClass::class], ['returnParent', '\\' . EmptyClass::class], ['returnVoid', 'void'], ['returnIterable', 'iterable'], ['returnSameClass', '\\' . ReturnTypeHintedClass::class], ['returnOtherClass', '\\' . EmptyClass::class], ]; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Generator/Util/000077500000000000000000000000001407505032400250705ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Generator/Util/ClassGeneratorUtilsTest.php000066400000000000000000000035241407505032400324020ustar00rootroot00000000000000createMock(ClassGenerator::class); $methodGenerator = $this->createMock(MethodGenerator::class); $methodGenerator ->expects(self::once()) ->method('getName') ->willReturn('foo'); $classGenerator ->expects(self::never()) ->method('addMethodFromGenerator'); $reflection = new ReflectionClass(ClassWithFinalMethods::class); self::assertFalse(ClassGeneratorUtils::addMethodIfNotFinal($reflection, $classGenerator, $methodGenerator)); } public function testCanAddANotFinalMethod(): void { $classGenerator = $this->createMock(ClassGenerator::class); $methodGenerator = $this->createMock(MethodGenerator::class); $methodGenerator ->expects(self::once()) ->method('getName') ->willReturn('publicMethod'); $classGenerator ->expects(self::once()) ->method('addMethodFromGenerator'); $reflection = new ReflectionClass(BaseClass::class); self::assertTrue(ClassGeneratorUtils::addMethodIfNotFinal($reflection, $classGenerator, $methodGenerator)); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Generator/Util/IdentifierSuffixerTest.php000066400000000000000000000046051407505032400322440ustar00rootroot00000000000000 */ public function returnExpressionsProvider(): array { return [ 'variable, no original method' => [ '$foo', null, 'return $foo;', ], 'variable, given non-void original method' => [ '$foo', new ReflectionMethod(self::class, 'returnExpressionsProvider'), 'return $foo;', ], 'variable, given void original method' => [ '$foo', new ReflectionMethod(VoidMethodTypeHintedClass::class, 'returnVoid'), "\$foo;\nreturn;", ], 'expression, no original method' => [ '(1 + 1)', null, 'return (1 + 1);', ], 'expression, given non-void original method' => [ '(1 + 1)', new ReflectionMethod(self::class, 'returnExpressionsProvider'), 'return (1 + 1);', ], 'expression, given void original method' => [ '(1 + 1)', new ReflectionMethod(VoidMethodTypeHintedClass::class, 'returnVoid'), "(1 + 1);\nreturn;", ], ]; } } UniqueIdentifierGeneratorTest.php000066400000000000000000000031551407505032400335060ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Generator/Utilgenerate($classGenerator); self::assertGreaterThan(0, strpos($generated, $className)); } } EvaluatingGeneratorStrategyTest.php000066400000000000000000000036561407505032400346730ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/GeneratorStrategygenerate($classGenerator); self::assertGreaterThan(0, strpos($generated, $className)); self::assertTrue(class_exists($className, false)); } /** * @covers \ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy::generate * @covers \ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy::__construct */ public function testGenerateWithDisabledEval(): void { if (! ini_get('suhosin.executor.disable_eval')) { self::markTestSkipped('Ini setting "suhosin.executor.disable_eval" is needed to run this test'); } $strategy = new EvaluatingGeneratorStrategy(); $className = 'Foo' . uniqid(); $classGenerator = new ClassGenerator($className); $generated = $strategy->generate($classGenerator); self::assertGreaterThan(0, strpos($generated, $className)); self::assertTrue(class_exists($className, false)); } } FileWriterGeneratorStrategyTest.php000066400000000000000000000136271407505032400346470ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/GeneratorStrategytempDir = tempnam(sys_get_temp_dir(), 'FileWriterGeneratorStrategyTest'); $this->originalErrorHandler = static function (): bool { throw new ErrorException(); }; unlink($this->tempDir); mkdir($this->tempDir); set_error_handler($this->originalErrorHandler); } protected function tearDown(): void { self::assertSame($this->originalErrorHandler, set_error_handler(static function (): bool { return true; })); restore_error_handler(); restore_error_handler(); parent::tearDown(); } public function testGenerate(): void { $locator = $this->createMock(FileLocatorInterface::class); $generator = new FileWriterGeneratorStrategy($locator); $tmpFile = $this->tempDir . '/' . uniqid('FileWriterGeneratorStrategyTest', true) . '.php'; $namespace = 'Foo'; $className = UniqueIdentifierGenerator::getIdentifier('Bar'); $fqcn = $namespace . '\\' . $className; $locator ->method('getProxyFileName') ->with($fqcn) ->will(self::returnValue($tmpFile)); $body = $generator->generate(new ClassGenerator($fqcn)); self::assertGreaterThan(0, strpos($body, $className)); self::assertFalse(class_exists($fqcn, false)); self::assertFileExists($tmpFile); self::assertFileIsReadable($tmpFile); // a user note on php.net recommended calling this as we have just called chmod on a file. clearstatcache(); // Calculate the permission that should have been set. // The operators below are bit-wise "AND" (&) and "NOT" (~), read more at: http://php.net/manual/en/language.operators.bitwise.php $perm = 0666 & ~umask(); self::assertSame($perm, fileperms($tmpFile) & 0777, 'File permission was not correct: ' . decoct($perm)); /* @noinspection PhpIncludeInspection */ require $tmpFile; self::assertTrue(class_exists($fqcn, false)); } public function testGenerateWillFailIfTmpFileCannotBeWrittenToDisk(): void { $tmpDirPath = $this->tempDir . '/' . uniqid('nonWritable', true); mkdir($tmpDirPath, 0555, true); $locator = $this->createMock(FileLocatorInterface::class); $generator = new FileWriterGeneratorStrategy($locator); $tmpFile = $tmpDirPath . '/' . uniqid('FileWriterGeneratorStrategyFailedFileWriteTest', true) . '.php'; $namespace = 'Foo'; $className = UniqueIdentifierGenerator::getIdentifier('Bar'); $fqcn = $namespace . '\\' . $className; $locator ->method('getProxyFileName') ->with($fqcn) ->willReturn($tmpFile); $this->expectException(FileNotWritableException::class); $generator->generate(new ClassGenerator($fqcn)); } public function testGenerateWillFailIfTmpFileCannotBeMovedToFinalDestination(): void { $locator = $this->createMock(FileLocatorInterface::class); $generator = new FileWriterGeneratorStrategy($locator); $tmpFile = $this->tempDir . '/' . uniqid('FileWriterGeneratorStrategyFailedFileMoveTest', true) . '.php'; $namespace = 'Foo'; $className = UniqueIdentifierGenerator::getIdentifier('Bar'); $fqcn = $namespace . '\\' . $className; $locator ->method('getProxyFileName') ->with($fqcn) ->willReturn($tmpFile); mkdir($tmpFile); $this->expectException(FileNotWritableException::class); $generator->generate(new ClassGenerator($fqcn)); } public function testWhenFailingAllTemporaryFilesAreRemoved(): void { $tmpDirPath = $this->tempDir . '/' . uniqid('noTempFilesLeftBehind', true); mkdir($tmpDirPath); $locator = $this->createMock(FileLocatorInterface::class); $generator = new FileWriterGeneratorStrategy($locator); $tmpFile = $tmpDirPath . '/' . uniqid('FileWriterGeneratorStrategyFailedFileMoveTest', true) . '.php'; $namespace = 'Foo'; $className = UniqueIdentifierGenerator::getIdentifier('Bar'); $fqcn = $namespace . '\\' . $className; $locator ->method('getProxyFileName') ->with($fqcn) ->willReturn($tmpFile); mkdir($tmpFile); try { $generator->generate(new ClassGenerator($fqcn)); self::fail('An exception was supposed to be thrown'); } catch (FileNotWritableException $exception) { rmdir($tmpFile); self::assertEquals(['.', '..'], scandir($tmpDirPath, SCANDIR_SORT_ASCENDING)); } } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Inflector/000077500000000000000000000000001407505032400241525ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Inflector/ClassNameInflectorTest.php000066400000000000000000000114341407505032400312420ustar00rootroot00000000000000isProxyClassName($realClassName)); self::assertTrue($inflector->isProxyClassName($proxyClassName)); self::assertStringMatchesFormat($realClassName, $inflector->getUserClassName($realClassName)); self::assertStringMatchesFormat($proxyClassName, $inflector->getProxyClassName($proxyClassName)); self::assertStringMatchesFormat($proxyClassName, $inflector->getProxyClassName($realClassName)); self::assertStringMatchesFormat($realClassName, $inflector->getUserClassName($proxyClassName)); } public function testGeneratesSameClassNameWithSameParameters(): void { /** @var class-string $fooBar */ $fooBar = 'Foo\\Bar'; $inflector = new ClassNameInflector('ProxyNS'); self::assertSame($inflector->getProxyClassName($fooBar), $inflector->getProxyClassName($fooBar)); self::assertSame( $inflector->getProxyClassName($fooBar, ['baz' => 'tab']), $inflector->getProxyClassName($fooBar, ['baz' => 'tab']) ); self::assertSame( $inflector->getProxyClassName($fooBar, ['tab' => 'baz']), $inflector->getProxyClassName($fooBar, ['tab' => 'baz']) ); } public function testGeneratesDifferentClassNameWithDifferentParameters(): void { /** @var class-string $fooBar */ $fooBar = 'Foo\\Bar'; $inflector = new ClassNameInflector('ProxyNS'); self::assertNotSame( $inflector->getProxyClassName($fooBar), $inflector->getProxyClassName($fooBar, ['foo' => 'bar']) ); self::assertNotSame( $inflector->getProxyClassName($fooBar, ['baz' => 'tab']), $inflector->getProxyClassName($fooBar, ['tab' => 'baz']) ); self::assertNotSame( $inflector->getProxyClassName($fooBar, ['foo' => 'bar', 'tab' => 'baz']), $inflector->getProxyClassName($fooBar, ['foo' => 'bar']) ); self::assertNotSame( $inflector->getProxyClassName($fooBar, ['foo' => 'bar', 'tab' => 'baz']), $inflector->getProxyClassName($fooBar, ['tab' => 'baz', 'foo' => 'bar']) ); } public function testGeneratesCorrectClassNameWhenGivenLeadingBackslash(): void { /** @var class-string $fooBar */ $fooBar = 'Foo\\Bar'; /** @var class-string $fooBarPrefixed */ $fooBarPrefixed = '\\Foo\\Bar'; $inflector = new ClassNameInflector('ProxyNS'); self::assertSame( $inflector->getProxyClassName($fooBarPrefixed, ['tab' => 'baz']), $inflector->getProxyClassName($fooBar, ['tab' => 'baz']) ); } /** * @param class-string $className * @param array $parameters * * @dataProvider getClassAndParametersCombinations */ public function testClassNameIsValidClassIdentifier(string $className, array $parameters): void { $inflector = new ClassNameInflector('ProxyNS'); self::assertMatchesRegularExpression( '/([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]+)(\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]+)*/', $inflector->getProxyClassName($className, $parameters), 'Class name string is a valid class identifier' ); } /** * Data provider. * * @return string[][] */ public static function getClassNames(): array { return [ ['Foo', 'ProxyNS\\' . ClassNameInflectorInterface::PROXY_MARKER . '\\Foo\\%s'], ['Foo\\Bar', 'ProxyNS\\' . ClassNameInflectorInterface::PROXY_MARKER . '\\Foo\\Bar\\%s'], ]; } /** * Data provider. * * @return mixed[][] */ public static function getClassAndParametersCombinations(): array { return [ ['Foo', []], ['Foo\\Bar', []], ['Foo', [null]], ['Foo\\Bar', [null]], ['Foo', ['foo' => 'bar']], ['Foo\\Bar', ['foo' => 'bar']], ['Foo', ["\0" => "very \0 bad"]], ['Foo\\Bar', ["\0" => "very \0 bad"]], ]; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Inflector/Util/000077500000000000000000000000001407505032400250675ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Inflector/Util/ParameterEncoderTest.php000066400000000000000000000022561407505032400316650ustar00rootroot00000000000000encodeParameters($parameters), 'Encoded string is a valid class identifier' ); } /** @return mixed[][] */ public static function getParameters(): array { return [ [[]], [['foo' => 'bar']], [['bar' => 'baz']], [[null]], [[null, null]], [['bar' => null]], [['bar' => 12345]], [['foo' => 'bar', 'bar' => 'baz']], ]; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Inflector/Util/ParameterHasherTest.php000066400000000000000000000025311407505032400315140ustar00rootroot00000000000000hashParameters($parameters)); } /** @return mixed[][][]|string[][] */ public static function getParameters(): array { return [ [[], '40cd750bba9870f18aada2478b24840a'], [['foo' => 'bar'], '49a3696adf0fbfacc12383a2d7400d51'], [['bar' => 'baz'], '6ed41c8a63c1571554ecaeb998198757'], [[null], '38017a839aaeb8ff1a658fce9af6edd3'], [[null, null], '12051f9a58288e5328ad748881cc4e00'], [['bar' => null], '0dbb112e1c4e6e4126232de2daa2d660'], [['bar' => 12345], 'eb6291ea4973741bf9b6571f49b4ffd2'], [['foo' => 'bar', 'bar' => 'baz'], '4447ff857f244d24c31bd84d7a855eda'], ]; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/000077500000000000000000000000001407505032400252155ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AbstractProxyGeneratorTest.php000066400000000000000000000102621407505032400332430ustar00rootroot00000000000000getProxyGenerator(); $generatedClassName = UniqueIdentifierGenerator::getIdentifier('AbstractProxyGeneratorTest'); $generatedClass = new ClassGenerator($generatedClassName); $originalClass = new ReflectionClass($className); $generatorStrategy = new EvaluatingGeneratorStrategy(); $generator->generate($originalClass, $generatedClass); $generatorStrategy->generate($generatedClass); $generatedReflection = new ReflectionClass($generatedClassName); if ($originalClass->isInterface()) { self::assertTrue($generatedReflection->implementsInterface($className)); } else { $parentClass = $generatedReflection->getParentClass(); self::assertInstanceOf(ReflectionClass::class, $parentClass); self::assertSame($originalClass->getName(), $parentClass->getName()); } self::assertSame($generatedClassName, $generatedReflection->getName()); foreach ($this->getExpectedImplementedInterfaces() as $interface) { self::assertTrue($generatedReflection->implementsInterface($interface)); } } /** * Retrieve a new generator instance */ abstract protected function getProxyGenerator(): ProxyGeneratorInterface; /** * Retrieve interfaces that should be implemented by the generated code * * @return string[] * * @psalm-return list */ abstract protected function getExpectedImplementedInterfaces(): array; /** @return string[][] */ public function getTestedImplementations(): array { $implementations = [ [BaseClass::class], [ClassWithMagicMethods::class], [ClassWithByRefMagicMethods::class], [ClassWithMixedProperties::class], [ClassWithMixedTypedProperties::class], [ClassWithMixedReferenceableTypedProperties::class], [ClassWithAbstractPublicMethod::class], [BaseInterface::class], [ReturnTypeHintedClass::class], [VoidMethodTypeHintedClass::class], [ReturnTypeHintedInterface::class], [VoidMethodTypeHintedInterface::class], [IterableMethodTypeHintedInterface::class], [ObjectMethodTypeHintedInterface::class], ]; if (PHP_VERSION_ID >= 80000) { $implementations[] = [ClassWithPhp80TypedMethods::class]; } return $implementations; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptor/000077500000000000000000000000001407505032400306355ustar00rootroot00000000000000MethodGenerator/000077500000000000000000000000001407505032400336455ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorMagicWakeupTest.php000066400000000000000000000042261407505032400374170ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptor/MethodGeneratorgetName()); self::assertCount(0, $magicWakeup->getParameters()); self::assertSame("unset(\$this->bar, \$this->baz);\n\n", $magicWakeup->getBody()); } public function testBodyStructureWithoutPublicProperties(): void { $magicWakeup = new MagicWakeup(new ReflectionClass(EmptyClass::class)); self::assertSame('__wakeup', $magicWakeup->getName()); self::assertCount(0, $magicWakeup->getParameters()); self::assertEmpty($magicWakeup->getBody()); } /** * @group 276 */ public function testWillUnsetPrivateProperties(): void { $magicWakeup = new MagicWakeup(new ReflectionClass(ClassWithMixedProperties::class)); self::assertSame( 'unset($this->publicProperty0, $this->publicProperty1, $this->publicProperty2, ' . '$this->protectedProperty0, $this->protectedProperty1, $this->protectedProperty2); \Closure::bind(function (\ProxyManagerTestAsset\ClassWithMixedProperties $instance) { unset($instance->privateProperty0, $instance->privateProperty1, $instance->privateProperty2); }, $this, \'ProxyManagerTestAsset\\\\ClassWithMixedProperties\')->__invoke($this); ', $magicWakeup->getBody() ); } } SetMethodPrefixInterceptorTest.php000066400000000000000000000024121407505032400425060ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptor/MethodGeneratorcreateMock(PropertyGenerator::class); $suffix->expects(self::once())->method('getName')->willReturn('foo'); $setter = new SetMethodPrefixInterceptor($suffix); self::assertEquals(TypeGenerator::fromTypeString('void'), $setter->getReturnType()); self::assertSame('setMethodPrefixInterceptor', $setter->getName()); self::assertCount(2, $setter->getParameters()); self::assertSame('$this->foo[$methodName] = $prefixInterceptor;', $setter->getBody()); } } SetMethodSuffixInterceptorTest.php000066400000000000000000000024121407505032400425150ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptor/MethodGeneratorcreateMock(PropertyGenerator::class); $suffix->expects(self::once())->method('getName')->willReturn('foo'); $setter = new SetMethodSuffixInterceptor($suffix); self::assertEquals(TypeGenerator::fromTypeString('void'), $setter->getReturnType()); self::assertSame('setMethodSuffixInterceptor', $setter->getName()); self::assertCount(2, $setter->getParameters()); self::assertSame('$this->foo[$methodName] = $suffixInterceptor;', $setter->getBody()); } } PropertyGenerator/000077500000000000000000000000001407505032400342515ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorMethodPrefixInterceptorsTest.php000066400000000000000000000014171407505032400426250ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptor/PropertyGeneratorprefixInterceptors = $this->createMock(PropertyGenerator::class); $this->suffixInterceptors = $this->createMock(PropertyGenerator::class); $this->prefixInterceptors->method('getName')->willReturn('pre'); $this->suffixInterceptors->method('getName')->willReturn('post'); } public function testSignature(): void { $method = new BindProxyProperties( new ReflectionClass(ClassWithProtectedProperties::class), $this->prefixInterceptors, $this->suffixInterceptors ); self::assertSame('bindProxyProperties', $method->getName()); self::assertSame('private', $method->getVisibility()); self::assertFalse($method->isStatic()); $parameters = $method->getParameters(); self::assertCount(3, $parameters); self::assertSame( ClassWithProtectedProperties::class, $parameters['localizedObject']->getType() ); self::assertSame('array', $parameters['prefixInterceptors']->getType()); self::assertSame('array', $parameters['suffixInterceptors']->getType()); } public function testBodyStructure(): void { $method = new BindProxyProperties( new ReflectionClass(ClassWithMixedProperties::class), $this->prefixInterceptors, $this->suffixInterceptors ); $expectedCode = <<<'PHP' $this->publicProperty0 = & $localizedObject->publicProperty0; $this->publicProperty1 = & $localizedObject->publicProperty1; $this->publicProperty2 = & $localizedObject->publicProperty2; $this->protectedProperty0 = & $localizedObject->protectedProperty0; $this->protectedProperty1 = & $localizedObject->protectedProperty1; $this->protectedProperty2 = & $localizedObject->protectedProperty2; \Closure::bind(function () use ($localizedObject) { $this->privateProperty0 = & $localizedObject->privateProperty0; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedProperties')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->privateProperty1 = & $localizedObject->privateProperty1; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedProperties')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->privateProperty2 = & $localizedObject->privateProperty2; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedProperties')->__invoke(); $this->pre = $prefixInterceptors; $this->post = $suffixInterceptors; PHP; self::assertSame($expectedCode, $method->getBody()); } public function testBodyStructureWithProtectedProperties(): void { $method = new BindProxyProperties( new ReflectionClass(ClassWithProtectedProperties::class), $this->prefixInterceptors, $this->suffixInterceptors ); self::assertSame( '$this->property0 = & $localizedObject->property0; $this->property1 = & $localizedObject->property1; $this->property2 = & $localizedObject->property2; $this->property3 = & $localizedObject->property3; $this->property4 = & $localizedObject->property4; $this->property5 = & $localizedObject->property5; $this->property6 = & $localizedObject->property6; $this->property7 = & $localizedObject->property7; $this->property8 = & $localizedObject->property8; $this->property9 = & $localizedObject->property9; $this->pre = $prefixInterceptors; $this->post = $suffixInterceptors;', $method->getBody() ); } public function testBodyStructureWithPrivateProperties(): void { $method = new BindProxyProperties( new ReflectionClass(ClassWithPrivateProperties::class), $this->prefixInterceptors, $this->suffixInterceptors ); self::assertSame( '\Closure::bind(function () use ($localizedObject) { $this->property0 = & $localizedObject->property0; }, $this, \'ProxyManagerTestAsset\\\\ClassWithPrivateProperties\')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->property1 = & $localizedObject->property1; }, $this, \'ProxyManagerTestAsset\\\\ClassWithPrivateProperties\')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->property2 = & $localizedObject->property2; }, $this, \'ProxyManagerTestAsset\\\\ClassWithPrivateProperties\')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->property3 = & $localizedObject->property3; }, $this, \'ProxyManagerTestAsset\\\\ClassWithPrivateProperties\')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->property4 = & $localizedObject->property4; }, $this, \'ProxyManagerTestAsset\\\\ClassWithPrivateProperties\')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->property5 = & $localizedObject->property5; }, $this, \'ProxyManagerTestAsset\\\\ClassWithPrivateProperties\')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->property6 = & $localizedObject->property6; }, $this, \'ProxyManagerTestAsset\\\\ClassWithPrivateProperties\')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->property7 = & $localizedObject->property7; }, $this, \'ProxyManagerTestAsset\\\\ClassWithPrivateProperties\')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->property8 = & $localizedObject->property8; }, $this, \'ProxyManagerTestAsset\\\\ClassWithPrivateProperties\')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->property9 = & $localizedObject->property9; }, $this, \'ProxyManagerTestAsset\\\\ClassWithPrivateProperties\')->__invoke(); $this->pre = $prefixInterceptors; $this->post = $suffixInterceptors;', $method->getBody() ); } /** * @requires PHP 7.4 */ public function testBodyStructureWithTypedProperties(): void { $method = new BindProxyProperties( new ReflectionClass(ClassWithMixedReferenceableTypedProperties::class), $this->prefixInterceptors, $this->suffixInterceptors ); self::assertSame( <<<'PHP' $this->publicUnTypedProperty = & $localizedObject->publicUnTypedProperty; $this->publicBoolProperty = & $localizedObject->publicBoolProperty; $this->publicNullableBoolProperty = & $localizedObject->publicNullableBoolProperty; $this->publicIntProperty = & $localizedObject->publicIntProperty; $this->publicNullableIntProperty = & $localizedObject->publicNullableIntProperty; $this->publicFloatProperty = & $localizedObject->publicFloatProperty; $this->publicNullableFloatProperty = & $localizedObject->publicNullableFloatProperty; $this->publicStringProperty = & $localizedObject->publicStringProperty; $this->publicNullableStringProperty = & $localizedObject->publicNullableStringProperty; $this->publicArrayProperty = & $localizedObject->publicArrayProperty; $this->publicNullableArrayProperty = & $localizedObject->publicNullableArrayProperty; $this->publicIterableProperty = & $localizedObject->publicIterableProperty; $this->publicNullableIterableProperty = & $localizedObject->publicNullableIterableProperty; $this->protectedUnTypedProperty = & $localizedObject->protectedUnTypedProperty; $this->protectedBoolProperty = & $localizedObject->protectedBoolProperty; $this->protectedNullableBoolProperty = & $localizedObject->protectedNullableBoolProperty; $this->protectedIntProperty = & $localizedObject->protectedIntProperty; $this->protectedNullableIntProperty = & $localizedObject->protectedNullableIntProperty; $this->protectedFloatProperty = & $localizedObject->protectedFloatProperty; $this->protectedNullableFloatProperty = & $localizedObject->protectedNullableFloatProperty; $this->protectedStringProperty = & $localizedObject->protectedStringProperty; $this->protectedNullableStringProperty = & $localizedObject->protectedNullableStringProperty; $this->protectedArrayProperty = & $localizedObject->protectedArrayProperty; $this->protectedNullableArrayProperty = & $localizedObject->protectedNullableArrayProperty; $this->protectedIterableProperty = & $localizedObject->protectedIterableProperty; $this->protectedNullableIterableProperty = & $localizedObject->protectedNullableIterableProperty; \Closure::bind(function () use ($localizedObject) { $this->privateUnTypedProperty = & $localizedObject->privateUnTypedProperty; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedReferenceableTypedProperties')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->privateBoolProperty = & $localizedObject->privateBoolProperty; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedReferenceableTypedProperties')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->privateNullableBoolProperty = & $localizedObject->privateNullableBoolProperty; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedReferenceableTypedProperties')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->privateIntProperty = & $localizedObject->privateIntProperty; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedReferenceableTypedProperties')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->privateNullableIntProperty = & $localizedObject->privateNullableIntProperty; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedReferenceableTypedProperties')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->privateFloatProperty = & $localizedObject->privateFloatProperty; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedReferenceableTypedProperties')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->privateNullableFloatProperty = & $localizedObject->privateNullableFloatProperty; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedReferenceableTypedProperties')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->privateStringProperty = & $localizedObject->privateStringProperty; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedReferenceableTypedProperties')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->privateNullableStringProperty = & $localizedObject->privateNullableStringProperty; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedReferenceableTypedProperties')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->privateArrayProperty = & $localizedObject->privateArrayProperty; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedReferenceableTypedProperties')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->privateNullableArrayProperty = & $localizedObject->privateNullableArrayProperty; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedReferenceableTypedProperties')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->privateIterableProperty = & $localizedObject->privateIterableProperty; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedReferenceableTypedProperties')->__invoke(); \Closure::bind(function () use ($localizedObject) { $this->privateNullableIterableProperty = & $localizedObject->privateNullableIterableProperty; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedReferenceableTypedProperties')->__invoke(); $this->pre = $prefixInterceptors; $this->post = $suffixInterceptors; PHP , $method->getBody() ); } } InterceptedMethodTest.php000066400000000000000000000047631407505032400434760ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorprefixInterceptors = $this->createMock(PropertyGenerator::class); $this->suffixInterceptors = $this->createMock(PropertyGenerator::class); $this->prefixInterceptors->method('getName')->willReturn('pre'); $this->suffixInterceptors->method('getName')->willReturn('post'); } public function testBodyStructure(): void { $method = InterceptedMethod::generateMethod( new MethodReflection(BaseClass::class, 'publicByReferenceParameterMethod'), $this->prefixInterceptors, $this->suffixInterceptors ); self::assertSame('publicByReferenceParameterMethod', $method->getName()); self::assertCount(2, $method->getParameters()); self::assertStringMatchesFormat( '%a$returnValue = parent::publicByReferenceParameterMethod($param, $byRefParam);%A', $method->getBody() ); } public function testForwardsVariadicParameters(): void { $method = InterceptedMethod::generateMethod( new MethodReflection(ClassWithMethodWithVariadicFunction::class, 'foo'), $this->prefixInterceptors, $this->suffixInterceptors ); self::assertSame('foo', $method->getName()); self::assertCount(2, $method->getParameters()); self::assertStringMatchesFormat( '%a$returnValue = parent::foo($bar, ...$baz);%A', $method->getBody() ); } } MagicCloneTest.php000066400000000000000000000045471407505032400420700ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorcreateMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $magicClone = new MagicClone($reflection, $prefixInterceptors, $suffixInterceptors); self::assertSame('__clone', $magicClone->getName()); self::assertCount(0, $magicClone->getParameters()); self::assertStringMatchesFormat("%a\n\n\$returnValue = null;\n\n%a", $magicClone->getBody()); } /** * @covers \ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\MagicClone::__construct */ public function testBodyStructureWithInheritedMethod(): void { $reflection = new ReflectionClass(ClassWithMagicMethods::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $magicClone = new MagicClone($reflection, $prefixInterceptors, $suffixInterceptors); self::assertSame('__clone', $magicClone->getName()); self::assertCount(0, $magicClone->getParameters()); self::assertStringMatchesFormat("%a\n\n\$returnValue = parent::__clone();\n\n%a", $magicClone->getBody()); } } MagicGetTest.php000066400000000000000000000043721407505032400415430ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorcreateMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $magicGet = new MagicGet( $reflection, $prefixInterceptors, $suffixInterceptors ); self::assertSame('__get', $magicGet->getName()); self::assertCount(1, $magicGet->getParameters()); self::assertStringMatchesFormat('%a$returnValue = & $accessor();%a', $magicGet->getBody()); } public function testBodyStructureWithInheritedMethod(): void { $reflection = new ReflectionClass(ClassWithMagicMethods::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $magicGet = new MagicGet( $reflection, $prefixInterceptors, $suffixInterceptors ); self::assertSame('__get', $magicGet->getName()); self::assertCount(1, $magicGet->getParameters()); self::assertStringMatchesFormat('%a$returnValue = & parent::__get($name);%a', $magicGet->getBody()); } } MagicIssetTest.php000066400000000000000000000046771407505032400421230ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorcreateMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $magicIsset = new MagicIsset( $reflection, $prefixInterceptors, $suffixInterceptors ); self::assertSame('__isset', $magicIsset->getName()); self::assertCount(1, $magicIsset->getParameters()); self::assertStringMatchesFormat('%a$returnValue = $accessor();%a', $magicIsset->getBody()); } /** * @covers \ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\MagicIsset::__construct */ public function testBodyStructureWithInheritedMethod(): void { $reflection = new ReflectionClass(ClassWithMagicMethods::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $magicIsset = new MagicIsset( $reflection, $prefixInterceptors, $suffixInterceptors ); self::assertSame('__isset', $magicIsset->getName()); self::assertCount(1, $magicIsset->getParameters()); self::assertStringMatchesFormat('%a$returnValue = & parent::__isset($name);%a', $magicIsset->getBody()); } } MagicSetTest.php000066400000000000000000000046451407505032400415620ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorcreateMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $magicGet = new MagicSet( $reflection, $prefixInterceptors, $suffixInterceptors ); self::assertSame('__set', $magicGet->getName()); self::assertCount(2, $magicGet->getParameters()); self::assertStringMatchesFormat('%a$returnValue = & $accessor();%a', $magicGet->getBody()); } /** * @covers \ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\MagicSet::__construct */ public function testBodyStructureWithInheritedMethod(): void { $reflection = new ReflectionClass(ClassWithMagicMethods::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $magicGet = new MagicSet( $reflection, $prefixInterceptors, $suffixInterceptors ); self::assertSame('__set', $magicGet->getName()); self::assertCount(2, $magicGet->getParameters()); self::assertStringMatchesFormat('%a$returnValue = & parent::__set($name, $value);%a', $magicGet->getBody()); } } MagicSleepTest.php000066400000000000000000000046621407505032400420760ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorcreateMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $magicGet = new MagicSleep( $reflection, $prefixInterceptors, $suffixInterceptors ); self::assertSame('__sleep', $magicGet->getName()); self::assertEmpty($magicGet->getParameters()); self::assertStringMatchesFormat('%a$returnValue = array_keys((array) $this);%a', $magicGet->getBody()); } /** * @covers \ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\MagicSleep::__construct */ public function testBodyStructureWithInheritedMethod(): void { $reflection = new ReflectionClass(ClassWithMagicMethods::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $magicGet = new MagicSleep( $reflection, $prefixInterceptors, $suffixInterceptors ); self::assertSame('__sleep', $magicGet->getName()); self::assertEmpty($magicGet->getParameters()); self::assertStringMatchesFormat('%a$returnValue = & parent::__sleep();%a', $magicGet->getBody()); } } MagicUnsetTest.php000066400000000000000000000046401407505032400421200ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorcreateMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $magicGet = new MagicUnset( $reflection, $prefixInterceptors, $suffixInterceptors ); self::assertSame('__unset', $magicGet->getName()); self::assertCount(1, $magicGet->getParameters()); self::assertStringMatchesFormat('%a$accessor();%a', $magicGet->getBody()); } /** * @covers \ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator\MagicUnset::__construct */ public function testBodyStructureWithInheritedMethod(): void { $reflection = new ReflectionClass(ClassWithMagicMethods::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $magicGet = new MagicUnset( $reflection, $prefixInterceptors, $suffixInterceptors ); self::assertSame('__unset', $magicGet->getName()); self::assertCount(1, $magicGet->getParameters()); self::assertStringMatchesFormat('%a$returnValue = & parent::__unset($name);%a', $magicGet->getBody()); } } StaticProxyConstructorTest.php000066400000000000000000000047331407505032400446230ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorprefixInterceptors = $this->createMock(PropertyGenerator::class); $this->suffixInterceptors = $this->createMock(PropertyGenerator::class); $this->prefixInterceptors->method('getName')->willReturn('pre'); $this->suffixInterceptors->method('getName')->willReturn('post'); } public function testSignature(): void { $method = new StaticProxyConstructor(new ReflectionClass(ClassWithProtectedProperties::class)); self::assertSame('staticProxyConstructor', $method->getName()); self::assertTrue($method->isStatic()); self::assertSame('public', $method->getVisibility()); $parameters = $method->getParameters(); self::assertCount(3, $parameters); self::assertSame(ClassWithProtectedProperties::class, $parameters['localizedObject']->getType()); self::assertSame('array', $parameters['prefixInterceptors']->getType()); self::assertSame('array', $parameters['suffixInterceptors']->getType()); } public function testBodyStructure(): void { $method = new StaticProxyConstructor(new ReflectionClass(ClassWithPublicProperties::class)); self::assertSame( 'static $reflection; $reflection = $reflection ?? new \ReflectionClass(__CLASS__); $instance = $reflection->newInstanceWithoutConstructor(); $instance->bindProxyProperties($localizedObject, $prefixInterceptors, $suffixInterceptors); return $instance;', $method->getBody() ); } } Util/000077500000000000000000000000001407505032400374215ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGeneratorInterceptorGeneratorTest.php000066400000000000000000000146411407505032400451450ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/UtilcreateMock(MethodGenerator::class); $bar = $this->createMock(ParameterGenerator::class); $baz = $this->createMock(ParameterGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $bar->method('getName')->willReturn('bar'); $baz->method('getName')->willReturn('baz'); $method->method('getName')->willReturn('fooMethod'); $method->method('getParameters')->will(self::returnValue([$bar, $baz])); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); // @codingStandardsIgnoreStart $expected = <<<'PHP' if (isset($this->pre['fooMethod'])) { $returnEarly = false; $prefixReturnValue = $this->pre['fooMethod']->__invoke($this, $this, 'fooMethod', array('bar' => $bar, 'baz' => $baz), $returnEarly); if ($returnEarly) { return $prefixReturnValue; } } $returnValue = "foo"; if (isset($this->post['fooMethod'])) { $returnEarly = false; $suffixReturnValue = $this->post['fooMethod']->__invoke($this, $this, 'fooMethod', array('bar' => $bar, 'baz' => $baz), $returnValue, $returnEarly); if ($returnEarly) { return $suffixReturnValue; } } return $returnValue; PHP; // @codingStandardsIgnoreEnd self::assertSame( $expected, InterceptorGenerator::createInterceptedMethodBody( '$returnValue = "foo";', $method, $prefixInterceptors, $suffixInterceptors, null ) ); } public function testInterceptorGeneratorWithVoidReturnType(): void { $method = $this->createMock(MethodGenerator::class); $bar = $this->createMock(ParameterGenerator::class); $baz = $this->createMock(ParameterGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $bar->method('getName')->willReturn('bar'); $baz->method('getName')->willReturn('baz'); $method->method('getName')->willReturn('fooMethod'); $method->method('getParameters')->will(self::returnValue([$bar, $baz])); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); // @codingStandardsIgnoreStart $expected = <<<'PHP' if (isset($this->pre['fooMethod'])) { $returnEarly = false; $prefixReturnValue = $this->pre['fooMethod']->__invoke($this, $this, 'fooMethod', array('bar' => $bar, 'baz' => $baz), $returnEarly); if ($returnEarly) { $prefixReturnValue; return; } } $returnValue = "foo"; if (isset($this->post['fooMethod'])) { $returnEarly = false; $suffixReturnValue = $this->post['fooMethod']->__invoke($this, $this, 'fooMethod', array('bar' => $bar, 'baz' => $baz), $returnValue, $returnEarly); if ($returnEarly) { $suffixReturnValue; return; } } $returnValue; return; PHP; // @codingStandardsIgnoreEnd self::assertSame( $expected, InterceptorGenerator::createInterceptedMethodBody( '$returnValue = "foo";', $method, $prefixInterceptors, $suffixInterceptors, new ReflectionMethod(VoidMethodTypeHintedInterface::class, 'returnVoid') ) ); } public function testInterceptorGeneratorWithExistingNonVoidMethod(): void { $method = $this->createMock(MethodGenerator::class); $bar = $this->createMock(ParameterGenerator::class); $baz = $this->createMock(ParameterGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $bar->method('getName')->willReturn('bar'); $baz->method('getName')->willReturn('baz'); $method->method('getName')->willReturn('fooMethod'); $method->method('getParameters')->will(self::returnValue([$bar, $baz])); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); // @codingStandardsIgnoreStart $expected = <<<'PHP' if (isset($this->pre['fooMethod'])) { $returnEarly = false; $prefixReturnValue = $this->pre['fooMethod']->__invoke($this, $this, 'fooMethod', array('bar' => $bar, 'baz' => $baz), $returnEarly); if ($returnEarly) { return $prefixReturnValue; } } $returnValue = "foo"; if (isset($this->post['fooMethod'])) { $returnEarly = false; $suffixReturnValue = $this->post['fooMethod']->__invoke($this, $this, 'fooMethod', array('bar' => $bar, 'baz' => $baz), $returnValue, $returnEarly); if ($returnEarly) { return $suffixReturnValue; } } return $returnValue; PHP; // @codingStandardsIgnoreEnd self::assertSame( $expected, InterceptorGenerator::createInterceptedMethodBody( '$returnValue = "foo";', $method, $prefixInterceptors, $suffixInterceptors, new ReflectionMethod(BaseClass::class, 'publicMethod') ) ); } } AccessInterceptorScopeLocalizerTest.php000066400000000000000000000043341407505032400347720ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGeneratorisInterface()) { // @todo interfaces *may* be proxied by deferring property localization to the constructor (no hardcoding) $this->expectException(InvalidProxiedClassException::class); } if ($reflectionClass->getName() === ClassWithMixedTypedProperties::class) { $this->expectException(UnsupportedProxiedClassException::class); } parent::testGeneratesValidCode($className); } public function testWillRejectInterfaces(): void { $this->expectException(InvalidProxiedClassException::class); $this ->getProxyGenerator() ->generate(new ReflectionClass(BaseInterface::class), new ClassGenerator()); } protected function getProxyGenerator(): ProxyGeneratorInterface { return new AccessInterceptorScopeLocalizerGenerator(); } /** * {@inheritDoc} */ protected function getExpectedImplementedInterfaces(): array { return [AccessInterceptorInterface::class]; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorValueHolder/000077500000000000000000000000001407505032400327705ustar00rootroot00000000000000MethodGenerator/000077500000000000000000000000001407505032400360005ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorValueHolderInterceptedMethodTest.php000066400000000000000000000035521407505032400427650ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $valueHolder->method('getName')->willReturn('foo'); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $method = InterceptedMethod::generateMethod( new MethodReflection(BaseClass::class, 'publicByReferenceParameterMethod'), $valueHolder, $prefixInterceptors, $suffixInterceptors ); self::assertSame('publicByReferenceParameterMethod', $method->getName()); self::assertCount(2, $method->getParameters()); self::assertGreaterThan( 0, strpos( $method->getBody(), '$returnValue = $this->foo->publicByReferenceParameterMethod($param, $byRefParam);' ) ); } } MagicCloneTest.php000066400000000000000000000035631407505032400413610ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $valueHolder->method('getName')->willReturn('bar'); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $magicClone = new MagicClone($reflection, $valueHolder, $prefixInterceptors, $suffixInterceptors); self::assertSame('__clone', $magicClone->getName()); self::assertCount(0, $magicClone->getParameters()); self::assertSame( '$this->bar = clone $this->bar;' . "\n\n" . 'foreach ($this->pre as $key => $value) {' . "\n" . ' $this->pre[$key] = clone $value;' . "\n" . '}' . "\n\n" . 'foreach ($this->post as $key => $value) {' . "\n" . ' $this->post[$key] = clone $value;' . "\n" . '}', $magicClone->getBody() ); } } MagicGetTest.php000066400000000000000000000035231407505032400410340ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $publicProperties = $this->createMock(PublicPropertiesMap::class); $valueHolder->method('getName')->willReturn('bar'); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $publicProperties->method('isEmpty')->willReturn(false); $magicGet = new MagicGet( $reflection, $valueHolder, $prefixInterceptors, $suffixInterceptors, $publicProperties ); self::assertSame('__get', $magicGet->getName()); self::assertCount(1, $magicGet->getParameters()); self::assertStringMatchesFormat('%A$returnValue = & $this->bar->$name;%A', $magicGet->getBody()); } } MagicIssetTest.php000066400000000000000000000036011407505032400414010ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $publicProperties = $this->createMock(PublicPropertiesMap::class); $valueHolder->method('getName')->willReturn('bar'); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $publicProperties->method('isEmpty')->willReturn(false); $magicIsset = new MagicIsset( $reflection, $valueHolder, $prefixInterceptors, $suffixInterceptors, $publicProperties ); self::assertSame('__isset', $magicIsset->getName()); self::assertCount(1, $magicIsset->getParameters()); self::assertGreaterThan(0, strpos($magicIsset->getBody(), '$returnValue = isset($this->bar->$name);')); } } MagicSetTest.php000066400000000000000000000035611407505032400410520ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $publicProperties = $this->createMock(PublicPropertiesMap::class); $valueHolder->method('getName')->willReturn('bar'); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $publicProperties->method('isEmpty')->willReturn(false); $magicSet = new MagicSet( $reflection, $valueHolder, $prefixInterceptors, $suffixInterceptors, $publicProperties ); self::assertSame('__set', $magicSet->getName()); self::assertCount(2, $magicSet->getParameters()); self::assertGreaterThan(0, strpos($magicSet->getBody(), '$returnValue = ($this->bar->$name = $value);')); } } MagicUnsetTest.php000066400000000000000000000036241407505032400414150ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $publicProperties = $this->createMock(PublicPropertiesMap::class); $valueHolder->method('getName')->willReturn('bar'); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $publicProperties->method('isEmpty')->willReturn(false); $magicUnset = new MagicUnset( $reflection, $valueHolder, $prefixInterceptors, $suffixInterceptors, $publicProperties ); self::assertSame('__unset', $magicUnset->getName()); self::assertCount(1, $magicUnset->getParameters()); self::assertGreaterThan( 0, strpos($magicUnset->getBody(), 'unset($this->bar->$name);') ); } } StaticProxyConstructorTest.php000066400000000000000000000110731407505032400441120ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $valueHolder->method('getName')->willReturn('foo'); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $constructor = new StaticProxyConstructor( new ReflectionClass( ClassWithTwoPublicProperties::class ), $valueHolder, $prefixInterceptors, $suffixInterceptors ); self::assertSame('staticProxyConstructor', $constructor->getName()); self::assertTrue($constructor->isStatic()); self::assertSame('public', $constructor->getVisibility()); self::assertCount(3, $constructor->getParameters()); self::assertSame( 'static $reflection; $reflection = $reflection ?? new \ReflectionClass(__CLASS__); $instance = $reflection->newInstanceWithoutConstructor(); unset($instance->bar, $instance->baz); $instance->foo = $wrappedObject; $instance->pre = $prefixInterceptors; $instance->post = $suffixInterceptors; return $instance;', $constructor->getBody() ); } public function testBodyStructureWithoutPublicProperties(): void { $valueHolder = $this->createMock(PropertyGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $valueHolder->method('getName')->willReturn('foo'); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $constructor = new StaticProxyConstructor( new ReflectionClass(EmptyClass::class), $valueHolder, $prefixInterceptors, $suffixInterceptors ); self::assertSame( 'static $reflection; $reflection = $reflection ?? new \ReflectionClass(__CLASS__); $instance = $reflection->newInstanceWithoutConstructor(); $instance->foo = $wrappedObject; $instance->pre = $prefixInterceptors; $instance->post = $suffixInterceptors; return $instance;', $constructor->getBody() ); } /** * @group 276 */ public function testUnsetsPrivatePropertiesAsWell(): void { $valueHolder = $this->createMock(PropertyGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $valueHolder->method('getName')->willReturn('foo'); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); $constructor = new StaticProxyConstructor( new ReflectionClass(ClassWithMixedProperties::class), $valueHolder, $prefixInterceptors, $suffixInterceptors ); self::assertStringContainsString( 'unset($instance->publicProperty0, $instance->publicProperty1, $instance->publicProperty2, ' . '$instance->protectedProperty0, $instance->protectedProperty1, $instance->protectedProperty2); \Closure::bind(function (\ProxyManagerTestAsset\ClassWithMixedProperties $instance) { unset($instance->privateProperty0, $instance->privateProperty1, $instance->privateProperty2); }, $instance, \'ProxyManagerTestAsset\\\\ClassWithMixedProperties\')->__invoke($instance);', $constructor->getBody() ); } } Util/000077500000000000000000000000001407505032400367155ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorValueHolder/MethodGeneratorInterceptorGeneratorTest.php000066400000000000000000000156411407505032400444420ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/UtilcreateMock(MethodGenerator::class); $bar = $this->createMock(ParameterGenerator::class); $baz = $this->createMock(ParameterGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $bar->method('getName')->willReturn('bar'); $baz->method('getName')->willReturn('baz'); $method->method('getName')->willReturn('fooMethod'); $method->method('getParameters')->will(self::returnValue([$bar, $baz])); $valueHolder->method('getName')->willReturn('foo'); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); // @codingStandardsIgnoreStart $expected = <<<'PHP' if (isset($this->pre['fooMethod'])) { $returnEarly = false; $prefixReturnValue = $this->pre['fooMethod']->__invoke($this, $this->foo, 'fooMethod', array('bar' => $bar, 'baz' => $baz), $returnEarly); if ($returnEarly) { return $prefixReturnValue; } } $returnValue = "foo"; if (isset($this->post['fooMethod'])) { $returnEarly = false; $suffixReturnValue = $this->post['fooMethod']->__invoke($this, $this->foo, 'fooMethod', array('bar' => $bar, 'baz' => $baz), $returnValue, $returnEarly); if ($returnEarly) { return $suffixReturnValue; } } return $returnValue; PHP; // @codingStandardsIgnoreEnd self::assertSame( $expected, InterceptorGenerator::createInterceptedMethodBody( '$returnValue = "foo";', $method, $valueHolder, $prefixInterceptors, $suffixInterceptors, null ) ); } public function testInterceptorGeneratorWithVoidMethod(): void { $method = $this->createMock(MethodGenerator::class); $bar = $this->createMock(ParameterGenerator::class); $baz = $this->createMock(ParameterGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $bar->method('getName')->willReturn('bar'); $baz->method('getName')->willReturn('baz'); $method->method('getName')->willReturn('fooMethod'); $method->method('getParameters')->will(self::returnValue([$bar, $baz])); $valueHolder->method('getName')->willReturn('foo'); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); // @codingStandardsIgnoreStart $expected = <<<'PHP' if (isset($this->pre['fooMethod'])) { $returnEarly = false; $prefixReturnValue = $this->pre['fooMethod']->__invoke($this, $this->foo, 'fooMethod', array('bar' => $bar, 'baz' => $baz), $returnEarly); if ($returnEarly) { $prefixReturnValue; return; } } $returnValue = "foo"; if (isset($this->post['fooMethod'])) { $returnEarly = false; $suffixReturnValue = $this->post['fooMethod']->__invoke($this, $this->foo, 'fooMethod', array('bar' => $bar, 'baz' => $baz), $returnValue, $returnEarly); if ($returnEarly) { $suffixReturnValue; return; } } $returnValue; return; PHP; // @codingStandardsIgnoreEnd self::assertSame( $expected, InterceptorGenerator::createInterceptedMethodBody( '$returnValue = "foo";', $method, $valueHolder, $prefixInterceptors, $suffixInterceptors, new ReflectionMethod(VoidMethodTypeHintedInterface::class, 'returnVoid') ) ); } public function testInterceptorGeneratorWithNonVoidOriginalMethod(): void { $method = $this->createMock(MethodGenerator::class); $bar = $this->createMock(ParameterGenerator::class); $baz = $this->createMock(ParameterGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $prefixInterceptors = $this->createMock(PropertyGenerator::class); $suffixInterceptors = $this->createMock(PropertyGenerator::class); $bar->method('getName')->willReturn('bar'); $baz->method('getName')->willReturn('baz'); $method->method('getName')->willReturn('fooMethod'); $method->method('getParameters')->will(self::returnValue([$bar, $baz])); $valueHolder->method('getName')->willReturn('foo'); $prefixInterceptors->method('getName')->willReturn('pre'); $suffixInterceptors->method('getName')->willReturn('post'); // @codingStandardsIgnoreStart $expected = <<<'PHP' if (isset($this->pre['fooMethod'])) { $returnEarly = false; $prefixReturnValue = $this->pre['fooMethod']->__invoke($this, $this->foo, 'fooMethod', array('bar' => $bar, 'baz' => $baz), $returnEarly); if ($returnEarly) { return $prefixReturnValue; } } $returnValue = "foo"; if (isset($this->post['fooMethod'])) { $returnEarly = false; $suffixReturnValue = $this->post['fooMethod']->__invoke($this, $this->foo, 'fooMethod', array('bar' => $bar, 'baz' => $baz), $returnValue, $returnEarly); if ($returnEarly) { return $suffixReturnValue; } } return $returnValue; PHP; // @codingStandardsIgnoreEnd self::assertSame( $expected, InterceptorGenerator::createInterceptedMethodBody( '$returnValue = "foo";', $method, $valueHolder, $prefixInterceptors, $suffixInterceptors, new ReflectionMethod(BaseClass::class, 'publicMethod') ) ); } } AccessInterceptorValueHolderTest.php000066400000000000000000000020601407505032400342600ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGeneratorexpectException(InvalidProxiedClassException::class); CanProxyAssertion::assertClassCanBeProxied(new ReflectionClass(FinalClass::class)); } public function testDeniesClassesWithAbstractProtectedMethods(): void { $this->expectException(InvalidProxiedClassException::class); CanProxyAssertion::assertClassCanBeProxied(new ReflectionClass( ClassWithAbstractProtectedMethod::class )); } public function testAllowsInterfaceByDefault(): void { CanProxyAssertion::assertClassCanBeProxied(new ReflectionClass( BaseInterface::class )); self::assertTrue(true); // not nice, but assertions are just fail-checks, no real code executed } public function testDeniesInterfaceIfSpecified(): void { CanProxyAssertion::assertClassCanBeProxied(new ReflectionClass(BaseClass::class), false); $this->expectException(InvalidProxiedClassException::class); CanProxyAssertion::assertClassCanBeProxied(new ReflectionClass(BaseInterface::class), false); } /** * @dataProvider validClasses * @psalm-param class-string $className */ public function testAllowedClass(string $className): void { CanProxyAssertion::assertClassCanBeProxied(new ReflectionClass($className)); self::assertTrue(true); // not nice, but assertions are just fail-checks, no real code executed } public function testDisallowsConstructor(): void { $this->expectException(BadMethodCallException::class); new CanProxyAssertion(); } /** * @return string[][] */ public function validClasses(): array { return [ [AccessInterceptorValueHolderMock::class], [BaseClass::class], [BaseInterface::class], [CallableTypeHintClass::class], [ClassWithByRefMagicMethods::class], [ClassWithFinalMagicMethods::class], [ClassWithFinalMethods::class], [ClassWithMethodWithDefaultParameters::class], [ClassWithMixedProperties::class], [ClassWithPrivateProperties::class], [ClassWithProtectedProperties::class], [ClassWithPublicProperties::class], [ClassWithPublicArrayProperty::class], [ClassWithSelfHint::class], [ClassWithParentHint::class], [EmptyClass::class], [HydratedObject::class], [LazyLoadingMock::class], [NullObjectMock::class], ]; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoading/000077500000000000000000000000001407505032400274325ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoading/MethodGenerator/000077500000000000000000000000001407505032400325215ustar00rootroot00000000000000StaticProxyConstructorTest.php000066400000000000000000000041141407505032400405520ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoading/MethodGeneratorcreateMock(PropertyGenerator::class); $initializer->method('getName')->willReturn('foo'); $constructor = new StaticProxyConstructor( $initializer, Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class)) ); self::assertSame('staticProxyConstructor', $constructor->getName()); self::assertCount(1, $constructor->getParameters()); self::assertTrue($constructor->isStatic()); self::assertSame('public', $constructor->getVisibility()); self::assertStringMatchesFormat( 'static $reflection; $reflection = $reflection ?? new \ReflectionClass(__CLASS__); $instance = $reflection->newInstanceWithoutConstructor(); unset($instance->publicProperty0, $instance->publicProperty1, $instance->publicProperty2, ' . '$instance->protectedProperty0, $instance->protectedProperty1, $instance->protectedProperty2); \Closure::bind(function (\ProxyManagerTestAsset\ClassWithMixedProperties $instance) { unset($instance->privateProperty0, $instance->privateProperty1, $instance->privateProperty2); }, $instance, \'ProxyManagerTestAsset\\\\ClassWithMixedProperties\')->__invoke($instance); $instance->foo = $initializer; return $instance;', $constructor->getBody() ); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/000077500000000000000000000000001407505032400304375ustar00rootroot00000000000000MethodGenerator/000077500000000000000000000000001407505032400334475ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhostCallInitializerTest.php000066400000000000000000000423321407505032400401030ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/MethodGeneratorcreateMock(PropertyGenerator::class); $initializationTracker = $this->createMock(PropertyGenerator::class); $initializer->method('getName')->willReturn('init'); $initializationTracker->method('getName')->willReturn('track'); $callInitializer = new CallInitializer( $initializer, $initializationTracker, Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class)) ); $expectedCode = <<<'PHP' if ($this->track || ! $this->init) { return; } $this->track = true; $this->publicProperty0 = 'publicProperty0'; $this->publicProperty1 = 'publicProperty1'; $this->publicProperty2 = 'publicProperty2'; $this->protectedProperty0 = 'protectedProperty0'; $this->protectedProperty1 = 'protectedProperty1'; $this->protectedProperty2 = 'protectedProperty2'; static $cacheProxyManagerTestAsset_ClassWithMixedProperties; $cacheProxyManagerTestAsset_ClassWithMixedProperties ?? $cacheProxyManagerTestAsset_ClassWithMixedProperties = \Closure::bind(static function ($instance) { $instance->privateProperty0 = 'privateProperty0'; $instance->privateProperty1 = 'privateProperty1'; $instance->privateProperty2 = 'privateProperty2'; }, null, 'ProxyManagerTestAsset\\ClassWithMixedProperties'); $cacheProxyManagerTestAsset_ClassWithMixedProperties($this); $properties = [ 'publicProperty0' => & $this->publicProperty0, 'publicProperty1' => & $this->publicProperty1, 'publicProperty2' => & $this->publicProperty2, '' . "\0" . '*' . "\0" . 'protectedProperty0' => & $this->protectedProperty0, '' . "\0" . '*' . "\0" . 'protectedProperty1' => & $this->protectedProperty1, '' . "\0" . '*' . "\0" . 'protectedProperty2' => & $this->protectedProperty2, ]; static $cacheFetchProxyManagerTestAsset_ClassWithMixedProperties; $cacheFetchProxyManagerTestAsset_ClassWithMixedProperties ?? $cacheFetchProxyManagerTestAsset_ClassWithMixedProperties = \Closure::bind(function ($instance, array & $properties) { $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedProperties' . "\0" . 'privateProperty0'] = & $instance->privateProperty0; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedProperties' . "\0" . 'privateProperty1'] = & $instance->privateProperty1; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedProperties' . "\0" . 'privateProperty2'] = & $instance->privateProperty2; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedProperties'); $cacheFetchProxyManagerTestAsset_ClassWithMixedProperties($this, $properties); $result = $this->init->__invoke($this, $methodName, $parameters, $this->init, $properties); $this->track = false; return $result; PHP; self::assertSame( $expectedCode, $callInitializer->getBody() ); } /** * @requires PHP 7.4 */ public function testBodyStructureWithTypedProperties(): void { $initializer = $this->createMock(PropertyGenerator::class); $initializationTracker = $this->createMock(PropertyGenerator::class); $initializer->method('getName')->willReturn('init'); $initializationTracker->method('getName')->willReturn('track'); $callInitializer = new CallInitializer( $initializer, $initializationTracker, Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedTypedProperties::class)) ); $expectedCode = <<<'PHP' if ($this->track || ! $this->init) { return; } $this->track = true; $this->publicUnTypedProperty = 'publicUnTypedProperty'; $this->publicUnTypedPropertyWithoutDefaultValue = NULL; $this->publicBoolProperty = true; $this->publicNullableBoolProperty = true; $this->publicNullableBoolPropertyWithoutDefaultValue = NULL; $this->publicIntProperty = 123; $this->publicNullableIntProperty = 123; $this->publicNullableIntPropertyWithoutDefaultValue = NULL; $this->publicFloatProperty = 123.456; $this->publicNullableFloatProperty = 123.456; $this->publicNullableFloatPropertyWithoutDefaultValue = NULL; $this->publicStringProperty = 'publicStringProperty'; $this->publicNullableStringProperty = 'publicStringProperty'; $this->publicNullableStringPropertyWithoutDefaultValue = NULL; $this->publicArrayProperty = array ( 0 => 'publicArrayProperty', ); $this->publicNullableArrayProperty = array ( 0 => 'publicArrayProperty', ); $this->publicNullableArrayPropertyWithoutDefaultValue = NULL; $this->publicIterableProperty = array ( 0 => 'publicIterableProperty', ); $this->publicNullableIterableProperty = array ( 0 => 'publicIterableProperty', ); $this->publicNullableIterablePropertyWithoutDefaultValue = NULL; $this->publicNullableObjectProperty = NULL; $this->publicNullableClassProperty = NULL; $this->protectedUnTypedProperty = 'protectedUnTypedProperty'; $this->protectedUnTypedPropertyWithoutDefaultValue = NULL; $this->protectedBoolProperty = true; $this->protectedNullableBoolProperty = true; $this->protectedNullableBoolPropertyWithoutDefaultValue = NULL; $this->protectedIntProperty = 123; $this->protectedNullableIntProperty = 123; $this->protectedNullableIntPropertyWithoutDefaultValue = NULL; $this->protectedFloatProperty = 123.456; $this->protectedNullableFloatProperty = 123.456; $this->protectedNullableFloatPropertyWithoutDefaultValue = NULL; $this->protectedStringProperty = 'protectedStringProperty'; $this->protectedNullableStringProperty = 'protectedStringProperty'; $this->protectedNullableStringPropertyWithoutDefaultValue = NULL; $this->protectedArrayProperty = array ( 0 => 'protectedArrayProperty', ); $this->protectedNullableArrayProperty = array ( 0 => 'protectedArrayProperty', ); $this->protectedNullableArrayPropertyWithoutDefaultValue = NULL; $this->protectedIterableProperty = array ( 0 => 'protectedIterableProperty', ); $this->protectedNullableIterableProperty = array ( 0 => 'protectedIterableProperty', ); $this->protectedNullableIterablePropertyWithoutDefaultValue = NULL; $this->protectedNullableObjectProperty = NULL; $this->protectedNullableClassProperty = NULL; static $cacheProxyManagerTestAsset_ClassWithMixedTypedProperties; $cacheProxyManagerTestAsset_ClassWithMixedTypedProperties ?? $cacheProxyManagerTestAsset_ClassWithMixedTypedProperties = \Closure::bind(static function ($instance) { $instance->privateUnTypedProperty = 'privateUnTypedProperty'; $instance->privateUnTypedPropertyWithoutDefaultValue = NULL; $instance->privateBoolProperty = true; $instance->privateNullableBoolProperty = true; $instance->privateNullableBoolPropertyWithoutDefaultValue = NULL; $instance->privateIntProperty = 123; $instance->privateNullableIntProperty = 123; $instance->privateNullableIntPropertyWithoutDefaultValue = NULL; $instance->privateFloatProperty = 123.456; $instance->privateNullableFloatProperty = 123.456; $instance->privateNullableFloatPropertyWithoutDefaultValue = NULL; $instance->privateStringProperty = 'privateStringProperty'; $instance->privateNullableStringProperty = 'privateStringProperty'; $instance->privateNullableStringPropertyWithoutDefaultValue = NULL; $instance->privateArrayProperty = array ( 0 => 'privateArrayProperty', ); $instance->privateNullableArrayProperty = array ( 0 => 'privateArrayProperty', ); $instance->privateNullableArrayPropertyWithoutDefaultValue = NULL; $instance->privateIterableProperty = array ( 0 => 'privateIterableProperty', ); $instance->privateNullableIterableProperty = array ( 0 => 'privateIterableProperty', ); $instance->privateNullableIterablePropertyWithoutDefaultValue = NULL; $instance->privateNullableObjectProperty = NULL; $instance->privateNullableClassProperty = NULL; }, null, 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties'); $cacheProxyManagerTestAsset_ClassWithMixedTypedProperties($this); $properties = [ 'publicUnTypedProperty' => & $this->publicUnTypedProperty, 'publicUnTypedPropertyWithoutDefaultValue' => & $this->publicUnTypedPropertyWithoutDefaultValue, 'publicBoolProperty' => & $this->publicBoolProperty, 'publicNullableBoolProperty' => & $this->publicNullableBoolProperty, 'publicNullableBoolPropertyWithoutDefaultValue' => & $this->publicNullableBoolPropertyWithoutDefaultValue, 'publicIntProperty' => & $this->publicIntProperty, 'publicNullableIntProperty' => & $this->publicNullableIntProperty, 'publicNullableIntPropertyWithoutDefaultValue' => & $this->publicNullableIntPropertyWithoutDefaultValue, 'publicFloatProperty' => & $this->publicFloatProperty, 'publicNullableFloatProperty' => & $this->publicNullableFloatProperty, 'publicNullableFloatPropertyWithoutDefaultValue' => & $this->publicNullableFloatPropertyWithoutDefaultValue, 'publicStringProperty' => & $this->publicStringProperty, 'publicNullableStringProperty' => & $this->publicNullableStringProperty, 'publicNullableStringPropertyWithoutDefaultValue' => & $this->publicNullableStringPropertyWithoutDefaultValue, 'publicArrayProperty' => & $this->publicArrayProperty, 'publicNullableArrayProperty' => & $this->publicNullableArrayProperty, 'publicNullableArrayPropertyWithoutDefaultValue' => & $this->publicNullableArrayPropertyWithoutDefaultValue, 'publicIterableProperty' => & $this->publicIterableProperty, 'publicNullableIterableProperty' => & $this->publicNullableIterableProperty, 'publicNullableIterablePropertyWithoutDefaultValue' => & $this->publicNullableIterablePropertyWithoutDefaultValue, 'publicNullableObjectProperty' => & $this->publicNullableObjectProperty, 'publicNullableClassProperty' => & $this->publicNullableClassProperty, '' . "\0" . '*' . "\0" . 'protectedUnTypedProperty' => & $this->protectedUnTypedProperty, '' . "\0" . '*' . "\0" . 'protectedUnTypedPropertyWithoutDefaultValue' => & $this->protectedUnTypedPropertyWithoutDefaultValue, '' . "\0" . '*' . "\0" . 'protectedBoolProperty' => & $this->protectedBoolProperty, '' . "\0" . '*' . "\0" . 'protectedNullableBoolProperty' => & $this->protectedNullableBoolProperty, '' . "\0" . '*' . "\0" . 'protectedNullableBoolPropertyWithoutDefaultValue' => & $this->protectedNullableBoolPropertyWithoutDefaultValue, '' . "\0" . '*' . "\0" . 'protectedIntProperty' => & $this->protectedIntProperty, '' . "\0" . '*' . "\0" . 'protectedNullableIntProperty' => & $this->protectedNullableIntProperty, '' . "\0" . '*' . "\0" . 'protectedNullableIntPropertyWithoutDefaultValue' => & $this->protectedNullableIntPropertyWithoutDefaultValue, '' . "\0" . '*' . "\0" . 'protectedFloatProperty' => & $this->protectedFloatProperty, '' . "\0" . '*' . "\0" . 'protectedNullableFloatProperty' => & $this->protectedNullableFloatProperty, '' . "\0" . '*' . "\0" . 'protectedNullableFloatPropertyWithoutDefaultValue' => & $this->protectedNullableFloatPropertyWithoutDefaultValue, '' . "\0" . '*' . "\0" . 'protectedStringProperty' => & $this->protectedStringProperty, '' . "\0" . '*' . "\0" . 'protectedNullableStringProperty' => & $this->protectedNullableStringProperty, '' . "\0" . '*' . "\0" . 'protectedNullableStringPropertyWithoutDefaultValue' => & $this->protectedNullableStringPropertyWithoutDefaultValue, '' . "\0" . '*' . "\0" . 'protectedArrayProperty' => & $this->protectedArrayProperty, '' . "\0" . '*' . "\0" . 'protectedNullableArrayProperty' => & $this->protectedNullableArrayProperty, '' . "\0" . '*' . "\0" . 'protectedNullableArrayPropertyWithoutDefaultValue' => & $this->protectedNullableArrayPropertyWithoutDefaultValue, '' . "\0" . '*' . "\0" . 'protectedIterableProperty' => & $this->protectedIterableProperty, '' . "\0" . '*' . "\0" . 'protectedNullableIterableProperty' => & $this->protectedNullableIterableProperty, '' . "\0" . '*' . "\0" . 'protectedNullableIterablePropertyWithoutDefaultValue' => & $this->protectedNullableIterablePropertyWithoutDefaultValue, '' . "\0" . '*' . "\0" . 'protectedNullableObjectProperty' => & $this->protectedNullableObjectProperty, '' . "\0" . '*' . "\0" . 'protectedNullableClassProperty' => & $this->protectedNullableClassProperty, ]; static $cacheFetchProxyManagerTestAsset_ClassWithMixedTypedProperties; $cacheFetchProxyManagerTestAsset_ClassWithMixedTypedProperties ?? $cacheFetchProxyManagerTestAsset_ClassWithMixedTypedProperties = \Closure::bind(function ($instance, array & $properties) { $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateUnTypedProperty'] = & $instance->privateUnTypedProperty; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateUnTypedPropertyWithoutDefaultValue'] = & $instance->privateUnTypedPropertyWithoutDefaultValue; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateBoolProperty'] = & $instance->privateBoolProperty; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateNullableBoolProperty'] = & $instance->privateNullableBoolProperty; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateNullableBoolPropertyWithoutDefaultValue'] = & $instance->privateNullableBoolPropertyWithoutDefaultValue; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateIntProperty'] = & $instance->privateIntProperty; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateNullableIntProperty'] = & $instance->privateNullableIntProperty; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateNullableIntPropertyWithoutDefaultValue'] = & $instance->privateNullableIntPropertyWithoutDefaultValue; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateFloatProperty'] = & $instance->privateFloatProperty; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateNullableFloatProperty'] = & $instance->privateNullableFloatProperty; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateNullableFloatPropertyWithoutDefaultValue'] = & $instance->privateNullableFloatPropertyWithoutDefaultValue; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateStringProperty'] = & $instance->privateStringProperty; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateNullableStringProperty'] = & $instance->privateNullableStringProperty; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateNullableStringPropertyWithoutDefaultValue'] = & $instance->privateNullableStringPropertyWithoutDefaultValue; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateArrayProperty'] = & $instance->privateArrayProperty; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateNullableArrayProperty'] = & $instance->privateNullableArrayProperty; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateNullableArrayPropertyWithoutDefaultValue'] = & $instance->privateNullableArrayPropertyWithoutDefaultValue; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateIterableProperty'] = & $instance->privateIterableProperty; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateNullableIterableProperty'] = & $instance->privateNullableIterableProperty; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateNullableIterablePropertyWithoutDefaultValue'] = & $instance->privateNullableIterablePropertyWithoutDefaultValue; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateNullableObjectProperty'] = & $instance->privateNullableObjectProperty; $properties['' . "\0" . 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties' . "\0" . 'privateNullableClassProperty'] = & $instance->privateNullableClassProperty; }, $this, 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties'); $cacheFetchProxyManagerTestAsset_ClassWithMixedTypedProperties($this, $properties); $result = $this->init->__invoke($this, $methodName, $parameters, $this->init, $properties); $this->track = false; return $result; PHP; self::assertSame( $expectedCode, $callInitializer->getBody() ); } } GetProxyInitializerTest.php000066400000000000000000000022761407505032400410140ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/MethodGeneratorcreateMock(PropertyGenerator::class); $initializer->method('getName')->willReturn('foo'); $getter = new GetProxyInitializer($initializer); self::assertEquals(TypeGenerator::fromTypeString('?\Closure'), $getter->getReturnType()); self::assertSame('getProxyInitializer', $getter->getName()); self::assertCount(0, $getter->getParameters()); self::assertSame('return $this->foo;', $getter->getBody()); } } InitializeProxyTest.php000066400000000000000000000026561407505032400401740ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/MethodGeneratorcreateMock(PropertyGenerator::class); $initCall = $this->createMock(MethodGenerator::class); $initializer->method('getName')->willReturn('foo'); $initCall->method('getName')->willReturn('bar'); $initializeProxy = new InitializeProxy($initializer, $initCall); self::assertSame('initializeProxy', $initializeProxy->getName()); self::assertCount(0, $initializeProxy->getParameters()); self::assertSame( 'return $this->foo && $this->bar(\'initializeProxy\', []);', $initializeProxy->getBody() ); self::assertStringMatchesFormat('%A : bool%A', $initializeProxy->generate(), 'Return type hint is boolean'); } } IsProxyInitializedTest.php000066400000000000000000000023261407505032400406260ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/MethodGeneratorcreateMock(PropertyGenerator::class); $initializer->method('getName')->willReturn('foo'); $isProxyInitialized = new IsProxyInitialized($initializer); self::assertSame('isProxyInitialized', $isProxyInitialized->getName()); self::assertCount(0, $isProxyInitialized->getParameters()); self::assertSame('return ! $this->foo;', $isProxyInitialized->getBody()); self::assertStringMatchesFormat('%A : bool%A', $isProxyInitialized->generate(), 'Return type hint is boolean'); } } MagicCloneTest.php000066400000000000000000000025741407505032400370310ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/MethodGeneratorcreateMock(PropertyGenerator::class); $initCall = $this->createMock(MethodGenerator::class); $initializer->method('getName')->willReturn('foo'); $initCall->method('getName')->willReturn('bar'); $magicClone = new MagicClone($reflection, $initializer, $initCall); self::assertSame('__clone', $magicClone->getName()); self::assertCount(0, $magicClone->getParameters()); self::assertSame( "\$this->foo && \$this->bar('__clone', []);", $magicClone->getBody() ); } } MagicGetTest.php000066400000000000000000000135761407505032400365140ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/MethodGeneratorfoo && ! $this->init && $this->baz('__get', array('name' => $name)); if (isset(self::$bar[$name])) { return $this->$name; } if (isset(self::$baz[$name])) { if ($this->init) { 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::$baz[$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::$tab[$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::$tab[$name][$class])) { $cacheKey = $class . '#' . $name; $accessor = isset($accessorCache[$cacheKey]) ? $accessorCache[$cacheKey] : $accessorCache[$cacheKey] = \Closure::bind(static function & ($instance) use ($name) { return $instance->$name; }, null, $class); return $accessor($this); } if ($this->init || 'ReflectionProperty' === $class) { $tmpClass = key(self::$tab[$name]); $cacheKey = $tmpClass . '#' . $name; $accessor = isset($accessorCache[$cacheKey]) ? $accessorCache[$cacheKey] : $accessorCache[$cacheKey] = \Closure::bind(static function & ($instance) use ($name) { return $instance->$name; }, null, $tmpClass); return $accessor($this); } } %a PHP; protected function setUp(): void { $this->initializer = $this->createMock(PropertyGenerator::class); $this->initMethod = $this->createMock(MethodGenerator::class); $this->publicProperties = $this->createMock(PublicPropertiesMap::class); $this->protectedProperties = $this->createMock(ProtectedPropertiesMap::class); $this->privateProperties = $this->createMock(PrivatePropertiesMap::class); $this->initializationTracker = $this->createMock(InitializationTracker::class); $this->initializer->method('getName')->willReturn('foo'); $this->initMethod->method('getName')->willReturn('baz'); $this->publicProperties->method('isEmpty')->willReturn(false); $this->publicProperties->method('getName')->willReturn('bar'); $this->protectedProperties->method('getName')->willReturn('baz'); $this->privateProperties->method('getName')->willReturn('tab'); $this->initializationTracker->method('getName')->willReturn('init'); } /** * @covers \ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicGet */ public function testBodyStructure(): void { $magicGet = new MagicGet( new ReflectionClass(BaseClass::class), $this->initializer, $this->initMethod, $this->publicProperties, $this->protectedProperties, $this->privateProperties, $this->initializationTracker ); self::assertSame('__get', $magicGet->getName()); self::assertCount(1, $magicGet->getParameters()); self::assertStringMatchesFormat($this->expectedCode, $magicGet->getBody()); } /** * @covers \ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicGet */ public function testBodyStructureWithOverriddenMagicGet(): void { $magicGet = new MagicGet( new ReflectionClass(ClassWithMagicMethods::class), $this->initializer, $this->initMethod, $this->publicProperties, $this->protectedProperties, $this->privateProperties, $this->initializationTracker ); self::assertSame('__get', $magicGet->getName()); self::assertCount(1, $magicGet->getParameters()); self::assertStringMatchesFormat($this->expectedCode, $magicGet->getBody()); self::assertStringMatchesFormat('%Areturn parent::__get($name);', $magicGet->getBody()); } } MagicIssetTest.php000066400000000000000000000127421407505032400370560ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/MethodGeneratorfoo && $this->baz('__isset', array('name' => $name)); if (isset(self::$bar[$name])) { return isset($this->$name); } if (isset(self::$baz[$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::$baz[$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::$tab[$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::$tab[$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); } } %A PHP; protected function setUp(): void { $this->initializer = $this->createMock(PropertyGenerator::class); $this->initMethod = $this->createMock(MethodGenerator::class); $this->publicProperties = $this->createMock(PublicPropertiesMap::class); $this->protectedProperties = $this->createMock(ProtectedPropertiesMap::class); $this->privateProperties = $this->createMock(PrivatePropertiesMap::class); $this->initializer->method('getName')->willReturn('foo'); $this->initMethod->method('getName')->willReturn('baz'); $this->publicProperties->method('isEmpty')->willReturn(false); $this->publicProperties->method('getName')->willReturn('bar'); $this->protectedProperties->method('getName')->willReturn('baz'); $this->privateProperties->method('getName')->willReturn('tab'); } /** * @covers \ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicIsset */ public function testBodyStructureWithPublicProperties(): void { $magicIsset = new MagicIsset( new ReflectionClass(ClassWithTwoPublicProperties::class), $this->initializer, $this->initMethod, $this->publicProperties, $this->protectedProperties, $this->privateProperties ); self::assertSame('__isset', $magicIsset->getName()); self::assertCount(1, $magicIsset->getParameters()); self::assertStringMatchesFormat($this->expectedCode, $magicIsset->getBody()); } /** * @covers \ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicIsset */ public function testBodyStructureWithOverriddenMagicGet(): void { $magicIsset = new MagicIsset( new ReflectionClass(ClassWithMagicMethods::class), $this->initializer, $this->initMethod, $this->publicProperties, $this->protectedProperties, $this->privateProperties ); self::assertSame('__isset', $magicIsset->getName()); self::assertCount(1, $magicIsset->getParameters()); $body = $magicIsset->getBody(); self::assertStringMatchesFormat($this->expectedCode, $body); self::assertStringMatchesFormat('%Areturn parent::__isset($name);', $body); } } MagicSetTest.php000066400000000000000000000130021407505032400365100ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/MethodGeneratorfoo && $this->baz('__set', array('name' => $name, 'value' => $value)); if (isset(self::$bar[$name])) { return ($this->$name = $value); } if (isset(self::$baz[$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::$baz[$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::$tab[$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::$tab[$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::$tab[$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); } } %a PHP; protected function setUp(): void { $this->initializer = $this->createMock(PropertyGenerator::class); $this->initMethod = $this->createMock(MethodGenerator::class); $this->publicProperties = $this->createMock(PublicPropertiesMap::class); $this->protectedProperties = $this->createMock(ProtectedPropertiesMap::class); $this->privateProperties = $this->createMock(PrivatePropertiesMap::class); $this->initializer->method('getName')->willReturn('foo'); $this->initMethod->method('getName')->willReturn('baz'); $this->publicProperties->method('isEmpty')->willReturn(false); $this->publicProperties->method('getName')->willReturn('bar'); $this->protectedProperties->method('getName')->willReturn('baz'); $this->privateProperties->method('getName')->willReturn('tab'); } /** * @covers \ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicSet::__construct */ public function testBodyStructure(): void { $magicSet = new MagicSet( new ReflectionClass(EmptyClass::class), $this->initializer, $this->initMethod, $this->publicProperties, $this->protectedProperties, $this->privateProperties ); self::assertSame('__set', $magicSet->getName()); self::assertCount(2, $magicSet->getParameters()); self::assertStringMatchesFormat($this->expectedCode, $magicSet->getBody()); } /** * @covers \ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicSet::__construct */ public function testBodyStructureWithOverriddenMagicGet(): void { $magicSet = new MagicSet( new ReflectionClass(ClassWithMagicMethods::class), $this->initializer, $this->initMethod, $this->publicProperties, $this->protectedProperties, $this->privateProperties ); self::assertSame('__set', $magicSet->getName()); self::assertCount(2, $magicSet->getParameters()); $body = $magicSet->getBody(); self::assertStringMatchesFormat($this->expectedCode, $body); self::assertStringMatchesFormat('%Areturn parent::__set($name, $value);', $body); } } MagicSleepTest.php000066400000000000000000000026671407505032400370440ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/MethodGeneratorcreateMock(PropertyGenerator::class); $initMethod = $this->createMock(MethodGenerator::class); $initializer->method('getName')->willReturn('foo'); $initMethod->method('getName')->willReturn('bar'); $magicSleep = new MagicSleep($reflection, $initializer, $initMethod); self::assertSame('__sleep', $magicSleep->getName()); self::assertCount(0, $magicSleep->getParameters()); self::assertSame( "\$this->foo && \$this->bar('__sleep', []);" . "\n\nreturn array_keys((array) \$this);", $magicSleep->getBody() ); } } MagicUnsetTest.php000066400000000000000000000130631407505032400370620ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/MethodGeneratorfoo && $this->baz('__unset', array('name' => $name)); if (isset(self::$bar[$name])) { unset($this->$name); return; } if (isset(self::$baz[$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::$baz[$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::$tab[$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::$tab[$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::$tab[$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); } } %A PHP; protected function setUp(): void { $this->initializer = $this->createMock(PropertyGenerator::class); $this->initMethod = $this->createMock(MethodGenerator::class); $this->publicProperties = $this->createMock(PublicPropertiesMap::class); $this->protectedProperties = $this->createMock(ProtectedPropertiesMap::class); $this->privateProperties = $this->createMock(PrivatePropertiesMap::class); $this->initializer->method('getName')->willReturn('foo'); $this->initMethod->method('getName')->willReturn('baz'); $this->publicProperties->method('isEmpty')->willReturn(false); $this->publicProperties->method('getName')->willReturn('bar'); $this->protectedProperties->method('getName')->willReturn('baz'); $this->privateProperties->method('getName')->willReturn('tab'); } /** * @covers \ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicUnset::__construct */ public function testBodyStructure(): void { $magicIsset = new MagicUnset( new ReflectionClass(ClassWithTwoPublicProperties::class), $this->initializer, $this->initMethod, $this->publicProperties, $this->protectedProperties, $this->privateProperties ); self::assertSame('__unset', $magicIsset->getName()); self::assertCount(1, $magicIsset->getParameters()); self::assertStringMatchesFormat($this->expectedCode, $magicIsset->getBody()); } /** * @covers \ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicUnset::__construct */ public function testBodyStructureWithOverriddenMagicGet(): void { $magicIsset = new MagicUnset( new ReflectionClass(ClassWithMagicMethods::class), $this->initializer, $this->initMethod, $this->publicProperties, $this->protectedProperties, $this->privateProperties ); self::assertSame('__unset', $magicIsset->getName()); self::assertCount(1, $magicIsset->getParameters()); $body = $magicIsset->getBody(); self::assertStringMatchesFormat($this->expectedCode, $body); self::assertStringMatchesFormat('%Areturn parent::__unset($name);', $body); } } SetProxyInitializerTest.php000066400000000000000000000026471407505032400410320ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/MethodGeneratorcreateMock(PropertyGenerator::class); $initializer->method('getName')->willReturn('foo'); $setter = new SetProxyInitializer($initializer); $parameters = $setter->getParameters(); self::assertSame('setProxyInitializer', $setter->getName()); self::assertCount(1, $parameters); $initializer = array_shift($parameters); self::assertSame('initializer', $initializer->getName()); self::assertSame('$this->foo = $initializer;', $setter->getBody()); self::assertEquals(TypeGenerator::fromTypeString('void'), $setter->getReturnType()); } } PropertyGenerator/000077500000000000000000000000001407505032400340535ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhostInitializationTrackerTest.php000066400000000000000000000020001407505032400417170ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/PropertyGeneratorcreateProperty() ->getDefaultValue(); self::assertNotNull($defaultValue); self::assertFalse($defaultValue->getValue()); } } InitializerPropertyTest.php000066400000000000000000000013621407505032400414560ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/PropertyGeneratorgetDefaultValue(); self::assertNotNull($defaultValue); self::assertSame( [ 'privateProperty0' => [ClassWithMixedProperties::class => true], 'privateProperty1' => [ClassWithMixedProperties::class => true], 'privateProperty2' => [ClassWithMixedProperties::class => true], ], $defaultValue->getValue() ); } public function testSkipsAbstractProtectedMethods(): void { $defaultValue = (new PrivatePropertiesMap( Properties::fromReflectionClass(new ReflectionClass(ClassWithAbstractProtectedMethod::class)) ))->getDefaultValue(); self::assertNotNull($defaultValue); self::assertSame([], $defaultValue->getValue()); } public function testIsStaticPrivate(): void { $map = $this->createProperty(); self::assertTrue($map->isStatic()); self::assertSame(ProtectedPropertiesMap::VISIBILITY_PRIVATE, $map->getVisibility()); } } ProtectedPropertiesMapTest.php000066400000000000000000000043571407505032400421010ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhost/PropertyGeneratorgetDefaultValue(); self::assertNotNull($defaultValue); self::assertSame( [ 'protectedProperty0' => ClassWithMixedProperties::class, 'protectedProperty1' => ClassWithMixedProperties::class, 'protectedProperty2' => ClassWithMixedProperties::class, ], $defaultValue->getValue() ); } public function testSkipsAbstractProtectedMethods(): void { $defaultValue = (new ProtectedPropertiesMap( Properties::fromReflectionClass(new ReflectionClass(ClassWithAbstractProtectedMethod::class)) ))->getDefaultValue(); self::assertNotNull($defaultValue); self::assertSame([], $defaultValue->getValue()); } public function testIsStaticPrivate(): void { $map = $this->createProperty(); self::assertTrue($map->isStatic()); self::assertSame(ProtectedPropertiesMap::VISIBILITY_PRIVATE, $map->getVisibility()); } } LazyLoadingGhostGeneratorTest.php000066400000000000000000000044721407505032400336070ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGeneratorisInterface()) { // @todo interfaces *may* be proxied by deferring property localization to the constructor (no hardcoding) $this->expectException(InvalidProxiedClassException::class); } parent::testGeneratesValidCode($className); } public function testWillRejectInterfaces(): void { $this->expectException(InvalidProxiedClassException::class); $this ->getProxyGenerator() ->generate(new ReflectionClass(BaseInterface::class), new ClassGenerator()); } public function testAllAbstractMethodsWillBeMadeConcrete(): void { $classGenerator = new ClassGenerator(); $this ->getProxyGenerator() ->generate(new ReflectionClass(ClassWithAbstractPublicMethod::class), $classGenerator); foreach ($classGenerator->getMethods() as $method) { self::assertFalse($method->isAbstract()); } } protected function getProxyGenerator(): ProxyGeneratorInterface { return new LazyLoadingGhostGenerator(); } /** * {@inheritDoc} */ protected function getExpectedImplementedInterfaces(): array { return [GhostObjectInterface::class]; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolder/000077500000000000000000000000001407505032400315655ustar00rootroot00000000000000MethodGenerator/000077500000000000000000000000001407505032400345755ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolderGetProxyInitializerTest.php000066400000000000000000000023261407505032400421360ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $initializer->method('getName')->willReturn('foo'); $getter = new GetProxyInitializer($initializer); self::assertEquals(TypeGenerator::fromTypeString('?\Closure'), $getter->getReturnType()); self::assertSame('getProxyInitializer', $getter->getName()); self::assertCount(0, $getter->getParameters()); self::assertSame('return $this->foo;', $getter->getBody()); } } InitializeProxyTest.php000066400000000000000000000027671407505032400413250ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $initializer->method('getName')->willReturn('foo'); $valueHolder->method('getName')->willReturn('bar'); $initializeProxy = new InitializeProxy($initializer, $valueHolder); self::assertSame('initializeProxy', $initializeProxy->getName()); self::assertCount(0, $initializeProxy->getParameters()); self::assertSame( 'return $this->foo && ($this->foo->__invoke($bar, $this, \'initializeProxy\', array(), $this->foo) || 1)' . ' && $this->bar = $bar;', $initializeProxy->getBody() ); self::assertStringMatchesFormat('%A : bool%A', $initializeProxy->generate(), 'Return type hint is boolean'); } } IsProxyInitializedTest.php000066400000000000000000000023651407505032400417570ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $valueHolder->method('getName')->willReturn('bar'); $isProxyInitialized = new IsProxyInitialized($valueHolder); self::assertSame('isProxyInitialized', $isProxyInitialized->getName()); self::assertCount(0, $isProxyInitialized->getParameters()); self::assertSame('return null !== $this->bar;', $isProxyInitialized->getBody()); self::assertStringMatchesFormat('%A : bool%A', $isProxyInitialized->generate(), 'Return type hint is boolean'); } } LazyLoadingMethodInterceptorTest.php000066400000000000000000000055611407505032400437520ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $initializer->method('getName')->willReturn('foo'); $valueHolder->method('getName')->willReturn('bar'); $reflection = new MethodReflection(BaseClass::class, 'publicByReferenceParameterMethod'); $method = LazyLoadingMethodInterceptor::generateMethod($reflection, $initializer, $valueHolder); self::assertSame('publicByReferenceParameterMethod', $method->getName()); self::assertCount(2, $method->getParameters()); self::assertSame( "\$this->foo && (\$this->foo->__invoke(\$bar, \$this, 'publicByReferenceParameterMethod', " . "array('param' => \$param, 'byRefParam' => \$byRefParam), \$this->foo) || 1) && \$this->bar = \$bar;\n\n" . 'return $this->bar->publicByReferenceParameterMethod($param, $byRefParam);', $method->getBody() ); } /** * @covers \ProxyManager\ProxyGenerator\LazyLoadingValueHolder\MethodGenerator\LazyLoadingMethodInterceptor */ public function testBodyStructureWithoutParameters(): void { $reflectionMethod = new MethodReflection(BaseClass::class, 'publicMethod'); $initializer = $this->createMock(PropertyGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $initializer->method('getName')->willReturn('foo'); $valueHolder->method('getName')->willReturn('bar'); $initializer->method('getName')->willReturn('foo'); $method = LazyLoadingMethodInterceptor::generateMethod($reflectionMethod, $initializer, $valueHolder); self::assertSame('publicMethod', $method->getName()); self::assertCount(0, $method->getParameters()); self::assertSame( '$this->foo && ($this->foo->__invoke($bar, $this, ' . "'publicMethod', array(), \$this->foo) || 1) && \$this->bar = \$bar;\n\n" . 'return $this->bar->publicMethod();', $method->getBody() ); } } MagicCloneTest.php000066400000000000000000000027521407505032400401550ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $initializer->method('getName')->willReturn('foo'); $valueHolder->method('getName')->willReturn('bar'); $magicClone = new MagicClone($reflection, $initializer, $valueHolder); self::assertSame('__clone', $magicClone->getName()); self::assertCount(0, $magicClone->getParameters()); self::assertSame( '$this->foo && ($this->foo->__invoke($bar, $this, ' . "'__clone', array(), \$this->foo) || 1) && \$this->bar = \$bar;\n\n\$this->bar = clone \$this->bar;", $magicClone->getBody() ); } } MagicGetTest.php000066400000000000000000000065421407505032400376350ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $publicProperties = $this->createMock(PublicPropertiesMap::class); $initializer->method('getName')->willReturn('foo'); $valueHolder->method('getName')->willReturn('bar'); $publicProperties->method('isEmpty')->willReturn(false); $publicProperties->method('getName')->willReturn('bar'); $magicGet = new MagicGet($reflection, $initializer, $valueHolder, $publicProperties); self::assertSame('__get', $magicGet->getName()); self::assertCount(1, $magicGet->getParameters()); self::assertStringMatchesFormat( "\$this->foo && (\$this->foo->__invoke(\$bar, \$this, '__get', ['name' => \$name]" . ", \$this->foo) || 1) && \$this->bar = \$bar;\n\n" . "if (isset(self::\$bar[\$name])) {\n return \$this->bar->\$name;\n}" . '%areturn %s;', $magicGet->getBody() ); self::assertStringNotMatchesFormat('%Areturn $this->bar->__get($name);%A', $magicGet->getBody()); } /** * @group 344 */ public function testBodyStructureWithPreExistingGetMethod(): void { $reflection = new ReflectionClass(ClassWithMagicMethods::class); $initializer = $this->createMock(PropertyGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $publicProperties = $this->createMock(PublicPropertiesMap::class); $initializer->method('getName')->willReturn('foo'); $valueHolder->method('getName')->willReturn('bar'); $publicProperties->method('isEmpty')->willReturn(false); $publicProperties->method('getName')->willReturn('bar'); $magicGet = new MagicGet($reflection, $initializer, $valueHolder, $publicProperties); self::assertSame('__get', $magicGet->getName()); self::assertCount(1, $magicGet->getParameters()); self::assertStringMatchesFormat( "\$this->foo && (\$this->foo->__invoke(\$bar, \$this, '__get', ['name' => \$name]" . ", \$this->foo) || 1) && \$this->bar = \$bar;\n\n" . "if (isset(self::\$bar[\$name])) {\n return \$this->bar->\$name;\n}\n\n" . 'return $this->bar->__get($name);', $magicGet->getBody(), 'The pre-existing magic `__get` is called, if the property is not accessible' ); } } MagicIssetTest.php000066400000000000000000000036351407505032400402050ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $publicProperties = $this->createMock(PublicPropertiesMap::class); $initializer->method('getName')->willReturn('foo'); $valueHolder->method('getName')->willReturn('bar'); $publicProperties->method('isEmpty')->willReturn(false); $publicProperties->method('getName')->willReturn('bar'); $magicIsset = new MagicIsset($reflection, $initializer, $valueHolder, $publicProperties); self::assertSame('__isset', $magicIsset->getName()); self::assertCount(1, $magicIsset->getParameters()); self::assertStringMatchesFormat( "\$this->foo && (\$this->foo->__invoke(\$bar, \$this, '__isset', array('name' => \$name)" . ", \$this->foo) || 1) && \$this->bar = \$bar;\n\n" . "if (isset(self::\$bar[\$name])) {\n return isset(\$this->bar->\$name);\n}" . '%areturn %s;', $magicIsset->getBody() ); } } MagicSetTest.php000066400000000000000000000064461407505032400376540ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $publicProperties = $this->createMock(PublicPropertiesMap::class); $initializer->method('getName')->willReturn('foo'); $valueHolder->method('getName')->willReturn('bar'); $publicProperties->method('isEmpty')->willReturn(false); $publicProperties->method('getName')->willReturn('bar'); $magicSet = new MagicSet($reflection, $initializer, $valueHolder, $publicProperties); self::assertSame('__set', $magicSet->getName()); self::assertCount(2, $magicSet->getParameters()); self::assertStringMatchesFormat( '$this->foo && ($this->foo->__invoke($bar, $this, ' . "'__set', array('name' => \$name, 'value' => \$value), \$this->foo) || 1) && \$this->bar = \$bar;\n\n" . "if (isset(self::\$bar[\$name])) {\n return (\$this->bar->\$name = \$value);\n}" . '%areturn %s;', $magicSet->getBody() ); } /** * @group 344 */ public function testBodyStructureWithPreExistingMagicMethod(): void { $reflection = new ReflectionClass(ClassWithMagicMethods::class); $initializer = $this->createMock(PropertyGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $publicProperties = $this->createMock(PublicPropertiesMap::class); $initializer->method('getName')->willReturn('foo'); $valueHolder->method('getName')->willReturn('bar'); $publicProperties->method('isEmpty')->willReturn(false); $publicProperties->method('getName')->willReturn('bar'); $magicSet = new MagicSet($reflection, $initializer, $valueHolder, $publicProperties); self::assertSame('__set', $magicSet->getName()); self::assertCount(2, $magicSet->getParameters()); self::assertStringMatchesFormat( '$this->foo && ($this->foo->__invoke($bar, $this, ' . "'__set', array('name' => \$name, 'value' => \$value), \$this->foo) || 1) && \$this->bar = \$bar;\n\n" . "if (isset(self::\$bar[\$name])) {\n return (\$this->bar->\$name = \$value);\n}\n\n" . 'return $this->bar->__set($name, $value);', $magicSet->getBody(), 'Execution is deferred to pre-existing `__set` if the property is not accessible' ); } } MagicSleepTest.php000066400000000000000000000027421407505032400401640ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $initializer->method('getName')->willReturn('foo'); $valueHolder->method('getName')->willReturn('bar'); $magicSleep = new MagicSleep($reflection, $initializer, $valueHolder); self::assertSame('__sleep', $magicSleep->getName()); self::assertCount(0, $magicSleep->getParameters()); self::assertSame( "\$this->foo && (\$this->foo->__invoke(\$bar, \$this, '__sleep', array(), \$this->foo) || 1)" . " && \$this->bar = \$bar;\n\nreturn array('bar');", $magicSleep->getBody() ); } } MagicUnsetTest.php000066400000000000000000000064361407505032400402160ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $publicProperties = $this->createMock(PublicPropertiesMap::class); $initializer->method('getName')->willReturn('foo'); $valueHolder->method('getName')->willReturn('bar'); $publicProperties->method('isEmpty')->willReturn(false); $publicProperties->method('getName')->willReturn('bar'); $magicIsset = new MagicUnset($reflection, $initializer, $valueHolder, $publicProperties); self::assertSame('__unset', $magicIsset->getName()); self::assertCount(1, $magicIsset->getParameters()); self::assertStringMatchesFormat( "\$this->foo && (\$this->foo->__invoke(\$bar, \$this, '__unset', array('name' => \$name)" . ", \$this->foo) || 1) && \$this->bar = \$bar;\n\n" . "if (isset(self::\$bar[\$name])) {\n unset(\$this->bar->\$name);\n\n return;\n}" . '%a', $magicIsset->getBody() ); } /** * @group 344 */ public function testBodyStructureWithPreExistingMagicMethod(): void { $reflection = new ReflectionClass(ClassWithMagicMethods::class); $initializer = $this->createMock(PropertyGenerator::class); $valueHolder = $this->createMock(PropertyGenerator::class); $publicProperties = $this->createMock(PublicPropertiesMap::class); $initializer->method('getName')->willReturn('foo'); $valueHolder->method('getName')->willReturn('bar'); $publicProperties->method('isEmpty')->willReturn(false); $publicProperties->method('getName')->willReturn('bar'); $magicIsset = new MagicUnset($reflection, $initializer, $valueHolder, $publicProperties); self::assertSame('__unset', $magicIsset->getName()); self::assertCount(1, $magicIsset->getParameters()); self::assertStringMatchesFormat( "\$this->foo && (\$this->foo->__invoke(\$bar, \$this, '__unset', array('name' => \$name)" . ", \$this->foo) || 1) && \$this->bar = \$bar;\n\n" . "if (isset(self::\$bar[\$name])) {\n unset(\$this->bar->\$name);\n\n return;\n}\n\n" . 'return $this->bar->__unset($name);', $magicIsset->getBody(), 'The pre-existing magic `__unset` is called, if the property is not accessible' ); } } SetProxyInitializerTest.php000066400000000000000000000030101407505032400421410ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $initializer->method('getName')->willReturn('foo'); $setter = new SetProxyInitializer($initializer); $parameters = $setter->getParameters(); self::assertSame('setProxyInitializer', $setter->getName()); self::assertCount(1, $parameters); $initializer = array_shift($parameters); self::assertInstanceOf(ParameterGenerator::class, $initializer); self::assertSame('initializer', $initializer->getName()); self::assertSame('$this->foo = $initializer;', $setter->getBody()); self::assertEquals(TypeGenerator::fromTypeString('void'), $setter->getReturnType()); } } PropertyGenerator/000077500000000000000000000000001407505032400352015ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolderInitializerPropertyTest.php000066400000000000000000000014121407505032400426000ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/LazyLoadingValueHolder/PropertyGeneratorgetDocBlock(); self::assertNotNull($docBlock); self::assertEquals( <<<'PHPDOC' /** * @var \ProxyManagerTest\ProxyGenerator\LazyLoadingValueHolder\PropertyGenerator\ValueHolderPropertyTest|null wrapped object, if the proxy is initialized */ PHPDOC , $docBlock->generate() ); } } LazyLoadingValueHolderGeneratorTest.php000066400000000000000000000014541407505032400347320ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGeneratorgetName()); self::assertCount(2, $method->getParameters()); self::assertSame('', $method->getBody()); } /** * @covers \ProxyManager\ProxyGenerator\NullObject\MethodGenerator\NullObjectMethodInterceptor */ public function testBodyStructureWithoutParameters(): void { $reflectionMethod = new MethodReflection(self::class, 'testBodyStructureWithoutParameters'); $method = NullObjectMethodInterceptor::generateMethod($reflectionMethod); self::assertSame('testBodyStructureWithoutParameters', $method->getName()); self::assertCount(0, $method->getParameters()); self::assertSame('', $method->getBody()); } /** * @covers \ProxyManager\ProxyGenerator\NullObject\MethodGenerator\NullObjectMethodInterceptor */ public function testBodyStructureWithoutByRefReturn(): void { $reflectionMethod = new MethodReflection(BaseClass::class, 'publicByReferenceMethod'); $method = NullObjectMethodInterceptor::generateMethod($reflectionMethod); self::assertSame('publicByReferenceMethod', $method->getName()); self::assertCount(0, $method->getParameters()); self::assertStringMatchesFormat("\$ref%s = null;\nreturn \$ref%s;", $method->getBody()); } } StaticProxyConstructorTest.php000066400000000000000000000076671407505032400404160ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/NullObject/MethodGeneratorgetName()); self::assertSame(ClassWithMixedProperties::class, (string) $constructor->getReturnType()); self::assertTrue($constructor->isStatic()); self::assertSame('public', $constructor->getVisibility()); self::assertCount(0, $constructor->getParameters()); self::assertSame( 'static $reflection; $reflection = $reflection ?? new \ReflectionClass(__CLASS__); $instance = $reflection->newInstanceWithoutConstructor(); $instance->publicProperty0 = null; $instance->publicProperty1 = null; $instance->publicProperty2 = null; return $instance;', $constructor->getBody() ); } public function testBodyStructureWithoutPublicProperties(): void { $constructor = new StaticProxyConstructor( new ReflectionClass(ClassWithPrivateProperties::class) ); self::assertSame('staticProxyConstructor', $constructor->getName()); self::assertCount(0, $constructor->getParameters()); self::assertSame(ClassWithPrivateProperties::class, (string) $constructor->getReturnType()); $body = $constructor->getBody(); self::assertSame( 'static $reflection; $reflection = $reflection ?? new \ReflectionClass(__CLASS__); $instance = $reflection->newInstanceWithoutConstructor(); return $instance;', $body ); } /** * @requires PHP 7.4 */ public function testBodyStructureWithTypedProperties(): void { $constructor = new StaticProxyConstructor(new ReflectionClass(ClassWithMixedTypedProperties::class)); self::assertSame('staticProxyConstructor', $constructor->getName()); self::assertSame(ClassWithMixedTypedProperties::class, (string) $constructor->getReturnType()); self::assertTrue($constructor->isStatic()); self::assertSame('public', $constructor->getVisibility()); self::assertCount(0, $constructor->getParameters()); self::assertSame( 'static $reflection; $reflection = $reflection ?? new \ReflectionClass(__CLASS__); $instance = $reflection->newInstanceWithoutConstructor(); $instance->publicUnTypedProperty = null; $instance->publicUnTypedPropertyWithoutDefaultValue = null; $instance->publicNullableBoolProperty = null; $instance->publicNullableBoolPropertyWithoutDefaultValue = null; $instance->publicNullableIntProperty = null; $instance->publicNullableIntPropertyWithoutDefaultValue = null; $instance->publicNullableFloatProperty = null; $instance->publicNullableFloatPropertyWithoutDefaultValue = null; $instance->publicNullableStringProperty = null; $instance->publicNullableStringPropertyWithoutDefaultValue = null; $instance->publicNullableArrayProperty = null; $instance->publicNullableArrayPropertyWithoutDefaultValue = null; $instance->publicNullableIterableProperty = null; $instance->publicNullableIterablePropertyWithoutDefaultValue = null; $instance->publicNullableObjectProperty = null; $instance->publicNullableClassProperty = null; return $instance;', $constructor->getBody() ); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/NullObjectGeneratorTest.php000066400000000000000000000106431407505032400325020ustar00rootroot00000000000000getProxyGenerator(); $generatedClassName = UniqueIdentifierGenerator::getIdentifier('AbstractProxyGeneratorTest'); $generatedClass = new ClassGenerator($generatedClassName); $originalClass = new ReflectionClass($className); $generatorStrategy = new EvaluatingGeneratorStrategy(); $generator->generate($originalClass, $generatedClass); $generatorStrategy->generate($generatedClass); $generatedReflection = new ReflectionClass($generatedClassName); if ($originalClass->isInterface()) { self::assertTrue($generatedReflection->implementsInterface($className)); } self::assertSame($generatedClassName, $generatedReflection->getName()); foreach ($this->getExpectedImplementedInterfaces() as $interface) { self::assertTrue($generatedReflection->implementsInterface($interface)); } /** * @psalm-suppress InvalidStringClass * @psalm-suppress MixedAssignment * @psalm-suppress MixedMethodCall */ $proxy = $generatedClassName::staticProxyConstructor(); self::assertInstanceOf($className, $proxy); foreach ( Properties::fromReflectionClass($generatedReflection) ->onlyNullableProperties() ->getPublicProperties() as $property ) { /** @psalm-suppress MixedPropertyFetch */ self::assertNull($proxy->{$property->getName()}); } foreach ($generatedReflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { if ($method->getNumberOfParameters() || $method->isStatic()) { continue; } $callback = [$proxy, $method->getName()]; self::assertIsCallable($callback); self::assertNull($callback()); } } protected function getProxyGenerator(): ProxyGeneratorInterface { return new NullObjectGenerator(); } /** * {@inheritDoc} */ protected function getExpectedImplementedInterfaces(): array { return [ NullObjectInterface::class, ]; } /** * @psalm-return array> */ public function getTestedImplementations(): array { $implementations = [ [BaseClass::class], [ClassWithMagicMethods::class], [ClassWithByRefMagicMethods::class], [ClassWithMixedProperties::class], [ClassWithMixedTypedProperties::class], [ClassWithMixedReferenceableTypedProperties::class], [BaseInterface::class], ]; if (PHP_VERSION_ID >= 80000) { $implementations[] = [ClassWithPhp80TypedMethods::class]; } return $implementations; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/PropertyGenerator/000077500000000000000000000000001407505032400307105ustar00rootroot00000000000000AbstractUniquePropertyNameTest.php000066400000000000000000000014371407505032400375070ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/PropertyGeneratorcreateProperty(); $property2 = $this->createProperty(); self::assertSame($property1->getName(), $property1->getName()); self::assertSame($property1->getName(), $property2->getName()); } abstract protected function createProperty(): PropertyGenerator; } PublicPropertiesMapTest.php000066400000000000000000000053611407505032400361400ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/PropertyGeneratorgetDefaultValue(); self::assertNotNull($defaultValue); self::assertIsArray($defaultValue->getValue()); self::assertEmpty($defaultValue->getValue()); self::assertTrue($publicProperties->isStatic()); self::assertSame('private', $publicProperties->getVisibility()); self::assertTrue($publicProperties->isEmpty()); } public function testClassWithPublicProperties(): void { $publicProperties = new PublicPropertiesMap( Properties::fromReflectionClass(new ReflectionClass(ClassWithPublicProperties::class)) ); $defaultValue = $publicProperties->getDefaultValue(); self::assertTrue($publicProperties->isStatic()); self::assertSame('private', $publicProperties->getVisibility()); self::assertFalse($publicProperties->isEmpty()); self::assertNotNull($defaultValue); self::assertSame( [ 'property0' => true, 'property1' => true, 'property2' => true, 'property3' => true, 'property4' => true, 'property5' => true, 'property6' => true, 'property7' => true, 'property8' => true, 'property9' => true, ], $defaultValue->getValue() ); } public function testClassWithMixedProperties(): void { $defaultValue = (new PublicPropertiesMap( Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class)) ))->getDefaultValue(); self::assertNotNull($defaultValue); self::assertSame( [ 'publicProperty0' => true, 'publicProperty1' => true, 'publicProperty2' => true, ], $defaultValue->getValue() ); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/000077500000000000000000000000001407505032400275775ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/000077500000000000000000000000001407505032400326665ustar00rootroot00000000000000MagicGetTest.php000066400000000000000000000024011407505032400356350ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGeneratorcreateMock(PropertyGenerator::class); $adapter->method('getName')->willReturn('foo'); $magicGet = new MagicGet($reflection, $adapter); self::assertSame('__get', $magicGet->getName()); self::assertCount(1, $magicGet->getParameters()); self::assertStringMatchesFormat( '$return = $this->foo->call(\'ProxyManagerTestAsset\\\EmptyClass\', \'__get\', array($name));' . "\n\nreturn \$return;", $magicGet->getBody() ); } } MagicIssetTest.php000066400000000000000000000024171407505032400362140ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGeneratorcreateMock(PropertyGenerator::class); $adapter->method('getName')->willReturn('foo'); $magicGet = new MagicIsset($reflection, $adapter); self::assertSame('__isset', $magicGet->getName()); self::assertCount(1, $magicGet->getParameters()); self::assertStringMatchesFormat( '$return = $this->foo->call(\'ProxyManagerTestAsset\\\EmptyClass\', \'__isset\', array($name));' . "\n\nreturn \$return;", $magicGet->getBody() ); } } MagicSetTest.php000066400000000000000000000024111407505032400356520ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGeneratorcreateMock(PropertyGenerator::class); $adapter->method('getName')->willReturn('foo'); $magicGet = new MagicSet($reflection, $adapter); self::assertSame('__set', $magicGet->getName()); self::assertCount(2, $magicGet->getParameters()); self::assertStringMatchesFormat( '$return = $this->foo->call(\'ProxyManagerTestAsset\\\EmptyClass\', \'__set\', array($name, $value));' . "\n\nreturn \$return;", $magicGet->getBody() ); } } MagicUnsetTest.php000066400000000000000000000024171407505032400362230ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGeneratorcreateMock(PropertyGenerator::class); $adapter->method('getName')->willReturn('foo'); $magicGet = new MagicUnset($reflection, $adapter); self::assertSame('__unset', $magicGet->getName()); self::assertCount(1, $magicGet->getParameters()); self::assertStringMatchesFormat( '$return = $this->foo->call(\'ProxyManagerTestAsset\\\EmptyClass\', \'__unset\', array($name));' . "\n\nreturn \$return;", $magicGet->getBody() ); } } RemoteObjectMethodTest.php000066400000000000000000000073041407505032400377070ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGeneratorcreateMock(PropertyGenerator::class); $adapter->method('getName')->willReturn('adapter'); $reflectionMethod = new MethodReflection( BaseClass::class, 'publicByReferenceParameterMethod' ); $method = RemoteObjectMethod::generateMethod( $reflectionMethod, $adapter, new ReflectionClass(PropertyGenerator::class) ); self::assertSame('publicByReferenceParameterMethod', $method->getName()); self::assertCount(2, $method->getParameters()); self::assertSame( '$defaultValues = array ( 0 => NULL, 1 => NULL, ); $declaredParameterCount = 2; $args = \func_get_args() + $defaultValues; $return = $this->adapter->call(\'Laminas\\\\Code\\\\Generator\\\\PropertyGenerator\', \'publicByReferenceParameterMethod\', $args); return $return;', $method->getBody() ); } /** * @covers \ProxyManager\ProxyGenerator\RemoteObject\MethodGenerator\RemoteObjectMethod */ public function testBodyStructureWithArrayParameter(): void { $adapter = $this->createMock(PropertyGenerator::class); $adapter->method('getName')->willReturn('adapter'); $reflectionMethod = new MethodReflection(BaseClass::class, 'publicArrayHintedMethod'); $method = RemoteObjectMethod::generateMethod( $reflectionMethod, $adapter, new ReflectionClass(PropertyGenerator::class) ); self::assertSame('publicArrayHintedMethod', $method->getName()); self::assertCount(1, $method->getParameters()); self::assertSame( "\$defaultValues = array ( 0 => NULL, ); \$declaredParameterCount = 1; \$args = \\func_get_args() + \$defaultValues; \$return = \$this->adapter->call('Laminas\\\\Code\\\\Generator\\\\PropertyGenerator', 'publicArrayHintedMethod', \$args); return \$return;", $method->getBody() ); } /** * @covers \ProxyManager\ProxyGenerator\RemoteObject\MethodGenerator\RemoteObjectMethod */ public function testBodyStructureWithoutParameters(): void { $adapter = $this->createMock(PropertyGenerator::class); $adapter->method('getName')->willReturn('adapter'); $reflectionMethod = new MethodReflection(BaseClass::class, 'publicMethod'); $method = RemoteObjectMethod::generateMethod( $reflectionMethod, $adapter, new ReflectionClass(PropertyGenerator::class) ); self::assertSame('publicMethod', $method->getName()); self::assertCount(0, $method->getParameters()); self::assertSame( "\$defaultValues = array ( ); \$declaredParameterCount = 0; \$args = \\func_get_args() + \$defaultValues; \$return = \$this->adapter->call('Laminas\\\\Code\\\\Generator\\\\PropertyGenerator', 'publicMethod', \$args); return \$return;", $method->getBody() ); } } StaticProxyConstructorTest.php000066400000000000000000000037501407505032400407240ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGeneratorcreateMock(PropertyGenerator::class); $adapter->method('getName')->willReturn('adapter'); $constructor = new StaticProxyConstructor( new ReflectionClass(ClassWithMixedProperties::class), $adapter ); self::assertSame('staticProxyConstructor', $constructor->getName()); self::assertTrue($constructor->isStatic()); self::assertSame('public', $constructor->getVisibility()); self::assertCount(1, $constructor->getParameters()); self::assertSame( 'static $reflection; $reflection = $reflection ?? new \ReflectionClass(__CLASS__); $instance = $reflection->newInstanceWithoutConstructor(); $instance->adapter = $adapter; unset($instance->publicProperty0, $instance->publicProperty1, $instance->publicProperty2, ' . '$instance->protectedProperty0, $instance->protectedProperty1, $instance->protectedProperty2); \Closure::bind(function (\ProxyManagerTestAsset\ClassWithMixedProperties $instance) { unset($instance->privateProperty0, $instance->privateProperty1, $instance->privateProperty2); }, $instance, \'ProxyManagerTestAsset\\\\ClassWithMixedProperties\')->__invoke($instance); return $instance;', $constructor->getBody() ); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/PropertyGenerator/000077500000000000000000000000001407505032400332725ustar00rootroot00000000000000AdapterPropertyTest.php000066400000000000000000000013161407505032400377120ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/PropertyGeneratorgetProxyGenerator(); $generatedClassName = UniqueIdentifierGenerator::getIdentifier('AbstractProxyGeneratorTest'); $generatedClass = new ClassGenerator($generatedClassName); $originalClass = new ReflectionClass($className); $generatorStrategy = new EvaluatingGeneratorStrategy(); $generator->generate($originalClass, $generatedClass); $generatorStrategy->generate($generatedClass); $generatedReflection = new ReflectionClass($generatedClassName); if ($originalClass->isInterface()) { self::assertTrue($generatedReflection->implementsInterface($className)); } else { self::assertEmpty( array_diff($originalClass->getInterfaceNames(), $generatedReflection->getInterfaceNames()) ); } self::assertSame($generatedClassName, $generatedReflection->getName()); foreach ($this->getExpectedImplementedInterfaces() as $interface) { self::assertTrue($generatedReflection->implementsInterface($interface)); } } protected function getProxyGenerator(): ProxyGeneratorInterface { return new RemoteObjectGenerator(); } /** * {@inheritDoc} */ protected function getExpectedImplementedInterfaces(): array { return [ RemoteObjectInterface::class, ]; } /** @return string[][] */ public function getTestedImplementations(): array { $implementations = [ [BaseClass::class], [ClassWithMagicMethods::class], [ClassWithByRefMagicMethods::class], [ClassWithMixedProperties::class], [ClassWithMixedTypedProperties::class], [ClassWithMixedReferenceableTypedProperties::class], [BaseInterface::class], ]; if (PHP_VERSION_ID >= 80000) { $implementations[] = [ClassWithPhp80TypedMethods::class]; } return $implementations; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/Util/000077500000000000000000000000001407505032400261325ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/Util/GetMethodIfExistsTest.php000066400000000000000000000017701407505032400330470ustar00rootroot00000000000000getName()); self::assertSame(self::class, $method->getDeclaringClass()->getName()); } public function testGetNonExistingMethod(): void { self::assertNull(GetMethodIfExists::get(new ReflectionClass(self::class), uniqid('nonExisting', true))); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/Util/PropertiesTest.php000066400000000000000000000557061407505032400316540ustar00rootroot00000000000000getPublicProperties(); self::assertCount(3, $publicProperties); self::assertArrayHasKey('publicProperty0', $publicProperties); self::assertArrayHasKey('publicProperty1', $publicProperties); self::assertArrayHasKey('publicProperty2', $publicProperties); } public function testGetPublicPropertiesSkipsAbstractMethods(): void { $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithAbstractPublicMethod::class)); self::assertEmpty($properties->getPublicProperties()); } public function testGetProtectedProperties(): void { $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class)); $protectedProperties = $properties->getProtectedProperties(); self::assertCount(3, $protectedProperties); self::assertArrayHasKey("\0*\0protectedProperty0", $protectedProperties); self::assertArrayHasKey("\0*\0protectedProperty1", $protectedProperties); self::assertArrayHasKey("\0*\0protectedProperty2", $protectedProperties); } /** * @requires PHP 7.4 */ public function testOnlyNullableProperties(): void { $nullablePublicProperties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedTypedProperties::class)) ->onlyNullableProperties() ->getInstanceProperties(); self::assertCount(48, $nullablePublicProperties); self::assertSame( [ 'publicUnTypedProperty', 'publicUnTypedPropertyWithoutDefaultValue', 'publicNullableBoolProperty', 'publicNullableBoolPropertyWithoutDefaultValue', 'publicNullableIntProperty', 'publicNullableIntPropertyWithoutDefaultValue', 'publicNullableFloatProperty', 'publicNullableFloatPropertyWithoutDefaultValue', 'publicNullableStringProperty', 'publicNullableStringPropertyWithoutDefaultValue', 'publicNullableArrayProperty', 'publicNullableArrayPropertyWithoutDefaultValue', 'publicNullableIterableProperty', 'publicNullableIterablePropertyWithoutDefaultValue', 'publicNullableObjectProperty', 'publicNullableClassProperty', 'protectedUnTypedProperty', 'protectedUnTypedPropertyWithoutDefaultValue', 'protectedNullableBoolProperty', 'protectedNullableBoolPropertyWithoutDefaultValue', 'protectedNullableIntProperty', 'protectedNullableIntPropertyWithoutDefaultValue', 'protectedNullableFloatProperty', 'protectedNullableFloatPropertyWithoutDefaultValue', 'protectedNullableStringProperty', 'protectedNullableStringPropertyWithoutDefaultValue', 'protectedNullableArrayProperty', 'protectedNullableArrayPropertyWithoutDefaultValue', 'protectedNullableIterableProperty', 'protectedNullableIterablePropertyWithoutDefaultValue', 'protectedNullableObjectProperty', 'protectedNullableClassProperty', 'privateUnTypedProperty', 'privateUnTypedPropertyWithoutDefaultValue', 'privateNullableBoolProperty', 'privateNullableBoolPropertyWithoutDefaultValue', 'privateNullableIntProperty', 'privateNullableIntPropertyWithoutDefaultValue', 'privateNullableFloatProperty', 'privateNullableFloatPropertyWithoutDefaultValue', 'privateNullableStringProperty', 'privateNullableStringPropertyWithoutDefaultValue', 'privateNullableArrayProperty', 'privateNullableArrayPropertyWithoutDefaultValue', 'privateNullableIterableProperty', 'privateNullableIterablePropertyWithoutDefaultValue', 'privateNullableObjectProperty', 'privateNullableClassProperty', ], array_values(array_map(static function (ReflectionProperty $property): string { return $property->getName(); }, $nullablePublicProperties)) ); } /** * @requires PHP 7.4 */ public function testOnlyPropertiesThatCanBeUnset(): void { $nonReferenceableProperties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedTypedProperties::class)) ->getInstanceProperties(); self::assertSame( [ 'publicUnTypedProperty', 'publicUnTypedPropertyWithoutDefaultValue', 'publicBoolProperty', 'publicBoolPropertyWithoutDefaultValue', 'publicNullableBoolProperty', 'publicNullableBoolPropertyWithoutDefaultValue', 'publicIntProperty', 'publicIntPropertyWithoutDefaultValue', 'publicNullableIntProperty', 'publicNullableIntPropertyWithoutDefaultValue', 'publicFloatProperty', 'publicFloatPropertyWithoutDefaultValue', 'publicNullableFloatProperty', 'publicNullableFloatPropertyWithoutDefaultValue', 'publicStringProperty', 'publicStringPropertyWithoutDefaultValue', 'publicNullableStringProperty', 'publicNullableStringPropertyWithoutDefaultValue', 'publicArrayProperty', 'publicArrayPropertyWithoutDefaultValue', 'publicNullableArrayProperty', 'publicNullableArrayPropertyWithoutDefaultValue', 'publicIterableProperty', 'publicIterablePropertyWithoutDefaultValue', 'publicNullableIterableProperty', 'publicNullableIterablePropertyWithoutDefaultValue', 'publicObjectProperty', 'publicNullableObjectProperty', 'publicClassProperty', 'publicNullableClassProperty', 'protectedUnTypedProperty', 'protectedUnTypedPropertyWithoutDefaultValue', 'protectedBoolProperty', 'protectedBoolPropertyWithoutDefaultValue', 'protectedNullableBoolProperty', 'protectedNullableBoolPropertyWithoutDefaultValue', 'protectedIntProperty', 'protectedIntPropertyWithoutDefaultValue', 'protectedNullableIntProperty', 'protectedNullableIntPropertyWithoutDefaultValue', 'protectedFloatProperty', 'protectedFloatPropertyWithoutDefaultValue', 'protectedNullableFloatProperty', 'protectedNullableFloatPropertyWithoutDefaultValue', 'protectedStringProperty', 'protectedStringPropertyWithoutDefaultValue', 'protectedNullableStringProperty', 'protectedNullableStringPropertyWithoutDefaultValue', 'protectedArrayProperty', 'protectedArrayPropertyWithoutDefaultValue', 'protectedNullableArrayProperty', 'protectedNullableArrayPropertyWithoutDefaultValue', 'protectedIterableProperty', 'protectedIterablePropertyWithoutDefaultValue', 'protectedNullableIterableProperty', 'protectedNullableIterablePropertyWithoutDefaultValue', 'protectedObjectProperty', 'protectedNullableObjectProperty', 'protectedClassProperty', 'protectedNullableClassProperty', 'privateUnTypedProperty', 'privateUnTypedPropertyWithoutDefaultValue', 'privateBoolProperty', 'privateBoolPropertyWithoutDefaultValue', 'privateNullableBoolProperty', 'privateNullableBoolPropertyWithoutDefaultValue', 'privateIntProperty', 'privateIntPropertyWithoutDefaultValue', 'privateNullableIntProperty', 'privateNullableIntPropertyWithoutDefaultValue', 'privateFloatProperty', 'privateFloatPropertyWithoutDefaultValue', 'privateNullableFloatProperty', 'privateNullableFloatPropertyWithoutDefaultValue', 'privateStringProperty', 'privateStringPropertyWithoutDefaultValue', 'privateNullableStringProperty', 'privateNullableStringPropertyWithoutDefaultValue', 'privateArrayProperty', 'privateArrayPropertyWithoutDefaultValue', 'privateNullableArrayProperty', 'privateNullableArrayPropertyWithoutDefaultValue', 'privateIterableProperty', 'privateIterablePropertyWithoutDefaultValue', 'privateNullableIterableProperty', 'privateNullableIterablePropertyWithoutDefaultValue', 'privateObjectProperty', 'privateNullableObjectProperty', 'privateClassProperty', 'privateNullableClassProperty', ], array_values(array_map(static function (ReflectionProperty $property): string { return $property->getName(); }, $nonReferenceableProperties)) ); } /** * @requires PHP 7.4 */ public function testOnlyNonReferenceableProperties(): void { self::assertTrue( Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedReferenceableTypedProperties::class)) ->onlyNonReferenceableProperties() ->empty() ); $nonReferenceableProperties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedTypedProperties::class)) ->onlyNonReferenceableProperties() ->getInstanceProperties(); self::assertCount(48, $nonReferenceableProperties); self::assertSame( [ 'publicBoolPropertyWithoutDefaultValue', 'publicNullableBoolPropertyWithoutDefaultValue', 'publicIntPropertyWithoutDefaultValue', 'publicNullableIntPropertyWithoutDefaultValue', 'publicFloatPropertyWithoutDefaultValue', 'publicNullableFloatPropertyWithoutDefaultValue', 'publicStringPropertyWithoutDefaultValue', 'publicNullableStringPropertyWithoutDefaultValue', 'publicArrayPropertyWithoutDefaultValue', 'publicNullableArrayPropertyWithoutDefaultValue', 'publicIterablePropertyWithoutDefaultValue', 'publicNullableIterablePropertyWithoutDefaultValue', 'publicObjectProperty', 'publicNullableObjectProperty', 'publicClassProperty', 'publicNullableClassProperty', 'protectedBoolPropertyWithoutDefaultValue', 'protectedNullableBoolPropertyWithoutDefaultValue', 'protectedIntPropertyWithoutDefaultValue', 'protectedNullableIntPropertyWithoutDefaultValue', 'protectedFloatPropertyWithoutDefaultValue', 'protectedNullableFloatPropertyWithoutDefaultValue', 'protectedStringPropertyWithoutDefaultValue', 'protectedNullableStringPropertyWithoutDefaultValue', 'protectedArrayPropertyWithoutDefaultValue', 'protectedNullableArrayPropertyWithoutDefaultValue', 'protectedIterablePropertyWithoutDefaultValue', 'protectedNullableIterablePropertyWithoutDefaultValue', 'protectedObjectProperty', 'protectedNullableObjectProperty', 'protectedClassProperty', 'protectedNullableClassProperty', 'privateBoolPropertyWithoutDefaultValue', 'privateNullableBoolPropertyWithoutDefaultValue', 'privateIntPropertyWithoutDefaultValue', 'privateNullableIntPropertyWithoutDefaultValue', 'privateFloatPropertyWithoutDefaultValue', 'privateNullableFloatPropertyWithoutDefaultValue', 'privateStringPropertyWithoutDefaultValue', 'privateNullableStringPropertyWithoutDefaultValue', 'privateArrayPropertyWithoutDefaultValue', 'privateNullableArrayPropertyWithoutDefaultValue', 'privateIterablePropertyWithoutDefaultValue', 'privateNullableIterablePropertyWithoutDefaultValue', 'privateObjectProperty', 'privateNullableObjectProperty', 'privateClassProperty', 'privateNullableClassProperty', ], array_values(array_map(static function (ReflectionProperty $property): string { return $property->getName(); }, $nonReferenceableProperties)) ); } public function testGetProtectedPropertiesSkipsAbstractMethods(): void { $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithAbstractProtectedMethod::class)); self::assertEmpty($properties->getProtectedProperties()); } public function testGetPrivateProperties(): void { $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class)); $privateProperties = $properties->getPrivateProperties(); self::assertCount(3, $privateProperties); $prefix = "\0" . ClassWithMixedProperties::class . "\0"; self::assertArrayHasKey($prefix . 'privateProperty0', $privateProperties); self::assertArrayHasKey($prefix . 'privateProperty1', $privateProperties); self::assertArrayHasKey($prefix . 'privateProperty2', $privateProperties); } public function testGetPrivatePropertiesFromInheritance(): void { $properties = Properties::fromReflectionClass( new ReflectionClass(ClassWithCollidingPrivateInheritedProperties::class) ); $privateProperties = $properties->getPrivateProperties(); self::assertCount(11, $privateProperties); $prefix = "\0" . ClassWithCollidingPrivateInheritedProperties::class . "\0"; self::assertArrayHasKey($prefix . 'property0', $privateProperties); $prefix = "\0" . ClassWithPrivateProperties::class . "\0"; self::assertArrayHasKey($prefix . 'property0', $privateProperties); self::assertArrayHasKey($prefix . 'property1', $privateProperties); self::assertArrayHasKey($prefix . 'property2', $privateProperties); self::assertArrayHasKey($prefix . 'property3', $privateProperties); self::assertArrayHasKey($prefix . 'property4', $privateProperties); self::assertArrayHasKey($prefix . 'property5', $privateProperties); self::assertArrayHasKey($prefix . 'property6', $privateProperties); self::assertArrayHasKey($prefix . 'property7', $privateProperties); self::assertArrayHasKey($prefix . 'property8', $privateProperties); self::assertArrayHasKey($prefix . 'property9', $privateProperties); } public function testGetAccessibleMethods(): void { $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class)); $accessibleProperties = $properties->getAccessibleProperties(); self::assertCount(6, $accessibleProperties); self::assertArrayHasKey('publicProperty0', $accessibleProperties); self::assertArrayHasKey('publicProperty1', $accessibleProperties); self::assertArrayHasKey('publicProperty2', $accessibleProperties); self::assertArrayHasKey("\0*\0protectedProperty0", $accessibleProperties); self::assertArrayHasKey("\0*\0protectedProperty1", $accessibleProperties); self::assertArrayHasKey("\0*\0protectedProperty2", $accessibleProperties); } public function testGetGroupedPrivateProperties(): void { $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class)); $groupedPrivate = $properties->getGroupedPrivateProperties(); self::assertCount(1, $groupedPrivate); $group = $groupedPrivate[ClassWithMixedProperties::class]; self::assertCount(3, $group); self::assertArrayHasKey('privateProperty0', $group); self::assertArrayHasKey('privateProperty1', $group); self::assertArrayHasKey('privateProperty2', $group); } public function testGetGroupedPrivatePropertiesWithInheritedProperties(): void { $properties = Properties::fromReflectionClass( new ReflectionClass(ClassWithCollidingPrivateInheritedProperties::class) ); $groupedPrivate = $properties->getGroupedPrivateProperties(); self::assertCount(2, $groupedPrivate); $group1 = $groupedPrivate[ClassWithCollidingPrivateInheritedProperties::class]; $group2 = $groupedPrivate[ClassWithPrivateProperties::class]; self::assertCount(1, $group1); self::assertCount(10, $group2); self::assertArrayHasKey('property0', $group1); self::assertArrayHasKey('property0', $group2); self::assertArrayHasKey('property1', $group2); self::assertArrayHasKey('property2', $group2); self::assertArrayHasKey('property3', $group2); self::assertArrayHasKey('property4', $group2); self::assertArrayHasKey('property5', $group2); self::assertArrayHasKey('property6', $group2); self::assertArrayHasKey('property7', $group2); self::assertArrayHasKey('property8', $group2); self::assertArrayHasKey('property9', $group2); } public function testGetInstanceProperties(): void { $properties = Properties::fromReflectionClass( new ReflectionClass(ClassWithMixedProperties::class) ); self::assertCount(9, $properties->getInstanceProperties()); } /** * @param string $propertyName with property name * * @dataProvider propertiesToSkipFixture */ public function testSkipPropertiesByFiltering(string $propertyName): void { $properties = Properties::fromReflectionClass( new ReflectionClass(ClassWithMixedProperties::class) ); self::assertArrayHasKey($propertyName, $properties->getInstanceProperties()); $filteredProperties = $properties->filter([$propertyName]); self::assertArrayNotHasKey($propertyName, $filteredProperties->getInstanceProperties()); } public function testSkipOverwritedPropertyUsingInheritance(): void { $propertyName = "\0ProxyManagerTestAsset\\ClassWithCollidingPrivateInheritedProperties\0property0"; $properties = Properties::fromReflectionClass( new ReflectionClass(ClassWithCollidingPrivateInheritedProperties::class) ); self::assertArrayHasKey($propertyName, $properties->getInstanceProperties()); $filteredProperties = $properties->filter([$propertyName]); self::assertArrayNotHasKey($propertyName, $filteredProperties->getInstanceProperties()); } public function testPropertiesIsSkippedFromRelatedMethods(): void { $properties = Properties::fromReflectionClass( new ReflectionClass(ClassWithMixedProperties::class) ); self::assertArrayHasKey("\0*\0protectedProperty0", $properties->getProtectedProperties()); self::assertArrayHasKey("\0*\0protectedProperty0", $properties->getInstanceProperties()); $filteredProperties = $properties->filter(["\0*\0protectedProperty0"]); self::assertArrayNotHasKey("\0*\0protectedProperty0", $filteredProperties->getProtectedProperties()); self::assertArrayNotHasKey("\0*\0protectedProperty0", $filteredProperties->getInstanceProperties()); } /** @return string[][] */ public function propertiesToSkipFixture(): array { return [ ['publicProperty0'], ["\0*\0protectedProperty0"], ["\0ProxyManagerTestAsset\\ClassWithMixedProperties\0privateProperty0"], ]; } /** * @requires PHP 7.4 */ public function testWithoutNonReferenceableProperties(): void { $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedTypedProperties::class)) ->withoutNonReferenceableProperties() ->getPublicProperties(); self::assertSame( [ 'publicUnTypedProperty', 'publicUnTypedPropertyWithoutDefaultValue', 'publicBoolProperty', 'publicNullableBoolProperty', 'publicNullableBoolPropertyWithoutDefaultValue', 'publicIntProperty', 'publicNullableIntProperty', 'publicNullableIntPropertyWithoutDefaultValue', 'publicFloatProperty', 'publicNullableFloatProperty', 'publicNullableFloatPropertyWithoutDefaultValue', 'publicStringProperty', 'publicNullableStringProperty', 'publicNullableStringPropertyWithoutDefaultValue', 'publicArrayProperty', 'publicNullableArrayProperty', 'publicNullableArrayPropertyWithoutDefaultValue', 'publicIterableProperty', 'publicNullableIterableProperty', 'publicNullableIterablePropertyWithoutDefaultValue', 'publicNullableObjectProperty', 'publicNullableClassProperty', ], array_keys($properties) ); } } ProxiedMethodsFilterTest.php000066400000000000000000000171651407505032400335420ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/Util|null $excludes * @param string[] $expectedMethods * * @dataProvider expectedMethods */ public function testFiltering(ReflectionClass $reflectionClass, ?array $excludes, array $expectedMethods): void { $filtered = ProxiedMethodsFilter::getProxiedMethods($reflectionClass, $excludes); $keys = array_map( static function (ReflectionMethod $method): string { return $method->getName(); }, $filtered ); sort($keys); sort($expectedMethods); self::assertSame($keys, $expectedMethods); } /** * @param array|null $excludes * @param string[] $expectedMethods * * @dataProvider expectedAbstractPublicMethods */ public function testFilteringOfAbstractPublic( ReflectionClass $reflectionClass, ?array $excludes, array $expectedMethods ): void { $filtered = ProxiedMethodsFilter::getAbstractProxiedMethods($reflectionClass, $excludes); $keys = array_map( static function (ReflectionMethod $method): string { return $method->getName(); }, $filtered ); sort($keys); sort($expectedMethods); self::assertSame($keys, $expectedMethods); } /** * Data provider * * @return ReflectionClass[][]|null[][]|string[][][] */ public function expectedMethods(): array { return [ [ new ReflectionClass(BaseClass::class), null, [ 'privatePropertyGetter', 'protectedPropertyGetter', 'publicArrayHintedMethod', 'publicByReferenceMethod', 'publicByReferenceParameterMethod', 'publicMethod', 'publicPropertyGetter', 'publicTypeHintedMethod', ], ], [ new ReflectionClass(EmptyClass::class), null, [], ], [ new ReflectionClass(LazyLoadingMock::class), null, [ 'getProxyInitializer', 'getWrappedValueHolderValue', 'initializeProxy', 'isProxyInitialized', 'setProxyInitializer', ], ], [ new ReflectionClass(LazyLoadingMock::class), [], [ 'getProxyInitializer', 'getWrappedValueHolderValue', 'initializeProxy', 'isProxyInitialized', 'setProxyInitializer', ], ], [ new ReflectionClass(HydratedObject::class), ['doFoo'], ['__get'], ], [ new ReflectionClass(HydratedObject::class), ['Dofoo'], ['__get'], ], [ new ReflectionClass(HydratedObject::class), [], ['doFoo', '__get'], ], [ new ReflectionClass(ClassWithAbstractProtectedMethod::class), null, [], ], [ new ReflectionClass(ClassWithAbstractPublicMethod::class), null, ['publicAbstractMethod'], ], [ new ReflectionClass(ClassWithAbstractPublicMethod::class), ['publicAbstractMethod'], [], ], [ new ReflectionClass(ClassWithAbstractMagicMethods::class), null, [], ], [ new ReflectionClass(ClassWithAbstractMagicMethods::class), [], [ '__clone', '__get', '__isset', '__set', '__sleep', '__unset', '__wakeup', ], ], [ new ReflectionClass(ClassWithMethodWithVariadicFunction::class), null, ['foo', 'buz'], ], [ new ReflectionClass(ClassWithMethodWithByRefVariadicFunction::class), null, ['tuz'], ], 'final magic methods' => [ new ReflectionClass(ClassWithFinalMagicMethods::class), null, [], ], 'non-final constructor is to be skipped' => [ new ReflectionClass(ClassWithCounterConstructor::class), null, ['getAmount'], ], ]; } /** * Data provider * * @return ReflectionClass[][]|null[][]|string[][][] */ public function expectedAbstractPublicMethods(): array { return [ [ new ReflectionClass(BaseClass::class), null, [], ], [ new ReflectionClass(EmptyClass::class), null, [], ], [ new ReflectionClass(ClassWithAbstractProtectedMethod::class), null, [], ], [ new ReflectionClass(ClassWithAbstractPublicMethod::class), null, ['publicAbstractMethod'], ], [ new ReflectionClass(ClassWithAbstractPublicMethod::class), ['publicAbstractMethod'], [], ], [ new ReflectionClass(ClassWithMagicMethods::class), [], [], ], [ new ReflectionClass(ClassWithAbstractMagicMethods::class), null, [], ], [ new ReflectionClass(ClassWithAbstractMagicMethods::class), [], [ '__clone', '__get', '__isset', '__set', '__sleep', '__unset', '__wakeup', ], ], ]; } } PublicScopeSimulatorTest.php000066400000000000000000000227211407505032400335400ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/UtilhasProperty($foo)) { $targetObject = $this; $backtrace = debug_backtrace(false, 1); trigger_error( sprintf( 'Undefined property: %s::$%s in %s on line %s', $realInstanceReflection->getName(), $foo, $backtrace[0]['file'], $backtrace[0]['line'] ), \E_USER_NOTICE ); return $targetObject->$foo; } $targetObject = $realInstanceReflection->newInstanceWithoutConstructor(); $accessor = function & () use ($targetObject, $foo) { return $targetObject->$foo; }; $backtrace = debug_backtrace(true, 2); $scopeObject = isset($backtrace[1]['object']) ? $backtrace[1]['object'] : new \ProxyManager\Stub\EmptyClassStub(); $accessor = $accessor->bindTo($scopeObject, get_class($scopeObject)); $bar = & $accessor(); PHP; self::assertSame( $expected, PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_GET, 'foo', null, null, 'bar' ) ); } public function testValueParameterNameIgnoredForSetOperation(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Parameter $valueParameter should be provided (only) when $operationType === "set"'); PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_GET, 'foo', 'givenValue', null, 'bar' ); } public function testSimpleSet(): void { $expected = <<<'PHP' $realInstanceReflection = new \ReflectionClass(get_parent_class($this)); if (! $realInstanceReflection->hasProperty($foo)) { $targetObject = $this; $targetObject->$foo = $baz; return $targetObject->$foo; } $targetObject = $realInstanceReflection->newInstanceWithoutConstructor(); $accessor = function & () use ($targetObject, $foo, $baz) { $targetObject->$foo = $baz; return $targetObject->$foo; }; $backtrace = debug_backtrace(true, 2); $scopeObject = isset($backtrace[1]['object']) ? $backtrace[1]['object'] : new \ProxyManager\Stub\EmptyClassStub(); $accessor = $accessor->bindTo($scopeObject, get_class($scopeObject)); $bar = & $accessor(); PHP; self::assertSame( $expected, PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_SET, 'foo', 'baz', null, 'bar' ) ); } public function testSimpleIsset(): void { $expected = <<<'PHP' $realInstanceReflection = new \ReflectionClass(get_parent_class($this)); if (! $realInstanceReflection->hasProperty($foo)) { $targetObject = $this; return isset($targetObject->$foo); } $targetObject = $realInstanceReflection->newInstanceWithoutConstructor(); $accessor = function () use ($targetObject, $foo) { return isset($targetObject->$foo); }; $backtrace = debug_backtrace(true, 2); $scopeObject = isset($backtrace[1]['object']) ? $backtrace[1]['object'] : new \ProxyManager\Stub\EmptyClassStub(); $accessor = $accessor->bindTo($scopeObject, get_class($scopeObject)); $bar = $accessor(); PHP; self::assertSame( $expected, PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_ISSET, 'foo', null, null, 'bar' ) ); } public function testSimpleUnset(): void { $expected = <<<'PHP' $realInstanceReflection = new \ReflectionClass(get_parent_class($this)); if (! $realInstanceReflection->hasProperty($foo)) { $targetObject = $this; unset($targetObject->$foo); return; } $targetObject = $realInstanceReflection->newInstanceWithoutConstructor(); $accessor = function () use ($targetObject, $foo) { unset($targetObject->$foo); return; }; $backtrace = debug_backtrace(true, 2); $scopeObject = isset($backtrace[1]['object']) ? $backtrace[1]['object'] : new \ProxyManager\Stub\EmptyClassStub(); $accessor = $accessor->bindTo($scopeObject, get_class($scopeObject)); $accessor(); PHP; self::assertSame( $expected, PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_UNSET, 'foo', null, null, 'bar' ) ); } /** * @group #632 * @group #645 * @group #646 */ public function testUnsetCodeWillNotProduceReturnValueStatements(): void { self::assertStringNotContainsString( 'return ', PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_UNSET, 'foo' ), 'Generated return statements do not contain value expressions (invalid since PHP 7.3+)' ); } /** * @group #632 * @group #645 * @group #646 */ public function testUnsetCodeWillNotAssignAccessorEvaluationToVariable(): void { self::assertStringEndsWith( "\n" . '$accessor();', PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_UNSET, 'foo' ) ); } public function testSetRequiresValueParameterName(): void { $this->expectException(InvalidArgumentException::class); PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_SET, 'foo', null, null, 'bar' ); } public function testDelegatesToValueHolderWhenAvailable(): void { $expected = <<<'PHP' $realInstanceReflection = new \ReflectionClass(get_parent_class($this)); if (! $realInstanceReflection->hasProperty($foo)) { $targetObject = $this->valueHolder; $targetObject->$foo = $baz; return $targetObject->$foo; } $targetObject = $this->valueHolder; $accessor = function & () use ($targetObject, $foo, $baz) { $targetObject->$foo = $baz; return $targetObject->$foo; }; $backtrace = debug_backtrace(true, 2); $scopeObject = isset($backtrace[1]['object']) ? $backtrace[1]['object'] : new \ProxyManager\Stub\EmptyClassStub(); $accessor = $accessor->bindTo($scopeObject, get_class($scopeObject)); $bar = & $accessor(); PHP; self::assertSame( $expected, PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_SET, 'foo', 'baz', new PropertyGenerator('valueHolder'), 'bar' ) ); } public function testSetRequiresValidOperation(): void { $this->expectException(InvalidArgumentException::class); PublicScopeSimulator::getPublicAccessSimulationCode('invalid', 'foo'); } public function testWillReturnDirectlyWithNoReturnParam(): void { $expected = <<<'PHP' $realInstanceReflection = new \ReflectionClass(get_parent_class($this)); if (! $realInstanceReflection->hasProperty($foo)) { $targetObject = $this; $backtrace = debug_backtrace(false, 1); trigger_error( sprintf( 'Undefined property: %s::$%s in %s on line %s', $realInstanceReflection->getName(), $foo, $backtrace[0]['file'], $backtrace[0]['line'] ), \E_USER_NOTICE ); return $targetObject->$foo; } $targetObject = $realInstanceReflection->newInstanceWithoutConstructor(); $accessor = function & () use ($targetObject, $foo) { return $targetObject->$foo; }; $backtrace = debug_backtrace(true, 2); $scopeObject = isset($backtrace[1]['object']) ? $backtrace[1]['object'] : new \ProxyManager\Stub\EmptyClassStub(); $accessor = $accessor->bindTo($scopeObject, get_class($scopeObject)); $returnValue = & $accessor(); return $returnValue; PHP; self::assertSame( $expected, PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_GET, 'foo' ) ); } /** @group #642 */ public function testWillNotAttemptToGetParentClassWhenReflectionClassIsGivenUpfront(): void { self::assertStringStartsWith( <<<'PHP' $realInstanceReflection = new \ReflectionClass('ArrayAccess'); PHP , PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_GET, 'foo', null, null, null, new ReflectionClass(ArrayAccess::class) ) ); } } UnsetPropertiesGeneratorTest.php000066400000000000000000000167501407505032400344570ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/Util [ EmptyClass::class, '', 'foo', ], BaseClass::class => [ BaseClass::class, 'unset($foo->publicProperty, $foo->protectedProperty); \Closure::bind(function (\ProxyManagerTestAsset\BaseClass $instance) { unset($instance->privateProperty); }, $foo, \'ProxyManagerTestAsset\\\\BaseClass\')->__invoke($foo); ', 'foo', ], ClassWithMixedProperties::class => [ ClassWithMixedProperties::class, 'unset($foo->publicProperty0, $foo->publicProperty1, $foo->publicProperty2, $foo->protectedProperty0, ' . '$foo->protectedProperty1, $foo->protectedProperty2); \Closure::bind(function (\ProxyManagerTestAsset\ClassWithMixedProperties $instance) { unset($instance->privateProperty0, $instance->privateProperty1, $instance->privateProperty2); }, $foo, \'ProxyManagerTestAsset\\\\ClassWithMixedProperties\')->__invoke($foo); ', 'foo', ], ClassWithCollidingPrivateInheritedProperties::class => [ ClassWithCollidingPrivateInheritedProperties::class, '\Closure::bind(function (\ProxyManagerTestAsset\ClassWithCollidingPrivateInheritedProperties ' . '$instance) { unset($instance->property0); }, $bar, \'ProxyManagerTestAsset\\\\ClassWithCollidingPrivateInheritedProperties\')->__invoke($bar); \Closure::bind(function (\ProxyManagerTestAsset\ClassWithPrivateProperties $instance) { unset($instance->property0, $instance->property1, $instance->property2, $instance->property3, ' . '$instance->property4, $instance->property5, $instance->property6, $instance->property7, ' . '$instance->property8, $instance->property9); }, $bar, \'ProxyManagerTestAsset\\\\ClassWithPrivateProperties\')->__invoke($bar); ', 'bar', ], ClassWithMixedTypedProperties::class => [ ClassWithMixedTypedProperties::class, <<<'PHP' unset($bar->publicUnTypedProperty, $bar->publicUnTypedPropertyWithoutDefaultValue, $bar->publicBoolProperty, $bar->publicBoolPropertyWithoutDefaultValue, $bar->publicNullableBoolProperty, $bar->publicNullableBoolPropertyWithoutDefaultValue, $bar->publicIntProperty, $bar->publicIntPropertyWithoutDefaultValue, $bar->publicNullableIntProperty, $bar->publicNullableIntPropertyWithoutDefaultValue, $bar->publicFloatProperty, $bar->publicFloatPropertyWithoutDefaultValue, $bar->publicNullableFloatProperty, $bar->publicNullableFloatPropertyWithoutDefaultValue, $bar->publicStringProperty, $bar->publicStringPropertyWithoutDefaultValue, $bar->publicNullableStringProperty, $bar->publicNullableStringPropertyWithoutDefaultValue, $bar->publicArrayProperty, $bar->publicArrayPropertyWithoutDefaultValue, $bar->publicNullableArrayProperty, $bar->publicNullableArrayPropertyWithoutDefaultValue, $bar->publicIterableProperty, $bar->publicIterablePropertyWithoutDefaultValue, $bar->publicNullableIterableProperty, $bar->publicNullableIterablePropertyWithoutDefaultValue, $bar->publicObjectProperty, $bar->publicNullableObjectProperty, $bar->publicClassProperty, $bar->publicNullableClassProperty, $bar->protectedUnTypedProperty, $bar->protectedUnTypedPropertyWithoutDefaultValue, $bar->protectedBoolProperty, $bar->protectedBoolPropertyWithoutDefaultValue, $bar->protectedNullableBoolProperty, $bar->protectedNullableBoolPropertyWithoutDefaultValue, $bar->protectedIntProperty, $bar->protectedIntPropertyWithoutDefaultValue, $bar->protectedNullableIntProperty, $bar->protectedNullableIntPropertyWithoutDefaultValue, $bar->protectedFloatProperty, $bar->protectedFloatPropertyWithoutDefaultValue, $bar->protectedNullableFloatProperty, $bar->protectedNullableFloatPropertyWithoutDefaultValue, $bar->protectedStringProperty, $bar->protectedStringPropertyWithoutDefaultValue, $bar->protectedNullableStringProperty, $bar->protectedNullableStringPropertyWithoutDefaultValue, $bar->protectedArrayProperty, $bar->protectedArrayPropertyWithoutDefaultValue, $bar->protectedNullableArrayProperty, $bar->protectedNullableArrayPropertyWithoutDefaultValue, $bar->protectedIterableProperty, $bar->protectedIterablePropertyWithoutDefaultValue, $bar->protectedNullableIterableProperty, $bar->protectedNullableIterablePropertyWithoutDefaultValue, $bar->protectedObjectProperty, $bar->protectedNullableObjectProperty, $bar->protectedClassProperty, $bar->protectedNullableClassProperty); \Closure::bind(function (\ProxyManagerTestAsset\ClassWithMixedTypedProperties $instance) { unset($instance->privateUnTypedProperty, $instance->privateUnTypedPropertyWithoutDefaultValue, $instance->privateBoolProperty, $instance->privateBoolPropertyWithoutDefaultValue, $instance->privateNullableBoolProperty, $instance->privateNullableBoolPropertyWithoutDefaultValue, $instance->privateIntProperty, $instance->privateIntPropertyWithoutDefaultValue, $instance->privateNullableIntProperty, $instance->privateNullableIntPropertyWithoutDefaultValue, $instance->privateFloatProperty, $instance->privateFloatPropertyWithoutDefaultValue, $instance->privateNullableFloatProperty, $instance->privateNullableFloatPropertyWithoutDefaultValue, $instance->privateStringProperty, $instance->privateStringPropertyWithoutDefaultValue, $instance->privateNullableStringProperty, $instance->privateNullableStringPropertyWithoutDefaultValue, $instance->privateArrayProperty, $instance->privateArrayPropertyWithoutDefaultValue, $instance->privateNullableArrayProperty, $instance->privateNullableArrayPropertyWithoutDefaultValue, $instance->privateIterableProperty, $instance->privateIterablePropertyWithoutDefaultValue, $instance->privateNullableIterableProperty, $instance->privateNullableIterablePropertyWithoutDefaultValue, $instance->privateObjectProperty, $instance->privateNullableObjectProperty, $instance->privateClassProperty, $instance->privateNullableClassProperty); }, $bar, 'ProxyManagerTestAsset\\ClassWithMixedTypedProperties')->__invoke($bar); PHP , 'bar', ], ]; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/ValueHolder/000077500000000000000000000000001407505032400274275ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/ValueHolder/MethodGenerator/000077500000000000000000000000001407505032400325165ustar00rootroot00000000000000ConstructorTest.php000066400000000000000000000113351407505032400363400ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/ValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $valueHolder->method('getName')->willReturn('foo'); $constructor = Constructor::generateMethod( new ReflectionClass( ClassWithTwoPublicProperties::class ), $valueHolder ); self::assertSame('__construct', $constructor->getName()); self::assertCount(0, $constructor->getParameters()); self::assertSame( 'static $reflection; if (! $this->foo) { $reflection = $reflection ?? new \ReflectionClass(\'ProxyManagerTestAsset\\\\ProxyGenerator\\\\LazyLoading\\\\' . 'MethodGenerator\\\\ClassWithTwoPublicProperties\'); $this->foo = $reflection->newInstanceWithoutConstructor(); unset($this->bar, $this->baz); }', $constructor->getBody() ); } public function testBodyStructureWithoutPublicProperties(): void { $valueHolder = $this->createMock(PropertyGenerator::class); $valueHolder->method('getName')->willReturn('foo'); $constructor = Constructor::generateMethod( new ReflectionClass(EmptyClass::class), $valueHolder ); self::assertSame('__construct', $constructor->getName()); self::assertCount(0, $constructor->getParameters()); self::assertSame( 'static $reflection; if (! $this->foo) { $reflection = $reflection ?? new \ReflectionClass(\'ProxyManagerTestAsset\\\\EmptyClass\'); $this->foo = $reflection->newInstanceWithoutConstructor(); }', $constructor->getBody() ); } public function testBodyStructureWithStaticProperties(): void { $valueHolder = $this->createMock(PropertyGenerator::class); $valueHolder->method('getName')->willReturn('foo'); $constructor = Constructor::generateMethod(new ReflectionClass(ClassWithMixedProperties::class), $valueHolder); self::assertSame('__construct', $constructor->getName()); self::assertCount(0, $constructor->getParameters()); $expectedCode = 'static $reflection; if (! $this->foo) { $reflection = $reflection ?? new \ReflectionClass(\'ProxyManagerTestAsset\\\\ClassWithMixedProperties\'); $this->foo = $reflection->newInstanceWithoutConstructor(); unset($this->publicProperty0, $this->publicProperty1, $this->publicProperty2, $this->protectedProperty0, ' . '$this->protectedProperty1, $this->protectedProperty2); \Closure::bind(function (\ProxyManagerTestAsset\ClassWithMixedProperties $instance) { unset($instance->privateProperty0, $instance->privateProperty1, $instance->privateProperty2); }, $this, \'ProxyManagerTestAsset\\\\ClassWithMixedProperties\')->__invoke($this); }'; self::assertSame($expectedCode, $constructor->getBody()); } public function testBodyStructureWithVariadicArguments(): void { $valueHolder = $this->createMock(PropertyGenerator::class); $valueHolder->method('getName')->willReturn('foo'); $constructor = Constructor::generateMethod( new ReflectionClass(ClassWithVariadicConstructorArgument::class), $valueHolder ); self::assertSame('__construct', $constructor->getName()); self::assertCount(2, $constructor->getParameters()); $expectedCode = <<<'PHP' static $reflection; if (! $this->foo) { $reflection = $reflection ?? new \ReflectionClass('ProxyManagerTestAsset\\ClassWithVariadicConstructorArgument'); $this->foo = $reflection->newInstanceWithoutConstructor(); \Closure::bind(function (\ProxyManagerTestAsset\ClassWithVariadicConstructorArgument $instance) { unset($instance->foo, $instance->bar); }, $this, 'ProxyManagerTestAsset\\ClassWithVariadicConstructorArgument')->__invoke($this); } $this->foo->__construct($foo, ...$bar); PHP; self::assertSame($expectedCode, $constructor->getBody()); } } GetWrappedValueHolderValueTest.php000066400000000000000000000021621407505032400412030ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/ValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $valueHolder->method('getName')->willReturn('foo'); $getter = new GetWrappedValueHolderValue($valueHolder); self::assertSame('getWrappedValueHolderValue', $getter->getName()); self::assertCount(0, $getter->getParameters()); self::assertSame('return $this->foo;', $getter->getBody()); } } MagicSleepTest.php000066400000000000000000000022401407505032400360170ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/ProxyGenerator/ValueHolder/MethodGeneratorcreateMock(PropertyGenerator::class); $valueHolder->method('getName')->willReturn('bar'); $magicSleep = new MagicSleep($reflection, $valueHolder); self::assertSame('__sleep', $magicSleep->getName()); self::assertCount(0, $magicSleep->getParameters()); self::assertSame( "return array('bar');", $magicSleep->getBody() ); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Signature/000077500000000000000000000000001407505032400241665ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Signature/ClassSignatureGeneratorTest.php000066400000000000000000000040271407505032400323400ustar00rootroot00000000000000signatureGenerator = $this->createMock(SignatureGeneratorInterface::class); $this->classSignatureGenerator = new ClassSignatureGenerator($this->signatureGenerator); } public function testAddSignature(): void { $classGenerator = $this->createMock(ClassGenerator::class); $classGenerator ->expects(self::once()) ->method('addPropertyFromGenerator') ->with(self::callback(static function (PropertyGenerator $property): bool { $defaultValue = $property->getDefaultValue(); return $property->getName() === 'signaturePropertyName' && $property->isStatic() && $property->getVisibility() === 'private' && $defaultValue !== null && $defaultValue->getValue() === 'valid-signature'; })); $this ->signatureGenerator ->method('generateSignature') ->with(['foo' => 'bar']) ->willReturn('valid-signature'); $this ->signatureGenerator ->method('generateSignatureKey') ->with(['foo' => 'bar']) ->willReturn('PropertyName'); $this->classSignatureGenerator->addSignature($classGenerator, ['foo' => 'bar']); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Signature/Exception/000077500000000000000000000000001407505032400261245ustar00rootroot00000000000000InvalidSignatureExceptionTest.php000066400000000000000000000017301407505032400345460ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Signature/Exception 'bar', 'baz' => 'tab'], 'blah', 'expected-signature' ); self::assertSame( 'Found signature "blah" for class "' . self::class . '" does not correspond to expected signature "expected-signature" for 2 parameters', $exception->getMessage() ); } } MissingSignatureExceptionTest.php000066400000000000000000000016521407505032400345740ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Signature/Exception 'bar', 'baz' => 'tab'], 'expected-signature' ); self::assertSame( 'No signature found for class "' . self::class . '", expected signature "expected-signature" for 2 parameters', $exception->getMessage() ); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Signature/SignatureCheckerTest.php000066400000000000000000000052641407505032400307740ustar00rootroot00000000000000signatureGenerator = $this->createMock(SignatureGeneratorInterface::class); $this->signatureChecker = new SignatureChecker($this->signatureGenerator); } public function testCheckSignatureWithValidKey(): void { $this ->signatureGenerator ->expects(self::atLeastOnce()) ->method('generateSignatureKey') ->with(['foo' => 'bar']) ->willReturn('Example'); $this ->signatureGenerator ->expects(self::atLeastOnce()) ->method('generateSignature') ->with(['foo' => 'bar']) ->willReturn('valid-signature'); $this->signatureChecker->checkSignature(new ReflectionClass($this), ['foo' => 'bar']); } public function testCheckSignatureWithInvalidKey(): void { $this ->signatureGenerator ->method('generateSignatureKey') ->with(['foo' => 'bar']) ->willReturn('InvalidKey'); $this ->signatureGenerator ->method('generateSignature') ->with(['foo' => 'bar']) ->willReturn('valid-signature'); $this->expectException(MissingSignatureException::class); $this->signatureChecker->checkSignature(new ReflectionClass($this), ['foo' => 'bar']); } public function testCheckSignatureWithInvalidValue(): void { $this ->signatureGenerator ->method('generateSignatureKey') ->with(['foo' => 'bar']) ->willReturn('Example'); $this ->signatureGenerator ->method('generateSignature') ->with(['foo' => 'bar']) ->willReturn('invalid-signature'); $this->expectException(InvalidSignatureException::class); $this->signatureChecker->checkSignature(new ReflectionClass($this), ['foo' => 'bar']); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/Signature/SignatureGeneratorTest.php000066400000000000000000000044241407505032400313530ustar00rootroot00000000000000signatureGenerator = new SignatureGenerator(); } /** * @param array> $parameters * * @dataProvider signatures */ public function testGenerateSignature(array $parameters, string $expected): void { self::assertSame($expected, $this->signatureGenerator->generateSignature($parameters)); } /** * @param array> $parameters * * @dataProvider signatureKeys */ public function testGenerateSignatureKey(array $parameters, string $expected): void { self::assertSame($expected, $this->signatureGenerator->generateSignatureKey($parameters)); } /** @return array|string>> */ public static function signatures(): array { return [ [ [], 'YTowOnt9', ], [ ['foo' => 'bar'], 'YToxOntzOjM6ImZvbyI7czozOiJiYXIiO30=', ], [ ['foo' => 'bar', 'baz' => 'tab'], 'YToyOntzOjM6ImZvbyI7czozOiJiYXIiO3M6MzoiYmF6IjtzOjM6InRhYiI7fQ==', ], [ ['bar'], 'YToxOntpOjA7czozOiJiYXIiO30=', ], [ ['bar', 'baz'], 'YToyOntpOjA7czozOiJiYXIiO2k6MTtzOjM6ImJheiI7fQ==', ], ]; } /** @return string[][]|string[][][] */ public static function signatureKeys(): array { return [ [[], '40cd750bba9870f18aada2478b24840a'], [['foo' => 'bar'], '49a3696adf0fbfacc12383a2d7400d51'], [['foo' => 'bar', 'baz' => 'tab'], '3f3cabbf33bae82b0711205c913a8fa0'], [['bar'], '6fc5f617053f53f56b4734453ec86daa'], [['bar', 'baz'], 'b9f31192ffbb4aa958cd1c5f88540c1e'], ]; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTest/VersionTest.php000066400000000000000000000006641407505032400252310ustar00rootroot00000000000000 * @license MIT */ class AccessInterceptorValueHolderMock implements AccessInterceptorValueHolderInterface { /** * @var object */ public $instance; /** * @var callable[] */ public $prefixInterceptors; /** * @var callable[] */ public $suffixInterceptors; /** * @param object $instance * @param callable[] $prefixInterceptors * @param callable[] $suffixInterceptors */ public static function staticProxyConstructor($instance, $prefixInterceptors, $suffixInterceptors) : self { $selfInstance = new static(); // note: static because on-the-fly generated classes in tests extend this one. $selfInstance->instance = $instance; $selfInstance->prefixInterceptors = $prefixInterceptors; $selfInstance->suffixInterceptors = $suffixInterceptors; return $selfInstance; } public function setMethodPrefixInterceptor(string $methodName, \Closure $prefixInterceptor = null) : void { // no-op (on purpose) } public function setMethodSuffixInterceptor(string $methodName, \Closure $suffixInterceptor = null) : void { // no-op (on purpose) } public function getWrappedValueHolderValue() : ?object { return $this->instance; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/BaseClass.php000066400000000000000000000041301407505032400255740ustar00rootroot00000000000000 * @license MIT */ class BaseClass implements BaseInterface { /** * @var string */ public $publicProperty = 'publicPropertyDefault'; /** * @var string */ protected $protectedProperty = 'protectedPropertyDefault'; /** * @var string */ private $privateProperty = 'privatePropertyDefault'; /** * @return string */ public function publicMethod() { return 'publicMethodDefault'; } /** * @return string */ public function publicPropertyGetter() { return $this->publicProperty; } /** * @return string */ public function protectedPropertyGetter() { return $this->protectedProperty; } /** * @return string */ public function privatePropertyGetter() { return $this->privateProperty; } /** * @return string */ protected function protectedMethod() { return 'protectedMethodDefault'; } /** * @return string */ private function privateMethod() { return 'privateMethodDefault'; } /** * @param \stdClass $param * * @return string */ public function publicTypeHintedMethod(\stdClass $param) { return 'publicTypeHintedMethodDefault'; } /** * @param array $param * * @return string */ public function publicArrayHintedMethod(array $param) { return 'publicArrayHintedMethodDefault'; } /** * @return string */ public function & publicByReferenceMethod() { $returnValue = 'publicByReferenceMethodDefault'; return $returnValue; } /** * @param mixed $param * @param mixed $byRefParam * * @return string */ public function publicByReferenceParameterMethod($param, & $byRefParam) { return 'publicByReferenceParameterMethodDefault'; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/BaseInterface.php000066400000000000000000000005171407505032400264340ustar00rootroot00000000000000 * @license MIT */ interface BaseInterface { /** * @return string */ public function publicMethod(); } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/CallableInterface.php000066400000000000000000000003251407505032400272560ustar00rootroot00000000000000 * @license MIT */ class CallableTypeHintClass { /** * @param callable $parameter * * @return callable */ public function callableTypeHintMethod(callable $parameter) { return $parameter; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithAbstractMagicMethods.php000066400000000000000000000010461407505032400316110ustar00rootroot00000000000000 * @license MIT */ abstract class ClassWithAbstractMagicMethods { abstract public function __set($name, $value); abstract public function __get($name); abstract public function __isset($name); abstract public function __unset($name); abstract public function __sleep(); abstract public function __wakeup(); abstract public function __clone(); } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithAbstractProtectedMethod.php000066400000000000000000000005131407505032400323350ustar00rootroot00000000000000 * @license MIT */ abstract class ClassWithAbstractProtectedMethod { /** * @return void */ abstract protected function protectedAbstractMethod(); } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithAbstractPublicMethod.php000066400000000000000000000004771407505032400316330ustar00rootroot00000000000000 * @license MIT */ abstract class ClassWithAbstractPublicMethod { /** * @return void */ abstract public function publicAbstractMethod(); } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithByRefMagicMethods.php000066400000000000000000000012521407505032400310540ustar00rootroot00000000000000 * @license MIT */ class ClassWithByRefMagicMethods { public function & __set($name, $value) { return [$name => $value]; } public function & __get($name) { return $name; } public function & __isset($name) { return (bool) $name; } public function & __unset($name) { return (bool) $name; } public function & __sleep() { } public function & __wakeup() { } } ClassWithCollidingPrivateInheritedProperties.php000066400000000000000000000006201407505032400346470ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset * @license MIT */ class ClassWithCollidingPrivateInheritedProperties extends ClassWithPrivateProperties { /** * @var string */ private $property0 = 'childClassProperty0'; } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithCounterConstructor.php000066400000000000000000000011671407505032400314520ustar00rootroot00000000000000 * @license MIT */ class ClassWithCounterConstructor { /** * @var int */ public $amount = 0; /** * @param int $increment */ public function __construct($increment) { $this->amount += $increment; } /** * @return int */ public function getAmount() { return $this->amount; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithDynamicArgumentsMethod.php000066400000000000000000000006111407505032400321710ustar00rootroot00000000000000 * @license MIT */ class ClassWithDynamicArgumentsMethod { /** * @param mixed ...$args * * @return mixed[] */ public function dynamicArgumentsMethod() { return func_get_args(); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithFinalMagicMethods.php000066400000000000000000000014231407505032400310760ustar00rootroot00000000000000 * @license MIT */ class ClassWithFinalMagicMethods { final public function __construct() { } final public function __set($name, $value) { return [$name => $value]; } final public function __get($name) { return $name; } final public function __isset($name) { return (bool) $name; } final public function __unset($name) { return (bool) $name; } final public function __sleep() { } final public function __wakeup() { } final public function __clone() { } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithFinalMethods.php000066400000000000000000000006501407505032400301360ustar00rootroot00000000000000 * @license MIT */ class ClassWithFinalMethods extends TestCase { final public function foo() { } private function bar() { } final protected function baz() { } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithMagicMethods.php000066400000000000000000000012701407505032400301240ustar00rootroot00000000000000 * @license MIT */ class ClassWithMagicMethods { public function __set($name, $value) { return [$name => $value]; } public function __get($name) { return $name; } public function __isset($name) { return (bool) $name; } public function __unset($name) { return (bool) $name; } public function __sleep() { return []; } public function __wakeup() { } public function __clone() { } } ClassWithMethodWithByRefVariadicFunction.php000066400000000000000000000007051407505032400336600ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset * @license MIT */ class ClassWithMethodWithByRefVariadicFunction { /** * @param array $fooz * * @return array */ public function tuz(& ...$fooz) { $fooz[1] = 'changed'; return $fooz; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithMethodWithDefaultParameters.php000066400000000000000000000006571407505032400331750ustar00rootroot00000000000000 * @license MIT */ class ClassWithMethodWithDefaultParameters { /** * @param array $parameter * * @return string */ public function publicMethodWithDefaults(array $parameter = ['foo']) { return 'defaultValue'; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithMethodWithVariadicFunction.php000066400000000000000000000012311407505032400330020ustar00rootroot00000000000000 * @license MIT */ class ClassWithMethodWithVariadicFunction { /** * @var mixed */ public $bar; /** * @var mixed */ public $baz; /** * @param mixed $bar * @param mixed $baz */ public function foo($bar, ...$baz) { $this->bar = $bar; $this->baz = $baz; } /** * @param mixed ...$fooz * * @return mixed[] */ public function buz(...$fooz) { return $fooz; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithMixedProperties.php000066400000000000000000000023501407505032400307030ustar00rootroot00000000000000 * @license MIT */ class ClassWithMixedProperties { /** @var string */ public static $publicStaticProperty = 'publicStaticProperty'; /** @var string */ protected static $protectedStaticProperty = 'protectedStaticProperty'; /** @var string */ private static $privateStaticProperty = 'privateStaticProperty'; /** @var string */ public $publicProperty0 = 'publicProperty0'; /** @var string */ public $publicProperty1 = 'publicProperty1'; /** @var string */ public $publicProperty2 = 'publicProperty2'; /** @var string */ protected $protectedProperty0 = 'protectedProperty0'; /** @var string */ protected $protectedProperty1 = 'protectedProperty1'; /** @var string */ protected $protectedProperty2 = 'protectedProperty2'; /** @var string */ private $privateProperty0 = 'privateProperty0'; /** @var string */ private $privateProperty1 = 'privateProperty1'; /** @var string */ private $privateProperty2 = 'privateProperty2'; } ClassWithMixedPropertiesAndAccessorMethods.php000066400000000000000000000021301407505032400342520ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset * @license MIT */ class ClassWithMixedPropertiesAndAccessorMethods { /** * @var mixed */ public $publicProperty = 'publicProperty'; /** * @var mixed */ protected $protectedProperty = 'protectedProperty'; /** * @var mixed */ private $privateProperty = 'privateProperty'; /** * @param string $name * * @return bool */ public function has($name) { return isset($this->$name); } /** * @param string $name * * @return mixed */ public function get($name) { return $this->$name; } /** * @param string $name * @param mixed $value * * @return void */ public function set($name, $value) { $this->$name = $value; } /** * @param string $name * * @return void */ public function remove($name) { unset($this->$name); } } ClassWithMixedReferenceableTypedProperties.php000066400000000000000000000231311407505032400342750ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset * @license MIT */ class ClassWithMixedReferenceableTypedProperties { public static $publicStaticUnTypedProperty = 'publicStaticUnTypedProperty'; public static $publicStaticUnTypedPropertyWithoutDefaultValue; public static bool $publicStaticBoolProperty = true; public static bool $publicStaticBoolPropertyWithoutDefaultValue; public static ?bool $publicStaticNullableBoolProperty = true; public static ?bool $publicStaticNullableBoolPropertyWithoutDefaultValue; public static int $publicStaticIntProperty = 123; public static int $publicStaticIntPropertyWithoutDefaultValue; public static ?int $publicStaticNullableIntProperty = 123; public static ?int $publicStaticNullableIntPropertyWithoutDefaultValue; public static float $publicStaticFloatProperty = 123.456; public static float $publicStaticFloatPropertyWithoutDefaultValue; public static ?float $publicStaticNullableFloatProperty = 123.456; public static ?float $publicStaticNullableFloatPropertyWithoutDefaultValue; public static string $publicStaticStringProperty = 'publicStaticStringProperty'; public static string $publicStaticStringPropertyWithoutDefaultValue; public static ?string $publicStaticNullableStringProperty = 'publicStaticStringProperty'; public static ?string $publicStaticNullableStringPropertyWithoutDefaultValue; public static array $publicStaticArrayProperty = ['publicStaticArrayProperty']; public static array $publicStaticArrayPropertyWithoutDefaultValue; public static ?array $publicStaticNullableArrayProperty = ['publicStaticArrayProperty']; public static ?array $publicStaticNullableArrayPropertyWithoutDefaultValue; public static iterable $publicStaticIterableProperty = ['publicStaticIterableProperty']; public static iterable $publicStaticIterablePropertyWithoutDefaultValue; public static ?iterable $publicStaticNullableIterableProperty = ['publicStaticIterableProperty']; public static ?iterable $publicStaticNullableIterablePropertyWithoutDefaultValue; public static object $publicStaticObjectProperty; public static ?object $publicStaticNullableObjectProperty; public static EmptyClass $publicStaticClassProperty; public static ?EmptyClass $publicStaticNullableClassProperty; protected static $protectedStaticUnTypedProperty = 'protectedStaticUnTypedProperty'; protected static $protectedStaticUnTypedPropertyWithoutDefaultValue; protected static bool $protectedStaticBoolProperty = true; protected static bool $protectedStaticBoolPropertyWithoutDefaultValue; protected static ?bool $protectedStaticNullableBoolProperty = true; protected static ?bool $protectedStaticNullableBoolPropertyWithoutDefaultValue; protected static int $protectedStaticIntProperty = 123; protected static int $protectedStaticIntPropertyWithoutDefaultValue; protected static ?int $protectedStaticNullableIntProperty = 123; protected static ?int $protectedStaticNullableIntPropertyWithoutDefaultValue; protected static float $protectedStaticFloatProperty = 123.456; protected static float $protectedStaticFloatPropertyWithoutDefaultValue; protected static ?float $protectedStaticNullableFloatProperty = 123.456; protected static ?float $protectedStaticNullableFloatPropertyWithoutDefaultValue; protected static string $protectedStaticStringProperty = 'protectedStaticStringProperty'; protected static string $protectedStaticStringPropertyWithoutDefaultValue; protected static ?string $protectedStaticNullableStringProperty = 'protectedStaticStringProperty'; protected static ?string $protectedStaticNullableStringPropertyWithoutDefaultValue; protected static array $protectedStaticArrayProperty = ['protectedStaticArrayProperty']; protected static array $protectedStaticArrayPropertyWithoutDefaultValue; protected static ?array $protectedStaticNullableArrayProperty = ['protectedStaticArrayProperty']; protected static ?array $protectedStaticNullableArrayPropertyWithoutDefaultValue; protected static iterable $protectedStaticIterableProperty = ['protectedStaticIterableProperty']; protected static iterable $protectedStaticIterablePropertyWithoutDefaultValue; protected static ?iterable $protectedStaticNullableIterableProperty = ['protectedStaticIterableProperty']; protected static ?iterable $protectedStaticNullableIterablePropertyWithoutDefaultValue; protected static object $protectedStaticObjectProperty; protected static ?object $protectedStaticNullableObjectProperty; protected static EmptyClass $protectedStaticClassProperty; protected static ?EmptyClass $protectedStaticNullableClassProperty; private static $privateStaticUnTypedProperty = 'privateStaticUnTypedProperty'; private static $privateStaticUnTypedPropertyWithoutDefaultValue; private static bool $privateStaticBoolProperty = true; private static bool $privateStaticBoolPropertyWithoutDefaultValue; private static ?bool $privateStaticNullableBoolProperty = true; private static ?bool $privateStaticNullableBoolPropertyWithoutDefaultValue; private static int $privateStaticIntProperty = 123; private static int $privateStaticIntPropertyWithoutDefaultValue; private static ?int $privateStaticNullableIntProperty = 123; private static ?int $privateStaticNullableIntPropertyWithoutDefaultValue; private static float $privateStaticFloatProperty = 123.456; private static float $privateStaticFloatPropertyWithoutDefaultValue; private static ?float $privateStaticNullableFloatProperty = 123.456; private static ?float $privateStaticNullableFloatPropertyWithoutDefaultValue; private static string $privateStaticStringProperty = 'privateStaticStringProperty'; private static string $privateStaticStringPropertyWithoutDefaultValue; private static ?string $privateStaticNullableStringProperty = 'privateStaticStringProperty'; private static ?string $privateStaticNullableStringPropertyWithoutDefaultValue; private static array $privateStaticArrayProperty = ['privateStaticArrayProperty']; private static array $privateStaticArrayPropertyWithoutDefaultValue; private static ?array $privateStaticNullableArrayProperty = ['privateStaticArrayProperty']; private static ?array $privateStaticNullableArrayPropertyWithoutDefaultValue; private static iterable $privateStaticIterableProperty = ['privateStaticIterableProperty']; private static iterable $privateStaticIterablePropertyWithoutDefaultValue; private static ?iterable $privateStaticNullableIterableProperty = ['privateStaticIterableProperty']; private static ?iterable $privateStaticNullableIterablePropertyWithoutDefaultValue; private static object $privateStaticObjectProperty; private static ?object $privateStaticNullableObjectProperty; private static EmptyClass $privateStaticClassProperty; private static ?EmptyClass $privateStaticNullableClassProperty; public $publicUnTypedProperty = 'publicUnTypedProperty'; public bool $publicBoolProperty = true; public ?bool $publicNullableBoolProperty = true; public int $publicIntProperty = 123; public ?int $publicNullableIntProperty = 123; public float $publicFloatProperty = 123.456; public ?float $publicNullableFloatProperty = 123.456; public string $publicStringProperty = 'publicStringProperty'; public ?string $publicNullableStringProperty = 'publicStringProperty'; public array $publicArrayProperty = ['publicArrayProperty']; public ?array $publicNullableArrayProperty = ['publicArrayProperty']; public iterable $publicIterableProperty = ['publicIterableProperty']; public ?iterable $publicNullableIterableProperty = ['publicIterableProperty']; protected $protectedUnTypedProperty = 'protectedUnTypedProperty'; protected bool $protectedBoolProperty = true; protected ?bool $protectedNullableBoolProperty = true; protected int $protectedIntProperty = 123; protected ?int $protectedNullableIntProperty = 123; protected float $protectedFloatProperty = 123.456; protected ?float $protectedNullableFloatProperty = 123.456; protected string $protectedStringProperty = 'protectedStringProperty'; protected ?string $protectedNullableStringProperty = 'protectedStringProperty'; protected array $protectedArrayProperty = ['protectedArrayProperty']; protected ?array $protectedNullableArrayProperty = ['protectedArrayProperty']; protected iterable $protectedIterableProperty = ['protectedIterableProperty']; protected ?iterable $protectedNullableIterableProperty = ['protectedIterableProperty']; private $privateUnTypedProperty = 'privateUnTypedProperty'; private bool $privateBoolProperty = true; private ?bool $privateNullableBoolProperty = true; private int $privateIntProperty = 123; private ?int $privateNullableIntProperty = 123; private float $privateFloatProperty = 123.456; private ?float $privateNullableFloatProperty = 123.456; private string $privateStringProperty = 'privateStringProperty'; private ?string $privateNullableStringProperty = 'privateStringProperty'; private array $privateArrayProperty = ['privateArrayProperty']; private ?array $privateNullableArrayProperty = ['privateArrayProperty']; private iterable $privateIterableProperty = ['privateIterableProperty']; private ?iterable $privateNullableIterableProperty = ['privateIterableProperty']; } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithMixedTypedProperties.php000066400000000000000000000312001407505032400317050ustar00rootroot00000000000000 * @license MIT */ class ClassWithMixedTypedProperties { public static $publicStaticUnTypedProperty = 'publicStaticUnTypedProperty'; public static $publicStaticUnTypedPropertyWithoutDefaultValue; public static bool $publicStaticBoolProperty = true; public static bool $publicStaticBoolPropertyWithoutDefaultValue; public static ?bool $publicStaticNullableBoolProperty = true; public static ?bool $publicStaticNullableBoolPropertyWithoutDefaultValue; public static int $publicStaticIntProperty = 123; public static int $publicStaticIntPropertyWithoutDefaultValue; public static ?int $publicStaticNullableIntProperty = 123; public static ?int $publicStaticNullableIntPropertyWithoutDefaultValue; public static float $publicStaticFloatProperty = 123.456; public static float $publicStaticFloatPropertyWithoutDefaultValue; public static ?float $publicStaticNullableFloatProperty = 123.456; public static ?float $publicStaticNullableFloatPropertyWithoutDefaultValue; public static string $publicStaticStringProperty = 'publicStaticStringProperty'; public static string $publicStaticStringPropertyWithoutDefaultValue; public static ?string $publicStaticNullableStringProperty = 'publicStaticStringProperty'; public static ?string $publicStaticNullableStringPropertyWithoutDefaultValue; public static array $publicStaticArrayProperty = ['publicStaticArrayProperty']; public static array $publicStaticArrayPropertyWithoutDefaultValue; public static ?array $publicStaticNullableArrayProperty = ['publicStaticArrayProperty']; public static ?array $publicStaticNullableArrayPropertyWithoutDefaultValue; public static iterable $publicStaticIterableProperty = ['publicStaticIterableProperty']; public static iterable $publicStaticIterablePropertyWithoutDefaultValue; public static ?iterable $publicStaticNullableIterableProperty = ['publicStaticIterableProperty']; public static ?iterable $publicStaticNullableIterablePropertyWithoutDefaultValue; public static object $publicStaticObjectProperty; public static ?object $publicStaticNullableObjectProperty; public static EmptyClass $publicStaticClassProperty; public static ?EmptyClass $publicStaticNullableClassProperty; protected static $protectedStaticUnTypedProperty = 'protectedStaticUnTypedProperty'; protected static $protectedStaticUnTypedPropertyWithoutDefaultValue; protected static bool $protectedStaticBoolProperty = true; protected static bool $protectedStaticBoolPropertyWithoutDefaultValue; protected static ?bool $protectedStaticNullableBoolProperty = true; protected static ?bool $protectedStaticNullableBoolPropertyWithoutDefaultValue; protected static int $protectedStaticIntProperty = 123; protected static int $protectedStaticIntPropertyWithoutDefaultValue; protected static ?int $protectedStaticNullableIntProperty = 123; protected static ?int $protectedStaticNullableIntPropertyWithoutDefaultValue; protected static float $protectedStaticFloatProperty = 123.456; protected static float $protectedStaticFloatPropertyWithoutDefaultValue; protected static ?float $protectedStaticNullableFloatProperty = 123.456; protected static ?float $protectedStaticNullableFloatPropertyWithoutDefaultValue; protected static string $protectedStaticStringProperty = 'protectedStaticStringProperty'; protected static string $protectedStaticStringPropertyWithoutDefaultValue; protected static ?string $protectedStaticNullableStringProperty = 'protectedStaticStringProperty'; protected static ?string $protectedStaticNullableStringPropertyWithoutDefaultValue; protected static array $protectedStaticArrayProperty = ['protectedStaticArrayProperty']; protected static array $protectedStaticArrayPropertyWithoutDefaultValue; protected static ?array $protectedStaticNullableArrayProperty = ['protectedStaticArrayProperty']; protected static ?array $protectedStaticNullableArrayPropertyWithoutDefaultValue; protected static iterable $protectedStaticIterableProperty = ['protectedStaticIterableProperty']; protected static iterable $protectedStaticIterablePropertyWithoutDefaultValue; protected static ?iterable $protectedStaticNullableIterableProperty = ['protectedStaticIterableProperty']; protected static ?iterable $protectedStaticNullableIterablePropertyWithoutDefaultValue; protected static object $protectedStaticObjectProperty; protected static ?object $protectedStaticNullableObjectProperty; protected static EmptyClass $protectedStaticClassProperty; protected static ?EmptyClass $protectedStaticNullableClassProperty; private static $privateStaticUnTypedProperty = 'privateStaticUnTypedProperty'; private static $privateStaticUnTypedPropertyWithoutDefaultValue; private static bool $privateStaticBoolProperty = true; private static bool $privateStaticBoolPropertyWithoutDefaultValue; private static ?bool $privateStaticNullableBoolProperty = true; private static ?bool $privateStaticNullableBoolPropertyWithoutDefaultValue; private static int $privateStaticIntProperty = 123; private static int $privateStaticIntPropertyWithoutDefaultValue; private static ?int $privateStaticNullableIntProperty = 123; private static ?int $privateStaticNullableIntPropertyWithoutDefaultValue; private static float $privateStaticFloatProperty = 123.456; private static float $privateStaticFloatPropertyWithoutDefaultValue; private static ?float $privateStaticNullableFloatProperty = 123.456; private static ?float $privateStaticNullableFloatPropertyWithoutDefaultValue; private static string $privateStaticStringProperty = 'privateStaticStringProperty'; private static string $privateStaticStringPropertyWithoutDefaultValue; private static ?string $privateStaticNullableStringProperty = 'privateStaticStringProperty'; private static ?string $privateStaticNullableStringPropertyWithoutDefaultValue; private static array $privateStaticArrayProperty = ['privateStaticArrayProperty']; private static array $privateStaticArrayPropertyWithoutDefaultValue; private static ?array $privateStaticNullableArrayProperty = ['privateStaticArrayProperty']; private static ?array $privateStaticNullableArrayPropertyWithoutDefaultValue; private static iterable $privateStaticIterableProperty = ['privateStaticIterableProperty']; private static iterable $privateStaticIterablePropertyWithoutDefaultValue; private static ?iterable $privateStaticNullableIterableProperty = ['privateStaticIterableProperty']; private static ?iterable $privateStaticNullableIterablePropertyWithoutDefaultValue; private static object $privateStaticObjectProperty; private static ?object $privateStaticNullableObjectProperty; private static EmptyClass $privateStaticClassProperty; private static ?EmptyClass $privateStaticNullableClassProperty; public $publicUnTypedProperty = 'publicUnTypedProperty'; public $publicUnTypedPropertyWithoutDefaultValue; public bool $publicBoolProperty = true; public bool $publicBoolPropertyWithoutDefaultValue; public ?bool $publicNullableBoolProperty = true; public ?bool $publicNullableBoolPropertyWithoutDefaultValue; public int $publicIntProperty = 123; public int $publicIntPropertyWithoutDefaultValue; public ?int $publicNullableIntProperty = 123; public ?int $publicNullableIntPropertyWithoutDefaultValue; public float $publicFloatProperty = 123.456; public float $publicFloatPropertyWithoutDefaultValue; public ?float $publicNullableFloatProperty = 123.456; public ?float $publicNullableFloatPropertyWithoutDefaultValue; public string $publicStringProperty = 'publicStringProperty'; public string $publicStringPropertyWithoutDefaultValue; public ?string $publicNullableStringProperty = 'publicStringProperty'; public ?string $publicNullableStringPropertyWithoutDefaultValue; public array $publicArrayProperty = ['publicArrayProperty']; public array $publicArrayPropertyWithoutDefaultValue; public ?array $publicNullableArrayProperty = ['publicArrayProperty']; public ?array $publicNullableArrayPropertyWithoutDefaultValue; public iterable $publicIterableProperty = ['publicIterableProperty']; public iterable $publicIterablePropertyWithoutDefaultValue; public ?iterable $publicNullableIterableProperty = ['publicIterableProperty']; public ?iterable $publicNullableIterablePropertyWithoutDefaultValue; public object $publicObjectProperty; public ?object $publicNullableObjectProperty; public EmptyClass $publicClassProperty; public ?EmptyClass $publicNullableClassProperty; protected $protectedUnTypedProperty = 'protectedUnTypedProperty'; protected $protectedUnTypedPropertyWithoutDefaultValue; protected bool $protectedBoolProperty = true; protected bool $protectedBoolPropertyWithoutDefaultValue; protected ?bool $protectedNullableBoolProperty = true; protected ?bool $protectedNullableBoolPropertyWithoutDefaultValue; protected int $protectedIntProperty = 123; protected int $protectedIntPropertyWithoutDefaultValue; protected ?int $protectedNullableIntProperty = 123; protected ?int $protectedNullableIntPropertyWithoutDefaultValue; protected float $protectedFloatProperty = 123.456; protected float $protectedFloatPropertyWithoutDefaultValue; protected ?float $protectedNullableFloatProperty = 123.456; protected ?float $protectedNullableFloatPropertyWithoutDefaultValue; protected string $protectedStringProperty = 'protectedStringProperty'; protected string $protectedStringPropertyWithoutDefaultValue; protected ?string $protectedNullableStringProperty = 'protectedStringProperty'; protected ?string $protectedNullableStringPropertyWithoutDefaultValue; protected array $protectedArrayProperty = ['protectedArrayProperty']; protected array $protectedArrayPropertyWithoutDefaultValue; protected ?array $protectedNullableArrayProperty = ['protectedArrayProperty']; protected ?array $protectedNullableArrayPropertyWithoutDefaultValue; protected iterable $protectedIterableProperty = ['protectedIterableProperty']; protected iterable $protectedIterablePropertyWithoutDefaultValue; protected ?iterable $protectedNullableIterableProperty = ['protectedIterableProperty']; protected ?iterable $protectedNullableIterablePropertyWithoutDefaultValue; protected object $protectedObjectProperty; protected ?object $protectedNullableObjectProperty; protected EmptyClass $protectedClassProperty; protected ?EmptyClass $protectedNullableClassProperty; private $privateUnTypedProperty = 'privateUnTypedProperty'; private $privateUnTypedPropertyWithoutDefaultValue; private bool $privateBoolProperty = true; private bool $privateBoolPropertyWithoutDefaultValue; private ?bool $privateNullableBoolProperty = true; private ?bool $privateNullableBoolPropertyWithoutDefaultValue; private int $privateIntProperty = 123; private int $privateIntPropertyWithoutDefaultValue; private ?int $privateNullableIntProperty = 123; private ?int $privateNullableIntPropertyWithoutDefaultValue; private float $privateFloatProperty = 123.456; private float $privateFloatPropertyWithoutDefaultValue; private ?float $privateNullableFloatProperty = 123.456; private ?float $privateNullableFloatPropertyWithoutDefaultValue; private string $privateStringProperty = 'privateStringProperty'; private string $privateStringPropertyWithoutDefaultValue; private ?string $privateNullableStringProperty = 'privateStringProperty'; private ?string $privateNullableStringPropertyWithoutDefaultValue; private array $privateArrayProperty = ['privateArrayProperty']; private array $privateArrayPropertyWithoutDefaultValue; private ?array $privateNullableArrayProperty = ['privateArrayProperty']; private ?array $privateNullableArrayPropertyWithoutDefaultValue; private iterable $privateIterableProperty = ['privateIterableProperty']; private iterable $privateIterablePropertyWithoutDefaultValue; private ?iterable $privateNullableIterableProperty = ['privateIterableProperty']; private ?iterable $privateNullableIterablePropertyWithoutDefaultValue; private object $privateObjectProperty; private ?object $privateNullableObjectProperty; private EmptyClass $privateClassProperty; private ?EmptyClass $privateNullableClassProperty; } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithParentHint.php000066400000000000000000000006211407505032400276330ustar00rootroot00000000000000 * @license MIT */ class ClassWithParentHint extends EmptyClass { public function parentHintMethod(parent $parameter) { return $parameter; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithPhp80TypedMethods.php000066400000000000000000000030671407505032400310170ustar00rootroot00000000000000 * @license MIT */ class ClassWithPrivateProperties { private $property0 = 'property0'; private $property1 = 'property1'; private $property2 = 'property2'; private $property3 = 'property3'; private $property4 = 'property4'; private $property5 = 'property5'; private $property6 = 'property6'; private $property7 = 'property7'; private $property8 = 'property8'; private $property9 = 'property9'; } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithProtectedMethod.php000066400000000000000000000004271407505032400306550ustar00rootroot00000000000000 * @license MIT */ abstract class ClassWithProtectedMethod { protected function protectedMethod() : void { } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithProtectedProperties.php000066400000000000000000000012101407505032400315600ustar00rootroot00000000000000 * @license MIT */ class ClassWithProtectedProperties { protected $property0 = 'property0'; protected $property1 = 'property1'; protected $property2 = 'property2'; protected $property3 = 'property3'; protected $property4 = 'property4'; protected $property5 = 'property5'; protected $property6 = 'property6'; protected $property7 = 'property7'; protected $property8 = 'property8'; protected $property9 = 'property9'; } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithPublicArrayProperty.php000066400000000000000000000005371407505032400315470ustar00rootroot00000000000000 * @license MIT */ class ClassWithPublicArrayProperty { /** @var mixed[] */ public $arrayProperty = []; } ClassWithPublicArrayPropertyAccessibleViaMethod.php000066400000000000000000000007561407505032400352520ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset * @license MIT */ class ClassWithPublicArrayPropertyAccessibleViaMethod { /** @var mixed[] */ public $arrayProperty = []; /** @return mixed[] */ public function getArrayProperty() : array { return $this->arrayProperty; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithPublicProperties.php000066400000000000000000000015121407505032400310520ustar00rootroot00000000000000 * @license MIT */ class ClassWithPublicProperties { /** @var string */ public $property0 = 'property0'; /** @var string */ public $property1 = 'property1'; /** @var string */ public $property2 = 'property2'; /** @var string */ public $property3 = 'property3'; /** @var string */ public $property4 = 'property4'; /** @var string */ public $property5 = 'property5'; /** @var string */ public $property6 = 'property6'; /** @var string */ public $property7 = 'property7'; /** @var string */ public $property8 = 'property8'; /** @var string */ public $property9 = 'property9'; } ClassWithPublicStringNullableNullDefaultTypedProperty.php000066400000000000000000000005771407505032400365110ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset * @license MIT */ class ClassWithPublicStringNullableNullDefaultTypedProperty { public ?string $typedNullableNullDefaultProperty = null; } ClassWithPublicStringNullableTypedProperty.php000066400000000000000000000005111407505032400343350ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset * @license MIT */ class ClassWithPublicStringNullableTypedProperty { public ?string $typedNullableProperty; } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithPublicStringTypedProperty.php000066400000000000000000000005061407505032400327410ustar00rootroot00000000000000 * @license MIT */ class ClassWithPublicStringTypedProperty { public string $typedProperty; } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithSelfHint.php000066400000000000000000000005711407505032400272770ustar00rootroot00000000000000 * @license MIT */ class ClassWithSelfHint { public function selfHintMethod(self $parameter) { return $parameter; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ClassWithVariadicConstructorArgument.php000066400000000000000000000011341407505032400332520ustar00rootroot00000000000000 * @license MIT */ class ClassWithVariadicConstructorArgument { /** * @var mixed */ private $foo; /** * @var array */ private $bar; /** * ClassWithVariadicConstructorArguments constructor. * * @param mixed $foo * @param array ...$bar */ public function __construct($foo, ... $bar) { $this->foo = $foo; $this->bar = $bar; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/EmptyClass.php000066400000000000000000000002641407505032400260240ustar00rootroot00000000000000 * @license MIT */ class EmptyClass { } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/FinalClass.php000066400000000000000000000002761407505032400257620ustar00rootroot00000000000000 * @license MIT */ final class FinalClass { } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/HydratedObject.php000066400000000000000000000011261407505032400266310ustar00rootroot00000000000000 * @license MIT */ class HydratedObject { /** * @var mixed */ public $foo = 1; /** * @var mixed */ protected $bar = 2; /** * @var mixed */ private $baz = 3; /** * Method to be disabled */ public function doFoo() { } /** * @param string $name * * @return mixed */ public function __get($name) { return $this->$name; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/IterableMethodTypeHintedInterface.php000066400000000000000000000002441407505032400324450ustar00rootroot00000000000000 * @license MIT */ class IterableTypeHintClass { public function iterableTypeHintMethod(iterable $parameter) : iterable { return $parameter; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/LazyLoadingMock.php000066400000000000000000000026241407505032400267710ustar00rootroot00000000000000 * @license MIT */ class LazyLoadingMock implements VirtualProxyInterface, GhostObjectInterface { /** * @var callable */ public $initializer; /** * @param callable $initializer * * @return static */ public static function staticProxyConstructor($initializer) : self { $instance = new static(); $instance->initializer = $initializer; return $instance; } public function setProxyInitializer(\Closure $initializer = null) : void { $this->initializer = $initializer; } public function getProxyInitializer() : ?\Closure { return $this->initializer; } public function initializeProxy() : bool { // empty (on purpose) return true; } public function isProxyInitialized() : bool { return true; } /** * {@inheritDoc} * * @throws BadMethodCallException */ public function getWrappedValueHolderValue() : ?object { // we're not supposed to call this throw new BadMethodCallException('Not implemented'); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/NullObjectMock.php000066400000000000000000000007001407505032400266060ustar00rootroot00000000000000 * @license MIT */ class NullObjectMock implements NullObjectInterface { /** * @return static */ public static function staticProxyConstructor() : self { return new static(); } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ObjectMethodTypeHintedInterface.php000066400000000000000000000020641407505032400321260ustar00rootroot00000000000000 * @license MIT */ class ObjectTypeHintClass { /** * @param object $parameter * * @return object */ public function objectTypeHintMethod(object $parameter) { return $parameter; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/OtherObjectAccessClass.php000066400000000000000000000013201407505032400302520ustar00rootroot00000000000000privateProperty; } public function getProtectedProperty(self $other) : string { return $other->protectedProperty; } public function getPublicProperty(self $other) : string { return $other->publicProperty; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ProxyGenerator/000077500000000000000000000000001407505032400262155ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ProxyGenerator/LazyLoading/000077500000000000000000000000001407505032400304325ustar00rootroot00000000000000MethodGenerator/000077500000000000000000000000001407505032400334425ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ProxyGenerator/LazyLoadingClassWithTwoPublicProperties.php000066400000000000000000000005541407505032400417660ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ProxyGenerator/LazyLoading/MethodGenerator * @license MIT */ class ClassWithTwoPublicProperties { /** * @var mixed */ public $bar; /** * @var mixed */ public $baz; } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/RemoteProxy/000077500000000000000000000000001407505032400255225ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/RemoteProxy/BazServiceInterface.php000066400000000000000000000005111407505032400321060ustar00rootroot00000000000000 * @license MIT */ interface BazServiceInterface { /** * @param string $param * * @return string */ public function baz($param); } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/RemoteProxy/Foo.php000066400000000000000000000012311407505032400267530ustar00rootroot00000000000000 * @license MIT */ class Foo implements FooServiceInterface, BazServiceInterface { /** * @return string */ public function foo() { return 'bar remote'; } /** * @param string $param * * @return string */ public function baz($param) { return $param . ' remote'; } /** * @param string $name * * @return string */ public function __get($name) { return $name . ' remote'; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/RemoteProxy/FooServiceInterface.php000066400000000000000000000004401407505032400321160ustar00rootroot00000000000000 * @license MIT */ interface FooServiceInterface { /** * @return string */ public function foo(); } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/RemoteProxy/RemoteObjectMock.php000066400000000000000000000006711407505032400314330ustar00rootroot00000000000000 * @license MIT */ class RemoteObjectMock implements RemoteObjectInterface { /** * @return static */ public static function staticProxyConstructor() : self { return new static(); } } RemoteServiceWithDefaultsAndVariadicArguments.php000066400000000000000000000006341407505032400372330ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/RemoteProxy * @license MIT */ interface VariadicArgumentsServiceInterface { public function method(string $param1, int ...$param2) : bool; } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/ReturnTypeHintedClass.php000066400000000000000000000015521407505032400302040ustar00rootroot00000000000000counter += $amount; } } php-proxy-manager-2.11.1+1.0.5/tests/ProxyManagerTestAsset/VoidMethodTypeHintedClass.php000066400000000000000000000002331407505032400307620ustar00rootroot00000000000000createProxy(new Kitchen()); var_dump(isset($proxy->sweets)); ?> --EXPECT-- bool(false)access-interceptor-denies-private-property-read.phpt000066400000000000000000000006421407505032400357770ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow private property direct read --FILE-- createProxy(new Kitchen()); $proxy->sweets; ?> --EXPECTF-- %SFatal error:%sCannot access private property %s::$sweets in %aaccess-interceptor-denies-private-property-unset.phpt000066400000000000000000000006171407505032400362240ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow private property direct unset --FILE-- createProxy(new Kitchen()); unset($proxy->sweets); ?> --EXPECTF-- %SFatal error:%sCannot %s property %aaccess-interceptor-denies-private-property-write.phpt000066400000000000000000000006371407505032400362220ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow private property direct write --FILE-- createProxy(new Kitchen()); $proxy->sweets = 'stolen'; ?> --EXPECTF-- %SFatal error:%sCannot access %s property%S in %aaccess-interceptor-denies-protected-property-isset.phpt000066400000000000000000000006221407505032400365300ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow protected property direct isset check --FILE-- createProxy(new Kitchen()); var_dump(isset($proxy->sweets)); ?> --EXPECT-- bool(false)access-interceptor-denies-protected-property-read.phpt000066400000000000000000000006501407505032400363150ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow protected property direct read --FILE-- createProxy(new Kitchen()); $proxy->sweets; ?> --EXPECTF-- %SFatal error:%sCannot access protected property %s::$sweets in %aaccess-interceptor-denies-protected-property-unset.phpt000066400000000000000000000006271407505032400365440ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow protected property direct unset --FILE-- createProxy(new Kitchen()); unset($proxy->sweets); ?> --EXPECTF-- %SFatal error:%sCannot %s property%sin %aaccess-interceptor-denies-protected-property-write.phpt000066400000000000000000000006331407505032400365350ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow protected property direct write --FILE-- createProxy(new Kitchen()); $proxy->sweets = 'stolen'; ?> --EXPECTF-- %SFatal error:%sCannot %s property%sin %aaccess-interceptor-scope-localizer-denies-private-property-isset.phpt000066400000000000000000000006221407505032400413020ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow private property direct isset check --FILE-- createProxy(new Kitchen()); var_dump(isset($proxy->sweets)); ?> --EXPECT-- bool(false) access-interceptor-scope-localizer-denies-private-property-read.phpt000066400000000000000000000006451407505032400410730ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow private property direct read --FILE-- createProxy(new Kitchen()); $proxy->sweets; ?> --EXPECTF-- %SFatal error:%sCannot access private property %s::$sweets in %aaccess-interceptor-scope-localizer-denies-private-property-unset.phpt000066400000000000000000000006261407505032400413150ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow private property direct unset --FILE-- createProxy(new Kitchen()); unset($proxy->sweets); ?> --EXPECTF-- %SFatal error:%sCannot %s property%sin %aaccess-interceptor-scope-localizer-denies-private-property-write.phpt000066400000000000000000000006321407505032400413060ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow private property direct write --FILE-- createProxy(new Kitchen()); $proxy->sweets = 'stolen'; ?> --EXPECTF-- %SFatal error:%sCannot %s property%sin %aaccess-interceptor-scope-localizer-denies-protected-property-isset.phpt000066400000000000000000000006261407505032400416250ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow protected property direct isset check --FILE-- createProxy(new Kitchen()); var_dump(isset($proxy->sweets)); ?> --EXPECT-- bool(false) access-interceptor-scope-localizer-denies-protected-property-read.phpt000066400000000000000000000006531407505032400414110ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow protected property direct read --FILE-- createProxy(new Kitchen()); $proxy->sweets; ?> --EXPECTF-- %SFatal error:%sCannot access protected property %s::$sweets in %aaccess-interceptor-scope-localizer-denies-protected-property-unset.phpt000066400000000000000000000006321407505032400416310ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow protected property direct unset --FILE-- createProxy(new Kitchen()); unset($proxy->sweets); ?> --EXPECTF-- %SFatal error:%sCannot %s property%sin %aaccess-interceptor-scope-localizer-denies-protected-property-write.phpt000066400000000000000000000006361407505032400416310ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors disallow protected property direct write --FILE-- createProxy(new Kitchen()); $proxy->sweets = 'stolen'; ?> --EXPECTF-- %SFatal error:%sCannot %s property%sin %aaccess-interceptor-scope-localizer-serialized-class-private-property-isset.phpt000066400000000000000000000011541407505032400432720ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors doesn't throw PHP Warning on Serialized class private property direct isset check --FILE-- sweets; } function unserialize($serialized) { $this->sweets = $serialized; } } $factory = new \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory($configuration); $proxy = $factory->createProxy(new Kitchen()); var_dump(isset($proxy->sweets)); ?> --EXPECT-- bool(false) access-interceptor-scope-localizer-serialized-class-private-property-read.phpt000066400000000000000000000012121407505032400430510ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors doesn't throw PHP Warning on Serialized class private property direct read --FILE-- sweets; } function unserialize($serialized) { $this->sweets = $serialized; } } $factory = new \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory($configuration); $proxy = $factory->createProxy(new Kitchen()); $proxy->sweets; ?> --EXPECTF-- %SFatal error:%sCannot access private property %s::$sweets in %a access-interceptor-scope-localizer-serialized-class-private-property-unset.phpt000066400000000000000000000011731407505032400433020ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors doesn't throw PHP Warning on Serialized class private property direct unset --FILE-- sweets; } function unserialize($serialized) { $this->sweets = $serialized; } } $factory = new \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory($configuration); $proxy = $factory->createProxy(new Kitchen()); unset($proxy->sweets); ?> --EXPECTF-- %SFatal error:%sCannot %s property%sin %a access-interceptor-scope-localizer-serialized-class-private-property-write.phpt000066400000000000000000000011771407505032400433020ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors doesn't throw PHP Warning on Serialized class private property direct write --FILE-- sweets; } function unserialize($serialized) { $this->sweets = $serialized; } } $factory = new \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory($configuration); $proxy = $factory->createProxy(new Kitchen()); $proxy->sweets = 'stolen'; ?> --EXPECTF-- %SFatal error:%sCannot %s property%sin %a access-interceptor-scope-localizer-serialized-class-protected-property-isset.phpt000066400000000000000000000011601407505032400436060ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors doesn't throw PHP Warning on Serialized class protected property direct isset check --FILE-- sweets; } function unserialize($serialized) { $this->sweets = $serialized; } } $factory = new \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory($configuration); $proxy = $factory->createProxy(new Kitchen()); var_dump(isset($proxy->sweets)); ?> --EXPECT-- bool(false) access-interceptor-scope-localizer-serialized-class-protected-property-read.phpt000066400000000000000000000012201407505032400433670ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors doesn't throw PHP Warning on Serialized class protected property direct read --FILE-- sweets; } function unserialize($serialized) { $this->sweets = $serialized; } } $factory = new \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory($configuration); $proxy = $factory->createProxy(new Kitchen()); $proxy->sweets; ?> --EXPECTF-- %SFatal error:%sCannot access protected property %s::$sweets in %a access-interceptor-scope-localizer-serialized-class-protected-property-unset.phpt000066400000000000000000000011771407505032400436250ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors doesn't throw PHP Warning on Serialized class protected property direct unset --FILE-- sweets; } function unserialize($serialized) { $this->sweets = $serialized; } } $factory = new \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory($configuration); $proxy = $factory->createProxy(new Kitchen()); unset($proxy->sweets); ?> --EXPECTF-- %SFatal error:%sCannot %s property%sin %a access-interceptor-scope-localizer-serialized-class-protected-property-write.phpt000066400000000000000000000012031407505032400436070ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated access interceptors doesn't throw PHP Warning on Serialized class protected property direct write --FILE-- sweets; } function unserialize($serialized) { $this->sweets = $serialized; } } $factory = new \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory($configuration); $proxy = $factory->createProxy(new Kitchen()); $proxy->sweets = 'stolen'; ?> --EXPECTF-- %SFatal error:%sCannot %s property%sin %a php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts/access-interceptor-with-cache.phpt000066400000000000000000000014661407505032400323650ustar00rootroot00000000000000--TEST-- Verifies that access interceptor proxy file is generated --FILE-- setProxiesTargetDir(__DIR__ . '/cache'); $fileLocator = new \ProxyManager\FileLocator\FileLocator($configuration->getProxiesTargetDir()); $configuration->setGeneratorStrategy( new \ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy($fileLocator) ); $factory = new \ProxyManager\Factory\AccessInterceptorValueHolderFactory($configuration); $proxy = $factory->createProxy(new Kitchen()); $filename = $fileLocator->getProxyFileName(get_class($proxy)); var_dump(file_exists($filename)); $proxy = $factory->createProxy(new Kitchen()); var_dump(file_exists($filename)); @unlink($filename); ?> --EXPECT-- bool(true) bool(true)php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts/cache/000077500000000000000000000000001407505032400247155ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts/cache/README.md000066400000000000000000000001351407505032400261730ustar00rootroot00000000000000## Integration tests for PHP language features of proxies This folder is used for the cachesphp-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts/init.php000066400000000000000000000004501407505032400253250ustar00rootroot00000000000000setGeneratorStrategy(new EvaluatingGeneratorStrategy()); lazy-loading-ghost-allows-inexisting-magic-property-read.phpt000066400000000000000000000007341407505032400375370ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading ghost objects disallow reading non-existing properties via direct read --FILE-- createProxy(Kitchen::class, function () {}); echo $proxy->nonExisting; ?> --EXPECTF-- nonExistinglazy-loading-ghost-allows-inexisting-property-write.phpt000066400000000000000000000007011407505032400366720ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading ghost objects disallow reading non-existing properties via direct read --FILE-- createProxy(Kitchen::class, function () {}); $proxy->nonExisting = 'I do not exist'; echo $proxy->nonExisting; ?> --EXPECTF-- I do not existlazy-loading-ghost-allows-private-property-isset-checks-in-private-scope.phpt000066400000000000000000000016501407505032400426050ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading ghost objects allows checking property `isset()` in private class scope --FILE-- sweet); } public function hasSour() { return isset($this->sour); } } $factory = new \ProxyManager\Factory\LazyLoadingGhostFactory($configuration); var_dump($factory->createProxy(Kitchen::class, function () {})->hasSweet()); var_dump($factory->createProxy(Kitchen::class, function () {})->hasSour()); /** @var Kitchen $kitchen */ $kitchen = $factory->createProxy(Kitchen::class, function () {}); var_dump($kitchen->hasSweet()); var_dump($kitchen->hasSweet()); var_dump($kitchen->hasSour()); var_dump($kitchen->hasSour()); ?> --EXPECTF-- bool(true) bool(false) bool(true) bool(true) bool(false) bool(false)lazy-loading-ghost-denies-inexisting-property-read.phpt000066400000000000000000000006771407505032400364350ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading ghost objects disallow reading non-existing properties via direct read --FILE-- createProxy(Kitchen::class, function () {}); $proxy->nonExisting; ?> --EXPECTF-- %SNotice: Undefined property: Kitchen::$nonExisting in %alazy-loading-ghost-denies-private-property-isset.phpt000066400000000000000000000006321407505032400361310ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading ghost objects disallow private property direct isset check --FILE-- createProxy(Kitchen::class, function () {}); var_dump(isset($proxy->sweets)); ?> --EXPECT-- bool(false)lazy-loading-ghost-denies-private-property-read.phpt000066400000000000000000000006561407505032400357230ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading ghost objects disallow private property direct read --FILE-- createProxy(Kitchen::class, function () {}); $proxy->sweets; ?> --EXPECTF-- %SFatal error:%sCannot access private property %s::$sweets in %alazy-loading-ghost-denies-private-property-unset.phpt000066400000000000000000000006331407505032400361410ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading ghost objects disallow private property direct unset --FILE-- createProxy(Kitchen::class, function () {}); unset($proxy->sweets); ?> --EXPECTF-- %SFatal error:%sCannot %s property %alazy-loading-ghost-denies-private-property-write.phpt000066400000000000000000000006531407505032400361370ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading ghost objects disallow private property direct write --FILE-- createProxy(Kitchen::class, function () {}); $proxy->sweets = 'stolen'; ?> --EXPECTF-- %SFatal error:%sCannot access %s property%S in %alazy-loading-ghost-denies-protected-property-isset.phpt000066400000000000000000000006361407505032400364540ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading ghost objects disallow protected property direct isset check --FILE-- createProxy(Kitchen::class, function () {}); var_dump(isset($proxy->sweets)); ?> --EXPECT-- bool(false)lazy-loading-ghost-denies-protected-property-read.phpt000066400000000000000000000006641407505032400362410ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading ghost objects disallow protected property direct read --FILE-- createProxy(Kitchen::class, function () {}); $proxy->sweets; ?> --EXPECTF-- %SFatal error:%sCannot access protected property %s::$sweets in %alazy-loading-ghost-denies-protected-property-unset.phpt000066400000000000000000000006431407505032400364610ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading ghost objects disallow protected property direct unset --FILE-- createProxy(Kitchen::class, function () {}); unset($proxy->sweets); ?> --EXPECTF-- %SFatal error:%sCannot %s property%sin %alazy-loading-ghost-denies-protected-property-write.phpt000066400000000000000000000006471407505032400364610ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading ghost objects disallow protected property direct write --FILE-- createProxy(Kitchen::class, function () {}); $proxy->sweets = 'stolen'; ?> --EXPECTF-- %SFatal error:%sCannot %s property%sin %alazy-loading-ghost-multiple-inheritance-private-access.phpt000066400000000000000000000014161407505032400372350ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that private API of proxies is guaranteed to access private properties in any case --FILE-- multiplier * $value; } } class Bar extends Foo { private $multiplier = 5; public function multiply($value) { return $value * parent::multiply($this->multiplier); } } class Baz extends Bar { private $multiplier = 7; public function multiply($value) { return $value * parent::multiply($this->multiplier); } } echo (new \ProxyManager\Factory\LazyLoadingGhostFactory($configuration)) ->createProxy(Baz::class, function () {}) ->multiply(2); ?> --EXPECTF-- 210lazy-loading-ghost-skip-destructor.phpt000066400000000000000000000015361407505032400333510ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading ghost objects can skip calling the proxied destructor --FILE-- createProxy(Destructable::class, $init, ['skipDestructor' => true]); echo "NO __destruct\n"; unset($proxy); $proxy = $factory->createProxy(Destructable::class, $init, ['skipDestructor' => true]); echo 'DO '; $proxy->triggerInit = true; unset($proxy); $proxy = $factory->createProxy(Destructable::class, $init); echo "\nDO "; unset($proxy); ?> --EXPECT-- NO __destruct DO init__destruct DO __destruct php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts/lazy-loading-ghost-with-cache.phpt000066400000000000000000000015141407505032400322760ustar00rootroot00000000000000--TEST-- Verifies that lazy loading ghost proxy file is generated --FILE-- setProxiesTargetDir(__DIR__ . '/cache'); $fileLocator = new \ProxyManager\FileLocator\FileLocator($configuration->getProxiesTargetDir()); $configuration->setGeneratorStrategy( new \ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy($fileLocator) ); $factory = new \ProxyManager\Factory\LazyLoadingGhostFactory($configuration); $proxy = $factory->createProxy(Kitchen::class, function () {}); $filename = $fileLocator->getProxyFileName(get_class($proxy)); var_dump(file_exists($filename)); $proxy = $factory->createProxy(Kitchen::class, function () {}); var_dump(file_exists($filename)); @unlink($filename); ?> --EXPECT-- bool(true) bool(true)lazy-loading-value-holder-denies-interface-property-read.phpt000066400000000000000000000012231407505032400374430ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that lazy loading value holder proxies for interfaces disallow public property read attempts --FILE-- createProxy(MyInterface::class, function (& $wrapped, $proxy, $method, array $parameters, & $initializer) : bool { $initializer = null; $wrapped = new class implements MyInterface { }; return true; }); echo $proxy->someDynamicProperty; ?> --EXPECTF-- Notice: Undefined property: MyInterface::$someDynamicProperty %s lazy-loading-value-holder-denies-private-property-isset.phpt000066400000000000000000000010321407505032400373670ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading value holders disallow private property direct isset check --FILE-- createProxy(Kitchen::class, function (& $wrapped, $proxy, $method, array $parameters, & $initializer) { $initializer = null; $wrapped = new Kitchen(); }); var_dump(isset($proxy->sweets)); ?> --EXPECT-- bool(false)lazy-loading-value-holder-denies-private-property-read.phpt000066400000000000000000000010561407505032400371610ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading value holders disallow private property direct read --FILE-- createProxy(Kitchen::class, function (& $wrapped, $proxy, $method, array $parameters, & $initializer) { $initializer = null; $wrapped = new Kitchen(); }); $proxy->sweets; ?> --EXPECTF-- %SFatal error:%sCannot access private property %s::$sweets in %alazy-loading-value-holder-denies-private-property-unset.phpt000066400000000000000000000010331407505032400373770ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading value holders disallow private property direct unset --FILE-- createProxy(Kitchen::class, function (& $wrapped, $proxy, $method, array $parameters, & $initializer) { $initializer = null; $wrapped = new Kitchen(); }); unset($proxy->sweets); ?> --EXPECTF-- %SFatal error:%sCannot %s property %alazy-loading-value-holder-denies-private-property-write.phpt000066400000000000000000000010461407505032400373770ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading value holders disallow private property direct write --FILE-- createProxy(Kitchen::class, function (& $wrapped, $proxy, $method, array $parameters, & $initializer) { $initializer = null; $wrapped = new Kitchen(); }); $proxy->sweets = 'stolen'; ?> --EXPECTF-- %SFatal error:%sCannot access %s property %alazy-loading-value-holder-denies-protected-property-isset.phpt000066400000000000000000000010361407505032400377120ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading value holders disallow protected property direct isset check --FILE-- createProxy(Kitchen::class, function (& $wrapped, $proxy, $method, array $parameters, & $initializer) { $initializer = null; $wrapped = new Kitchen(); }); var_dump(isset($proxy->sweets)); ?> --EXPECT-- bool(false)lazy-loading-value-holder-denies-protected-property-read.phpt000066400000000000000000000010641407505032400374770ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading value holders disallow protected property direct read --FILE-- createProxy(Kitchen::class, function (& $wrapped, $proxy, $method, array $parameters, & $initializer) { $initializer = null; $wrapped = new Kitchen(); }); $proxy->sweets; ?> --EXPECTF-- %SFatal error:%sCannot access protected property %s::$sweets in %alazy-loading-value-holder-denies-protected-property-unset.phpt000066400000000000000000000010431407505032400377170ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading value holders disallow protected property direct unset --FILE-- createProxy(Kitchen::class, function (& $wrapped, $proxy, $method, array $parameters, & $initializer) { $initializer = null; $wrapped = new Kitchen(); }); unset($proxy->sweets); ?> --EXPECTF-- %SFatal error:%sCannot %s property%sin %alazy-loading-value-holder-denies-protected-property-write.phpt000066400000000000000000000010471407505032400377170ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading value holders disallow protected property direct write --FILE-- createProxy(Kitchen::class, function (& $wrapped, $proxy, $method, array $parameters, & $initializer) { $initializer = null; $wrapped = new Kitchen(); }); $proxy->sweets = 'stolen'; ?> --EXPECTF-- %SFatal error:%sCannot %s property%sin %alazy-loading-value-holder-fluent-safe.phpt000066400000000000000000000013221407505032400336540ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading value holders can be fluent-safe --FILE-- createProxy(FluentClass::class, $init, ['fluentSafe' => true]); echo $proxy->foo() === $proxy; $proxy = $factory->createProxy(FluentClass::class, $init); echo $proxy->foo() === $fluentObject; ?> --EXPECT-- 11 lazy-loading-value-holder-initializer-removes-reference.phpt000066400000000000000000000013421407505032400374020ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that lazy loading value holder cannot be turned to a reference ?> --FILE-- reference = & $wrapped; }; $proxy = $factory->createProxy(Proxied::class, $initializer); $proxy->publicProperty = 123; $clone = clone $proxy; $clone->publicProperty = 234; echo $proxy->publicProperty, "\n"; echo $clone->publicProperty, "\n"; ?> --EXPECT-- 123 234 lazy-loading-value-holder-interface-proxy.phpt000066400000000000000000000014061407505032400345650ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that lazy loading value holder factory can generate proxy for interfaces. --FILE-- createProxy(MyInterface::class, function (& $wrapped, $proxy, $method, array $parameters, & $initializer) { $initializer = null; $wrapped = new MyClass(); }); $proxy->do(); $proxy->someDynamicProperty = ' World'; echo $proxy->someDynamicProperty; ?> --EXPECTF-- Hello Notice: Undefined property: MyInterface::$someDynamicProperty %s World lazy-loading-value-holder-internal-php-classes.phpt000066400000000000000000000016621407505032400355060ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that lazy loading value holder factory can generate proxy for PHP core classes. ?> --SKIPIF-- = 80000) { Laminas\Code\Generator\TypeGenerator::fromTypeString('array|string'); } } catch (\InvalidArgumentException $e) { die('skip laminas/laminas-code >= 3.5 must be installed'); } --FILE-- createProxy(Phar::class, function (& $wrapped, $proxy, $method, array $parameters, & $initializer) { $initializer = null; $wrapped = new PharMock(); }) ->compress(123); ?> --EXPECT-- 123 lazy-loading-value-holder-skip-destructor.phpt000066400000000000000000000016521407505032400346130ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated lazy loading value holders can skip calling the proxied destructor --FILE-- createProxy(Destructable::class, $init, ['skipDestructor' => true]); echo "NO __destruct\n"; unset($proxy); $proxy = $factory->createProxy(Destructable::class, $init, ['skipDestructor' => true]); echo "DO "; $proxy->triggerInit = true; unset($proxy); $proxy = $factory->createProxy(Destructable::class, $init); echo "\nDO "; unset($proxy); ?> --EXPECT-- NO __destruct DO init__destruct__destruct DO init__destruct__destruct lazy-loading-value-holder-with-cache.phpt000066400000000000000000000021151407505032400334600ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that lazy loading value holder proxy file is generated --FILE-- setProxiesTargetDir(__DIR__ . '/cache'); $fileLocator = new \ProxyManager\FileLocator\FileLocator($configuration->getProxiesTargetDir()); $configuration->setGeneratorStrategy( new \ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy($fileLocator) ); $factory = new \ProxyManager\Factory\LazyLoadingValueHolderFactory($configuration); $proxy = $factory->createProxy(Kitchen::class, function (& $wrapped, $proxy, $method, array $parameters, & $initializer) { $initializer = null; $wrapped = new Kitchen(); }); $filename = $fileLocator->getProxyFileName(get_class($proxy)); var_dump(file_exists($filename)); $proxy = $factory->createProxy(Kitchen::class, function (& $wrapped, $proxy, $method, array $parameters, & $initializer) { $initializer = null; $wrapped = new Kitchen(); }); var_dump(file_exists($filename)); @unlink($filename); ?> --EXPECT-- bool(true) bool(true)php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts/null-object-public-function-empty.phpt000066400000000000000000000005601407505032400332210ustar00rootroot00000000000000--TEST-- Verifies that generated null object disallow public function --FILE-- createProxy(Kitchen::class); var_dump($proxy->foo()); ?> --EXPECT-- NULL php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts/null-object-public-property-empty.phpt000066400000000000000000000005131407505032400332560ustar00rootroot00000000000000--TEST-- Verifies that generated null object disallow public function --FILE-- createProxy(Kitchen::class); var_dump($proxy->foo); ?> --EXPECT-- NULL null-object-satisfies-return-type-declaration.phpt000066400000000000000000000006511407505032400354570ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated null object satisfies return type declarations --FILE-- createProxy(Kitchen::class); var_dump($proxy instanceof Kitchen); ?> --EXPECT-- bool(true) remote-object-json-adapter-default-parameters-and-variadic.phpt000066400000000000000000000021311407505032400377140ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated remote object will pass default parameters in method declaration to Adapter. --FILE-- createProxy(FooServiceInterface::class); echo $proxy->fooBar('required') . "\n"; echo $proxy->fooBar('required', 'passed') . "\n"; echo $proxy->fooBar('required', 'passed', 'first_variadic') . "\n"; echo $proxy->fooBar('required', 'passed', 'first_variadic', 'second_variadic') . "\n"; ?> --EXPECTF-- required,default required,passed required,passed,first_variadic required,passed,first_variadic,second_variadic remote-object-json-adapter-denies-unknow-method.phpt000066400000000000000000000015631407505032400356630ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated remote object can call public property --FILE-- createProxy(FooServiceInterface::class); echo $proxy->fooBar() . "\n"; $proxy->unknown(); ?> --EXPECTF-- baz %AFatal error:%sCall to undefined method %s::unknown%S in %A remote-object-json-adapter-passes-default-parameters-correctly.phpt000066400000000000000000000014351407505032400407020ustar00rootroot00000000000000php-proxy-manager-2.11.1+1.0.5/tests/language-feature-scripts--TEST-- Verifies that generated remote object will pass default parameters in method declaration to Adapter. --FILE-- createProxy(FooServiceInterface::class); echo $proxy->fooBar('required') . "\n"; ?> --EXPECTF-- required,default