18c2e8227SGreg Roach<?php 23976b470SGreg Roach 38c2e8227SGreg Roach/** 48c2e8227SGreg Roach * webtrees: online genealogy 58fcd0d32SGreg Roach * Copyright (C) 2019 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 158c2e8227SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>. 168c2e8227SGreg Roach */ 17fcfa147eSGreg Roach 18e7f56f2aSGreg Roachdeclare(strict_types=1); 19e7f56f2aSGreg Roach 2076692c8bSGreg Roachnamespace Fisharebest\Webtrees\Module; 2176692c8bSGreg Roach 22*1d1f373cSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\ControlPanel; 230e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N; 240e62c4b8SGreg Roachuse Fisharebest\Webtrees\Menu; 2550d6f48cSGreg Roachuse Fisharebest\Webtrees\Services\HtmlService; 26*1d1f373cSGreg Roachuse Fisharebest\Webtrees\Services\TreeService; 270e62c4b8SGreg Roachuse Fisharebest\Webtrees\Tree; 2877654037SGreg Roachuse Illuminate\Database\Capsule\Manager as DB; 2977654037SGreg Roachuse Illuminate\Database\Query\Builder; 3077654037SGreg Roachuse Illuminate\Support\Collection; 315229eadeSGreg Roachuse InvalidArgumentException; 326ccdf4f0SGreg Roachuse Psr\Http\Message\ResponseInterface; 336ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface; 348de50a4eSGreg Roachuse stdClass; 35f3874e19SGreg Roach 365229eadeSGreg Roachuse function assert; 37*1d1f373cSGreg Roachuse function redirect; 38*1d1f373cSGreg 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 4850d6f48cSGreg Roach /** @var HtmlService */ 4950d6f48cSGreg Roach private $html_service; 5050d6f48cSGreg Roach 51*1d1f373cSGreg Roach /** @var TreeService */ 52*1d1f373cSGreg Roach private $tree_service; 53*1d1f373cSGreg Roach 5450d6f48cSGreg Roach /** 55*1d1f373cSGreg Roach * BatchUpdateModule constructor. 5650d6f48cSGreg Roach * 5750d6f48cSGreg Roach * @param HtmlService $html_service 58*1d1f373cSGreg Roach * @param TreeService $tree_service 5950d6f48cSGreg Roach */ 60*1d1f373cSGreg Roach public function __construct(HtmlService $html_service, TreeService $tree_service) 6150d6f48cSGreg Roach { 6250d6f48cSGreg Roach $this->html_service = $html_service; 63*1d1f373cSGreg Roach $this->tree_service = $tree_service; 6450d6f48cSGreg Roach } 6550d6f48cSGreg Roach 66961ec755SGreg Roach /** 670cfd6963SGreg Roach * How should this module be identified in the control panel, etc.? 68961ec755SGreg Roach * 69961ec755SGreg Roach * @return string 70961ec755SGreg Roach */ 7149a243cbSGreg Roach public function title(): string 72c1010edaSGreg Roach { 73bbb76c12SGreg Roach /* I18N: Name of a module. Abbreviation for “Frequently Asked Questions” */ 74bbb76c12SGreg Roach return I18N::translate('FAQ'); 758c2e8227SGreg Roach } 768c2e8227SGreg Roach 77961ec755SGreg Roach /** 78961ec755SGreg Roach * A sentence describing what this module does. 79961ec755SGreg Roach * 80961ec755SGreg Roach * @return string 81961ec755SGreg Roach */ 8249a243cbSGreg Roach public function description(): string 83c1010edaSGreg Roach { 84bbb76c12SGreg Roach /* I18N: Description of the “FAQ” module */ 85bbb76c12SGreg Roach return I18N::translate('A list of frequently asked questions and answers.'); 868c2e8227SGreg Roach } 878c2e8227SGreg Roach 8876692c8bSGreg Roach /** 8949a243cbSGreg Roach * The default position for this menu. It can be changed in the control panel. 900ee13198SGreg Roach * 910ee13198SGreg Roach * @return int 920ee13198SGreg Roach */ 938f53f488SRico Sonntag public function defaultMenuOrder(): int 94c1010edaSGreg Roach { 95353b36abSGreg Roach return 8; 968c2e8227SGreg Roach } 978c2e8227SGreg Roach 980ee13198SGreg Roach /** 990ee13198SGreg Roach * A menu, to be added to the main application menu. 1000ee13198SGreg Roach * 101aee13b6dSGreg Roach * @param Tree $tree 102aee13b6dSGreg Roach * 1030ee13198SGreg Roach * @return Menu|null 1040ee13198SGreg Roach */ 10546295629SGreg Roach public function getMenu(Tree $tree): ?Menu 106c1010edaSGreg Roach { 10777654037SGreg Roach if ($this->faqsExist($tree, WT_LOCALE)) { 10849a243cbSGreg Roach return new Menu($this->title(), route('module', [ 10926684e68SGreg Roach 'module' => $this->name(), 110c1010edaSGreg Roach 'action' => 'Show', 1119022ab66SGreg Roach 'tree' => $tree->name(), 112c1010edaSGreg Roach ]), 'menu-help'); 1138c2e8227SGreg Roach } 114b2ce94c6SRico Sonntag 115b2ce94c6SRico Sonntag return null; 1168c2e8227SGreg Roach } 117aee13b6dSGreg Roach 118aee13b6dSGreg Roach /** 11957ab2231SGreg Roach * @param ServerRequestInterface $request 120aee13b6dSGreg Roach * 1216ccdf4f0SGreg Roach * @return ResponseInterface 122aee13b6dSGreg Roach */ 12357ab2231SGreg Roach public function getAdminAction(ServerRequestInterface $request): ResponseInterface 124c1010edaSGreg Roach { 125aee13b6dSGreg Roach $this->layout = 'layouts/administration'; 126aee13b6dSGreg Roach 127*1d1f373cSGreg Roach // This module can't run without a tree 128*1d1f373cSGreg Roach $tree = $request->getQueryParams()['tree'] ?? ''; 129*1d1f373cSGreg Roach $tree = $this->tree_service->findByName($tree) ?? $this->tree_service->all()->first(); 130*1d1f373cSGreg Roach if (!$tree instanceof Tree) { 131*1d1f373cSGreg Roach return redirect(route(ControlPanel::class)); 132*1d1f373cSGreg Roach } 1335229eadeSGreg Roach 13426348dcdSGreg Roach $faqs = $this->faqsForTree($tree); 135aee13b6dSGreg Roach 13677654037SGreg Roach $min_block_order = DB::table('block') 13726684e68SGreg Roach ->where('module_name', '=', $this->name()) 1380b5fd0a6SGreg Roach ->where(static function (Builder $query) use ($tree): void { 13977654037SGreg Roach $query 14077654037SGreg Roach ->whereNull('gedcom_id') 14177654037SGreg Roach ->orWhere('gedcom_id', '=', $tree->id()); 14277654037SGreg Roach }) 14377654037SGreg Roach ->min('block_order'); 144aee13b6dSGreg Roach 14577654037SGreg Roach $max_block_order = DB::table('block') 14626684e68SGreg Roach ->where('module_name', '=', $this->name()) 1470b5fd0a6SGreg Roach ->where(static function (Builder $query) use ($tree): void { 14877654037SGreg Roach $query 14977654037SGreg Roach ->whereNull('gedcom_id') 15077654037SGreg Roach ->orWhere('gedcom_id', '=', $tree->id()); 15177654037SGreg Roach }) 15277654037SGreg Roach ->max('block_order'); 153aee13b6dSGreg Roach 154cc13d6d8SGreg Roach $title = I18N::translate('Frequently asked questions') . ' — ' . $tree->title(); 155aee13b6dSGreg Roach 156aee13b6dSGreg Roach return $this->viewResponse('modules/faq/config', [ 15783615acfSGreg Roach 'action' => route('module', ['module' => $this->name(), 'action' => 'Admin']), 158aee13b6dSGreg Roach 'faqs' => $faqs, 159aee13b6dSGreg Roach 'max_block_order' => $max_block_order, 160aee13b6dSGreg Roach 'min_block_order' => $min_block_order, 16171378461SGreg Roach 'module' => $this->name(), 162aee13b6dSGreg Roach 'title' => $title, 163aee13b6dSGreg Roach 'tree' => $tree, 164aee13b6dSGreg Roach 'tree_names' => Tree::getNameList(), 165aee13b6dSGreg Roach ]); 166aee13b6dSGreg Roach } 167aee13b6dSGreg Roach 168aee13b6dSGreg Roach /** 1696ccdf4f0SGreg Roach * @param ServerRequestInterface $request 170aee13b6dSGreg Roach * 1716ccdf4f0SGreg Roach * @return ResponseInterface 172aee13b6dSGreg Roach */ 17357ab2231SGreg Roach public function postAdminDeleteAction(ServerRequestInterface $request): ResponseInterface 174c1010edaSGreg Roach { 175eb235819SGreg Roach $block_id = (int) $request->getQueryParams()['block_id']; 176aee13b6dSGreg Roach 17777654037SGreg Roach DB::table('block_setting')->where('block_id', '=', $block_id)->delete(); 178aee13b6dSGreg Roach 17977654037SGreg Roach DB::table('block')->where('block_id', '=', $block_id)->delete(); 180aee13b6dSGreg Roach 181c1010edaSGreg Roach $url = route('module', [ 18226684e68SGreg Roach 'module' => $this->name(), 183c1010edaSGreg Roach 'action' => 'Admin', 184c1010edaSGreg Roach ]); 185aee13b6dSGreg Roach 1866ccdf4f0SGreg Roach return redirect($url); 187aee13b6dSGreg Roach } 188aee13b6dSGreg Roach 189aee13b6dSGreg Roach /** 1906ccdf4f0SGreg Roach * @param ServerRequestInterface $request 191aee13b6dSGreg Roach * 1926ccdf4f0SGreg Roach * @return ResponseInterface 193aee13b6dSGreg Roach */ 19457ab2231SGreg Roach public function postAdminMoveDownAction(ServerRequestInterface $request): ResponseInterface 195c1010edaSGreg Roach { 196eb235819SGreg Roach $block_id = (int) $request->getQueryParams()['block_id']; 197aee13b6dSGreg Roach 19877654037SGreg Roach $block_order = DB::table('block') 19977654037SGreg Roach ->where('block_id', '=', $block_id) 20077654037SGreg Roach ->value('block_order'); 201aee13b6dSGreg Roach 20277654037SGreg Roach $swap_block = DB::table('block') 20326684e68SGreg Roach ->where('module_name', '=', $this->name()) 20477654037SGreg Roach ->where('block_order', '>', $block_order) 205*1d1f373cSGreg Roach ->orderBy('block_order', 'asc') 20677654037SGreg Roach ->first(); 207aee13b6dSGreg Roach 208*1d1f373cSGreg Roach if ($block_order !== null && $swap_block !== null) { 20977654037SGreg Roach DB::table('block') 21077654037SGreg Roach ->where('block_id', '=', $block_id) 21177654037SGreg Roach ->update([ 212aee13b6dSGreg Roach 'block_order' => $swap_block->block_order, 213aee13b6dSGreg Roach ]); 21477654037SGreg Roach 21577654037SGreg Roach DB::table('block') 21677654037SGreg Roach ->where('block_id', '=', $swap_block->block_id) 21777654037SGreg Roach ->update([ 218aee13b6dSGreg Roach 'block_order' => $block_order, 219aee13b6dSGreg Roach ]); 220aee13b6dSGreg Roach } 221aee13b6dSGreg Roach 222*1d1f373cSGreg Roach return response(); 223aee13b6dSGreg Roach } 224aee13b6dSGreg Roach 225aee13b6dSGreg Roach /** 2266ccdf4f0SGreg Roach * @param ServerRequestInterface $request 227aee13b6dSGreg Roach * 2286ccdf4f0SGreg Roach * @return ResponseInterface 229aee13b6dSGreg Roach */ 23057ab2231SGreg Roach public function postAdminMoveUpAction(ServerRequestInterface $request): ResponseInterface 231c1010edaSGreg Roach { 232eb235819SGreg Roach $block_id = (int) $request->getQueryParams()['block_id']; 233aee13b6dSGreg Roach 23477654037SGreg Roach $block_order = DB::table('block') 23577654037SGreg Roach ->where('block_id', '=', $block_id) 23677654037SGreg Roach ->value('block_order'); 237aee13b6dSGreg Roach 23877654037SGreg Roach $swap_block = DB::table('block') 23926684e68SGreg Roach ->where('module_name', '=', $this->name()) 24077654037SGreg Roach ->where('block_order', '<', $block_order) 241*1d1f373cSGreg Roach ->orderBy('block_order', 'desc') 24277654037SGreg Roach ->first(); 243aee13b6dSGreg Roach 244*1d1f373cSGreg Roach if ($block_order !== null && $swap_block !== null) { 24577654037SGreg Roach DB::table('block') 24677654037SGreg Roach ->where('block_id', '=', $block_id) 24777654037SGreg Roach ->update([ 248aee13b6dSGreg Roach 'block_order' => $swap_block->block_order, 249aee13b6dSGreg Roach ]); 25077654037SGreg Roach 25177654037SGreg Roach DB::table('block') 25277654037SGreg Roach ->where('block_id', '=', $swap_block->block_id) 25377654037SGreg Roach ->update([ 254aee13b6dSGreg Roach 'block_order' => $block_order, 255aee13b6dSGreg Roach ]); 256aee13b6dSGreg Roach } 257aee13b6dSGreg Roach 258*1d1f373cSGreg Roach return response(); 259aee13b6dSGreg Roach } 260aee13b6dSGreg Roach 261aee13b6dSGreg Roach /** 2626ccdf4f0SGreg Roach * @param ServerRequestInterface $request 263aee13b6dSGreg Roach * 2646ccdf4f0SGreg Roach * @return ResponseInterface 265aee13b6dSGreg Roach */ 26657ab2231SGreg Roach public function getAdminEditAction(ServerRequestInterface $request): ResponseInterface 267c1010edaSGreg Roach { 268aee13b6dSGreg Roach $this->layout = 'layouts/administration'; 269aee13b6dSGreg Roach 27057ab2231SGreg Roach $tree = $request->getAttribute('tree'); 271eb235819SGreg Roach $block_id = (int) ($request->getQueryParams()['block_id'] ?? 0); 272aee13b6dSGreg Roach 273aee13b6dSGreg Roach if ($block_id === 0) { 274aee13b6dSGreg Roach // Creating a new faq 275aee13b6dSGreg Roach $header = ''; 276aee13b6dSGreg Roach $faqbody = ''; 27777654037SGreg Roach 27877654037SGreg Roach $block_order = 1 + (int) DB::table('block') 27926684e68SGreg Roach ->where('module_name', '=', $this->name()) 28077654037SGreg Roach ->max('block_order'); 28177654037SGreg Roach 282aee13b6dSGreg Roach $languages = []; 283aee13b6dSGreg Roach 284aee13b6dSGreg Roach $title = I18N::translate('Add an FAQ'); 285aee13b6dSGreg Roach } else { 286aee13b6dSGreg Roach // Editing an existing faq 287aee13b6dSGreg Roach $header = $this->getBlockSetting($block_id, 'header'); 288aee13b6dSGreg Roach $faqbody = $this->getBlockSetting($block_id, 'faqbody'); 28977654037SGreg Roach 29077654037SGreg Roach $block_order = DB::table('block') 29177654037SGreg Roach ->where('block_id', '=', $block_id) 29277654037SGreg Roach ->value('block_order'); 29377654037SGreg Roach 294aee13b6dSGreg Roach $languages = explode(',', $this->getBlockSetting($block_id, 'languages')); 295aee13b6dSGreg Roach 296aee13b6dSGreg Roach $title = I18N::translate('Edit the FAQ'); 297aee13b6dSGreg Roach } 298aee13b6dSGreg Roach 299b6c326d8SGreg Roach $tree_names = ['' => I18N::translate('All')] + Tree::getIdList(); 300b6c326d8SGreg Roach 301aee13b6dSGreg Roach return $this->viewResponse('modules/faq/edit', [ 302aee13b6dSGreg Roach 'block_id' => $block_id, 303aee13b6dSGreg Roach 'block_order' => $block_order, 304aee13b6dSGreg Roach 'header' => $header, 305aee13b6dSGreg Roach 'faqbody' => $faqbody, 306aee13b6dSGreg Roach 'languages' => $languages, 307aee13b6dSGreg Roach 'title' => $title, 308aee13b6dSGreg Roach 'tree' => $tree, 309b6c326d8SGreg Roach 'tree_names' => $tree_names, 310aee13b6dSGreg Roach ]); 311aee13b6dSGreg Roach } 312aee13b6dSGreg Roach 313aee13b6dSGreg Roach /** 3146ccdf4f0SGreg Roach * @param ServerRequestInterface $request 315aee13b6dSGreg Roach * 3166ccdf4f0SGreg Roach * @return ResponseInterface 317aee13b6dSGreg Roach */ 31857ab2231SGreg Roach public function postAdminEditAction(ServerRequestInterface $request): ResponseInterface 319c1010edaSGreg Roach { 32057ab2231SGreg Roach $tree = $request->getAttribute('tree'); 321eb235819SGreg Roach $block_id = (int) ($request->getQueryParams()['block_id'] ?? 0); 322eb235819SGreg Roach 323eb235819SGreg Roach $params = $request->getParsedBody(); 324eb235819SGreg Roach 325eb235819SGreg Roach $faqbody = $params['faqbody']; 326eb235819SGreg Roach $header = $params['header']; 327eb235819SGreg Roach $languages = $params['languages'] ?? []; 328eb235819SGreg Roach $gedcom_id = (int) $params['gedcom_id'] ?: null; 329eb235819SGreg Roach $block_order = (int) $params['block_order']; 330aee13b6dSGreg Roach 33150d6f48cSGreg Roach $faqbody = $this->html_service->sanitize($faqbody); 33250d6f48cSGreg Roach $header = $this->html_service->sanitize($header); 33350d6f48cSGreg Roach 334aee13b6dSGreg Roach if ($block_id !== 0) { 33577654037SGreg Roach DB::table('block') 33677654037SGreg Roach ->where('block_id', '=', $block_id) 33777654037SGreg Roach ->update([ 33877654037SGreg Roach 'gedcom_id' => $gedcom_id, 33977654037SGreg Roach 'block_order' => $block_order, 340aee13b6dSGreg Roach ]); 341aee13b6dSGreg Roach } else { 34277654037SGreg Roach DB::table('block')->insert([ 34377654037SGreg Roach 'gedcom_id' => $gedcom_id, 34426684e68SGreg Roach 'module_name' => $this->name(), 34577654037SGreg Roach 'block_order' => $block_order, 346aee13b6dSGreg Roach ]); 347aee13b6dSGreg Roach 34877654037SGreg Roach $block_id = (int) DB::connection()->getPdo()->lastInsertId(); 349aee13b6dSGreg Roach } 350aee13b6dSGreg Roach 351aee13b6dSGreg Roach $this->setBlockSetting($block_id, 'faqbody', $faqbody); 352aee13b6dSGreg Roach $this->setBlockSetting($block_id, 'header', $header); 353aee13b6dSGreg Roach $this->setBlockSetting($block_id, 'languages', implode(',', $languages)); 354aee13b6dSGreg Roach 355c1010edaSGreg Roach $url = route('module', [ 35626684e68SGreg Roach 'module' => $this->name(), 357c1010edaSGreg Roach 'action' => 'Admin', 3589022ab66SGreg Roach 'tree' => $tree->name(), 359c1010edaSGreg Roach ]); 360aee13b6dSGreg Roach 3616ccdf4f0SGreg Roach return redirect($url); 362aee13b6dSGreg Roach } 363aee13b6dSGreg Roach 364b998dbceSGreg Roach /** 36557ab2231SGreg Roach * @param ServerRequestInterface $request 366b998dbceSGreg Roach * 3676ccdf4f0SGreg Roach * @return ResponseInterface 368b998dbceSGreg Roach */ 36957ab2231SGreg Roach public function getShowAction(ServerRequestInterface $request): ResponseInterface 370c1010edaSGreg Roach { 37157ab2231SGreg Roach $tree = $request->getAttribute('tree'); 3725229eadeSGreg Roach assert($tree instanceof Tree, new InvalidArgumentException()); 37357ab2231SGreg Roach 3748de50a4eSGreg Roach // Filter foreign languages. 37577654037SGreg Roach $faqs = $this->faqsForTree($tree) 3760b5fd0a6SGreg Roach ->filter(static function (stdClass $faq): bool { 37722d65e5aSGreg Roach return $faq->languages === '' || in_array(WT_LOCALE, explode(',', $faq->languages), true); 3788de50a4eSGreg Roach }); 379aee13b6dSGreg Roach 380aee13b6dSGreg Roach return $this->viewResponse('modules/faq/show', [ 3818de50a4eSGreg Roach 'faqs' => $faqs, 382aee13b6dSGreg Roach 'title' => I18N::translate('Frequently asked questions'), 3838de50a4eSGreg Roach 'tree' => $tree, 384aee13b6dSGreg Roach ]); 385aee13b6dSGreg Roach } 38677654037SGreg Roach 38777654037SGreg Roach /** 38877654037SGreg Roach * @param Tree $tree 38977654037SGreg Roach * 39077654037SGreg Roach * @return Collection 39177654037SGreg Roach */ 39277654037SGreg Roach private function faqsForTree(Tree $tree): Collection 39377654037SGreg Roach { 39477654037SGreg Roach return DB::table('block') 39577654037SGreg Roach ->join('block_setting AS bs1', 'bs1.block_id', '=', 'block.block_id') 39677654037SGreg Roach ->join('block_setting AS bs2', 'bs2.block_id', '=', 'block.block_id') 39777654037SGreg Roach ->join('block_setting AS bs3', 'bs3.block_id', '=', 'block.block_id') 39826684e68SGreg Roach ->where('module_name', '=', $this->name()) 39977654037SGreg Roach ->where('bs1.setting_name', '=', 'header') 40077654037SGreg Roach ->where('bs2.setting_name', '=', 'faqbody') 40177654037SGreg Roach ->where('bs3.setting_name', '=', 'languages') 4020b5fd0a6SGreg Roach ->where(static function (Builder $query) use ($tree): void { 40377654037SGreg Roach $query 40477654037SGreg Roach ->whereNull('gedcom_id') 40577654037SGreg Roach ->orWhere('gedcom_id', '=', $tree->id()); 40677654037SGreg Roach }) 40777654037SGreg Roach ->orderBy('block_order') 40877654037SGreg Roach ->select(['block.block_id', 'block_order', 'gedcom_id', 'bs1.setting_value AS header', 'bs2.setting_value AS faqbody', 'bs3.setting_value AS languages']) 40977654037SGreg Roach ->get(); 41077654037SGreg Roach } 41177654037SGreg Roach 41277654037SGreg Roach /** 41377654037SGreg Roach * @param Tree $tree 41477654037SGreg Roach * @param string $language 41577654037SGreg Roach * 41677654037SGreg Roach * @return bool 41777654037SGreg Roach */ 41877654037SGreg Roach private function faqsExist(Tree $tree, string $language): bool 41977654037SGreg Roach { 42077654037SGreg Roach return DB::table('block') 42177654037SGreg Roach ->join('block_setting', 'block_setting.block_id', '=', 'block.block_id') 42226684e68SGreg Roach ->where('module_name', '=', $this->name()) 42377654037SGreg Roach ->where('setting_name', '=', 'languages') 4240b5fd0a6SGreg Roach ->where(static function (Builder $query) use ($tree): void { 42577654037SGreg Roach $query 42677654037SGreg Roach ->whereNull('gedcom_id') 42777654037SGreg Roach ->orWhere('gedcom_id', '=', $tree->id()); 42877654037SGreg Roach }) 42977654037SGreg Roach ->select(['setting_value AS languages']) 43077654037SGreg Roach ->get() 4310b5fd0a6SGreg Roach ->filter(static function (stdClass $faq) use ($language): bool { 4320b5fd0a6SGreg Roach return $faq->languages === '' || in_array($language, explode(',', $faq->languages), true); 43377654037SGreg Roach }) 43477654037SGreg Roach ->isNotEmpty(); 43577654037SGreg Roach } 4368c2e8227SGreg Roach} 437