xref: /webtrees/app/Module/StoriesModule.php (revision 6ccdf4f0fd1b65a5d54259c969912382ce49629d)
18c2e8227SGreg Roach<?php
28c2e8227SGreg Roach/**
38c2e8227SGreg Roach * webtrees: online genealogy
48fcd0d32SGreg Roach * Copyright (C) 2019 webtrees development team
58c2e8227SGreg Roach * This program is free software: you can redistribute it and/or modify
68c2e8227SGreg Roach * it under the terms of the GNU General Public License as published by
78c2e8227SGreg Roach * the Free Software Foundation, either version 3 of the License, or
88c2e8227SGreg Roach * (at your option) any later version.
98c2e8227SGreg Roach * This program is distributed in the hope that it will be useful,
108c2e8227SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
118c2e8227SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
128c2e8227SGreg Roach * GNU General Public License for more details.
138c2e8227SGreg Roach * You should have received a copy of the GNU General Public License
148c2e8227SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
158c2e8227SGreg Roach */
16e7f56f2aSGreg Roachdeclare(strict_types=1);
17e7f56f2aSGreg Roach
1876692c8bSGreg Roachnamespace Fisharebest\Webtrees\Module;
1976692c8bSGreg Roach
200e62c4b8SGreg Roachuse Fisharebest\Webtrees\Auth;
210e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N;
220e62c4b8SGreg Roachuse Fisharebest\Webtrees\Individual;
230e62c4b8SGreg Roachuse Fisharebest\Webtrees\Menu;
240e62c4b8SGreg Roachuse Fisharebest\Webtrees\Tree;
254b92b602SGreg Roachuse Illuminate\Database\Capsule\Manager as DB;
26*6ccdf4f0SGreg Roachuse Psr\Http\Message\ResponseInterface;
27*6ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface;
28225e381fSGreg Roachuse stdClass;
298c2e8227SGreg Roach
308c2e8227SGreg Roach/**
318c2e8227SGreg Roach * Class StoriesModule
328c2e8227SGreg Roach */
3337eb8894SGreg Roachclass StoriesModule extends AbstractModule implements ModuleConfigInterface, ModuleMenuInterface, ModuleTabInterface
34c1010edaSGreg Roach{
3549a243cbSGreg Roach    use ModuleTabTrait;
3649a243cbSGreg Roach    use ModuleConfigTrait;
3749a243cbSGreg Roach    use ModuleMenuTrait;
3849a243cbSGreg Roach
3949a243cbSGreg Roach    /** @var int The default access level for this module.  It can be changed in the control panel. */
4049a243cbSGreg Roach    protected $access_level = Auth::PRIV_HIDE;
4149a243cbSGreg Roach
42961ec755SGreg Roach    /**
43961ec755SGreg Roach     * A sentence describing what this module does.
44961ec755SGreg Roach     *
45961ec755SGreg Roach     * @return string
46961ec755SGreg Roach     */
4749a243cbSGreg Roach    public function description(): string
48c1010edaSGreg Roach    {
49bbb76c12SGreg Roach        /* I18N: Description of the “Stories” module */
50bbb76c12SGreg Roach        return I18N::translate('Add narrative stories to individuals in the family tree.');
518c2e8227SGreg Roach    }
528c2e8227SGreg Roach
53aee13b6dSGreg Roach    /**
5449a243cbSGreg Roach     * The default position for this menu.  It can be changed in the control panel.
55aee13b6dSGreg Roach     *
5649a243cbSGreg Roach     * @return int
57aee13b6dSGreg Roach     */
5849a243cbSGreg Roach    public function defaultMenuOrder(): int
59c1010edaSGreg Roach    {
60353b36abSGreg Roach        return 7;
618c2e8227SGreg Roach    }
628c2e8227SGreg Roach
6349a243cbSGreg Roach    /**
6449a243cbSGreg Roach     * The default position for this tab.  It can be changed in the control panel.
6549a243cbSGreg Roach     *
6649a243cbSGreg Roach     * @return int
6749a243cbSGreg Roach     */
68cbf4b7faSGreg Roach    public function defaultTabOrder(): int
69cbf4b7faSGreg Roach    {
70fb7a0427SGreg Roach        return 9;
718c2e8227SGreg Roach    }
728c2e8227SGreg Roach
738c2e8227SGreg Roach    /** {@inheritdoc} */
749b34404bSGreg Roach    public function getTabContent(Individual $individual): string
75c1010edaSGreg Roach    {
7672ac996dSGreg Roach        return view('modules/stories/tab', [
7772ac996dSGreg Roach            'is_admin'   => Auth::isAdmin(),
78225e381fSGreg Roach            'individual' => $individual,
79225e381fSGreg Roach            'stories'    => $this->getStoriesForIndividual($individual),
80225e381fSGreg Roach        ]);
818c2e8227SGreg Roach    }
828c2e8227SGreg Roach
83225e381fSGreg Roach    /**
84225e381fSGreg Roach     * @param Individual $individual
85225e381fSGreg Roach     *
86225e381fSGreg Roach     * @return stdClass[]
87225e381fSGreg Roach     */
88c1010edaSGreg Roach    private function getStoriesForIndividual(Individual $individual): array
89c1010edaSGreg Roach    {
904b92b602SGreg Roach        $block_ids = DB::table('block')
9126684e68SGreg Roach            ->where('module_name', '=', $this->name())
924b92b602SGreg Roach            ->where('xref', '=', $individual->xref())
934b92b602SGreg Roach            ->where('gedcom_id', '=', $individual->tree()->id())
944b92b602SGreg Roach            ->pluck('block_id');
95225e381fSGreg Roach
96225e381fSGreg Roach        $stories = [];
97225e381fSGreg Roach        foreach ($block_ids as $block_id) {
987d988ec3SGreg Roach            $block_id = (int) $block_id;
997d988ec3SGreg Roach
100225e381fSGreg Roach            // Only show this block for certain languages
101225e381fSGreg Roach            $languages = $this->getBlockSetting($block_id, 'languages', '');
102225e381fSGreg Roach            if ($languages === '' || in_array(WT_LOCALE, explode(',', $languages))) {
103225e381fSGreg Roach                $stories[] = (object) [
104225e381fSGreg Roach                    'block_id'   => $block_id,
105225e381fSGreg Roach                    'title'      => $this->getBlockSetting($block_id, 'title'),
10672ac996dSGreg Roach                    'story_body' => $this->getBlockSetting($block_id, 'story_body'),
107225e381fSGreg Roach                ];
108225e381fSGreg Roach            }
109225e381fSGreg Roach        }
110225e381fSGreg Roach
111225e381fSGreg Roach        return $stories;
1128c2e8227SGreg Roach    }
1138c2e8227SGreg Roach
114*6ccdf4f0SGreg Roach    /** {@inheritdoc} */
115*6ccdf4f0SGreg Roach    public function hasTabContent(Individual $individual): bool
116*6ccdf4f0SGreg Roach    {
117*6ccdf4f0SGreg Roach        return Auth::isManager($individual->tree()) || !empty($this->getStoriesForIndividual($individual));
118*6ccdf4f0SGreg Roach    }
119*6ccdf4f0SGreg Roach
120*6ccdf4f0SGreg Roach    /** {@inheritdoc} */
121*6ccdf4f0SGreg Roach    public function isGrayedOut(Individual $individual): bool
122*6ccdf4f0SGreg Roach    {
123*6ccdf4f0SGreg Roach        return !empty($this->getStoriesForIndividual($individual));
124*6ccdf4f0SGreg Roach    }
125*6ccdf4f0SGreg Roach
126*6ccdf4f0SGreg Roach    /** {@inheritdoc} */
127*6ccdf4f0SGreg Roach    public function canLoadAjax(): bool
128*6ccdf4f0SGreg Roach    {
129*6ccdf4f0SGreg Roach        return false;
130*6ccdf4f0SGreg Roach    }
131*6ccdf4f0SGreg Roach
1328c2e8227SGreg Roach    /**
1330ee13198SGreg Roach     * A menu, to be added to the main application menu.
1340ee13198SGreg Roach     *
135aee13b6dSGreg Roach     * @param Tree $tree
136aee13b6dSGreg Roach     *
1370ee13198SGreg Roach     * @return Menu|null
1380ee13198SGreg Roach     */
13946295629SGreg Roach    public function getMenu(Tree $tree): ?Menu
140c1010edaSGreg Roach    {
14149a243cbSGreg Roach        $menu = new Menu($this->title(), route('module', [
14226684e68SGreg Roach            'module' => $this->name(),
143c1010edaSGreg Roach            'action' => 'ShowList',
144aa6f03bbSGreg Roach            'ged'    => $tree->name(),
145c1010edaSGreg Roach        ]), 'menu-story');
1468c2e8227SGreg Roach
1478c2e8227SGreg Roach        return $menu;
1488c2e8227SGreg Roach    }
14972ac996dSGreg Roach
15072ac996dSGreg Roach    /**
151*6ccdf4f0SGreg Roach     * How should this module be identified in the control panel, etc.?
152*6ccdf4f0SGreg Roach     *
153*6ccdf4f0SGreg Roach     * @return string
154*6ccdf4f0SGreg Roach     */
155*6ccdf4f0SGreg Roach    public function title(): string
156*6ccdf4f0SGreg Roach    {
157*6ccdf4f0SGreg Roach        /* I18N: Name of a module */
158*6ccdf4f0SGreg Roach        return I18N::translate('Stories');
159*6ccdf4f0SGreg Roach    }
160*6ccdf4f0SGreg Roach
161*6ccdf4f0SGreg Roach    /**
162b6db7c1fSGreg Roach     * @param Tree $tree
16372ac996dSGreg Roach     *
164*6ccdf4f0SGreg Roach     * @return ResponseInterface
16572ac996dSGreg Roach     */
166*6ccdf4f0SGreg Roach    public function getAdminAction(Tree $tree): ResponseInterface
167c1010edaSGreg Roach    {
16872ac996dSGreg Roach        $this->layout = 'layouts/administration';
16972ac996dSGreg Roach
1704b92b602SGreg Roach        $stories = DB::table('block')
17126684e68SGreg Roach            ->where('module_name', '=', $this->name())
1724b92b602SGreg Roach            ->where('gedcom_id', '=', $tree->id())
1734b92b602SGreg Roach            ->orderBy('xref')
1744b92b602SGreg Roach            ->get();
17572ac996dSGreg Roach
17672ac996dSGreg Roach        foreach ($stories as $story) {
1775db543e1SGreg Roach            $block_id = (int) $story->block_id;
1785db543e1SGreg Roach
17972ac996dSGreg Roach            $story->individual = Individual::getInstance($story->xref, $tree);
1805db543e1SGreg Roach            $story->title      = $this->getBlockSetting($block_id, 'title');
1815db543e1SGreg Roach            $story->languages  = $this->getBlockSetting($block_id, 'languages');
18272ac996dSGreg Roach        }
18372ac996dSGreg Roach
18472ac996dSGreg Roach        return $this->viewResponse('modules/stories/config', [
18572ac996dSGreg Roach            'stories'    => $stories,
18649a243cbSGreg Roach            'title'      => $this->title() . ' — ' . $tree->title(),
18772ac996dSGreg Roach            'tree'       => $tree,
18872ac996dSGreg Roach            'tree_names' => Tree::getNameList(),
18972ac996dSGreg Roach        ]);
19072ac996dSGreg Roach    }
19172ac996dSGreg Roach
19272ac996dSGreg Roach    /**
193*6ccdf4f0SGreg Roach     * @param ServerRequestInterface $request
194b6db7c1fSGreg Roach     * @param Tree                   $tree
19572ac996dSGreg Roach     *
196*6ccdf4f0SGreg Roach     * @return ResponseInterface
19772ac996dSGreg Roach     */
198*6ccdf4f0SGreg Roach    public function getAdminEditAction(ServerRequestInterface $request, Tree $tree): ResponseInterface
199c1010edaSGreg Roach    {
20072ac996dSGreg Roach        $this->layout = 'layouts/administration';
20172ac996dSGreg Roach
20272ac996dSGreg Roach        $block_id = (int) $request->get('block_id');
20372ac996dSGreg Roach
20472ac996dSGreg Roach        if ($block_id === 0) {
20572ac996dSGreg Roach            // Creating a new story
20672ac996dSGreg Roach            $individual  = Individual::getInstance($request->get('xref', ''), $tree);
20772ac996dSGreg Roach            $story_title = '';
20872ac996dSGreg Roach            $story_body  = '';
20972ac996dSGreg Roach            $languages   = [];
21072ac996dSGreg Roach
211cc13d6d8SGreg Roach            $title = I18N::translate('Add a story') . ' — ' . e($tree->title());
21272ac996dSGreg Roach        } else {
21372ac996dSGreg Roach            // Editing an existing story
2144b92b602SGreg Roach            $xref = (string) DB::table('block')
2154b92b602SGreg Roach                ->where('block_id', '=', $block_id)
2164b92b602SGreg Roach                ->value('xref');
21772ac996dSGreg Roach
21872ac996dSGreg Roach            $individual  = Individual::getInstance($xref, $tree);
21972ac996dSGreg Roach            $story_title = $this->getBlockSetting($block_id, 'title', '');
22072ac996dSGreg Roach            $story_body  = $this->getBlockSetting($block_id, 'story_body', '');
22172ac996dSGreg Roach            $languages   = explode(',', $this->getBlockSetting($block_id, 'languages'));
22272ac996dSGreg Roach
223cc13d6d8SGreg Roach            $title = I18N::translate('Edit the story') . ' — ' . e($tree->title());
22472ac996dSGreg Roach        }
22572ac996dSGreg Roach
22672ac996dSGreg Roach        return $this->viewResponse('modules/stories/edit', [
22772ac996dSGreg Roach            'block_id'    => $block_id,
22872ac996dSGreg Roach            'languages'   => $languages,
22972ac996dSGreg Roach            'story_body'  => $story_body,
23072ac996dSGreg Roach            'story_title' => $story_title,
23172ac996dSGreg Roach            'title'       => $title,
23272ac996dSGreg Roach            'tree'        => $tree,
23372ac996dSGreg Roach            'individual'  => $individual,
23472ac996dSGreg Roach        ]);
23572ac996dSGreg Roach    }
23672ac996dSGreg Roach
23772ac996dSGreg Roach    /**
238*6ccdf4f0SGreg Roach     * @param ServerRequestInterface $request
239b6db7c1fSGreg Roach     * @param Tree                   $tree
24072ac996dSGreg Roach     *
241*6ccdf4f0SGreg Roach     * @return ResponseInterface
24272ac996dSGreg Roach     */
243*6ccdf4f0SGreg Roach    public function postAdminEditAction(ServerRequestInterface $request, Tree $tree): ResponseInterface
244c1010edaSGreg Roach    {
24572ac996dSGreg Roach        $block_id    = (int) $request->get('block_id');
24672ac996dSGreg Roach        $xref        = $request->get('xref', '');
24772ac996dSGreg Roach        $story_body  = $request->get('story_body', '');
24872ac996dSGreg Roach        $story_title = $request->get('story_title', '');
24972ac996dSGreg Roach        $languages   = $request->get('languages', []);
25072ac996dSGreg Roach
25172ac996dSGreg Roach        if ($block_id !== 0) {
2524b92b602SGreg Roach            DB::table('block')
2534b92b602SGreg Roach                ->where('block_id', '=', $block_id)
2544b92b602SGreg Roach                ->update([
2554b92b602SGreg Roach                    'gedcom_id' => $tree->id(),
25672ac996dSGreg Roach                    'xref'      => $xref,
25772ac996dSGreg Roach                ]);
25872ac996dSGreg Roach        } else {
2594b92b602SGreg Roach            DB::table('block')->insert([
2604b92b602SGreg Roach                'gedcom_id'   => $tree->id(),
26172ac996dSGreg Roach                'xref'        => $xref,
26226684e68SGreg Roach                'module_name' => $this->name(),
2634b92b602SGreg Roach                'block_order' => 0,
26472ac996dSGreg Roach            ]);
26572ac996dSGreg Roach
2664b92b602SGreg Roach            $block_id = (int) DB::connection()->getPdo()->lastInsertId();
26772ac996dSGreg Roach        }
26872ac996dSGreg Roach
26972ac996dSGreg Roach        $this->setBlockSetting($block_id, 'story_body', $story_body);
27072ac996dSGreg Roach        $this->setBlockSetting($block_id, 'title', $story_title);
27172ac996dSGreg Roach        $this->setBlockSetting($block_id, 'languages', implode(',', $languages));
27272ac996dSGreg Roach
273c1010edaSGreg Roach        $url = route('module', [
27426684e68SGreg Roach            'module' => $this->name(),
275c1010edaSGreg Roach            'action' => 'Admin',
276aa6f03bbSGreg Roach            'ged'    => $tree->name(),
277c1010edaSGreg Roach        ]);
27872ac996dSGreg Roach
279*6ccdf4f0SGreg Roach        return redirect($url);
28072ac996dSGreg Roach    }
28172ac996dSGreg Roach
28272ac996dSGreg Roach    /**
283*6ccdf4f0SGreg Roach     * @param ServerRequestInterface $request
284b6db7c1fSGreg Roach     * @param Tree                   $tree
28572ac996dSGreg Roach     *
286*6ccdf4f0SGreg Roach     * @return ResponseInterface
28772ac996dSGreg Roach     */
288*6ccdf4f0SGreg Roach    public function postAdminDeleteAction(ServerRequestInterface $request, Tree $tree): ResponseInterface
289c1010edaSGreg Roach    {
29072ac996dSGreg Roach        $block_id = (int) $request->get('block_id');
29172ac996dSGreg Roach
2924b92b602SGreg Roach        DB::table('block_setting')
2934b92b602SGreg Roach            ->where('block_id', '=', $block_id)
2944b92b602SGreg Roach            ->delete();
29572ac996dSGreg Roach
2964b92b602SGreg Roach        DB::table('block')
2974b92b602SGreg Roach            ->where('block_id', '=', $block_id)
2984b92b602SGreg Roach            ->delete();
29972ac996dSGreg Roach
300c1010edaSGreg Roach        $url = route('module', [
30126684e68SGreg Roach            'module' => $this->name(),
302c1010edaSGreg Roach            'action' => 'Admin',
303aa6f03bbSGreg Roach            'ged'    => $tree->name(),
304c1010edaSGreg Roach        ]);
30572ac996dSGreg Roach
306*6ccdf4f0SGreg Roach        return redirect($url);
30772ac996dSGreg Roach    }
30872ac996dSGreg Roach
30972ac996dSGreg Roach    /**
310b6db7c1fSGreg Roach     * @param Tree $tree
31172ac996dSGreg Roach     *
312*6ccdf4f0SGreg Roach     * @return ResponseInterface
31372ac996dSGreg Roach     */
314*6ccdf4f0SGreg Roach    public function getShowListAction(Tree $tree): ResponseInterface
315c1010edaSGreg Roach    {
3164b92b602SGreg Roach        $stories = DB::table('block')
31726684e68SGreg Roach            ->where('module_name', '=', $this->name())
3184b92b602SGreg Roach            ->where('gedcom_id', '=', $tree->id())
3194b92b602SGreg Roach            ->get()
3204b92b602SGreg Roach            ->map(function (stdClass $story) use ($tree): stdClass {
3215db543e1SGreg Roach                $block_id = (int) $story->block_id;
3225db543e1SGreg Roach
32372ac996dSGreg Roach                $story->individual = Individual::getInstance($story->xref, $tree);
3245db543e1SGreg Roach                $story->title      = $this->getBlockSetting($block_id, 'title');
3255db543e1SGreg Roach                $story->languages  = $this->getBlockSetting($block_id, 'languages');
32672ac996dSGreg Roach
3274b92b602SGreg Roach                return $story;
3280b5fd0a6SGreg Roach            })->filter(static function (stdClass $story): bool {
32972ac996dSGreg Roach                // Filter non-existant and private individuals.
3304b92b602SGreg Roach                return $story->individual instanceof Individual && $story->individual->canShow();
3310b5fd0a6SGreg Roach            })->filter(static function (stdClass $story): bool {
33272ac996dSGreg Roach                // Filter foreign languages.
333a44b57a9SGreg Roach                return $story->languages === '' || in_array(WT_LOCALE, explode(',', $story->languages));
33472ac996dSGreg Roach            });
33572ac996dSGreg Roach
33672ac996dSGreg Roach        return $this->viewResponse('modules/stories/list', [
33772ac996dSGreg Roach            'stories' => $stories,
33849a243cbSGreg Roach            'title'   => $this->title(),
33972ac996dSGreg Roach        ]);
34072ac996dSGreg Roach    }
3418c2e8227SGreg Roach}
342