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