diff --git a/src/Database/Database.php b/src/Database/Database.php index 4b39ef231..8f0a0746f 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -259,7 +259,14 @@ class Database '*' => [], ]; - protected bool $silentEvents = false; + /** + * Array in which the keys are the names of databse listeners that + * should be skipped when dispatching events. null $silentListeners + * will skip all listeners. + * + * @var ?array + */ + protected ?array $silentListeners = []; protected ?\DateTime $timestamp = null; @@ -372,31 +379,41 @@ function (?string $value) { * @param callable $callback * @return self */ - public function on(string $event, callable $callback): self + public function on(string $event, string $name, callable $callback): self { if (!isset($this->listeners[$event])) { $this->listeners[$event] = []; } - $this->listeners[$event][] = $callback; + $this->listeners[$event][$name] = $callback; return $this; } /** - * Silent event generation for all the calls inside the callback + * Silent event generation for calls inside the callback * * @template T * @param callable(): T $callback + * @param array|null $listeners List of listeners to silence; if null, all listeners will be silenced * @return T */ - public function silent(callable $callback): mixed + public function silent(callable $callback, array $listeners = null): mixed { - $previous = $this->silentEvents; - $this->silentEvents = true; + $previous = $this->silentListeners; + + if (is_null($listeners)) { + $this->silentListeners = null; + } else { + $silentListeners = []; + foreach ($listeners as $listener) { + $silentListeners[$listener] = true; + } + $this->silentListeners = $silentListeners; + } try { return $callback(); } finally { - $this->silentEvents = $previous; + $this->silentListeners = $previous; } } @@ -428,14 +445,20 @@ public function skipRelationships(callable $callback): mixed */ protected function trigger(string $event, mixed $args = null): void { - if ($this->silentEvents) { + if (\is_null($this->silentListeners)) { return; } - foreach ($this->listeners[self::EVENT_ALL] as $callback) { + foreach ($this->listeners[self::EVENT_ALL] as $name => $callback) { + if (isset($this->silentListeners[$name])) { + continue; + } call_user_func($callback, $event, $args); } - foreach (($this->listeners[$event] ?? []) as $callback) { + foreach (($this->listeners[$event] ?? []) as $name => $callback) { + if (isset($this->silentListeners[$name])) { + continue; + } call_user_func($callback, $event, $args); } } diff --git a/tests/Database/Base.php b/tests/Database/Base.php index dda3bd57a..c0c141b9a 100644 --- a/tests/Database/Base.php +++ b/tests/Database/Base.php @@ -11225,7 +11225,7 @@ public function testEvents(): void Database::EVENT_DATABASE_DELETE, ]; - $database->on(Database::EVENT_ALL, function ($event, $data) use (&$events) { + $database->on(Database::EVENT_ALL, 'test', function ($event, $data) use (&$events) { $shifted = array_shift($events); $this->assertEquals($shifted, $event); @@ -11261,14 +11261,23 @@ public function testEvents(): void ], ])); - $database->updateDocument($collectionId, 'doc1', $document->setAttribute('attr1', 15)); - $database->getDocument($collectionId, 'doc1'); - $database->find($collectionId); - $database->findOne($collectionId); - $database->count($collectionId); - $database->sum($collectionId, 'attr1'); - $database->increaseDocumentAttribute($collectionId, $document->getId(), 'attr1'); - $database->decreaseDocumentAttribute($collectionId, $document->getId(), 'attr1'); + $executed = false; + $database->on(Database::EVENT_ALL, 'should-not-execute', function ($event, $data) use (&$executed) { + $executed = true; + }); + + $database->silent(function () use ($database, $collectionId, $document) { + $database->updateDocument($collectionId, 'doc1', $document->setAttribute('attr1', 15)); + $database->getDocument($collectionId, 'doc1'); + $database->find($collectionId); + $database->findOne($collectionId); + $database->count($collectionId); + $database->sum($collectionId, 'attr1'); + $database->increaseDocumentAttribute($collectionId, $document->getId(), 'attr1'); + $database->decreaseDocumentAttribute($collectionId, $document->getId(), 'attr1'); + }, ['should-not-execute']); + + $this->assertFalse($executed); $database->deleteIndex($collectionId, $indexId1); $database->deleteDocument($collectionId, 'doc1');