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 */ 3449a243cbSGreg Roachclass StoriesModule extends AbstractModule implements ModuleInterface, 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 438c2e8227SGreg Roach /** {@inheritdoc} */ 4449a243cbSGreg Roach public function title(): string 45c1010edaSGreg Roach { 46bbb76c12SGreg Roach /* I18N: Name of a module */ 47bbb76c12SGreg Roach return I18N::translate('Stories'); 488c2e8227SGreg Roach } 498c2e8227SGreg Roach 508c2e8227SGreg Roach /** {@inheritdoc} */ 5149a243cbSGreg Roach public function description(): string 52c1010edaSGreg Roach { 53bbb76c12SGreg Roach /* I18N: Description of the “Stories” module */ 54bbb76c12SGreg Roach return I18N::translate('Add narrative stories to individuals in the family tree.'); 558c2e8227SGreg Roach } 568c2e8227SGreg Roach 57aee13b6dSGreg Roach /** 5849a243cbSGreg Roach * The default position for this menu. It can be changed in the control panel. 59aee13b6dSGreg Roach * 6049a243cbSGreg Roach * @return int 61aee13b6dSGreg Roach */ 6249a243cbSGreg Roach public function defaultMenuOrder(): int 63c1010edaSGreg Roach { 64*46295629SGreg Roach return 70; 658c2e8227SGreg Roach } 668c2e8227SGreg Roach 6749a243cbSGreg Roach /** 6849a243cbSGreg Roach * The default position for this tab. It can be changed in the control panel. 6949a243cbSGreg Roach * 7049a243cbSGreg Roach * @return int 7149a243cbSGreg Roach */ 72cbf4b7faSGreg Roach public function defaultTabOrder(): int 73cbf4b7faSGreg Roach { 7449a243cbSGreg Roach return 70; 758c2e8227SGreg Roach } 768c2e8227SGreg Roach 778c2e8227SGreg Roach /** {@inheritdoc} */ 789b34404bSGreg Roach public function getTabContent(Individual $individual): string 79c1010edaSGreg Roach { 8072ac996dSGreg Roach return view('modules/stories/tab', [ 8172ac996dSGreg Roach 'is_admin' => Auth::isAdmin(), 82225e381fSGreg Roach 'individual' => $individual, 83225e381fSGreg Roach 'stories' => $this->getStoriesForIndividual($individual), 84225e381fSGreg Roach ]); 858c2e8227SGreg Roach } 868c2e8227SGreg Roach 878c2e8227SGreg Roach /** {@inheritdoc} */ 889b34404bSGreg Roach public function hasTabContent(Individual $individual): bool 89c1010edaSGreg Roach { 90f4afa648SGreg Roach return Auth::isManager($individual->tree()) || !empty($this->getStoriesForIndividual($individual)); 918c2e8227SGreg Roach } 928c2e8227SGreg Roach 938c2e8227SGreg Roach /** {@inheritdoc} */ 949b34404bSGreg Roach public function isGrayedOut(Individual $individual): bool 95c1010edaSGreg Roach { 96225e381fSGreg Roach return !empty($this->getStoriesForIndividual($individual)); 978c2e8227SGreg Roach } 988c2e8227SGreg Roach 998c2e8227SGreg Roach /** {@inheritdoc} */ 1009b34404bSGreg Roach public function canLoadAjax(): bool 101c1010edaSGreg Roach { 1028c2e8227SGreg Roach return false; 1038c2e8227SGreg Roach } 1048c2e8227SGreg Roach 105225e381fSGreg Roach /** 106225e381fSGreg Roach * @param Individual $individual 107225e381fSGreg Roach * 108225e381fSGreg Roach * @return stdClass[] 109225e381fSGreg Roach */ 110c1010edaSGreg Roach private function getStoriesForIndividual(Individual $individual): array 111c1010edaSGreg Roach { 1124b92b602SGreg Roach $block_ids = DB::table('block') 1134b92b602SGreg Roach ->where('module_name', '=', $this->getName()) 1144b92b602SGreg Roach ->where('xref', '=', $individual->xref()) 1154b92b602SGreg Roach ->where('gedcom_id', '=', $individual->tree()->id()) 1164b92b602SGreg Roach ->pluck('block_id'); 117225e381fSGreg Roach 118225e381fSGreg Roach $stories = []; 119225e381fSGreg Roach foreach ($block_ids as $block_id) { 1207d988ec3SGreg Roach $block_id = (int) $block_id; 1217d988ec3SGreg Roach 122225e381fSGreg Roach // Only show this block for certain languages 123225e381fSGreg Roach $languages = $this->getBlockSetting($block_id, 'languages', ''); 124225e381fSGreg Roach if ($languages === '' || in_array(WT_LOCALE, explode(',', $languages))) { 125225e381fSGreg Roach $stories[] = (object) [ 126225e381fSGreg Roach 'block_id' => $block_id, 127225e381fSGreg Roach 'title' => $this->getBlockSetting($block_id, 'title'), 12872ac996dSGreg Roach 'story_body' => $this->getBlockSetting($block_id, 'story_body'), 129225e381fSGreg Roach ]; 130225e381fSGreg Roach } 131225e381fSGreg Roach } 132225e381fSGreg Roach 133225e381fSGreg Roach return $stories; 1348c2e8227SGreg Roach } 1358c2e8227SGreg Roach 1368c2e8227SGreg Roach /** 1370ee13198SGreg Roach * A menu, to be added to the main application menu. 1380ee13198SGreg Roach * 139aee13b6dSGreg Roach * @param Tree $tree 140aee13b6dSGreg Roach * 1410ee13198SGreg Roach * @return Menu|null 1420ee13198SGreg Roach */ 143*46295629SGreg Roach public function getMenu(Tree $tree): ?Menu 144c1010edaSGreg Roach { 14549a243cbSGreg Roach $menu = new Menu($this->title(), route('module', [ 146c1010edaSGreg Roach 'module' => $this->getName(), 147c1010edaSGreg Roach 'action' => 'ShowList', 148aa6f03bbSGreg Roach 'ged' => $tree->name(), 149c1010edaSGreg Roach ]), 'menu-story'); 1508c2e8227SGreg Roach 1518c2e8227SGreg Roach return $menu; 1528c2e8227SGreg Roach } 15372ac996dSGreg Roach 15472ac996dSGreg Roach /** 155b6db7c1fSGreg Roach * @param Tree $tree 15672ac996dSGreg Roach * 15772ac996dSGreg Roach * @return Response 15872ac996dSGreg Roach */ 159b6db7c1fSGreg Roach public function getAdminAction(Tree $tree): Response 160c1010edaSGreg Roach { 16172ac996dSGreg Roach $this->layout = 'layouts/administration'; 16272ac996dSGreg Roach 1634b92b602SGreg Roach $stories = DB::table('block') 1644b92b602SGreg Roach ->where('module_name', '=', $this->getName()) 1654b92b602SGreg Roach ->where('gedcom_id', '=', $tree->id()) 1664b92b602SGreg Roach ->orderBy('xref') 1674b92b602SGreg Roach ->get(); 16872ac996dSGreg Roach 16972ac996dSGreg Roach foreach ($stories as $story) { 1705db543e1SGreg Roach $block_id = (int) $story->block_id; 1715db543e1SGreg Roach 17272ac996dSGreg Roach $story->individual = Individual::getInstance($story->xref, $tree); 1735db543e1SGreg Roach $story->title = $this->getBlockSetting($block_id, 'title'); 1745db543e1SGreg Roach $story->languages = $this->getBlockSetting($block_id, 'languages'); 17572ac996dSGreg Roach } 17672ac996dSGreg Roach 17772ac996dSGreg Roach return $this->viewResponse('modules/stories/config', [ 17872ac996dSGreg Roach 'stories' => $stories, 17949a243cbSGreg Roach 'title' => $this->title() . ' — ' . $tree->title(), 18072ac996dSGreg Roach 'tree' => $tree, 18172ac996dSGreg Roach 'tree_names' => Tree::getNameList(), 18272ac996dSGreg Roach ]); 18372ac996dSGreg Roach } 18472ac996dSGreg Roach 18572ac996dSGreg Roach /** 18672ac996dSGreg Roach * @param Request $request 187b6db7c1fSGreg Roach * @param Tree $tree 18872ac996dSGreg Roach * 18972ac996dSGreg Roach * @return Response 19072ac996dSGreg Roach */ 191b6db7c1fSGreg Roach public function getAdminEditAction(Request $request, Tree $tree): Response 192c1010edaSGreg Roach { 19372ac996dSGreg Roach $this->layout = 'layouts/administration'; 19472ac996dSGreg Roach 19572ac996dSGreg Roach $block_id = (int) $request->get('block_id'); 19672ac996dSGreg Roach 19772ac996dSGreg Roach if ($block_id === 0) { 19872ac996dSGreg Roach // Creating a new story 19972ac996dSGreg Roach $individual = Individual::getInstance($request->get('xref', ''), $tree); 20072ac996dSGreg Roach $story_title = ''; 20172ac996dSGreg Roach $story_body = ''; 20272ac996dSGreg Roach $languages = []; 20372ac996dSGreg Roach 204cc13d6d8SGreg Roach $title = I18N::translate('Add a story') . ' — ' . e($tree->title()); 20572ac996dSGreg Roach } else { 20672ac996dSGreg Roach // Editing an existing story 2074b92b602SGreg Roach $xref = (string) DB::table('block') 2084b92b602SGreg Roach ->where('block_id', '=', $block_id) 2094b92b602SGreg Roach ->value('xref'); 21072ac996dSGreg Roach 21172ac996dSGreg Roach $individual = Individual::getInstance($xref, $tree); 21272ac996dSGreg Roach $story_title = $this->getBlockSetting($block_id, 'title', ''); 21372ac996dSGreg Roach $story_body = $this->getBlockSetting($block_id, 'story_body', ''); 21472ac996dSGreg Roach $languages = explode(',', $this->getBlockSetting($block_id, 'languages')); 21572ac996dSGreg Roach 216cc13d6d8SGreg Roach $title = I18N::translate('Edit the story') . ' — ' . e($tree->title()); 21772ac996dSGreg Roach } 21872ac996dSGreg Roach 21972ac996dSGreg Roach return $this->viewResponse('modules/stories/edit', [ 22072ac996dSGreg Roach 'block_id' => $block_id, 22172ac996dSGreg Roach 'languages' => $languages, 22272ac996dSGreg Roach 'story_body' => $story_body, 22372ac996dSGreg Roach 'story_title' => $story_title, 22472ac996dSGreg Roach 'title' => $title, 22572ac996dSGreg Roach 'tree' => $tree, 22672ac996dSGreg Roach 'individual' => $individual, 22772ac996dSGreg Roach ]); 22872ac996dSGreg Roach } 22972ac996dSGreg Roach 23072ac996dSGreg Roach /** 23172ac996dSGreg Roach * @param Request $request 232b6db7c1fSGreg Roach * @param Tree $tree 23372ac996dSGreg Roach * 23472ac996dSGreg Roach * @return RedirectResponse 23572ac996dSGreg Roach */ 236b6db7c1fSGreg Roach public function postAdminEditAction(Request $request, Tree $tree): RedirectResponse 237c1010edaSGreg Roach { 23872ac996dSGreg Roach $block_id = (int) $request->get('block_id'); 23972ac996dSGreg Roach $xref = $request->get('xref', ''); 24072ac996dSGreg Roach $story_body = $request->get('story_body', ''); 24172ac996dSGreg Roach $story_title = $request->get('story_title', ''); 24272ac996dSGreg Roach $languages = $request->get('languages', []); 24372ac996dSGreg Roach 24472ac996dSGreg Roach if ($block_id !== 0) { 2454b92b602SGreg Roach DB::table('block') 2464b92b602SGreg Roach ->where('block_id', '=', $block_id) 2474b92b602SGreg Roach ->update([ 2484b92b602SGreg Roach 'gedcom_id' => $tree->id(), 24972ac996dSGreg Roach 'xref' => $xref, 25072ac996dSGreg Roach ]); 25172ac996dSGreg Roach } else { 2524b92b602SGreg Roach DB::table('block')->insert([ 2534b92b602SGreg Roach 'gedcom_id' => $tree->id(), 25472ac996dSGreg Roach 'xref' => $xref, 2554b92b602SGreg Roach 'module_name' => $this->getName(), 2564b92b602SGreg Roach 'block_order' => 0, 25772ac996dSGreg Roach ]); 25872ac996dSGreg Roach 2594b92b602SGreg Roach $block_id = (int) DB::connection()->getPdo()->lastInsertId(); 26072ac996dSGreg Roach } 26172ac996dSGreg Roach 26272ac996dSGreg Roach $this->setBlockSetting($block_id, 'story_body', $story_body); 26372ac996dSGreg Roach $this->setBlockSetting($block_id, 'title', $story_title); 26472ac996dSGreg Roach $this->setBlockSetting($block_id, 'languages', implode(',', $languages)); 26572ac996dSGreg Roach 266c1010edaSGreg Roach $url = route('module', [ 26749a243cbSGreg Roach 'module' => $this->getName(), 268c1010edaSGreg Roach 'action' => 'Admin', 269aa6f03bbSGreg Roach 'ged' => $tree->name(), 270c1010edaSGreg Roach ]); 27172ac996dSGreg Roach 27272ac996dSGreg Roach return new RedirectResponse($url); 27372ac996dSGreg Roach } 27472ac996dSGreg Roach 27572ac996dSGreg Roach /** 27672ac996dSGreg Roach * @param Request $request 277b6db7c1fSGreg Roach * @param Tree $tree 27872ac996dSGreg Roach * 27972ac996dSGreg Roach * @return Response 28072ac996dSGreg Roach */ 281b6db7c1fSGreg Roach public function postAdminDeleteAction(Request $request, Tree $tree): Response 282c1010edaSGreg Roach { 28372ac996dSGreg Roach $block_id = (int) $request->get('block_id'); 28472ac996dSGreg Roach 2854b92b602SGreg Roach DB::table('block_setting') 2864b92b602SGreg Roach ->where('block_id', '=', $block_id) 2874b92b602SGreg Roach ->delete(); 28872ac996dSGreg Roach 2894b92b602SGreg Roach DB::table('block') 2904b92b602SGreg Roach ->where('block_id', '=', $block_id) 2914b92b602SGreg Roach ->delete(); 29272ac996dSGreg Roach 293c1010edaSGreg Roach $url = route('module', [ 29449a243cbSGreg Roach 'module' => $this->getName(), 295c1010edaSGreg Roach 'action' => 'Admin', 296aa6f03bbSGreg Roach 'ged' => $tree->name(), 297c1010edaSGreg Roach ]); 29872ac996dSGreg Roach 29972ac996dSGreg Roach return new RedirectResponse($url); 30072ac996dSGreg Roach } 30172ac996dSGreg Roach 30272ac996dSGreg Roach /** 303b6db7c1fSGreg Roach * @param Tree $tree 30472ac996dSGreg Roach * 30572ac996dSGreg Roach * @return Response 30672ac996dSGreg Roach */ 307b6db7c1fSGreg Roach public function getShowListAction(Tree $tree): Response 308c1010edaSGreg Roach { 3094b92b602SGreg Roach $stories = DB::table('block') 3104b92b602SGreg Roach ->where('module_name', '=', $this->getName()) 3114b92b602SGreg Roach ->where('gedcom_id', '=', $tree->id()) 3124b92b602SGreg Roach ->get() 3134b92b602SGreg Roach ->map(function (stdClass $story) use ($tree): stdClass { 3145db543e1SGreg Roach $block_id = (int) $story->block_id; 3155db543e1SGreg Roach 31672ac996dSGreg Roach $story->individual = Individual::getInstance($story->xref, $tree); 3175db543e1SGreg Roach $story->title = $this->getBlockSetting($block_id, 'title'); 3185db543e1SGreg Roach $story->languages = $this->getBlockSetting($block_id, 'languages'); 31972ac996dSGreg Roach 3204b92b602SGreg Roach return $story; 3214b92b602SGreg Roach })->filter(function (stdClass $story): bool { 32272ac996dSGreg Roach // Filter non-existant and private individuals. 3234b92b602SGreg Roach return $story->individual instanceof Individual && $story->individual->canShow(); 3244b92b602SGreg Roach })->filter(function (stdClass $story): bool { 32572ac996dSGreg Roach // Filter foreign languages. 326a44b57a9SGreg Roach return $story->languages === '' || in_array(WT_LOCALE, explode(',', $story->languages)); 32772ac996dSGreg Roach }); 32872ac996dSGreg Roach 32972ac996dSGreg Roach return $this->viewResponse('modules/stories/list', [ 33072ac996dSGreg Roach 'stories' => $stories, 33149a243cbSGreg Roach 'title' => $this->title(), 33272ac996dSGreg Roach ]); 33372ac996dSGreg Roach } 3348c2e8227SGreg Roach} 335