1<?php
2
3declare(strict_types=1);
4
5namespace OCA\Notes\Controller;
6
7use OCA\Notes\Service\NotesService;
8use OCA\Notes\Service\MetaService;
9use OCA\Notes\Service\SettingsService;
10
11use OCP\AppFramework\Controller;
12use OCP\IRequest;
13use OCP\IConfig;
14use OCP\IL10N;
15use OCP\AppFramework\Http;
16use OCP\AppFramework\Http\JSONResponse;
17
18class NotesController extends Controller {
19
20	/** @var NotesService */
21	private $notesService;
22	/** @var MetaService */
23	private $metaService;
24	/** @var SettingsService */
25	private $settingsService;
26	/** @var Helper */
27	private $helper;
28	/** @var IConfig */
29	private $settings;
30	/** @var IL10N */
31	private $l10n;
32
33	public function __construct(
34		string $AppName,
35		IRequest $request,
36		NotesService $notesService,
37		MetaService $metaService,
38		SettingsService $settingsService,
39		Helper $helper,
40		IConfig $settings,
41		IL10N $l10n
42	) {
43		parent::__construct($AppName, $request);
44		$this->notesService = $notesService;
45		$this->metaService = $metaService;
46		$this->settingsService = $settingsService;
47		$this->helper = $helper;
48		$this->settings = $settings;
49		$this->l10n = $l10n;
50	}
51
52	/**
53	 * @NoAdminRequired
54	 */
55	public function index(int $pruneBefore = 0) : JSONResponse {
56		return $this->helper->handleErrorResponse(function () use ($pruneBefore) {
57			$userId = $this->helper->getUID();
58			$settings = $this->settingsService->getAll($userId);
59
60			$lastViewedNote = (int) $this->settings->getUserValue(
61				$userId,
62				$this->appName,
63				'notesLastViewedNote'
64			);
65			$errorMessage = null;
66			$nac = null;
67
68			try {
69				$nac = $this->helper->getNotesAndCategories($pruneBefore, [ 'etag', 'content' ]);
70			} catch (\Throwable $e) {
71				$this->helper->logException($e);
72				$errorMessage = $this->l10n->t('Reading notes from filesystem has failed.').' ('.get_class($e).')';
73			}
74
75			if ($errorMessage === null && $lastViewedNote
76				&& is_array($nac) && is_array($nac['notesAll']) && !count($nac['notesAll'])
77			) {
78				$this->settings->deleteUserValue($userId, $this->appName, 'notesLastViewedNote');
79				$lastViewedNote = 0;
80			}
81
82			$result = [
83				'notesData' => $nac ? array_values($nac['notesData']) : null,
84				'noteIds' => $nac ? array_keys($nac['notesAll']) : null,
85				'categories' => $nac['categories'] ?? null,
86				'settings' => $settings,
87				'lastViewedNote' => $lastViewedNote,
88				'errorMessage' => $errorMessage,
89			];
90			$etag = md5(json_encode($result));
91			return (new JSONResponse($result))
92				->setLastModified($nac['lastUpdate'] ?? null)
93				->setETag($etag)
94			;
95		});
96	}
97
98
99	/**
100	 * @NoAdminRequired
101	 */
102	public function dashboard() : JSONResponse {
103		return $this->helper->handleErrorResponse(function () {
104			$maxItems = 7;
105			$userId = $this->helper->getUID();
106			$notes = $this->notesService->getTopNotes($userId, $maxItems + 1);
107			$hasMoreNotes = count($notes) > $maxItems;
108			$notes = array_slice($notes, 0, $maxItems);
109			$items = array_map(function ($note) {
110				$excerpt = '';
111				try {
112					$excerpt = $note->getExcerpt();
113				} catch (\Throwable $e) {
114				}
115				return [
116					'id' => $note->getId(),
117					'title' => $note->getTitle(),
118					'category' => $note->getCategory(),
119					'favorite' => $note->getFavorite(),
120					'excerpt' => $excerpt,
121				];
122			}, $notes);
123			return [
124				'items' => $items,
125				'hasMoreItems' => $hasMoreNotes,
126			];
127		});
128	}
129
130
131	/**
132	 * @NoAdminRequired
133	 */
134	public function get(int $id) : JSONResponse {
135		return $this->helper->handleErrorResponse(function () use ($id) {
136			$note = $this->notesService->get($this->helper->getUID(), $id);
137
138			// save the last viewed note
139			$this->settings->setUserValue(
140				$this->helper->getUID(),
141				$this->appName,
142				'notesLastViewedNote',
143				strval($id)
144			);
145
146			$noteData = $this->helper->getNoteData($note);
147			return (new JSONResponse($noteData))
148				->setETag($noteData['etag'])
149			;
150		});
151	}
152
153
154	/**
155	 * @NoAdminRequired
156	 */
157	public function create(string $category) : JSONResponse {
158		return $this->helper->handleErrorResponse(function () use ($category) {
159			$note = $this->notesService->create($this->helper->getUID(), '', $category);
160			return $this->helper->getNoteData($note);
161		});
162	}
163
164
165	/**
166	 * @NoAdminRequired
167	 */
168	public function undo(
169		int $id,
170		string $title,
171		string $content,
172		string $category,
173		int $modified,
174		bool $favorite
175	) : JSONResponse {
176		return $this->helper->handleErrorResponse(function () use (
177			$id,
178			$title,
179			$content,
180			$category,
181			$modified,
182			$favorite
183		) {
184			try {
185				// check if note still exists
186				$note = $this->notesService->get($this->helper->getUID(), $id);
187				$noteData = $this->helper->getNoteData($note);
188				if ($noteData['error']) {
189					throw new \Exception();
190				}
191				return $noteData;
192			} catch (\Throwable $e) {
193				// re-create if note doesn't exit anymore
194				$note = $this->notesService->create($this->helper->getUID(), $title, $category);
195				$note->setContent($content);
196				$note->setModified($modified);
197				$note->setFavorite($favorite);
198				return $this->helper->getNoteData($note);
199			}
200		});
201	}
202
203
204	/**
205	 * @NoAdminRequired
206	 */
207	public function autotitle(int $id) : JSONResponse {
208		return $this->helper->handleErrorResponse(function () use ($id) {
209			$note = $this->notesService->get($this->helper->getUID(), $id);
210			$oldTitle = $note->getTitle();
211			$newTitle = $this->notesService->getTitleFromContent($note->getContent());
212			if ($oldTitle !== $newTitle) {
213				$note->setTitle($newTitle);
214			}
215			return $note->getTitle();
216		});
217	}
218
219
220	/**
221	 * @NoAdminRequired
222	 */
223	public function update(int $id, string $content) : JSONResponse {
224		return $this->helper->handleErrorResponse(function () use ($id, $content) {
225			$note = $this->helper->getNoteWithETagCheck($id, $this->request);
226			$note->setContent($content);
227			return $this->helper->getNoteData($note);
228		});
229	}
230
231
232	/**
233	 * @NoAdminRequired
234	 */
235	public function updateProperty(
236		int $id,
237		string $property,
238		?int $modified = null,
239		?string $title = null,
240		?string $category = null,
241		?bool $favorite = null
242	) : JSONResponse {
243		return $this->helper->handleErrorResponse(function () use (
244			$id,
245			$property,
246			$modified,
247			$title,
248			$category,
249			$favorite
250		) {
251			$note = $this->notesService->get($this->helper->getUID(), $id);
252			$result = null;
253			switch ($property) {
254				case 'modified':
255					if ($modified !== null) {
256						$note->setModified($modified);
257					}
258					$result = $note->getModified();
259					break;
260
261				case 'title':
262					if ($title !== null) {
263						$note->setTitle($title);
264					}
265					$result = $note->getTitle();
266					break;
267
268				case 'category':
269					if ($category !== null) {
270						$note->setCategory($category);
271					}
272					$result = $note->getCategory();
273					break;
274
275				case 'favorite':
276					if ($favorite !== null) {
277						$note->setFavorite($favorite);
278					}
279					$result = $note->getFavorite();
280					break;
281
282				default:
283					return new JSONResponse([], Http::STATUS_BAD_REQUEST);
284			}
285			return $result;
286		});
287	}
288
289
290	/**
291	 * @NoAdminRequired
292	 */
293	public function destroy(int $id) : JSONResponse {
294		return $this->helper->handleErrorResponse(function () use ($id) {
295			$this->notesService->delete($this->helper->getUID(), $id);
296			return [];
297		});
298	}
299}
300