xref: /webtrees/app/Module/FamilyTreeNewsModule.php (revision bd44f43fad3efd8fd7f063363bfcb5a97080fa7d)
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        return /* I18N: Name of a module */
58            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        return /* I18N: Description of the “News” module */
69            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     * An HTML form to edit block settings
130     *
131     * @param Tree $tree
132     * @param int  $block_id
133     *
134     * @return void
135     */
136    public function configureBlock(Tree $tree, int $block_id)
137    {
138    }
139
140    /**
141     * @param Request $request
142     * @param Tree    $tree
143     *
144     * @return Response
145     */
146    public function getEditNewsAction(Request $request, Tree $tree): Response
147    {
148        if (!Auth::isManager($tree)) {
149            throw new AccessDeniedHttpException;
150        }
151
152        $news_id = $request->get('news_id');
153
154        if ($news_id > 0) {
155            $row = Database::prepare(
156                "SELECT subject, body FROM `##news` WHERE news_id = :news_id AND gedcom_id = :tree_id"
157            )->execute([
158                'news_id' => $news_id,
159                'tree_id' => $tree->getTreeId(),
160            ])->fetchOneRow();
161        } else {
162            $row = (object)[
163                'body'    => '',
164                'subject' => '',
165            ];
166        }
167
168        $title = I18N::translate('Add/edit a journal/news entry');
169
170        return $this->viewResponse('modules/gedcom_news/edit', [
171            'body'    => $row->body,
172            'news_id' => $news_id,
173            'subject' => $row->subject,
174            'title'   => $title,
175        ]);
176    }
177
178    /**
179     * @param Request $request
180     * @param Tree    $tree
181     *
182     * @return RedirectResponse
183     */
184    public function postEditNewsAction(Request $request, Tree $tree): RedirectResponse
185    {
186        if (!Auth::isManager($tree)) {
187            throw new AccessDeniedHttpException;
188        }
189
190        $news_id = $request->get('news_id');
191        $subject = $request->get('subject');
192        $body    = $request->get('body');
193
194        if ($news_id > 0) {
195            Database::prepare(
196                "UPDATE `##news` SET subject = :subject, body = :body, updated = CURRENT_TIMESTAMP" .
197                " WHERE news_id = :news_id AND gedcom_id = :tree_id"
198            )->execute([
199                'subject' => $subject,
200                'body'    => $body,
201                'news_id' => $news_id,
202                'tree_id' => $tree->getTreeId(),
203            ]);
204        } else {
205            Database::prepare(
206                "INSERT INTO `##news` (gedcom_id, subject, body, updated) VALUES (:tree_id, :subject ,:body, CURRENT_TIMESTAMP)"
207            )->execute([
208                'body'    => $body,
209                'subject' => $subject,
210                'tree_id' => $tree->getTreeId(),
211            ]);
212        }
213
214        $url = route('tree-page', [
215            'ged' => $tree->getName(),
216        ]);
217
218        return new RedirectResponse($url);
219    }
220
221    /**
222     * @param Request $request
223     * @param Tree    $tree
224     *
225     * @return RedirectResponse
226     */
227    public function postDeleteNewsAction(Request $request, Tree $tree): RedirectResponse
228    {
229        $news_id = $request->get('news_id');
230
231        if (!Auth::isManager($tree)) {
232            throw new AccessDeniedHttpException;
233        }
234
235        Database::prepare(
236            "DELETE FROM `##news` WHERE news_id = :news_id AND gedcom_id = :tree_id"
237        )->execute([
238            'news_id' => $news_id,
239            'tree_id' => $tree->getTreeId(),
240        ]);
241
242        $url = route('tree-page', [
243            'ged' => $tree->getName(),
244        ]);
245
246        return new RedirectResponse($url);
247    }
248}
249