Passed
Pull Request — master (#381)
by korelstar
01:57
created

NotesService::get()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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