Skip to content
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

Remove dependency to doctrine/common #299

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/coding-standards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,4 @@ jobs:
name: "Coding Standards"
uses: "doctrine/.github/.github/workflows/[email protected]"
with:
composer-root-version: "2.3"
php-version: "8.1"
1 change: 0 additions & 1 deletion .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,4 @@ jobs:
name: "PHPUnit"
uses: "doctrine/.github/.github/workflows/[email protected]"
with:
composer-root-version: "2.3"
php-versions: '["7.2", "7.3", "7.4", "8.0", "8.1"]'
1 change: 0 additions & 1 deletion .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,4 @@ jobs:
name: "Static Analysis"
uses: "doctrine/.github/.github/workflows/[email protected]"
with:
composer-root-version: "2.3"
php-version: "8.1"
11 changes: 0 additions & 11 deletions CONTRIBUTING.md

This file was deleted.

8 changes: 8 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ awareness about deprecated code.
- Use of our low-overhead runtime deprecation API, details:
https://github.com/doctrine/deprecations/

# Upgrade to 3.1

## Deprecated partial implementation of `Doctrine\Persistence\Proxy`

Classes implementing `Doctrine\Persistence\Proxy` should implement all the
methods described with the standard `@method` phpdoc annotations that were
added to it. These methods will be added to the interface in 4.0.

# Upgrade to 3.0

## Removed `OnClearEventArgs::clearsAllEntities()` and `OnClearEventArgs::getEntityClass()`
Expand Down
1 change: 0 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
"phpstan/phpstan-strict-rules": "^1.1",
"doctrine/annotations": "^1.7",
"doctrine/coding-standard": "^9.0",
"doctrine/common": "^3.0",
"phpunit/phpunit": "^8.5 || ^9.5",
"symfony/cache": "^4.4 || ^5.4 || ^6.0",
"vimeo/psalm": "4.22.0"
Expand Down
10 changes: 10 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ parameters:
count: 1
path: src/Persistence/Reflection/EnumReflectionProperty.php

-
message: "#^Call to function method_exists\\(\\) with Doctrine\\\\Persistence\\\\Proxy and '__getInitializer' will always evaluate to true\\.$#"
count: 1
path: src/Persistence/Reflection/RuntimePublicReflectionProperty.php

-
message: "#^Call to function method_exists\\(\\) with Doctrine\\\\Persistence\\\\Proxy and '__setInitializer' will always evaluate to true\\.$#"
count: 1
path: src/Persistence/Reflection/RuntimePublicReflectionProperty.php

-
message: "#^Variable property access on \\$this\\(Doctrine\\\\Persistence\\\\Reflection\\\\TypedNoDefaultRuntimePublicReflectionProperty\\)\\.$#"
count: 1
Expand Down
16 changes: 16 additions & 0 deletions src/Persistence/Proxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@
* Interface for proxy classes.
*
* @template T of object
* @method void __setInitialized(bool $initialized) Marks the proxy as initialized or not.
* @method void __setInitializer(Closure|null $initializer = null) Sets the
* initializer callback to be used when initializing the proxy. That
* initializer should accept 3 parameters: $proxy, $method and $params. Those
* are respectively the proxy object that is being initialized, the method name
* that triggered initialization and the parameters passed to that method.
* @method Closure|null __getInitializer() Retrieves the initializer callback
* used to initialize the proxy.
* @method void __setCloner(Closure|null $cloner = null) Sets the callback to
* be used when cloning the proxy. That initializer should accept a single
* parameter, which is the cloned proxy instance itself.
* @method Closure|null __getCloner() Retrieves the callback to be used when
* cloning the proxy.
* @method array<string, mixed> __getLazyProperties() Retrieves the list of
* lazy loaded properties for a given proxy. Keys are the property names, and
* values are the default values for those properties.
*/
interface Proxy
{
Expand Down
15 changes: 13 additions & 2 deletions src/Persistence/Reflection/RuntimePublicReflectionProperty.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@

namespace Doctrine\Persistence\Reflection;

use Doctrine\Common\Proxy\Proxy;
use Doctrine\Persistence\Proxy;
use InvalidArgumentException;
use ReflectionProperty;
use ReturnTypeWillChange;

use function method_exists;
use function sprintf;

/**
* PHP Runtime Reflection Public Property - special overrides for public properties.
*/
Expand All @@ -31,7 +35,7 @@ public function getValue($object = null)
* {@inheritDoc}
*
* Avoids triggering lazy loading via `__set` if the provided object
* is a {@see \Doctrine\Common\Proxy\Proxy}.
* is a {@see \Doctrine\Persistence\Proxy}.
*
* @link https://bugs.php.net/bug.php?id=63463
*
Expand All @@ -49,6 +53,13 @@ public function setValue($object, $value = null)
return;
}

