Passed
Push — master ( b80fb7...0c270b )
by René
11:50
created

ApiController::writePoll()   C

Complexity

Conditions 16
Paths 121

Size

Total Lines 101
Code Lines 64

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 272

Importance

Changes 0
Metric Value
cc 16
eloc 64
nc 121
nop 4
dl 0
loc 101
rs 5.3916
c 0
b 0
f 0
ccs 0
cts 77
cp 0
crap 272

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2017 Vinzenz Rosenkranz <[email protected]>
4
 *
5
 * @author René Gieling <[email protected]>
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 *  This program is free software: you can redistribute it and/or modify
10
 *  it under the terms of the GNU Affero General Public License as
11
 *  published by the Free Software Foundation, either version 3 of the
12
 *  License, or (at your option) any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU Affero General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU Affero General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
namespace OCA\Polls\Controller;
25
26
use OCP\AppFramework\Controller;
27
use OCP\AppFramework\Http;
28
use OCP\AppFramework\Http\DataResponse;
29
use OCP\AppFramework\Db\DoesNotExistException;
30
31
use OCP\IGroupManager;
32
use OCP\IRequest;
33
use OCP\IUser;
34
use OCP\IConfig;
35
use OCP\IUserManager;
36
use OCP\Security\ISecureRandom;
37
38
use OCA\Polls\Db\Event;
39
use OCA\Polls\Db\EventMapper;
40
use OCA\Polls\Db\Options;
41
use OCA\Polls\Db\OptionsMapper;
42
use OCA\Polls\Db\Votes;
43
use OCA\Polls\Db\VotesMapper;
44
use OCA\Polls\Db\Comment;
45
use OCA\Polls\Db\CommentMapper;
46
47
48
49
class ApiController extends Controller {
50
51
	private $eventMapper;
52
	private $optionsMapper;
53
	private $votesMapper;
54
	private $commentMapper;
55
	private $systemConfig;
56
57
	/**
58
	 * PageController constructor.
59
	 * @param string $appName
60
	 * @param IRequest $request
61
	 * @param string $userId
62
	 * @param EventMapper $eventMapper
63
	 * @param OptionsMapper $optionsMapper
64
	 * @param VotesMapper $VotesMapper
65
	 * @param CommentMapper $CommentMapper
66
	 */
67
	public function __construct(
68
		$appName,
69
		IConfig $systemConfig,
70
		IGroupManager $groupManager,
71
		IRequest $request,
72
		IUserManager $userManager,
73
		$userId,
74
		EventMapper $eventMapper,
75
		OptionsMapper $optionsMapper,
76
		VotesMapper $VotesMapper,
77
		CommentMapper $CommentMapper
78
	) {
79
		parent::__construct($appName, $request);
80
		$this->userId = $userId;
0 ignored issues
show
Bug Best Practice introduced by
The property userId does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
81
		$this->groupManager = $groupManager;
0 ignored issues
show
Bug Best Practice introduced by
The property groupManager does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
82
		$this->systemConfig = $systemConfig;
83
		$this->userManager = $userManager;
0 ignored issues
show
Bug Best Practice introduced by
The property userManager does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
84
		$this->eventMapper = $eventMapper;
85
		$this->optionsMapper = $optionsMapper;
86
		$this->votesMapper = $VotesMapper;
87
		$this->commentMapper = $CommentMapper;
88
	}
89
90
  	/**
91
	* @NoAdminRequired
92
	* @NoCSRFRequired
93
	* @return DataResponse
94
	*/
95
	public function getSiteUsersAndGroups($query = '', $getGroups = true, $getUsers = true, $skipGroups = array(), $skipUsers = array()) {
96
		$list = array();
97
		$data = array();
98
		if ($getGroups) {
99
			$groups = $this->groupManager->search($query);
100
			foreach ($groups as $group) {
101
				if (!in_array($group->getGID(), $skipGroups)) {
102
					$list[] = [
103
						'id' => $group->getGID(),
104
						'type' => 'group',
105
						'displayName' => $group->getGID(),
106
						'avatarURL' => ''
107
					];
108
				}
109
			}
110
		}
111
		if ($getUsers) {
112
			$users = $this->userManager->searchDisplayName($query);
113
			foreach ($users as $user) {
114
				if (!in_array($user->getUID(), $skipUsers)) {
115
					$list[] = [
116
						'id' => $user->getUID(),
117
						'type' => 'user',
118
						'displayName' => $user->getDisplayName(),
119
						'avatarURL' => '',
120
						'lastLogin' => $user->getLastLogin(),
121
						'cloudId' => $user->getCloudId()
122
					];
123
				}
124
			}
125
		}
126
127
		$data['siteusers'] = $list;
128
		return new DataResponse($data, Http::STATUS_OK);
129
	}
130
  	/**
131
	* @NoAdminRequired
132
	* @NoCSRFRequired
133
	* @return Array
134
	*/	
135
	function convertAccessList($item) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
136
		$split = Array();
137
		if (strpos($item, 'user_') === 0) {
138
			$user = $this->userManager->get(substr($item, 5));
139
			$split = [
140
				'id' => $user->getUID(),
141
				'type' => 'user',
142
				'displayName' => $user->getDisplayName(),
143
				'avatarURL' => ''
144
			];
145
		} elseif (strpos($item, 'group_') === 0) {
146
			$group = substr($item, 6);
147
			$group = $this->groupManager->get($group);
148
			$split = [
149
				'id' => $group->getGID(),
150
				'type' => 'group',
151
				'displayName' => $group->getDisplayName(),
152
				'avatarURL' => '',
153
			];
154
		}
155
		
156
157
		return($split);
158
	}
