1 | <?php |
||||
2 | |||||
3 | /** |
||||
4 | * DelegatesModule |
||||
5 | * Class can be used to get delegate information of a particular user. |
||||
6 | * The delegate information can be created/update using this class as well. |
||||
7 | */ |
||||
8 | class DelegatesModule extends Module { |
||||
9 | /** |
||||
10 | * @var array contains entryid's of all default folders |
||||
11 | */ |
||||
12 | private $defaultFolders; |
||||
13 | |||||
14 | /** |
||||
15 | * @var array contains delegate properties from special message (LocalFreebusy) |
||||
16 | */ |
||||
17 | private $delegateProps; |
||||
18 | |||||
19 | /** |
||||
20 | * @var resource of LocalFreeBusy Message. This contains for delegates. |
||||
21 | */ |
||||
22 | private $localFreeBusyMessage; |
||||
23 | |||||
24 | /** |
||||
25 | * @var resource of FreeBusy Folder in IPM_SUBTREE. This permissions for freebusy folder used in calendar. |
||||
26 | */ |
||||
27 | private $freeBusyFolder; |
||||
28 | |||||
29 | /** |
||||
30 | * @var resource of default store of the current user |
||||
31 | */ |
||||
32 | private $defaultStore; |
||||
33 | |||||
34 | /** |
||||
35 | * Constructor. |
||||
36 | * |
||||
37 | * @param int $id unique id |
||||
38 | * @param array $data list of all actions |
||||
39 | */ |
||||
40 | public function __construct($id, $data) { |
||||
41 | $this->defaultFolders = []; |
||||
42 | $this->delegateProps = []; |
||||
43 | $this->localFreeBusyMessage = false; |
||||
0 ignored issues
–
show
|
|||||
44 | $this->freeBusyFolder = false; |
||||
0 ignored issues
–
show
It seems like
false of type false is incompatible with the declared type resource of property $freeBusyFolder .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||||
45 | $this->defaultStore = false; |
||||
0 ignored issues
–
show
It seems like
false of type false is incompatible with the declared type resource of property $defaultStore .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||||
46 | |||||
47 | parent::__construct($id, $data); |
||||
48 | } |
||||
49 | |||||
50 | /** |
||||
51 | * Executes all the actions in the $data variable. |
||||
52 | */ |
||||
53 | #[Override] |
||||
54 | public function execute() { |
||||
55 | foreach ($this->data as $actionType => $action) { |
||||
56 | if (isset($actionType)) { |
||||
57 | try { |
||||
58 | match ($actionType) { |
||||
59 | 'list' => $this->delegateList(), |
||||
0 ignored issues
–
show
Are you sure the usage of
$this->delegateList() targeting DelegatesModule::delegateList() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||||
60 | 'open' => $this->openDelegate($action), |
||||
0 ignored issues
–
show
Are you sure the usage of
$this->openDelegate($action) targeting DelegatesModule::openDelegate() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||||
61 | 'save' => $this->saveDelegates($action), |
||||
0 ignored issues
–
show
Are you sure the usage of
$this->saveDelegates($action) targeting DelegatesModule::saveDelegates() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||||
62 | 'delete' => $this->deleteDelegates($action), |
||||
0 ignored issues
–
show
Are you sure the usage of
$this->deleteDelegates($action) targeting DelegatesModule::deleteDelegates() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||||
63 | default => $this->handleUnknownActionType($actionType), |
||||
0 ignored issues
–
show
Are you sure the usage of
$this->handleUnknownActionType($actionType) targeting Module::handleUnknownActionType() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||||
64 | }; |
||||
65 | } |
||||
66 | catch (MAPIException $e) { |
||||
67 | $this->processException($e, $actionType); |
||||
68 | } |
||||
69 | } |
||||
70 | } |
||||
71 | } |
||||
72 | |||||
73 | /* Generic functions to access data */ |
||||
74 | |||||
75 | /** |
||||
76 | * Function will return values of the properties PR_DELEGATE_FLAGS, PR_SCHDINFO_DELEGATE_ENTRYIDS and |
||||
77 | * PR_SCHDINFO_DELEGATE_NAMES from LocalFreeBusyMessage of the user's store. |
||||
78 | * |
||||
79 | * @param resource $localFreeBusyMessage (optional) local freebusy message of the user's store |
||||
80 | * |
||||
81 | * @return array values of delegate properties |
||||
82 | */ |
||||
83 | public function getDelegateProps($localFreeBusyMessage = false) { |
||||
84 | if (empty($this->delegateProps)) { |
||||
85 | if ($localFreeBusyMessage === false) { |
||||
86 | $localFreeBusyMessage = FreeBusy::getLocalFreeBusyMessage($this->getDefaultStore()); |
||||
87 | } |
||||
88 | |||||
89 | $this->delegateProps = mapi_getprops($localFreeBusyMessage, [PR_DELEGATE_FLAGS, PR_SCHDINFO_DELEGATE_ENTRYIDS, PR_SCHDINFO_DELEGATE_NAMES]); |
||||
90 | |||||
91 | // check if properties exists or not, if not then initialize with default values |
||||
92 | // this way in caller functions we don't need to check for non-existent properties |
||||
93 | if (!isset($this->delegateProps[PR_DELEGATE_FLAGS])) { |
||||
94 | $this->delegateProps[PR_DELEGATE_FLAGS] = []; |
||||
95 | } |
||||
96 | |||||
97 | if (!isset($this->delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS])) { |
||||
98 | $this->delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS] = []; |
||||
99 | } |
||||
100 | |||||
101 | if (!isset($this->delegateProps[PR_SCHDINFO_DELEGATE_NAMES])) { |
||||
102 | $this->delegateProps[PR_SCHDINFO_DELEGATE_NAMES] = []; |
||||
103 | } |
||||
104 | } |
||||
105 | |||||
106 | return $this->delegateProps; |
||||
107 | } |
||||
108 | |||||
109 | /** |
||||
110 | * Function will return array of entryids of default folders of the user's store. |
||||
111 | * |
||||
112 | * @param resource $store (optional) user's store |
||||
113 | * |
||||
114 | * @return array default folder entryids |
||||
115 | */ |
||||
116 | public function getDefaultFolders($store = false) { |
||||
117 | if (empty($this->defaultFolders)) { |
||||
118 | if ($store === false) { |
||||
119 | $store = $this->getDefaultStore(); |
||||
120 | } |
||||
121 | |||||
122 | // Get root store |
||||
123 | $root = mapi_msgstore_openentry($store); |
||||
124 | |||||
125 | // Get Inbox folder |
||||
126 | $inbox = mapi_msgstore_getreceivefolder($store); |
||||
127 | $inboxprops = mapi_getprops($inbox, [PR_ENTRYID]); |
||||
128 | |||||
129 | // Get entryids of default folders. |
||||
130 | $rootStoreProps = mapi_getprops($root, [PR_IPM_APPOINTMENT_ENTRYID, PR_IPM_TASK_ENTRYID, PR_IPM_CONTACT_ENTRYID, PR_IPM_NOTE_ENTRYID, PR_IPM_JOURNAL_ENTRYID]); |
||||
131 | |||||
132 | $this->defaultFolders = [ |
||||
133 | 'calendar' => $rootStoreProps[PR_IPM_APPOINTMENT_ENTRYID], |
||||
134 | 'tasks' => $rootStoreProps[PR_IPM_TASK_ENTRYID], |
||||
135 | 'inbox' => $inboxprops[PR_ENTRYID], |
||||
136 | 'contacts' => $rootStoreProps[PR_IPM_CONTACT_ENTRYID], |
||||
137 | 'notes' => $rootStoreProps[PR_IPM_NOTE_ENTRYID], |
||||
138 | 'journal' => $rootStoreProps[PR_IPM_JOURNAL_ENTRYID], |
||||
139 | ]; |
||||
140 | } |
||||
141 | |||||
142 | return $this->defaultFolders; |
||||
143 | } |
||||
144 | |||||
145 | /** |
||||
146 | * Function will return index of a particular delegate, this index can be used to get information of |
||||
147 | * delegate from PR_DELEGATE_FLAGS, PR_SCHDINFO_DELEGATE_ENTRYIDS and |
||||
148 | * PR_SCHDINFO_DELEGATE_NAMES properties. |
||||
149 | * |
||||
150 | * @param string $entryId entryid of delegate |
||||
151 | * |
||||
152 | * @return int index of the delegate information |
||||
153 | */ |
||||
154 | public function getDelegateIndex($entryId) { |
||||
155 | $delegateProps = $this->getDelegateProps(); |
||||
156 | |||||
157 | // Check if user is existing delegate. |
||||
158 | if (!empty($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS])) { |
||||
159 | return array_search($entryId, $delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS]); |
||||
0 ignored issues
–
show
|
|||||
160 | } |
||||
161 | |||||
162 | return false; |
||||
0 ignored issues
–
show
|
|||||
163 | } |
||||
164 | |||||
165 | /** |
||||
166 | * Function will return resource of the default store of the current logged in user. |
||||
167 | * |
||||
168 | * @return resource current user's store |
||||
169 | */ |
||||
170 | public function getDefaultStore() { |
||||
171 | if (!$this->defaultStore) { |
||||
172 | $this->defaultStore = $GLOBALS['mapisession']->getDefaultMessageStore(); |
||||
173 | } |
||||
174 | |||||
175 | return $this->defaultStore; |
||||
176 | } |
||||
177 | |||||
178 | /** |
||||
179 | * Function will return properties of the user from addressbook based on passed user's entryid. |
||||
180 | * |
||||
181 | * @param string $userEntryId entryid of the user from addressbook |
||||
182 | * |
||||
183 | * @return array properties of user from addressbook |
||||
184 | */ |
||||
185 | public function getUserInfo($userEntryId) { |
||||
186 | // default return stuff |
||||
187 | $result = [ |
||||
188 | 'display_name' => _('Unknown user/group'), |
||||
189 | 'entryid' => null, |
||||
190 | ]; |
||||
191 | |||||
192 | // open the addressbook |
||||
193 | $ab = $GLOBALS['mapisession']->getAddressbook(); |
||||
194 | |||||
195 | try { |
||||
196 | // try userid as normal user |
||||
197 | $user = mapi_ab_openentry($ab, $userEntryId); |
||||
198 | } |
||||
199 | catch (MAPIException $e) { |
||||
200 | if ($e->getCode() === MAPI_E_NOT_FOUND) { |
||||
201 | $e->setHandled(); |
||||
202 | |||||
203 | return $result; |
||||
204 | } |
||||
205 | } |
||||
206 | |||||
207 | $props = mapi_getprops($user, [PR_DISPLAY_NAME]); |
||||
208 | $result['display_name'] = $props[PR_DISPLAY_NAME]; |
||||
209 | $result['entryid'] = bin2hex($userEntryId); |
||||
210 | |||||
211 | return $result; |
||||
212 | } |
||||
213 | |||||
214 | /* Functions to get delegates information */ |
||||
215 | |||||
216 | /** |
||||
217 | * Function will return all the delegates information for current user. |
||||
218 | */ |
||||
219 | public function delegateList() { |
||||
220 | $delegateProps = $this->getDelegateProps(); |
||||
221 | |||||
222 | $data = []; |
||||
223 | |||||
224 | // get delegate meeting rule |
||||
225 | $delegateMeetingRule = $this->getDelegateMeetingRule(); |
||||
226 | |||||
227 | // Get permissions of all delegates. |
||||
228 | if (!empty($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS])) { |
||||
229 | for ($i = 0, $len = count($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS]); $i < $len; ++$i) { |
||||
230 | array_push($data, $this->getDelegatePermissions($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS][$i], $delegateMeetingRule)); |
||||
231 | } |
||||
232 | } |
||||
233 | |||||
234 | $this->addActionData('list', ['item' => $data]); |
||||
235 | $GLOBALS['bus']->addData($this->getResponseData()); |
||||
236 | } |
||||
237 | |||||
238 | /** |
||||
239 | * Function will return the permissions assigned for a particular delegate user. |
||||
240 | * |
||||
241 | * @param array $delegate the delegate information sent by client |
||||
242 | */ |
||||
243 | public function openDelegate($delegate) { |
||||
244 | // Get permissions of a delegate. |
||||
245 | $data = $this->getDelegatePermissions(hex2bin((string) $delegate['entryid'])); |
||||
246 | |||||
247 | $this->addActionData('item', ['item' => $data]); |
||||
248 | $GLOBALS['bus']->addData($this->getResponseData()); |
||||
249 | } |
||||
250 | |||||
251 | /** |
||||
252 | * Function will return information of a particular delegate from current user's store. |
||||
253 | * |
||||
254 | * @param string $userEntryId entryid of the delegate |
||||
255 | * @param array $delegateMeetingRule (optional) information of the delegate meeting rule that can be used to check if |
||||
256 | * current delegate exists in the meeting rule |
||||
257 | * |
||||
258 | * @return array delegate information |
||||
259 | */ |
||||
260 | public function getDelegatePermissions($userEntryId, $delegateMeetingRule = false) { |
||||
0 ignored issues
–
show
The parameter
$delegateMeetingRule is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
261 | $delegateProps = $this->getDelegateProps(); |
||||
262 | $delegateIndex = $this->getDelegateIndex($userEntryId); |
||||
263 | $userinfo = $this->getUserInfo($userEntryId); |
||||
264 | |||||
265 | $delegate = []; |
||||
266 | $delegate['entryid'] = bin2hex($userEntryId); |
||||
267 | |||||
268 | $delegate['props'] = []; |
||||
269 | $delegate['props']['display_name'] = $userinfo['display_name']; |
||||
270 | $delegate['props']['can_see_private'] = isset($delegateProps[PR_DELEGATE_FLAGS][$delegateIndex]) ? ($delegateProps[PR_DELEGATE_FLAGS][$delegateIndex] == 1) : false; |
||||
271 | |||||
272 | $delegate['props'] = array_merge($delegate['props'], $this->getFolderPermissions($userEntryId)); |
||||
273 | |||||
274 | return $delegate; |
||||
275 | } |
||||
276 | |||||
277 | /** |
||||
278 | * Function will return folder permissions of a delegate user. |
||||
279 | * |
||||
280 | * @param string $userEntryId entryid of the delegate |
||||
281 | * |
||||
282 | * @return array folder permissions of a delegate user |
||||
283 | */ |
||||
284 | public function getFolderPermissions($userEntryId) { |
||||
285 | $delegateRights = []; |
||||
286 | $store = $this->getDefaultStore(); |
||||
287 | |||||
288 | foreach ($this->getDefaultFolders($store) as $folderName => $folderEntryId) { |
||||
289 | $folder = mapi_msgstore_openentry($store, $folderEntryId); |
||||
290 | |||||
291 | // Get all users who has permissions |
||||
292 | $grants = mapi_zarafa_getpermissionrules($folder, ACCESS_TYPE_GRANT); |
||||
293 | |||||
294 | // Find current delegate and get permission. |
||||
295 | foreach ($grants as $id => $grant) { |
||||
296 | if ($GLOBALS["entryid"]->compareEntryIds(bin2hex($userEntryId), bin2hex((string) $grant['userid']))) { |
||||
297 | $delegateRights['rights_' . $folderName] = $grant['rights']; |
||||
298 | } |
||||
299 | } |
||||
300 | } |
||||
301 | |||||
302 | return $delegateRights; |
||||
303 | } |
||||
304 | |||||
305 | /** |
||||
306 | * Function will return properties of meeting rule that is used to send meeting related messages to delegate. |
||||
307 | * |
||||
308 | * @return array delegate meeting rule information |
||||
309 | */ |
||||
310 | public function getDelegateMeetingRule() { |
||||
311 | $inbox = mapi_msgstore_getreceivefolder($this->getDefaultStore()); |
||||
312 | $rulesTable = mapi_folder_getrulestable($inbox); |
||||
313 | // get delegate meeting rule |
||||
314 | $restriction = [RES_CONTENT, |
||||
315 | [ |
||||
316 | FUZZYLEVEL => FL_FULLSTRING | FL_IGNORECASE, |
||||
317 | ULPROPTAG => PR_RULE_PROVIDER, |
||||
318 | VALUE => [ |
||||
319 | PR_RULE_PROVIDER => 'Schedule+ EMS Interface', |
||||
320 | ], |
||||
321 | ], |
||||
322 | ]; |
||||
323 | mapi_table_restrict($rulesTable, $restriction); |
||||
324 | // there will be only one rule, so fetch that only |
||||
325 | $delegateMeetingRule = mapi_table_queryrows($rulesTable, $GLOBALS['properties']->getRulesProperties(), 0, 1); |
||||
326 | |||||
327 | return !empty($delegateMeetingRule) ? $delegateMeetingRule[0] : false; |
||||
0 ignored issues
–
show
The expression
return ! empty($delegate...eMeetingRule[0] : false could also return false which is incompatible with the documented return type array . Did you maybe forget to handle an error condition?
If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled. ![]() |
|||||
328 | } |
||||
329 | |||||
330 | /* Functions to update delegates information */ |
||||
331 | |||||
332 | /** |
||||
333 | * Function which saves delegates information sent from client. |
||||
334 | * |
||||
335 | * @param array $delegates the delegates information sent by client |
||||
336 | */ |
||||
337 | public function saveDelegates($delegates) { |
||||
338 | $responseData = []; |
||||
339 | |||||
340 | // @FIXME currently client only sends a single delegate in a request, if we can change that to contain |
||||
341 | // multiple delegates that would be good |
||||
342 | |||||
343 | if (is_assoc_array($delegates)) { |
||||
344 | // wrap single delegate in an array |
||||
345 | $delegates = [$delegates]; |
||||
346 | } |
||||
347 | |||||
348 | for ($index = 0, $len = count($delegates); $index < $len; ++$index) { |
||||
349 | $delegate = $delegates[$index]; |
||||
350 | $this->setFolderPermissions($delegate); |
||||
351 | // set properties for delegates on user's freebusy folder |
||||
352 | array_push($responseData, ['entryid' => $delegate['entryid']]); |
||||
353 | } |
||||
354 | $this->setDelegateProps($delegates); |
||||
355 | // set delegate meeting rule |
||||
356 | $this->setDelegateMeetingRule($delegates); |
||||
357 | |||||
358 | // send response to indicate success |
||||
359 | if (!empty($responseData)) { |
||||
360 | $this->addActionData('update', ['item' => $responseData]); |
||||
361 | $GLOBALS['bus']->addData($this->getResponseData()); |
||||
362 | } |
||||
363 | } |
||||
364 | |||||
365 | /** |
||||
366 | * Function will update PR_DELEGATE_FLAGS, PR_SCHDINFO_DELEGATE_ENTRYIDS and |
||||
367 | * PR_SCHDINFO_DELEGATE_NAMES properties in the current user's store. |
||||
368 | * |
||||
369 | * @param mixed $delegates |
||||
370 | */ |
||||
371 | public function setDelegateProps($delegates) { |
||||
372 | $localFreeBusyMessage = FreeBusy::getLocalFreeBusyMessage($this->getDefaultStore()); |
||||
373 | $delegateProps = $this->getDelegateProps($localFreeBusyMessage); |
||||
374 | $len = count($delegates); |
||||
375 | for ($i = 0; $i < $len; ++$i) { |
||||
376 | $delegate = $delegates[$i]; |
||||
377 | $len1 = count($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS]); |
||||
378 | for ($j = 0; $j < $len1; ++$j) { |
||||
379 | if ($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS][$j] == hex2bin((string) $delegate['entryid'])) { |
||||
380 | break; |
||||
381 | } |
||||
382 | } |
||||
383 | $delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS][$j] = hex2bin((string) $delegate['entryid']); |
||||
384 | if (isset($delegate['props']['display_name'])) { |
||||
385 | $delegateProps[PR_SCHDINFO_DELEGATE_NAMES][$j] = $delegate['props']['display_name']; |
||||
386 | } |
||||
387 | else { |
||||
388 | $addrBook = $GLOBALS['mapisession']->getAddressbook(); |
||||
389 | $user = mapi_ab_openentry($addrBook, hex2bin((string) $delegate['entryid'])); |
||||
390 | if (empty($user)) { |
||||
391 | $delegateProps[PR_SCHDINFO_DELEGATE_NAMES][$j] = ""; |
||||
392 | } |
||||
393 | else { |
||||
394 | $userProps = mapi_getprops($user, [PR_SMTP_ADDRESS]); |
||||
395 | if (empty($userProps[PR_SMTP_ADDRESS])) { |
||||
396 | $delegateProps[PR_SCHDINFO_DELEGATE_NAMES][$j] = ""; |
||||
397 | } |
||||
398 | else { |
||||
399 | $delegateProps[PR_SCHDINFO_DELEGATE_NAMES][$j] = $userProps[PR_SMTP_ADDRESS]; |
||||
400 | } |
||||
401 | } |
||||
402 | } |
||||
403 | if (isset($delegate['props']['can_see_private'])) { |
||||
404 | $delegateProps[PR_DELEGATE_FLAGS][$j] = $delegate['props']['can_see_private']; |
||||
405 | } |
||||
406 | else { |
||||
407 | $delegateProps[PR_DELEGATE_FLAGS][$j] = false; |
||||
408 | } |
||||
409 | } |
||||
410 | mapi_setprops($localFreeBusyMessage, $delegateProps); |
||||
411 | mapi_savechanges($localFreeBusyMessage); |
||||
412 | // unset the module variable, so subsequent calls will have the updated value |
||||
413 | unset($this->delegateProps); |
||||
414 | } |
||||
415 | |||||
416 | /** |
||||
417 | * Function will set folder permissions for a delegate user. |
||||
418 | * |
||||
419 | * @param array $delegate delegate information sent from client |
||||
420 | */ |
||||
421 | public function setFolderPermissions($delegate) { |
||||
422 | $store = $this->getDefaultStore(); |
||||
423 | |||||
424 | // Get all default folders and set permissions. |
||||
425 | foreach ($this->getDefaultFolders($store) as $folderName => $folderEntryID) { |
||||
426 | // we need to only modify those permissions which are modified on client |
||||
427 | if (isset($delegate['props']['rights_' . $folderName]) && $delegate['props']['rights_' . $folderName] !== '') { |
||||
428 | $folder = mapi_msgstore_openentry($store, $folderEntryID); |
||||
429 | |||||
430 | // Set new permissions. |
||||
431 | $acls = [ |
||||
432 | [ |
||||
433 | 'type' => ACCESS_TYPE_GRANT, |
||||
434 | 'userid' => hex2bin((string) $delegate['entryid']), |
||||
435 | 'rights' => $delegate['props']['rights_' . $folderName], |
||||
436 | 'state' => RIGHT_NEW | RIGHT_AUTOUPDATE_DENIED, |
||||
437 | 'memberid' => 0, |
||||
438 | ], |
||||
439 | ]; |
||||
440 | |||||
441 | mapi_zarafa_setpermissionrules($folder, $acls); |
||||
442 | mapi_savechanges($folder); |
||||
443 | |||||
444 | if ($folderName === 'calendar') { |
||||
445 | $freeBusyFolder = FreeBusy::getLocalFreeBusyFolder($store); |
||||
446 | |||||
447 | if ($freeBusyFolder !== false) { |
||||
448 | // set permissions on free/busy message |
||||
449 | $acls[0]['rights'] |= ecRightsDefaultPublic; |
||||
450 | |||||
451 | mapi_zarafa_setpermissionrules($freeBusyFolder, $acls); |
||||
452 | mapi_savechanges($freeBusyFolder); |
||||
453 | } |
||||
454 | } |
||||
455 | } |
||||
456 | } |
||||
457 | } |
||||
458 | |||||
459 | /** |
||||
460 | * Function which creates/modifies delegate meeting rule in user store |
||||
461 | * to send meeting request mails to delegates also. |
||||
462 | * |
||||
463 | * @param array $delegates all delegate information |
||||
464 | */ |
||||
465 | public function setDelegateMeetingRule($delegates) { |
||||
466 | $delegateMeetingRule = $this->getDelegateMeetingRule(); |
||||
467 | if ($delegateMeetingRule !== false) { |
||||
0 ignored issues
–
show
|
|||||
468 | $users = $delegateMeetingRule[PR_RULE_ACTIONS][0]['adrlist']; |
||||
469 | } |
||||
470 | else { |
||||
471 | $users = []; |
||||
472 | } |
||||
473 | // open addressbook to get information of all users |
||||
474 | $addrBook = $GLOBALS['mapisession']->getAddressbook(); |
||||
475 | $len = count($delegates); |
||||
476 | for ($i = 0; $i < $len; ++$i) { |
||||
477 | $delegate = $delegates[$i]; |
||||
478 | // get user info, using entryid |
||||
479 | $user = mapi_ab_openentry($addrBook, hex2bin((string) $delegate['entryid'])); |
||||
480 | $userProps = mapi_getprops($user, [PR_ENTRYID, PR_ADDRTYPE, PR_EMAIL_ADDRESS, PR_DISPLAY_NAME, PR_SEARCH_KEY, PR_SMTP_ADDRESS, PR_OBJECT_TYPE, PR_DISPLAY_TYPE, PR_DISPLAY_TYPE_EX]); |
||||
481 | |||||
482 | if (is_array($userProps)) { |
||||
483 | // add recipient type prop, to specify type of recipient in mail |
||||
484 | $userProps[PR_RECIPIENT_TYPE] = MAPI_TO; |
||||
485 | $len1 = count($users); |
||||
486 | for ($j = 0; $j < $len1; ++$j) { |
||||
487 | if ($userProps[PR_ENTRYID] == $users[$j][PR_ENTRYID]) { |
||||
488 | break; |
||||
489 | } |
||||
490 | } |
||||
491 | $users[$j] = $userProps; |
||||
492 | } |
||||
493 | } |
||||
494 | // only continue if any delegate has set the flag |
||||
495 | if (!empty($users)) { |
||||
496 | if ($delegateMeetingRule === false) { |
||||
0 ignored issues
–
show
|
|||||
497 | $this->createDelegateMeetingRule($users); |
||||
498 | } |
||||
499 | else { |
||||
500 | $this->modifyDelegateMeetingRule($delegateMeetingRule, $users); |
||||
501 | } |
||||
502 | } |
||||
503 | } |
||||
504 | |||||
505 | /** |
||||
506 | * Function will create a new delegate meeting rule if it is not present in current user's store. |
||||
507 | * |
||||
508 | * @param array $usersInfo user properties which should be added in PR_RULE_ACTIONS |
||||
509 | */ |
||||
510 | public function createDelegateMeetingRule($usersInfo) { |
||||
511 | // create new rule |
||||
512 | $rule = []; |
||||
513 | |||||
514 | // no need to pass rule_id when creating new rule |
||||
515 | $rule[PR_RULE_ACTIONS] = [ |
||||
516 | [ |
||||
517 | 'action' => OP_DELEGATE, |
||||
518 | // don't set this value it will have no effect, its hardcoded to FWD_PRESERVE_SENDER | FWD_DO_NOT_MUNGE_MSG |
||||
519 | 'flavor' => 0, |
||||
520 | 'flags' => 0, |
||||
521 | 'adrlist' => $usersInfo, |
||||
522 | ], |
||||
523 | ]; |
||||
524 | |||||
525 | $rule[PR_RULE_CONDITION] = [RES_AND, |
||||
526 | [ |
||||
527 | [RES_CONTENT, |
||||
528 | [ |
||||
529 | FUZZYLEVEL => FL_PREFIX, |
||||
530 | ULPROPTAG => PR_MESSAGE_CLASS, |
||||
531 | VALUE => [PR_MESSAGE_CLASS => 'IPM.Schedule.Meeting'], |
||||
532 | ], |
||||
533 | ], |
||||
534 | [RES_NOT, |
||||
535 | [ |
||||
536 | [RES_EXIST, |
||||
537 | [ |
||||
538 | ULPROPTAG => PR_DELEGATED_BY_RULE, |
||||
539 | ], |
||||
540 | ], |
||||
541 | ], |
||||
542 | ], |
||||
543 | [RES_OR, |
||||
544 | [ |
||||
545 | [RES_NOT, |
||||
546 | [ |
||||
547 | [RES_EXIST, |
||||
548 | [ |
||||
549 | ULPROPTAG => PR_SENSITIVITY, |
||||
550 | ], |
||||
551 | ], |
||||
552 | ], |
||||
553 | ], |
||||
554 | [RES_PROPERTY, |
||||
555 | [ |
||||
556 | RELOP => RELOP_NE, |
||||
557 | ULPROPTAG => PR_SENSITIVITY, |
||||
558 | VALUE => [PR_SENSITIVITY => SENSITIVITY_PRIVATE], |
||||
559 | ], |
||||
560 | ], |
||||
561 | ], |
||||
562 | ], |
||||
563 | ], |
||||
564 | ]; |
||||
565 | |||||
566 | $rule[PR_RULE_NAME] = ''; |
||||
567 | $rule[PR_RULE_PROVIDER_DATA] = ''; // 0 byte binary string |
||||
568 | $rule[PR_RULE_STATE] = ST_ENABLED; |
||||
569 | $rule[PR_RULE_LEVEL] = 0; |
||||
570 | $rule[PR_RULE_SEQUENCE] = 0; |
||||
571 | $rule[PR_RULE_PROVIDER] = 'Schedule+ EMS Interface'; |
||||
572 | $rule[PR_RULE_USER_FLAGS] = 0; |
||||
573 | |||||
574 | $rows = [ |
||||
575 | 0 => [ |
||||
576 | 'rowflags' => ROW_ADD, |
||||
577 | 'properties' => $rule, |
||||
578 | ], |
||||
579 | ]; |
||||
580 | $inbox = mapi_msgstore_getreceivefolder($this->getDefaultStore()); |
||||
581 | mapi_folder_modifyrules($inbox, $rows); |
||||
582 | } |
||||
583 | |||||
584 | public function modifyDelegateMeetingRule($delegateMeetingRule, $users) { |
||||
585 | $inbox = mapi_msgstore_getreceivefolder($this->getDefaultStore()); |
||||
586 | if (count($users) > 0) { |
||||
587 | // update the adrlist in the rule |
||||
588 | $delegateMeetingRule[PR_RULE_ACTIONS][0]['adrlist'] = $users; |
||||
589 | |||||
590 | $rows = [ |
||||
591 | [ |
||||
592 | 'rowflags' => ROW_MODIFY, |
||||
593 | 'properties' => $delegateMeetingRule, |
||||
594 | ], |
||||
595 | ]; |
||||
596 | } |
||||
597 | else { |
||||
598 | // no users remaining in the rule so delete the rule |
||||
599 | $rows = [ |
||||
600 | 0 => [ |
||||
601 | 'rowflags' => ROW_REMOVE, |
||||
602 | 'properties' => $delegateMeetingRule, |
||||
603 | ], |
||||
604 | ]; |
||||
605 | } |
||||
606 | mapi_folder_modifyrules($inbox, $rows); |
||||
607 | } |
||||
608 | |||||
609 | /* Functions to delete delegates information */ |
||||
610 | |||||
611 | /** |
||||
612 | * Function which deletes delegates information sent by client. |
||||
613 | * |
||||
614 | * @param array $delegates delegates information sent by client |
||||
615 | */ |
||||
616 | public function deleteDelegates($delegates) { |
||||
617 | if (is_assoc_array($delegates)) { |
||||
618 | // wrap single delegate in an array |
||||
619 | $delegates = [$delegates]; |
||||
620 | } |
||||
621 | foreach ($delegates as $delegate) { |
||||
622 | // set properties for delegates on user's freebusy folder |
||||
623 | $this->deleteDelegateProps($delegate); |
||||
624 | |||||
625 | // set permissions on user's default folders |
||||
626 | $this->deleteFolderPermissions($delegate); |
||||
627 | } |
||||
628 | // delete delegate meeting rule |
||||
629 | $this->removeDelegatesFromDelegateMeetingRule($delegates); |
||||
630 | $this->sendFeedback(true); |
||||
631 | } |
||||
632 | |||||
633 | /** |
||||
634 | * Function will delete values from PR_DELEGATE_FLAGS, PR_SCHDINFO_DELEGATE_ENTRYIDS and PR_SCHDINFO_DELEGATE_NAMES and save the properties back if its not empty. |
||||
635 | * |
||||
636 | * @param array $delegate delegate information sent from client |
||||
637 | */ |
||||
638 | public function deleteDelegateProps($delegate) { |
||||
639 | $localFreeBusyMessage = FreeBusy::getLocalFreeBusyMessage($this->getDefaultStore()); |
||||
640 | $delegateProps = $this->getDelegateProps($localFreeBusyMessage); |
||||
641 | $delegateIndex = -1; |
||||
642 | $len = count($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS]); |
||||
643 | for ($i = 0; $i < $len; ++$i) { |
||||
644 | if ($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS][$i] == hex2bin((string) $delegate["entryid"])) { |
||||
645 | $delegateIndex = $i; |
||||
646 | break; |
||||
647 | } |
||||
648 | } |
||||
649 | if ($delegateIndex == -1) { |
||||
650 | return; |
||||
651 | } |
||||
652 | unset($delegateProps[PR_DELEGATE_FLAGS][$delegateIndex], $delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS][$delegateIndex], $delegateProps[PR_SCHDINFO_DELEGATE_NAMES][$delegateIndex]); |
||||
653 | |||||
654 | // unset will remove the value but will not regenerate array keys, so we need to |
||||
655 | // do it here |
||||
656 | $delegateProps[PR_DELEGATE_FLAGS] = array_values($delegateProps[PR_DELEGATE_FLAGS]); |
||||
657 | $delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS] = array_values($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS]); |
||||
658 | $delegateProps[PR_SCHDINFO_DELEGATE_NAMES] = array_values($delegateProps[PR_SCHDINFO_DELEGATE_NAMES]); |
||||
659 | |||||
660 | if (!empty($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS])) { |
||||
661 | mapi_setprops($localFreeBusyMessage, $delegateProps); |
||||
662 | } |
||||
663 | else { |
||||
664 | // Delete delegate properties. |
||||
665 | mapi_deleteprops($localFreeBusyMessage, [PR_DELEGATE_FLAGS, PR_SCHDINFO_DELEGATE_ENTRYIDS, PR_SCHDINFO_DELEGATE_NAMES]); |
||||
666 | } |
||||
667 | |||||
668 | mapi_savechanges($localFreeBusyMessage); |
||||
669 | |||||
670 | // unset the module variable, so subsequent calls will have the updated value |
||||
671 | unset($this->delegateProps); |
||||
672 | } |
||||
673 | |||||
674 | /** |
||||
675 | * Function which deletes permissions from all default folder for a particular delegate. |
||||
676 | * |
||||
677 | * @param array $delegate delegate's information sent by client |
||||
678 | */ |
||||
679 | public function deleteFolderPermissions($delegate) { |
||||
680 | $store = $this->getDefaultStore(); |
||||
681 | |||||
682 | // Get all default folders and set permissions. |
||||
683 | foreach ($this->getDefaultFolders($store) as $folderName => $folderEntryID) { |
||||
684 | $folder = mapi_msgstore_openentry($store, $folderEntryID); |
||||
685 | |||||
686 | // delete current acl's |
||||
687 | $acls = [ |
||||
688 | [ |
||||
689 | 'type' => ACCESS_TYPE_GRANT, |
||||
690 | 'userid' => hex2bin((string) $delegate['entryid']), |
||||
691 | 'rights' => ecRightsNone, |
||||
692 | 'state' => RIGHT_DELETED | RIGHT_AUTOUPDATE_DENIED, |
||||
693 | 'memberid' => 0, |
||||
694 | ], |
||||
695 | ]; |
||||
696 | |||||
697 | mapi_zarafa_setpermissionrules($folder, $acls); |
||||
698 | |||||
699 | if ($folderName === 'calendar') { |
||||
700 | $freeBusyFolder = FreeBusy::getLocalFreeBusyFolder($store); |
||||
701 | |||||
702 | if ($freeBusyFolder !== false) { |
||||
703 | mapi_zarafa_setpermissionrules($freeBusyFolder, $acls); |
||||
704 | mapi_savechanges($freeBusyFolder); |
||||
705 | } |
||||
706 | } |
||||
707 | |||||
708 | mapi_savechanges($folder); |
||||
709 | } |
||||
710 | } |
||||
711 | |||||
712 | /** |
||||
713 | * Function will remove delegates from delegate meeting rule when the user is deleted from delegate list. |
||||
714 | * |
||||
715 | * @param array $delegates all delegate information that are deleted |
||||
716 | */ |
||||
717 | public function removeDelegatesFromDelegateMeetingRule($delegates) { |
||||
718 | $delegateMeetingRule = $this->getDelegateMeetingRule(); |
||||
719 | if ($delegateMeetingRule === false) { |
||||
0 ignored issues
–
show
|
|||||
720 | // no delegate rule exists, nothing to do |
||||
721 | return; |
||||
722 | } |
||||
723 | $len = count($delegates); |
||||
724 | $old_users = $delegateMeetingRule[PR_RULE_ACTIONS][0]['adrlist']; |
||||
725 | $new_users = []; |
||||
726 | foreach ($old_users as $user) { |
||||
727 | for ($index = 0; $index < $len; ++$index) { |
||||
728 | if ($user[PR_ENTRYID] == hex2bin((string) $delegates[$index]['entryid'])) { |
||||
729 | break; |
||||
730 | } |
||||
731 | } |
||||
732 | if ($index == $len) { |
||||
733 | $new_users[] = $user; |
||||
734 | } |
||||
735 | } |
||||
736 | $this->modifyDelegateMeetingRule($delegateMeetingRule, $new_users); |
||||
737 | } |
||||
738 | |||||
739 | /* Functions for exception handling */ |
||||
740 | |||||
741 | /** |
||||
742 | * Function does customization of MAPIException based on module data. |
||||
743 | * like, here it will generate display message based on actionType |
||||
744 | * for particular exception. |
||||
745 | * |
||||
746 | * @param object $e Exception object |
||||
747 | * @param string $actionType the action type, sent by the client |
||||
748 | * @param MAPIobject $store store object of the current user |
||||
0 ignored issues
–
show
The type
MAPIobject was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||
749 | * @param string $parententryid parent entryid of the message |
||||
750 | * @param string $entryid entryid of the message/folder |
||||
751 | * @param array $action the action data, sent by the client |
||||
752 | */ |
||||
753 | #[Override] |
||||
754 | public function handleException(&$e, $actionType = null, $store = null, $parententryid = null, $entryid = null, $action = null) { |
||||
755 | switch ($actionType) { |
||||
756 | case 'save': |
||||
757 | $e->setDisplayMessage(_('Could not save delegate information.')); |
||||
758 | break; |
||||
759 | |||||
760 | case 'delete': |
||||
761 | $e->setDisplayMessage(_('Could not delete delegate.')); |
||||
762 | break; |
||||
763 | |||||
764 | case 'list': |
||||
765 | $e->setDisplayMessage(_('Can not get list of delegates.')); |
||||
766 | break; |
||||
767 | } |
||||
768 | |||||
769 | parent::handleException($e, $actionType, $store, $parententryid, $entryid, $action); |
||||
770 | } |
||||
771 | } |
||||
772 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..