xref: /webtrees/app/Module/FrequentlyAskedQuestionsModule.php (revision 7413816e6dd2d50e569034fb804f3dce7471bb94)
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