getMember(); $circle = $event->getCircle(); $initiator = $circle->getInitiator(); $initiatorHelper = new MemberHelper($initiator); if (!$circle->isConfig(Circle::CFG_FRIEND)) { $initiatorHelper->mustBeModerator(); } $member = $this->generateMember($event, $circle, $member); $event->setMembers([$member]); $event->setOutcome($this->serialize($member)); $this->eventService->memberPreparing($event); } /** * @param FederatedEvent $event * * @throws InvalidIdException * @throws RemoteNotFoundException * @throws RequestBuilderException * @throws UnknownRemoteException */ public function manage(FederatedEvent $event): void { $member = $event->getMember(); if (!$this->memberService->insertOrUpdate($member)) { return; } if ($member->getStatus() === Member::STATUS_INVITED) { $this->eventService->memberInviting($event); } else { $this->eventService->memberAdding($event); } $this->membershipService->updatePopulation($event->getCircle()); } /** * @param FederatedEvent $event * @param array $results */ public function result(FederatedEvent $event, array $results): void { $member = $event->getMember(); if ($member->getStatus() === Member::STATUS_INVITED) { $this->eventService->memberInvited($event, $results); } else { $this->eventService->memberAdded($event, $results); } } /** * @param FederatedEvent $event * @param Circle $circle * @param Member $member * * @return Member * @throws CircleNotFoundException * @throws FederatedItemBadRequestException * @throws FederatedItemException * @throws FederatedUserException * @throws FederatedUserNotFoundException * @throws InvalidIdException * @throws MembersLimitException * @throws OwnerNotFoundException * @throws RemoteInstanceException * @throws RemoteNotFoundException * @throws RemoteResourceNotFoundException * @throws SingleCircleNotFoundException * @throws UnknownRemoteException * @throws UserTypeNotFoundException * @throws RequestBuilderException */ protected function generateMember(FederatedEvent $event, Circle $circle, Member $member): Member { try { if ($member->getSingleId() !== '') { $userId = $member->getSingleId() . '@' . $member->getInstance(); $federatedUser = $this->federatedUserService->getFederatedUser($userId, Member::TYPE_SINGLE); } else { $userId = $member->getUserId() . '@' . $member->getInstance(); $federatedUser = $this->federatedUserService->getFederatedUser( $userId, $member->getUserType() ); } } catch (MemberNotFoundException $e) { throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[120], 120); } $allowedTypes = $this->configService->getAppValueInt(ConfigService::ALLOWED_TYPES); if ($federatedUser->getUserType() < Member::TYPE_APP && ($allowedTypes & $federatedUser->getUserType()) === 0) { throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[132], 132); } if ($federatedUser->getBasedOn()->isConfig(Circle::CFG_ROOT)) { throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[125], 125); } if ($circle->isConfig(Circle::CFG_LOCAL) && $federatedUser->getUserType() === Member::TYPE_CIRCLE && !$federatedUser->getBasedOn()->isConfig(Circle::CFG_LOCAL)) { throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[131], 131); } if ($member->getSingleId() === $circle->getSingleId()) { throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[128], 128); } if (!$this->configService->isLocalInstance($member->getInstance())) { if ($circle->isConfig(Circle::CFG_LOCAL)) { throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[126], 126); } if (!$circle->isConfig(Circle::CFG_FEDERATED)) { $remoteInstance = $this->remoteStreamService->getCachedRemoteInstance($member->getInstance()); if ($remoteInstance->getType() !== RemoteInstance::TYPE_GLOBALSCALE) { throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[127], 127); } } } $member->importFromIFederatedUser($federatedUser); $member->setCircleId($circle->getSingleId()); $member->setCircle($circle); $this->confirmPatron($event, $member); $this->manageMemberStatus($circle, $member); $this->circleService->confirmCircleNotFull($circle); // The idea is that adding the member during the self::verify() will help during the broadcasting // of the event to Federated RemoteInstance for their first member. $this->memberRequest->insertOrUpdate($member); try { $displayName = $this->maintenanceService->updateDisplayName($member); if ($displayName !== '') { $member->setDisplayName($displayName); } } catch (NoUserException) { // ignoreable } return $member; } /** * @param Circle $circle * @param Member $member * * @throws FederatedItemBadRequestException * @throws RequestBuilderException */ private function manageMemberStatus(Circle $circle, Member $member) { try { $knownMember = $this->memberRequest->searchMember($member); $member->setId($knownMember->getId()); if ($knownMember->getLevel() === Member::LEVEL_NONE) { switch ($knownMember->getStatus()) { case Member::STATUS_BLOCKED: if ($circle->isConfig(Circle::CFG_INVITE)) { $member->setStatus(Member::STATUS_INVITED); } return; case Member::STATUS_REQUEST: $member->setLevel(Member::LEVEL_MEMBER); $member->setStatus(Member::STATUS_MEMBER); return; case Member::STATUS_INVITED: throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[123], 123); } } throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[122], 122); } catch (MemberNotFoundException $e) { $member->setId($this->token(ManagedModel::ID_LENGTH)); if ($circle->isConfig(Circle::CFG_INVITE) && $member->getUserType() !== Member::TYPE_MAIL && $member->getUserType() !== Member::TYPE_CONTACT) { $member->setStatus(Member::STATUS_INVITED); } else { $member->setLevel(Member::LEVEL_MEMBER); $member->setStatus(Member::STATUS_MEMBER); } } } /** * @param FederatedEvent $event * @param Member $member * * @throws FederatedItemBadRequestException * @throws FederatedUserException * @throws RemoteNotFoundException * @throws RequestBuilderException * @throws UnknownRemoteException */ private function confirmPatron(FederatedEvent $event, Member $member): void { if (!$member->hasInvitedBy()) { throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[129], 129); } $patron = $member->getInvitedBy(); if ($patron->getInstance() !== $event->getSender()) { throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[130], 130); } $this->federatedUserService->confirmSingleIdUniqueness($patron); } }