xref: /webtrees/app/Module/FamilyTreeNewsModule.php (revision 998f7ab12230321db5118a72cd8104e773440a4a)
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\I18N;
21use Fisharebest\Webtrees\Tree;
22use Symfony\Component\HttpFoundation\RedirectResponse;
23use Symfony\Component\HttpFoundation\Request;
24use Symfony\Component\HttpFoundation\Response;
25use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
26
27/**
28 * Class FamilyTreeNewsModule
29 */
30class FamilyTreeNewsModule extends AbstractModule implements ModuleBlockInterface {
31	// How to update the database schema for this module
32	const SCHEMA_TARGET_VERSION   = 3;
33	const SCHEMA_SETTING_NAME     = 'NB_SCHEMA_VERSION';
34	const SCHEMA_MIGRATION_PREFIX = '\Fisharebest\Webtrees\Module\FamilyTreeNews\Schema';
35
36	/**
37	 * Create a new module.
38	 *
39	 * @param string $directory Where is this module installed
40	 */
41	public function __construct($directory) {
42		parent::__construct($directory);
43
44		// Create/update the database tables.
45		Database::updateSchema(self::SCHEMA_MIGRATION_PREFIX, self::SCHEMA_SETTING_NAME, self::SCHEMA_TARGET_VERSION);
46	}
47
48	/**
49	 * How should this module be labelled on tabs, menus, etc.?
50	 *
51	 * @return string
52	 */
53	public function getTitle() {
54		return /* I18N: Name of a module */ I18N::translate('News');
55	}
56
57	/**
58	 * A sentence describing what this module does.
59	 *
60	 * @return string
61	 */
62	public function getDescription() {
63		return /* I18N: Description of the “News” module */ I18N::translate('Family news and site announcements.');
64	}
65
66	/**
67	 * Generate the HTML content of this block.
68	 *
69	 * @param int      $block_id
70	 * @param bool     $template
71	 * @param string[] $cfg
72	 *
73	 * @return string
74	 */
75	public function getBlock($block_id, $template = true, $cfg = []): string {
76		global $WT_TREE;
77
78		$articles = Database::prepare(
79			"SELECT SQL_CACHE news_id, user_id, gedcom_id, UNIX_TIMESTAMP(updated) + :offset AS updated, subject, body FROM `##news` WHERE gedcom_id = :tree_id ORDER BY updated DESC"
80		)->execute([
81			'offset'  => WT_TIMESTAMP_OFFSET,
82			'tree_id' => $WT_TREE->getTreeId(),
83		])->fetchAll();
84
85		$content = view('blocks/news', [
86			'articles' => $articles,
87			'block_id' => $block_id,
88			'limit'    => 5,
89		]);
90
91		if ($template) {
92			return view('blocks/template', [
93				'block'      => str_replace('_', '-', $this->getName()),
94				'id'         => $block_id,
95				'config_url' => '',
96				'title'      => $this->getTitle(),
97				'content'    => $content,
98			]);
99		} else {
100			return $content;
101		}
102	}
103
104	/** {@inheritdoc} */
105	public function loadAjax(): bool {
106		return false;
107	}
108
109	/** {@inheritdoc} */
110	public function isUserBlock(): bool {
111		return false;
112	}
113
114	/** {@inheritdoc} */
115	public function isGedcomBlock(): bool {
116		return true;
117	}
118
119	/**
120	 * An HTML form to edit block settings
121	 *
122	 * @param int $block_id
123	 *
124	 * @return void
125	 */
126	public function configureBlock($block_id) {
127	}
128
129	/**
130	 * @param Request $request
131	 *
132	 * @return Response
133	 */
134	public function getEditNewsAction(Request $request): Response {
135		/** @var Tree $tree */
136		$tree = $request->attributes->get('tree');
137
138		if (!Auth::isManager($tree)) {
139			throw new AccessDeniedHttpException;
140		}
141
142		$news_id = $request->get('news_id');
143
144		if ($news_id > 0) {
145			$row = Database::prepare(
146				"SELECT subject, body FROM `##news` WHERE news_id = :news_id AND gedcom_id = :tree_id"
147			)->execute([
148				'news_id' => $news_id,
149				'tree_id' => $tree->getTreeId(),
150			])->fetchOneRow();
151		} else {
152			$row = (object) [
153				'body'    => '',
154				'subject' => '',
155			];
156		}
157
158		$title = I18N::translate('Add/edit a journal/news entry');
159
160		return $this->viewResponse('blocks/news-edit', [
161			'body'    => $row->body,
162			'news_id' => $news_id,
163			'subject' => $row->subject,
164			'title'   => $title,
165		]);
166	}
167
168	/**
169	 * @param Request $request
170	 *
171	 * @return RedirectResponse
172	 */
173	public function postEditNewsAction(Request $request): RedirectResponse {
174		/** @var Tree $tree */
175		$tree = $request->attributes->get('tree');
176
177		if (!Auth::isManager($tree)) {
178			throw new AccessDeniedHttpException;
179		}
180
181		$news_id = $request->get('news_id');
182		$subject = $request->get('subject');
183		$body    = $request->get('body');
184
185		if ($news_id > 0) {
186			Database::prepare(
187				"UPDATE `##news` SET subject = :subject, body = :body, updated = CURRENT_TIMESTAMP" .
188				" WHERE news_id = :news_id AND gedcom_id = :tree_id"
189			)->execute([
190				'subject' => $subject,
191				'body'    => $body,
192				'news_id' => $news_id,
193				'tree_id' => $tree->getTreeId(),
194			]);
195		} else {
196			Database::prepare(
197				"INSERT INTO `##news` (gedcom_id, subject, body, updated) VALUES (:tree_id, :subject ,:body, CURRENT_TIMESTAMP)"
198			)->execute([
199				'body'    => $body,
200				'subject' => $subject,
201				'tree_id' => $tree->getTreeId(),
202			]);
203		}
204
205		$url = route('home-page', [
206			'ged' => $tree->getName(),
207		]);
208
209		return new RedirectResponse($url);
210	}
211
212	/**
213	 * @param Request $request
214	 *
215	 * @return RedirectResponse
216	 */
217	public function postDeleteNewsAction(Request $request): RedirectResponse {
218		/** @var Tree $tree */
219		$tree = $request->attributes->get('tree');
220
221		$news_id = $request->get('news_id');
222
223		if (!Auth::isManager($tree)) {
224			throw new AccessDeniedHttpException;
225		}
226
227		Database::prepare(
228			"DELETE FROM `##news` WHERE news_id = :news_id AND gedcom_id = :tree_id"
229		)->execute([
230			'news_id' => $news_id,
231			'tree_id' => $tree->getTreeId(),
232		]);
233
234		$url = route('home-page', [
235			'ged' => $tree->getName(),
236		]);
237
238		return new RedirectResponse($url);
239	}
240}
241