159
160
  	/**
161
	* @NoAdminRequired
162
	* @NoCSRFRequired
163
	* @PublicPage
164
	* @param string $hash
165
	* @return DataResponse
166
	*/
167
	
168
	public function getPoll($hash) {
169
		if (!\OC::$server->getUserSession()->getUser() instanceof IUser) {
170
			return new DataResponse(null, Http::STATUS_UNAUTHORIZED);
171
		}
172
		
173
		try {
174
			$poll = $this->eventMapper->findByHash($hash);
175
176
			if ($poll->getExpire() === null) {
0 ignored issues
show
introduced by
The condition $poll->getExpire() === null is always false.
Loading history...
177
				$expired = false;
178
				$expiration = false;
179
			} else {
180
				$expired = time() > strtotime($poll->getExpire());
181
				$expiration = true;
182
			}
183
184
			if ($poll->getType() == 0) {
185
				$pollType = 'datePoll'; 
186
			} else {
187
				$pollType = 'textPoll';
188
			};
189
190
			if ($poll->getOwner() !== \OC::$server->getUserSession()->getUser()->getUID()) {
191
				$mode = 'create';
192
			} else {
193
				$mode = 'edit';
194
			}
195
			$accessList = Array();
196
			$accessType = $poll->getAccess();
197
			if (!strpos('|public|hidden|registered', $accessType)) {
198
				$accessList = explode(';',$accessType);
199
				$accessList = array_filter($accessList);
200
				$accessList = array_map(Array($this,'convertAccessList'), $accessList);
201
				$accessType = 'select';
202
			}
203
				
204
			$data = array();
205
			$commentsList = array();
206
			$optionList = array();
207
			$votesList = array();
208
			
209
		} catch (DoesNotExistException $e) {
210
			return new DataResponse($e, Http::STATUS_NOT_FOUND);
211
		};
212
213
214
		try {
215
			$options = $this->optionsMapper->findByPoll($poll->getId());
216
			foreach ($options as $optionElement) {
217
				$optionList[] = [
218
					'id' => $optionElement->getId(),
219
					'text' => $optionElement->getPollOptionText(),
220
					'timestamp' => $optionElement->getTimestamp()
221
				];
222
			};
223
		} catch (DoesNotExistException $e) {
224
			// ignore
225
		};
226
227
		try {
228
			$votes = $this->votesMapper->findByPoll($poll->getId());
229
			foreach ($votes as $voteElement) {
230
				$votesList[] = [
231
					'id' => $voteElement->getId(),
232
					'userId' => $voteElement->getUserId(),
233
					'voteOptionId' => $voteElement->getVoteOptionId(),
234
					'voteOptionText' => $voteElement->getVoteOptionText(),
235
					'voteAnswer' => $voteElement->getVoteAnswer()
236
				];
237
			};
238
		} catch (DoesNotExistException $e) {
239
			// ignore
240
		};
241
242
		try {
243
			$comments = $this->commentMapper->findByPoll($poll->getId());
244
			foreach ($comments as $commentElement) {
245
				$commentsList[] = [
246
					'id' => $commentElement->getId(),
247
					'userId' => $commentElement->getUserId(),
248
					'date' => $commentElement->getDt() . ' UTC',
249
					'comment' => $commentElement->getComment()
250
				];
251
			};
252
		} catch (DoesNotExistException $e) {
253
			// ignore
254
		};
255
	
256
		$data['poll'] = [
257
			'result' => 'found',
258
			'mode' => $mode,
259
			'comments' => $commentsList,
260
			'votes' => $votesList,
261
			'shares' => $accessList,
262
			'event' => [
263
				'id' => $poll->getId(),
264
				'hash' => $hash,
265
				'type' => $pollType,
266
				'title' => $poll->getTitle(),
267
				'description' => $poll->getDescription(),
268
				'owner' => $poll->getOwner(),
269
				'created' => $poll->getCreated(),
270
				'access' => $accessType,
271
				'expiration' => $expiration,
272
				'expired' => $expired,
273
				'expirationDate' => $poll->getExpire(),
274
				'isAnonymous' => $poll->getIsAnonymous(),
275
				'fullAnonymous' => $poll->getFullAnonymous(),
276
				'disallowMaybe' => $poll->getDisallowMaybe()
277
			],
278
			'options' => [
279
				'pollDates' => [],
280
				'pollTexts' => $optionList
281
			]
282
		];
283
284
		return new DataResponse($data, Http::STATUS_OK);
285
	}
