1 | <?php |
||
25 | class NotesService { |
||
26 | |||
27 | private $l10n; |
||
28 | private $root; |
||
29 | |||
30 | /** |
||
31 | * @param IRootFolder $root |
||
32 | * @param IL10N $l10n |
||
33 | */ |
||
34 | 11 | public function __construct (IRootFolder $root, IL10N $l10n) { |
|
38 | |||
39 | |||
40 | /** |
||
41 | * @param string $userId |
||
42 | * @return array with all notes in the current directory |
||
43 | */ |
||
44 | 1 | public function getAll ($userId){ |
|
45 | 1 | $folder = $this->getFolderForUser($userId); |
|
46 | 1 | $files = $folder->getDirectoryListing(); |
|
47 | 1 | $filesById = []; |
|
48 | 1 | foreach($files as $file) { |
|
49 | 1 | if($this->isNote($file)) { |
|
50 | 1 | $filesById[$file->getId()] = $file; |
|
51 | 1 | } |
|
52 | 1 | } |
|
53 | 1 | $tagger = \OC::$server->getTagManager()->load('files'); |
|
54 | 1 | if($tagger==null) { |
|
55 | 1 | $tags = []; |
|
56 | 1 | } else { |
|
57 | $tags = $tagger->getTagsForObjects(array_keys($filesById)); |
||
58 | } |
||
59 | |||
60 | 1 | $notes = []; |
|
61 | 1 | foreach($filesById as $id=>$file) { |
|
62 | 1 | $notes[] = Note::fromFile($file, array_key_exists($id, $tags) ? $tags[$id] : []); |
|
63 | 1 | } |
|
64 | |||
65 | 1 | return $notes; |
|
66 | } |
||
67 | |||
68 | |||
69 | /** |
||
70 | * Used to get a single note by id |
||
71 | * @param int $id the id of the note to get |
||
72 | * @param string $userId |
||
73 | * @throws NoteDoesNotExistException if note does not exist |
||
74 | * @return Note |
||
75 | */ |
||
76 | 3 | public function get ($id, $userId) { |
|
77 | 3 | $folder = $this->getFolderForUser($userId); |
|
78 | 3 | return Note::fromFile($this->getFileById($folder, $id), $this->getTags($id)); |
|
79 | } |
||
80 | |||
81 | 3 | private function getTags ($id) { |
|
82 | 3 | $tagger = \OC::$server->getTagManager()->load('files'); |
|
83 | 3 | if($tagger==null) { |
|
84 | 3 | $tags = []; |
|
85 | 3 | } else { |
|
86 | $tags = $tagger->getTagsForObjects([$id]); |
||
87 | } |
||
88 | 3 | return array_key_exists($id, $tags) ? $tags[$id] : []; |
|
89 | } |
||
90 | |||
91 | /** |
||
92 | * Creates a note and returns the empty note |
||
93 | * @param string $userId |
||
94 | * @see update for setting note content |
||
95 | * @return Note the newly created note |
||
96 | */ |
||
97 | 2 | public function create ($userId) { |
|
98 | 2 | $title = $this->l10n->t('New note'); |
|
99 | 2 | $folder = $this->getFolderForUser($userId); |
|
100 | |||
101 | // check new note exists already and we need to number it |
||
102 | // pass -1 because no file has id -1 and that will ensure |
||
103 | // to only return filenames that dont yet exist |
||
104 | 2 | $path = $this->generateFileName($folder, $title, "txt", -1); |
|
105 | 2 | $file = $folder->newFile($path); |
|
106 | |||
107 | 2 | return Note::fromFile($file); |
|
108 | } |
||
109 | |||
110 | |||
111 | /** |
||
112 | * Updates a note. Be sure to check the returned note since the title is |
||
113 | * dynamically generated and filename conflicts are resolved |
||
114 | * @param int $id the id of the note used to update |
||
115 | * @param string $content the content which will be written into the note |
||
116 | * the title is generated from the first line of the content |
||
117 | * @throws NoteDoesNotExistException if note does not exist |
||
118 | * @return \OCA\Notes\Db\Note the updated note |
||
119 | */ |
||
120 | 2 | public function update ($id, $content, $userId){ |
|
121 | 2 | $folder = $this->getFolderForUser($userId); |
|
122 | 2 | $file = $this->getFileById($folder, $id); |
|
123 | |||
124 | // generate content from the first line of the title |
||
125 | 2 | $splitContent = explode("\n", $content); |
|
126 | 2 | $title = $splitContent[0]; |
|
127 | |||
128 | 2 | if(!$title) { |
|
129 | 1 | $title = $this->l10n->t('New note'); |
|
130 | 1 | } |
|
131 | |||
132 | // prevent directory traversal |
||
133 | 2 | $title = str_replace(array('/', '\\'), '', $title); |
|
134 | // remove hash and space characters from the beginning of the filename |
||
135 | // in case of markdown |
||
136 | 2 | $title = ltrim($title, ' #'); |
|
137 | // using a maximum of 100 chars should be enough |
||
138 | 2 | $title = mb_substr($title, 0, 100, "UTF-8"); |
|
139 | |||
140 | // generate filename if there were collisions |
||
141 | 2 | $currentFilePath = $file->getPath(); |
|
142 | 2 | $basePath = '/' . $userId . '/files/Notes/'; |
|
143 | 2 | $fileExtension = pathinfo($file->getName(), PATHINFO_EXTENSION); |
|
144 | 2 | $newFilePath = $basePath . $this->generateFileName($folder, $title, $fileExtension, $id); |
|
145 | |||
146 | // if the current path is not the new path, the file has to be renamed |
||
147 | 2 | if($currentFilePath !== $newFilePath) { |
|
148 | 2 | $file->move($newFilePath); |
|
149 | 2 | } |
|
150 | |||
151 | 2 | $file->putContent($content); |
|
152 | |||
153 | 2 | return Note::fromFile($file, $this->getTags($id)); |
|
154 | } |
||
155 | |||
156 | |||
157 | /** |
||
158 | * Set or unset a note as favorite. |
||
159 | * @param int $id the id of the note used to update |
||
160 | * @param boolean $favorite whether the note should be a favorite or not |
||
161 | * @throws NoteDoesNotExistException if note does not exist |
||
162 | * @return boolean the new favorite state of the note |
||
163 | */ |
||
164 | public function favorite ($id, $favorite, $userId){ |
||
165 | $folder = $this->getFolderForUser($userId); |
||
166 | $file = $this->getFileById($folder, $id); |
||
167 | if(!$this->isNote($file)) { |
||
168 | throw new NoteDoesNotExistException(); |
||
169 | } |
||
170 | $tagger = \OC::$server->getTagManager()->load('files'); |
||
171 | if($favorite) |
||
172 | $tagger->addToFavorites($id); |
||
173 | else |
||
174 | $tagger->removeFromFavorites($id); |
||
175 | |||
176 | $tags = $tagger->getTagsForObjects([$id]); |
||
177 | return in_array(\OC\Tags::TAG_FAVORITE, $tags[$id]); |
||
178 | } |
||
179 | |||
180 | |||
181 | /** |
||
182 | * Deletes a note |
||
183 | * @param int $id the id of the note which should be deleted |
||
184 | * @param string $userId |
||
185 | * @throws NoteDoesNotExistException if note does not |
||
186 | * exist |
||
187 | */ |
||
188 | 3 | public function delete ($id, $userId) { |
|
189 | 3 | $folder = $this->getFolderForUser($userId); |
|
190 | 3 | $file = $this->getFileById($folder, $id); |
|
191 | 1 | $file->delete(); |
|
192 | 1 | } |
|
193 | |||
194 | |||
195 | /** |
||
196 | * @param Folder $folder |
||
197 | * @param int $id |
||
198 | * @throws NoteDoesNotExistException |
||
199 | * @return \OCP\Files\File |
||
200 | */ |
||
201 | 8 | private function getFileById ($folder, $id) { |
|
209 | |||
210 | |||
211 | /** |
||
212 | * @param string $userId the user id |
||
213 | * @return Folder |
||
214 | */ |
||
215 | 11 | private function getFolderForUser ($userId) { |
|
216 | 11 | $path = '/' . $userId . '/files/Notes'; |
|
224 | |||
225 | |||
226 | /** |
||
227 | * get path of file and the title.txt and check if they are the same |
||
228 | * file. If not the title needs to be renamed |
||
229 | * |
||
230 | * @param Folder $folder a folder to the notes directory |
||
231 | * @param string $title the filename which should be used |
||
232 | * @param string $extension the extension which should be used |
||
233 | * @param int $id the id of the note for which the title should be generated |
||
234 | * used to see if the file itself has the title and not a different file for |
||
235 | * checking for filename collisions |
||
236 | * @return string the resolved filename to prevent overwriting different |
||
237 | * files with the same title |
||
238 | */ |
||
239 | 4 | private function generateFileName (Folder $folder, $title, $extension, $id) { |
|
259 | |||
260 | /** |
||
261 | * test if file is a note |
||
262 | * |
||
263 | * @param \OCP\Files\File $file |
||
264 | * @return bool |
||
265 | */ |
||
266 | 7 | private function isNote($file) { |
|
277 | |||
278 | } |
||
279 |