Skip to content
This repository has been archived by the owner on Feb 6, 2020. It is now read-only.

Commit

Permalink
Merge branch 'hotfix/5100' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
weierophinney committed Oct 22, 2013
175 parents 2190833 + fa773c1 + 741de27 + 4d1adc8 + 8c5c414 + a7502a7 + 5058513 + 68f3d6e + f0a44c8 + 921096f + acfe55c + 35c857a + a9dd8d2 + 44d8daf + d1f9e24 + a36339c + 86f0f77 + 7ed9bcc + 754bd9a + c36f6c0 + 3ead99d + be05873 + 34e7aec + 2fcaf1c + 3f9b994 + ea3acc3 + fe35f10 + 45cc91b + aa77760 + 4959b82 + 35e2edb + 7717bd8 + 127fcbd + fc52973 + 528f461 + 8e251cd + d95b25a + 0f89697 + c941b0e + 3dc45ae + 180e140 + 67c3033 + 533cd3e + 29e7718 + 936c9be + 2d11657 + fa66751 + 2b778cc + ba628cd + ff761e1 + 5b64ee3 + 9456811 + 1c2d797 + 46b0d8f + 82264b3 + 39c88ce + cee064b + c303bed + ea247e3 + 1f87514 + 8896fc2 + 313a38d + 42848d4 + 8f5c457 + e035a2a + 544e341 + 467f8b2 + 30bb6f0 + f8cc896 + 2ee0afd + 656f0b0 + 7092cb4 + 5e1b259 + abb3ff8 + 39a873f + b6e6c92 + 83055d8 + 1dd5d72 + 9bc304a + 479b8c7 + 41fab24 + 80aee85 + 3962f1e + 6c6b004 + acb7af7 + 39aca71 + 9d55623 + c2210f2 + 50b7a31 + 327d366 + 00cfdb8 + 77c12db + 4a66170 + 4bd5c7f + 9549d20 + d3a95e2 + 5e04377 + d9da2cf + 1049b39 + 001d281 + ca437e5 + a5cb2da + e2db3b8 + 27f50b4 + 8008d6f + 4a6bead + e2df9ad + 9045ea9 + 0d18a05 + 48cc7df + dc08391 + ceec2bd + c5fc623 + 6335bda + 2a78ec6 + 56c198e + 3fab1eb + 6e15982 + 75f672f + 6efac6a + 7818a15 + fc61f7c + 0f89452 + 4ce1a3e + 8e87de6 + ff8bdbb + 30d8776 + df9df5b + 95173ad + 6f9a231 + b28d0cf + d4be36e + 335a3c1 + 6b736dd + 303ab92 + 4594eeb + 7db8ed5 + fecc97b + 5a47e2a + fdab45c + a4698e4 + 0eb7480 + d73e943 + cda61b2 + f5875b9 + 485d763 + e23536a + 7981849 + 388d6df + b3220c5 + 112a8ed + 9f981d8 + 5d39422 + 7bbeff8 + d9b366d + 2e1a8ce + 6c95b5a + 831b797 + 4a459ec + 18d7a25 + 90f630e + 0c71387 + 2f90b43 + c8deb2c + 4d3a9b8 + 0d718c7 + 7d9869d + c07a4ae + ec26a71 + cf75bf9 + d383ad4 + b1adcfd + a70e111 + 189cb73 + b655053 commit 88622d8
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 5 deletions.
14 changes: 14 additions & 0 deletions src/Exception/CircularReferenceException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\ServiceManager\Exception;

class CircularReferenceException extends RuntimeException
{
}
69 changes: 64 additions & 5 deletions src/ServiceManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,32 @@ public function setShared($name, $isShared)
return $this;
}

