Test Failed
Push — master ( 647c72...cd42b5 )
by
unknown
10:25
created

Module::getEntryID()   A

Complexity

Conditions 6
Paths 4

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 7
nc 4
nop 0
dl 0
loc 13
rs 9.2222
c 0
b 0
f 0
1
<?php
2
	require_once(__DIR__ . '/../exceptions/class.SearchException.php');
3
4
	/**
5
	 * Module
6
	 * Superclass of every module. Many default functions are defined in this class.
7
	 */
8
	class Module
9
	{
10
		/**
11
		 * @var int unique id of the class.
12
		 */
13
		var $id;
14
15
		/**
16
		 * @var string entryid, which will be registered by the bus object.
17
		 */
18
		var $entryid;
19
20
		/**
21
		 * @var array list of all actions, which is received from the client.
22
		 */
23
		var $data;
24
25
		/**
26
		 * @var array list of the results, which is send to the client.
27
		 */
28
		var $responseData;
29
30
		/**
31
		 * @var array list of all the errors occurred.
32
		 */
33
		var $errors;
34
35
		/**
36
		 * @var State The state object which refers to the statefile
37
		 */
38
		var $sessionState;
39
40
		/**
41
		 * @var array data stored in session for this module
42
		 */
43
		var $sessionData;
44
45
		/**
46
		 * Constructor
47
		 * @param int $id unique id.
48
		 * @param array $data list of all actions.
49
		 */
50
		function __construct($id, $data)
51
		{
52
			$this->id = $id;
53
			$this->data = $data;
54
			$this->errors = array();
55
			$this->responseData = array();
56
			$this->sessionState = false;
0 ignored issues
show
Documentation Bug introduced by
It seems like false of type false is incompatible with the declared type State of property $sessionState.

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..

Loading history...
57
			$this->sessionData = false;
0 ignored issues
show
Documentation Bug introduced by
It seems like false of type false is incompatible with the declared type array of property $sessionData.

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..

Loading history...
58
59
			$this->createNotifiers();
60
61
			// Get the store from $data and set it to properties class.
62
			// It is requires for multi server environment where namespace differs.
63
			// e.g. 'categories' => -2062020578, 'categories' => -2062610402,
64
			if (isset($GLOBALS['properties'])) {
65
				$GLOBALS['properties']->setStore($this->getActionStore($this->getActionData($data)));
66
			}
67
		}
68
69
		/**
70
		 * Creates the notifiers for this module,
71
		 * and register them to the Bus.
72
		 */
73
		function createNotifiers()
74
		{
75
		}
76
77
		/**
78
		 * Executes all the actions in the $data variable.
79
		 * @return boolean true on success of false on fialure.
80
		 */
81
		function execute()
82
		{
83
			// you must implement this function for each module
84
		}
85
86
		/**
87
		 * This will call $handleException of updating the MAPIException based in the module data.
88
		 * When this is done, $sendFeedback will be called to send the message to the client.
89
		 *
90
		 * @param object $e Exception object.
91
		 * @param string $actionType the action type, sent by the client.
92
		 * @param MAPIobject $store Store object of the store.
0 ignored issues
show
Bug introduced by
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. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
93
		 * @param string $parententryid parent entryid of the message.
94
		 * @param string $entryid entryid of the message/folder.
95
		 * @param array $action the action data, sent by the client.
96
		 */
97
		function processException(&$e, $actionType = null, $store = null, $parententryid = null, $entryid = null, $action = null)
98
		{
99
			$this->handleException($e, $actionType, $store, $parententryid, $entryid, $action);
100
			$this->sendFeedback(false, $this->errorDetailsFromException($e));
101
		}
102
103
		/**
104
		 * Function does customization of MAPIException based on module data.
105
		 * like, here it will generate display message based on actionType
106
		 * for particular exception.
107
		 *
108
		 * @param object $e Exception object.
109
		 * @param string $actionType the action type, sent by the client.
110
		 * @param MAPIobject $store Store object of the message.
111
		 * @param string $parententryid parent entryid of the message.
112
		 * @param string $entryid entryid of the message/folder.
113
		 * @param array $action the action data, sent by the client.
114
		 */
115
		function handleException(&$e, $actionType = null, $store = null, $parententryid = null, $entryid = null, $action = null)
116
		{
117
			if(is_null($e->displayMessage)) {
118
				switch($actionType)
119
				{
120
					case "save":
121
						if($e->getCode() == MAPI_E_NO_ACCESS)
122
							$e->setDisplayMessage(_("You have insufficient privileges to save this message."));
123
						else
124
							$e->setDisplayMessage(_("Could not save message."));
125
							$e->allowToShowDetailMessage = true;
126
						break;
127
128
					case "delete":
129
						if($e->getCode() == MAPI_E_NO_ACCESS)
130
							$e->setDisplayMessage(_("You have insufficient privileges to delete this message."));
131
						else
132
							$e->setDisplayMessage(_("Could not delete message."));
133
						break;
134
135
					case "cancelMeetingRequest":
136
						if($e->getCode() == MAPI_E_NO_ACCESS)
137
							$e->setDisplayMessage(_("You have insufficient privileges to cancel this Meeting Request."));
138
						else
139
							$e->setDisplayMessage(_("Could not cancel Meeting Request."));
140
						break;
141
142
					case "declineMeetingRequest":
143
						if($e->getCode() == MAPI_E_NO_ACCESS)
144
							$e->setDisplayMessage(_("You have insufficient privileges to decline this Meeting Request."));
145
						else
146
							$e->setDisplayMessage(_("Could not decline Meeting Request."));
147
						break;
148
149
					case "acceptMeetingRequest":
150
						if($e->getCode() == MAPI_E_NO_ACCESS)
151
							$e->setDisplayMessage(_("You have insufficient privileges to accept this Meeting Request."));
152
						else
153
							$e->setDisplayMessage(_("Could not accept Meeting Request."));
154
						break;
155
156
					case "cancelInvitation":
157
						if($e->getCode() == MAPI_E_NO_ACCESS)
158
							$e->setDisplayMessage(_("You have insufficient privileges to cancel Meeting Request invitation."));
159
						else
160
							$e->setDisplayMessage(_("Could not cancel Meeting Request invitations."));
161
						break;
162
163
					case "updatesearch":
164
					case "stopsearch":
165
					case "search":
166
						if($e->getCode() == MAPI_E_NOT_INITIALIZED)
167
							$e->setDisplayMessage(_("You can not continue search operation on this folder."));
168
						else
169
							$e->setDisplayMessage(_("Error in search, please try again."));
170
						break;
171
172
					case "expand":
173
						$e->setDisplayMessage(_("Error in distribution list expansion."));
174
						break;
175
				}
176
				Log::Write(
177
					LOGLEVEL_ERROR,
178
					"Module::handleException():". $actionType . ": " . $e->displayMessage,
179
					$e,
0 ignored issues
show
Unused Code introduced by
The call to Log::Write() has too many arguments starting with $e. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

179
				Log::/** @scrutinizer ignore-call */ 
180
         Write(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
180
					$action);
181
			}
182
		}
183
184
		/**
185
		 * Get quota information of user store and check for over qouta restrictions,
186
		 * if any qouta (softquota/hardquota) limit is exceeded then it will simply
187
		 * return appropriate message string according to quota type(hardquota/softquota).
188
		 * @param MAPIobject $store Store object of the store
189
		 * @param string $actionType the action type, sent by the client
190
		 * @param array $action the action data, sent by the client
191
		 * @return string Short message according to quota type(hardquota/softquota) or a blank string.
192
		 */
193
194
		function getOverQuotaMessage($store)
195
		{
196
			if($store === false) {
0 ignored issues
show
introduced by
The condition $store === false is always false.
Loading history...
197
				$store = $GLOBALS['mapisession']->getDefaultMessageStore();
198
			}
199
200
			$storeProps = mapi_getprops($store, array(PR_QUOTA_WARNING_THRESHOLD, PR_QUOTA_SEND_THRESHOLD, PR_QUOTA_RECEIVE_THRESHOLD, PR_MESSAGE_SIZE_EXTENDED));
201
202
			$quotaDetails = array(
203
				'store_size' => round($storeProps[PR_MESSAGE_SIZE_EXTENDED]/1024),
204
				'quota_warning' => $storeProps[PR_QUOTA_WARNING_THRESHOLD],
205
				'quota_soft' => $storeProps[PR_QUOTA_SEND_THRESHOLD],
206
				'quota_hard' => $storeProps[PR_QUOTA_RECEIVE_THRESHOLD]
207
			);
208
209
			if($quotaDetails['quota_hard'] !== 0 && $quotaDetails['store_size'] > $quotaDetails['quota_hard']) {
210
				return _('The message store has exceeded its hard quota limit.') . '<br/>' .
211
						_('To reduce the amount of data in this message store, select some items that you no longer need, delete them and cleanup your Deleted Items folder.');
212
			}
213
214
			// if hard quota limit doesn't restrict the operation then check for soft qouta limit
215
			if($quotaDetails['quota_soft'] !== 0 && $quotaDetails['store_size'] > $quotaDetails['quota_soft']) {
216
				return _('The message store has exceeded its soft quota limit.') . '<br/> '.
217
						_('To reduce the amount of data in this message store, select some items that you no longer need, delete them and cleanup your Deleted Items folder.');
218
			}
219
220
			return '';
221
		}
222
223
		/**
224
		 * sends a success or error message to client based on parameters passed
225
		 * @param boolean $success operation completed successfully or not
226
		 * @param Array $data The data array that will be send to the client as a response to success/failure.
227
		 * @param Boolean $addResponseDataToBus if true then data will be added to bus otherwise data
228
		 * will be stored in module and later requests can add it to bus.
229
		 */
230
		function sendFeedback($success = false, $data = array(), $addResponseDataToBus = true)
231
		{
232
			// Send success/error message to client
233
			$this->addActionData($success == true ? "success" : "error", $data);
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
234
235
			if ($addResponseDataToBus) {
236
				$GLOBALS["bus"]->addData($this->getResponseData());
237
			}
238
		}
239
240
		/**
241
		 * Function will retrieve error details from exception object based on exception type.
242
		 * it should also send type of exception with the data. so client can know which type
243
		 * of exception is generated.
244
		 * @param Object $exception the exception object which is generated.
245
		 * @return Array error data
246
		 */
247
		function errorDetailsFromException($exception)
248
		{
249
			if(!$exception->isHandled) {
250
				if($exception instanceof MAPIException) {
251
					$exception->setHandled();
252
					$mapiError = array(
253
						"type" => ERROR_MAPI,
254
						"info" => array(
255
							"hresult" => $exception->getCode(),
256
							"title" => $exception->getTitle(),
257
							"hresult_name" => get_mapi_error_name($exception->getCode()),
258
							"file" => $exception->getFileLine(),
259
							"display_message" => $exception->getDisplayMessage(),
260
							"details_message" => $exception->getDetailsMessage()
261
						)
262
					);
263
					return $mapiError;
264
265
				} else if($exception instanceof ZarafaException) {
266
					$exception->setHandled();
267
					$grommunioError = array(
268
						"type" => ERROR_ZARAFA,
269
						"info" => array(
270
							"file" => $exception->getFileLine(),
271
							"title" => $exception->getTitle(),
272
							"display_message" => $exception->getDisplayMessage(),
273
							"original_message" => $exception->getMessage()
274
						)
275
					);
276
					return $grommunioError;
277
				}
278
			}
279
280
			return array();
281
		}
282
283
		/**
284
		 * Function which returns an entryid, which is used to register this module. It
285
		 * searches in the class variable $data for a ParentEntryID or an EntryID.
286
		 * @return string an entryid if found, false if entryid not found.
287
		 */
288
		function getEntryID()
289
		{
290
			$entryid = false;
291
			foreach($this->data as $action)
292
			{
293
				if(isset($action["parent_entryid"]) && !empty($action["parent_entryid"])) {
294
					$entryid = $action["parent_entryid"];
295
				} else if(isset($action["entryid"]) && !empty($action["entryid"])) {
296
					$entryid = $action["entryid"];
297
				}
298
			}
299
300
			return $entryid;
301
		}
302
303
		/**
304
		 * Returns all the errors, which occurred.
305
		 * @return array An array of all the errors, which occurred.
306
		 */
307
		function getErrors()
308
		{
309
			return $this->errors;
310
		}
311
312
		/**
313
		 * Returns the response data.
314
		 * @return array An array of the response data. This data is send to the client.
315
		 */
316
		function getData()
317
		{
318
			return $this->responseData;
319
		}
320
321
		/**
322
		 * Sets the action data, which will be executed.
323
		 * @param array $data array of all the actions.
324
		 */
325
		function setData($data)
326
		{
327
			$this->data = $data;
328
		}
329
330
		/**
331
		 * Function which returns MAPI Message Store Object. It
332
		 * searches in the variable $action for a storeid.
333
		 * @param array $action the XML data retrieved from the client
334
		 * @return object MAPI Message Store Object, false if storeid is not found in the $action variable
335
		 */
336
		function getActionStore($action)
337
		{
338
			$store = false;
339
			try {
340
				if(isset($action["store_entryid"]) && !empty($action["store_entryid"])) {
341
					if(is_array($action["store_entryid"])) {
342
						$store = array();
343
						foreach($action["store_entryid"] as $store_id) {
344
							array_push($store, $GLOBALS["mapisession"]->openMessageStore(hex2bin($store_id)));
345
						}
346
					} elseif (ctype_xdigit($action["store_entryid"])) {
347
						$store = $GLOBALS["mapisession"]->openMessageStore(hex2bin($action["store_entryid"]));
348
					}
349
				}
350
			}
351
			catch(Exception $e) {}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
352
353
			return $store;
354
		}
355
356
		/**
357
		 * Function which returns a parent entryid. It
358
		 * searches in the variable $action for a parententryid.
359
		 * @param array $action the XML data retrieved from the client
360
		 * @return object MAPI Message Store Object, false if parententryid is not found in the $action variable
361
		 */
362
		function getActionParentEntryID($action)
363
		{
364
			$parententryid = false;
365
366
			if(isset($action["parent_entryid"]) && !empty($action["parent_entryid"])) {
367
				$parententryid = hex2bin($action["parent_entryid"]);
368
			}
369
370
			return $parententryid;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $parententryid returns the type false|string which is incompatible with the documented return type object.
Loading history...
371
		}
372
373
		/**
374
		 * Function which returns an entryid. It
375
		 * searches in the variable $action for an entryid.
376
		 * @param array $action the XML data retrieved from the client
377
		 * @return object MAPI Message Store Object, false if entryid is not found in the $action variable
378
		 */
379
		function getActionEntryID($action)
380
		{
381
			$entryid = false;
382
383
			if(isset($action["entryid"]) && !empty($action["entryid"])) {
384
				if(is_array($action["entryid"])) {
385
					$entryid = array();
386
					foreach($action["entryid"] as $action_entryid)
387
					{
388
						array_push($entryid, hex2bin($action_entryid));
389
					}
390
				} else {
391
					$entryid = hex2bin($action["entryid"]);
392
				}
393
			}
394
395
			return $entryid;
396
		}
397
398
		/**
399
		 * Helper function which used to get the action data from request.
400
		 *
401
		 * @param array $data list of all actions.
402
		 * @return array $action the json data retrieved from the client
403
		 */
404
		function getActionData($data)
405
		{
406
			$actionData = false;
407
			foreach($data as $actionType => $action)
408
			{
409
				if(isset($actionType)) {
410
					$actionData = $action;
411
				}
412
			}
413
414
			return $actionData;
415
		}
416
417
		/**
418
		 * Function which adds action data to module, so later it can be retrieved to send.
419
		 * @param string $actionType type of action that response data corresponds.
420
		 * @return array data object.
421
		 */
422
		function addActionData($actionType, $data)
423
		{
424
			if(!isset($this->responseData[$actionType])) {
425
				$this->responseData[$actionType] = $data;
426
			}
427
		}
428
429
		/**
430
		 * Function which returns response data that will be sent to client. If there isn't any data added
431
		 * to response data then it will return a blank array.
432
		 * @return object response data.
433
		 */
434
		function getResponseData()
435
		{
436
			if(!empty($this->responseData)) {
437
				return
0 ignored issues
show
Bug Best Practice introduced by
The expression return array($this->getM...> $this->responseData)) returns the type array<string,array<integer,array>> which is incompatible with the documented return type object.
Loading history...
438
					array(
439
						$this->getModuleName() => array(
440
							$this->id => $this->responseData
441
						)
442
					);
443
			} else {
444
				return array();
0 ignored issues
show
Bug Best Practice introduced by
The expression return array() returns the type array which is incompatible with the documented return type object.
Loading history...
445
			}
446
		}
447
448
		/**
449
		 * Function which returns name of the module class.
450
		 * @return string module name.
451
		 */
452
		function getModuleName()
453
		{
454
			return strtolower(get_class($this));
455
		}
456
457
		/**
458
		 * Function which will handle unknown action type for all modules.
459
		 * @param string $actionType action type.
460
		 */
461
		function handleUnknownActionType($actionType)
462
		{
463
			$this->sendFeedback(false,
464
				array(
465
					"type" => ERROR_ZARAFA,
466
						"info" => array(
467
							"display_message" => _("Could not process request data properly."),
468
							"original_message" => sprintf(_("Unknown action type specified - %s"), $actionType)
469
						)
470
				)
471
			);
472
			Log::Write(
473
				LOGLEVEL_ERROR,
474
				"Module::handleUnknownActionType(): ERROR_ZARAFA : " . _("Could not process request data properly."),
475
				sprintf(_("Unknown action type specified - %s"), $actionType)
0 ignored issues
show
Unused Code introduced by
The call to Log::Write() has too many arguments starting with sprintf(_('Unknown actio...ed - %s'), $actionType). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

475
			Log::/** @scrutinizer ignore-call */ 
476
        Write(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
476
			);
477
		}
478
479
		/**
480
		 * Loads sessiondata of the module from state file on disk.
481
		 */
482
		function loadSessionData() {
483
			$this->sessionState = new State('module_sessiondata');
484
			$this->sessionState->open();
485
			$this->sessionData = $this->sessionState->read($this->getModuleName());
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->sessionState->read($this->getModuleName()) of type string is incompatible with the declared type array of property $sessionData.

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..

Loading history...
486
		}
487
488
		/**
489
		 * Saves sessiondata of the module to the state file on disk.
490
		 */
491
		function saveSessionData() {
492
			if ($this->sessionData !== false) {
0 ignored issues
show
introduced by
The condition $this->sessionData !== false is always true.
Loading history...
493
				$this->sessionState->write($this->getModuleName(), $this->sessionData);
494
			}
495
			$this->sessionState->close();
496
		}
497
	}
498
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
499