@@ -82,6 +82,12 @@ final class ClassReflection
82
82
/** @var ExtendedPropertyReflection[] */
83
83
private array $ properties = [];
84
84
85
+ /** @var ExtendedPropertyReflection[] */
86
+ private array $ instanceProperties = [];
87
+
88
+ /** @var ExtendedPropertyReflection[] */
89
+ private array $ staticProperties = [];
90
+
85
91
/** @var RealClassClassConstantReflection[] */
86
92
private array $ constants = [];
87
93
@@ -148,6 +154,12 @@ final class ClassReflection
148
154
/** @var array<string, bool> */
149
155
private array $ hasPropertyCache = [];
150
156
157
+ /** @var array<string, bool> */
158
+ private array $ hasInstancePropertyCache = [];
159
+
160
+ /** @var array<string, bool> */
161
+ private array $ hasStaticPropertyCache = [];
162
+
151
163
/**
152
164
* @param PropertiesClassReflectionExtension[] $propertiesClassReflectionExtensions
153
165
* @param MethodsClassReflectionExtension[] $methodsClassReflectionExtensions
@@ -462,6 +474,9 @@ private function allowsDynamicPropertiesExtensions(): bool
462
474
return false ;
463
475
}
464
476
477
+ /**
478
+ * @deprecated Use hasInstanceProperty or hasStaticProperty instead
479
+ */
465
480
public function hasProperty (string $ propertyName ): bool
466
481
{
467
482
if (array_key_exists ($ propertyName , $ this ->hasPropertyCache )) {
@@ -481,13 +496,61 @@ public function hasProperty(string $propertyName): bool
481
496
}
482
497
}
483
498
499
+ // For BC purpose
500
+ if ($ this ->getPhpExtension ()->hasStaticProperty ($ this , $ propertyName )) {
501
+ return $ this ->hasPropertyCache [$ propertyName ] = true ;
502
+ }
503
+
484
504
if ($ this ->requireExtendsPropertiesClassReflectionExtension ->hasProperty ($ this , $ propertyName )) {
485
505
return $ this ->hasPropertyCache [$ propertyName ] = true ;
486
506
}
487
507
488
508
return $ this ->hasPropertyCache [$ propertyName ] = false ;
489
509
}
490
510
511
+ public function hasInstanceProperty (string $ propertyName ): bool
512
+ {
513
+ if (array_key_exists ($ propertyName , $ this ->hasInstancePropertyCache )) {
514
+ return $ this ->hasInstancePropertyCache [$ propertyName ];
515
+ }
516
+
517
+ if ($ this ->isEnum ()) {
518
+ return $ this ->hasInstancePropertyCache [$ propertyName ] = $ this ->hasNativeProperty ($ propertyName );
519
+ }
520
+
521
+ foreach ($ this ->propertiesClassReflectionExtensions as $ i => $ extension ) {
522
+ if ($ i > 0 && !$ this ->allowsDynamicPropertiesExtensions ()) {
523
+ break ;
524
+ }
525
+ if ($ extension ->hasProperty ($ this , $ propertyName )) {
526
+ return $ this ->hasInstancePropertyCache [$ propertyName ] = true ;
527
+ }
528
+ }
529
+
530
+ if ($ this ->requireExtendsPropertiesClassReflectionExtension ->hasInstanceProperty ($ this , $ propertyName )) {
531
+ return $ this ->hasPropertyCache [$ propertyName ] = true ;
532
+ }
533
+
534
+ return $ this ->hasPropertyCache [$ propertyName ] = false ;
535
+ }
536
+
537
+ public function hasStaticProperty (string $ propertyName ): bool
538
+ {
539
+ if (array_key_exists ($ propertyName , $ this ->hasStaticPropertyCache )) {
540
+ return $ this ->hasStaticPropertyCache [$ propertyName ];
541
+ }
542
+
543
+ if ($ this ->getPhpExtension ()->hasStaticProperty ($ this , $ propertyName )) {
544
+ return $ this ->hasStaticPropertyCache [$ propertyName ] = true ;
545
+ }
546
+
547
+ if ($ this ->requireExtendsPropertiesClassReflectionExtension ->hasStaticProperty ($ this , $ propertyName )) {
548
+ return $ this ->hasStaticPropertyCache [$ propertyName ] = true ;
549
+ }
550
+
551
+ return $ this ->hasStaticPropertyCache [$ propertyName ] = false ;
552
+ }
553
+
491
554
public function hasMethod (string $ methodName ): bool
492
555
{
493
556
if (array_key_exists ($ methodName , $ this ->hasMethodCache )) {
@@ -632,6 +695,20 @@ public function evictPrivateSymbols(): void
632
695
633
696
unset($ this ->properties [$ name ]);
634
697
}
698
+ foreach ($ this ->instanceProperties as $ name => $ property ) {
699
+ if (!$ property ->isPrivate ()) {
700
+ continue ;
701
+ }
702
+
703
+ unset($ this ->instanceProperties [$ name ]);
704
+ }
705
+ foreach ($ this ->staticProperties as $ name => $ property ) {
706
+ if (!$ property ->isPrivate ()) {
707
+ continue ;
708
+ }
709
+
710
+ unset($ this ->staticProperties [$ name ]);
711
+ }
635
712
foreach ($ this ->methods as $ name => $ method ) {
636
713
if (!$ method ->isPrivate ()) {
637
714
continue ;
@@ -642,6 +719,7 @@ public function evictPrivateSymbols(): void
642
719
$ this ->getPhpExtension ()->evictPrivateSymbols ($ this ->getCacheKey ());
643
720
}
644
721
722
+ /** @deprecated Use getInstanceProperty or getStaticProperty */
645
723
public function getProperty (string $ propertyName , ClassMemberAccessAnswerer $ scope ): ExtendedPropertyReflection
646
724
{
647
725
if ($ this ->isEnum ()) {
@@ -671,6 +749,15 @@ public function getProperty(string $propertyName, ClassMemberAccessAnswerer $sco
671
749
}
672
750
}
673
751
752
+ // For BC purpose
753
+ if ($ this ->getPhpExtension ()->hasStaticProperty ($ this , $ propertyName )) {
754
+ $ property = $ this ->wrapExtendedProperty ($ this ->getPhpExtension ()->getStaticProperty ($ this , $ propertyName ));
755
+ if ($ scope ->canReadProperty ($ property )) {
756
+ return $ this ->properties [$ key ] = $ property ;
757
+ }
758
+ $ this ->properties [$ key ] = $ property ;
759
+ }
760
+
674
761
if (!isset ($ this ->properties [$ key ])) {
675
762
if ($ this ->requireExtendsPropertiesClassReflectionExtension ->hasProperty ($ this , $ propertyName )) {
676
763
$ property = $ this ->requireExtendsPropertiesClassReflectionExtension ->getProperty ($ this , $ propertyName );
@@ -685,9 +772,83 @@ public function getProperty(string $propertyName, ClassMemberAccessAnswerer $sco
685
772
return $ this ->properties [$ key ];
686
773
}
687
774
775
+ public function getInstanceProperty (string $ propertyName , ClassMemberAccessAnswerer $ scope ): ExtendedPropertyReflection
776
+ {
777
+ if ($ this ->isEnum ()) {
778
+ return $ this ->getNativeProperty ($ propertyName );
779
+ }
780
+
781
+ $ key = $ propertyName ;
782
+ if ($ scope ->isInClass ()) {
783
+ $ key = sprintf ('%s-%s ' , $ key , $ scope ->getClassReflection ()->getCacheKey ());
784
+ }
785
+
786
+ if (!isset ($ this ->instanceProperties [$ key ])) {
787
+ foreach ($ this ->propertiesClassReflectionExtensions as $ i => $ extension ) {
788
+ if ($ i > 0 && !$ this ->allowsDynamicPropertiesExtensions ()) {
789
+ break ;
790
+ }
791
+
792
+ if (!$ extension ->hasProperty ($ this , $ propertyName )) {
793
+ continue ;
794
+ }
795
+
796
+ $ property = $ this ->wrapExtendedProperty ($ extension ->getProperty ($ this , $ propertyName ));
797
+ if ($ scope ->canReadProperty ($ property )) {
798
+ return $ this ->instanceProperties [$ key ] = $ property ;
799
+ }
800
+ $ this ->instanceProperties [$ key ] = $ property ;
801
+ }
802
+ }
803
+
804
+ if (!isset ($ this ->instanceProperties [$ key ])) {
805
+ if ($ this ->requireExtendsPropertiesClassReflectionExtension ->hasInstanceProperty ($ this , $ propertyName )) {
806
+ $ property = $ this ->requireExtendsPropertiesClassReflectionExtension ->getInstanceProperty ($ this , $ propertyName );
807
+ $ this ->instanceProperties [$ key ] = $ property ;
808
+ }
809
+ }
810
+
811
+ if (!isset ($ this ->instanceProperties [$ key ])) {
812
+ throw new MissingPropertyFromReflectionException ($ this ->getName (), $ propertyName );
813
+ }
814
+
815
+ return $ this ->instanceProperties [$ key ];
816
+ }
817
+
818
+ public function getStaticProperty (string $ propertyName , ClassMemberAccessAnswerer $ scope ): ExtendedPropertyReflection
819
+ {
820
+ $ key = $ propertyName ;
821
+ if ($ scope ->isInClass ()) {
822
+ $ key = sprintf ('%s-%s ' , $ key , $ scope ->getClassReflection ()->getCacheKey ());
823
+ }
824
+
825
+ if (!isset ($ this ->staticProperties [$ key ])) {
826
+ if ($ this ->getPhpExtension ()->hasStaticProperty ($ this , $ propertyName )) {
827
+ $ property = $ this ->wrapExtendedProperty ($ this ->getPhpExtension ()->getStaticProperty ($ this , $ propertyName ));
828
+ if ($ scope ->canReadProperty ($ property )) {
829
+ return $ this ->staticProperties [$ key ] = $ property ;
830
+ }
831
+ $ this ->staticProperties [$ key ] = $ property ;
832
+ }
833
+ }
834
+
835
+ if (!isset ($ this ->staticProperties [$ key ])) {
836
+ if ($ this ->requireExtendsPropertiesClassReflectionExtension ->hasStaticProperty ($ this , $ propertyName )) {
837
+ $ property = $ this ->requireExtendsPropertiesClassReflectionExtension ->getStaticProperty ($ this , $ propertyName );
838
+ $ this ->staticProperties [$ key ] = $ property ;
839
+ }
840
+ }
841
+
842
+ if (!isset ($ this ->staticProperties [$ key ])) {
843
+ throw new MissingPropertyFromReflectionException ($ this ->getName (), $ propertyName );
844
+ }
845
+
846
+ return $ this ->staticProperties [$ key ];
847
+ }
848
+
688
849
public function hasNativeProperty (string $ propertyName ): bool
689
850
{
690
- return $ this ->getPhpExtension ()->hasProperty ($ this , $ propertyName );
851
+ return $ this ->getPhpExtension ()->hasNativeProperty ($ this , $ propertyName );
691
852
}
692
853
693
854
public function getNativeProperty (string $ propertyName ): PhpPropertyReflection
0 commit comments