FIX: ViewableData::setFailover() didn't remove cached methods

This commit is contained in:
Loz Calver 2016-06-03 17:04:22 +01:00
parent 2ea07f9c84
commit 429ce55756
No known key found for this signature in database
GPG Key ID: F91FFC2D7E0CAEDB
3 changed files with 52 additions and 0 deletions

View File

@ -845,6 +845,48 @@ abstract class Object {
}
}
/**
* Add all the methods from an object property (which is an {@link Extension}) to this object.
*
* @param string $property the property name
* @param string|int $index an index to use if the property is an array
*/
protected function removeMethodsFrom($property, $index = null) {
$extension = ($index !== null) ? $this->{$property}[$index] : $this->$property;
if(!$extension) {
throw new InvalidArgumentException (
"Object->removeMethodsFrom(): could not remove methods from {$this->class}->{$property}[$index]"
);
}
if(method_exists($extension, 'allMethodNames')) {
if ($extension instanceof Extension) $extension->setOwner($this);
$methods = $extension->allMethodNames(true);
if ($extension instanceof Extension) $extension->clearOwner();
} else {
if(!isset(self::$built_in_methods[$extension->class])) {
self::$built_in_methods[$extension->class] = array_map('strtolower', get_class_methods($extension));
}
$methods = self::$built_in_methods[$extension->class];
}
if($methods) {
foreach ($methods as $method) {
$methodInfo = self::$extra_methods[$this->class][$method];
if ($methodInfo['property'] === $property && $methodInfo['index'] === $index) {
unset(self::$extra_methods[$this->class][$method]);
}
}
if (empty(self::$extra_methods[$this->class])) {
unset(self::$extra_methods[$this->class]);
}
}
}
/**
* Add a wrapper method - a method which points to another method with a different name. For example, Thumbnail(x)
* can be wrapped to generateThumbnail(x)

View File

@ -187,6 +187,11 @@ class ViewableDataTest extends SapphireTest {
// Ensure that defined methods detected from the failover aren't cached when setting a new failover
$container->setFailover(new ViewableDataTest_Failover);
$this->assertTrue($container->hasMethod('testMethod'));
// Test the reverse - that defined methods previously detected in a failover are removed if they no longer exist
$container->setFailover($failover);
$this->assertSame($failover, $container->getFailover(), 'getFailover() returned a different object');
$this->assertFalse($container->hasMethod('testMethod'), 'testMethod() incorrectly reported as existing');
}
}

View File

@ -134,6 +134,11 @@ class ViewableData extends Object implements IteratorAggregate {
* @param ViewableData $failover
*/
public function setFailover(ViewableData $failover) {
// Ensure cached methods from previous failover are removed
if ($this->failover) {
$this->removeMethodsFrom('failover');
}
$this->failover = $failover;
$this->defineMethods();
}