group; } /** * Create a new GroupMailingList. * * @param string $title * @param ?string $description * @param string $email * @param string|null $sid * * @return \Civi\Mailinglistsync\GroupMailingList * @throws \Civi\Mailinglistsync\Exceptions\MailinglistException */ public static function createGroup( string $title, string $email, string $description = NULL, string $sid = NULL ): self { try { $request = \Civi\Api4\Group::create() ->addValue('title', $title) ->addValue(static::CUSTOM_GROUP_NAME . '.E_mail_address', $email) ->addValue(static::CUSTOM_GROUP_NAME . '.Enable_mailing_list', 1) ->addValue('is_active', 1); // Add the description if it's not empty if (!empty($description)) { $request->addValue('description', $description); } // If the group is an AD group, add the AD SID if (!empty($sid)) { $request->addValue(static::CUSTOM_GROUP_NAME . '.Active_Directory_SID', $sid); } $group = $request->execute()->first(); return empty($sid) ? new self($group): new ADGroupMailingList($group); } catch (\Exception $e) { throw new MailinglistException( "Could not create group\n$e", MailinglistException::ERROR_CODE_GROUP_CREATION_FAILED ); } } /** * Set the related group. * * @param array $value */ protected function setEntity(array $value): void { $this->group = $value; } /** * Check if the group is an AD mailing list. * @return bool */ public function isADGroup(): bool { return !empty($this->group[static::CUSTOM_GROUP_NAME . '.Active_Directory_SID']); } /** * Get a list of recipients indexed by email address. * * @return array List of recipients (MailListRecipient) * @throws \Civi\Mailinglistsync\Exceptions\MailinglistException */ public function getRecipients(): array { try { $recipientData = Contact::get() ->addSelect('id', 'first_name', 'last_name', 'email.email', 'Active_Directory.SID') ->addJoin('Email AS email', 'LEFT', ['id', '=', 'email.contact_id']) ->addJoin('GroupContact AS group_contact', 'INNER', ['id', '=', 'group_contact.contact_id'], ['group_contact.group_id', '=', $this->group['id']], ['group_contact.status', '=', '"Added"'], ) ->addGroupBy('id') ->execute() ->getArrayCopy(); } catch (\Exception $e) { throw new MailinglistException( "Could not get recipients for group with id '{$this->group['id']}'\n$e", MailinglistException::ERROR_CODE_GET_RECIPIENTS_FAILED ); } $recipients = []; foreach ($recipientData as $recipient) { try { $recipients[$recipient['email.email']] = new MailingListRecipient( sid: $recipient['Active_Directory.SID'], contact_id: $recipient['id'], first_name: $recipient['first_name'], last_name: $recipient['last_name'], email: $recipient['email.email'], ); } catch (\Exception $e) { throw new MailinglistException( "Could not create recipient object for contact with id '{$recipient['id']}': {$e->getMessage()}", MailinglistException::ERROR_CODE_GET_RECIPIENTS_FAILED ); } } return $recipients; } /** * Update the title of the group. * * @param string $title * * @return void * @throws \Civi\Mailinglistsync\Exceptions\MailinglistException */ public function updateGroupTitle(string $title): void { $this->update(['title' => $title]); } /** * Update the description of the group. * * @return string */ public function getGroupDescription(): string { return $this->group['description'] ?? ''; } /** * Update the description of the group. * * @param string $description * * @return void */ public function updateGroupDescription(string $description): void { $this->update(['description' => $description]); } /** * Add a contact to this mailing lists related group. * * @param int $contactId * * @return void * @throws \Civi\Mailinglistsync\Exceptions\MailinglistException */ protected function addContactToGroup(int $contactId): void { try { \Civi\Api4\GroupContact::create() ->addValue('contact_id', $contactId) ->addValue('group_id', $this->group['id']) ->execute(); } catch (\Exception $e) { if ($e->getMessage() === 'DB Error: already exists') { $this->reAddContactToGroup($contactId); } else { throw new MailinglistException( "Could not add contact with id '$contactId' to group with id '{$this->group['id']}': $e", MailinglistException::ERROR_CODE_ADD_CONTACT_TO_GROUP_FAILED ); } } } /** * Remove a contact from this mailing lists related group. * * @param int $contactId * * @return void * @throws \Civi\Mailinglistsync\Exceptions\MailinglistException */ protected function removeContactFromGroup(int $contactId): void { try { \Civi\Api4\GroupContact::update() ->addWhere('contact_id', '=', $contactId) ->addWhere('group_id', '=', $this->group['id']) ->addValue('status', 'Removed') ->execute(); } catch (\Exception $e) { throw new MailinglistException( "Could not remove contact with id '$contactId' from group with id '{$this->group['id']}'\n$e", MailinglistException::ERROR_CODE_REMOVE_CONTACT_FROM_GROUP_FAILED ); } } /** * If a group_contact entry already exists, but is marked as removed, * re-add the contact to the group. * * @param int $contactId * * @return void * @throws \Civi\Mailinglistsync\Exceptions\MailinglistException */ private function reAddContactToGroup(int $contactId): void { try { \Civi\Api4\GroupContact::update() ->addWhere('contact_id', '=', $contactId) ->addWhere('group_id', '=', $this->group['id']) ->addValue('status', 'Added') ->execute(); } catch (\Exception $e) { throw new MailinglistException( "Could not re-add contact with id '$contactId' to group with id '{$this->group['id']}': $e", MailinglistException::ERROR_CODE_ADD_CONTACT_TO_GROUP_FAILED ); } } }