Coder Social home page Coder Social logo

proxy-manager-lts's People

Contributors

2dsharp avatar blanchonvincent avatar dependabot-preview[bot] avatar derrabus avatar fmasa avatar geeh avatar greg0ire avatar gws avatar hultberg avatar localheinz avatar ludo444 avatar malukenho avatar martinssipenko avatar michaelmoussa avatar michaelpetri avatar michalbundyra avatar muglug avatar nicolas-grekas avatar ocramius avatar ondrejmirtes avatar orklah avatar ostrolucky avatar pedro-stanaka avatar raulfraile avatar renovate[bot] avatar samsonasik avatar snapshotpl avatar staabm avatar tobion avatar wouterj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

proxy-manager-lts's Issues

doctrine/reflection is abandoned

Hello,

as doctrine/reflection say itself that it is abandoned:

⚠️ This package is abandoned, consider migrating to alternatives, such as roave/better-reflection. Features that are still useful to Doctrine have been moved to doctrine/persistence ⚠️

Maybe you should either abandon this project or edit the readme to no longer act as a fork and thus not asking to "report issues and submit new features to the origin library."

:)

fixExport() produces invalid FQCN on PHP 8.2

fixExport() introduced in #17 does not work correctly on PHP 8.2, where var_export() behaviour was changed:

1) ProxyManagerTest\Functional\MultipleProxyGenerationTest::testCanGenerateMultipleDifferentProxiesForSameClass with data set "php81defaults" (ProxyManagerTestAsset\ClassWithPhp81Defaults Object (...))
Error: Class "P\roxyManagerTestAsset\FooEnum" not found

proxy-manager-lts/tests/ProxyManagerTest/Functional/MultipleProxyGenerationTest.php:103

2) ProxyManagerTest\Functional\RemoteObjectFunctionalTest::testXmlRpcMethodCalls with data set "when using php8.1 defaults" ('ProxyManagerTestAsset\RemoteP...erface', 'php81Defaults', array(), array(ProxyManagerTestAsset\RemoteProxy\FooEnum Object (...), stdClass Object ()), 200)
Error: Class "P\roxyManagerTestAsset\RemoteProxy\FooEnum" not found

proxy-manager-lts/tests/ProxyManagerTest/Functional/RemoteObjectFunctionalTest.php:107

3) ProxyManagerTest\Functional\RemoteObjectFunctionalTest::testJsonRpcMethodCalls with data set "when using php8.1 defaults" ('ProxyManagerTestAsset\RemoteP...erface', 'php81Defaults', array(), array(ProxyManagerTestAsset\RemoteProxy\FooEnum Object (...), stdClass Object ()), 200)
Error: Class "P\roxyManagerTestAsset\RemoteProxy\FooEnum" not found

proxy-manager-lts/tests/ProxyManagerTest/Functional/RemoteObjectFunctionalTest.php:131

As you can see, it produces \P\roxyManagerTestAsset\FooEnum instead of \ProxyManagerTestAsset\FooEnum.

Ref: php/php-src#8232
Ref: php/php-src#8233

Public readonly properties

I have an issue when trying to read public readonly properties from the Proxy. I got an error:

Cannot initialize readonly property App\Entity\Customer::$firstName from scope App\Command\Command

Library version: 1.0.12

Preconditions:
We have a class only with public properties.

<?php

declare(strict_types=1);

namespace App\Entity;

class Customer
{
    public function __construct(
        public readonly string $firstName,
        public readonly string $lastName,
    ) {
    }
}

Steps to Reproduce:

  1. Create a Proxy object
$instance = (new LazyLoadingGhostFactory())->createProxy(
    Customer::class,
    static function (
        GhostObjectInterface $ghostObject,
        string $method,
        array $parameters,
        ?Closure &$initializer,
        array $properties,
    ) {
        $initializer = null;

        $properties['firstName'] = 'User';
        $properties['lastName'] = 'Test';

        return true;
    },
);
  1. Getting value from any public property results in an error.
    Cannot initialize readonly property App\Entity\Customer::$firstName from scope App\Command\Command
$output->writeln('First Name: ' . $customer->firstName);
$output->writeln('Last Name: ' . $customer->lastName);

After investigation, I see the $class and $scopeObject variables equal to the App\Command\Command.

} elseif (isset(self::$privateProperties98259[$name])) {
    $callers = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT, 2);
    $caller  = isset($callers[1]) ? $callers[1] : [];
    $class   = isset($caller['class']) ? $caller['class'] : '';
    ...
}

...
$targetObject = $realInstanceReflection->newInstanceWithoutConstructor();
$accessor = function & () use ($targetObject, $name) {
    return $targetObject->$name;
};
$backtrace = debug_backtrace(true, 2);
$scopeObject = isset($backtrace[1]['object']) ? $backtrace[1]['object'] : new \ProxyManager\Stub\EmptyClassStub();

Note
But if we will add a getter for the property all works without errors.

