18c2e8227SGreg Roach<?php 23976b470SGreg Roach 38c2e8227SGreg Roach/** 48c2e8227SGreg Roach * webtrees: online genealogy 5d11be702SGreg Roach * Copyright (C) 2023 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 226f4ec3caSGreg Roachuse Fisharebest\Webtrees\DB; 231d1f373cSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\ControlPanel; 240e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N; 250e62c4b8SGreg Roachuse Fisharebest\Webtrees\Menu; 2650d6f48cSGreg Roachuse Fisharebest\Webtrees\Services\HtmlService; 271d1f373cSGreg Roachuse Fisharebest\Webtrees\Services\TreeService; 28431d5e92SGreg Roachuse Fisharebest\Webtrees\Site; 290e62c4b8SGreg Roachuse Fisharebest\Webtrees\Tree; 30b55cbc6bSGreg Roachuse Fisharebest\Webtrees\Validator; 3177654037SGreg Roachuse Illuminate\Database\Query\Builder; 3277654037SGreg Roachuse Illuminate\Support\Collection; 336ccdf4f0SGreg Roachuse Psr\Http\Message\ResponseInterface; 346ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface; 35f3874e19SGreg Roach 3610e06497SGreg Roachuse function in_array; 371d1f373cSGreg Roachuse function redirect; 381d1f373cSGreg Roachuse function route; 398c2e8227SGreg Roach 408c2e8227SGreg Roach/** 418c2e8227SGreg Roach * Class FrequentlyAskedQuestionsModule 428c2e8227SGreg Roach */ 4337eb8894SGreg Roachclass FrequentlyAskedQuestionsModule extends AbstractModule implements ModuleConfigInterface, ModuleMenuInterface 44c1010edaSGreg Roach{ 4549a243cbSGreg Roach use ModuleConfigTrait; 4649a243cbSGreg Roach use ModuleMenuTrait; 4749a243cbSGreg Roach 4843f2f523SGreg Roach private HtmlService $html_service; 4950d6f48cSGreg Roach 5043f2f523SGreg Roach private TreeService $tree_service; 511d1f373cSGreg Roach 5250d6f48cSGreg Roach /** 5350d6f48cSGreg Roach * @param HtmlService $html_service 541d1f373cSGreg Roach * @param TreeService $tree_service 5550d6f48cSGreg Roach */ 561d1f373cSGreg Roach public function __construct(HtmlService $html_service, TreeService $tree_service) 5750d6f48cSGreg Roach { 5850d6f48cSGreg Roach $this->html_service = $html_service; 591d1f373cSGreg Roach $this->tree_service = $tree_service; 6050d6f48cSGreg Roach } 6150d6f48cSGreg Roach 62961ec755SGreg Roach /** 630cfd6963SGreg Roach * How should this module be identified in the control panel, etc.? 64961ec755SGreg Roach * 65961ec755SGreg Roach * @return string 66961ec755SGreg Roach */ 6749a243cbSGreg Roach public function title(): string 68c1010edaSGreg Roach { 69bbb76c12SGreg Roach /* I18N: Name of a module. Abbreviation for “Frequently Asked Questions” */ 70bbb76c12SGreg Roach return I18N::translate('FAQ'); 718c2e8227SGreg Roach } 728c2e8227SGreg Roach 7349a243cbSGreg Roach public function description(): string 74c1010edaSGreg Roach { 75bbb76c12SGreg Roach /* I18N: Description of the “FAQ” module */ 76bbb76c12SGreg Roach return I18N::translate('A list of frequently asked questions and answers.'); 778c2e8227SGreg Roach } 788c2e8227SGreg Roach 7976692c8bSGreg Roach /** 8049a243cbSGreg Roach * The default position for this menu. It can be changed in the control panel. 810ee13198SGreg Roach * 820ee13198SGreg Roach * @return int 830ee13198SGreg Roach */ 848f53f488SRico Sonntag public function defaultMenuOrder(): int 85c1010edaSGreg Roach { 86353b36abSGreg Roach return 8; 878c2e8227SGreg Roach } 888c2e8227SGreg Roach 890ee13198SGreg Roach /** 900ee13198SGreg Roach * A menu, to be added to the main application menu. 910ee13198SGreg Roach * 92aee13b6dSGreg Roach * @param Tree $tree 93aee13b6dSGreg Roach * 940ee13198SGreg Roach * @return Menu|null 950ee13198SGreg Roach */ 961ff45046SGreg Roach public function getMenu(Tree $tree): Menu|null 97c1010edaSGreg Roach { 9865cf5706SGreg Roach if ($this->faqsExist($tree, I18N::languageTag())) { 9949a243cbSGreg Roach return new Menu($this->title(), route('module', [ 10026684e68SGreg Roach 'module' => $this->name(), 101c1010edaSGreg Roach 'action' => 'Show', 1029022ab66SGreg Roach 'tree' => $tree->name(), 10308362db4SGreg Roach ]), 'menu-faq'); 1048c2e8227SGreg Roach } 105b2ce94c6SRico Sonntag 106b2ce94c6SRico Sonntag return null; 1078c2e8227SGreg Roach } 108aee13b6dSGreg Roach 109aee13b6dSGreg Roach /** 11057ab2231SGreg Roach * @param ServerRequestInterface $request 111aee13b6dSGreg Roach * 1126ccdf4f0SGreg Roach * @return ResponseInterface 113aee13b6dSGreg Roach */ 11457ab2231SGreg Roach public function getAdminAction(ServerRequestInterface $request): ResponseInterface 115c1010edaSGreg Roach { 116aee13b6dSGreg Roach $this->layout = 'layouts/administration'; 117aee13b6dSGreg Roach 1181d1f373cSGreg Roach // This module can't run without a tree 119b55cbc6bSGreg Roach $tree = Validator::attributes($request)->treeOptional(); 120e218f363SGreg Roach 1211d1f373cSGreg Roach if (!$tree instanceof Tree) { 122431d5e92SGreg Roach $trees = $this->tree_service->all(); 123431d5e92SGreg Roach 124431d5e92SGreg Roach $tree = $trees->get(Site::getPreference('DEFAULT_GEDCOM')) ?? $trees->first(); 125431d5e92SGreg Roach 126e218f363SGreg Roach if ($tree instanceof Tree) { 127e218f363SGreg Roach return redirect(route('module', ['module' => $this->name(), 'action' => 'Admin', 'tree' => $tree->name()])); 128e218f363SGreg Roach } 129e218f363SGreg Roach 1301d1f373cSGreg Roach return redirect(route(ControlPanel::class)); 1311d1f373cSGreg Roach } 1325229eadeSGreg Roach 13326348dcdSGreg Roach $faqs = $this->faqsForTree($tree); 134aee13b6dSGreg Roach 135748dbe15SGreg Roach $min_block_order = (int) DB::table('block') 13626684e68SGreg Roach ->where('module_name', '=', $this->name()) 1370b5fd0a6SGreg Roach ->where(static function (Builder $query) use ($tree): void { 13877654037SGreg Roach $query 13977654037SGreg Roach ->whereNull('gedcom_id') 14077654037SGreg Roach ->orWhere('gedcom_id', '=', $tree->id()); 14177654037SGreg Roach }) 14277654037SGreg Roach ->min('block_order'); 143aee13b6dSGreg Roach 144748dbe15SGreg Roach $max_block_order = (int) DB::table('block') 14526684e68SGreg Roach ->where('module_name', '=', $this->name()) 1460b5fd0a6SGreg Roach ->where(static function (Builder $query) use ($tree): void { 14777654037SGreg Roach $query 14877654037SGreg Roach ->whereNull('gedcom_id') 14977654037SGreg Roach ->orWhere('gedcom_id', '=', $tree->id()); 15077654037SGreg Roach }) 15177654037SGreg Roach ->max('block_order'); 152aee13b6dSGreg Roach 153cc13d6d8SGreg Roach $title = I18N::translate('Frequently asked questions') . ' — ' . $tree->title(); 154aee13b6dSGreg Roach 155aee13b6dSGreg Roach return $this->viewResponse('modules/faq/config', [ 15683615acfSGreg Roach 'action' => route('module', ['module' => $this->name(), 'action' => 'Admin']), 157aee13b6dSGreg Roach 'faqs' => $faqs, 158aee13b6dSGreg Roach 'max_block_order' => $max_block_order, 159aee13b6dSGreg Roach 'min_block_order' => $min_block_order, 16071378461SGreg Roach 'module' => $this->name(), 161aee13b6dSGreg Roach 'title' => $title, 162aee13b6dSGreg Roach 'tree' => $tree, 1631e653452SGreg Roach 'tree_names' => $this->tree_service->titles(), 164aee13b6dSGreg Roach ]); 165aee13b6dSGreg Roach } 166aee13b6dSGreg Roach 167aee13b6dSGreg Roach /** 1686ccdf4f0SGreg Roach * @param ServerRequestInterface $request 169aee13b6dSGreg Roach * 1706ccdf4f0SGreg Roach * @return ResponseInterface 171aee13b6dSGreg Roach */ 172e218f363SGreg Roach public function postAdminAction(ServerRequestInterface $request): ResponseInterface 173e218f363SGreg Roach { 174e218f363SGreg Roach return redirect(route('module', [ 175e218f363SGreg Roach 'module' => $this->name(), 176e218f363SGreg Roach 'action' => 'Admin', 177748dbe15SGreg Roach 'tree' => Validator::parsedBody($request)->string('tree'), 178e218f363SGreg Roach ])); 179e218f363SGreg Roach } 180e218f363SGreg Roach 181e218f363SGreg Roach /** 182e218f363SGreg Roach * @param ServerRequestInterface $request 183e218f363SGreg Roach * 184e218f363SGreg Roach * @return ResponseInterface 185e218f363SGreg Roach */ 18657ab2231SGreg Roach public function postAdminDeleteAction(ServerRequestInterface $request): ResponseInterface 187c1010edaSGreg Roach { 188748dbe15SGreg Roach $block_id = Validator::queryParams($request)->integer('block_id'); 189aee13b6dSGreg Roach 19077654037SGreg Roach DB::table('block_setting')->where('block_id', '=', $block_id)->delete(); 191aee13b6dSGreg Roach 19277654037SGreg Roach DB::table('block')->where('block_id', '=', $block_id)->delete(); 193aee13b6dSGreg Roach 194c1010edaSGreg Roach $url = route('module', [ 19526684e68SGreg Roach 'module' => $this->name(), 196c1010edaSGreg Roach 'action' => 'Admin', 197c1010edaSGreg Roach ]); 198aee13b6dSGreg Roach 1996ccdf4f0SGreg Roach return redirect($url); 200aee13b6dSGreg Roach } 201aee13b6dSGreg Roach 202aee13b6dSGreg Roach /** 2036ccdf4f0SGreg Roach * @param ServerRequestInterface $request 204aee13b6dSGreg Roach * 2056ccdf4f0SGreg Roach * @return ResponseInterface 206aee13b6dSGreg Roach */ 20757ab2231SGreg Roach public function postAdminMoveDownAction(ServerRequestInterface $request): ResponseInterface 208c1010edaSGreg Roach { 209748dbe15SGreg Roach $block_id = Validator::queryParams($request)->integer('block_id'); 210aee13b6dSGreg Roach 21177654037SGreg Roach $block_order = DB::table('block') 21277654037SGreg Roach ->where('block_id', '=', $block_id) 21377654037SGreg Roach ->value('block_order'); 214aee13b6dSGreg Roach 21577654037SGreg Roach $swap_block = DB::table('block') 21626684e68SGreg Roach ->where('module_name', '=', $this->name()) 21777654037SGreg Roach ->where('block_order', '>', $block_order) 218a9866bf2SGreg Roach ->orderBy('block_order') 21977654037SGreg Roach ->first(); 220aee13b6dSGreg Roach 2211d1f373cSGreg Roach if ($block_order !== null && $swap_block !== null) { 22277654037SGreg Roach DB::table('block') 22377654037SGreg Roach ->where('block_id', '=', $block_id) 22477654037SGreg Roach ->update([ 225aee13b6dSGreg Roach 'block_order' => $swap_block->block_order, 226aee13b6dSGreg Roach ]); 22777654037SGreg Roach 22877654037SGreg Roach DB::table('block') 22977654037SGreg Roach ->where('block_id', '=', $swap_block->block_id) 23077654037SGreg Roach ->update([ 231aee13b6dSGreg Roach 'block_order' => $block_order, 232aee13b6dSGreg Roach ]); 233aee13b6dSGreg Roach } 234aee13b6dSGreg Roach 2351d1f373cSGreg Roach return response(); 236aee13b6dSGreg Roach } 237aee13b6dSGreg Roach 238aee13b6dSGreg Roach /** 2396ccdf4f0SGreg Roach * @param ServerRequestInterface $request 240aee13b6dSGreg Roach * 2416ccdf4f0SGreg Roach * @return ResponseInterface 242aee13b6dSGreg Roach */ 24357ab2231SGreg Roach public function postAdminMoveUpAction(ServerRequestInterface $request): ResponseInterface 244c1010edaSGreg Roach { 245748dbe15SGreg Roach $block_id = Validator::queryParams($request)->integer('block_id'); 246aee13b6dSGreg Roach 24777654037SGreg Roach $block_order = DB::table('block') 24877654037SGreg Roach ->where('block_id', '=', $block_id) 24977654037SGreg Roach ->value('block_order'); 250aee13b6dSGreg Roach 25177654037SGreg Roach $swap_block = DB::table('block') 25226684e68SGreg Roach ->where('module_name', '=', $this->name()) 25377654037SGreg Roach ->where('block_order', '<', $block_order) 2541d1f373cSGreg Roach ->orderBy('block_order', 'desc') 25577654037SGreg Roach ->first(); 256aee13b6dSGreg Roach 2571d1f373cSGreg Roach if ($block_order !== null && $swap_block !== null) { 25877654037SGreg Roach DB::table('block') 25977654037SGreg Roach ->where('block_id', '=', $block_id) 26077654037SGreg Roach ->update([ 261aee13b6dSGreg Roach 'block_order' => $swap_block->block_order, 262aee13b6dSGreg Roach ]); 26377654037SGreg Roach 26477654037SGreg Roach DB::table('block') 26577654037SGreg Roach ->where('block_id', '=', $swap_block->block_id) 26677654037SGreg Roach ->update([ 267aee13b6dSGreg Roach 'block_order' => $block_order, 268aee13b6dSGreg Roach ]); 269aee13b6dSGreg Roach } 270aee13b6dSGreg Roach 2711d1f373cSGreg Roach return response(); 272aee13b6dSGreg Roach } 273aee13b6dSGreg Roach 274aee13b6dSGreg Roach /** 2756ccdf4f0SGreg Roach * @param ServerRequestInterface $request 276aee13b6dSGreg Roach * 2776ccdf4f0SGreg Roach * @return ResponseInterface 278aee13b6dSGreg Roach */ 27957ab2231SGreg Roach public function getAdminEditAction(ServerRequestInterface $request): ResponseInterface 280c1010edaSGreg Roach { 281aee13b6dSGreg Roach $this->layout = 'layouts/administration'; 282aee13b6dSGreg Roach 283748dbe15SGreg Roach $block_id = Validator::queryParams($request)->integer('block_id', 0); 284aee13b6dSGreg Roach 285aee13b6dSGreg Roach if ($block_id === 0) { 286aee13b6dSGreg Roach // Creating a new faq 287aee13b6dSGreg Roach $header = ''; 2881e653452SGreg Roach $body = ''; 2891e653452SGreg Roach $gedcom_id = null; 2901e653452SGreg Roach $block_order = 1 + (int) DB::table('block')->where('module_name', '=', $this->name())->max('block_order'); 29177654037SGreg Roach 292aee13b6dSGreg Roach $languages = []; 293aee13b6dSGreg Roach 294aee13b6dSGreg Roach $title = I18N::translate('Add an FAQ'); 295aee13b6dSGreg Roach } else { 296aee13b6dSGreg Roach // Editing an existing faq 297aee13b6dSGreg Roach $header = $this->getBlockSetting($block_id, 'header'); 2981e653452SGreg Roach $body = $this->getBlockSetting($block_id, 'faqbody'); 2991e653452SGreg Roach $gedcom_id = DB::table('block')->where('block_id', '=', $block_id)->value('gedcom_id'); 3001e653452SGreg Roach $block_order = DB::table('block')->where('block_id', '=', $block_id)->value('block_order'); 30177654037SGreg Roach 302aee13b6dSGreg Roach $languages = explode(',', $this->getBlockSetting($block_id, 'languages')); 303aee13b6dSGreg Roach 304aee13b6dSGreg Roach $title = I18N::translate('Edit the FAQ'); 305aee13b6dSGreg Roach } 306aee13b6dSGreg Roach 3071e653452SGreg Roach $gedcom_ids = $this->tree_service->all() 308f25fc0f9SGreg Roach ->mapWithKeys(static fn (Tree $tree): array => [$tree->id() => $tree->title()]) 3091e653452SGreg Roach ->all(); 3101e653452SGreg Roach 3111e653452SGreg Roach $gedcom_ids = ['' => I18N::translate('All')] + $gedcom_ids; 312b6c326d8SGreg Roach 313aee13b6dSGreg Roach return $this->viewResponse('modules/faq/edit', [ 314aee13b6dSGreg Roach 'block_id' => $block_id, 315aee13b6dSGreg Roach 'block_order' => $block_order, 316aee13b6dSGreg Roach 'header' => $header, 3171e653452SGreg Roach 'body' => $body, 318aee13b6dSGreg Roach 'languages' => $languages, 319aee13b6dSGreg Roach 'title' => $title, 3201e653452SGreg Roach 'gedcom_id' => $gedcom_id, 3211e653452SGreg Roach 'gedcom_ids' => $gedcom_ids, 322aee13b6dSGreg Roach ]); 323aee13b6dSGreg Roach } 324aee13b6dSGreg Roach 325aee13b6dSGreg Roach /** 3266ccdf4f0SGreg Roach * @param ServerRequestInterface $request 327aee13b6dSGreg Roach * 3286ccdf4f0SGreg Roach * @return ResponseInterface 329aee13b6dSGreg Roach */ 33057ab2231SGreg Roach public function postAdminEditAction(ServerRequestInterface $request): ResponseInterface 331c1010edaSGreg Roach { 332748dbe15SGreg Roach $block_id = Validator::queryParams($request)->integer('block_id', 0); 333748dbe15SGreg Roach $body = Validator::parsedBody($request)->string('body'); 334748dbe15SGreg Roach $header = Validator::parsedBody($request)->string('header'); 335748dbe15SGreg Roach $languages = Validator::parsedBody($request)->array('languages'); 336748dbe15SGreg Roach $gedcom_id = Validator::parsedBody($request)->string('gedcom_id'); 337748dbe15SGreg Roach $block_order = Validator::parsedBody($request)->integer('block_order'); 338aee13b6dSGreg Roach 3391e653452SGreg Roach if ($gedcom_id === '') { 3401e653452SGreg Roach $gedcom_id = null; 3411e653452SGreg Roach } 3421e653452SGreg Roach 3431e653452SGreg Roach $body = $this->html_service->sanitize($body); 34450d6f48cSGreg Roach $header = $this->html_service->sanitize($header); 34550d6f48cSGreg Roach 346aee13b6dSGreg Roach if ($block_id !== 0) { 34777654037SGreg Roach DB::table('block') 34877654037SGreg Roach ->where('block_id', '=', $block_id) 34977654037SGreg Roach ->update([ 35077654037SGreg Roach 'gedcom_id' => $gedcom_id, 35177654037SGreg Roach 'block_order' => $block_order, 352aee13b6dSGreg Roach ]); 353aee13b6dSGreg Roach } else { 35477654037SGreg Roach DB::table('block')->insert([ 35577654037SGreg Roach 'gedcom_id' => $gedcom_id, 35626684e68SGreg Roach 'module_name' => $this->name(), 35777654037SGreg Roach 'block_order' => $block_order, 358aee13b6dSGreg Roach ]); 359aee13b6dSGreg Roach 360*4c96e13dSGreg Roach $block_id = DB::lastInsertId(); 361aee13b6dSGreg Roach } 362aee13b6dSGreg Roach 3631e653452SGreg Roach $this->setBlockSetting($block_id, 'faqbody', $body); 364aee13b6dSGreg Roach $this->setBlockSetting($block_id, 'header', $header); 365aee13b6dSGreg Roach $this->setBlockSetting($block_id, 'languages', implode(',', $languages)); 366aee13b6dSGreg Roach 367c1010edaSGreg Roach $url = route('module', [ 36826684e68SGreg Roach 'module' => $this->name(), 369c1010edaSGreg Roach 'action' => 'Admin', 370c1010edaSGreg Roach ]); 371aee13b6dSGreg Roach 3726ccdf4f0SGreg Roach return redirect($url); 373aee13b6dSGreg Roach } 374aee13b6dSGreg Roach 375b998dbceSGreg Roach /** 37657ab2231SGreg Roach * @param ServerRequestInterface $request 377b998dbceSGreg Roach * 3786ccdf4f0SGreg Roach * @return ResponseInterface 379b998dbceSGreg Roach */ 38057ab2231SGreg Roach public function getShowAction(ServerRequestInterface $request): ResponseInterface 381c1010edaSGreg Roach { 382b55cbc6bSGreg Roach $tree = Validator::attributes($request)->tree(); 38357ab2231SGreg Roach 3848de50a4eSGreg Roach // Filter foreign languages. 38577654037SGreg Roach $faqs = $this->faqsForTree($tree) 386f25fc0f9SGreg Roach ->filter(static fn (object $faq): bool => $faq->languages === '' || in_array(I18N::languageTag(), explode(',', $faq->languages), true)); 387aee13b6dSGreg Roach 388aee13b6dSGreg Roach return $this->viewResponse('modules/faq/show', [ 3898de50a4eSGreg Roach 'faqs' => $faqs, 390aee13b6dSGreg Roach 'title' => I18N::translate('Frequently asked questions'), 3918de50a4eSGreg Roach 'tree' => $tree, 392aee13b6dSGreg Roach ]); 393aee13b6dSGreg Roach } 39477654037SGreg Roach 39577654037SGreg Roach /** 39677654037SGreg Roach * @param Tree $tree 39777654037SGreg Roach * 39836779af1SGreg Roach * @return Collection<int,object> 39977654037SGreg Roach */ 40077654037SGreg Roach private function faqsForTree(Tree $tree): Collection 40177654037SGreg Roach { 40277654037SGreg Roach return DB::table('block') 40377654037SGreg Roach ->join('block_setting AS bs1', 'bs1.block_id', '=', 'block.block_id') 40477654037SGreg Roach ->join('block_setting AS bs2', 'bs2.block_id', '=', 'block.block_id') 40577654037SGreg Roach ->join('block_setting AS bs3', 'bs3.block_id', '=', 'block.block_id') 40626684e68SGreg Roach ->where('module_name', '=', $this->name()) 40777654037SGreg Roach ->where('bs1.setting_name', '=', 'header') 40877654037SGreg Roach ->where('bs2.setting_name', '=', 'faqbody') 40977654037SGreg Roach ->where('bs3.setting_name', '=', 'languages') 4100b5fd0a6SGreg Roach ->where(static function (Builder $query) use ($tree): void { 41177654037SGreg Roach $query 41277654037SGreg Roach ->whereNull('gedcom_id') 41377654037SGreg Roach ->orWhere('gedcom_id', '=', $tree->id()); 41477654037SGreg Roach }) 41577654037SGreg Roach ->orderBy('block_order') 41677654037SGreg Roach ->select(['block.block_id', 'block_order', 'gedcom_id', 'bs1.setting_value AS header', 'bs2.setting_value AS faqbody', 'bs3.setting_value AS languages']) 417748dbe15SGreg Roach ->get() 418748dbe15SGreg Roach ->map(static function (object $row): object { 419748dbe15SGreg Roach $row->block_id = (int) $row->block_id; 420748dbe15SGreg Roach $row->block_order = (int) $row->block_order; 421748dbe15SGreg Roach $row->gedcom_id = (int) $row->gedcom_id; 422748dbe15SGreg Roach 423748dbe15SGreg Roach return $row; 424748dbe15SGreg Roach }); 42577654037SGreg Roach } 42677654037SGreg Roach 42777654037SGreg Roach /** 42877654037SGreg Roach * @param Tree $tree 42977654037SGreg Roach * @param string $language 43077654037SGreg Roach * 43177654037SGreg Roach * @return bool 43277654037SGreg Roach */ 43377654037SGreg Roach private function faqsExist(Tree $tree, string $language): bool 43477654037SGreg Roach { 43577654037SGreg Roach return DB::table('block') 43677654037SGreg Roach ->join('block_setting', 'block_setting.block_id', '=', 'block.block_id') 43726684e68SGreg Roach ->where('module_name', '=', $this->name()) 43877654037SGreg Roach ->where('setting_name', '=', 'languages') 4390b5fd0a6SGreg Roach ->where(static function (Builder $query) use ($tree): void { 44077654037SGreg Roach $query 44177654037SGreg Roach ->whereNull('gedcom_id') 44277654037SGreg Roach ->orWhere('gedcom_id', '=', $tree->id()); 44377654037SGreg Roach }) 44477654037SGreg Roach ->select(['setting_value AS languages']) 44577654037SGreg Roach ->get() 446f25fc0f9SGreg Roach ->filter(static fn (object $faq): bool => $faq->languages === '' || in_array($language, explode(',', $faq->languages), true)) 44777654037SGreg Roach ->isNotEmpty(); 44877654037SGreg Roach } 4498c2e8227SGreg Roach} 450