isConfig(Circle::CFG_PERSONAL) || !$this->configService->getAppValueBool(ConfigService::ACTIVITY_ON_NEW_CIRCLE)) { return; } $event = $this->generateEvent('circles_as_non_member'); $event->setSubject( 'circle_create', [ 'ver' => 2, 'circle' => $this->shortenCircleData($circle), 'initiator' => ($circle->hasInitiator() ? $this->shortenMemberData($circle->getInitiator()) : null), ] ); $this->userManager->callForSeenUsers( function ($user) use ($event) { /** @var IUser $user */ $this->publishEvent($event, [$user]); } ); } /** * @param Circle $circle */ public function onCircleDestruction(Circle $circle): void { if ($circle->isConfig(Circle::CFG_PERSONAL)) { return; } $event = $this->generateEvent('circles_as_member'); $event->setSubject( 'circle_delete', [ 'ver' => 2, 'circle' => $this->shortenCircleData($circle), 'initiator' => ($circle->hasInitiator() ? $this->shortenMemberData($circle->getInitiator()) : null), ] ); $this->publishEvent( $event, $this->memberRequest->getInheritedMembers($circle->getSingleId(), false, Member::LEVEL_MEMBER) ); } /** * @param Circle $circle * @param Member $member * @param int $eventType */ public function onMemberNew( Circle $circle, Member $member, int $eventType, ): void { if ($circle->isConfig(Circle::CFG_PERSONAL)) { return; } if ($member->getLevel() === Member::LEVEL_NONE) { $this->onMemberAlmost($circle, $member, $eventType); return; } switch ($member->getUserType()) { case Member::TYPE_USER: case Member::TYPE_MAIL: case Member::TYPE_CONTACT: $this->onMemberNewAccount($circle, $member, $eventType); break; case Member::TYPE_CIRCLE: $this->onMemberNewCircle( $circle, $member, $eventType ); break; } } /** * @param Circle $circle * @param Member $member * @param int $eventType */ private function onMemberNewAccount( Circle $circle, Member $member, int $eventType, ): void { $event = $this->generateEvent('circles_as_member'); try { $event->setSubject( match ($eventType) { CircleGenericEvent::ADDED => 'member_added', CircleGenericEvent::JOINED => 'member_join' }, [ 'ver' => 2, 'circle' => $this->shortenCircleData($circle), 'initiator' => ($circle->hasInitiator() ? $this->shortenMemberData($circle->getInitiator()) : null), 'member' => $this->shortenMemberData($member), ] ); } catch (UnhandledMatchError $e) { return; } $this->publishEvent( $event, array_merge( [$member], $this->memberRequest->getInheritedMembers( $circle->getSingleId(), false, Member::LEVEL_MODERATOR ) ) ); } /** * @param Circle $circle * @param Member $member * @param int $eventType */ private function onMemberNewCircle( Circle $circle, Member $member, int $eventType = CircleGenericEvent::JOINED, ): void { $event = $this->generateEvent('circles_as_member'); try { $event->setSubject( match ($eventType) { CircleGenericEvent::ADDED => 'member_circle_added', CircleGenericEvent::JOINED => 'member_circle_joined' }, [ 'ver' => 2, 'circle' => $this->shortenCircleData($circle), 'initiator' => ($circle->hasInitiator() ? $this->shortenMemberData($circle->getInitiator()) : null), 'member' => $this->shortenMemberData($member), ] ); } catch (UnhandledMatchError $e) { return; } $this->publishEvent( $event, array_merge( $this->memberRequest->getInheritedMembers($member->getSingleId(), false, Member::LEVEL_MEMBER), $this->memberRequest->getInheritedMembers($circle->getSingleId(), false, Member::LEVEL_MODERATOR) ) ); } /** * @param Circle $circle * @param Member $member * @param int $eventType */ private function onMemberAlmost( Circle $circle, Member $member, int $eventType, ): void { if ($member->getUserType() !== Member::TYPE_USER) { return; // only if almost-member is a local account } $event = $this->generateEvent('circles_as_moderator'); try { $event->setSubject( match ($eventType) { CircleGenericEvent::INVITED => 'member_invited', CircleGenericEvent::REQUESTED => 'member_request_invitation' }, [ 'ver' => 2, 'circle' => $this->shortenCircleData($circle), 'initiator' => ($circle->hasInitiator() ? $this->shortenMemberData($circle->getInitiator()) : null), 'member' => $this->shortenMemberData($member), ] ); } catch (UnhandledMatchError $e) { return; } $this->publishEvent( $event, array_merge( [$member], $this->memberRequest->getInheritedMembers($circle->getSingleId(), false, Member::LEVEL_MODERATOR) ) ); } /** * @param Circle $circle * @param Member $member * @param int $eventType */ public function onMemberRemove(Circle $circle, Member $member, int $eventType): void { if ($circle->isConfig(Circle::CFG_PERSONAL)) { return; } switch ($member->getUserType()) { case Member::TYPE_USER: case Member::TYPE_MAIL: case Member::TYPE_CONTACT: $this->onMemberRemoveAccount($circle, $member, $eventType); break; case Member::TYPE_CIRCLE: $this->onMemberRemoveCircle( $circle, $member, $eventType ); break; } } private function onMemberRemoveAccount( Circle $circle, Member $member, int $eventType, ): void { $event = $this->generateEvent('circles_as_member'); try { $event->setSubject( match ($eventType) { CircleGenericEvent::LEFT => 'member_left', CircleGenericEvent::REMOVED => 'member_remove' }, [ 'ver' => 2, 'circle' => $this->shortenCircleData($circle), 'initiator' => ($circle->hasInitiator() ? $this->shortenMemberData($circle->getInitiator()) : null), 'member' => $this->shortenMemberData($member), ] ); } catch (UnhandledMatchError $e) { return; } $this->publishEvent( $event, array_merge( [$member], $this->memberRequest->getInheritedMembers( $circle->getSingleId(), false, Member::LEVEL_MODERATOR ) ) ); } private function onMemberRemoveCircle( Circle $circle, Member $member, int $eventType = CircleGenericEvent::JOINED, ): void { $event = $this->generateEvent('circles_as_member'); try { $event->setSubject( match ($eventType) { CircleGenericEvent::LEFT => 'member_circle_left', CircleGenericEvent::REMOVED => 'member_circle_removed' }, [ 'ver' => 2, 'circle' => $this->shortenCircleData($circle), 'initiator' => ($circle->hasInitiator() ? $this->shortenMemberData($circle->getInitiator()) : null), 'member' => $this->shortenMemberData($member), ] ); } catch (UnhandledMatchError $e) { return; } $this->publishEvent( $event, array_merge( $this->memberRequest->getInheritedMembers($member->getSingleId(), false, Member::LEVEL_MEMBER), $this->memberRequest->getInheritedMembers($circle->getSingleId(), false, Member::LEVEL_MODERATOR) ) ); } /** * @param Circle $circle * @param Member $member * @param int $level */ public function onMemberLevel( Circle $circle, Member $member, int $level, ): void { if ($member->getLevel() === Member::LEVEL_OWNER) { $this->onMemberOwner($circle, $member); return; } $event = $this->generateEvent('circles_as_moderator'); $event->setSubject( 'member_level', [ 'ver' => 2, 'circle' => $this->shortenCircleData($circle), 'initiator' => ($circle->hasInitiator() ? $this->shortenMemberData($circle->getInitiator()) : null), 'member' => $this->shortenMemberData($member), 'level' => $level ] ); $this->publishEvent( $event, array_merge( [$member], $this->memberRequest->getInheritedMembers($circle->getSingleId(), false, Member::LEVEL_MODERATOR) ) ); } /** * @param Circle $circle * @param Member $member */ public function onMemberOwner(Circle $circle, Member $member): void { $event = $this->generateEvent('circles_as_moderator'); $event->setSubject( 'member_owner', [ 'ver' => 2, 'circle' => $this->shortenCircleData($circle), 'initiator' => ($circle->hasInitiator() ? $this->shortenMemberData($circle->getInitiator()) : null), 'member' => $this->shortenMemberData($member), ] ); $this->publishEvent( $event, $this->memberRequest->getInheritedMembers($circle->getSingleId(), false, Member::LEVEL_MEMBER) ); } public function onShareNew(Circle $getCircle, FederatedEvent $federatedEvent): void { } /** * generateEvent() * Create an Activity Event with the basic settings for the app. * * @param string $type * * @return IEvent */ private function generateEvent(string $type): IEvent { $event = $this->activityManager->generateEvent(); $event->setApp(Application::APP_ID) ->setType($type); return $event; } /** * Publish the event to the users. * - if user is IUser, we get userId, * - if user is Member, we ignore non-local account and returns local userId, * - others models are ignored * - avoid duplicate activity in case of inheritance as an account can be inherited memberships throw different path * * @param IEvent $event * @param array $users */ private function publishEvent(IEvent $event, array $users): void { $knownSingleIds = []; foreach ($users as $user) { if ($user instanceof IUser) { $userId = $user->getUID(); } elseif ($user instanceof IFederatedUser) { $singleId = $user->getSingleId(); if ($user->getUserType() !== Member::TYPE_USER || in_array($singleId, $knownSingleIds)) { continue; // we ignore non-local account and already known single ids } $knownSingleIds[] = $singleId; $userId = $user->getUserId(); } else { continue; } $event->setAffectedUser($userId); $this->activityManager->publish($event); } } private function shortenCircleData(Circle $circle): array { return [ 'singleId' => $circle->getSingleId(), 'name' => $circle->getName(), 'config' => $circle->getConfig(), 'url' => $circle->getUrl(), ]; } private function shortenMemberData(Member $member): array { return [ 'userId' => $member->getUserId(), 'displayName' => $member->getDisplayName(), 'type' => $member->getUserType(), 'level' => $member->getLevel(), 'status' => $member->getStatus(), ]; } }