286
	
287
	/**
288
	 * @NoAdminRequired
289
	 * @NoCSRFRequired
290
	 * @param string $poll
291
	 * @return DataResponse
292
	 */
293
	public function writePoll($event, $options, $shares, $mode) {
294
		$user = \OC::$server->getUserSession()->getUser();
295
296
		if (!$user instanceof IUser) {
297
			return new DataResponse(null, Http::STATUS_UNAUTHORIZED);
298
		}
299
		$userId = \OC::$server->getUserSession()->getUser()->getUID();
300
301
		$newEvent = new Event();
302
303
		// Set the configuration options entered by the user
304
		$newEvent->setTitle($event['title']);
305
		$newEvent->setDescription($event['description']);
306
307
		$newEvent->setType($event['type']);
308
		$newEvent->setIsAnonymous($event['isAnonymous']);
309
		$newEvent->setFullAnonymous($event['fullAnonymous']);
310
		$newEvent->setDisallowMaybe($event['disallowMaybe']);
311
	
312
		if ($event['access'] === 'select') {
313
			$shareAccess = '';
314
			foreach ($shares as $shareElement) {
315
				if ($shareElement['type'] === 'user') {
316
					$shareAccess = $shareAccess . 'user_' . $shareElement['id'] . ';';
317
				} elseif ($shareElement['type'] === 'group') {
318
					$shareAccess = $shareAccess . 'group_' . $shareElement['id'] . ';';
319
				}
320
			}
321
			$newEvent->setAccess(rtrim($shareAccess, ';'));
322
		} else {
323
			$newEvent->setAccess($event['access']);
324
		}
325
326
		if ($event['expiration']) {
327
			$newEvent->setExpire($event['expirationDate']);
328
		} else {
329
			$newEvent->setExpire(null);
330
		}
331
		
332
		if ($event['type'] === 'datePoll') {
333
			$newEvent->setType(0);
334
		} elseif ($event['type'] === 'textPoll') {
335
			$newEvent->setType(1);
336
		}
337
338
		if ($mode === 'edit') {
339
			// Edit existing poll
340
			$oldPoll = $this->eventMapper->findByHash($event['hash']);
341
342
			// Check if current user is allowed to edit existing poll
343
			if ($oldPoll->getOwner() !== $userId) {
344
				// If current user is not owner of existing poll deny access
345
				return new DataResponse(null, Http::STATUS_UNAUTHORIZED);
346
			} 
347
348
			// else take owner, hash and id of existing poll
349
			$newEvent->setOwner($oldPoll->getOwner());
350
			$newEvent->setHash($oldPoll->getHash());
351
			$newEvent->setId($oldPoll->getId());
352
			$this->eventMapper->update($newEvent);
353
			$this->optionsMapper->deleteByPoll($newEvent->getId());
354
					
355
		} elseif ($mode === 'create') {
356
			// Create new poll
357
			// Define current user as owner, set new creation date and create a new hash
358
			$newEvent->setOwner($userId);
359
			$newEvent->setCreated(date('Y-m-d H:i:s'));
360
			$newEvent->setHash(\OC::$server->getSecureRandom()->generate(
361
				16,
362
				ISecureRandom::CHAR_DIGITS .
363
				ISecureRandom::CHAR_LOWER .
364
				ISecureRandom::CHAR_UPPER
365
			));
366
			$newEvent = $this->eventMapper->insert($newEvent);
367
		}
368
		
369
		// Update options
370
		if ($event['type'] === 'datePoll') {
371
			foreach ($options['pollDates'] as $optionElement) {
372
				$newOption = new Options();
373
				
374
				$newOption->setPollId($newEvent->getId());
375
				$newOption->setPollOptionText(date('Y-m-d H:i:s', $optionElement['timestamp']));
376
				$newOption->setTimestamp($optionElement['timestamp']);
377
				
378
				$this->optionsMapper->insert($newOption);
379
			}
380
		} elseif ($event['type'] === "textPoll") {
381
			foreach ($options['pollTexts'] as $optionElement) {
382
				$newOption = new Options();
383
				
384
				$newOption->setPollId($newEvent->getId());
385
				$newOption->setpollOptionText(htmlspecialchars($optionElement['text']));
386
				
387
				$this->optionsMapper->insert($newOption);
388
			}
389
		}
390
		return new DataResponse(array(
391
			'id' => $newEvent->getId(),
392
			'hash' => $newEvent->getHash()
393
		), Http::STATUS_OK);
394
395
	}
396
397
	private function getVendor() {
398
		// this should really be a JSON file
399
		require \OC::$SERVERROOT . '/version.php';
400
		/** @var string $vendor */
401
		return (string) $vendor;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $vendor seems to be never defined.
Loading history...
402
	}
403
404
	/**
405
	 * @NoAdminRequired
406
	 * @NoCSRFRequired
407
	 * @return DataResponse
408
	 */
409
	public function getSystem() {
410
		$userId = \OC::$server->getUserSession()->getUser()->getUID();
411
		$data['system'] = [
0 ignored issues
show
Comprehensibility Best Practice introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.
Loading history...
412
			'versionArray' => \OCP\Util::getVersion(),
413
			'version' => implode('.', \OCP\Util::getVersion()),
414
			'vendor' => $this->getVendor(),
415
			'language' => $this->systemConfig->getUserValue($userId, 'core', 'lang')
416
		];
417
		return new DataResponse($data, Http::STATUS_OK);
418
	}
419
}
420