Skip to content

Commit 38fe500

Browse files
Fix enums and new in initializers as default values on PHP 8.1
1 parent c828ced commit 38fe500

17 files changed

+174
-42
lines changed

src/ProxyManager/Factory/AbstractBaseFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
namespace ProxyManager\Factory;
66

7-
use Laminas\Code\Generator\ClassGenerator;
87
use OutOfBoundsException;
98
use ProxyManager\Configuration;
9+
use ProxyManager\Generator\ClassGenerator;
1010
use ProxyManager\ProxyGenerator\ProxyGeneratorInterface;
1111
use ProxyManager\Signature\Exception\InvalidSignatureException;
1212
use ProxyManager\Signature\Exception\MissingSignatureException;

src/ProxyManager/Generator/ClassGenerator.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,30 @@
55
namespace ProxyManager\Generator;
66

77
use Laminas\Code\Generator\ClassGenerator as LaminasClassGenerator;
8+
use ProxyManager\Generator\ValueGenerator;
9+
use ReflectionParameter;
10+
11+
use function method_exists;
812

913
/**
1014
* Class generator that ensures that interfaces/classes that are implemented/extended are FQCNs
1115
*
1216
* @internal do not use this in your code: it is only here for internal use
13-
* @deprecated this class was in use due to parent implementation not receiving prompt bugfixes, but
14-
* `laminas/laminas-code` is actively maintained and receives quick release iterations.
1517
*/
1618
class ClassGenerator extends LaminasClassGenerator
1719
{
20+
public function generate(): string
21+
{
22+
$extendedClass = $this->getExtendedClass();
23+
24+
foreach ($this->getMethods() as $method) {
25+
foreach ($method->getParameters() as $parameter) {
26+
if ($extendedClass && method_exists($extendedClass, $method->getName()) && $default = $parameter->getDefaultValue()) {
27+
$parameter->setDefaultValue(new ValueGenerator($default, new ReflectionParameter([$extendedClass, $method->getName()], $parameter->getName())));
28+
}
29+
}
30+
}
31+
32+
return parent::generate();
33+
}
1834
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ProxyManager\Generator;
6+
7+
use Laminas\Code\Generator\ValueGenerator as LaminasValueGenerator;
8+
use Laminas\Code\Generator\Exception\RuntimeException;
9+
use UnitEnum;
10+
11+
use function is_array;
12+
13+
/**
14+
* @internal do not use this in your code: it is only here for internal use
15+
*/
16+
class ValueGenerator extends LaminasValueGenerator
17+
{
18+
private $reflection;
19+
20+
public function __construct(LaminasValueGenerator $value, \ReflectionParameter $reflection)
21+
{
22+
foreach ($value as $k => $v) {
23+
$this->$k = $v;
24+
}
25+
26+
$this->reflection = $reflection;
27+
}
28+
29+
public function generate(): string
30+
{
31+
if ($this->value instanceof UnitEnum) {
32+
return self::export($this->value);
33+
}
34+
35+
try {
36+
return parent::generate();
37+
} catch (RuntimeException $e) {
38+
// FIXME: indentation and root namespace
39+
return rtrim(substr(explode('$' . $this->reflection->name . ' = ', (string) $this->reflection, 2)[1], 0, -2));
40+
}
41+
}
42+
43+
public static function export($value): string
44+
{
45+
$value = var_export($value, true);
46+
$parts = preg_split('{(\'(?:[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')}', $value, -1, PREG_SPLIT_DELIM_CAPTURE);
47+
48+
foreach ($parts as $i => $part) {
49+
if ($part !== '' && $i % 2 === 0) {
50+
$parts[$i] = preg_replace('/(?(DEFINE)(?<V>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))(?&V)(?:\\\\(?&V))*+::/', '\\\\$0', $part);
51+
}
52+
}
53+
54+
return implode('', $parts);
55+
}
56+
}

src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/CallInitializer.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,20 @@
88
use Laminas\Code\Generator\PropertyGenerator;
99
use ProxyManager\Generator\MethodGenerator;
1010
use ProxyManager\Generator\Util\IdentifierSuffixer;
11+
use ProxyManager\Generator\ValueGenerator;
1112
use ProxyManager\ProxyGenerator\Util\Properties;
1213
use ReflectionProperty;
1314

1415
use function array_map;
1516
use function implode;
17+
use function preg_replace;
18+
use function preg_split;
1619
use function sprintf;
1720
use function str_replace;
1821
use function var_export;
1922

