xref: /webtrees/app/Module/StoriesModule.php (revision 0b5fd0a636fa959f5279ee28ebd2f27e921c091e)
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;
26225e381fSGreg Roachuse stdClass;
2772ac996dSGreg Roachuse Symfony\Component\HttpFoundation\RedirectResponse;
2872ac996dSGreg Roachuse Symfony\Component\HttpFoundation\Request;
2972ac996dSGreg Roachuse Symfony\Component\HttpFoundation\Response;
308c2e8227SGreg Roach
318c2e8227SGreg Roach/**
328c2e8227SGreg Roach * Class StoriesModule
338c2e8227SGreg Roach */
3437eb8894SGreg Roachclass StoriesModule extends AbstractModule implements ModuleConfigInterface, ModuleMenuInterface, ModuleTabInterface
35c1010edaSGreg Roach{
3649a243cbSGreg Roach    use ModuleTabTrait;
3749a243cbSGreg Roach    use ModuleConfigTrait;
3849a243cbSGreg Roach    use ModuleMenuTrait;
3949a243cbSGreg Roach
4049a243cbSGreg Roach    /** @var int The default access level for this module.  It can be changed in the control panel. */
4149a243cbSGreg Roach    protected $access_level = Auth::PRIV_HIDE;
4249a243cbSGreg Roach
43961ec755SGreg Roach    /**
440cfd6963SGreg Roach     * How should this module be identified in the control panel, etc.?
45961ec755SGreg Roach     *
46961ec755SGreg Roach     * @return string
47961ec755SGreg Roach     */
4849a243cbSGreg Roach    public function title(): string
49c1010edaSGreg Roach    {
50bbb76c12SGreg Roach        /* I18N: Name of a module */
51bbb76c12SGreg Roach        return I18N::translate('Stories');
528c2e8227SGreg Roach    }
538c2e8227SGreg Roach
54961ec755SGreg Roach    /**
55961ec755SGreg Roach     * A sentence describing what this module does.
56961ec755SGreg Roach     *
57961ec755SGreg Roach     * @return string
58961ec755SGreg Roach     */
5949a243cbSGreg Roach    public function description(): string
60c1010edaSGreg Roach    {
61bbb76c12SGreg Roach        /* I18N: Description of the “Stories” module */
62bbb76c12SGreg Roach        return I18N::translate('Add narrative stories to individuals in the family tree.');
638c2e8227SGreg Roach    }
648c2e8227SGreg Roach
65aee13b6dSGreg Roach    /**
6649a243cbSGreg Roach     * The default position for this menu.  It can be changed in the control panel.
67aee13b6dSGreg Roach     *
6849a243cbSGreg Roach     * @return int
69aee13b6dSGreg Roach     */
7049a243cbSGreg Roach    public function defaultMenuOrder(): int
71c1010edaSGreg Roach    {
72353b36abSGreg Roach        return 7;
738c2e8227SGreg Roach    }
748c2e8227SGreg Roach
7549a243cbSGreg Roach    /**
7649a243cbSGreg Roach     * The default position for this tab.  It can be changed in the control panel.
7749a243cbSGreg Roach     *
7849a243cbSGreg Roach     * @return int
7949a243cbSGreg Roach     */
80cbf4b7faSGreg Roach    public function defaultTabOrder(): int
81cbf4b7faSGreg Roach    {
82fb7a0427SGreg Roach        return 9;
838c2e8227SGreg Roach    }
848c2e8227SGreg Roach
858c2e8227SGreg Roach    /** {@inheritdoc} */
869b34404bSGreg Roach    public function getTabContent(Individual $individual): string
87c1010edaSGreg Roach    {
8872ac996dSGreg Roach        return view('modules/stories/tab', [
8972ac996dSGreg Roach            'is_admin'   => Auth::isAdmin(),
90225e381fSGreg Roach            'individual' => $individual,
91225e381fSGreg Roach            'stories'    => $this->getStoriesForIndividual($individual),
92225e381fSGreg Roach        ]);
938c2e8227SGreg Roach    }
948c2e8227SGreg Roach
958c2e8227SGreg Roach    /** {@inheritdoc} */
969b34404bSGreg Roach    public function hasTabContent(Individual $individual): bool
97c1010edaSGreg Roach    {
98f4afa648SGreg Roach        return Auth::isManager($individual->tree()) || !empty($this->getStoriesForIndividual($individual));
998c2e8227SGreg Roach    }
1008c2e8227SGreg Roach
1018c2e8227SGreg Roach    /** {@inheritdoc} */
1029b34404bSGreg Roach    public function isGrayedOut(Individual $individual): bool
103c1010edaSGreg Roach    {
104225e381fSGreg Roach        return !empty($this->getStoriesForIndividual($individual));
1058c2e8227SGreg Roach    }
1068c2e8227SGreg Roach
1078c2e8227SGreg Roach    /** {@inheritdoc} */
1089b34404bSGreg Roach    public function canLoadAjax(): bool
109c1010edaSGreg Roach    {
1108c2e8227SGreg Roach        return false;
1118c2e8227SGreg Roach    }
1128c2e8227SGreg Roach
113225e381fSGreg Roach    /**
114225e381fSGreg Roach     * @param Individual $individual
115225e381fSGreg Roach     *
116225e381fSGreg Roach     * @return stdClass[]
117225e381fSGreg Roach     */
118c1010edaSGreg Roach    private function getStoriesForIndividual(Individual $individual): array
119c1010edaSGreg Roach    {
1204b92b602SGreg Roach        $block_ids = DB::table('block')
12126684e68SGreg Roach            ->where('module_name', '=', $this->name())
1224b92b602SGreg Roach            ->where('xref', '=', $individual->xref())
1234b92b602SGreg Roach            ->where('gedcom_id', '=', $individual->tree()->id())
1244b92b602SGreg Roach            ->pluck('block_id');
125225e381fSGreg Roach
126225e381fSGreg Roach        $stories = [];
127225e381fSGreg Roach        foreach ($block_ids as $block_id) {
1287d988ec3SGreg Roach            $block_id = (int) $block_id;
1297d988ec3SGreg Roach
130225e381fSGreg Roach            // Only show this block for certain languages
131225e381fSGreg Roach            $languages = $this->getBlockSetting($block_id, 'languages', '');
132225e381fSGreg Roach            if ($languages === '' || in_array(WT_LOCALE, explode(',', $languages))) {
133225e381fSGreg Roach                $stories[] = (object) [
134225e381fSGreg Roach                    'block_id'   => $block_id,
135225e381fSGreg Roach                    'title'      => $this->getBlockSetting($block_id, 'title'),
13672ac996dSGreg Roach                    'story_body' => $this->getBlockSetting($block_id, 'story_body'),
137225e381fSGreg Roach                ];
138225e381fSGreg Roach            }
139225e381fSGreg Roach        }
140225e381fSGreg Roach
141225e381fSGreg Roach        return $stories;
1428c2e8227SGreg Roach    }
1438c2e8227SGreg Roach
1448c2e8227SGreg Roach    /**
1450ee13198SGreg Roach     * A menu, to be added to the main application menu.
1460ee13198SGreg Roach     *
147aee13b6dSGreg Roach     * @param Tree $tree
148aee13b6dSGreg Roach     *
1490ee13198SGreg Roach     * @return Menu|null
1500ee13198SGreg Roach     */
15146295629SGreg Roach    public function getMenu(Tree $tree): ?Menu
152c1010edaSGreg Roach    {
15349a243cbSGreg Roach        $menu = new Menu($this->title(), route('module', [
15426684e68SGreg Roach            'module' => $this->name(),
155c1010edaSGreg Roach            'action' => 'ShowList',
156aa6f03bbSGreg Roach            'ged'    => $tree->name(),
157c1010edaSGreg Roach        ]), 'menu-story');
1588c2e8227SGreg Roach
1598c2e8227SGreg Roach        return $menu;
1608c2e8227SGreg Roach    }
16172ac996dSGreg Roach
16272ac996dSGreg Roach    /**
163b6db7c1fSGreg Roach     * @param Tree $tree
16472ac996dSGreg Roach     *
16572ac996dSGreg Roach     * @return Response
16672ac996dSGreg Roach     */
167b6db7c1fSGreg Roach    public function getAdminAction(Tree $tree): Response
168c1010edaSGreg Roach    {
16972ac996dSGreg Roach        $this->layout = 'layouts/administration';
17072ac996dSGreg Roach
1714b92b602SGreg Roach        $stories = DB::table('block')
17226684e68SGreg Roach            ->where('module_name', '=', $this->name())
1734b92b602SGreg Roach            ->where('gedcom_id', '=', $tree->id())
1744b92b602SGreg Roach            ->orderBy('xref')
1754b92b602SGreg Roach            ->get();
17672ac996dSGreg Roach
17772ac996dSGreg Roach        foreach ($stories as $story) {
1785db543e1SGreg Roach            $block_id = (int) $story->block_id;
1795db543e1SGreg Roach
18072ac996dSGreg Roach            $story->individual = Individual::getInstance($story->xref, $tree);
1815db543e1SGreg Roach            $story->title      = $this->getBlockSetting($block_id, 'title');
1825db543e1SGreg Roach            $story->languages  = $this->getBlockSetting($block_id, 'languages');
18372ac996dSGreg Roach        }
18472ac996dSGreg Roach
18572ac996dSGreg Roach        return $this->viewResponse('modules/stories/config', [
18672ac996dSGreg Roach            'stories'    => $stories,
18749a243cbSGreg Roach            'title'      => $this->title() . ' — ' . $tree->title(),
18872ac996dSGreg Roach            'tree'       => $tree,
18972ac996dSGreg Roach            'tree_names' => Tree::getNameList(),
19072ac996dSGreg Roach        ]);
19172ac996dSGreg Roach    }
19272ac996dSGreg Roach
19372ac996dSGreg Roach    /**
19472ac996dSGreg Roach     * @param Request $request
195b6db7c1fSGreg Roach     * @param Tree    $tree
19672ac996dSGreg Roach     *
19772ac996dSGreg Roach     * @return Response
19872ac996dSGreg Roach     */
199b6db7c1fSGreg Roach    public function getAdminEditAction(Request $request, Tree $tree): Response
200c1010edaSGreg Roach    {
20172ac996dSGreg Roach        $this->layout = 'layouts/administration';
20272ac996dSGreg Roach
20372ac996dSGreg Roach        $block_id = (int) $request->get('block_id');
20472ac996dSGreg Roach
20572ac996dSGreg Roach        if ($block_id === 0) {
20672ac996dSGreg Roach            // Creating a new story
20772ac996dSGreg Roach            $individual  = Individual::getInstance($request->get('xref', ''), $tree);
20872ac996dSGreg Roach            $story_title = '';
20972ac996dSGreg Roach            $story_body  = '';
21072ac996dSGreg Roach            $languages   = [];
21172ac996dSGreg Roach
212cc13d6d8SGreg Roach            $title = I18N::translate('Add a story') . ' — ' . e($tree->title());
21372ac996dSGreg Roach        } else {
21472ac996dSGreg Roach            // Editing an existing story
2154b92b602SGreg Roach            $xref = (string) DB::table('block')
2164b92b602SGreg Roach                ->where('block_id', '=', $block_id)
2174b92b602SGreg Roach                ->value('xref');
21872ac996dSGreg Roach
21972ac996dSGreg Roach            $individual  = Individual::getInstance($xref, $tree);
22072ac996dSGreg Roach            $story_title = $this->getBlockSetting($block_id, 'title', '');
22172ac996dSGreg Roach            $story_body  = $this->getBlockSetting($block_id, 'story_body', '');
22272ac996dSGreg Roach            $languages   = explode(',', $this->getBlockSetting($block_id, 'languages'));
22372ac996dSGreg Roach
224cc13d6d8SGreg Roach            $title = I18N::translate('Edit the story') . ' — ' . e($tree->title());
22572ac996dSGreg Roach        }
22672ac996dSGreg Roach
22772ac996dSGreg Roach        return $this->viewResponse('modules/stories/edit', [
22872ac996dSGreg Roach            'block_id'    => $block_id,
22972ac996dSGreg Roach            'languages'   => $languages,
23072ac996dSGreg Roach            'story_body'  => $story_body,
23172ac996dSGreg Roach            'story_title' => $story_title,
23272ac996dSGreg Roach            'title'       => $title,
23372ac996dSGreg Roach            'tree'        => $tree,
23472ac996dSGreg Roach            'individual'  => $individual,
23572ac996dSGreg Roach        ]);
23672ac996dSGreg Roach    }
23772ac996dSGreg Roach
23872ac996dSGreg Roach    /**
23972ac996dSGreg Roach     * @param Request $request
240b6db7c1fSGreg Roach     * @param Tree    $tree
24172ac996dSGreg Roach     *
24272ac996dSGreg Roach     * @return RedirectResponse
24372ac996dSGreg Roach     */
244b6db7c1fSGreg Roach    public function postAdminEditAction(Request $request, Tree $tree): RedirectResponse
245c1010edaSGreg Roach    {
24672ac996dSGreg Roach        $block_id    = (int) $request->get('block_id');
24772ac996dSGreg Roach        $xref        = $request->get('xref', '');
24872ac996dSGreg Roach        $story_body  = $request->get('story_body', '');
24972ac996dSGreg Roach        $story_title = $request->get('story_title', '');
25072ac996dSGreg Roach        $languages   = $request->get('languages', []);
25172ac996dSGreg Roach
25272ac996dSGreg Roach        if ($block_id !== 0) {
2534b92b602SGreg Roach            DB::table('block')
2544b92b602SGreg Roach                ->where('block_id', '=', $block_id)
2554b92b602SGreg Roach                ->update([
2564b92b602SGreg Roach                    'gedcom_id' => $tree->id(),
25772ac996dSGreg Roach                    'xref'      => $xref,
25872ac996dSGreg Roach                ]);
25972ac996dSGreg Roach        } else {
2604b92b602SGreg Roach            DB::table('block')->insert([
2614b92b602SGreg Roach                'gedcom_id'   => $tree->id(),
26272ac996dSGreg Roach                'xref'        => $xref,
26326684e68SGreg Roach                'module_name' => $this->name(),
2644b92b602SGreg Roach                'block_order' => 0,
26572ac996dSGreg Roach            ]);
26672ac996dSGreg Roach
2674b92b602SGreg Roach            $block_id = (int) DB::connection()->getPdo()->lastInsertId();
26872ac996dSGreg Roach        }
26972ac996dSGreg Roach
27072ac996dSGreg Roach        $this->setBlockSetting($block_id, 'story_body', $story_body);
27172ac996dSGreg Roach        $this->setBlockSetting($block_id, 'title', $story_title);
27272ac996dSGreg Roach        $this->setBlockSetting($block_id, 'languages', implode(',', $languages));
27372ac996dSGreg Roach
274c1010edaSGreg Roach        $url = route('module', [
27526684e68SGreg Roach            'module' => $this->name(),
276c1010edaSGreg Roach            'action' => 'Admin',
277aa6f03bbSGreg Roach            'ged'    => $tree->name(),
278c1010edaSGreg Roach        ]);
27972ac996dSGreg Roach
28072ac996dSGreg Roach        return new RedirectResponse($url);
28172ac996dSGreg Roach    }
28272ac996dSGreg Roach
28372ac996dSGreg Roach    /**
28472ac996dSGreg Roach     * @param Request $request
285b6db7c1fSGreg Roach     * @param Tree    $tree
28672ac996dSGreg Roach     *
28772ac996dSGreg Roach     * @return Response
28872ac996dSGreg Roach     */
289b6db7c1fSGreg Roach    public function postAdminDeleteAction(Request $request, Tree $tree): Response
290c1010edaSGreg Roach    {
29172ac996dSGreg Roach        $block_id = (int) $request->get('block_id');
29272ac996dSGreg Roach
2934b92b602SGreg Roach        DB::table('block_setting')
2944b92b602SGreg Roach            ->where('block_id', '=', $block_id)
2954b92b602SGreg Roach            ->delete();
29672ac996dSGreg Roach
2974b92b602SGreg Roach        DB::table('block')
2984b92b602SGreg Roach            ->where('block_id', '=', $block_id)
2994b92b602SGreg Roach            ->delete();
30072ac996dSGreg Roach
301c1010edaSGreg Roach        $url = route('module', [
30226684e68SGreg Roach            'module' => $this->name(),
303c1010edaSGreg Roach            'action' => 'Admin',
304aa6f03bbSGreg Roach            'ged'    => $tree->name(),
305c1010edaSGreg Roach        ]);
30672ac996dSGreg Roach
30772ac996dSGreg Roach        return new RedirectResponse($url);
30872ac996dSGreg Roach    }
30972ac996dSGreg Roach
31072ac996dSGreg Roach    /**
311b6db7c1fSGreg Roach     * @param Tree $tree
31272ac996dSGreg Roach     *
31372ac996dSGreg Roach     * @return Response
31472ac996dSGreg Roach     */
315b6db7c1fSGreg Roach    public function getShowListAction(Tree $tree): Response
316c1010edaSGreg Roach    {
3174b92b602SGreg Roach        $stories = DB::table('block')
31826684e68SGreg Roach            ->where('module_name', '=', $this->name())
3194b92b602SGreg Roach            ->where('gedcom_id', '=', $tree->id())
3204b92b602SGreg Roach            ->get()
3214b92b602SGreg Roach            ->map(function (stdClass $story) use ($tree): stdClass {
3225db543e1SGreg Roach                $block_id = (int) $story->block_id;
3235db543e1SGreg Roach
32472ac996dSGreg Roach                $story->individual = Individual::getInstance($story->xref, $tree);
3255db543e1SGreg Roach                $story->title      = $this->getBlockSetting($block_id, 'title');
3265db543e1SGreg Roach                $story->languages  = $this->getBlockSetting($block_id, 'languages');
32772ac996dSGreg Roach
3284b92b602SGreg Roach                return $story;
329*0b5fd0a6SGreg Roach            })->filter(static function (stdClass $story): bool {
33072ac996dSGreg Roach                // Filter non-existant and private individuals.
3314b92b602SGreg Roach                return $story->individual instanceof Individual && $story->individual->canShow();
332*0b5fd0a6SGreg Roach            })->filter(static function (stdClass $story): bool {
33372ac996dSGreg Roach                // Filter foreign languages.
334a44b57a9SGreg Roach                return $story->languages === '' || in_array(WT_LOCALE, explode(',', $story->languages));
33572ac996dSGreg Roach            });
33672ac996dSGreg Roach
33772ac996dSGreg Roach        return $this->viewResponse('modules/stories/list', [
33872ac996dSGreg Roach            'stories' => $stories,
33949a243cbSGreg Roach            'title'   => $this->title(),
34072ac996dSGreg Roach        ]);
34172ac996dSGreg Roach    }
3428c2e8227SGreg Roach}
343