18c2e8227SGreg Roach<?php 28c2e8227SGreg Roach/** 38c2e8227SGreg Roach * webtrees: online genealogy 41062a142SGreg Roach * Copyright (C) 2018 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\Database; 210e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N; 220e62c4b8SGreg Roachuse Fisharebest\Webtrees\Menu; 230e62c4b8SGreg Roachuse Fisharebest\Webtrees\Tree; 248de50a4eSGreg Roachuse stdClass; 25aee13b6dSGreg Roachuse Symfony\Component\HttpFoundation\RedirectResponse; 26aee13b6dSGreg Roachuse Symfony\Component\HttpFoundation\Request; 27aee13b6dSGreg Roachuse Symfony\Component\HttpFoundation\Response; 288c2e8227SGreg Roach 298c2e8227SGreg Roach/** 308c2e8227SGreg Roach * Class FrequentlyAskedQuestionsModule 318c2e8227SGreg Roach */ 32c1010edaSGreg Roachclass FrequentlyAskedQuestionsModule extends AbstractModule implements ModuleMenuInterface, ModuleConfigInterface 33c1010edaSGreg Roach{ 348c2e8227SGreg Roach /** {@inheritdoc} */ 358f53f488SRico Sonntag public function getTitle(): string 36c1010edaSGreg Roach { 37bbb76c12SGreg Roach /* I18N: Name of a module. Abbreviation for “Frequently Asked Questions” */ 38bbb76c12SGreg Roach return I18N::translate('FAQ'); 398c2e8227SGreg Roach } 408c2e8227SGreg Roach 418c2e8227SGreg Roach /** {@inheritdoc} */ 428f53f488SRico Sonntag public function getDescription(): string 43c1010edaSGreg Roach { 44bbb76c12SGreg Roach /* I18N: Description of the “FAQ” module */ 45bbb76c12SGreg Roach return I18N::translate('A list of frequently asked questions and answers.'); 468c2e8227SGreg Roach } 478c2e8227SGreg Roach 4876692c8bSGreg Roach /** 49aee13b6dSGreg Roach * The URL to a page where the user can modify the configuration of this module. 5076692c8bSGreg Roach * 51aee13b6dSGreg Roach * @return string 5276692c8bSGreg Roach */ 538f53f488SRico Sonntag public function getConfigLink(): string 54c1010edaSGreg Roach { 55c1010edaSGreg Roach return route('module', [ 56c1010edaSGreg Roach 'module' => $this->getName(), 57c1010edaSGreg Roach 'action' => 'Admin', 58c1010edaSGreg Roach ]); 598c2e8227SGreg Roach } 608c2e8227SGreg Roach 618c2e8227SGreg Roach /** 620ee13198SGreg Roach * The user can re-order menus. Until they do, they are shown in this order. 630ee13198SGreg Roach * 640ee13198SGreg Roach * @return int 650ee13198SGreg Roach */ 668f53f488SRico Sonntag public function defaultMenuOrder(): int 67c1010edaSGreg Roach { 688c2e8227SGreg Roach return 40; 698c2e8227SGreg Roach } 708c2e8227SGreg Roach 710ee13198SGreg Roach /** 720ee13198SGreg Roach * A menu, to be added to the main application menu. 730ee13198SGreg Roach * 74aee13b6dSGreg Roach * @param Tree $tree 75aee13b6dSGreg Roach * 760ee13198SGreg Roach * @return Menu|null 770ee13198SGreg Roach */ 78c1010edaSGreg Roach public function getMenu(Tree $tree) 79c1010edaSGreg Roach { 808c2e8227SGreg Roach $faqs = Database::prepare( 812b6675d7SGreg Roach "SELECT block_id FROM `##block`" . 822b6675d7SGreg Roach " JOIN `##block_setting` USING (block_id)" . 832b6675d7SGreg Roach " WHERE module_name = :module_name AND IFNULL(gedcom_id, :tree_id_1) = :tree_id_2" . 842b6675d7SGreg Roach " AND setting_name='languages' AND (setting_value LIKE CONCAT('%', :locale, '%') OR setting_value='')" 8513abd6f3SGreg Roach )->execute([ 868c2e8227SGreg Roach 'module_name' => $this->getName(), 8772cf66d4SGreg Roach 'tree_id_1' => $tree->id(), 8872cf66d4SGreg Roach 'tree_id_2' => $tree->id(), 892b6675d7SGreg Roach 'locale' => WT_LOCALE, 9013abd6f3SGreg Roach ])->fetchAll(); 918c2e8227SGreg Roach 9236e59714SGreg Roach if (!empty($faqs)) { 93c1010edaSGreg Roach return new Menu($this->getTitle(), route('module', [ 94c1010edaSGreg Roach 'module' => 'faq', 95c1010edaSGreg Roach 'action' => 'Show', 96*aa6f03bbSGreg Roach 'ged' => $tree->name(), 97c1010edaSGreg Roach ]), 'menu-help'); 988c2e8227SGreg Roach } 99b2ce94c6SRico Sonntag 100b2ce94c6SRico Sonntag return null; 1018c2e8227SGreg Roach } 102aee13b6dSGreg Roach 103aee13b6dSGreg Roach /** 104b6db7c1fSGreg Roach * @param Tree $tree 105aee13b6dSGreg Roach * 106aee13b6dSGreg Roach * @return Response 107aee13b6dSGreg Roach */ 108b6db7c1fSGreg Roach public function getAdminAction(Tree $tree): Response 109c1010edaSGreg Roach { 110aee13b6dSGreg Roach $this->layout = 'layouts/administration'; 111aee13b6dSGreg Roach 112aee13b6dSGreg Roach $faqs = Database::prepare( 113aee13b6dSGreg Roach "SELECT block_id, block_order, gedcom_id, bs1.setting_value AS header, bs2.setting_value AS faqbody" . 114aee13b6dSGreg Roach " FROM `##block` b" . 115aee13b6dSGreg Roach " JOIN `##block_setting` bs1 USING (block_id)" . 116aee13b6dSGreg Roach " JOIN `##block_setting` bs2 USING (block_id)" . 117aee13b6dSGreg Roach " WHERE module_name = :module_name" . 118aee13b6dSGreg Roach " AND bs1.setting_name = 'header'" . 119aee13b6dSGreg Roach " AND bs2.setting_name = 'faqbody'" . 120aee13b6dSGreg Roach " AND IFNULL(gedcom_id, :tree_id_1) = :tree_id_2" . 121aee13b6dSGreg Roach " ORDER BY block_order" 122aee13b6dSGreg Roach )->execute([ 123aee13b6dSGreg Roach 'module_name' => $this->getName(), 12472cf66d4SGreg Roach 'tree_id_1' => $tree->id(), 12572cf66d4SGreg Roach 'tree_id_2' => $tree->id(), 126aee13b6dSGreg Roach ])->fetchAll(); 127aee13b6dSGreg Roach 128aee13b6dSGreg Roach $min_block_order = Database::prepare( 129aee13b6dSGreg Roach "SELECT MIN(block_order) FROM `##block` WHERE module_name = 'faq' AND (gedcom_id = :tree_id OR gedcom_id IS NULL)" 130aee13b6dSGreg Roach )->execute([ 13172cf66d4SGreg Roach 'tree_id' => $tree->id(), 132aee13b6dSGreg Roach ])->fetchOne(); 133aee13b6dSGreg Roach 134aee13b6dSGreg Roach $max_block_order = Database::prepare( 135aee13b6dSGreg Roach "SELECT MAX(block_order) FROM `##block` WHERE module_name = 'faq' AND (gedcom_id = :tree_id OR gedcom_id IS NULL)" 136aee13b6dSGreg Roach )->execute([ 13772cf66d4SGreg Roach 'tree_id' => $tree->id(), 138aee13b6dSGreg Roach ])->fetchOne(); 139aee13b6dSGreg Roach 140aee13b6dSGreg Roach $title = I18N::translate('Frequently asked questions') . ' — ' . $tree->getTitle(); 141aee13b6dSGreg Roach 142aee13b6dSGreg Roach return $this->viewResponse('modules/faq/config', [ 143aee13b6dSGreg Roach 'faqs' => $faqs, 144aee13b6dSGreg Roach 'max_block_order' => $max_block_order, 145aee13b6dSGreg Roach 'min_block_order' => $min_block_order, 146aee13b6dSGreg Roach 'title' => $title, 147aee13b6dSGreg Roach 'tree' => $tree, 148aee13b6dSGreg Roach 'tree_names' => Tree::getNameList(), 149aee13b6dSGreg Roach ]); 150aee13b6dSGreg Roach } 151aee13b6dSGreg Roach 152aee13b6dSGreg Roach /** 153aee13b6dSGreg Roach * @param Request $request 154b6db7c1fSGreg Roach * @param Tree $tree 155aee13b6dSGreg Roach * 156aee13b6dSGreg Roach * @return RedirectResponse 157aee13b6dSGreg Roach */ 158b6db7c1fSGreg Roach public function postAdminDeleteAction(Request $request, Tree $tree): RedirectResponse 159c1010edaSGreg Roach { 160aee13b6dSGreg Roach $block_id = (int) $request->get('block_id'); 161aee13b6dSGreg Roach 162aee13b6dSGreg Roach Database::prepare( 163aee13b6dSGreg Roach "DELETE FROM `##block_setting` WHERE block_id = :block_id" 164aee13b6dSGreg Roach )->execute(['block_id' => $block_id]); 165aee13b6dSGreg Roach 166aee13b6dSGreg Roach Database::prepare( 167aee13b6dSGreg Roach "DELETE FROM `##block` WHERE block_id = :block_id" 168aee13b6dSGreg Roach )->execute(['block_id' => $block_id]); 169aee13b6dSGreg Roach 170aee13b6dSGreg Roach 171c1010edaSGreg Roach $url = route('module', [ 172c1010edaSGreg Roach 'module' => 'faq', 173c1010edaSGreg Roach 'action' => 'Admin', 174*aa6f03bbSGreg Roach 'ged' => $tree->name(), 175c1010edaSGreg Roach ]); 176aee13b6dSGreg Roach 177aee13b6dSGreg Roach return new RedirectResponse($url); 178aee13b6dSGreg Roach } 179aee13b6dSGreg Roach 180aee13b6dSGreg Roach /** 181aee13b6dSGreg Roach * @param Request $request 182b6db7c1fSGreg Roach * @param Tree $tree 183aee13b6dSGreg Roach * 184aee13b6dSGreg Roach * @return RedirectResponse 185aee13b6dSGreg Roach */ 186b6db7c1fSGreg Roach public function postAdminMoveDownAction(Request $request, Tree $tree): RedirectResponse 187c1010edaSGreg Roach { 188aee13b6dSGreg Roach $block_id = (int) $request->get('block_id'); 189aee13b6dSGreg Roach 190aee13b6dSGreg Roach $block_order = Database::prepare( 191aee13b6dSGreg Roach "SELECT block_order FROM `##block` WHERE block_id = :block_id" 192aee13b6dSGreg Roach )->execute([ 193aee13b6dSGreg Roach 'block_id' => $block_id, 194aee13b6dSGreg Roach ])->fetchOne(); 195aee13b6dSGreg Roach 196aee13b6dSGreg Roach $swap_block = Database::prepare( 197aee13b6dSGreg Roach "SELECT block_order, block_id" . 198aee13b6dSGreg Roach " FROM `##block`" . 199aee13b6dSGreg Roach " WHERE block_order=(" . 200aee13b6dSGreg Roach " SELECT MIN(block_order) FROM `##block` WHERE block_order > :block_order AND module_name = :module_name_1" . 201aee13b6dSGreg Roach " ) AND module_name = :module_name_2" . 202aee13b6dSGreg Roach " LIMIT 1" 203aee13b6dSGreg Roach )->execute([ 204aee13b6dSGreg Roach 'block_order' => $block_order, 205aee13b6dSGreg Roach 'module_name_1' => $this->getName(), 206aee13b6dSGreg Roach 'module_name_2' => $this->getName(), 207aee13b6dSGreg Roach ])->fetchOneRow(); 208aee13b6dSGreg Roach 209aee13b6dSGreg Roach if ($swap_block !== null) { 210aee13b6dSGreg Roach Database::prepare( 211aee13b6dSGreg Roach "UPDATE `##block` SET block_order = :block_order WHERE block_id = :block_id" 212aee13b6dSGreg Roach )->execute([ 213aee13b6dSGreg Roach 'block_order' => $swap_block->block_order, 214aee13b6dSGreg Roach 'block_id' => $block_id, 215aee13b6dSGreg Roach ]); 216aee13b6dSGreg Roach Database::prepare( 217aee13b6dSGreg Roach "UPDATE `##block` SET block_order = :block_order WHERE block_id = :block_id" 218aee13b6dSGreg Roach )->execute([ 219aee13b6dSGreg Roach 'block_order' => $block_order, 220aee13b6dSGreg Roach 'block_id' => $swap_block->block_id, 221aee13b6dSGreg Roach ]); 222aee13b6dSGreg Roach } 223aee13b6dSGreg Roach 224c1010edaSGreg Roach $url = route('module', [ 225c1010edaSGreg Roach 'module' => 'faq', 226c1010edaSGreg Roach 'action' => 'Admin', 227*aa6f03bbSGreg Roach 'ged' => $tree->name(), 228c1010edaSGreg Roach ]); 229aee13b6dSGreg Roach 230aee13b6dSGreg Roach return new RedirectResponse($url); 231aee13b6dSGreg Roach } 232aee13b6dSGreg Roach 233aee13b6dSGreg Roach /** 234aee13b6dSGreg Roach * @param Request $request 235b6db7c1fSGreg Roach * @param Tree $tree 236aee13b6dSGreg Roach * 237aee13b6dSGreg Roach * @return RedirectResponse 238aee13b6dSGreg Roach */ 239b6db7c1fSGreg Roach public function postAdminMoveUpAction(Request $request, Tree $tree): RedirectResponse 240c1010edaSGreg Roach { 241aee13b6dSGreg Roach $block_id = (int) $request->get('block_id'); 242aee13b6dSGreg Roach 243aee13b6dSGreg Roach $block_order = Database::prepare( 244aee13b6dSGreg Roach "SELECT block_order FROM `##block` WHERE block_id = :block_id" 245aee13b6dSGreg Roach )->execute([ 246aee13b6dSGreg Roach 'block_id' => $block_id, 247aee13b6dSGreg Roach ])->fetchOne(); 248aee13b6dSGreg Roach 249aee13b6dSGreg Roach $swap_block = Database::prepare( 250aee13b6dSGreg Roach "SELECT block_order, block_id" . 251aee13b6dSGreg Roach " FROM `##block`" . 252aee13b6dSGreg Roach " WHERE block_order = (" . 253aee13b6dSGreg Roach " SELECT MAX(block_order) FROM `##block` WHERE block_order < :block_order AND module_name = :module_name_1" . 254aee13b6dSGreg Roach " ) AND module_name = :module_name_2" . 255aee13b6dSGreg Roach " LIMIT 1" 256aee13b6dSGreg Roach )->execute([ 257aee13b6dSGreg Roach 'block_order' => $block_order, 258aee13b6dSGreg Roach 'module_name_1' => $this->getName(), 259aee13b6dSGreg Roach 'module_name_2' => $this->getName(), 260aee13b6dSGreg Roach ])->fetchOneRow(); 261aee13b6dSGreg Roach 262aee13b6dSGreg Roach if ($swap_block !== null) { 263aee13b6dSGreg Roach Database::prepare( 264aee13b6dSGreg Roach "UPDATE `##block` SET block_order = :block_order WHERE block_id = :block_id" 265aee13b6dSGreg Roach )->execute([ 266aee13b6dSGreg Roach 'block_order' => $swap_block->block_order, 267aee13b6dSGreg Roach 'block_id' => $block_id, 268aee13b6dSGreg Roach ]); 269aee13b6dSGreg Roach Database::prepare( 270aee13b6dSGreg Roach "UPDATE `##block` SET block_order = :block_order WHERE block_id = :block_id" 271aee13b6dSGreg Roach )->execute([ 272aee13b6dSGreg Roach 'block_order' => $block_order, 273aee13b6dSGreg Roach 'block_id' => $swap_block->block_id, 274aee13b6dSGreg Roach ]); 275aee13b6dSGreg Roach } 276aee13b6dSGreg Roach 277c1010edaSGreg Roach $url = route('module', [ 278c1010edaSGreg Roach 'module' => 'faq', 279c1010edaSGreg Roach 'action' => 'Admin', 280*aa6f03bbSGreg Roach 'ged' => $tree->name(), 281c1010edaSGreg Roach ]); 282aee13b6dSGreg Roach 283aee13b6dSGreg Roach return new RedirectResponse($url); 284aee13b6dSGreg Roach } 285aee13b6dSGreg Roach 286aee13b6dSGreg Roach /** 287aee13b6dSGreg Roach * @param Request $request 288b6db7c1fSGreg Roach * @param Tree $tree 289aee13b6dSGreg Roach * 290aee13b6dSGreg Roach * @return Response 291aee13b6dSGreg Roach */ 292b6db7c1fSGreg Roach public function getAdminEditAction(Request $request, Tree $tree): Response 293c1010edaSGreg Roach { 294aee13b6dSGreg Roach $this->layout = 'layouts/administration'; 295aee13b6dSGreg Roach 296aee13b6dSGreg Roach $block_id = (int) $request->get('block_id'); 297aee13b6dSGreg Roach 298aee13b6dSGreg Roach if ($block_id === 0) { 299aee13b6dSGreg Roach // Creating a new faq 300aee13b6dSGreg Roach $header = ''; 301aee13b6dSGreg Roach $faqbody = ''; 302aee13b6dSGreg Roach $block_order = Database::prepare( 303aee13b6dSGreg Roach "SELECT IFNULL(MAX(block_order)+1, 0) FROM `##block` WHERE module_name = :module_name" 304aee13b6dSGreg Roach )->execute([ 305aee13b6dSGreg Roach 'module_name' => $this->getName(), 306aee13b6dSGreg Roach ])->fetchOne(); 307aee13b6dSGreg Roach $languages = []; 308aee13b6dSGreg Roach 309aee13b6dSGreg Roach $title = I18N::translate('Add an FAQ'); 310aee13b6dSGreg Roach } else { 311aee13b6dSGreg Roach // Editing an existing faq 312aee13b6dSGreg Roach $header = $this->getBlockSetting($block_id, 'header'); 313aee13b6dSGreg Roach $faqbody = $this->getBlockSetting($block_id, 'faqbody'); 314aee13b6dSGreg Roach $block_order = Database::prepare( 315aee13b6dSGreg Roach "SELECT block_order FROM `##block` WHERE block_id = :block_id" 316aee13b6dSGreg Roach )->execute(['block_id' => $block_id])->fetchOne(); 317aee13b6dSGreg Roach $languages = explode(',', $this->getBlockSetting($block_id, 'languages')); 318aee13b6dSGreg Roach 319aee13b6dSGreg Roach $title = I18N::translate('Edit the FAQ'); 320aee13b6dSGreg Roach } 321aee13b6dSGreg Roach 322aee13b6dSGreg Roach // @TODO enable CKEDITOR 323aee13b6dSGreg Roach 324aee13b6dSGreg Roach return $this->viewResponse('modules/faq/edit', [ 325aee13b6dSGreg Roach 'block_id' => $block_id, 326aee13b6dSGreg Roach 'block_order' => $block_order, 327aee13b6dSGreg Roach 'header' => $header, 328aee13b6dSGreg Roach 'faqbody' => $faqbody, 329aee13b6dSGreg Roach 'languages' => $languages, 330aee13b6dSGreg Roach 'title' => $title, 331aee13b6dSGreg Roach 'tree' => $tree, 332aee13b6dSGreg Roach 'tree_names' => Tree::getNameList(), 333aee13b6dSGreg Roach ]); 334aee13b6dSGreg Roach } 335aee13b6dSGreg Roach 336aee13b6dSGreg Roach /** 337aee13b6dSGreg Roach * @param Request $request 338b6db7c1fSGreg Roach * @param Tree $tree 339aee13b6dSGreg Roach * 340aee13b6dSGreg Roach * @return RedirectResponse 341aee13b6dSGreg Roach */ 342b6db7c1fSGreg Roach public function postAdminEditAction(Request $request, Tree $tree): RedirectResponse 343c1010edaSGreg Roach { 344aee13b6dSGreg Roach $block_id = (int) $request->get('block_id'); 345aee13b6dSGreg Roach $faqbody = $request->get('faqbody', ''); 346aee13b6dSGreg Roach $header = $request->get('header', ''); 347aee13b6dSGreg Roach $languages = $request->get('languages', []); 348aee13b6dSGreg Roach 349aee13b6dSGreg Roach if ($block_id !== 0) { 350aee13b6dSGreg Roach Database::prepare( 351aee13b6dSGreg Roach "UPDATE `##block` SET gedcom_id = NULLIF(:tree_id, '0'), block_order = :block_order WHERE block_id = :block_id" 352aee13b6dSGreg Roach )->execute([ 353a45f9889SGreg Roach 'tree_id' => (int) $request->get('gedcom_id'), 354a45f9889SGreg Roach 'block_order' => (int) $request->get('block_order'), 355aee13b6dSGreg Roach 'block_id' => $block_id, 356aee13b6dSGreg Roach ]); 357aee13b6dSGreg Roach } else { 358aee13b6dSGreg Roach Database::prepare( 359aee13b6dSGreg Roach "INSERT INTO `##block` (gedcom_id, module_name, block_order) VALUES (NULLIF(:tree_id, '0'), :module_name, :block_order)" 360aee13b6dSGreg Roach )->execute([ 361a45f9889SGreg Roach 'tree_id' => (int) $request->get('gedcom_id'), 362aee13b6dSGreg Roach 'module_name' => $this->getName(), 363a45f9889SGreg Roach 'block_order' => (int) $request->get('block_order'), 364aee13b6dSGreg Roach ]); 365aee13b6dSGreg Roach 36636e59714SGreg Roach $block_id = Database::lastInsertId(); 367aee13b6dSGreg Roach } 368aee13b6dSGreg Roach 369aee13b6dSGreg Roach $this->setBlockSetting($block_id, 'faqbody', $faqbody); 370aee13b6dSGreg Roach $this->setBlockSetting($block_id, 'header', $header); 371aee13b6dSGreg Roach $this->setBlockSetting($block_id, 'languages', implode(',', $languages)); 372aee13b6dSGreg Roach 373c1010edaSGreg Roach $url = route('module', [ 374c1010edaSGreg Roach 'module' => 'faq', 375c1010edaSGreg Roach 'action' => 'Admin', 376*aa6f03bbSGreg Roach 'ged' => $tree->name(), 377c1010edaSGreg Roach ]); 378aee13b6dSGreg Roach 379aee13b6dSGreg Roach return new RedirectResponse($url); 380aee13b6dSGreg Roach } 381aee13b6dSGreg Roach 382b998dbceSGreg Roach /** 383b6db7c1fSGreg Roach * @param Tree $tree 384b998dbceSGreg Roach * 385b998dbceSGreg Roach * @return Response 386b998dbceSGreg Roach */ 38738f9e88cSGreg Roach public function getShowAction(Tree $tree): Response 388c1010edaSGreg Roach { 389aee13b6dSGreg Roach $faqs = Database::prepare( 390aee13b6dSGreg Roach "SELECT block_id, bs1.setting_value AS header, bs2.setting_value AS body, bs3.setting_value AS languages" . 391aee13b6dSGreg Roach " FROM `##block` b" . 392aee13b6dSGreg Roach " JOIN `##block_setting` bs1 USING (block_id)" . 393aee13b6dSGreg Roach " JOIN `##block_setting` bs2 USING (block_id)" . 394aee13b6dSGreg Roach " JOIN `##block_setting` bs3 USING (block_id)" . 395aee13b6dSGreg Roach " WHERE module_name = :module_name" . 396aee13b6dSGreg Roach " AND bs1.setting_name = 'header'" . 397aee13b6dSGreg Roach " AND bs2.setting_name = 'faqbody'" . 398aee13b6dSGreg Roach " AND bs3.setting_name = 'languages'" . 399aee13b6dSGreg Roach " AND IFNULL(gedcom_id, :tree_id_1) = :tree_id_2" . 400aee13b6dSGreg Roach " ORDER BY block_order" 401aee13b6dSGreg Roach )->execute([ 402aee13b6dSGreg Roach 'module_name' => $this->getName(), 40372cf66d4SGreg Roach 'tree_id_1' => $tree->id(), 40472cf66d4SGreg Roach 'tree_id_2' => $tree->id(), 405aee13b6dSGreg Roach ])->fetchAll(); 406aee13b6dSGreg Roach 4078de50a4eSGreg Roach // Filter foreign languages. 408492c7072SGreg Roach $faqs = array_filter($faqs, function (stdClass $faq): bool { 4098de50a4eSGreg Roach return $faq->languages === '' || in_array(WT_LOCALE, explode(',', $faq->languages)); 4108de50a4eSGreg Roach }); 411aee13b6dSGreg Roach 412aee13b6dSGreg Roach return $this->viewResponse('modules/faq/show', [ 4138de50a4eSGreg Roach 'faqs' => $faqs, 414aee13b6dSGreg Roach 'title' => I18N::translate('Frequently asked questions'), 4158de50a4eSGreg Roach 'tree' => $tree, 416aee13b6dSGreg Roach ]); 417aee13b6dSGreg Roach } 4188c2e8227SGreg Roach} 419