class Customer
{
    public function __construct(
        public readonly string $firstName,
        public readonly string $lastName,
    ) {
    }

    public function getFirstName(): string
    {
        return $this->firstName;
    }
}
$output->writeln('First Name: ' . $customer->getFirstName());
$output->writeln('Last Name: ' . $customer->lastName);

Incompatible with PHP 8.1

In its current state, this library does not work fully with PHP 8.1. When using a promoted readonly only property in a class, this library will generate code that tries to change the readonly property and therefor breaking execution. Consider the following class (all have been stripped to only show the constructor):

class SystemNotificationService extends AbstractCacheableService
{
  public function __construct(
      private readonly SystemNotificationRepository $systemNotificationRepository,
      private readonly SerializerInterface $serializer,
      Features $features,
      string $kernelEnvironment,
      string $commitHash,
      string $httpHost,
      string $cacheDir)
  {
    parent::__construct($features, $kernelEnvironment, $commitHash, $httpHost, $cacheDir);
  }
}
abstract class AbstractCacheableService
{
  public function __construct(
      protected readonly Features $features,
      string $kernelEnvironment,
      string $commitHash,
      string $httpHost,
      private readonly string $cacheDir)
  {
  }
}

will generate the following proxy:

class SystemNotificationService_6ddbdeb extends \App\Service\SystemNotificationService implements \ProxyManager\Proxy\VirtualProxyInterface
{
    public function __construct(private \JMS\Serializer\SerializerInterface $serializer, \App\Features $features)
    {
        static $reflection;

        if (! $this->valueHolder06ae0) {
            $reflection = $reflection ?? new \ReflectionClass('App\\Service\\SystemNotificationService');
            $this->valueHolder06ae0 = $reflection->newInstanceWithoutConstructor();
        unset($this->features);

        \Closure::bind(function (\App\Service\SystemNotificationService $instance) {
            unset($instance->systemNotificationRepository, $instance->serializer);
        }, $this, 'App\\Service\\SystemNotificationService')->__invoke($this);

        \Closure::bind(function (\App\Service\AbstractCacheableService $instance) {
            unset($instance->cache, $instance->cacheHash, $instance->clearedTags, $instance->clearedKeys, $instance->cacheDir);
        }, $this, 'App\\Service\\AbstractCacheableService')->__invoke($this);

        }

        $this->valueHolder06ae0->__construct($systemNotificationRepository, $serializer, $features, $kernelEnvironment, $commitHash, $httpHost, $cacheDir);
    }
}

and thus throw Cannot unset readonly property App\Service\AbstractCacheableService::$features from scope ContainerXH6sJpc\SystemNotificationService_6ddbdeb, caused by the unset($instance->features).

Note that the same will also happen with the systemNotificationRepository and serializer properties (unset($instance->systemNotificationRepository, $instance->serializer);).

Also posted at Ocramius/ProxyManager#737.

Change version requirement for laminas/laminas-code

Right now the composer.json has the following requirement:

"laminas/laminas-code": "~3.4.1|^4.0"

This constraint won't allow version 3.5.x. This has the downside that it is not possible to support 7.3, 7.4. and 8.0 at once. For reference:

laminas-code require
3.4.* php: ^7.1
3.5.* php: ^7.3 || ~8.0.0
4.0.* php: ^7.4 || ~8.0.0

As far as I can tell, it doesn't make sense to take this upstream as the version support is explicitly why this package exists. Would it make sense to change the requirement in the composer.json to support 3.5 as well?

Finalize replacement of Zend CodeGenerator with Laminas CodeGenerator

There is still code in the library that triggers class_exists(\Zend\CodeGenerator\ClassGenerator) for an unclear reason, maybe to make the laminas/laminas-zendframework-bridge happy that is transisently loaded via laminas/laminas-eventmanager even though it already uses Laminas use statements everywhere.

This laminas-zendframework-bridge introduces a heavy autoloader as documented here laminas/laminas-zendframework-bridge#83 and this library should make sure to avoid this trap by lobbying this dependency be removed from laminas/laminas-eventmanager laminas/laminas-eventmanager#21 and remove the class_exists calls.

proxy-manager-lts requires laminas-code which cannot cover php from 7.2 to 8.0

Hello everyone,

First of all thank you for the great work on this repository. Long term support for old PHP versions is very precious and happens thanks to your hard work.

At prestashop we are trying provide a wide range of PHP versions for our next version, which would be php7.2 to php8.0 .

Although php versions prior to 7.4 are not maintained anymore, in the CMS ecosystem php versions can be slow to upgrade.

Moreover if someone is running a PrestaShop version on php7.2 today and wants to upgrade to the latest version tomorrow, it's very useful for her/him to be able to 1) upgrade the software ; and it runs on 7.2 ; 2) verify everything seems all right 3) upgrade php version. If we drop php7.2 compatibility, this cannot happen and make the upgrade path harder.

proxy-manager-lts requires laminas-code which provide

  • a 3.4.x branch that supports php7.1^ but AFAIK does not support php8
  • a 3.5.x branch that supports php8 but requires php7.3^

