xref: /webtrees/app/Module/FamilyTreeFavoritesModule.php (revision a4439c01d86a2e935e1a12fb1b61b28b6de511d1)
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\GedcomRecord;
21use Fisharebest\Webtrees\I18N;
22use Fisharebest\Webtrees\Tree;
23use Fisharebest\Webtrees\User;
24use stdClass;
25use Symfony\Component\HttpFoundation\RedirectResponse;
26use Symfony\Component\HttpFoundation\Request;
27
28/**
29 * Class FamilyTreeFavoritesModule
30 */
31class FamilyTreeFavoritesModule extends AbstractModule implements ModuleBlockInterface {
32	/**
33	 * How should this module be labelled on tabs, menus, etc.?
34	 *
35	 * @return string
36	 */
37	public function getTitle() {
38		return /* I18N: Name of a module */ I18N::translate('Favorites');
39	}
40
41	/**
42	 * A sentence describing what this module does.
43	 *
44	 * @return string
45	 */
46	public function getDescription() {
47		return /* I18N: Description of the “Favorites” module */ I18N::translate('Display and manage a family tree’s favorite pages.');
48	}
49
50	/**
51	 * Generate the HTML content of this block.
52	 *
53	 * @param Tree     $tree
54	 * @param int      $block_id
55	 * @param bool     $template
56	 * @param string[] $cfg
57	 *
58	 * @return string
59	 */
60	public function getBlock(Tree $tree, int $block_id, bool $template = true, array $cfg = []): string {
61		$content = view('modules/gedcom_favorites/favorites', [
62			'block_id'   => $block_id,
63			'favorites'  => $this->getFavorites($tree),
64			'is_manager' => Auth::isManager($tree),
65			'tree'       => $tree,
66		]);
67
68		if ($template) {
69			return view('blocks/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 false;
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 true;
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 favorites for a family tree
124	 *
125	 * @param Tree $tree
126	 *
127	 * @return stdClass[]
128	 */
129	public function getFavorites(Tree $tree) {
130		$favorites =
131			Database::prepare(
132				"SELECT favorite_id, user_id, gedcom_id, xref, favorite_type, title, note, url" .
133				" FROM `##favorite` WHERE gedcom_id = :tree_id AND user_id IS NULL")
134				->execute([
135					'tree_id' => $tree->getTreeId(),
136				])
137				->fetchAll();
138
139		foreach ($favorites as $favorite) {
140			$favorite->record = GedcomRecord::getInstance($favorite->xref, $tree);
141		}
142
143		return $favorites;
144	}
145
146	/**
147	 * @param Request $request
148	 *
149	 * @return RedirectResponse
150	 */
151	public function postAddFavoriteAction(Request $request): RedirectResponse {
152		/** @var Tree $tree */
153		$tree = $request->attributes->get('tree');
154
155		/** @var User $user */
156		$user = $request->attributes->get('user');
157
158		$note  = $request->get('note', '');
159		$title = $request->get('title', '');
160		$url   = $request->get('url', '');
161		$xref  = $request->get('xref', '');
162
163		if (Auth::isManager($tree, $user)) {
164			if ($url !== '') {
165				$this->addUrlFavorite($tree, $url, $title ?: $url, $note);
166			} else {
167				$this->addRecordFavorite($tree, $xref, $note);
168			}
169		}
170
171		$url = route('tree-page', ['ged' => $tree->getName()]);
172
173		return new RedirectResponse($url);
174	}
175
176	/**
177	 * @param Request $request
178	 *
179	 * @return RedirectResponse
180	 */
181	public function postDeleteFavoriteAction(Request $request): RedirectResponse {
182		/** @var Tree $tree */
183		$tree = $request->attributes->get('tree');
184
185		/** @var User $user */
186		$user = $request->attributes->get('user');
187
188		$favorite_id = (int) $request->get('favorite_id');
189
190		if (Auth::isManager($tree, $user)) {
191			Database::prepare(
192				"DELETE FROM `##favorite` WHERE favorite_id = :favorite_id AND gedcom_id = :tree_id"
193			)->execute([
194				'favorite_id' => $favorite_id,
195				'tree_id'     => $tree->getTreeId(),
196			]);
197		}
198
199		$url = route('tree-page', ['ged' => $tree->getName()]);
200
201		return new RedirectResponse($url);
202	}
203
204	/**
205	 * @param Tree   $tree
206	 * @param string $url
207	 * @param string $title
208	 * @param string $note
209	 */
210	private function addUrlFavorite(Tree $tree, string $url, string $title, string $note) {
211		$favorite = Database::prepare(
212			"SELECT * FROM `##favorite` WHERE gedcom_id = :gedcom_id AND user_id IS NULL AND url = :url"
213		)->execute([
214			'gedcom_id' => $tree->getTreeId(),
215			'url'       => $url,
216		])->fetchOneRow();
217
218		if ($favorite === null) {
219			Database::prepare(
220				"INSERT INTO `##favorite` (gedcom_id, url, note, title) VALUES (:gedcom_id, :user_id, :url, :note, :title)"
221			)->execute([
222				'gedcom_id' => $tree->getTreeId(),
223				'url'       => $url,
224				'note'      => $note,
225				'title'     => $title,
226			]);
227		} else {
228			Database::prepare(
229				"UPDATE `##favorite` SET note = :note, title = :title WHERE favorite_id = :favorite_id"
230			)->execute([
231				'note'        => $note,
232				'title'       => $title,
233				'favorite_id' => $favorite->favorite_id,
234			]);
235		}
236	}
237
238	/**
239	 * @param Tree   $tree
240	 * @param string $xref
241	 * @param string $note
242	 */
243	private function addRecordFavorite(Tree $tree, string $xref, string $note) {
244		$favorite = Database::prepare(
245			"SELECT * FROM `##favorite` WHERE gedcom_id = :gedcom_id AND user_id IS NULL AND xref = :xref"
246		)->execute([
247			'gedcom_id' => $tree->getTreeId(),
248			'xref'      => $xref,
249		])->fetchOneRow();
250
251		if ($favorite === null) {
252			Database::prepare(
253				"INSERT INTO `##favorite` (gedcom_id, xref, note) VALUES (:gedcom_id, :xref, :note)"
254			)->execute([
255				'gedcom_id' => $tree->getTreeId(),
256				'xref'      => $xref,
257				'note'      => $note,
258			]);
259		} else {
260			Database::prepare(
261				"UPDATE `##favorite` SET note = :note WHERE favorite_id = :favorite_id"
262			)->execute([
263				'note'        => $note,
264				'favorite_id' => $favorite->favorite_id,
265			]);
266		}
267	}
268}
269