1: <?php
2: /**
3: * This code is licensed under AGPLv3 license or Afterlogic Software License
4: * if commercial version of the product was purchased.
5: * For full statements of the licenses see LICENSE-AFTERLOGIC and LICENSE-AGPL3 files.
6: */
7:
8: namespace Aurora\Modules\TeamContacts;
9:
10: use Aurora\Modules\Contacts\Enums\PrimaryEmail;
11: use Aurora\Modules\Contacts\Enums\SortField;
12: use Aurora\Modules\Contacts\Enums\StorageType;
13: use Aurora\Modules\Contacts\Models\Contact;
14: use Aurora\Modules\Contacts\Module as ContactsModule;
15: use Aurora\System\Enums\UserRole;
16:
17: /**
18: * @license https://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
19: * @license https://afterlogic.com/products/common-licensing Afterlogic Software License
20: * @copyright Copyright (c) 2023, Afterlogic Corp.
21: *
22: * @package Modules
23: */
24: class Module extends \Aurora\System\Module\AbstractModule
25: {
26: protected static $iStorageOrder = 20;
27:
28: /**
29: *
30: * @return Module
31: */
32: public static function getInstance()
33: {
34: return \Aurora\System\Api::GetModule(self::GetName());
35: }
36:
37: public function init()
38: {
39: $this->subscribeEvent('Contacts::GetStorages', array($this, 'onGetStorages'));
40: $this->subscribeEvent('Core::CreateUser::after', array($this, 'onAfterCreateUser'));
41: $this->subscribeEvent('Core::DeleteUser::after', array($this, 'onAfterDeleteUser'));
42: $this->subscribeEvent('Contacts::PrepareFiltersFromStorage', array($this, 'prepareFiltersFromStorage'));
43: $this->subscribeEvent('Contacts::GetContacts::after', array($this, 'onAfterGetContacts'));
44: $this->subscribeEvent('Contacts::GetContact::after', array($this, 'onAfterGetContact'));
45: $this->subscribeEvent('Core::DoServerInitializations::after', array($this, 'onAfterDoServerInitializations'));
46: $this->subscribeEvent('Contacts::CheckAccessToObject::after', array($this, 'onAfterCheckAccessToObject'));
47: $this->subscribeEvent('Contacts::GetContactSuggestions', array($this, 'onGetContactSuggestions'));
48: }
49:
50: public function onGetStorages(&$aStorages)
51: {
52: $aStorages[self::$iStorageOrder] = StorageType::Team;
53: }
54:
55: private function createContactForUser($iUserId, $sEmail)
56: {
57: $mResult = false;
58: if (0 < $iUserId) {
59: $aContact = array(
60: 'Storage' => StorageType::Team,
61: 'PrimaryEmail' => PrimaryEmail::Business,
62: 'BusinessEmail' => $sEmail
63: );
64:
65: $aCurrentUserSession = \Aurora\Api::GetUserSession();
66: \Aurora\Api::GrantAdminPrivileges();
67: $mResult = \Aurora\Modules\Contacts\Module::Decorator()->CreateContact($aContact, $iUserId);
68: \Aurora\Api::SetUserSession($aCurrentUserSession);
69: }
70: return $mResult;
71: }
72:
73: public function onAfterCreateUser($aArgs, &$mResult)
74: {
75: $iUserId = isset($mResult) && (int) $mResult > 0 ? $mResult : 0;
76:
77: return $this->createContactForUser($iUserId, $aArgs['PublicId']);
78: }
79:
80: public function onAfterDeleteUser(&$aArgs, &$mResult)
81: {
82: if ($mResult) {
83: Contact::where([['IdUser', '=', $aArgs['UserId']], ['Storage', '=', StorageType::Team]])->delete();
84: }
85: }
86:
87: public function prepareFiltersFromStorage(&$aArgs, &$mResult)
88: {
89: if (isset($aArgs['Storage']) && ($aArgs['Storage'] === StorageType::Team || $aArgs['Storage'] === StorageType::All)) {
90: $aArgs['IsValid'] = true;
91:
92: if (!isset($mResult)) {
93: $mResult = \Aurora\Modules\Contacts\Models\Contact::query();
94: }
95:
96: $oUser = \Aurora\System\Api::getAuthenticatedUser();
97:
98: $mResult = $mResult->orWhere(function ($query) use ($oUser, $aArgs) {
99: $query = $query->where('IdTenant', $oUser->IdTenant)
100: ->where('Storage', StorageType::Team);
101: // if (isset($aArgs['SortField']) && $aArgs['SortField'] === SortField::Frequency) {
102: // $query->whereNotNull('DateModified');
103: // }
104: });
105: }
106: }
107:
108: public function onAfterGetContacts($aArgs, &$mResult)
109: {
110: if (\is_array($mResult) && \is_array($mResult['List'])) {
111: foreach ($mResult['List'] as $iIndex => $aContact) {
112: if ($aContact['Storage'] === StorageType::Team) {
113: $iUserId = \Aurora\System\Api::getAuthenticatedUserId();
114: if ($aContact['IdUser'] === $iUserId) {
115: $aContact['ItsMe'] = true;
116: } else {
117: $aContact['ReadOnly'] = true;
118: }
119: $mResult['List'][$iIndex] = $aContact;
120: }
121: }
122: }
123: }
124:
125: public function onAfterGetContact($aArgs, &$mResult)
126: {
127: $authenticatedUser = \Aurora\System\Api::getAuthenticatedUser();
128: if ($mResult && $authenticatedUser && $mResult->Storage === StorageType::Team) {
129: $allowEditTeamContactsByTenantAdmins = ContactsModule::getInstance()->getConfig('AllowEditTeamContactsByTenantAdmins', false);
130: $isUserTenantAdmin = $authenticatedUser->Role === UserRole::TenantAdmin;
131: $isContactInTenant = $mResult->IdTenant === $authenticatedUser->IdTenant;
132: if ($mResult->IdUser === $authenticatedUser->Id) {
133: $mResult->ExtendedInformation['ItsMe'] = true;
134: } elseif (!($allowEditTeamContactsByTenantAdmins && $isUserTenantAdmin && $isContactInTenant)) {
135: $mResult->ExtendedInformation['ReadOnly'] = true;
136: }
137: }
138: }
139:
140: /**
141: * Creates team contacts if they are missing within current tenant.
142: */
143: public function onAfterDoServerInitializations($aArgs, &$mResult)
144: {
145: $oUser = \Aurora\System\Api::getAuthenticatedUser();
146: if ($oUser && $oUser->Role === \Aurora\System\Enums\UserRole::TenantAdmin) {
147: $aUsers = \Aurora\Modules\Core\Module::Decorator()->GetUsers($oUser->IdTenant);
148:
149: if (is_array($aUsers) && is_array($aUsers['Items']) && count($aUsers['Items']) > 0) {
150: $aUserIds = array_map(
151: function ($aUser) {
152: if (is_array($aUser) && isset($aUser['Id'])) {
153: return $aUser['Id'];
154: }
155: },
156: $aUsers['Items']
157: );
158:
159: $aContactsIdUsers = Contact::select('IdUser')
160: ->where('Storage', StorageType::Team)
161: ->whereIn('IdUser', $aUserIds)
162: ->get()
163: ->map(function ($oUser) {
164: return $oUser->IdUser;
165: })->toArray();
166:
167: $aDiffIds = array_diff($aUserIds, $aContactsIdUsers);
168: if (is_array($aDiffIds) && count($aDiffIds) > 0) {
169: foreach ($aDiffIds as $iId) {
170: $aUsersFilter = array_filter($aUsers, function ($aUser) use ($iId) {
171: return ($aUser['Id'] === $iId);
172: });
173: if (is_array($aUsersFilter) && count($aUsersFilter) > 0) {
174: $this->createContactForUser($iId, $aUsersFilter[0]['PublicId']);
175: }
176: }
177: }
178: }
179: }
180: }
181:
182: public function onAfterCheckAccessToObject(&$aArgs, &$mResult)
183: {
184: $oUser = $aArgs['User'];
185: $oContact = isset($aArgs['Contact']) ? $aArgs['Contact'] : null;
186:
187: if ($oContact instanceof \Aurora\Modules\Contacts\Models\Contact && $oContact->Storage === StorageType::Team) {
188: if ($oUser->Role !== \Aurora\System\Enums\UserRole::SuperAdmin && $oUser->IdTenant !== $oContact->IdTenant) {
189: $mResult = false;
190: } else {
191: $mResult = true;
192: }
193: }
194: }
195:
196: public function onGetContactSuggestions(&$aArgs, &$mResult)
197: {
198: if ($aArgs['Storage'] === 'all' || $aArgs['Storage'] === StorageType::Team) {
199: $mResult[StorageType::Team] = \Aurora\Modules\Contacts\Module::Decorator()->GetContacts(
200: $aArgs['UserId'],
201: StorageType::Team,
202: 0,
203: $aArgs['Limit'],
204: $aArgs['SortField'],
205: $aArgs['SortOrder'],
206: $aArgs['Search']
207: );
208: }
209: }
210: }
211: