Skip to content

Commit 0527f28

Browse files
committed
Refactor - Simplify interceptor creation and enhance return value decoration in StopwatchDecorator
1 parent 635f3bf commit 0527f28

File tree

1 file changed

+108
-91
lines changed

1 file changed

+108
-91
lines changed

src/Decorator/StopwatchDecorator.php

Lines changed: 108 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ public function __construct(
3939
* Decorates a service with stopwatch timing interceptors.
4040
*
4141
* @template T of object
42+
*
4243
* @param T $service
44+
*
4345
* @return T
4446
*/
4547
public function decorate(object $service): object
@@ -50,13 +52,14 @@ public function decorate(object $service): object
5052
return $service;
5153
}
5254

53-
$className = $class->getName();
54-
[$prefixInterceptors, $suffixInterceptors] = $this->getPrefixAndSuffixInterceptors($class, $className);
55+
[$prefixInterceptors, $suffixInterceptors] = $this->getPrefixAndSuffixInterceptors($class);
5556

5657
/** @var T */
5758
return $this->createProxyWithInterceptors($service, $prefixInterceptors, $suffixInterceptors);
5859
}
5960

61+
// Validation methods
62+
6063
private function shouldSkipDecoration(ReflectionClass $class): bool
6164
{
6265
return $class->getFileName() === false
@@ -71,6 +74,71 @@ private function isExcludedClassName(string $className): bool
7174
|| str_contains($className, 'StopwatchProxy_');
7275
}
7376

77+
// Interceptor creation methods
78+
79+
/**
80+
* @return array{0: array<string, Closure>, 1: array<string, Closure>}
81+
*/
82+
private function getPrefixAndSuffixInterceptors(ReflectionClass $class): array
83+
{
84+
$className = $class->getName();
85+
86+
$prefixInterceptors = [];
87+
$suffixInterceptors = [];
88+
89+
$methods = $this->getProxyableMethods($class);
90+
91+
$stopwatch = $this->stopwatch;
92+
$decorator = $this;
93+
94+
foreach ($methods as $method) {
95+
$methodName = $method->getName();
96+
$eventName = "{$class->getShortName()}->{$methodName}";
97+
98+
$prefixInterceptors[$methodName] = $this->createPrefixInterceptor($eventName, $className, $stopwatch);
99+
$suffixInterceptors[$methodName] = $this->createSuffixInterceptor($eventName, $stopwatch, $decorator);
100+
}
101+
102+
return [$prefixInterceptors, $suffixInterceptors];
103+
}
104+
105+
private function createPrefixInterceptor(string $eventName, string $className, Stopwatch $stopwatch): Closure
106+
{
107+
return static function () use ($eventName, $className, $stopwatch): void {
108+
$stopwatch->start($eventName, $className);
109+
};
110+
}
111+
112+
private function createSuffixInterceptor(
113+
string $eventName,
114+
Stopwatch $stopwatch,
115+
self $decorator,
116+
): Closure {
117+
return static function (
118+
mixed $proxy,
119+
mixed $instance,
120+
mixed $method,
121+
mixed $params,
122+
mixed &$returnValue,
123+
) use (
124+
$eventName,
125+
$stopwatch,
126+
$decorator,
127+
): void {
128+
$stopwatch->stop($eventName);
129+
$decorator->decorateReturnValue($returnValue);
130+
};
131+
}
132+
133+
private function decorateReturnValue(mixed &$returnValue): void
134+
{
135+
if (is_object($returnValue) && !$returnValue instanceof EntityInterface) {
136+
$returnValue = $this->decorate($returnValue);
137+
}
138+
}
139+
140+
// Proxy creation methods
141+
74142
/**
75143
* @param array<string, Closure> $prefixInterceptors
76144
* @param array<string, Closure> $suffixInterceptors
@@ -129,6 +197,8 @@ private function createProxy(
129197
}
130198
}
131199

200+
// Proxy class generation methods
201+
132202
private function generateProxyClass(
133203
string $proxyClassName,
134204
string $originalClassName,
@@ -182,6 +252,39 @@ private function generateProxyMethod(ReflectionMethod $method): string
182252
return $code;
183253
}
184254

255+
private function generateMethodBody(string $methodName, string $argsList, bool $isVoid): string
256+
{
257+
return $isVoid
258+
? $this->generateVoidMethodBody($methodName, $argsList)
259+
: $this->generateNonVoidMethodBody($methodName, $argsList);
260+
}
261+
262+
private function generateVoidMethodBody(string $methodName, string $argsList): string
263+
{
264+
$code = " \$this->wrappedInstance->{$methodName}({$argsList});\n";
265+
$code .= " if (isset(\$this->suffixInterceptors['{$methodName}'])) {\n";
266+
$code .= " \$returnValue = null;\n";
267+
$code .= " (\$this->suffixInterceptors['{$methodName}'])";
268+
$code .= "(null, null, null, func_get_args(), \$returnValue);\n";
269+
$code .= " }\n";
270+
271+
return $code;
272+
}
273+
274+
private function generateNonVoidMethodBody(string $methodName, string $argsList): string
275+
{
276+
$code = " \$returnValue = \$this->wrappedInstance->{$methodName}({$argsList});\n";
277+
$code .= " if (isset(\$this->suffixInterceptors['{$methodName}'])) {\n";
278+
$code .= " (\$this->suffixInterceptors['{$methodName}'])";
279+
$code .= "(null, null, null, func_get_args(), \$returnValue);\n";
280+
$code .= " }\n";
281+
$code .= " return \$returnValue;\n";
282+
283+
return $code;
284+
}
285+
286+
// Method parameter handling
287+
185288
/**
186289
* @return array{0: string, 1: string}
187290
*/
@@ -247,6 +350,8 @@ private function getDefaultValueString(\ReflectionParameter $param): string
247350
return $result;
248351
}
249352

