@@ -2264,6 +2264,8 @@ class ClassInfo {
2264
2264
/** @var bool */
2265
2265
public $ isStrictProperties ;
2266
2266
/** @var bool */
2267
+ public $ allowsDynamicProperties ;
2268
+ /** @var bool */
2267
2269
public $ isNotSerializable ;
2268
2270
/** @var Name[] */
2269
2271
public $ extends ;
@@ -2296,6 +2298,7 @@ public function __construct(
2296
2298
?SimpleType $ enumBackingType ,
2297
2299
bool $ isDeprecated ,
2298
2300
bool $ isStrictProperties ,
2301
+ bool $ allowsDynamicProperties ,
2299
2302
bool $ isNotSerializable ,
2300
2303
array $ extends ,
2301
2304
array $ implements ,
@@ -2312,6 +2315,7 @@ public function __construct(
2312
2315
$ this ->enumBackingType = $ enumBackingType ;
2313
2316
$ this ->isDeprecated = $ isDeprecated ;
2314
2317
$ this ->isStrictProperties = $ isStrictProperties ;
2318
+ $ this ->allowsDynamicProperties = $ allowsDynamicProperties ;
2315
2319
$ this ->isNotSerializable = $ isNotSerializable ;
2316
2320
$ this ->extends = $ extends ;
2317
2321
$ this ->implements = $ implements ;
@@ -2400,6 +2404,10 @@ function (Name $item) {
2400
2404
$ code .= $ property ->getDeclaration ($ allConstInfos );
2401
2405
}
2402
2406
2407
+ if ($ this ->allowsDynamicProperties ) {
2408
+ $ code .= "\tzend_add_class_attribute(class_entry, zend_ce_allow_dynamic_properties->name, 0); \n" ;
2409
+ }
2410
+
2403
2411
if ($ attributeInitializationCode = generateAttributeInitialization ($ this ->funcInfos , $ this ->cond )) {
2404
2412
$ code .= "\n" . $ attributeInitializationCode ;
2405
2413
}
@@ -2443,6 +2451,10 @@ private function getFlagsAsString(): string
2443
2451
$ flags [] = "ZEND_ACC_NO_DYNAMIC_PROPERTIES " ;
2444
2452
}
2445
2453
2454
+ if ($ this ->allowsDynamicProperties ) {
2455
+ $ flags [] = "ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES " ;
2456
+ }
2457
+
2446
2458
if ($ this ->isNotSerializable ) {
2447
2459
$ flags [] = "ZEND_ACC_NOT_SERIALIZABLE " ;
2448
2460
}
@@ -3264,6 +3276,7 @@ function parseClass(
3264
3276
$ isDeprecated = false ;
3265
3277
$ isStrictProperties = false ;
3266
3278
$ isNotSerializable = false ;
3279
+ $ allowsDynamicProperties = false ;
3267
3280
3268
3281
if ($ comment ) {
3269
3282
$ tags = parseDocComment ($ comment );
@@ -3280,6 +3293,18 @@ function parseClass(
3280
3293
}
3281
3294
}
3282
3295
3296
+ foreach ($ class ->attrGroups as $ attrGroup ) {
3297
+ foreach ($ attrGroup ->attrs as $ attr ) {
3298
+ switch ($ attr ->name ->toCodeString ()) {
3299
+ case '\\AllowDynamicProperties ' :
3300
+ $ allowsDynamicProperties = true ;
3301
+ break ;
3302
+ default :
3303
+ throw new Exception ("Unhandled attribute {$ attr ->name ->toCodeString ()}. " );
3304
+ }
3305
+ }
3306
+ }
3307
+
3283
3308
$ extends = [];
3284
3309
$ implements = [];
3285
3310
@@ -3310,6 +3335,7 @@ function parseClass(
3310
3335
? SimpleType::fromNode ($ class ->scalarType ) : null ,
3311
3336
$ isDeprecated ,
3312
3337
$ isStrictProperties ,
3338
+ $ allowsDynamicProperties ,
3313
3339
$ isNotSerializable ,
3314
3340
$ extends ,
3315
3341
$ implements ,
0 commit comments