-
-
Notifications
You must be signed in to change notification settings - Fork 188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for non-nullable typed properties #685
base: 2.15.x
Are you sure you want to change the base?
Changes from 5 commits
a8762ac
eb58579
2c1fd62
2289807
bd486fb
7f814ec
9601a2b
21a6653
88737ee
470df17
f6da532
d667f90
063d8de
fbc7965
113f45f
1381ecf
04c4867
10a2cc5
2a0b09a
598a66f
a580ed9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizer\MethodGenerator; | ||
|
||
use Laminas\Code\Generator\ParameterGenerator; | ||
use ProxyManager\Exception\UnsupportedProxiedClassException; | ||
use ProxyManager\Generator\MethodGenerator; | ||
use ReflectionClass; | ||
|
||
use function strtr; | ||
|
||
class BindProxyProperty extends MethodGenerator | ||
{ | ||
public function __construct(ReflectionClass $originalClass) | ||
{ | ||
parent::__construct( | ||
'bindProxyProperty', | ||
[ | ||
new ParameterGenerator('localizedObject', $originalClass->getName()), | ||
new ParameterGenerator('class', ReflectionClass::class), | ||
new ParameterGenerator('propertyName', 'string'), | ||
], | ||
self::FLAG_PRIVATE | ||
); | ||
|
||
$bodyTemplate = <<<'CODE' | ||
$originalClass = $class; | ||
while (! $class->hasProperty($propertyName)) { | ||
$class = $class->getParentClass(); | ||
} | ||
$property = $class->getProperty($propertyName); | ||
$property->setAccessible(true); | ||
if (!$property->isInitialized($localizedObject)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand this correctly, the difference here is that we aren't creating an "empty shell", but proxying when the other class is correctly initialized? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes: for now proxy can be created only when properties are nullable and have default value in class itself. |
||
throw new \{ EXCEPTION_CLASS }( | ||
sprintf( | ||
'Cannot create reference for property $%s of class %s: property must be initialized', | ||
$property->getName(), | ||
$originalClass->getName() | ||
) | ||
); | ||
} | ||
if (!$property->isPrivate()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This call can be prevented by inspecting the reflection information for a property upfront There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
$this->{$propertyName} = & $localizedObject->{$propertyName}; | ||
return; | ||
} | ||
|
||
\Closure::bind( | ||
function () use ($localizedObject, $propertyName) { | ||
$this->{$propertyName} = & $localizedObject->{$propertyName}; | ||
}, | ||
$this, | ||
$property->getDeclaringClass()->getName() | ||
)->__invoke(); | ||
CODE; | ||
|
||
$this->setBody( | ||
strtr( | ||
$bodyTemplate, | ||
['{ EXCEPTION_CLASS }' => UnsupportedProxiedClassException::class] | ||
) | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This operation should be performed during compilation, rather than during runtime: it's quite expensive to traverse ancestors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Ocramius unfortunately I don't understand how to perform this during compilation: different properties would have different declaring classes. So how this can be done during compilation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done - I'm generating a
$classesMap
variable at build time, which has instances ofReflectionClass
for private properties, and then use it when localizing private props.