/**
* Resolve the alias for the given canonical name
*
* @param string $cName The canonical name to resolve
* @return string The resolved canonical name
*/
protected function resolveAlias($cName)
{
$stack = array();

while ($this->hasAlias($cName)) {
if (isset($stack[$cName])) {
throw new Exception\CircularReferenceException(sprintf(
'Circular alias reference: %s -> %s',
implode(' -> ', $stack),
$cName
));
}

$stack[$cName] = $cName;
$cName = $this->aliases[$cName];
}

return $cName;
}

/**
* Retrieve a registered instance
*
Expand All @@ -448,12 +474,9 @@ public function get($name, $usePeeringServiceManagers = true)

$isAlias = false;

if (isset($this->aliases[$cName])) {
if ($this->hasAlias($cName)) {
$isAlias = true;

do {
$cName = $this->aliases[$cName];
} while ($this->hasAlias($cName));
$cName = $this->resolveAlias($cName);
}

$instance = null;
Expand Down Expand Up @@ -731,6 +754,38 @@ public function canCreateFromAbstractFactory($cName, $rName)
return false;
}

/**
* Ensure the alias definition will not result in a circular reference
*
* @param string $alias
* @param string $nameOrAlias
* @throws Exception\CircularReferenceException
* @return self
*/
protected function checkForCircularAliasReference($alias, $nameOrAlias)
{
$aliases = $this->aliases;
$aliases[$alias] = $nameOrAlias;
$stack = array();

while (isset($aliases[$alias])) {
if (isset($stack[$alias])) {
throw new Exception\CircularReferenceException(sprintf(
'The alias definition "%s" : "%s" results in a circular reference: "%s" -> "%s"',
$alias,
$nameOrAlias,
implode('" -> "', $stack),
$alias
));
}

$stack[$alias] = $alias;
$alias = $aliases[$alias];
}

return $this;
}

/**
* @param string $alias
* @param string $nameOrAlias
Expand Down Expand Up @@ -759,6 +814,10 @@ public function setAlias($alias, $nameOrAlias)
));
}

if ($this->hasAlias($alias)) {
$this->checkForCircularAliasReference($cAlias, $nameOrAlias);
}

$this->aliases[$cAlias] = $nameOrAlias;
return $this;
}
Expand Down
42 changes: 42 additions & 0 deletions test/ServiceManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -810,4 +810,46 @@ public function testUsesMultipleDelegates()
$this->assertInstanceOf('stdClass', array_shift($fooDelegator->instances));
$this->assertSame($fooDelegator, array_shift($barDelegator->instances));
}

/**
* @covers Zend\ServiceManager\ServiceManager::resolveAlias
*/
public function testSetCircularAliasReferenceThrowsException()
{
$this->setExpectedException('Zend\ServiceManager\Exception\CircularReferenceException');

// Only affects service managers that allow overwriting definitions
$this->serviceManager->setAllowOverride(true);
$this->serviceManager->setInvokableClass('foo-service', 'stdClass');
$this->serviceManager->setAlias('foo-alias', 'foo-service');
$this->serviceManager->setAlias('bar-alias', 'foo-alias');
$this->serviceManager->setAlias('baz-alias', 'bar-alias');

// This will now cause a cyclic reference and should throw an exception
$this->serviceManager->setAlias('foo-alias', 'bar-alias');
}

/**
* @covers Zend\ServiceManager\ServiceManager::checkForCircularAliasReference
*/
public function testResolveCircularAliasReferenceThrowsException()
{
$this->setExpectedException('Zend\ServiceManager\Exception\CircularReferenceException');

// simulate an inconsistent state of $servicemanager->aliases as it could be
// caused by derived classes
$cyclicAliases = array(
'fooalias' => 'bazalias',
'baralias' => 'fooalias',
'bazalias' => 'baralias'
);

$reflection = new \ReflectionObject($this->serviceManager);
$propertyReflection = $reflection->getProperty('aliases');
$propertyReflection->setAccessible(true);
$propertyReflection->setValue($this->serviceManager, $cyclicAliases);

// This should throw the exception
$this->serviceManager->get('baz-alias');
}
}

0 comments on commit 88622d8

Please sign in to comment.