Fix #17223: Fixed detaching a behavior event when it is a Closure instance

This commit is contained in:
Nikolay Poryadin
2019-08-13 20:35:42 +03:00
committed by Alexander Makarov
parent 14a7198434
commit 491f9737fe
5 changed files with 49 additions and 2 deletions

View File

@ -4,6 +4,7 @@ Yii Framework 2 Change Log
2.0.25 under development
------------------------
- Bug #17223: Fixed detaching a behavior event when it is a Closure instance (GHopperMSK, rob006)
- Bug #15779: If directory path is passed to `FileHelper::unlink()` and directory has files it will not delete files in this directory on Windows now (alexkart)
- Bug #17473: Fixed `SimpleConditionBuilder::build()` when column is not a string (alexkart)
- Bug #17486: Fixed error when using `batch()` without `$db` parameter with MSSQL (alexkart)

View File

@ -27,6 +27,10 @@ class Behavior extends BaseObject
*/
public $owner;
/**
* @var Array Attached events handlers
*/
private $_attachedEvents = [];
/**
* Declares event handlers for the [[owner]]'s events.
@ -72,6 +76,7 @@ class Behavior extends BaseObject
{
$this->owner = $owner;
foreach ($this->events() as $event => $handler) {
$this->_attachedEvents[$event] = $handler;
$owner->on($event, is_string($handler) ? [$this, $handler] : $handler);
}
}
@ -85,9 +90,10 @@ class Behavior extends BaseObject
public function detach()
{
if ($this->owner) {
foreach ($this->events() as $event => $handler) {
foreach ($this->_attachedEvents as $event => $handler) {
$this->owner->off($event, is_string($handler) ? [$this, $handler] : $handler);
}
$this->_attachedEvents = [];
$this->owner = null;
}
}

View File

@ -445,6 +445,25 @@ class ComponentTest extends TestCase
$this->assertFalse($obj->off('test', [$this, 'handler2']), 'Trying to remove the handler that is not attached');
$this->assertTrue($obj->off('test', [$this, 'handler']), 'Trying to remove the attached handler');
}
/**
* @see https://github.com/yiisoft/yii2/issues/17223
*/
public function testEventClosureDetachesItself()
{
if (PHP_VERSION_ID < 70000) {
$this->markTestSkipped('Can not be tested on PHP < 7.0');
return;
}
$obj = require __DIR__ . '/stub/AnonymousComponentClass.php';
$obj->trigger('barEventOnce');
$this->assertEquals(1, $obj->foo);
$obj->trigger('barEventOnce');
$this->assertEquals(1, $obj->foo);
}
}
class NewComponent extends Component

View File

@ -494,7 +494,7 @@ class ModelTest extends TestCase
return;
}
$model = include 'stub/AnonymousModelClass.php';
$model = require __DIR__ . '/stub/AnonymousModelClass.php';
$this->expectException('yii\base\InvalidConfigException');
$this->expectExceptionMessage('The "formName()" method should be explicitly defined for anonymous models');

View File

@ -0,0 +1,21 @@
<?php
$obj = new class () extends \yii\base\Component
{
public $foo = 0;
};
$obj->attachBehavior('bar', (new class () extends \yii\base\Behavior
{
public function events()
{
return [
'barEventOnce' => function ($event) {
$this->owner->foo++;
$this->detach();
},
];
}
}));
return $obj;