bug #26176 Retro-fit proxy code to make it deterministic for older proxy manager implementations (lstrojny)

This PR was merged into the 3.4 branch.

Discussion
----------

Retro-fit proxy code to make it deterministic for older proxy manager implementations

Follow up on https://github.com/symfony/symfony/issues/25958#issuecomment-365543535

ProxyManager >= 7.2 already implements a deterministic identifier naming strategy which is critical for reproducible builds (https://github.com/symfony/symfony/issues/25958).  but versions below that don’t. This is what this PR fixes. Here is more context: https://github.com/Ocramius/ProxyManager/pull/411

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

Commits
-------

0f16056 Retro-fit proxy code to make it deterministic for older proxy manager implementations
This commit is contained in:
Nicolas Grekas 2018-02-17 21:58:51 +01:00
commit b97e9a903a
2 changed files with 44 additions and 3 deletions

View File

@ -13,6 +13,7 @@ namespace Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper;
use ProxyManager\Generator\ClassGenerator;
use ProxyManager\GeneratorStrategy\BaseGeneratorStrategy;
use ProxyManager\Version;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface;
@ -94,11 +95,35 @@ EOF;
*/
public function getProxyCode(Definition $definition)
{
return preg_replace(
$code = $this->classGenerator->generate($this->generateProxyClass($definition));
$code = preg_replace(
'/(\$this->initializer[0-9a-f]++) && \1->__invoke\(\$this->(valueHolder[0-9a-f]++), (.*?), \1\);/',
'$1 && ($1->__invoke(\$$2, $3, $1) || 1) && $this->$2 = \$$2;',
$this->classGenerator->generate($this->generateProxyClass($definition))
$code
);
if (version_compare(self::getProxyManagerVersion(), '2.2', '<')) {
$code = preg_replace(
'/((?:\$(?:this|initializer|instance)->)?(?:publicProperties|initializer|valueHolder))[0-9a-f]++/',
'${1}'.$this->getIdentifierSuffix($definition),
$code
);
}
return $code;
}
/**
* @return string
*/
private static function getProxyManagerVersion()
{
if (!\class_exists(Version::class)) {
return '0.0.1';
}
return defined(Version::class.'::VERSION') ? Version::VERSION : Version::getVersion();
}
/**
@ -108,7 +133,7 @@ EOF;
*/
private function getProxyClassName(Definition $definition)
{
return preg_replace('/^.*\\\\/', '', $definition->getClass()).'_'.substr(hash('sha256', $definition->getClass().$this->salt), -7);
return preg_replace('/^.*\\\\/', '', $definition->getClass()).'_'.$this->getIdentifierSuffix($definition);
}
/**
@ -122,4 +147,12 @@ EOF;
return $generatedClass;
}
/**
* @return string
*/
private function getIdentifierSuffix(Definition $definition)
{
return substr(hash('sha256', $definition->getClass().$this->salt), -7);
}
}

View File

@ -61,6 +61,14 @@ class ProxyDumperTest extends TestCase
);
}
public function testDeterministicProxyCode()
{
$definition = new Definition(__CLASS__);
$definition->setLazy(true);
$this->assertSame($this->dumper->getProxyCode($definition), $this->dumper->getProxyCode($definition));
}
public function testGetProxyFactoryCode()
{
$definition = new Definition(__CLASS__);