Skip to content

Commit 459d7bf

Browse files
committed
Merge pull request #105 from marcteyssier/2.0
Add a loop constructor arguments detector
2 parents 4e26cfc + 6099f6e commit 459d7bf

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

src/Mouf/MoufManager.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2121,4 +2121,45 @@ public function setDelegateLookupContainer(ContainerInterface $delegateLookupCon
21212121
return $this;
21222122
}
21232123

2124+
/**
2125+
* Check if there is no loop in constructor arguments
2126+
* @throws MoufException
2127+
*/
2128+
public function checkConstructorLoop() {
2129+
foreach ($this->declaredInstances as $instanceName => $descriptor) {
2130+
$this->walkConstructorLoop($instanceName, []);
2131+
}
2132+
}
2133+
2134+
/**
2135+
* This take a instance name and the path to access.
2136+
* It throw an exception if a loop was detected
2137+
*
2138+
* @param string $instanceName
2139+
* @param array $path
2140+
* @throws MoufException
2141+
*/
2142+
private function walkConstructorLoop($instanceName, array $path) {
2143+
if(isset($path[$instanceName])) {
2144+
$instances = array_keys($path);
2145+
$instances = array_slice($instances, array_search($instanceName, $instances));
2146+
throw new MoufException('A loop was detected on constructor arguments '.implode(' -> ', $instances).' -> '.$instanceName);
2147+
}
2148+
$path[$instanceName] = true;
2149+
$descriptor = $this->declaredInstances[$instanceName];
2150+
if(isset($descriptor['constructor'])) {
2151+
foreach ($descriptor['constructor'] as $constructorArg) {
2152+
if($constructorArg['parametertype'] == 'object') {
2153+
if(is_array($constructorArg['value'])) {
2154+
foreach ($constructorArg['value'] as $subInstanceName) {
2155+
$this->walkConstructorLoop($subInstanceName, $path);
2156+
}
2157+
}
2158+
else {
2159+
$this->walkConstructorLoop($constructorArg['value'], $path);
2160+
}
2161+
}
2162+
}
2163+
}
2164+
}
21242165
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
namespace Mouf\Validator;
3+
4+
use Mouf\MoufManager;
5+
use Mouf\MoufInstanceDescriptor;
6+
use Mouf\MoufException;
7+
8+
/**
9+
* Check that there is no loop on constructor parameters
10+
*/
11+
class CheckConstructorLoopValidator implements MoufStaticValidatorInterface {
12+
13+
/**
14+
* Check all constructor arguments to detect a loop
15+
*
16+
* @return MoufValidatorResult
17+
*/
18+
public static function validateClass() {
19+
$moufManager = MoufManager::getMoufManager();
20+
21+
try {
22+
$moufManager->checkConstructorLoop();
23+
return new MoufValidatorResult(MoufValidatorResult::SUCCESS, "No loop detected in constructor arguments.");
24+
}
25+
catch(MoufException $e) {
26+
return new MoufValidatorResult(MoufValidatorResult::ERROR, '<b>'.$e->getMessage().'</b><br /><br />
27+
Please check yours instances to refactor your code and change your code architecture.<br />
28+
The other ugly solution is to make a setter for one of this parameter to remove it from constructor argument');
29+
}
30+
}
31+
32+
}

0 commit comments

Comments
 (0)