Skip to content

Commit

Permalink
Fix behavior method alias management.
Browse files Browse the repository at this point in the history
When behaviors explicitly defined their finders/methods aliasing and
disabling methods no longer worked. This was due to the underlying
config() method always merging and the values - not the keys - being the
key feature of the data. This new code now uses the values to determine
what the correct config data should be. This results in additional calls
to config when methods are customized, but the code behaves as most
people would expect now.

Refs #4414
  • Loading branch information
markstory committed Aug 28, 2014
1 parent 0fa5a84 commit 0cb4ee6
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 3 deletions.
40 changes: 40 additions & 0 deletions src/ORM/Behavior.php
Expand Up @@ -125,9 +125,49 @@ class Behavior implements EventListener {
* @param array $config The config for this behavior.
*/
public function __construct(Table $table, array $config = []) {
$config = $this->_resolveMethodAliases(
'implementedFinders',
$this->_defaultConfig,
$config
);
$config = $this->_resolveMethodAliases(
'implementedMethods',
$this->_defaultConfig,
$config
);
$this->config($config);
}

/**
* Removes aliased methods that would otherwise be duplicated by userland configuration.
*
* @param string $key The key to filter.
* @param array $defaults The default method mappings.
* @param array $config The customized method mappings.
* @return array A de-duped list of config data.
*/
protected function _resolveMethodAliases($key, $defaults, $config) {
if (!isset($defaults[$key], $config[$key])) {
return $config;
}
if (isset($config[$key]) && $config[$key] === []) {
$this->config($key, [], false);
unset($config[$key]);
return $config;
}

$indexed = array_flip($defaults[$key]);
$indexedCustom = array_flip($config[$key]);
foreach ($indexed as $method => $alias) {
if (!isset($indexedCustom[$method])) {
$indexedCustom[$method] = $alias;
}
}
$this->config($key, array_flip($indexedCustom), false);
unset($config[$key]);
return $config;
}

/**
* verifyConfig
*
Expand Down
45 changes: 45 additions & 0 deletions tests/TestCase/ORM/BehaviorRegistryTest.php
Expand Up @@ -128,6 +128,51 @@ public function testLoadDuplicateMethodError() {
$this->Behaviors->load('Duplicate');
}

/**
* Test load() duplicate method aliasing
*
* @return void
*/
public function testLoadDuplicateMethodAliasing() {
$this->Behaviors->load('Tree');
$this->Behaviors->load('Duplicate', [
'implementedFinders' => [
'renamed' => 'findChildren',
],
'implementedMethods' => [
'renamed' => 'slugify',
]
]);
$this->assertTrue($this->Behaviors->hasMethod('renamed'));
}

/**
* Test load() duplicate finder error
*
* @expectedException \Cake\Error\Exception
* @expectedExceptionMessage TestApp\Model\Behavior\DuplicateBehavior contains duplicate finder "children"
* @return void
*/
public function testLoadDuplicateFinderError() {
$this->Behaviors->load('Tree');
$this->Behaviors->load('Duplicate');
}

/**
* Test load() duplicate finder aliasing
*
* @return void
*/
public function testLoadDuplicateFinderAliasing() {
$this->Behaviors->load('Tree');
$this->Behaviors->load('Duplicate', [
'implementedFinders' => [
'renamed' => 'findChildren',
]
]);
$this->assertTrue($this->Behaviors->hasFinder('renamed'));
}

/**
* test hasMethod()
*
Expand Down
13 changes: 10 additions & 3 deletions tests/TestCase/ORM/BehaviorTest.php
Expand Up @@ -34,6 +34,14 @@ public function beforeFind() {
* Test Stub.
*/
class Test2Behavior extends Behavior {
protected $_defaultConfig = [
'implementedFinders' => [
'foo' => 'findFoo',
],
'implementedMethods' => [
'doSomething' => 'doSomething',
]
];

/**
* Test for event bindings.
Expand Down Expand Up @@ -239,7 +247,7 @@ public function testImplementedFinders() {
$table = $this->getMock('Cake\ORM\Table');
$behavior = new Test2Behavior($table);
$expected = [
'foo' => 'findFoo'
'foo' => 'findFoo',
];
$this->assertEquals($expected, $behavior->implementedFinders());
}
Expand Down Expand Up @@ -272,8 +280,7 @@ public function testImplementedFindersDisabled() {
$behavior = new Test2Behavior($table, [
'implementedFinders' => []
]);
$expected = [];
$this->assertEquals($expected, $behavior->implementedFinders());
$this->assertEquals([], $behavior->implementedFinders());
}

/**
Expand Down
11 changes: 11 additions & 0 deletions tests/test_app/TestApp/Model/Behavior/DuplicateBehavior.php
Expand Up @@ -20,6 +20,17 @@
* Test class for trigging duplicate method errors.
*/
class DuplicateBehavior extends Behavior {
protected $_defaultConfig = [
'implementedFinders' => [
'children' => 'findChildren',
],
'implementedMethods' => [
'slugify' => 'slugify',
]
];

public function findChildren() {
}

public function slugify() {
}
Expand Down

0 comments on commit 0cb4ee6

Please sign in to comment.