GroupController   B
last analyzed

Complexity

Total Complexity 44

Size/Duplication

Total Lines 335
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 0%
Metric Value
wmc 44
lcom 1
cbo 5
dl 0
loc 335
ccs 0
cts 233
cp 0
rs 8.3396

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B getGroups() 0 33 4
A addGroup() 0 19 3
B deleteGroup() 0 55 9
C renameGroup() 0 61 9
B addToGroup() 0 53 7
C removeFromGroup() 0 65 9
A displayName() 0 6 2

How to fix   Complexity   

Complex Class

Complex classes like GroupController 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 GroupController, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @author Thomas Tanghus
4
 * @copyright 2013-2014 Thomas Tanghus ([email protected])
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later.
8
 * See the COPYING-README file.
9
 */
10
11
namespace OCA\Contacts\Controller;
12
13
use OCA\Contacts\App,
14
	OCA\Contacts\JSONResponse,
15
	OCA\Contacts\Controller,
16
	OCP\AppFramework\Http,
17
	OCP\ITags,
18
	OCP\IRequest;
19
20
/**
21
 * Controller class for groups/categories
22
 */
23
class GroupController extends Controller {
24
25
	public function __construct($appName, IRequest $request, App $app, ITags $tags) {
26
		parent::__construct($appName, $request, $app);
27
		$this->app = $app;
28
		$this->tags = $tags;
29
	}
30
31
	/**
32
	 * @NoAdminRequired
33
	 */
34
	public function getGroups() {
35
		$tags = $this->tags->getTags();
36
37
		foreach ($tags as &$tag) {
38
			try {
39
				$ids = $this->tags->getIdsForTag($tag['id']);
40
				$tag['contacts'] = $ids;
41
				$tag['displayname'] = $this->displayName($tag);
42
			} catch(\Exception $e) {
43
				\OCP\Util::writeLog('contacts', __METHOD__ . ', ' . $e->getMessage(), \OCP\Util::ERROR);
44
			}
45
		}
46
47
		$favorites = $this->tags->getFavorites();
48
49
		$shares = \OCP\Share::getItemsSharedWith('addressbook', \OCA\Contacts\Share\Addressbook::FORMAT_ADDRESSBOOKS);
50
		$addressbookShare = new \OCA\Contacts\Share\Addressbook();
51
		foreach ($shares as $key => $share) {
52
			$children = $addressbookShare->getChildren($share['id']); // FIXME: This should be cheaper!
53
			$shares[$key]['length'] = count($children);
54
		}
55
56
		$currentUid = \OC::$server->getUserSession()->getUser()->getUId();
57
		$groups = array(
58
			'categories' => $tags,
59
			'favorites' => $favorites,
60
			'shared' => $shares,
61
			'lastgroup' => \OCP\Config::getUserValue($currentUid, 'contacts', 'lastgroup', 'all'),
62
			'sortorder' => \OCP\Config::getUserValue($currentUid, 'contacts', 'groupsort', ''),
63
			);
64
65
		return new JSONResponse($groups);
66
	}
67
68
	/**
69
	 * @NoAdminRequired
70
	 */
71
	public function addGroup() {
72
		$name = $this->request->post['name'];
73
74
		$response = new JSONResponse();
75
76
		if (empty($name)) {
77
			$response->bailOut(App::$l10n->t('No group name given.'));
78
		}
79
80
		$id = $this->tags->add($name);
81
82
		if ($id === false) {
83
			$response->bailOut(App::$l10n->t('Error adding group.'));
84
		} else {
85
			$response->setParams(array('id'=>$id, 'name' => $name));
86
		}
87
88
		return $response;
89
	}
90
91
	/**
92
	 * @NoAdminRequired
93
	 */
94
	public function deleteGroup() {
95
		$id = $this->request->post['id'];
96
		$name = $this->request->post['name'];
97
98
		$response = new JSONResponse();
99
		if (empty($id)) {
100
			$response->bailOut(App::$l10n->t('No group ID given.'));
101
			return $response;
102
		}
103
104
		try {
105
			$ids = $this->tags->getIdsForTag($id);
106
		} catch(\Exception $e) {
107
			$response->setErrorMessage($e->getMessage());
108
			\OCP\Util::writeLog('contacts', __METHOD__.', ' . $e->getMessage(), \OCP\Util::ERROR);
109
			return $response;
110
		}
111
112
		$tagId = $id;
113
		if ($ids !== false) {
114
115
			$backend = $this->app->getBackend('local');
116
117
			foreach ($ids as $id) {
118
				$contact = $backend->getContact(null, $id, array('noCollection' => true));
119
				$obj = \Sabre\VObject\Reader::read(
120
					$contact['carddata'],
121
					\Sabre\VObject\Reader::OPTION_IGNORE_INVALID_LINES
122
				);
123
124
				if ($obj) {
125
126
					if (!$obj->inGroup($name)) {
127
						continue;
128
					}
129
130
					if ($obj->removeFromGroup($name)) {
131
						$backend->updateContact(null, $id, $obj, array('noCollection' => true, 'isBatch' => true));
132
					}
133
134
				} else {
135
					\OCP\Util::writeLog('contacts', __METHOD__.', could not parse card ' . $id, \OCP\Util::DEBUG);
136
				}
137
			}
138
139
		}
140
141
		try {
142
			$this->tags->delete($tagId);
143
		} catch(\Exception $e) {
144
			$response->setErrorMessage($e->getMessage());
145
			\OCP\Util::writeLog('contacts', __METHOD__.', ' . $e->getMessage(), \OCP\Util::ERROR);
146
		}
147
		return $response;
148
	}
149
150
	/**
151
	 * @NoAdminRequired
152
	 */
153
	public function renameGroup() {
154
		$from = $this->request->post['from'];
155
		$to = $this->request->post['to'];
156
157
		$response = new JSONResponse();
158
159
		if (empty($from)) {
160
			$response->bailOut(App::$l10n->t('No group name to rename from given.'));
161
			return $response;
162
		}
163
164
		if (empty($to)) {
165
			$response->bailOut(App::$l10n->t('No group name to rename to given.'));
166
			return $response;
167
		}
168
169
		if (!$this->tags->rename($from, $to)) {
170
			$response->bailOut(App::$l10n->t('Error renaming group.'));
171
			return $response;
172
		}
173
174
		$tag = $this->tags->getTag($from);
175
176
		if (!$tag) {
177
			$response->bailOut(App::$l10n->t('Error renaming group.'));
178
			return $response;
179
		}
180
181
		$response->setParams(array('displayname'=>$this->displayName($tag)));
182
		$ids = $this->tags->getIdsForTag($to);
183
184
		if ($ids !== false) {
185
186
			$backend = $this->app->getBackend('local');
187
188
			foreach ($ids as $id) {
189
				$contact = $backend->getContact(null, $id, array('noCollection' => true));
190
				$obj = \Sabre\VObject\Reader::read(
191
					$contact['carddata'],
192
					\Sabre\VObject\Reader::OPTION_IGNORE_INVALID_LINES
193
				);
194
195
				if ($obj) {
196
197
					if (!isset($obj->CATEGORIES)) {
198
						continue;
199
					}
200
201
					$obj->CATEGORIES->renameGroup($from, $to);
202
					$backend->updateContact(null, $id, $obj, array('noCollection' => true));
203
204
				} else {
205
					\OCP\Util::writeLog('contacts', __METHOD__.', could not parse card ' . $id, \OCP\Util::DEBUG);
206
				}
207
208
			}
209
210
		}
211
212
		return $response;
213
	}
214
215
	/**
216
	 * @NoAdminRequired
217
	 */
218
	public function addToGroup() {
219
		$response = new JSONResponse();
220
		$params = $this->request->urlParams;
221
		$categoryId = $params['categoryId'];
222
		$categoryName = $this->request->post['name'];
223
		$ids = $this->request->post['contactIds'];
224
		$response->debug('request: '.print_r($this->request->post, true));
225
226
		if (empty($categoryId)) {
227
			throw new \Exception(
228
				App::$l10n->t('Group ID missing from request.'),
229
				Http::STATUS_PRECONDITION_FAILED
230
			);
231
		}
232
233
		if (empty($categoryName)) {
234
			throw new \Exception(
235
				App::$l10n->t('Group name missing from request.'),
236
				Http::STATUS_PRECONDITION_FAILED
237
			);
238
		}
239
240
		if (is_null($ids)) {
241
			throw new \Exception(
242
				App::$l10n->t('Contact ID missing from request.'),
243
				Http::STATUS_PRECONDITION_FAILED
244
			);
245
		}
246
247
		$backend = $this->app->getBackend('local');
248
249
		foreach ($ids as $contactId) {
250
251
			$contact = $backend->getContact(null, $contactId, array('noCollection' => true));
252
			$obj = \Sabre\VObject\Reader::read(
253
				$contact['carddata'],
254
				\Sabre\VObject\Reader::OPTION_IGNORE_INVALID_LINES
255
			);
256
257
			if ($obj) {
258
259
				if ($obj->addToGroup($categoryName)) {
260
					$backend->updateContact(null, $contactId, $obj, array('noCollection' => true));
261
				}
262
263
			}
264
265
			$response->debug('contactId: ' . $contactId . ', categoryId: ' . $categoryId);
266
			$this->tags->tagAs($contactId, $categoryId);
267
		}
268
269
		return $response;
270
	}
271
272
	/**
273
	 * @NoAdminRequired
274
	 */
275
	public function removeFromGroup() {
276
		$response = new JSONResponse();
277
		$params = $this->request->urlParams;
278
		$categoryId = $params['categoryId'];
279
		$categoryName = $this->request->post['name'];
280
		$ids = $this->request->post['contactIds'];
281
		//$response->debug('request: '.print_r($this->request->post, true));
282
283
		if (empty($categoryId)) {
284
			throw new \Exception(
285
				App::$l10n->t('Group ID missing from request.'),
286
				Http::STATUS_PRECONDITION_FAILED
287
			);
288
		}
289
290
		if (empty($categoryName)) {
291
			throw new \Exception(
292
				App::$l10n->t('Group name missing from request.'),
293
				Http::STATUS_PRECONDITION_FAILED
294
			);
295
		}
296
297
		if (is_null($ids)) {
298
			throw new \Exception(
299
				App::$l10n->t('Contact ID missing from request.'),
300
				Http::STATUS_PRECONDITION_FAILED
301
			);
302
		}
303
304
		$backend = $this->app->getBackend('local');
305
306
		foreach ($ids as $contactId) {
307
308
			$contact = $backend->getContact(null, $contactId, array('noCollection' => true));
309
310
			if (!$contact) {
311
				$response->debug('Couldn\'t get contact: ' . $contactId);
312
				continue;
313
			}
314
315
			$obj = \Sabre\VObject\Reader::read(
316
				$contact['carddata'],
317
				\Sabre\VObject\Reader::OPTION_IGNORE_INVALID_LINES
318
			);
319
320
			if ($obj) {
321
322
				if (!isset($obj->CATEGORIES)) {
323
					return $response;
324
				}
325
326
				if ($obj->removeFromGroup($categoryName)) {
327
					$backend->updateContact(null, $contactId, $obj, array('noCollection' => true));
328
				}
329
330
			} else {
331
				$response->debug('Error parsing contact: ' . $contactId);
332
			}
333
334
			$response->debug('contactId: ' . $contactId . ', categoryId: ' . $categoryId);
335
			$this->tags->unTag($contactId, $categoryId);
336
		}
337
338
		return $response;
339
	}
340
341
	/**
342
	* Returns a tag's name as it should be displayed.
343
	*
344
	* @param Tag
345
	* @return string
346
	*
347
	* If the tag belongs to the current user, simply returns the tag's name.
348
	* Otherwise, the tag's name is returned with it's owner's name appended
349
	* in parentheses, like "Tag (owner)".
350
	*/
351
	private function displayName($tag) {
352
		if ($tag['owner'] != \OC::$server->getUserSession()->getUser()->getUId()) {
353
			return $tag['name'] . ' ('. $tag['owner'] . ')';
354
		}
355
		return $tag['name'];
356
	}
357
}
358
359