23+
use const PREG_SPLIT_DELIM_CAPTURE;
24+
2025
/**
2126
* Implementation for {@see \ProxyManager\Proxy\LazyLoadingInterface::isProxyInitialized}
2227
* for lazy loading value holder objects
@@ -170,6 +175,15 @@ private function getExportedPropertyDefaultValue(ReflectionProperty $property):
170175
$name = $property->getName();
171176
$defaults = $property->getDeclaringClass()->getDefaultProperties();
172177

173-
return var_export($defaults[$name] ?? null, true);
178+
$value = var_export($defaults[$name] ?? null, true);
179+
$parts = preg_split('{(\'(?:[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')}', $value, -1, PREG_SPLIT_DELIM_CAPTURE);
180+
181+
foreach ($parts as $i => $part) {
182+
if ($part !== '' && $i % 2 === 0) {
183+
$parts[$i] = preg_replace('/(?(DEFINE)(?<V>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))(?&V)(?:\\\\(?&V))*+::/', '\\\\$0', $part);
184+
}
185+
}
186+
187+
return implode('', $parts);
174188
}
175189
}

src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/RemoteObjectMethod.php

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ class RemoteObjectMethod extends MethodGenerator
2121
{
2222
private const TEMPLATE
2323
= <<<'PHP'
24-
$defaultValues = #DEFAULT_VALUES#;
25-
$declaredParameterCount = #PARAMETER_COUNT#;
24+
static $reflection;
2625
27-
$args = \func_get_args() + $defaultValues;
26+
$args = \func_get_args();
27+
28+
switch (\func_num_args()) {#DEFAULT_VALUES#
29+
}
2830
2931
#PROXIED_RETURN#
3032
PHP;
@@ -41,39 +43,36 @@ public static function generateMethod(
4143
. ', ' . var_export($originalMethod->getName(), true) . ', $args);' . "\n\n"
4244
. ProxiedMethodReturnExpression::generate('$return', $originalMethod);
4345

44-
$defaultValues = self::getDefaultValuesForMethod($originalMethod);
45-
$declaredParameterCount = count($originalMethod->getParameters());
46+
$defaultValues = self::getDefaultValuesForMethod($originalMethod);
4647

4748
$method->setBody(
4849
strtr(
4950
self::TEMPLATE,
5051
[
5152
'#PROXIED_RETURN#' => $proxiedReturn,
52-
'#DEFAULT_VALUES#' => var_export($defaultValues, true),
53-
'#PARAMETER_COUNT#' => var_export($declaredParameterCount, true),
53+
'#DEFAULT_VALUES#' => $defaultValues,
5454
]
5555
)
5656
);
5757

5858
return $method;
5959
}
6060

61-
/** @psalm-return list<int|float|bool|array|string|null> */
62-
private static function getDefaultValuesForMethod(MethodReflection $originalMethod): array
61+
private static function getDefaultValuesForMethod(MethodReflection $originalMethod): string
6362
{
64-
$defaultValues = [];
65-
foreach ($originalMethod->getParameters() as $parameter) {
63+
$parameters = sprintf('($reflection ?? $reflection = (new \ReflectionMethod(\'%s\', \'%s\'))->getParameters())', $originalMethod->class, $originalMethod->name);
64+
$defaultValues = '';
65+
foreach ($originalMethod->getParameters() as $i => $parameter) {
6666
if ($parameter->isOptional() && $parameter->isDefaultValueAvailable()) {
67-
/** @psalm-var int|float|bool|array|string|null */
68-
$defaultValues[] = $parameter->getDefaultValue();
67+
$defaultValues .= "\n case $i: \$args[] = {$parameters}[$i]->getDefaultValue();";
6968
continue;
7069
}
7170

7271
if ($parameter->isVariadic()) {
7372
continue;
7473
}
7574

76-
$defaultValues[] = null;
75+
$defaultValues .= "\n case $i: \$args[] = NULL;";
7776
}
7877

7978
return $defaultValues;

tests/ProxyManagerTest/Functional/FatalPreventionFunctionalTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
namespace ProxyManagerTest\Functional;
66

7-
use Laminas\Code\Generator\ClassGenerator;
87
use PHPUnit\Framework\TestCase;
98
use ProxyManager\Exception\ExceptionInterface;
9+
use ProxyManager\Generator\ClassGenerator;
1010
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
1111
use ProxyManager\Proxy\ProxyInterface;
1212
use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizerGenerator;

tests/ProxyManagerTest/Functional/MultipleProxyGenerationTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use ProxyManagerTestAsset\ClassWithMixedTypedProperties;
2323
use ProxyManagerTestAsset\ClassWithParentHint;
2424
use ProxyManagerTestAsset\ClassWithPhp80TypedMethods;
25+
use ProxyManagerTestAsset\ClassWithPhp81Defaults;
2526
use ProxyManagerTestAsset\ClassWithPrivateProperties;
2627
use ProxyManagerTestAsset\ClassWithProtectedProperties;
2728
use ProxyManagerTestAsset\ClassWithPublicProperties;
@@ -138,6 +139,10 @@ public function getTestedClasses(): array
138139
$objects[] = [new ClassWithPhp80TypedMethods()];
139140
}
140141

142+
if (PHP_VERSION_ID >= 80100) {
143+
$objects['php81defaults'] = [new ClassWithPhp81Defaults()];
144+
}
145+
141146
return $objects;
142147
}
143148
}

