xref: /webtrees/app/Module/FamilyTreeNewsModule.php (revision 8a1bc7bd114eff24967c00f631a566b662dd7d50)
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 Tree     $tree
70	 * @param int      $block_id
71	 * @param bool     $template
72	 * @param string[] $cfg
73	 *
74	 * @return string
75	 */
76	public function getBlock(Tree $tree, int $block_id, bool $template = true, array $cfg = []): string {
77		$articles = Database::prepare(
78			"SELECT 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"
79		)->execute([
80			'offset'  => WT_TIMESTAMP_OFFSET,
81			'tree_id' => $tree->getTreeId(),
82		])->fetchAll();
83
84		$content = view('blocks/news', [
85			'articles' => $articles,
86			'block_id' => $block_id,
87			'limit'    => 5,
88		]);
89
90		if ($template) {
91			return view('blocks/template', [
92				'block'      => str_replace('_', '-', $this->getName()),
93				'id'         => $block_id,
94				'config_url' => '',
95				'title'      => $this->getTitle(),
96				'content'    => $content,
97			]);
98		} else {
99			return $content;
100		}
101	}
102
103	/** {@inheritdoc} */
104	public function loadAjax(): bool {
105		return false;
106	}
107
108	/** {@inheritdoc} */
109	public function isUserBlock(): bool {
110		return false;
111	}
112
113	/** {@inheritdoc} */
114	public function isGedcomBlock(): bool {
115		return true;
116	}
117
118	/**
119	 * An HTML form to edit block settings
120	 *
121	 * @param Tree $tree
122	 * @param int  $block_id
123	 *
124	 * @return void
125	 */
126	public function configureBlock(Tree $tree, int $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