xref: /webtrees/app/Services/HomePageService.php (revision 81b729d3a9a6e0a0e8b96285d1ad7955d2d0c659)
18e0e1b25SGreg Roach<?php
28e0e1b25SGreg Roach
38e0e1b25SGreg Roach/**
48e0e1b25SGreg Roach * webtrees: online genealogy
589f7189bSGreg Roach * Copyright (C) 2021 webtrees development team
68e0e1b25SGreg Roach * This program is free software: you can redistribute it and/or modify
78e0e1b25SGreg Roach * it under the terms of the GNU General Public License as published by
88e0e1b25SGreg Roach * the Free Software Foundation, either version 3 of the License, or
98e0e1b25SGreg Roach * (at your option) any later version.
108e0e1b25SGreg Roach * This program is distributed in the hope that it will be useful,
118e0e1b25SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
128e0e1b25SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
138e0e1b25SGreg Roach * GNU General Public License for more details.
148e0e1b25SGreg 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/>.
168e0e1b25SGreg Roach */
178e0e1b25SGreg Roach
188e0e1b25SGreg Roachdeclare(strict_types=1);
198e0e1b25SGreg Roach
208e0e1b25SGreg Roachnamespace Fisharebest\Webtrees\Services;
218e0e1b25SGreg Roach
228e0e1b25SGreg Roachuse Fisharebest\Webtrees\Auth;
238e0e1b25SGreg Roachuse Fisharebest\Webtrees\Contracts\UserInterface;
24*81b729d3SGreg Roachuse Fisharebest\Webtrees\Http\Exceptions\HttpNotFoundException;
258e0e1b25SGreg Roachuse Fisharebest\Webtrees\Module\ModuleBlockInterface;
268e0e1b25SGreg Roachuse Fisharebest\Webtrees\Module\ModuleInterface;
278e0e1b25SGreg Roachuse Fisharebest\Webtrees\Tree;
288e0e1b25SGreg Roachuse Illuminate\Database\Capsule\Manager as DB;
298e0e1b25SGreg Roachuse Illuminate\Support\Collection;
308e0e1b25SGreg Roachuse Psr\Http\Message\ServerRequestInterface;
318e0e1b25SGreg Roachuse stdClass;
328e0e1b25SGreg Roach
338e0e1b25SGreg Roachuse function assert;
348e0e1b25SGreg Roachuse function is_numeric;
358e0e1b25SGreg Roach
368e0e1b25SGreg Roach/**
378e0e1b25SGreg Roach * Logic and content for the home-page blocks.
388e0e1b25SGreg Roach */
398e0e1b25SGreg Roachclass HomePageService
408e0e1b25SGreg Roach{
41c4943cffSGreg Roach    private ModuleService $module_service;
428e0e1b25SGreg Roach
438e0e1b25SGreg Roach    /**
448e0e1b25SGreg Roach     * HomePageController constructor.
458e0e1b25SGreg Roach     *
468e0e1b25SGreg Roach     * @param ModuleService $module_service
478e0e1b25SGreg Roach     */
488e0e1b25SGreg Roach    public function __construct(ModuleService $module_service)
498e0e1b25SGreg Roach    {
508e0e1b25SGreg Roach        $this->module_service = $module_service;
518e0e1b25SGreg Roach    }
528e0e1b25SGreg Roach
538e0e1b25SGreg Roach    /**
5424c0163eSGreg Roach     * Load a tree block.
558e0e1b25SGreg Roach     *
568e0e1b25SGreg Roach     * @param ServerRequestInterface $request
578e0e1b25SGreg Roach     *
588e0e1b25SGreg Roach     * @return ModuleBlockInterface
598e0e1b25SGreg Roach     */
6024c0163eSGreg Roach    public function treeBlock(ServerRequestInterface $request): ModuleBlockInterface
618e0e1b25SGreg Roach    {
628e0e1b25SGreg Roach        $tree = $request->getAttribute('tree');
638e0e1b25SGreg Roach        assert($tree instanceof Tree);
648e0e1b25SGreg Roach
658e0e1b25SGreg Roach        $block_id = (int) $request->getQueryParams()['block_id'];
668e0e1b25SGreg Roach
678e0e1b25SGreg Roach        $block = DB::table('block')
688e0e1b25SGreg Roach            ->where('block_id', '=', $block_id)
698e0e1b25SGreg Roach            ->where('gedcom_id', '=', $tree->id())
708e0e1b25SGreg Roach            ->whereNull('user_id')
718e0e1b25SGreg Roach            ->first();
728e0e1b25SGreg Roach
7324c0163eSGreg Roach        if ($block instanceof stdClass) {
748e0e1b25SGreg Roach            $module = $this->module_service->findByName($block->module_name);
758e0e1b25SGreg Roach
7624c0163eSGreg Roach            if ($module instanceof ModuleBlockInterface) {
778e0e1b25SGreg Roach                return $module;
788e0e1b25SGreg Roach            }
7924c0163eSGreg Roach        }
8024c0163eSGreg Roach
8124c0163eSGreg Roach        throw new HttpNotFoundException();
8224c0163eSGreg Roach    }
838e0e1b25SGreg Roach
848e0e1b25SGreg Roach    /**
8524c0163eSGreg Roach     * Load a user block.
868e0e1b25SGreg Roach     *
878e0e1b25SGreg Roach     * @param ServerRequestInterface $request
888e0e1b25SGreg Roach     * @param UserInterface          $user
898e0e1b25SGreg Roach     *
908e0e1b25SGreg Roach     * @return ModuleBlockInterface
918e0e1b25SGreg Roach     */
928e0e1b25SGreg Roach    public function userBlock(ServerRequestInterface $request, UserInterface $user): ModuleBlockInterface
938e0e1b25SGreg Roach    {
948e0e1b25SGreg Roach        $block_id = (int) $request->getQueryParams()['block_id'];
958e0e1b25SGreg Roach
968e0e1b25SGreg Roach        $block = DB::table('block')
978e0e1b25SGreg Roach            ->where('block_id', '=', $block_id)
988e0e1b25SGreg Roach            ->where('user_id', '=', $user->id())
998e0e1b25SGreg Roach            ->whereNull('gedcom_id')
1008e0e1b25SGreg Roach            ->first();
1018e0e1b25SGreg Roach
10224c0163eSGreg Roach        if ($block instanceof stdClass) {
1038e0e1b25SGreg Roach            $module = $this->module_service->findByName($block->module_name);
1048e0e1b25SGreg Roach
10524c0163eSGreg Roach            if ($module instanceof ModuleBlockInterface) {
1068e0e1b25SGreg Roach                return $module;
1078e0e1b25SGreg Roach            }
10824c0163eSGreg Roach        }
10924c0163eSGreg Roach
11024c0163eSGreg Roach        throw new HttpNotFoundException();
11124c0163eSGreg Roach    }
1128e0e1b25SGreg Roach
1138e0e1b25SGreg Roach    /**
1148e0e1b25SGreg Roach     * Get a specific block.
1158e0e1b25SGreg Roach     *
1168e0e1b25SGreg Roach     * @param Tree $tree
1178e0e1b25SGreg Roach     * @param int  $block_id
1188e0e1b25SGreg Roach     *
1198e0e1b25SGreg Roach     * @return ModuleBlockInterface
1208e0e1b25SGreg Roach     */
1218e0e1b25SGreg Roach    public function getBlockModule(Tree $tree, int $block_id): ModuleBlockInterface
1228e0e1b25SGreg Roach    {
1238e0e1b25SGreg Roach        $active_blocks = $this->module_service->findByComponent(ModuleBlockInterface::class, $tree, Auth::user());
1248e0e1b25SGreg Roach
1258e0e1b25SGreg Roach        $module_name = DB::table('block')
1268e0e1b25SGreg Roach            ->where('block_id', '=', $block_id)
1278e0e1b25SGreg Roach            ->value('module_name');
1288e0e1b25SGreg Roach
1298e0e1b25SGreg Roach        $block = $active_blocks->first(static function (ModuleInterface $module) use ($module_name): bool {
1308e0e1b25SGreg Roach            return $module->name() === $module_name;
1318e0e1b25SGreg Roach        });
1328e0e1b25SGreg Roach
1338e0e1b25SGreg Roach        if ($block instanceof ModuleBlockInterface) {
1348e0e1b25SGreg Roach            return $block;
1358e0e1b25SGreg Roach        }
1368e0e1b25SGreg Roach
1378e0e1b25SGreg Roach        throw new HttpNotFoundException('Block not found');
1388e0e1b25SGreg Roach    }
1398e0e1b25SGreg Roach
1408e0e1b25SGreg Roach    /**
1418e0e1b25SGreg Roach     * Get all the available blocks for a tree page.
1428e0e1b25SGreg Roach     *
143f6924bc8SGreg Roach     * @param Tree          $tree
144f6924bc8SGreg Roach     * @param UserInterface $user
145f6924bc8SGreg Roach     *
1468e0e1b25SGreg Roach     * @return Collection<string,ModuleBlockInterface>
1478e0e1b25SGreg Roach     */
148f6924bc8SGreg Roach    public function availableTreeBlocks(Tree $tree, UserInterface $user): Collection
1498e0e1b25SGreg Roach    {
150f6924bc8SGreg Roach        return $this->module_service->findByComponent(ModuleBlockInterface::class, $tree, $user)
1518e0e1b25SGreg Roach            ->filter(static function (ModuleBlockInterface $block): bool {
1528e0e1b25SGreg Roach                return $block->isTreeBlock();
1538e0e1b25SGreg Roach            })
1548e0e1b25SGreg Roach            ->mapWithKeys(static function (ModuleBlockInterface $block): array {
1558e0e1b25SGreg Roach                return [$block->name() => $block];
1568e0e1b25SGreg Roach            });
1578e0e1b25SGreg Roach    }
1588e0e1b25SGreg Roach
1598e0e1b25SGreg Roach    /**
1608e0e1b25SGreg Roach     * Get all the available blocks for a user page.
1618e0e1b25SGreg Roach     *
162f6924bc8SGreg Roach     * @param Tree          $tree
163f6924bc8SGreg Roach     * @param UserInterface $user
164f6924bc8SGreg Roach     *
1658e0e1b25SGreg Roach     * @return Collection<string,ModuleBlockInterface>
1668e0e1b25SGreg Roach     */
167f6924bc8SGreg Roach    public function availableUserBlocks(Tree $tree, UserInterface $user): Collection
1688e0e1b25SGreg Roach    {
169f6924bc8SGreg Roach        return $this->module_service->findByComponent(ModuleBlockInterface::class, $tree, $user)
1708e0e1b25SGreg Roach            ->filter(static function (ModuleBlockInterface $block): bool {
1718e0e1b25SGreg Roach                return $block->isUserBlock();
1728e0e1b25SGreg Roach            })
1738e0e1b25SGreg Roach            ->mapWithKeys(static function (ModuleBlockInterface $block): array {
1748e0e1b25SGreg Roach                return [$block->name() => $block];
1758e0e1b25SGreg Roach            });
1768e0e1b25SGreg Roach    }
1778e0e1b25SGreg Roach
1788e0e1b25SGreg Roach    /**
1798e0e1b25SGreg Roach     * Get the blocks for a specified tree.
1808e0e1b25SGreg Roach     *
181f6924bc8SGreg Roach     * @param Tree          $tree
182f6924bc8SGreg Roach     * @param UserInterface $user
1838e0e1b25SGreg Roach     * @param string        $location "main" or "side"
1848e0e1b25SGreg Roach     *
1857c2c99faSGreg Roach     * @return Collection<int,ModuleBlockInterface>
1868e0e1b25SGreg Roach     */
187f6924bc8SGreg Roach    public function treeBlocks(Tree $tree, UserInterface $user, string $location): Collection
1888e0e1b25SGreg Roach    {
1898e0e1b25SGreg Roach        $rows = DB::table('block')
190f6924bc8SGreg Roach            ->where('gedcom_id', '=', $tree->id())
1918e0e1b25SGreg Roach            ->where('location', '=', $location)
1928e0e1b25SGreg Roach            ->orderBy('block_order')
1938e0e1b25SGreg Roach            ->pluck('module_name', 'block_id');
1948e0e1b25SGreg Roach
195f6924bc8SGreg Roach        return $this->filterActiveBlocks($rows, $this->availableTreeBlocks($tree, $user));
1968e0e1b25SGreg Roach    }
1978e0e1b25SGreg Roach
1988e0e1b25SGreg Roach    /**
1998e0e1b25SGreg Roach     * Make sure that default blocks exist for a tree.
2008e0e1b25SGreg Roach     *
2018e0e1b25SGreg Roach     * @return void
2028e0e1b25SGreg Roach     */
2038e0e1b25SGreg Roach    public function checkDefaultTreeBlocksExist(): void
2048e0e1b25SGreg Roach    {
2058e0e1b25SGreg Roach        $has_blocks = DB::table('block')
2068e0e1b25SGreg Roach            ->where('gedcom_id', '=', -1)
2078e0e1b25SGreg Roach            ->exists();
2088e0e1b25SGreg Roach
2098e0e1b25SGreg Roach        // No default settings?  Create them.
2108e0e1b25SGreg Roach        if (!$has_blocks) {
2118e0e1b25SGreg Roach            foreach ([ModuleBlockInterface::MAIN_BLOCKS, ModuleBlockInterface::SIDE_BLOCKS] as $location) {
2128e0e1b25SGreg Roach                foreach (ModuleBlockInterface::DEFAULT_TREE_PAGE_BLOCKS[$location] as $block_order => $class) {
2133cf189cfSGreg Roach                    $module = $this->module_service->findByInterface($class)->first();
2148e0e1b25SGreg Roach
2153cf189cfSGreg Roach                    if ($module instanceof ModuleInterface) {
2168e0e1b25SGreg Roach                        DB::table('block')->insert([
2178e0e1b25SGreg Roach                            'gedcom_id'   => -1,
2188e0e1b25SGreg Roach                            'location'    => $location,
2198e0e1b25SGreg Roach                            'block_order' => $block_order,
2203cf189cfSGreg Roach                            'module_name' => $module->name(),
2218e0e1b25SGreg Roach                        ]);
2228e0e1b25SGreg Roach                    }
2238e0e1b25SGreg Roach                }
2248e0e1b25SGreg Roach            }
2258e0e1b25SGreg Roach        }
2263cf189cfSGreg Roach    }
2278e0e1b25SGreg Roach
2288e0e1b25SGreg Roach    /**
2298e0e1b25SGreg Roach     * Get the blocks for a specified user.
2308e0e1b25SGreg Roach     *
231f6924bc8SGreg Roach     * @param Tree          $tree
232f6924bc8SGreg Roach     * @param UserInterface $user
2338e0e1b25SGreg Roach     * @param string        $location "main" or "side"
2348e0e1b25SGreg Roach     *
2357c2c99faSGreg Roach     * @return Collection<int,ModuleBlockInterface>
2368e0e1b25SGreg Roach     */
237f6924bc8SGreg Roach    public function userBlocks(Tree $tree, UserInterface $user, string $location): Collection
2388e0e1b25SGreg Roach    {
2398e0e1b25SGreg Roach        $rows = DB::table('block')
240f6924bc8SGreg Roach            ->where('user_id', '=', $user->id())
2418e0e1b25SGreg Roach            ->where('location', '=', $location)
2428e0e1b25SGreg Roach            ->orderBy('block_order')
2438e0e1b25SGreg Roach            ->pluck('module_name', 'block_id');
2448e0e1b25SGreg Roach
245f6924bc8SGreg Roach        return $this->filterActiveBlocks($rows, $this->availableUserBlocks($tree, $user));
2468e0e1b25SGreg Roach    }
2478e0e1b25SGreg Roach
2488e0e1b25SGreg Roach    /**
2498e0e1b25SGreg Roach     * Make sure that default blocks exist for a user.
2508e0e1b25SGreg Roach     *
2518e0e1b25SGreg Roach     * @return void
2528e0e1b25SGreg Roach     */
2538e0e1b25SGreg Roach    public function checkDefaultUserBlocksExist(): void
2548e0e1b25SGreg Roach    {
2558e0e1b25SGreg Roach        $has_blocks = DB::table('block')
2568e0e1b25SGreg Roach            ->where('user_id', '=', -1)
2578e0e1b25SGreg Roach            ->exists();
2588e0e1b25SGreg Roach
2598e0e1b25SGreg Roach        // No default settings?  Create them.
2608e0e1b25SGreg Roach        if (!$has_blocks) {
2618e0e1b25SGreg Roach            foreach ([ModuleBlockInterface::MAIN_BLOCKS, ModuleBlockInterface::SIDE_BLOCKS] as $location) {
2628e0e1b25SGreg Roach                foreach (ModuleBlockInterface::DEFAULT_USER_PAGE_BLOCKS[$location] as $block_order => $class) {
26323b84b22SGreg Roach                    $module = $this->module_service->findByInterface($class)->first();
2648e0e1b25SGreg Roach
26523b84b22SGreg Roach                    if ($module instanceof ModuleBlockInterface) {
2668e0e1b25SGreg Roach                        DB::table('block')->insert([
2678e0e1b25SGreg Roach                            'user_id'     => -1,
2688e0e1b25SGreg Roach                            'location'    => $location,
2698e0e1b25SGreg Roach                            'block_order' => $block_order,
27023b84b22SGreg Roach                            'module_name' => $module->name(),
2718e0e1b25SGreg Roach                        ]);
2728e0e1b25SGreg Roach                    }
2738e0e1b25SGreg Roach                }
2748e0e1b25SGreg Roach            }
2758e0e1b25SGreg Roach        }
27623b84b22SGreg Roach    }
2778e0e1b25SGreg Roach
2788e0e1b25SGreg Roach    /**
2798e0e1b25SGreg Roach     * Save the updated blocks for a user.
2808e0e1b25SGreg Roach     *
2818e0e1b25SGreg Roach     * @param int                $user_id
2828e0e1b25SGreg Roach     * @param Collection<string> $main_block_ids
2838e0e1b25SGreg Roach     * @param Collection<string> $side_block_ids
2848e0e1b25SGreg Roach     *
2858e0e1b25SGreg Roach     * @return void
2868e0e1b25SGreg Roach     */
2878e0e1b25SGreg Roach    public function updateUserBlocks(int $user_id, Collection $main_block_ids, Collection $side_block_ids): void
2888e0e1b25SGreg Roach    {
2898e0e1b25SGreg Roach        $existing_block_ids = DB::table('block')
2908e0e1b25SGreg Roach            ->where('user_id', '=', $user_id)
29178144954SGreg Roach            ->whereIn('location', [ModuleBlockInterface::MAIN_BLOCKS, ModuleBlockInterface::SIDE_BLOCKS])
2928e0e1b25SGreg Roach            ->pluck('block_id');
2938e0e1b25SGreg Roach
2948e0e1b25SGreg Roach        // Deleted blocks
2958e0e1b25SGreg Roach        foreach ($existing_block_ids as $existing_block_id) {
2968e0e1b25SGreg Roach            if (!$main_block_ids->contains($existing_block_id) && !$side_block_ids->contains($existing_block_id)) {
2978e0e1b25SGreg Roach                DB::table('block_setting')
2988e0e1b25SGreg Roach                    ->where('block_id', '=', $existing_block_id)
2998e0e1b25SGreg Roach                    ->delete();
3008e0e1b25SGreg Roach
3018e0e1b25SGreg Roach                DB::table('block')
3028e0e1b25SGreg Roach                    ->where('block_id', '=', $existing_block_id)
3038e0e1b25SGreg Roach                    ->delete();
3048e0e1b25SGreg Roach            }
3058e0e1b25SGreg Roach        }
3068e0e1b25SGreg Roach
3078e0e1b25SGreg Roach        $updates = [
3088e0e1b25SGreg Roach            ModuleBlockInterface::MAIN_BLOCKS => $main_block_ids,
3098e0e1b25SGreg Roach            ModuleBlockInterface::SIDE_BLOCKS => $side_block_ids,
3108e0e1b25SGreg Roach        ];
3118e0e1b25SGreg Roach
3128e0e1b25SGreg Roach        foreach ($updates as $location => $updated_blocks) {
3138e0e1b25SGreg Roach            foreach ($updated_blocks as $block_order => $block_id) {
3148e0e1b25SGreg Roach                if (is_numeric($block_id)) {
3158e0e1b25SGreg Roach                    // Updated block
3168e0e1b25SGreg Roach                    DB::table('block')
3178e0e1b25SGreg Roach                        ->where('block_id', '=', $block_id)
3188e0e1b25SGreg Roach                        ->update([
3198e0e1b25SGreg Roach                            'block_order' => $block_order,
3208e0e1b25SGreg Roach                            'location'    => $location,
3218e0e1b25SGreg Roach                        ]);
3228e0e1b25SGreg Roach                } else {
3238e0e1b25SGreg Roach                    // New block
3248e0e1b25SGreg Roach                    DB::table('block')->insert([
3258e0e1b25SGreg Roach                        'user_id'     => $user_id,
3268e0e1b25SGreg Roach                        'location'    => $location,
3278e0e1b25SGreg Roach                        'block_order' => $block_order,
3288e0e1b25SGreg Roach                        'module_name' => $block_id,
3298e0e1b25SGreg Roach                    ]);
3308e0e1b25SGreg Roach                }
3318e0e1b25SGreg Roach            }
3328e0e1b25SGreg Roach        }
3338e0e1b25SGreg Roach    }
3348e0e1b25SGreg Roach
3358e0e1b25SGreg Roach    /**
3368e0e1b25SGreg Roach     * Save the updated blocks for a tree.
3378e0e1b25SGreg Roach     *
3388e0e1b25SGreg Roach     * @param int                $tree_id
3398e0e1b25SGreg Roach     * @param Collection<string> $main_block_ids
3408e0e1b25SGreg Roach     * @param Collection<string> $side_block_ids
3418e0e1b25SGreg Roach     *
3428e0e1b25SGreg Roach     * @return void
3438e0e1b25SGreg Roach     */
3448e0e1b25SGreg Roach    public function updateTreeBlocks(int $tree_id, Collection $main_block_ids, Collection $side_block_ids): void
3458e0e1b25SGreg Roach    {
3468e0e1b25SGreg Roach        $existing_block_ids = DB::table('block')
3478e0e1b25SGreg Roach            ->where('gedcom_id', '=', $tree_id)
34878144954SGreg Roach            ->whereIn('location', [ModuleBlockInterface::MAIN_BLOCKS, ModuleBlockInterface::SIDE_BLOCKS])
3498e0e1b25SGreg Roach            ->pluck('block_id');
3508e0e1b25SGreg Roach
3518e0e1b25SGreg Roach        // Deleted blocks
3528e0e1b25SGreg Roach        foreach ($existing_block_ids as $existing_block_id) {
3538e0e1b25SGreg Roach            if (!$main_block_ids->contains($existing_block_id) && !$side_block_ids->contains($existing_block_id)) {
3548e0e1b25SGreg Roach                DB::table('block_setting')
3558e0e1b25SGreg Roach                    ->where('block_id', '=', $existing_block_id)
3568e0e1b25SGreg Roach                    ->delete();
3578e0e1b25SGreg Roach
3588e0e1b25SGreg Roach                DB::table('block')
3598e0e1b25SGreg Roach                    ->where('block_id', '=', $existing_block_id)
3608e0e1b25SGreg Roach                    ->delete();
3618e0e1b25SGreg Roach            }
3628e0e1b25SGreg Roach        }
3638e0e1b25SGreg Roach
3648e0e1b25SGreg Roach        $updates = [
3658e0e1b25SGreg Roach            ModuleBlockInterface::MAIN_BLOCKS => $main_block_ids,
3668e0e1b25SGreg Roach            ModuleBlockInterface::SIDE_BLOCKS => $side_block_ids,
3678e0e1b25SGreg Roach        ];
3688e0e1b25SGreg Roach
3698e0e1b25SGreg Roach        foreach ($updates as $location => $updated_blocks) {
3708e0e1b25SGreg Roach            foreach ($updated_blocks as $block_order => $block_id) {
3718e0e1b25SGreg Roach                if (is_numeric($block_id)) {
3728e0e1b25SGreg Roach                    // Updated block
3738e0e1b25SGreg Roach                    DB::table('block')
3748e0e1b25SGreg Roach                        ->where('block_id', '=', $block_id)
3758e0e1b25SGreg Roach                        ->update([
3768e0e1b25SGreg Roach                            'block_order' => $block_order,
3778e0e1b25SGreg Roach                            'location'    => $location,
3788e0e1b25SGreg Roach                        ]);
3798e0e1b25SGreg Roach                } else {
3808e0e1b25SGreg Roach                    // New block
3818e0e1b25SGreg Roach                    DB::table('block')->insert([
3828e0e1b25SGreg Roach                        'gedcom_id'   => $tree_id,
3838e0e1b25SGreg Roach                        'location'    => $location,
3848e0e1b25SGreg Roach                        'block_order' => $block_order,
3858e0e1b25SGreg Roach                        'module_name' => $block_id,
3868e0e1b25SGreg Roach                    ]);
3878e0e1b25SGreg Roach                }
3888e0e1b25SGreg Roach            }
3898e0e1b25SGreg Roach        }
3908e0e1b25SGreg Roach    }
3918e0e1b25SGreg Roach
3928e0e1b25SGreg Roach    /**
3938e0e1b25SGreg Roach     * Take a list of block names, and return block (module) objects.
3948e0e1b25SGreg Roach     *
3958e0e1b25SGreg Roach     * @param Collection<string>                   $blocks
3967c2c99faSGreg Roach     * @param Collection<int,ModuleBlockInterface> $active_blocks
3978e0e1b25SGreg Roach     *
3987c2c99faSGreg Roach     * @return Collection<int,ModuleBlockInterface>
3998e0e1b25SGreg Roach     */
4008e0e1b25SGreg Roach    private function filterActiveBlocks(Collection $blocks, Collection $active_blocks): Collection
4018e0e1b25SGreg Roach    {
4028e0e1b25SGreg Roach        return $blocks->map(static function (string $block_name) use ($active_blocks): ?ModuleBlockInterface {
4038e0e1b25SGreg Roach            return $active_blocks->filter(static function (ModuleInterface $block) use ($block_name): bool {
4048e0e1b25SGreg Roach                return $block->name() === $block_name;
4058e0e1b25SGreg Roach            })->first();
4068e0e1b25SGreg Roach        })->filter();
4078e0e1b25SGreg Roach    }
4088e0e1b25SGreg Roach}
409