diff --git a/application/Espo/ORM/EventDispatcher.php b/application/Espo/ORM/EventDispatcher.php index de7b5a1f7f..f3a73be269 100644 --- a/application/Espo/ORM/EventDispatcher.php +++ b/application/Espo/ORM/EventDispatcher.php @@ -53,6 +53,23 @@ class EventDispatcher $this->data[self::METADATA_UPDATE][] = $callback; } + /** + * @internal + * @since 8.4.0 + */ + public function unsubscribeFromMetadataUpdate(Closure $closure): void + { + $list = &$this->data[self::METADATA_UPDATE]; + + $index = array_search($closure, $list); + + if ($index !== false) { + unset($list[$index]); + + $list = array_values($list); + } + } + public function dispatchMetadataUpdate(): void { foreach ($this->data[self::METADATA_UPDATE] as $callback) { diff --git a/tests/unit/Espo/ORM/EntityDispatcherTest.php b/tests/unit/Espo/ORM/EntityDispatcherTest.php new file mode 100644 index 0000000000..d910487f07 --- /dev/null +++ b/tests/unit/Espo/ORM/EntityDispatcherTest.php @@ -0,0 +1,77 @@ +. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. + ************************************************************************/ + +namespace tests\unit\Espo\ORM; + +use Espo\ORM\EventDispatcher; +use PHPUnit\Framework\TestCase; + +class EntityDispatcherTest extends TestCase +{ + public function testSubscribe(): void + { + $eventDispatcher = new EventDispatcher(); + + $dispatched = false; + + $eventDispatcher->subscribeToMetadataUpdate(function () use (&$dispatched) { + $dispatched = true; + }); + + $eventDispatcher->dispatchMetadataUpdate(); + + $this->assertTrue($dispatched); + } + + public function testUnsubscribe(): void + { + $eventDispatcher = new EventDispatcher(); + + $dispatched1 = false; + + $closure1 = function () use (&$dispatched1) { + $dispatched1 = true; + }; + + $dispatched2 = false; + + $closure2 = function () use (&$dispatched2) { + $dispatched2 = true; + }; + + $eventDispatcher->subscribeToMetadataUpdate($closure1); + $eventDispatcher->subscribeToMetadataUpdate($closure2); + $eventDispatcher->unsubscribeFromMetadataUpdate($closure1); + + $eventDispatcher->dispatchMetadataUpdate(); + + $this->assertFalse($dispatched1); + $this->assertTrue($dispatched2); + } +}