diff options
Diffstat (limited to 'lib/public/EventDispatcher')
-rw-r--r-- | lib/public/EventDispatcher/ABroadcastedEvent.php | 53 | ||||
-rw-r--r-- | lib/public/EventDispatcher/Event.php | 68 | ||||
-rw-r--r-- | lib/public/EventDispatcher/GenericEvent.php | 173 | ||||
-rw-r--r-- | lib/public/EventDispatcher/IEventDispatcher.php | 86 | ||||
-rw-r--r-- | lib/public/EventDispatcher/IEventListener.php | 24 | ||||
-rw-r--r-- | lib/public/EventDispatcher/IWebhookCompatibleEvent.php | 24 | ||||
-rw-r--r-- | lib/public/EventDispatcher/JsonSerializer.php | 50 |
7 files changed, 478 insertions, 0 deletions
diff --git a/lib/public/EventDispatcher/ABroadcastedEvent.php b/lib/public/EventDispatcher/ABroadcastedEvent.php new file mode 100644 index 00000000000..cb3adbe46b3 --- /dev/null +++ b/lib/public/EventDispatcher/ABroadcastedEvent.php @@ -0,0 +1,53 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\EventDispatcher; + +use JsonSerializable; + +/** + * @since 18.0.0 + */ +abstract class ABroadcastedEvent extends Event implements JsonSerializable { + /** + * @since 18.0.0 + */ + private $broadcasted = false; + + /** + * Get the name of the event, as received on the client-side + * + * Uses the fully qualified event class name by default + * + * @return string + * @since 18.0.0 + */ + public function broadcastAs(): string { + return get_class($this); + } + + /** + * @return string[] + * @since 18.0.0 + */ + abstract public function getUids(): array; + + /** + * @since 18.0.0 + */ + public function setBroadcasted(): void { + $this->broadcasted = true; + } + + /** + * @since 18.0.0 + */ + public function isBroadcasted(): bool { + return $this->broadcasted; + } +} diff --git a/lib/public/EventDispatcher/Event.php b/lib/public/EventDispatcher/Event.php new file mode 100644 index 00000000000..f8d2e659f27 --- /dev/null +++ b/lib/public/EventDispatcher/Event.php @@ -0,0 +1,68 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\EventDispatcher; + +use Psr\EventDispatcher\StoppableEventInterface; + +/** + * Base event class for the event dispatcher service + * + * Typically this class isn't instantiated directly but sub classed for specific + * event types + * + * This class extended \Symfony\Contracts\EventDispatcher\Event until 21.0, since + * 22.0.0 this class directly implements the PSR StoppableEventInterface and no + * longer relies on Symfony. This transition does not come with any changes in API, + * the class has the same methods and behavior before and after this change. + * + * @since 17.0.0 + */ +class Event implements StoppableEventInterface { + /** + * @var bool + * + * @since 22.0.0 + */ + private $propagationStopped = false; + + /** + * Compatibility constructor + * + * In Nextcloud 17.0.0 this event class used a now deprecated/removed Symfony base + * class that had a constructor (with default arguments). To lower the risk of + * a breaking change (PHP won't allow parent constructor calls if there is none), + * this empty constructor's only purpose is to hopefully not break existing sub- + * classes of this class. + * + * @since 18.0.0 + */ + public function __construct() { + } + + /** + * Stops the propagation of the event to further event listeners + * + * @return void + * + * @since 22.0.0 + */ + public function stopPropagation(): void { + $this->propagationStopped = true; + } + + /** + * {@inheritDoc} + * + * @since 22.0.0 + * @see \Psr\EventDispatcher\StoppableEventInterface + */ + public function isPropagationStopped(): bool { + return $this->propagationStopped; + } +} diff --git a/lib/public/EventDispatcher/GenericEvent.php b/lib/public/EventDispatcher/GenericEvent.php new file mode 100644 index 00000000000..7e646c4d6a7 --- /dev/null +++ b/lib/public/EventDispatcher/GenericEvent.php @@ -0,0 +1,173 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\EventDispatcher; + +use ArrayAccess; +use ArrayIterator; +use InvalidArgumentException; +use IteratorAggregate; +use Traversable; +use function array_key_exists; + +/** + * Class GenericEvent + * + * convenience re-implementation of \Symfony\Component\GenericEvent against + * \OCP\EventDispatcher\Event + * + * @since 18.0.0 + * @template-implements ArrayAccess<array-key, mixed> + * @template-implements IteratorAggregate<array-key, mixed> + * @deprecated 22.0.0 use \OCP\EventDispatcher\Event + */ +class GenericEvent extends Event implements ArrayAccess, IteratorAggregate { + /** @deprecated 22.0.0 */ + protected $subject; + + /** @deprecated 22.0.0 */ + protected $arguments; + + /** + * Encapsulate an event with $subject and $args. + * + * @since 18.0.0 + * @deprecated 22.0.0 + */ + public function __construct($subject = null, array $arguments = []) { + parent::__construct(); + $this->subject = $subject; + $this->arguments = $arguments; + } + + /** + * Getter for subject property. + * + * @since 18.0.0 + * @deprecated 22.0.0 + */ + public function getSubject() { + return $this->subject; + } + + /** + * Get argument by key. + * + * @throws InvalidArgumentException if key is not found + * @since 18.0.0 + * @deprecated 22.0.0 + */ + public function getArgument(string $key) { + if ($this->hasArgument($key)) { + return $this->arguments[$key]; + } + + throw new InvalidArgumentException(sprintf('Argument "%s" not found.', $key)); + } + + /** + * Add argument to event. + * + * @since 18.0.0 + * @deprecated 22.0.0 + */ + public function setArgument($key, $value): GenericEvent { + $this->arguments[$key] = $value; + return $this; + } + + /** + * Getter for all arguments. + * + * @since 18.0.0 + * @deprecated 22.0.0 + */ + public function getArguments(): array { + return $this->arguments; + } + + /** + * Set args property. + * + * @since 18.0.0 + * @deprecated 22.0.0 + */ + public function setArguments(array $args = []): GenericEvent { + $this->arguments = $args; + return $this; + } + + /** + * Has argument. + * + * @since 18.0.0 + * @deprecated 22.0.0 + */ + public function hasArgument($key): bool { + return array_key_exists($key, $this->arguments); + } + + /** + * Retrieve an external iterator + * + * @link https://php.net/manual/en/iteratoraggregate.getiterator.php + * @since 18.0.0 + * @deprecated 22.0.0 + */ + public function getIterator(): Traversable { + return new ArrayIterator($this->arguments); + } + + /** + * Whether a offset exists + * + * @link https://php.net/manual/en/arrayaccess.offsetexists.php + * @since 18.0.0 + * @deprecated 22.0.0 + */ + public function offsetExists($offset): bool { + return $this->hasArgument($offset); + } + + /** + * Offset to retrieve + * + * @link https://php.net/manual/en/arrayaccess.offsetget.php + * @since 18.0.0 + * @deprecated 22.0.0 + * @return mixed + */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) { + return $this->arguments[$offset]; + } + + /** + * Offset to set + * + * @link https://php.net/manual/en/arrayaccess.offsetset.php + * @since 18.0.0 + * @deprecated 22.0.0 + */ + public function offsetSet($offset, $value): void { + $this->setArgument($offset, $value); + } + + /** + * Offset to unset + * + * @link https://php.net/manual/en/arrayaccess.offsetunset.php + * @since 18.0.0 + * @deprecated 22.0.0 + */ + public function offsetUnset($offset): void { + if ($this->hasArgument($offset)) { + unset($this->arguments[$offset]); + } + } +} diff --git a/lib/public/EventDispatcher/IEventDispatcher.php b/lib/public/EventDispatcher/IEventDispatcher.php new file mode 100644 index 00000000000..a1eb75580fe --- /dev/null +++ b/lib/public/EventDispatcher/IEventDispatcher.php @@ -0,0 +1,86 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\EventDispatcher; + +/** + * Event dispatcher service of Nextcloud + * + * @since 17.0.0 + */ +interface IEventDispatcher { + /** + * @template T of \OCP\EventDispatcher\Event + * @param string $eventName preferably the fully-qualified class name of the Event sub class + * @psalm-param string|class-string<T> $eventName preferably the fully-qualified class name of the Event sub class + * @param callable $listener the object that is invoked when a matching event is dispatched + * @psalm-param callable(T):void $listener + * @param int $priority The higher this value, the earlier an event + * listener will be triggered in the chain (defaults to 0) + * + * @since 17.0.0 + */ + public function addListener(string $eventName, callable $listener, int $priority = 0): void; + + /** + * @template T of \OCP\EventDispatcher\Event + * @param string $eventName preferably the fully-qualified class name of the Event sub class + * @psalm-param string|class-string<T> $eventName preferably the fully-qualified class name of the Event sub class + * @param callable $listener the object that is invoked when a matching event is dispatched + * @psalm-param callable(T):void $listener + * + * @since 19.0.0 + */ + public function removeListener(string $eventName, callable $listener): void; + + /** + * @template T of \OCP\EventDispatcher\Event + * @param string $eventName preferably the fully-qualified class name of the Event sub class to listen for + * @psalm-param string|class-string<T> $eventName preferably the fully-qualified class name of the Event sub class to listen for + * @param string $className fully qualified class name (or ::class notation) of a \OCP\EventDispatcher\IEventListener that can be built by the DI container + * @psalm-param class-string<\OCP\EventDispatcher\IEventListener<T>> $className fully qualified class name that can be built by the DI container + * @param int $priority The higher this value, the earlier an event + * listener will be triggered in the chain (defaults to 0) + * + * @since 17.0.0 + */ + public function addServiceListener(string $eventName, string $className, int $priority = 0): void; + + /** + * @template T of \OCP\EventDispatcher\Event + * @param string $eventName preferably the fully-qualified class name of the Event sub class + * + * @return bool TRUE if event has registered listeners + * @since 29.0.0 + */ + public function hasListeners(string $eventName): bool; + + /** + * @template T of \OCP\EventDispatcher\Event + * @param string $eventName + * @psalm-param string|class-string<T> $eventName + * @param Event $event + * @psalm-param T $event + * + * @since 17.0.0 + * @deprecated 21.0.0 use \OCP\EventDispatcher\IEventDispatcher::dispatchTyped + */ + public function dispatch(string $eventName, Event $event): void; + + /** + * Dispatch a typed event + * + * Only use this with subclasses of ``\OCP\EventDispatcher\Event``. + * The object's class will determine the event name. + * + * @param Event $event + * + * @since 18.0.0 + */ + public function dispatchTyped(Event $event): void; +} diff --git a/lib/public/EventDispatcher/IEventListener.php b/lib/public/EventDispatcher/IEventListener.php new file mode 100644 index 00000000000..46ed53fa7a2 --- /dev/null +++ b/lib/public/EventDispatcher/IEventListener.php @@ -0,0 +1,24 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\EventDispatcher; + +/** + * @since 17.0.0 + * + * @template T of Event + */ +interface IEventListener { + /** + * @param Event $event + * @psalm-param T $event + * + * @since 17.0.0 + */ + public function handle(Event $event): void; +} diff --git a/lib/public/EventDispatcher/IWebhookCompatibleEvent.php b/lib/public/EventDispatcher/IWebhookCompatibleEvent.php new file mode 100644 index 00000000000..b13c35c187b --- /dev/null +++ b/lib/public/EventDispatcher/IWebhookCompatibleEvent.php @@ -0,0 +1,24 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\EventDispatcher; + +/** + * Interface for events which can be listened to by webhooks + * + * @since 30.0.0 + */ +interface IWebhookCompatibleEvent { + /** + * Return data to be serialized and sent to the webhook. Will be serialized using json_encode. + * + * @since 30.0.0 + */ + public function getWebhookSerializable(): array; +} diff --git a/lib/public/EventDispatcher/JsonSerializer.php b/lib/public/EventDispatcher/JsonSerializer.php new file mode 100644 index 00000000000..d05367b746d --- /dev/null +++ b/lib/public/EventDispatcher/JsonSerializer.php @@ -0,0 +1,50 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\EventDispatcher; + +use OC\Files\Node\NonExistingFile; +use OC\Files\Node\NonExistingFolder; +use OCP\Files\FileInfo; +use OCP\IUser; + +/** + * Contains helper static methods to serialize OCP classes into arrays to pass json_encode. + * Useful for events implementing \JsonSerializable. + * + * @since 30.0.0 + */ + +final class JsonSerializer { + /** + * @since 30.0.0 + */ + public static function serializeFileInfo(FileInfo $node): array { + if ($node instanceof NonExistingFile || $node instanceof NonExistingFolder) { + return [ + 'path' => $node->getPath(), + ]; + } else { + return [ + 'id' => $node->getId(), + 'path' => $node->getPath(), + ]; + } + } + + /** + * @since 30.0.0 + */ + public static function serializeUser(IUser $user): array { + return [ + 'uid' => $user->getUID(), + 'displayName' => $user->getDisplayName(), + ]; + } +} |