PK
NiZ README.mdnu W+A # Proxy Manager
This library aims to provide abstraction for generating various kinds of
[proxy classes](http://ocramius.github.io/presentations/proxy-pattern-in-php/).
![ProxyManager](https://raw.githubusercontent.com/Ocramius/ProxyManager/917bf1698243a1079aaa27ed8ea08c2aef09f4cb/proxy-manager.png)
[![Build Status](https://travis-ci.org/Ocramius/ProxyManager.png?branch=master)](https://travis-ci.org/Ocramius/ProxyManager)
[![Code Coverage](https://scrutinizer-ci.com/g/Ocramius/ProxyManager/badges/coverage.png?s=ca3b9ceb9e36aeec0e57569cc8983394b7d2a59e)](https://scrutinizer-ci.com/g/Ocramius/ProxyManager/)
[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/Ocramius/ProxyManager/badges/quality-score.png?s=eaa858f876137ed281141b1d1e98acfa739729ed)](https://scrutinizer-ci.com/g/Ocramius/ProxyManager/)
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/69fe5f97-b1c8-4ddd-93ce-900b8b788cf2/mini.png)](https://insight.sensiolabs.com/projects/69fe5f97-b1c8-4ddd-93ce-900b8b788cf2)
[![Total Downloads](https://poser.pugx.org/ocramius/proxy-manager/downloads.png)](https://packagist.org/packages/ocramius/proxy-manager)
[![Latest Stable Version](https://poser.pugx.org/ocramius/proxy-manager/v/stable.png)](https://packagist.org/packages/ocramius/proxy-manager)
[![Latest Unstable Version](https://poser.pugx.org/ocramius/proxy-manager/v/unstable.png)](https://packagist.org/packages/ocramius/proxy-manager)
## Documentation
You can learn about the proxy pattern and how to use the **ProxyManager** in the [docs](docs), which are also
[compiled to HTML](http://ocramius.github.io/ProxyManager).
## Professional Support
[Professionally supported `ocramius/proxy-manager` is available through Tidelift](https://tidelift.com/subscription/pkg/packagist-ocramius-proxy-manager?utm_source=packagist-ocramius-proxy-manager&utm_medium=referral&utm_campaign=readme) .
You can also contact the maintainer at ocramius@gmail.com for looking into issues related to this package
in your private projects.
## Installation
The suggested installation method is via [composer](https://getcomposer.org/):
```sh
php composer.phar require ocramius/proxy-manager
```
## Proxy example
Here's how you build a lazy loadable object with ProxyManager using a *Virtual Proxy*
```php
$factory = new \ProxyManager\Factory\LazyLoadingValueHolderFactory();
$proxy = $factory->createProxy(
\MyApp\HeavyComplexObject::class,
function (& $wrappedObject, $proxy, $method, $parameters, & $initializer) {
$wrappedObject = new \MyApp\HeavyComplexObject(); // instantiation logic here
$initializer = null; // turning off further lazy initialization
}
);
$proxy->doFoo();
```
See the [online documentation](http://ocramius.github.io/ProxyManager) for more supported proxy types and examples.
PK
NCf psalm.xmlnu W+A
PK
NQ"
UPGRADE.mdnu W+A ---
title: Upgrade
---
This is a list of backwards compatibility (BC) breaks introduced in ProxyManager:
# 2.0.0
* PHP `~7.0` is now required to use ProxyManager
* HHVM compatibility is not guaranteed, as HHVM is not yet PHP 7 compliant
* All classes and interfaces now use [strict scalar type hints](http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration).
If you extended or implemented anything from the `ProxyManager\` namespace, you probably need to change
that code to adapt it to the new signature.
* All classes and interfaces now use [return type declarations](http://php.net/manual/en/functions.returning-values.php#functions.returning-values.type-declaration).
If you extended or implemented anything from the `ProxyManager\` namespace, you probably need to change
that code to adapt it to the new signature.
* ProxyManager will no longer write proxies to disk by default:
the [`EvaluatingGeneratorStrategy`](src/GeneratorStrategy/EvaluatingGeneratorStrategy.php) is used instead.
If you still want ProxyManager to write files to disk, please refer to the [tuning for production docs](docs/tuning-for-production.md)
* Ghost objects were entirely rewritten, for better support and improved performance. Lazy-loading is not
triggered by public API access, but by property access (private and public). While this is not really a BC
break, you are encouraged to check your applications if you rely on [ghost objects](docs/lazy-loading-ghost-object.md).
* If ProxyManager can't find a proxy, it will now automatically attempt to auto-generate it, regardless of
the settings passed to it.
* `ProxyManager\Configuration#setAutoGenerateProxies()` was removed. Please look for calls to this method and
remove them.
* Private properties are now also correctly handled by ProxyManager: accessing proxy state via friend classes
(protected or private scope) does not require any particular workarounds anymore.
* `ProxyManager\Version::VERSION` was removed. Please use `ProxyManager\Version::getVersion()` instead.
* PHP 4 style constructors are no longer supported
# 1.0.0
`1.0.0` is be fully compatible with `0.5.0`.
# 0.5.0
* The Generated Hydrator has been removed - it is now available as a separate project
at [Ocramius/GeneratedHydrator](https://github.com/Ocramius/GeneratedHydrator) [#65](https://github.com/Ocramius/ProxyManager/pull/65)
* When having a `public function __get($name)` defined (by-val) and public properties, it won't be possible to get public
properties by-ref while initializing the object. Either drop `__get()` or implement
a by-ref `& __get()` [#126](https://github.com/Ocramius/ProxyManager/pull/126)
* Proxies are now being always auto-generated if they could not be autoloaded by a factory. The methods
[`ProxyManager\Configuration#setAutoGenerateProxies()`](https://github.com/Ocramius/ProxyManager/blob/0.5.0-BETA2/src/ProxyManager/Configuration.php#L67)
and [`ProxyManager\Configuration#doesAutoGenerateProxies()`](https://github.com/Ocramius/ProxyManager/blob/0.5.0-BETA2/src/ProxyManager/Configuration.php#L75)
are now no-op and deprecated, and will be removed in the next minor
version [#87](https://github.com/Ocramius/ProxyManager/pull/87) [#90](https://github.com/Ocramius/ProxyManager/pull/90)
* Proxy public properties defaults are now set before initialization [#116](https://github.com/Ocramius/ProxyManager/pull/116) [#122](https://github.com/Ocramius/ProxyManager/pull/122)
# 0.4.0
* An optional parameter `$options` was introduced
in [`ProxyManager\Inflector\ClassNameInflectorInterface#getProxyClassName($className, array $options = array())`](https://github.com/Ocramius/ProxyManager/blob/master/src/ProxyManager/Inflector/ClassNameInflectorInterface.php)
parametrize the generated class name as of [#10](https://github.com/Ocramius/ProxyManager/pull/10)
and [#59](https://github.com/Ocramius/ProxyManager/pull/59)
* Generated hydrators no longer have constructor arguments. Any required reflection instantiation is now dealt with
in the hydrator internally as of [#63](https://github.com/Ocramius/ProxyManager/pull/63)
# 0.3.4
* Interface names are also supported for proxy generation as of [#40](https://github.com/Ocramius/ProxyManager/pull/40)
# 0.3.3
* [Generated hydrators](https://github.com/Ocramius/ProxyManager/tree/master/docs/generated-hydrator.md) were introduced
# 0.3.2
* An additional (optional) [by-ref parameter was added](https://github.com/Ocramius/ProxyManager/pull/31)
to the lazy loading proxies' initializer to allow unsetting the initializer with less overhead.
# 0.3.0
* Dependency to [jms/cg](https://github.com/schmittjoh/cg-library) removed
* Moved code generation logic to [`Zend\Code`](https://github.com/zendframework/zf2)
* Added method [`ProxyManager\Inflector\ClassNameInflectorInterface#isProxyClassName($className)`](https://github.com/Ocramius/ProxyManager/blob/master/src/ProxyManager/Inflector/ClassNameInflectorInterface.php)
* The constructor of [`ProxyManager\Autoloader\Autoloader`](https://github.com/Ocramius/ProxyManager/blob/master/src/ProxyManager/Autoloader/Autoloader.php)
changed from `__construct(\ProxyManager\FileLocator\FileLocatorInterface $fileLocator)` to
`__construct(\ProxyManager\FileLocator\FileLocatorInterface $fileLocator, \ProxyManager\Inflector\ClassNameInflectorInterface $classNameInflector)`
* Classes implementing `CG\Core\GeneratorStrategyInterface` now implement
[`ProxyManager\GeneratorStrategy\GeneratorStrategyInterface`](https://github.com/Ocramius/ProxyManager/blob/master/src/ProxyManager/GeneratorStrategy/GeneratorStrategyInterface.php)
instead
* All code generation logic has been replaced - If you wrote any logic based on `ProxyManager\ProxyGenerator`, you will
have to rewrite it
# 0.2.0
* The signature of initializers to be used with proxies implementing
[`ProxyManager\Proxy\LazyLoadingInterface`](https://github.com/Ocramius/ProxyManager/blob/master/src/ProxyManager/Proxy/LazyLoadingInterface.php)
changed from:
```php
$initializer = function ($proxy, & $wrappedObject, $method, $parameters) {};
```
to
```php
$initializer = function (& $wrappedObject, $proxy, $method, $parameters) {};
```
Only the order of parameters passed to the closures has been changed.
PK
N
?x = src/ProxyManager/Exception/InvalidProxyDirectoryException.phpnu W+A getName(),
$property->getDeclaringClass()->getName()
)
);
}
public static function nonReferenceableLocalizedReflectionProperties(
ReflectionClass $class,
Properties $properties
) : self {
return new self(sprintf(
'Cannot create references for following properties of class %s: %s',
$class->getName(),
implode(', ', array_map(static function (ReflectionProperty $property) : string {
return $property->getName();
}, $properties->getInstanceProperties()))
));
}
}
PK
NTJ> 7 src/ProxyManager/Exception/FileNotWritableException.phpnu W+A getName()));
}
public static function finalClassNotSupported(ReflectionClass $reflection) : self
{
return new self(sprintf('Provided class "%s" is final and cannot be proxied', $reflection->getName()));
}
public static function abstractProtectedMethodsNotSupported(ReflectionClass $reflection) : self
{
return new self(sprintf(
'Provided class "%s" has following protected abstract methods, and therefore cannot be proxied:' . "\n%s",
$reflection->getName(),
implode(
"\n",
array_map(
static function (ReflectionMethod $reflectionMethod) : string {
return $reflectionMethod->getDeclaringClass()->getName() . '::' . $reflectionMethod->getName();
},
array_filter(
$reflection->getMethods(),
static function (ReflectionMethod $method) : bool {
return $method->isAbstract() && $method->isProtected();
}
)
)
)
));
}
}
PK
Nr
6 src/ProxyManager/Exception/DisabledMethodException.phpnu W+A =,
* 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;
}
PK
NW#; 0 src/ProxyManager/Proxy/VirtualProxyInterface.phpnu W+A 7 src/ProxyManager/Proxy/FallbackValueHolderInterface.phpnu W+A
* $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;
}
PK
N{3pLr r 5 src/ProxyManager/Proxy/AccessInterceptorInterface.phpnu W+A
* $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;
}
PK
N6] @ src/ProxyManager/Proxy/AccessInterceptorValueHolderInterface.phpnu W+A =,
* 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() : ?object;
}
PK
N
g / src/ProxyManager/Proxy/ValueHolderInterface.phpnu W+A @,
* where the detected version is what composer could detect.
*
* @throws OutOfBoundsException
*/
public static function getVersion() : string
{
return Versions::getVersion('ocramius/proxy-manager');
}
}
PK
NC 1 src/ProxyManager/Inflector/ClassNameInflector.phpnu W+A 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);
}
/**
* {@inheritDoc}
*/
public function isProxyClassName(string $className) : bool
{
return strrpos($className, $this->proxyMarker) !== false;
}
}
PK
N.# 4 src/ProxyManager/Inflector/Util/ParameterEncoder.phpnu W+A |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
*
* @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
* @psalm-param class-string|class-string> $className
*/
public function isProxyClassName(string $className) : bool;
}
PK
Ns!j6 6 5 src/ProxyManager/FileLocator/FileLocatorInterface.phpnu W+A proxiesDirectory = $absolutePath;
}
/**
* {@inheritDoc}
*/
public function getProxyFileName(string $className) : string
{
return $this->proxiesDirectory . DIRECTORY_SEPARATOR . str_replace('\\', '', $className) . '.php';
}
}
PK
N ( src/ProxyManager/Stub/EmptyClassStub.phpnu W+A setInterface(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();
}
}
PK
Nh 6 src/ProxyManager/Generator/Util/IdentifierSuffixer.phpnu W+A getReturnType() === 'void') {
return $returnedValueExpression . ";\nreturn;";
}
return 'return ' . $returnedValueExpression . ';';
}
}
PK
NEK K = src/ProxyManager/Generator/Util/UniqueIdentifierGenerator.phpnu W+A getName();
if ($originalClass->hasMethod($methodName) && $originalClass->getMethod($methodName)->isFinal()) {
return false;
}
$classGenerator->addMethodFromGenerator($generatedMethod);
return true;
}
}
PK
NKT 3 src/ProxyManager/Generator/MagicMethodGenerator.phpnu W+A setReturnsReference(strtolower($name) === '__get');
if (! $originalClass->hasMethod($name)) {
return;
}
$this->setReturnsReference($originalClass->getMethod($name)->returnsReference());
}
}
PK
NQo.w w - src/ProxyManager/Generator/ClassGenerator.phpnu W+A $interfaces
*
* @psalm-suppress MoreSpecificImplementedParamType parent interface does not specify type of array values
*/
public function setImplementedInterfaces(array $interfaces) : ZendClassGenerator
{
return parent::setImplementedInterfaces(array_map(
static function (string $interface) : string {
return '\\' . trim($interface, '\\');
},
$interfaces
));
}
}
PK
N˄E@ @ <