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

RestoreItemsListModule   B

Complexity

Total Complexity 51

Size/Duplication

Total Lines 391
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 161
dl 0
loc 391
rs 7.92
c 0
b 0
f 0
wmc 51

12 Methods

Rating   Name   Duplication   Size   Complexity  
A deleteItems() 0 13 3
A itemList() 0 26 4
C execute() 0 57 14
A restoreAllItems() 0 24 2
A __construct() 0 5 1
A restoreFolder() 0 26 3
A deleteAll() 0 31 6
A restoreAllFolders() 0 32 5
A restoreAll() 0 16 4
A deleteFolder() 0 14 3
A notifyParentFolder() 0 21 3
A restoreItems() 0 25 3

How to fix   Complexity   

Complex Class

Complex classes like RestoreItemsListModule often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use RestoreItemsListModule, and based on these observations, apply Extract Interface, too.

1
<?php
2
	/**
3
	 * RestoreItemsList Module
4
	 */
5
	class RestoreItemsListModule extends ListModule
6
	{
7
		/**
8
		 * Constructor
9
		 * @param int $id unique id.
10
		 * @param array $data list of all actions.
11
		 */
12
		function __construct($id, $data)
13
		{
14
			parent::__construct($id, $data);
15
16
			$this->properties = $GLOBALS['properties']->getRestoreItemListProperties();
17
18
		}
19
20
		/**
21
		 * Executes all the actions in the $data variable.
22
		 * @return boolean true on success of false on failure.
23
		 */
24
		function execute()
25
		{
26
			foreach($this->data as $actionType => $action)
27
			{
28
				if(isset($actionType)) {
29
					try {
30
						$store = $this->getActionStore($action);
31
						$parententryid = $this->getActionParentEntryID($action);
32
						$folderentryid = $this->getActionEntryID($action);
33
34
						switch($actionType) {
35
							case "list":
36
							case "updatelist":
37
								if (isset($action["message_action"], $action["message_action"]["action_type"])) {
38
									$subActionType = $action["message_action"]["action_type"];
39
									switch ($subActionType) {
40
										case "restoreAll":
41
											$this->restoreAll($store, $folderentryid, $action);
42
											break;
43
										case "deleteAll":
44
											$this->deleteAll($store, $folderentryid, $action);
45
											break;
46
									}
47
								} else {
48
									$this->itemList($store, $folderentryid, $action);
49
								}
50
								break;
51
							case "delete":
52
								$itemType = $action["message_action"]["action_type"];
53
54
								switch($itemType) {
55
									case "restorefolder" :
56
										$this->restoreFolder($store, $parententryid, $folderentryid);
57
										break;
58
59
									case "deletefolder" :
60
										$this->deleteFolder($store, $parententryid, $action);
61
										break;
62
63
									case "restoremessage" :
64
										$this->restoreItems($store, $parententryid, $action);
65
										break;
66
67
									case "deletemessage" :
68
										$this->deleteItems($store, $parententryid, $action);
69
										break;
70
71
									default:
72
									$this->handleUnknownActionType($itemType);
73
								}
74
								break;
75
76
							default:
77
								$this->handleUnknownActionType($actionType);
78
						}
79
					} catch (MAPIException $e) {
80
						$this->processException($e, $actionType);
81
					}
82
				}
83
			}
84
		}
85
86
		/**
87
		 * Function which permanently delete all folder or message items.
88
		 *
89
		 * @param {object} $store store object
0 ignored issues
show
Documentation Bug introduced by
The doc comment {object} at position 0 could not be parsed: Unknown type name '{' at position 0 in {object}.
Loading history...
90
		 * @param {binary} $folderentryid entry id of that particular folder.
91
		 * @param object $action request data.
92
		 */
93
		function deleteAll($store, $folderentryid, $action)
94
		{
95
			$folder = mapi_msgstore_openentry($store, $folderentryid);
96
97
			// delete all folders.
98
			if (isset($action["itemType"]) && $action["itemType"] == "folder") {
99
				$table = mapi_folder_gethierarchytable($folder, MAPI_DEFERRED_ERRORS | SHOW_SOFT_DELETES);
100
				$items = mapi_table_queryallrows($table, array(PR_ENTRYID));
101
				$restoreItems = array();
102
				foreach ($items as $item) {
103
					array_push($restoreItems, $item[PR_ENTRYID]);
104
				}
105
106
				foreach ($restoreItems as $restoreItem) {
107
					mapi_folder_deletefolder($folder, $restoreItem, DEL_FOLDERS | DEL_MESSAGES | DELETE_HARD_DELETE);
108
				}
109
			} else {
110
				// delete all messages
111
				$table = mapi_folder_getcontentstable($folder, MAPI_DEFERRED_ERRORS | SHOW_SOFT_DELETES);
112
				$items = mapi_table_queryallrows($table, array(PR_ENTRYID));
113
114
				$restoreItems = array();
115
				foreach ($items as $item) {
116
					array_push($restoreItems, $item[PR_ENTRYID]);
117
				}
118
119
				mapi_folder_deletemessages($folder, $restoreItems , DELETE_HARD_DELETE);
120
			}
121
122
			$this->addActionData("list", array("item" => array()));
123
			$GLOBALS["bus"]->addData($this->getResponseData());
124
		}
125
126
		/**
127
		 * Function used to restore all folders.
128
		 *
129
		 * @param {object} $store store object.
0 ignored issues
show
Documentation Bug introduced by
The doc comment {object} at position 0 could not be parsed: Unknown type name '{' at position 0 in {object}.
Loading history...
130
		 * @param {object} $folder folder data which needs to restore.
131
		 * @throws MAPIException
132
		 */
133
		function restoreAllFolders($store, $folder)
134
		{
135
			$table = mapi_folder_gethierarchytable($folder, MAPI_DEFERRED_ERRORS | SHOW_SOFT_DELETES);
136
			$items = mapi_table_queryallrows($table, array(PR_ENTRYID));
137
			$restoreItems = array();
138
			foreach ($items as $item) {
139
				array_push($restoreItems, $item[PR_ENTRYID]);
140
			}
141
142
			foreach ($restoreItems as $restoreItem) {
143
				try {
144
					/*
145
					 * we should first try to copy folder and if it returns MAPI_E_COLLISION then
146
					 * only we should check for the conflicting folder names and generate a new name
147
					 * and restore folder with the generated name.
148
					 */
149
					mapi_folder_copyfolder($folder, $restoreItem, $folder, null, FOLDER_MOVE);
150
				} catch (MAPIException $e) {
151
					if($e->getCode() == MAPI_E_COLLISION) {
152
						$folder = mapi_msgstore_openentry($store, $restoreItem, SHOW_SOFT_DELETES);
153
						$folderNameProps = mapi_getprops($folder, array(PR_DISPLAY_NAME));
154
						$foldername = $GLOBALS["operations"]->checkFolderNameConflict($store, $folder, $folderNameProps[PR_DISPLAY_NAME]);
155
						mapi_folder_copyfolder($folder, $restoreItem, $folder, $foldername, FOLDER_MOVE);
156
					} else {
157
						// all other errors should be propagated to higher level exception handlers
158
						throw $e;
159
					}
160
				}
161
			}
162
163
			// Notify the parent folder.
164
			$this->notifyParentFolder($store, $folder, $folder);
165
		}
166
167
		/**
168
		 * Function which used to restore and message for give folder.
169
		 *
170
		 * @param {object} $folder the content of this folder is going to restored.
0 ignored issues
show
Documentation Bug introduced by
The doc comment {object} at position 0 could not be parsed: Unknown type name '{' at position 0 in {object}.
Loading history...
171
		 */
172
		function restoreAllItems($folder)
173
		{
174
			$table = mapi_folder_getcontentstable($folder, MAPI_DEFERRED_ERRORS | SHOW_SOFT_DELETES);
175
			$items = mapi_table_queryallrows($table, array(PR_ENTRYID));
176
177
			$restoreItems = array();
178
			foreach ($items as $item) {
179
				array_push($restoreItems, $item[PR_ENTRYID]);
180
			}
181
182
			mapi_folder_copymessages($folder, $restoreItems, $folder, MESSAGE_MOVE);
183
184
			// as after moving the message/s the entryid gets changed, so need to notify about the folder
185
			// so that we can update the folder on parent page.
186
			$folderProps = mapi_getprops($folder, array(PR_STORE_ENTRYID, PR_ENTRYID));
187
188
			/* when we restore any message from soft deleted system then we are actually copying the item, so at that time entryid of
189
			 * that particular item gets changed, so to notify client about changes we need to
190
			 * notify parent folder where we have restored the message
191
			 */
192
			$props[PR_PARENT_ENTRYID] = $folderProps[PR_ENTRYID];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$props was never initialized. Although not strictly required by PHP, it is generally a good practice to add $props = array(); before regardless.
Loading history...
193
			$props[PR_STORE_ENTRYID] = $folderProps[PR_STORE_ENTRYID];
194
195
			$GLOBALS["bus"]->notify(bin2hex($folderProps[PR_ENTRYID]), TABLE_SAVE, $props);
196
		}
197
198
		/**
199
		 * Function restored restore all folder or message based on give itemType.
200
		 *
201
		 * @param {object} $store store object
0 ignored issues
show
Documentation Bug introduced by
The doc comment {object} at position 0 could not be parsed: Unknown type name '{' at position 0 in {object}.
Loading history...
202
		 * @param {binary} $folderentryid entry id of that particular folder.
203
		 * @param object $action request data.
204
		 * @throws MAPIException
205
		 */
206
		function restoreAll($store, $folderentryid, $action)
207
		{
208
			$folder = mapi_msgstore_openentry($store, $folderentryid);
209
210
			if (isset($action["itemType"]) && $action["itemType"] == "folder") {
211
				try {
212
					$this->restoreAllFolders($store, $folder);
213
				} catch (MAPIException $e) {
214
					throw $e;
215
				}
216
			} else {
217
				$this->restoreAllItems($folder);
218
			}
219
220
			$this->addActionData("list", array("item" => array()));
221
			$GLOBALS["bus"]->addData($this->getResponseData());
222
		}
223
224
		/**
225
		 * Function to retrieve the list of messages or folder of particular folder
226
		 * @param object $store store object.
227
		 * @param binary $entryid entry id of that particular folder.
0 ignored issues
show
Bug introduced by
The type binary 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...
228
		 * @param object $action request data.
229
		 */
230
		function itemList($store, $entryid, $action)
231
		{
232
			// Restriction
233
			$this->parseRestriction($action);
234
235
			//set the this->$sort variable.
236
			$this->parseSortOrder($action);
237
238
			if(isset($action['restriction']['limit'])){
239
				$limit = $action['restriction']['limit'];
240
			} else {
241
				$limit = $GLOBALS['settings']->get('zarafa/v1/main/page_size', 50);
242
			}
243
244
			$folder = mapi_msgstore_openentry($store, $entryid);
245
246
			if (isset($action["itemType"]) && $action["itemType"] == "folder") {
247
				$table = mapi_folder_gethierarchytable($folder, MAPI_DEFERRED_ERRORS | SHOW_SOFT_DELETES);
248
			} else {
249
				$table = mapi_folder_getcontentstable($folder, MAPI_DEFERRED_ERRORS | SHOW_SOFT_DELETES);
250
			}
251
252
			$data = $GLOBALS["operations"]->getTableContent($table, $this->properties, $this->sort, $this->start, $limit, $this->restriction);
253
254
			$this->addActionData("list", $data);
255
			$GLOBALS["bus"]->addData($this->getResponseData());
256
		}
257
258
		/**
259
		 * Function to delete selected items of particular folder
260
		 * @param object $store store object.
261
		 * @param binary $parententryid entry id of the folder which contain particular item to be deleted.
262
		 * @param object $items request data.
263
		 */
264
		function deleteItems($store, $parententryid, $items){
265
266
			if(is_assoc_array($items)) {
0 ignored issues
show
Bug introduced by
$items of type object is incompatible with the type array expected by parameter $data of is_assoc_array(). ( Ignorable by Annotation )

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

266
			if(is_assoc_array(/** @scrutinizer ignore-type */ $items)) {
Loading history...
267
				// wrap single item in an array
268
				$items = array($items);
269
			}
270
271
			$sfolder = mapi_msgstore_openentry($store, $parententryid);
272
273
			for($index = 0, $len = count($items); $index < $len; $index++) {
274
				mapi_folder_deletemessages($sfolder, array(hex2bin($items[$index]['entryid'])), DELETE_HARD_DELETE);
275
			}
276
			$this->sendFeedback(true);
277
		}
278
279
		/**
280
		 * Function to restore message present into the selected folder
281
		 * @param object $store store object.
282
		 * @param binary $parententryid entry id of the folder which contain particular item to be restored.
283
		 * @param object $items request data.
284
		 */
285
		function restoreItems($store, $parententryid, $items){
286
287
			if(is_assoc_array($items)) {
0 ignored issues
show
Bug introduced by
$items of type object is incompatible with the type array expected by parameter $data of is_assoc_array(). ( Ignorable by Annotation )

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

287
			if(is_assoc_array(/** @scrutinizer ignore-type */ $items)) {
Loading history...
288
				// wrap single item in an array
289
				$items = array($items);
290
			}
291
292
			$sfolder = mapi_msgstore_openentry($store, $parententryid);
293
294
			for($index = 0, $len = count($items); $index < $len; $index++) {
295
				mapi_folder_copymessages($sfolder, array(hex2bin($items[$index]['entryid'])), $sfolder, MESSAGE_MOVE);
296
			}
297
298
			// as after moving the message/s the entryid gets changed, so need to notify about the folder
299
			// so that we can update the folder on parent page.
300
			$folderProps = mapi_getprops($sfolder, array(PR_STORE_ENTRYID, PR_ENTRYID));
301
302
			/* when we restore any message from soft deleted system then we are actually copying the item, so at that time entryid of
303
			 * that particular item gets changed, so to notify client about changes we need to 
304
			 * notify parent folder where we have restored the message
305
			 */
306
			$props[PR_PARENT_ENTRYID] = $folderProps[PR_ENTRYID];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$props was never initialized. Although not strictly required by PHP, it is generally a good practice to add $props = array(); before regardless.
Loading history...
307
			$props[PR_STORE_ENTRYID] = $folderProps[PR_STORE_ENTRYID];
308
			$GLOBALS["bus"]->notify(bin2hex($folderProps[PR_ENTRYID]), TABLE_SAVE, $props);
309
			$this->sendFeedback(true);
310
		}
311
312
		/**
313
		 * Function to delete selected folders
314
		 * @param object $store store object.
315
		 * @param binary $parententryid entry id of the folder which contain particular folder to be deleted.
316
		 * @param object $folders request data.
317
		 */
318
		function deleteFolder($store, $parententryid, $folders){
319
320
			if(is_assoc_array($folders)) {
0 ignored issues
show
Bug introduced by
$folders of type object is incompatible with the type array expected by parameter $data of is_assoc_array(). ( Ignorable by Annotation )

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

320
			if(is_assoc_array(/** @scrutinizer ignore-type */ $folders)) {
Loading history...
321
				// wrap single folder in an array
322
				$folders = array($folders);
323
			}
324
325
			$sfolder = mapi_msgstore_openentry($store, $parententryid);
326
327
			for($index = 0, $len = count($folders); $index < $len; $index++) {
328
				mapi_folder_deletefolder($sfolder, hex2bin($folders[$index]['entryid']), DEL_FOLDERS | DEL_MESSAGES | DELETE_HARD_DELETE);
329
			}
330
331
			$this->sendFeedback(true);
332
		}
333
334
		/**
335
		 * Function to restore soft deleted folder of particular folder
336
		 * @param object $store store object.
337
		 * @param binary $parententryid entry id of the folder which contain particular folder to be restored.
338
		 * @param binary $folderentryid entry id of the folder to be restored.
339
		 */
340
		function restoreFolder($store, $parententryid, $folderentryid)
341
		{
342
			$sfolder = mapi_msgstore_openentry($store, $parententryid);
343
			try {
344
				/*
345
				 * we should first try to copy folder and if it returns MAPI_E_COLLISION then
346
				 * only we should check for the conflicting folder names and generate a new name
347
				 * and restore folder with the generated name.
348
				 */
349
				mapi_folder_copyfolder($sfolder, $folderentryid, $sfolder, null, FOLDER_MOVE);
350
			} catch (MAPIException $e) {
351
				if($e->getCode() == MAPI_E_COLLISION) {
352
					$folder = mapi_msgstore_openentry($store, $folderentryid, SHOW_SOFT_DELETES);
353
					$folderNameProps = mapi_getprops($folder, array(PR_DISPLAY_NAME));
354
					$foldername = $GLOBALS["operations"]->checkFolderNameConflict($store, $sfolder, $folderNameProps[PR_DISPLAY_NAME]);
355
					mapi_folder_copyfolder($sfolder, $folderentryid, $sfolder, $foldername, FOLDER_MOVE);
356
				} else {
357
					// all other errors should be propagated to higher level exception handlers
358
					throw $e;
359
				}
360
			}
361
362
			// notify the parent folder
363
			$parentFolder = mapi_msgstore_openentry($store, $parententryid);
364
			$this->notifyParentFolder($store,$sfolder, $parentFolder);
365
			$this->sendFeedback(true);
366
		}
367
368
		/**
369
		 * Notify the parent folder about restoration.
370
		 *
371
		 * @param object $store store object.
372
		 * @param object $folder mapi folder which contain particular folder to be restored.
373
		 * @param object $parentFolder mapi folder which is going to notify.
374
		 */
375
		function notifyParentFolder($store, $folder, $parentFolder)
376
		{
377
			/* when we restore any folder from soft deleted system then we are actually copying the folder, so at that time entryid of
378
			 * folder gets changed and we don't have notification system to get new entryid, so to notify client about changes we need to
379
			 * notify all subfolders of parent folder where we have restored the folder
380
			 */
381
			$hierarchyTable = mapi_folder_gethierarchytable($folder, CONVENIENT_DEPTH | MAPI_DEFERRED_ERRORS);
382
			mapi_table_sort($hierarchyTable, array(PR_DISPLAY_NAME => TABLE_SORT_ASCEND), TBL_BATCH);
383
384
			$subfolders = mapi_table_queryallrows($hierarchyTable, array(PR_ENTRYID));
385
386
			if (is_array($subfolders)) {
387
				foreach($subfolders as $subfolder) {
388
					$folderObject = mapi_msgstore_openentry($store, $subfolder[PR_ENTRYID]);
389
					$folderProps = mapi_getprops($folderObject, array(PR_ENTRYID, PR_STORE_ENTRYID));
390
					$GLOBALS["bus"]->notify(bin2hex($subfolder[PR_ENTRYID]), OBJECT_SAVE, $folderProps);
391
				}
392
			}
393
394
			$folderProps = mapi_getprops($parentFolder, array(PR_ENTRYID, PR_STORE_ENTRYID));
395
			$GLOBALS["bus"]->notify(bin2hex($folderProps[PR_ENTRYID]), OBJECT_SAVE, $folderProps);
396
		}
397
	}
398
?>
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...
399