353+
// Return type handling
354+
250355
/**
251356
* @return array{0: string, 1: bool}
252357
*/
@@ -268,36 +373,7 @@ private function getMethodReturnType(ReflectionMethod $method): array
268373
return [$returnType, $isVoid];
269374
}
270375

271-
private function generateMethodBody(string $methodName, string $argsList, bool $isVoid): string
272-
{
273-
return $isVoid
274-
? $this->generateVoidMethodBody($methodName, $argsList)
275-
: $this->generateNonVoidMethodBody($methodName, $argsList);
276-
}
277-
278-
private function generateVoidMethodBody(string $methodName, string $argsList): string
279-
{
280-
$code = " \$this->wrappedInstance->{$methodName}({$argsList});\n";
281-
$code .= " if (isset(\$this->suffixInterceptors['{$methodName}'])) {\n";
282-
$code .= " \$returnValue = null;\n";
283-
$code .= " (\$this->suffixInterceptors['{$methodName}'])";
284-
$code .= "(null, null, null, func_get_args(), \$returnValue);\n";
285-
$code .= " }\n";
286-
287-
return $code;
288-
}
289-
290-
private function generateNonVoidMethodBody(string $methodName, string $argsList): string
291-
{
292-
$code = " \$returnValue = \$this->wrappedInstance->{$methodName}({$argsList});\n";
293-
$code .= " if (isset(\$this->suffixInterceptors['{$methodName}'])) {\n";
294-
$code .= " (\$this->suffixInterceptors['{$methodName}'])";
295-
$code .= "(null, null, null, func_get_args(), \$returnValue);\n";
296-
$code .= " }\n";
297-
$code .= " return \$returnValue;\n";
298-
299-
return $code;
300-
}
376+
// Method filtering
301377

302378
/**
303379
* @return array<ReflectionMethod>
@@ -317,63 +393,4 @@ private function isProxyableMethod(ReflectionMethod $method): bool
317393
&& !$method->isConstructor()
318394
&& !$method->isDestructor();
319395
}
320-
321-
/**
322-
* @return array{0: array<string, Closure>, 1: array<string, Closure>}
323-
*/
324-
private function getPrefixAndSuffixInterceptors(ReflectionClass $class, string $className): array
325-
{
326-
$prefixInterceptors = [];
327-
$suffixInterceptors = [];
328-
329-
$methods = $this->getProxyableMethods($class);
330-
331-
$stopwatch = $this->stopwatch;
332-
$decorator = $this;
333-
334-
foreach ($methods as $method) {
335-
$methodName = $method->getName();
336-
$eventName = "{$class->getShortName()}->{$methodName}";
337-
338-
$prefixInterceptors[$methodName] = $this->createPrefixInterceptor($eventName, $className, $stopwatch);
339-
$suffixInterceptors[$methodName] = $this->createSuffixInterceptor($eventName, $stopwatch, $decorator);
340-
}
341-
342-
return [$prefixInterceptors, $suffixInterceptors];
343-
}
344-
345-
private function createPrefixInterceptor(string $eventName, string $className, Stopwatch $stopwatch): Closure
346-
{
347-
return static function () use ($eventName, $className, $stopwatch): void {
348-
$stopwatch->start($eventName, $className);
349-
};
350-
}
351-
352-
private function createSuffixInterceptor(
353-
string $eventName,
354-
Stopwatch $stopwatch,
355-
self $decorator,
356-
): Closure {
357-
return static function (
358-
mixed $p,
359-
mixed $i,
360-
mixed $m,
361-
mixed $params,
362-
mixed &$returnValue,
363-
) use (
364-
$eventName,
365-
$stopwatch,
366-
$decorator,
367-
): void {
368-
$stopwatch->stop($eventName);
369-
$decorator->decorateReturnValue($returnValue);
370-
};
371-
}
372-
373-
private function decorateReturnValue(mixed &$returnValue): void
374-
{
375-
if (is_object($returnValue) && !$returnValue instanceof EntityInterface) {
376-
$returnValue = $this->decorate($returnValue);
377-
}
378-
}
379396
}

0 commit comments

Comments
 (0)