xref: /webtrees/app/Module/UserJournalModule.php (revision d97083fe315dad9b7d0a150d4fb5f563e57d1869)
18c2e8227SGreg Roach<?php
23976b470SGreg Roach
38c2e8227SGreg Roach/**
48c2e8227SGreg Roach * webtrees: online genealogy
589f7189bSGreg Roach * Copyright (C) 2021 webtrees development team
68c2e8227SGreg Roach * This program is free software: you can redistribute it and/or modify
78c2e8227SGreg Roach * it under the terms of the GNU General Public License as published by
88c2e8227SGreg Roach * the Free Software Foundation, either version 3 of the License, or
98c2e8227SGreg Roach * (at your option) any later version.
108c2e8227SGreg Roach * This program is distributed in the hope that it will be useful,
118c2e8227SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
128c2e8227SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
138c2e8227SGreg Roach * GNU General Public License for more details.
148c2e8227SGreg Roach * You should have received a copy of the GNU General Public License
1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>.
168c2e8227SGreg Roach */
17fcfa147eSGreg Roach
18e7f56f2aSGreg Roachdeclare(strict_types=1);
19e7f56f2aSGreg Roach
2076692c8bSGreg Roachnamespace Fisharebest\Webtrees\Module;
2176692c8bSGreg Roach
220e62c4b8SGreg Roachuse Fisharebest\Webtrees\Auth;
2381b729d3SGreg Roachuse Fisharebest\Webtrees\Http\Exceptions\HttpAccessDeniedException;
244348fc02SGreg Roachuse Fisharebest\Webtrees\Http\Exceptions\HttpNotFoundException;
258e0e1b25SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\UserPage;
260e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N;
27*d97083feSGreg Roachuse Fisharebest\Webtrees\Registry;
2850d6f48cSGreg Roachuse Fisharebest\Webtrees\Services\HtmlService;
29fe8a65d1SGreg Roachuse Fisharebest\Webtrees\Tree;
30ec589cf2SGreg Roachuse Illuminate\Database\Capsule\Manager as DB;
310dc38e08SGreg Roachuse Illuminate\Database\Query\Expression;
321e7a7a28SGreg Roachuse Illuminate\Support\Str;
336ccdf4f0SGreg Roachuse Psr\Http\Message\ResponseInterface;
346ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface;
35f3874e19SGreg Roach
365229eadeSGreg Roachuse function assert;
374348fc02SGreg Roachuse function is_string;
384348fc02SGreg Roachuse function redirect;
398c2e8227SGreg Roach
408c2e8227SGreg Roach/**
418c2e8227SGreg Roach * Class UserJournalModule
428c2e8227SGreg Roach */
4337eb8894SGreg Roachclass UserJournalModule extends AbstractModule implements ModuleBlockInterface
44c1010edaSGreg Roach{
4549a243cbSGreg Roach    use ModuleBlockTrait;
4649a243cbSGreg Roach
4743f2f523SGreg Roach    private HtmlService $html_service;
4850d6f48cSGreg Roach
4950d6f48cSGreg Roach    /**
509e18e23bSGreg Roach     * HtmlBlockModule constructor.
5150d6f48cSGreg Roach     *
5250d6f48cSGreg Roach     * @param HtmlService $html_service
5350d6f48cSGreg Roach     */
549e18e23bSGreg Roach    public function __construct(HtmlService $html_service)
5550d6f48cSGreg Roach    {
5650d6f48cSGreg Roach        $this->html_service = $html_service;
5750d6f48cSGreg Roach    }
5850d6f48cSGreg Roach
5976692c8bSGreg Roach    /**
6076692c8bSGreg Roach     * A sentence describing what this module does.
6176692c8bSGreg Roach     *
6276692c8bSGreg Roach     * @return string
6376692c8bSGreg Roach     */
6449a243cbSGreg Roach    public function description(): string
65c1010edaSGreg Roach    {
66bbb76c12SGreg Roach        /* I18N: Description of the “Journal” module */
67bbb76c12SGreg Roach        return I18N::translate('A private area to record notes or keep a journal.');
688c2e8227SGreg Roach    }
698c2e8227SGreg Roach
7076692c8bSGreg Roach    /**
7176692c8bSGreg Roach     * Generate the HTML content of this block.
7276692c8bSGreg Roach     *
73e490cd80SGreg Roach     * @param Tree          $tree
7476692c8bSGreg Roach     * @param int           $block_id
753caaa4d2SGreg Roach     * @param string        $context
7609482a55SGreg Roach     * @param array<string> $config
7776692c8bSGreg Roach     *
7876692c8bSGreg Roach     * @return string
7976692c8bSGreg Roach     */
803caaa4d2SGreg Roach    public function getBlock(Tree $tree, int $block_id, string $context, array $config = []): string
81c1010edaSGreg Roach    {
82ec589cf2SGreg Roach        $articles = DB::table('news')
83ec589cf2SGreg Roach            ->where('user_id', '=', Auth::id())
84ec589cf2SGreg Roach            ->orderByDesc('updated')
85ca52a408SGreg Roach            ->get()
86f70bcff5SGreg Roach            ->map(static function (object $row): object {
87*d97083feSGreg Roach                $row->updated = Registry::timestampFactory()->fromString($row->updated);
88ca52a408SGreg Roach
89ca52a408SGreg Roach                return $row;
90ca52a408SGreg Roach            });
91ec589cf2SGreg Roach
92147e99aaSGreg Roach        $content = view('modules/user_blog/list', [
93fe8a65d1SGreg Roach            'articles' => $articles,
94fe8a65d1SGreg Roach            'block_id' => $block_id,
95fe8a65d1SGreg Roach            'limit'    => 5,
965f1b387cSGreg Roach            'tree'     => $tree,
97fe8a65d1SGreg Roach        ]);
988c2e8227SGreg Roach
993caaa4d2SGreg Roach        if ($context !== self::CONTEXT_EMBED) {
100147e99aaSGreg Roach            return view('modules/block-template', [
1011e7a7a28SGreg Roach                'block'      => Str::kebab($this->name()),
1029c6524dcSGreg Roach                'id'         => $block_id,
1039c6524dcSGreg Roach                'config_url' => '',
10449a243cbSGreg Roach                'title'      => $this->title(),
1059c6524dcSGreg Roach                'content'    => $content,
1069c6524dcSGreg Roach            ]);
1078c2e8227SGreg Roach        }
108b2ce94c6SRico Sonntag
109b2ce94c6SRico Sonntag        return $content;
1108c2e8227SGreg Roach    }
1118c2e8227SGreg Roach
1126ccdf4f0SGreg Roach    /**
1136ccdf4f0SGreg Roach     * How should this module be identified in the control panel, etc.?
1146ccdf4f0SGreg Roach     *
1156ccdf4f0SGreg Roach     * @return string
1166ccdf4f0SGreg Roach     */
1176ccdf4f0SGreg Roach    public function title(): string
1186ccdf4f0SGreg Roach    {
1196ccdf4f0SGreg Roach        /* I18N: Name of a module */
1206ccdf4f0SGreg Roach        return I18N::translate('Journal');
1216ccdf4f0SGreg Roach    }
1226ccdf4f0SGreg Roach
12350d6f48cSGreg Roach    /**
12450d6f48cSGreg Roach     * Should this block load asynchronously using AJAX?
12550d6f48cSGreg Roach     *
1263caaa4d2SGreg Roach     * Simple blocks are faster in-line, more complex ones can be loaded later.
12750d6f48cSGreg Roach     *
12850d6f48cSGreg Roach     * @return bool
12950d6f48cSGreg Roach     */
130c1010edaSGreg Roach    public function loadAjax(): bool
131c1010edaSGreg Roach    {
1328c2e8227SGreg Roach        return false;
1338c2e8227SGreg Roach    }
1348c2e8227SGreg Roach
13550d6f48cSGreg Roach    /**
13650d6f48cSGreg Roach     * Can this block be shown on the user’s home page?
13750d6f48cSGreg Roach     *
13850d6f48cSGreg Roach     * @return bool
13950d6f48cSGreg Roach     */
140c1010edaSGreg Roach    public function isUserBlock(): bool
141c1010edaSGreg Roach    {
1428c2e8227SGreg Roach        return true;
1438c2e8227SGreg Roach    }
1448c2e8227SGreg Roach
14550d6f48cSGreg Roach    /**
14650d6f48cSGreg Roach     * Can this block be shown on the tree’s home page?
14750d6f48cSGreg Roach     *
14850d6f48cSGreg Roach     * @return bool
14950d6f48cSGreg Roach     */
15063276d8fSGreg Roach    public function isTreeBlock(): bool
151c1010edaSGreg Roach    {
1528c2e8227SGreg Roach        return false;
1538c2e8227SGreg Roach    }
1548c2e8227SGreg Roach
15576692c8bSGreg Roach    /**
1566ccdf4f0SGreg Roach     * @param ServerRequestInterface $request
157fe8a65d1SGreg Roach     *
1586ccdf4f0SGreg Roach     * @return ResponseInterface
159fe8a65d1SGreg Roach     */
1606ccdf4f0SGreg Roach    public function getEditJournalAction(ServerRequestInterface $request): ResponseInterface
161c1010edaSGreg Roach    {
1625f1b387cSGreg Roach        $tree = $request->getAttribute('tree');
1635f1b387cSGreg Roach        assert($tree instanceof Tree);
1645f1b387cSGreg Roach
165fe8a65d1SGreg Roach        if (!Auth::check()) {
166d501c45dSGreg Roach            throw new HttpAccessDeniedException();
167fe8a65d1SGreg Roach        }
168fe8a65d1SGreg Roach
169c9e6b699SGreg Roach        $news_id = $request->getQueryParams()['news_id'] ?? '';
170fe8a65d1SGreg Roach
171c9e6b699SGreg Roach        if ($news_id !== '') {
172ec589cf2SGreg Roach            $row = DB::table('news')
173ec589cf2SGreg Roach                ->where('news_id', '=', $news_id)
174ec589cf2SGreg Roach                ->where('user_id', '=', Auth::id())
175ec589cf2SGreg Roach                ->first();
1764348fc02SGreg Roach
1774348fc02SGreg Roach            // Record was deleted before we could read it?
178e61121aaSGreg Roach            if ($row === null) {
1794566681eSGreg Roach                throw new HttpNotFoundException(I18N::translate('%s does not exist.', 'news_id:' . $news_id));
1804348fc02SGreg Roach            }
181fe8a65d1SGreg Roach        } else {
1824348fc02SGreg Roach            $row = (object)['body' => '', 'subject' => ''];
183fe8a65d1SGreg Roach        }
184fe8a65d1SGreg Roach
185fe8a65d1SGreg Roach        $title = I18N::translate('Add/edit a journal/news entry');
186fe8a65d1SGreg Roach
187147e99aaSGreg Roach        return $this->viewResponse('modules/user_blog/edit', [
188fe8a65d1SGreg Roach            'body'    => $row->body,
189fe8a65d1SGreg Roach            'news_id' => $news_id,
190fe8a65d1SGreg Roach            'subject' => $row->subject,
191fe8a65d1SGreg Roach            'title'   => $title,
1925f1b387cSGreg Roach            'tree'    => $tree,
193fe8a65d1SGreg Roach        ]);
194fe8a65d1SGreg Roach    }
195fe8a65d1SGreg Roach
196fe8a65d1SGreg Roach    /**
1976ccdf4f0SGreg Roach     * @param ServerRequestInterface $request
198fe8a65d1SGreg Roach     *
1996ccdf4f0SGreg Roach     * @return ResponseInterface
200fe8a65d1SGreg Roach     */
20157ab2231SGreg Roach    public function postEditJournalAction(ServerRequestInterface $request): ResponseInterface
202c1010edaSGreg Roach    {
20357ab2231SGreg Roach        $tree = $request->getAttribute('tree');
20475964c75SGreg Roach        assert($tree instanceof Tree);
20557ab2231SGreg Roach
206fe8a65d1SGreg Roach        if (!Auth::check()) {
207d501c45dSGreg Roach            throw new HttpAccessDeniedException();
208fe8a65d1SGreg Roach        }
209fe8a65d1SGreg Roach
210b46c87bdSGreg Roach        $params = (array) $request->getParsedBody();
211b46c87bdSGreg Roach
212c9e6b699SGreg Roach        $news_id = $request->getQueryParams()['news_id'] ?? '';
213b46c87bdSGreg Roach        $subject = $params['subject'];
214b46c87bdSGreg Roach        $body    = $params['body'];
215fe8a65d1SGreg Roach
21650d6f48cSGreg Roach        $subject = $this->html_service->sanitize($subject);
21750d6f48cSGreg Roach        $body    = $this->html_service->sanitize($body);
21850d6f48cSGreg Roach
219c9e6b699SGreg Roach        if ($news_id !== '') {
220ec589cf2SGreg Roach            DB::table('news')
221ec589cf2SGreg Roach                ->where('news_id', '=', $news_id)
222ec589cf2SGreg Roach                ->where('user_id', '=', Auth::id())
223ec589cf2SGreg Roach                ->update([
224fe8a65d1SGreg Roach                    'body'    => $body,
225ec589cf2SGreg Roach                    'subject' => $subject,
2260dc38e08SGreg Roach                    'updated' => new Expression('updated'), // See issue #3208
227fe8a65d1SGreg Roach                ]);
228fe8a65d1SGreg Roach        } else {
229ec589cf2SGreg Roach            DB::table('news')->insert([
230fe8a65d1SGreg Roach                'body'    => $body,
231fe8a65d1SGreg Roach                'subject' => $subject,
232fe8a65d1SGreg Roach                'user_id' => Auth::id(),
233fe8a65d1SGreg Roach            ]);
234fe8a65d1SGreg Roach        }
235fe8a65d1SGreg Roach
2368e0e1b25SGreg Roach        $url = route(UserPage::class, ['tree' => $tree->name()]);
237fe8a65d1SGreg Roach
2386ccdf4f0SGreg Roach        return redirect($url);
239fe8a65d1SGreg Roach    }
240fe8a65d1SGreg Roach
241fe8a65d1SGreg Roach    /**
2426ccdf4f0SGreg Roach     * @param ServerRequestInterface $request
243fe8a65d1SGreg Roach     *
2446ccdf4f0SGreg Roach     * @return ResponseInterface
245fe8a65d1SGreg Roach     */
24657ab2231SGreg Roach    public function postDeleteJournalAction(ServerRequestInterface $request): ResponseInterface
247c1010edaSGreg Roach    {
24857ab2231SGreg Roach        $tree = $request->getAttribute('tree');
2494ea62551SGreg Roach        assert($tree instanceof Tree);
2504ea62551SGreg Roach
251c9e6b699SGreg Roach        $news_id = $request->getQueryParams()['news_id'];
252fe8a65d1SGreg Roach
253ec589cf2SGreg Roach        DB::table('news')
254ec589cf2SGreg Roach            ->where('news_id', '=', $news_id)
255ec589cf2SGreg Roach            ->where('user_id', '=', Auth::id())
256ec589cf2SGreg Roach            ->delete();
257fe8a65d1SGreg Roach
2588e0e1b25SGreg Roach        $url = route(UserPage::class, ['tree' => $tree->name()]);
259fe8a65d1SGreg Roach
2606ccdf4f0SGreg Roach        return redirect($url);
261fe8a65d1SGreg Roach    }
2628c2e8227SGreg Roach}
263