Passed
Push — master ( 10d0d6...905d58 )
by korelstar
02:28
created

NotesService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 8
c 2
b 0
f 0
dl 0
loc 18
rs 10
cc 1
nc 1
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace OCA\Notes\Service;
4
5
use OCP\Encryption\Exceptions\GenericEncryptionException;
6
use OCP\Files\File;
7
use OCP\Files\FileInfo;
8
use OCP\Files\Folder;
9
use OCP\Files\IRootFolder;
10
use OCP\IConfig;
11
use OCP\IL10N;
12
use OCP\ILogger;
13
use OCP\ITagManager;
14
15
use OCA\Notes\Db\Note;
16
use OCA\Notes\Service\SettingsService;
17
18
/**
19
 * Class NotesService
20
 *
21
 * @package OCA\Notes\Service
22
 */
23
class NotesService {
24
25
	private $l10n;
26
	private $root;
27
	private $logger;
28
	private $config;
29
	private $tags;
30
	private $settings;
31
	private $noteUtil;
32
	private $appName;
33
34
	/**
35
	 * @param IRootFolder $root
36
	 * @param IL10N $l10n
37
	 * @param ILogger $logger
38
	 * @param IConfig $config
39
	 * @param ITagManager $tagManager
40
	 * @param SettingsService $settings
41
	 * @param NoteUtil $noteUtil
42
	 * @param String $appName
43
	 */
44
	public function __construct(
45
		IRootFolder $root,
46
		IL10N $l10n,
47
		ILogger $logger,
48
		IConfig $config,
49
		ITagManager $tagManager,
50
		SettingsService $settings,
51
		NoteUtil $noteUtil,
52
		$appName
53
	) {
54
		$this->root = $root;
55
		$this->l10n = $l10n;
56
		$this->logger = $logger;
57
		$this->config = $config;
58
		$this->tags = $tagManager->load('files');
59
		$this->settings = $settings;
60
		$this->noteUtil = $noteUtil;
61
		$this->appName = $appName;
62
	}
63
64
65
	/**
66
	 * @param string $userId
67
	 * @return array with all notes in the current directory
68
	 */
69
	public function getAll($userId, $onlyMeta = false) {
70
		$notesFolder = $this->getFolderForUser($userId);
71
		$notes = $this->noteUtil->gatherNoteFiles($notesFolder);
72
		$filesById = [];
73
		foreach ($notes as $note) {
74
			$filesById[$note->getId()] = $note;
75
		}
76
		$tags = $this->tags->getTagsForObjects(array_keys($filesById));
77
78
		$notes = [];
79
		foreach ($filesById as $id => $file) {
80
			$noteTags = is_array($tags) && array_key_exists($id, $tags) ? $tags[$id] : [];
81
			$notes[] = $this->getNote($file, $notesFolder, $noteTags, $onlyMeta);
82
		}
83
84
		return $notes;
85
	}
86
87
88
	/**
89
	 * Used to get a single note by id
90
	 * @param int $id the id of the note to get
91
	 * @param string $userId
92
	 * @throws NoteDoesNotExistException if note does not exist
93
	 * @return Note
94
	 */
95
	public function get($id, $userId, $onlyMeta = false) : Note {
96
		$folder = $this->getFolderForUser($userId);
97
		return $this->getNote($this->getFileById($folder, $id), $folder, $this->getTags($id), $onlyMeta);
98
	}
99
100
	private function getTags($id) {
101
		$tags = $this->tags->getTagsForObjects([$id]);
102
		return is_array($tags) && array_key_exists($id, $tags) ? $tags[$id] : [];
103
	}
104
105
	private function getNote(File $file, Folder $notesFolder, $tags = [], $onlyMeta = false) : Note {
106
		$id = $file->getId();
107
		try {
108
			$note = Note::fromFile($file, $notesFolder, $tags, $onlyMeta);
109
		} catch (GenericEncryptionException $e) {
110
			$message = $this->l10n->t('Encryption Error').': ('.$file->getName().') '.$e->getMessage();
111
			$note = Note::fromException($message, $file, $notesFolder, array_key_exists($id, $tags) ? $tags[$id] : []);
112
		} catch (\Exception $e) {
113
			$message = $this->l10n->t('Error').': ('.$file->getName().') '.$e->getMessage();
114
			$note = Note::fromException($message, $file, $notesFolder, array_key_exists($id, $tags) ? $tags[$id] : []);
115
		}
116
		return $note;
117
	}
118
119
120
	/**
121
	 * Creates a note and returns the empty note
122
	 * @param string $userId
123
	 * @see update for setting note content
124
	 * @return Note the newly created note
125
	 */
126
	public function create($userId) : Note {
127
		$title = $this->l10n->t('New note');
128
		$folder = $this->getFolderForUser($userId);
129
		if ($folder->getFreeSpace() <= 1) {
130
			throw new InsufficientStorageException();
131
		}
132
133
		// check new note exists already and we need to number it
134
		// pass -1 because no file has id -1 and that will ensure
135
		// to only return filenames that dont yet exist
136
		$path = $this->noteUtil->generateFileName($folder, $title, $this->settings->get($userId, 'fileSuffix'), -1);
137
		$file = $folder->newFile($path);
138
139
		// try to write some content
140
		try {
141
			// If server-side encryption is activated, the server creates an empty file without signature
142
			// which leads to an GenericEncryptionException('Missing Signature') afterwards.
143
			// Saving a space-char (and removing it later) is a working work-around.
144
			$file->putContent(' ');
145
		} catch (\Throwable $e) {
146
			// if writing the content fails, we have to roll back the note creation
147
			$this->delete($file->getId(), $userId);
148
			throw $e;
149
		}
150
151
		return $this->getNote($file, $folder);
152
	}
153
154
155
	/**
156
	 * Updates a note. Be sure to check the returned note since the title is
157
	 * dynamically generated and filename conflicts are resolved
158
	 * @param int $id the id of the note used to update
159
	 * @param string|null $content the content which will be written into the note
160
	 * the title is generated from the first line of the content
161
	 * @param string|null $category the category in which the note should be saved
162
	 * @param int $mtime time of the note modification (optional)
163
	 * @throws NoteDoesNotExistException if note does not exist
164
	 * @return \OCA\Notes\Db\Note the updated note
165
	 */
166
	public function update($id, $content, $userId, $category = null, $mtime = 0) : Note {
167
		$notesFolder = $this->getFolderForUser($userId);
168
		$file = $this->getFileById($notesFolder, $id);
169
		$title = $this->noteUtil->getSafeTitleFromContent($content===null ? $file->getContent() : $content);
170
171
		// rename/move file with respect to title/category
172
		// this can fail if access rights are not sufficient or category name is illegal
173
		try {
174
			$this->noteUtil->moveNote($notesFolder, $file, $category, $title);
175
		} catch (\OCP\Files\NotPermittedException $e) {
176
			$err = 'Moving note '.$id.' ('.$title.') to the desired target is not allowed.'
177
				.' Please check the note\'s target category ('.$category.').';
178
			$this->logger->error($err, ['app' => $this->appName]);
179
		} catch (\Exception $e) {
180
			$err = 'Moving note '.$id.' ('.$title.') to the desired target has failed '
181
				.'with a '.get_class($e).': '.$e->getMessage();
182
			$this->logger->error($err, ['app' => $this->appName]);
183
		}
184
185
		if ($content !== null) {
186
			if ($file->getParent()->getFreeSpace() < strlen($content)) {
187
				throw new InsufficientStorageException();
188
			}
189
			$file->putContent($content);
190
		}
191
192
		if ($mtime) {
193
			$file->touch($mtime);
194
		}
195
196
		return $this->getNote($file, $notesFolder, $this->getTags($id));
197
	}
198
199
	/**
200
	 * Set or unset a note as favorite.
201
	 * @param int $id the id of the note used to update
202
	 * @param boolean $favorite whether the note should be a favorite or not
203
	 * @throws NoteDoesNotExistException if note does not exist
204
	 * @return boolean the new favorite state of the note
205
	 */
206
	public function favorite($id, $favorite, $userId) {
207
		$note = $this->get($id, $userId, true);
208
		if ($favorite !== $note->getFavorite()) {
209
			if ($favorite) {
210
				$this->tags->addToFavorites($id);
211
			} else {
212
				$this->tags->removeFromFavorites($id);
213
			}
214
			$note = $this->get($id, $userId, true);
215
		}
216
		return $note->getFavorite();
217
	}
218
219
220
	/**
221
	 * Deletes a note
222
	 * @param int $id the id of the note which should be deleted
223
	 * @param string $userId
224
	 * @throws NoteDoesNotExistException if note does not
225
	 * exist
226
	 */
227
	public function delete($id, $userId) {
228
		$notesFolder = $this->getFolderForUser($userId);
229
		$file = $this->getFileById($notesFolder, $id);
230
		$parent = $file->getParent();
231
		$file->delete();
232
		$this->noteUtil->deleteEmptyFolder($notesFolder, $parent);
233
	}
234
235
	/**
236
	 * @param Folder $folder
237
	 * @param int $id
238
	 * @throws NoteDoesNotExistException
239
	 * @return \OCP\Files\File
240
	 */
241
	private function getFileById(Folder $folder, $id) : File {
242
		$file = $folder->getById($id);
243
244
		if (count($file) <= 0 || !($file[0] instanceof File) || !$this->noteUtil->isNote($file[0])) {
245
			throw new NoteDoesNotExistException();
246
		}
247
		return $file[0];
248
	}
249
250
	/**
251
	 * @param string $userId the user id
252
	 * @return Folder
253
	 */
254
	private function getFolderForUser($userId) : Folder {
255
		// TODO use IRootFolder->getUserFolder()  ?
256
		$path = '/' . $userId . '/files/' . $this->settings->get($userId, 'notesPath');
257
		try {
258
			$folder = $this->noteUtil->getOrCreateFolder($path);
259
		} catch (\Exception $e) {
260
			throw new NotesFolderException($path);
261
		}
262
		return $folder;
263
	}
264
}
265