xref: /webtrees/app/Module/UserFavoritesModule.php (revision b295534922aa0d15bf8b3821f74784a5ff810d62)
1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2018 webtrees development team
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16namespace Fisharebest\Webtrees\Module;
17
18use Fisharebest\Webtrees\Auth;
19use Fisharebest\Webtrees\Database;
20use Fisharebest\Webtrees\FlashMessages;
21use Fisharebest\Webtrees\GedcomRecord;
22use Fisharebest\Webtrees\I18N;
23use Fisharebest\Webtrees\Tree;
24use Fisharebest\Webtrees\User;
25use stdClass;
26use Symfony\Component\HttpFoundation\RedirectResponse;
27use Symfony\Component\HttpFoundation\Request;
28
29/**
30 * Class UserFavoritesModule
31 */
32class UserFavoritesModule extends AbstractModule implements ModuleBlockInterface {
33	/**
34	 * How should this module be labelled on tabs, menus, etc.?
35	 *
36	 * @return string
37	 */
38	public function getTitle() {
39		return /* I18N: Name of a module */ I18N::translate('Favorites');
40	}
41
42	/**
43	 * A sentence describing what this module does.
44	 *
45	 * @return string
46	 */
47	public function getDescription() {
48		return /* I18N: Description of the “Favorites” module */ I18N::translate('Display and manage a user’s favorite pages.');
49	}
50
51	/**
52	 * Generate the HTML content of this block.
53	 *
54	 * @param Tree     $tree
55	 * @param int      $block_id
56	 * @param bool     $template
57	 * @param string[] $cfg
58	 *
59	 * @return string
60	 */
61	public function getBlock(Tree $tree, int $block_id, bool $template = true, array $cfg = []): string {
62		$content = view('modules/user_favorites/favorites', [
63			'block_id'   => $block_id,
64			'favorites'  => $this->getFavorites($tree, Auth::user()),
65			'tree'       => $tree,
66		]);
67
68		if ($template) {
69			return view('modules/block-template', [
70				'block'      => str_replace('_', '-', $this->getName()),
71				'id'         => $block_id,
72				'config_url' => '',
73				'title'      => $this->getTitle(),
74				'content'    => $content,
75			]);
76		} else {
77			return $content;
78		}
79	}
80
81	/**
82	 * Should this block load asynchronously using AJAX?
83	 *
84	 * Simple blocks are faster in-line, more comples ones
85	 * can be loaded later.
86	 *
87	 * @return bool
88	 */
89	public function loadAjax(): bool {
90		return false;
91	}
92
93	/**
94	 * Can this block be shown on the user’s home page?
95	 *
96	 * @return bool
97	 */
98	public function isUserBlock(): bool {
99		return true;
100	}
101
102	/**
103	 * Can this block be shown on the tree’s home page?
104	 *
105	 * @return bool
106	 */
107	public function isGedcomBlock(): bool {
108		return false;
109	}
110
111	/**
112	 * An HTML form to edit block settings
113	 *
114	 * @param Tree $tree
115	 * @param int  $block_id
116	 *
117	 * @return void
118	 */
119	public function configureBlock(Tree $tree, int $block_id) {
120	}
121
122	/**
123	 * Get the favorites for a user
124	 *
125	 * @param Tree $tree
126	 * @param User $user
127	 *
128	 * @return stdClass[]
129	 */
130	public function getFavorites(Tree $tree, User $user) {
131		$favorites =
132			Database::prepare(
133				"SELECT favorite_id, user_id, gedcom_id, xref, favorite_type, title, note, url" .
134				" FROM `##favorite` WHERE gedcom_id = :tree_id AND user_id = :user_id")
135				->execute([
136					'tree_id' => $tree->getTreeId(),
137					'user_id' => $user->getUserId(),
138				])
139				->fetchAll();
140
141		foreach ($favorites as $favorite) {
142			$favorite->record = GedcomRecord::getInstance($favorite->xref, $tree);
143		}
144
145		return $favorites;
146	}
147
148	/**
149	 * @param Request $request
150	 *
151	 * @return RedirectResponse
152	 */
153	public function postAddFavoriteAction(Request $request): RedirectResponse {
154		/** @var Tree $tree */
155		$tree = $request->attributes->get('tree');
156
157		/** @var User $user */
158		$user = $request->attributes->get('user');
159
160		$note  = $request->get('note', '');
161		$title = $request->get('title', '');
162		$url   = $request->get('url', '');
163		$xref  = $request->get('xref', '');
164
165		if (Auth::check()) {
166			if ($url !== '') {
167				$this->addUrlFavorite($tree, $user, $url, $title ?: $url, $note);
168			} else {
169				$this->addRecordFavorite($tree, $user, $xref, $note);
170			}
171		}
172
173		$url = route('user-page', ['ged' => $tree->getName()]);
174
175		return new RedirectResponse($url);
176	}
177
178	/**
179	 * @param Request $request
180	 *
181	 * @return RedirectResponse
182	 */
183	public function postDeleteFavoriteAction(Request $request): RedirectResponse {
184		/** @var Tree $tree */
185		$tree = $request->attributes->get('tree');
186
187		/** @var User $user */
188		$user = $request->attributes->get('user');
189
190		$favorite_id = (int) $request->get('favorite_id');
191
192		if (Auth::check()) {
193			Database::prepare(
194				"DELETE FROM `##favorite` WHERE favorite_id = :favorite_id AND user_id = :user_id"
195			)->execute([
196				'favorite_id' => $favorite_id,
197				'user_id'     => $user->getUserId(),
198			]);
199		}
200
201		$url = route('user-page', ['ged' => $tree->getName()]);
202
203		return new RedirectResponse($url);
204	}
205
206	/**
207	 * @param Tree   $tree
208	 * @param User   $user
209	 * @param string $url
210	 * @param string $title
211	 * @param string $note
212	 */
213	private function addUrlFavorite(Tree $tree, User $user, string $url, string $title, string $note) {
214		$favorite = Database::prepare(
215			"SELECT * FROM `##favorite` WHERE gedcom_id = :gedcom_id AND user_id = :user_id AND url = :url"
216		)->execute([
217			'gedcom_id' => $tree->getTreeId(),
218			'user_id'   => $user->getUserId(),
219			'url'       => $url,
220		])->fetchOneRow();
221
222		if ($favorite === null) {
223			Database::prepare(
224				"INSERT INTO `##favorite` (gedcom_id, user_id, url, note, title) VALUES (:gedcom_id, :user_id, :url, :note, :title)"
225			)->execute([
226				'gedcom_id' => $tree->getTreeId(),
227				'user_id'   => $user->getUserId(),
228				'url'       => $url,
229				'note'      => $note,
230				'title'     => $title,
231			]);
232		} else {
233			Database::prepare(
234				"UPDATE `##favorite` SET note = :note, title = :title WHERE favorite_id = :favorite_id"
235			)->execute([
236				'note'        => $note,
237				'title'       => $title,
238				'favorite_id' => $favorite->favorite_id,
239			]);
240		}
241	}
242
243	/**
244	 * @param Tree   $tree
245	 * @param User   $user
246	 * @param string $xref
247	 * @param string $note
248	 */
249	private function addRecordFavorite(Tree $tree, User $user, string $xref, string $note) {
250		$favorite = Database::prepare(
251			"SELECT * FROM `##favorite` WHERE gedcom_id = :gedcom_id AND user_id = :user_id AND xref = :xref"
252		)->execute([
253			'gedcom_id' => $tree->getTreeId(),
254			'user_id'   => $user->getUserId(),
255			'xref'      => $xref,
256		])->fetchOneRow();
257
258		if ($favorite === null) {
259			Database::prepare(
260				"INSERT INTO `##favorite` (gedcom_id, user_id, xref, note) VALUES (:gedcom_id, :user_id, :xref, :note)"
261			)->execute([
262				'gedcom_id' => $tree->getTreeId(),
263				'user_id'   => $user->getUserId(),
264				'xref'      => $xref,
265				'note'      => $note,
266			]);
267		} else {
268			Database::prepare(
269				"UPDATE `##favorite` SET note = :note WHERE favorite_id = :favorite_id"
270			)->execute([
271				'note'        => $note,
272				'favorite_id' => $favorite->favorite_id,
273			]);
274		}
275	}
276}
277