-
-
Notifications
You must be signed in to change notification settings - Fork 67
Import useful reflection classes #122
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
<?php | ||
|
||
namespace Doctrine\Persistence\Reflection; | ||
|
||
use Doctrine\Common\Proxy\Proxy; | ||
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. So this is where the package depends on the common library. It doesn't require it but supports it (hence the test). Would it make sense to just make the test skip if the library is not loaded and add it as a suggestion? I believe there should be consistency between the dependencies of the code and the dependencies of the tests that cover that code. Not that the code doesn't have a dependency while the test does. 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. So to be clear, you would add 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, this was the idea. Technically, the development of the script doesn't strictly depend on this package. For instance, DBAL has code and the tests that depend on certain PHP extensions. If those extensions are not available, the tests are skipped. How is it different from this case? I see what you're saying and I agree that eventually, we are adding the dependency on CI instead of having it added in the repository. 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.
Here, it doesn't depend on extensions. Extensions are more involving to install: you have to be root, composer can't do it for you, and in some cases you might even not have a system package for them. That's why it makes a lot of sense to proceed like this on the DBAL. 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. I can live with 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 may summarize it, if there's no reason for the change, let's not make it (i.e. keep the development dependency). 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. The other option is to copy the interface here and add a autoload-dev. Since its just a marker interface with no methods, there is no risk of breaking with or without doctrine/common. 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. I added the requirement under the |
||
use ReflectionProperty; | ||
|
||
/** | ||
* PHP Runtime Reflection Public Property - special overrides for public properties. | ||
*/ | ||
class RuntimePublicReflectionProperty extends ReflectionProperty | ||
{ | ||
/** | ||
* {@inheritDoc} | ||
* | ||
* Checks is the value actually exist before fetching it. | ||
* This is to avoid calling `__get` on the provided $object if it | ||
* is a {@see \Doctrine\Common\Proxy\Proxy}. | ||
*/ | ||
public function getValue($object = null) | ||
{ | ||
$name = $this->getName(); | ||
|
||
if ($object instanceof Proxy && ! $object->__isInitialized()) { | ||
$originalInitializer = $object->__getInitializer(); | ||
$object->__setInitializer(null); | ||
$val = $object->$name ?? null; | ||
$object->__setInitializer($originalInitializer); | ||
|
||
return $val; | ||
} | ||
|
||
return isset($object->$name) ? parent::getValue($object) : null; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
* | ||
* Avoids triggering lazy loading via `__set` if the provided object | ||
* is a {@see \Doctrine\Common\Proxy\Proxy}. | ||
* | ||
* @link https://bugs.php.net/bug.php?id=63463 | ||
*/ | ||
public function setValue($object, $value = null) | ||
{ | ||
if (! ($object instanceof Proxy && ! $object->__isInitialized())) { | ||
parent::setValue($object, $value); | ||
|
||
return; | ||
} | ||
|
||
$originalInitializer = $object->__getInitializer(); | ||
$object->__setInitializer(null); | ||
parent::setValue($object, $value); | ||
$object->__setInitializer($originalInitializer); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?php | ||
|
||
namespace Doctrine\Persistence\Reflection; | ||
|
||
use ReflectionProperty; | ||
|
||
/** | ||
* PHP Typed No Default Reflection Property - special override for typed properties without a default value. | ||
*/ | ||
class TypedNoDefaultReflectionProperty extends ReflectionProperty | ||
{ | ||
/** | ||
* {@inheritDoc} | ||
* | ||
* Checks that a typed property is initialized before accessing its value. | ||
* This is necessary to avoid PHP error "Error: Typed property must not be accessed before initialization". | ||
* Should be used only for reflecting typed properties without a default value. | ||
*/ | ||
public function getValue($object = null) | ||
{ | ||
return $object !== null && $this->isInitialized($object) ? parent::getValue($object) : null; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
* | ||
* Works around the problem with setting typed no default properties to | ||
* NULL which is not supported, instead unset() to uninitialize. | ||
* | ||
* @link https://github.com/doctrine/orm/issues/7999 | ||
*/ | ||
public function setValue($object, $value = null) | ||
{ | ||
if ($value === null && $this->hasType() && ! $this->getType()->allowsNull()) { | ||
$propertyName = $this->getName(); | ||
|
||
$unsetter = function () use ($propertyName) { | ||
unset($this->$propertyName); | ||
}; | ||
$unsetter = $unsetter->bindTo($object, $this->getDeclaringClass()->getName()); | ||
$unsetter(); | ||
|
||
return; | ||
} | ||
|
||
parent::setValue($object, $value); | ||
} | ||
} |
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.
So this is a circular dependency… yuck! It was a dev dependency in
doctrine/reflection
, not sure why… should I move it to a regular requirement?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.
Can you check what will fail if this dependency is removed? A dev dependency of one package is not necessarily a dev dependency of the one that depends on it. It might have been used by the reflection package to test other classes than the ones being carried over.
As long as neither this package nor the reflection had a production dependency on the common package, it doesn't look like the right thing to do.
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.
I forgot to add it at first and it failed 🙂