tests/ProxyManagerTest/GeneratorStrategy/BaseGeneratorStrategyTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
namespace ProxyManagerTest\GeneratorStrategy;
66

7-
use Laminas\Code\Generator\ClassGenerator;
87
use PHPUnit\Framework\TestCase;
8+
use ProxyManager\Generator\ClassGenerator;
99
use ProxyManager\Generator\Util\UniqueIdentifierGenerator;
1010
use ProxyManager\GeneratorStrategy\BaseGeneratorStrategy;
1111

tests/ProxyManagerTest/GeneratorStrategy/EvaluatingGeneratorStrategyTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
namespace ProxyManagerTest\GeneratorStrategy;
66

7-
use Laminas\Code\Generator\ClassGenerator;
87
use PHPUnit\Framework\TestCase;
8+
use ProxyManager\Generator\ClassGenerator;
99
use ProxyManager\Generator\Util\UniqueIdentifierGenerator;
1010
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
1111

tests/ProxyManagerTest/GeneratorStrategy/FileWriterGeneratorStrategyTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
namespace ProxyManagerTest\GeneratorStrategy;
66

7-
use Laminas\Code\Generator\ClassGenerator;
87
use PHPUnit\Framework\TestCase;
98
use ProxyManager\Exception\FileNotWritableException;
109
use ProxyManager\FileLocator\FileLocatorInterface;
10+
use ProxyManager\Generator\ClassGenerator;
1111
use ProxyManager\Generator\Util\UniqueIdentifierGenerator;
1212
use ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy;
1313

tests/ProxyManagerTest/ProxyGenerator/AbstractProxyGeneratorTest.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
namespace ProxyManagerTest\ProxyGenerator;
66

7-
use Laminas\Code\Generator\ClassGenerator;
87
use PHPUnit\Framework\TestCase;
8+
use ProxyManager\Generator\ClassGenerator;
99
use ProxyManager\Generator\Util\UniqueIdentifierGenerator;
1010
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
1111
use ProxyManager\ProxyGenerator\ProxyGeneratorInterface;
@@ -18,6 +18,7 @@
1818
use ProxyManagerTestAsset\ClassWithMixedReferenceableTypedProperties;
1919
use ProxyManagerTestAsset\ClassWithMixedTypedProperties;
2020
use ProxyManagerTestAsset\ClassWithPhp80TypedMethods;
21+
use ProxyManagerTestAsset\ClassWithPhp81Defaults;
2122
use ProxyManagerTestAsset\IterableMethodTypeHintedInterface;
2223
use ProxyManagerTestAsset\ObjectMethodTypeHintedInterface;
2324
use ProxyManagerTestAsset\ReturnTypeHintedClass;
@@ -112,6 +113,10 @@ public function getTestedImplementations(): array
112113
$implementations[] = [ClassWithPhp80TypedMethods::class];
113114
}
114115

116+
if (PHP_VERSION_ID >= 80100) {
117+
$implementations['php81defaults'] = [ClassWithPhp81Defaults::class];
118+
}
119+
115120
return $implementations;
116121
}
117122
}

tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
namespace ProxyManagerTest\ProxyGenerator;
66

7-
use Laminas\Code\Generator\ClassGenerator;
87
use ProxyManager\Exception\InvalidProxiedClassException;
98
use ProxyManager\Exception\UnsupportedProxiedClassException;
9+
use ProxyManager\Generator\ClassGenerator;
1010
use ProxyManager\Proxy\AccessInterceptorInterface;
1111
use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizerGenerator;
1212
use ProxyManager\ProxyGenerator\ProxyGeneratorInterface;

