@@ -887,6 +887,9 @@ private function createService(Definition $definition, $id, $tryProxy = true)
887
887
$ arguments = $ this ->resolveServices ($ parameterBag ->unescapeValue ($ parameterBag ->resolveValue ($ definition ->getArguments ())));
888
888
889
889
if (null !== $ factory = $ definition ->getFactory ()) {
890
+ if ($ definition ->getOverriddenGetters ()) {
891
+ throw new RuntimeException (sprintf ('Cannot dump definition: The "%s" service has both a factory and overridden getters but these are incompatible. ' , $ id ));
892
+ }
890
893
if (is_array ($ factory )) {
891
894
$ factory = array ($ this ->resolveServices ($ parameterBag ->resolveValue ($ factory [0 ])), $ factory [1 ]);
892
895
} elseif (!is_string ($ factory )) {
@@ -905,11 +908,15 @@ private function createService(Definition $definition, $id, $tryProxy = true)
905
908
} else {
906
909
$ r = new \ReflectionClass ($ parameterBag ->resolveValue ($ definition ->getClass ()));
907
910
908
- $ service = null === $ r ->getConstructor () ? $ r ->newInstance () : $ r ->newInstanceArgs ($ arguments );
909
-
910
911
if (!$ definition ->isDeprecated () && 0 < strpos ($ r ->getDocComment (), "\n * @deprecated " )) {
911
912
@trigger_error (sprintf ('The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded. ' , $ id , $ r ->name ), E_USER_DEPRECATED );
912
913
}
914
+ if ($ definition ->getOverriddenGetters ()) {
915
+ $ service = eval (sprintf ('return new class(...$arguments) extends %s { private $c0nt41n3r; private $g3ttErV4lu35; %s }; ' , $ r ->name , $ this ->addOverriddenGetters ($ id , $ definition , $ r )));
916
+ call_user_func (\Closure::bind (function ($ c , $ v ) { $ this ->c0nt41n3r = $ c ; $ this ->g3ttErV4lu35 = $ v ; }, $ service , $ service ), $ this , $ definition ->getOverriddenGetters ());
917
+ } else {
918
+ $ service = null === $ r ->getConstructor () ? $ r ->newInstance () : $ r ->newInstanceArgs ($ arguments );
919
+ }
913
920
}
914
921
915
922
if ($ tryProxy || !$ definition ->isLazy ()) {
@@ -1114,6 +1121,60 @@ public function getEnvCounters()
1114
1121
return $ this ->envCounters ;
1115
1122
}
1116
1123
1124
+ private function addOverriddenGetters ($ id , Definition $ definition , \ReflectionClass $ class )
1125
+ {
1126
+ if (PHP_VERSION_ID < 70000 ) {
1127
+ throw new RuntimeException (sprintf ('Getter-based injection requires PHP 7 or more as used for service "%s". ' , $ id ));
1128
+ }
1129
+ if ($ class ->isFinal ()) {
1130
+ throw new RuntimeException (sprintf ('Invalid getter for service "%s": class "%s" is final. ' , $ id , $ class ->name ));
1131
+ }
1132
+ $ getters = '' ;
1133
+ foreach ($ definition ->getOverriddenGetters () as $ name => $ returnValue ) {
1134
+ if (!$ class ->hasMethod ($ name )) {
1135
+ throw new RuntimeException (sprintf ('Invalid getter for service "%s": method "%s::%s" does not exist. ' , $ id , $ class ->name , $ name ));
1136
+ }
1137
+ if (($ r = $ class ->getMethod ($ name ))->isPrivate ()) {
1138
+ throw new RuntimeException (sprintf ('Invalid getter for service "%s": method "%s::%s" is private. ' , $ id , $ class ->name , $ name ));
1139
+ }
1140
+ if ($ r ->isFinal ()) {
1141
+ throw new RuntimeException (sprintf ('Invalid getter for service "%s": method "%s::%s" is final. ' , $ id , $ class ->name , $ name ));
1142
+ }
1143
+ if ($ r ->isInternal ()) {
1144
+ throw new RuntimeException (sprintf ('Invalid getter for service "%s": method "%s::%s" is internal. ' , $ id , $ class ->name , $ name ));
1145
+ }
1146
+ if ($ r ->returnsReference ()) {
1147
+ throw new RuntimeException (sprintf ('Invalid getter for service "%s": method "%s::%s" returns by reference. ' , $ id , $ class ->name , $ name ));
1148
+ }
1149
+ if (0 < $ r ->getNumberOfParameters ()) {
1150
+ throw new RuntimeException (sprintf ('Invalid getter for service "%s": method "%s::%s" has parameters. ' , $ id , $ class ->name , $ name ));
1151
+ }
1152
+ if ($ type = $ r ->getReturnType ()) {
1153
+ $ type = ': ' .($ type ->allowsNull () ? '? ' : '' ).$ this ->generateTypeHint ($ type , $ r );
1154
+ }
1155
+ $ visibility = $ r ->isProtected () ? 'protected ' : 'public ' ;
1156
+ $ nameExport = var_export ($ name , true );
1157
+ $ getters .= <<<EOF
1158
+
1159
+ $ visibility function $ name() $ type {
1160
+ \$c = \$this->cOnt4In3r;
1161
+ \$b = \$c->getParameterBag();
1162
+ \$v = \$this->g3ttErV4lu35[ $ nameExport];
1163
+
1164
+ foreach ( \$c->getServiceConditionals( \$v) as \$s) {
1165
+ if (! \$c->has( \$s)) {
1166
+ return parent:: $ name();
1167
+ }
1168
+ }
1169
+
1170
+ return \$c->resolveServices( \$b->unescapeValue( \$b->resolveValue( \$v)));
1171
+ }
1172
+ EOF ;
1173
+ }
1174
+
1175
+ return $ getters ;
1176
+ }
1177
+
1117
1178
/**
1118
1179
* Returns the Service Conditionals.
1119
1180
*
0 commit comments