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