tests/ProxyManagerTest/ProxyGenerator/LazyLoadingGhostGeneratorTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
namespace ProxyManagerTest\ProxyGenerator;
66

7-
use Laminas\Code\Generator\ClassGenerator;
87
use ProxyManager\Exception\InvalidProxiedClassException;
8+
use ProxyManager\Generator\ClassGenerator;
99
use ProxyManager\Proxy\GhostObjectInterface;
1010
use ProxyManager\ProxyGenerator\LazyLoadingGhostGenerator;
1111
use ProxyManager\ProxyGenerator\ProxyGeneratorInterface;

tests/ProxyManagerTest/ProxyGenerator/NullObjectGeneratorTest.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace ProxyManagerTest\ProxyGenerator;
66

7-
use Laminas\Code\Generator\ClassGenerator;
7+
use ProxyManager\Generator\ClassGenerator;
88
use ProxyManager\Generator\Util\UniqueIdentifierGenerator;
99
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
1010
use ProxyManager\Proxy\NullObjectInterface;
@@ -19,6 +19,7 @@
1919
use ProxyManagerTestAsset\ClassWithMixedReferenceableTypedProperties;
2020
use ProxyManagerTestAsset\ClassWithMixedTypedProperties;
2121
use ProxyManagerTestAsset\ClassWithPhp80TypedMethods;
22+
use ProxyManagerTestAsset\ClassWithPhp81Defaults;
2223
use ReflectionClass;
2324
use ReflectionMethod;
2425

@@ -131,6 +132,10 @@ public function getTestedImplementations(): array
131132
$implementations[] = [ClassWithPhp80TypedMethods::class];
132133
}
133134

135+
if (PHP_VERSION_ID >= 80100) {
136+
$implementations[] = [ClassWithPhp81Defaults::class];
137+
}
138+
134139
return $implementations;
135140
}
136141
}

tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/RemoteObjectMethodTest.php

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,14 @@ public function testBodyStructureWithParameters(): void
4040
self::assertSame('publicByReferenceParameterMethod', $method->getName());
4141
self::assertCount(2, $method->getParameters());
4242
self::assertSame(
43-
'$defaultValues = array (
44-
0 => NULL,
45-
1 => NULL,
46-
);
47-
$declaredParameterCount = 2;
43+
'static $reflection;
4844
49-
$args = \func_get_args() + $defaultValues;
45+
$args = \func_get_args();
46+
47+
switch (\func_num_args()) {
48+
case 0: $args[] = NULL;
49+
case 1: $args[] = NULL;
50+
}
5051
5152
$return = $this->adapter->call(\'Laminas\\\\Code\\\\Generator\\\\PropertyGenerator\', \'publicByReferenceParameterMethod\', $args);
5253
@@ -74,12 +75,13 @@ public function testBodyStructureWithArrayParameter(): void
7475
self::assertSame('publicArrayHintedMethod', $method->getName());
7576
self::assertCount(1, $method->getParameters());
7677
self::assertSame(
77-
"\$defaultValues = array (
78-
0 => NULL,
79-
);
80-
\$declaredParameterCount = 1;
78+
"static \$reflection;
79+
80+
\$args = \\func_get_args();
8181
82-
\$args = \\func_get_args() + \$defaultValues;
82+
switch (\\func_num_args()) {
83+
case 0: \$args[] = NULL;
84+
}
8385
8486
\$return = \$this->adapter->call('Laminas\\\\Code\\\\Generator\\\\PropertyGenerator', 'publicArrayHintedMethod', \$args);
8587
@@ -107,11 +109,12 @@ public function testBodyStructureWithoutParameters(): void
107109
self::assertSame('publicMethod', $method->getName());
108110
self::assertCount(0, $method->getParameters());
109111
self::assertSame(
110-
"\$defaultValues = array (
111-
);
112-
\$declaredParameterCount = 0;
112+
"static \$reflection;
113+
114+
\$args = \\func_get_args();
113115
114-
\$args = \\func_get_args() + \$defaultValues;
116+
switch (\\func_num_args()) {
117+
}
115118
116119
\$return = \$this->adapter->call('Laminas\\\\Code\\\\Generator\\\\PropertyGenerator', 'publicMethod', \$args);
117120

0 commit comments

Comments
 (0)