if (! method_exists($object, '__getInitializer') || ! method_exists($object, '__setInitializer')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't we assume that $object is always an isntance of the class used for this property and move the check to ctor?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes that's probably safe to do 👍

throw new InvalidArgumentException(sprintf(
'The proxy class must have all methods documented with @method on %s.',
Proxy::class
));
}

$originalInitializer = $object->__getInitializer();
$object->__setInitializer(null);
parent::setValue($object, $value);
Expand Down
63 changes: 39 additions & 24 deletions tests/Persistence/RuntimePublicReflectionPropertyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
namespace Doctrine\Tests\Persistence;

use Closure;
use Doctrine\Common\Proxy\Proxy;
use Doctrine\Persistence\Proxy;
use Doctrine\Persistence\Reflection\RuntimePublicReflectionProperty;
use InvalidArgumentException;
use LogicException;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -106,6 +107,37 @@ public function testSetValueOnProxyPublicProperty(): void
$reflProperty->setValue($mockProxy, 'againNewValue');
self::assertSame('againNewValue', $mockProxy->checkedProperty);
}

public function testItThrowsWhenSomeMethodsAreMissingFromAProxy(): void
{
$object = new MyProxy();

$reflProperty = new RuntimePublicReflectionProperty(
MyProxy::class,
'test'
);

$this->expectException(InvalidArgumentException::class);
$reflProperty->setValue($object, null);
}
}

/**
* @template-implements Proxy<object>
*/
class MyProxy implements Proxy
{
/** @var string */
public $test = 'test';

public function __load(): void
{
}

public function __isInitialized(): bool
{
return false;
}
}

/**
Expand All @@ -124,30 +156,22 @@ class RuntimePublicReflectionPropertyTestProxyMock implements Proxy
/** @var string */
public $checkedProperty = 'testValue';

/**
* {@inheritDoc}
*/
public function __getInitializer()
public function __getInitializer(): ?Closure
{
return $this->initializer;
}

/**
* {@inheritDoc}
*/
public function __setInitializer(?Closure $initializer = null)
public function __setInitializer(?Closure $initializer = null): void
{
$this->initializer = $initializer;
}

/**
* {@inheritDoc}
*
* @return mixed[] Keys are the property names, and values are the default
* values for those properties.
* @phpstan-return array<string, mixed>
*/
public function __getLazyProperties()
public function __getLazyProperties(): array
{
return [];
}
Expand All @@ -161,10 +185,7 @@ public function __isInitialized(): bool
return $this->initialized;
}

/**
* {@inheritDoc}
*/
public function __setInitialized($initialized)
public function __setInitialized(bool $initialized): void
{
$this->initialized = $initialized;
}
Expand Down Expand Up @@ -206,17 +227,11 @@ public function __isset(string $name): bool
return isset($this->checkedProperty);
}

/**
* {@inheritDoc}
*/
public function __setCloner(?Closure $cloner = null)
public function __setCloner(?Closure $cloner = null): void
{
}

/**
* {@inheritDoc}
*/
public function __getCloner()
public function __getCloner(): ?Closure
{
throw new LogicException('Not implemented');
}
Expand Down