Completed
Pull Request — master (#1038)
by René
06:20
created

OptionService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
c 1
b 0
f 0
dl 0
loc 14
ccs 0
cts 14
cp 0
rs 10
cc 1
nc 1
nop 6
crap 2
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\Service;
25
26
use DateTime;
27
use OCP\AppFramework\Db\DoesNotExistException;
28
use OCA\Polls\Exceptions\NotAuthorizedException;
29
use OCA\Polls\Exceptions\BadRequestException;
30
use OCA\Polls\Exceptions\DuplicateEntryException;
31
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
0 ignored issues
show
Bug introduced by
The type Doctrine\DBAL\Exception\...raintViolationException 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...
32
33
use OCA\Polls\Db\OptionMapper;
34
use OCA\Polls\Db\Option;
35
use OCA\Polls\Db\PollMapper;
36
use OCA\Polls\Db\Poll;
37
use OCA\Polls\Model\Acl;
38
39
class OptionService {
40
41
	/** @var OptionMapper */
42
	private $optionMapper;
43
44
	/** @var Option */
45
	private $option;
46
47
	/** @var PollMapper */
48
	private $pollMapper;
49
50
	/** @var Poll */
51
	private $poll;
52
53
	/** @var LogService */
54
	private $logService;
55
56
	/** @var Acl */
57
	private $acl;
58
59
	/**
60
	 * OptionService constructor.
61
	 * @param OptionMapper $optionMapper
62
	 * @param Option $option
63
	 * @param PollMapper $pollMapper
64
	 * @param Poll $poll
65
	 * @param LogService $logService
66
	 * @param Acl $acl
67
	 */
68
69
	public function __construct(
70
		OptionMapper $optionMapper,
71
		Option $option,
72
		PollMapper $pollMapper,
73
		Poll $poll,
74
		LogService $logService,
75
		Acl $acl
76
	) {
77
		$this->optionMapper = $optionMapper;
78
		$this->option = $option;
79
		$this->pollMapper = $pollMapper;
80
		$this->poll = $poll;
81
		$this->logService = $logService;
82
		$this->acl = $acl;
83
	}
84
85
	/**
86
	 * Get all options of given poll
87
	 * @NoAdminRequired
88
	 * @param int $pollId
89
	 * @param string $token
90
	 * @return array Array of Option objects
91
	 * @throws NotAuthorizedException
92
	 */
93
	public function list($pollId = 0, $token = '') {
94
		$acl = $this->acl->set($pollId, $token);
95
96
		if (!$acl->getAllowView()) {
97
			throw new NotAuthorizedException;
98
		}
99
100
		try {
101
			return $this->optionMapper->findByPoll($acl->getPollId());
102
		} catch (DoesNotExistException $e) {
103
			return [];
104
		}
105
	}
106
107
	/**
108
	 * Get option
109
	 * @NoAdminRequired
110
	 * @param int $optionId
111
	 * @return Option
112
	 * @throws NotAuthorizedException
113
	 */
114
	public function get($optionId) {
115
		if (!$this->acl->set($this->optionMapper->find($optionId)->getPollId())->getAllowView()) {
116
			throw new NotAuthorizedException;
117
		}
118
119
		return $this->optionMapper->find($optionId);
120
	}
121
122
123
	/**
124
	 * Add a new option
125
	 * @NoAdminRequired
126
	 * @param int $pollId
127
	 * @param int $timestamp
128
	 * @param string $pollOptionText
129
	 * @return Option
130
	 * @throws NotAuthorizedException
131
	 */
132
	public function add($pollId, $timestamp = 0, $pollOptionText = '') {
133
		$this->poll = $this->pollMapper->find($pollId);
134
		if (!$this->acl->set($pollId)->getAllowEdit()) {
135
			throw new NotAuthorizedException;
136
		}
137
138
		$this->option = new Option();
139
		$this->option->setPollId($pollId);
140
		$this->setOption($timestamp, $pollOptionText, 0);
141
142
		try {
143
			return $this->optionMapper->insert($this->option);
144
		} catch (UniqueConstraintViolationException $e) {
145
			throw new DuplicateEntryException('This option already exists');
146
		}
147
	}
148
149
	/**
150
	 * Update option
151
	 * @NoAdminRequired
152
	 * @param int $optionId
153
	 * @param int $timestamp
154
	 * @param string $pollOptionText
155
	 * @param int $order
156
	 * @return Option
157
	 * @throws NotAuthorizedException
158
	 */
159
	public function update($optionId, $timestamp = 0, $pollOptionText = '', $order = 0) {
160
		$this->option = $this->optionMapper->find($optionId);
161
		$this->poll = $this->pollMapper->find($this->option->getPollId());
162
163
		if (!$this->acl->set($this->option->getPollId())->getAllowEdit()) {
164
			throw new NotAuthorizedException;
165
		}
166
167
		$this->setOption($timestamp, $pollOptionText, $order);
168
169
		return $this->optionMapper->update($this->option);
170
	}
171
172
	/**
173
	 * Delete option
174
	 * @NoAdminRequired
175
	 * @param int $optionId
176
	 * @return Option deleted Option
177
	 * @throws NotAuthorizedException
178
	 */
179
	public function delete($optionId) {
180
		$this->option = $this->optionMapper->find($optionId);
181
182
		if (!$this->acl->set($this->option->getPollId())->getAllowEdit()) {
183
			throw new NotAuthorizedException;
184
		}
185
186
		$this->optionMapper->delete($this->option);
187
188
		return $this->option;
189
	}
190
191
	/**
192
	 * Switch optoin confirmation
193
	 * @NoAdminRequired
194
	 * @param int $optionId
195
	 * @return Option confirmed Option
196
	 * @throws NotAuthorizedException
197
	 */
198
	public function confirm($optionId) {
199
		$this->option = $this->optionMapper->find($optionId);
200
201
		if (!$this->acl->set($this->option->getPollId())->getAllowEdit()) {
202
			throw new NotAuthorizedException;
203
		}
204
205
		if ($this->option->getConfirmed()) {
206
			$this->option->setConfirmed(0);
207
		} else {
208
			$this->option->setConfirmed(time());
209
		}
210
211
		return $this->optionMapper->update($this->option);
212
	}
213
214
	/**
215
	 * Make a sequence of date poll options
216
	 * @NoAdminRequired
217
	 * @param int $optionId
218
	 * @param int $step
219
	 * @param string $unit
220
	 * @param int $amount
221
	 * @return array Array of Option objects
222
	 * @throws NotAuthorizedException
223
	 */
224
	public function sequence($optionId, $step, $unit, $amount) {
225
		$baseDate = new DateTime;
226
		$origin = $this->optionMapper->find($optionId);
227
228
		if (!$this->acl->set($origin->getPollId())->getAllowEdit()) {
229
			throw new NotAuthorizedException;
230
		}
231
232
		if ($step === 0) {
233
			return $this->optionMapper->findByPoll($origin->getPollId());
234
		}
235
236
		$baseDate->setTimestamp($origin->getTimestamp());
237
238
		for ($i = 0; $i < $amount; $i++) {
239
			$this->option = new Option();
240
			$this->option->setPollId($origin->getPollId());
241
			$this->option->setConfirmed(0);
242
			$this->option->setTimestamp($baseDate->modify($step . ' ' . $unit)->getTimestamp());
243
			$this->option->setPollOptionText($baseDate->format('c'));
244
			$this->option->setOrder($baseDate->getTimestamp());
245
			try {
246
				$this->optionMapper->insert($this->option);
247
			} catch (UniqueConstraintViolationException $e) {
248
				\OC::$server->getLogger()->warning('skip adding ' . $baseDate->format('c') . 'for pollId' . $origin->getPollId() . '. Option alredy exists.');
249
			}
250
		}
251
		return $this->optionMapper->findByPoll($origin->getPollId());
252
	}
253
254
	/**
255
	 * Copy options from $fromPoll to $toPoll
256
	 * @NoAdminRequired
257
	 * @param int $fromPollId
258
	 * @param int $toPollId
259
	 * @return array Array of Option objects
260
	 * @throws NotAuthorizedException
261
	 */
262
	public function clone($fromPollId, $toPollId) {
263
		if (!$this->acl->set($fromPollId)->getAllowView()) {
264
			throw new NotAuthorizedException;
265
		}
266
267
		foreach ($this->optionMapper->findByPoll($fromPollId) as $origin) {
268
			$option = new Option();
269
			$option->setPollId($toPollId);
270
			$option->setConfirmed(0);
271
			$option->setPollOptionText($origin->getPollOptionText());
272
			$option->setTimestamp($origin->getTimestamp());
273
			$option->setOrder($origin->getOrder());
274
			$this->optionMapper->insert($option);
275
		}
276
277
		return $this->optionMapper->findByPoll($toPollId);
278
	}
279
280
	/**
281
	 * Reorder options with the order specified by $options
282
	 * @NoAdminRequired
283
	 * @param int $pollId
284
	 * @param array $options - Array of options
285
	 * @return array Array of Option objects
286
	 * @throws NotAuthorizedException
287
	 * @throws BadRequestException
288
	 */
289
	public function reorder($pollId, $options) {
290
		$this->poll = $this->pollMapper->find($pollId);
291
292
		if (!$this->acl->set($pollId)->getAllowEdit()) {
293
			throw new NotAuthorizedException;
294
		}
295
296
		if ($this->poll->getType() === 'datePoll') {
297
			throw new BadRequestException("Not allowed in date polls");
298
		}
299
300
		$i = 0;
301
		foreach ($options as $option) {
302
			$this->option = $this->optionMapper->find($option['id']);
303
			if ($pollId === intval($this->option->getPollId())) {
304
				$this->option->setOrder(++$i);
305
				$this->optionMapper->update($this->option);
306
			}
307
		}
308
309
		return $this->optionMapper->findByPoll($pollId);
310
	}
311
312
	/**
313
	 * Change order for $optionId and reorder the options
314
	 * @NoAdminRequired
315
	 * @param int $optionId
316
	 * @param int $newOrder
317
	 * @return array Array of Option objects
318
	 * @throws NotAuthorizedException
319
	 * @throws BadRequestException
320
	 */
321
	public function setOrder($optionId, $newOrder) {
322
		$this->option = $this->optionMapper->find($optionId);
323
		$pollId = $this->option->getPollId();
324
		$this->poll = $this->pollMapper->find($pollId);
325
326
		if (!$this->acl->set($pollId)->getAllowEdit()) {
327
			throw new NotAuthorizedException;
328
		}
329
330
		if ($this->poll->getType() === 'datePoll') {
331
			throw new BadRequestException("Not allowed in date polls");
332
		}
333
334
		if ($newOrder < 1) {
335
			$newOrder = 1;
336
		} elseif ($newOrder > $this->getHighestOrder($pollId)) {
337
			$newOrder = $this->getHighestOrder($pollId);
338
		}
339
340
		$oldOrder = $this->option->getOrder();
341
342
		foreach ($this->optionMapper->findByPoll($pollId) as $option) {
343
			$currentOrder = $option->getOrder();
344
			if ($currentOrder > $oldOrder && $currentOrder <= $newOrder) {
345
				$option->setOrder($currentOrder - 1);
346
				$this->optionMapper->update($option);
347
			} elseif (
348
					   ($currentOrder < $oldOrder && $currentOrder >= $newOrder)
349
					|| ($currentOrder < $oldOrder && $currentOrder = $newOrder)
350
				) {
351
				$option->setOrder($currentOrder + 1);
352
				$this->optionMapper->update($option);
353
			} elseif ($currentOrder === $oldOrder) {
354
				$option->setOrder($newOrder);
355
				$this->optionMapper->update($option);
356
			} else {
357
				continue;
358
			}
359
		}
360
361
		return $this->optionMapper->findByPoll($this->option->getPollId());
362
	}
363
364
	/**
365
	 * Set option entities validated
366
	 * @NoAdminRequired
367
	 * @param int $timestamp
368
	 * @param string $pollOptionText
369
	 * @param int $order
370
	 * @throws BadRequestException
371
	 */
372
	private function setOption($timestamp = 0, $pollOptionText = '', $order = 0) {
373
		if ($this->poll->getType() === 'datePoll') {
374
			if ($timestamp) {
375
				$this->option->setTimestamp($timestamp);
376
				$this->option->setOrder($timestamp);
377
				$this->option->setPollOptionText(date('c', $timestamp));
378
			} else {
379
				throw new BadRequestException("Date poll must have a timestamp");
380
			}
381
		} elseif ($this->poll->getType() === 'textPoll') {
382
			if ($pollOptionText) {
383
				$this->option->setPollOptionText($pollOptionText);
384
			} else {
385
				throw new BadRequestException("Text poll must have a pollOptionText");
386
			}
387
388
			if (!$order && !$this->option->getOrder()) {
389
				$order = $this->getHighestOrder($this->option->getPollId()) + 1;
390
				$this->option->setOrder($order);
391
			}
392
		}
393
	}
394
395
	/**
396
	 * Get the highest order number in $pollId
397
	 * @NoAdminRequired
398
	 * @param int $pollId
399
	 * @return int Highest order number
400
	 */
401
	private function getHighestOrder($pollId) {
402
		$order = 0;
403
		foreach ($this->optionMapper->findByPoll($pollId) as $option) {
404
			if ($option->getOrder() > $order) {
405
				$order = $option->getOrder();
406
			}
407
		}
408
		return $order;
409
	}
410
}
411