1717use phpDocumentor \Reflection \DocBlock \Tags \Author ;
1818use phpDocumentor \Reflection \DocBlock \Tags \Covers ;
1919use phpDocumentor \Reflection \DocBlock \Tags \Deprecated ;
20+ use phpDocumentor \Reflection \DocBlock \Tags \Factory \Factory ;
2021use phpDocumentor \Reflection \DocBlock \Tags \Generic ;
2122use phpDocumentor \Reflection \DocBlock \Tags \InvalidTag ;
2223use phpDocumentor \Reflection \DocBlock \Tags \Link as LinkTag ;
4041use ReflectionParameter ;
4142use Webmozart \Assert \Assert ;
4243
44+ use function array_key_exists ;
4345use function array_merge ;
4446use function array_slice ;
4547use function call_user_func_array ;
4648use function count ;
4749use function get_class ;
50+ use function is_object ;
4851use function preg_match ;
52+ use function sprintf ;
4953use function strpos ;
5054use function trim ;
5155
@@ -72,7 +76,7 @@ final class StandardTagFactory implements TagFactory
7276 public const REGEX_TAGNAME = '[\w\-\_ \\\\:]+ ' ;
7377
7478 /**
75- * @var array<class-string<Tag>> An array with a tag as a key, and an
79+ * @var array<class-string<Tag>|Factory > An array with a tag as a key, and an
7680 * FQCN to a class that handles it as an array value.
7781 */
7882 private $ tagHandlerMappings = [
@@ -162,18 +166,25 @@ public function addService(object $service, ?string $alias = null): void
162166 $ this ->serviceLocator [$ alias ?: get_class ($ service )] = $ service ;
163167 }
164168
165- public function registerTagHandler (string $ tagName , string $ handler ): void
169+ /** {@inheritDoc} */
170+ public function registerTagHandler (string $ tagName , $ handler ): void
166171 {
167172 Assert::stringNotEmpty ($ tagName );
168- Assert::classExists ($ handler );
169- Assert::implementsInterface ($ handler , Tag::class);
170-
171173 if (strpos ($ tagName , '\\' ) && $ tagName [0 ] !== '\\' ) {
172174 throw new InvalidArgumentException (
173175 'A namespaced tag must have a leading backslash as it must be fully qualified '
174176 );
175177 }
176178
179+ if (is_object ($ handler )) {
180+ Assert::isInstanceOf ($ handler , Factory::class);
181+ $ this ->tagHandlerMappings [$ tagName ] = $ handler ;
182+
183+ return ;
184+ }
185+
186+ Assert::classExists ($ handler );
187+ Assert::implementsInterface ($ handler , Tag::class);
177188 $ this ->tagHandlerMappings [$ tagName ] = $ handler ;
178189 }
179190
@@ -210,6 +221,10 @@ private function createTag(string $body, string $name, TypeContext $context): Ta
210221 $ this ->getServiceLocatorWithDynamicParameters ($ context , $ name , $ body )
211222 );
212223
224+ if (array_key_exists ('tagLine ' , $ arguments )) {
225+ $ arguments ['tagLine ' ] = sprintf ('@%s %s ' , $ name , $ body );
226+ }
227+
213228 try {
214229 $ callable = [$ handlerClassName , 'create ' ];
215230 Assert::isCallable ($ callable );
@@ -225,9 +240,9 @@ private function createTag(string $body, string $name, TypeContext $context): Ta
225240 /**
226241 * Determines the Fully Qualified Class Name of the Factory or Tag (containing a Factory Method `create`).
227242 *
228- * @return class-string<Tag>
243+ * @return class-string<Tag>|Factory
229244 */
230- private function findHandlerClassName (string $ tagName , TypeContext $ context ): string
245+ private function findHandlerClassName (string $ tagName , TypeContext $ context )
231246 {
232247 $ handlerClassName = Generic::class;
233248 if (isset ($ this ->tagHandlerMappings [$ tagName ])) {
@@ -268,18 +283,18 @@ private function getArgumentsForParametersFromWiring(array $parameters, array $l
268283 }
269284 }
270285
286+ $ parameterName = $ parameter ->getName ();
271287 if (isset ($ locator [$ typeHint ])) {
272- $ arguments [] = $ locator [$ typeHint ];
288+ $ arguments [$ parameterName ] = $ locator [$ typeHint ];
273289 continue ;
274290 }
275291
276- $ parameterName = $ parameter ->getName ();
277292 if (isset ($ locator [$ parameterName ])) {
278- $ arguments [] = $ locator [$ parameterName ];
293+ $ arguments [$ parameterName ] = $ locator [$ parameterName ];
279294 continue ;
280295 }
281296
282- $ arguments [] = null ;
297+ $ arguments [$ parameterName ] = null ;
283298 }
284299
285300 return $ arguments ;
@@ -289,12 +304,14 @@ private function getArgumentsForParametersFromWiring(array $parameters, array $l
289304 * Retrieves a series of ReflectionParameter objects for the static 'create' method of the given
290305 * tag handler class name.
291306 *
292- * @param class-string $handlerClassName
307+ * @param class-string|Factory $handler
293308 *
294309 * @return ReflectionParameter[]
295310 */
296- private function fetchParametersForHandlerFactoryMethod (string $ handlerClassName ): array
311+ private function fetchParametersForHandlerFactoryMethod ($ handler ): array
297312 {
313+ $ handlerClassName = is_object ($ handler ) ? get_class ($ handler ) : $ handler ;
314+
298315 if (!isset ($ this ->tagHandlerParameterCache [$ handlerClassName ])) {
299316 $ methodReflection = new ReflectionMethod ($ handlerClassName , 'create ' );
300317 $ this ->tagHandlerParameterCache [$ handlerClassName ] = $ methodReflection ->getParameters ();
0 commit comments