So we cannot have a single set of dependencies for proxy-manager-lts that would support both php7.2 and php8.0.

Would it be possible to consider

  • accepting pull requests on laminas-code 4.5.x to cover a wider range of php versions, down to php7.2 ?
  • or creating a -tls package, just like this one, for laminas-code, to aim for the same goal ? that means a new package friendsofphp/laminas-code-lts, we will be happy to contribute to it to achieve this goal

Have a nice day :) I'm open to all ideas and feedback

Restrict circular proxy instantiation

I ran into a problem that took a lot of time, and perhaps it may be solved at the proxy creation level.

My problem was about EntityManager and EntityRepository behavior in Symfony app:

final class ProductRepository implements ProductRepositoryInterface
{
    /** @var EntityRepository<Product> $repository */
    private EntityRepository $repository;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->repository = $entityManager->getRepository(Product::class);
    }

    public function update(string $productId): void
    {
        $product = $this->repository->find($productId);
        $product->update(); // <- change state
        $this->entityManager->flush(); // <- do nothing
    }
}

Of course, it turned out that there were different UnitOfWork instances in the injected entity manager and stored repository:

$unitOfWork1 = $this->repository->getEntityManager()->getUnitOfWork();
$unitOfWork2 = $this->entityManager->getUnitOfWork();
dump($unitOfWork1 === $unitOfWork2); // <- FALSE

After investigation, I found implicit circular dependency in my container (and resolved it with making one of my services lazy).

Anyway, I think that it's interesting how can two (proxied) EntityManager instances (with different UnitOfWork instances) exist in the container.

What I found:

  1. My constructor has $entityManager->getRepository call
  2. It internally instantiates some services dependent on this one
  3. It calls $entityManager->getRepository again
    So now we have two \ContainerDjfkKub\EntityManager_9a5be93::getRepository calls in the stack; Thanks to coalesce $this->services['doctrine.dbal.default_connection'] ?? $this->getDoctrine_Dbal_DefaultConnectionService() or something else we do not go there third time
  4. Initializer assigns $wrappedInstance by ref with newly created EntityManager. Twice. While references to first are already saved in container.

My in-place dirty fix for it looks like callable "setter" param which ensures to not assign twice:

// EntityManager_9a5be93
public function getRepository($entityName)
{
    $this->initializer8b6cd && ($this->initializer8b6cd->__invoke(
        $valueHolder3da10,
        $this,
        'getRepository',
        array('entityName' => $entityName),
        $this->initializer8b6cd,
        setter: fn($v) => $this->valueHolder3da10 ??= $v, // <- instead of passing $valueHolder3da10 by ref, this closure assure to assign once
    ) || 1);
        return $this->valueHolder3da10->getRepository($entityName);
}
// App_KernelDevDebugContainer
return $this->services['doctrine.orm.default_entity_manager'] = $this->createProxy('EntityManager_9a5be93', function () {
    return \EntityManager_9a5be93::staticProxyConstructor(function (
        &$wrappedInstance,
        \ProxyManager\Proxy\LazyLoadingInterface $proxy,
        string $method,
        array $args,
        callable $self,
        ?callable $setter = null
    ) {
        $entityManager = $this->getDoctrine_Orm_DefaultEntityManagerService(false);

        if ($setter) {
            $setter($entityManager);
        } else {
            $wrappedInstance = $entityManager;
        }
        $proxy->setProxyInitializer(null);

        return true;
    });
});

I don't think a fix like that should be used. Instead, some checks to protect against proxy double initialization may be added

Version: "friendsofphp/proxy-manager-lts": "v1.0.12" (via "symfony/proxy-manager-bridge": "v6.1.0")

Maybe the whole issue should be redirected to original ocramius/proxymanager, but I can't find easy way to reproduce Symfony behavior using proxymanager directly

Allow symfony/filesystem earlier than 4.4.17

Requirements have a dependency with an especific version of symfony/filesystem >= 4.4.17, this avoids installation if using earlier versions of Symfony.
I see this library is used just to dump code to disk, something that was present on earlier versions of symfony/filesystem, I have forked the project and tried symfony/filesystem:^3.4 to be exact 3.4.47 and it works fine, there is some reason to require '>= 4.4.17`?

laminas/laminas-code version compatibility

Hello,
This is not a bug, but a question, why laminas/laminas-code dependency is limited to that?

"laminas/laminas-code": "~3.4.1|^4.0",

There is a incompatibility with 3.5.x? We are having 3.5.1 in a project.
Thank you very much.

Type "Psr\Log\NullLogger" is unknown or cannot be used as property default value.

Hi,

After upgrading this package to 1.0.15, I'm getting the error Type "Psr\Log\NullLogger" is unknown or cannot be used as property default value. in my app.

I have a feeling this is not the fault of this package, but somewhere in my project and I have a hard time tracking this down.

Can anyone point me in direction of solving this? Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.