xref: /webtrees/app/Http/RequestHandlers/MapDataList.php (revision ed612bd3141b9cb4c1ed840b5f6b8d8f62a64d0f)
194e35917SGreg Roach<?php
294e35917SGreg Roach
394e35917SGreg Roach/**
494e35917SGreg Roach * webtrees: online genealogy
594e35917SGreg Roach * Copyright (C) 2020 webtrees development team
694e35917SGreg Roach * This program is free software: you can redistribute it and/or modify
794e35917SGreg Roach * it under the terms of the GNU General Public License as published by
894e35917SGreg Roach * the Free Software Foundation, either version 3 of the License, or
994e35917SGreg Roach * (at your option) any later version.
1094e35917SGreg Roach * This program is distributed in the hope that it will be useful,
1194e35917SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
1294e35917SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1394e35917SGreg Roach * GNU General Public License for more details.
1494e35917SGreg Roach * You should have received a copy of the GNU General Public License
1594e35917SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
1694e35917SGreg Roach */
1794e35917SGreg Roach
1894e35917SGreg Roachdeclare(strict_types=1);
1994e35917SGreg Roach
2094e35917SGreg Roachnamespace Fisharebest\Webtrees\Http\RequestHandlers;
2194e35917SGreg Roach
2294e35917SGreg Roachuse Fisharebest\Webtrees\Http\ViewResponseTrait;
2394e35917SGreg Roachuse Fisharebest\Webtrees\I18N;
248504fb2dSGreg Roachuse Fisharebest\Webtrees\Module\PlaceHierarchyListModule;
2594e35917SGreg Roachuse Fisharebest\Webtrees\Services\MapDataService;
268504fb2dSGreg Roachuse Fisharebest\Webtrees\Services\ModuleService;
27ac34be60SRichard Cisséeuse Fisharebest\Webtrees\Services\TreeService;
2811464183SGreg Roachuse Illuminate\Database\Capsule\Manager as DB;
2911464183SGreg Roachuse Illuminate\Database\Query\Expression;
3094e35917SGreg Roachuse Psr\Http\Message\ResponseInterface;
3194e35917SGreg Roachuse Psr\Http\Message\ServerRequestInterface;
3294e35917SGreg Roachuse Psr\Http\Server\RequestHandlerInterface;
3311464183SGreg Roachuse stdClass;
34*ed612bd3SGreg Roach
3594e35917SGreg Roachuse function array_reverse;
3694e35917SGreg Roachuse function redirect;
3794e35917SGreg Roachuse function route;
3894e35917SGreg Roach
3994e35917SGreg Roach/**
4094e35917SGreg Roach * Show a list of map data.
4194e35917SGreg Roach */
4294e35917SGreg Roachclass MapDataList implements RequestHandlerInterface
4394e35917SGreg Roach{
4494e35917SGreg Roach    use ViewResponseTrait;
4594e35917SGreg Roach
4694e35917SGreg Roach    /** @var MapDataService */
4794e35917SGreg Roach    private $map_data_service;
4894e35917SGreg Roach
498504fb2dSGreg Roach    /** @var ModuleService */
508504fb2dSGreg Roach    private $module_service;
518504fb2dSGreg Roach
52ac34be60SRichard Cissée    /** @var TreeService */
53ac34be60SRichard Cissée    private $tree_service;
54ac34be60SRichard Cissée
5594e35917SGreg Roach    /**
5694e35917SGreg Roach     * Dependency injection.
5794e35917SGreg Roach     *
5894e35917SGreg Roach     * @param MapDataService $map_data_service
598504fb2dSGreg Roach     * @param ModuleService  $module_service
60*ed612bd3SGreg Roach     * @param TreeService    $tree_service
6194e35917SGreg Roach     */
62*ed612bd3SGreg Roach    public function __construct(
63*ed612bd3SGreg Roach        MapDataService $map_data_service,
64*ed612bd3SGreg Roach        ModuleService $module_service,
65*ed612bd3SGreg Roach        TreeService $tree_service
66*ed612bd3SGreg Roach    ) {
6794e35917SGreg Roach        $this->map_data_service = $map_data_service;
688504fb2dSGreg Roach        $this->module_service   = $module_service;
69ac34be60SRichard Cissée        $this->tree_service   = $tree_service;
7094e35917SGreg Roach    }
7194e35917SGreg Roach
7294e35917SGreg Roach    /**
7394e35917SGreg Roach     * @param ServerRequestInterface $request
7494e35917SGreg Roach     *
7594e35917SGreg Roach     * @return ResponseInterface
7694e35917SGreg Roach     */
7794e35917SGreg Roach    public function handle(ServerRequestInterface $request): ResponseInterface
7894e35917SGreg Roach    {
7994e35917SGreg Roach        $parent_id   = (int) ($request->getQueryParams()['parent_id'] ?? 0);
8094e35917SGreg Roach        $title       = I18N::translate('Geographic data');
8194e35917SGreg Roach        $parent      = $this->map_data_service->findById($parent_id);
8294e35917SGreg Roach
8394e35917SGreg Roach        // Request for a non-existent location?
8494e35917SGreg Roach        if ($parent_id !== $parent->id()) {
8594e35917SGreg Roach            return redirect(route(__CLASS__));
8694e35917SGreg Roach        }
8794e35917SGreg Roach
8894e35917SGreg Roach        // Automatically import any new/missing places.
890e50635cSGreg Roach        $this->map_data_service->importMissingLocations();
9094e35917SGreg Roach
919ee82875SGreg Roach        $breadcrumbs = [$parent->locationName()];
929ee82875SGreg Roach
939ee82875SGreg Roach        $tmp = $parent->parent();
9494e35917SGreg Roach
9594e35917SGreg Roach        while ($tmp->id() !== 0) {
9694e35917SGreg Roach            $breadcrumbs[route(__CLASS__, ['parent_id' => $tmp->id()])] = $tmp->locationName();
9794e35917SGreg Roach
9894e35917SGreg Roach            $tmp = $tmp->parent();
9994e35917SGreg Roach        }
10094e35917SGreg Roach
10194e35917SGreg Roach        $breadcrumbs[route(__CLASS__)]           = $title;
10294e35917SGreg Roach        $breadcrumbs[route(ControlPanel::class)] = I18N::translate('Control panel');
10394e35917SGreg Roach
104*ed612bd3SGreg Roach        $list_module = $this->module_service
105*ed612bd3SGreg Roach            ->findByInterface(PlaceHierarchyListModule::class)
106*ed612bd3SGreg Roach            ->first();
1078504fb2dSGreg Roach
10894e35917SGreg Roach        $this->layout = 'layouts/administration';
10994e35917SGreg Roach
11094e35917SGreg Roach        return $this->viewResponse('admin/locations', [
11194e35917SGreg Roach            'active'       => $this->map_data_service->activePlaces($parent),
112*ed612bd3SGreg Roach            'all_trees'    => $this->tree_service->all(),
11394e35917SGreg Roach            'breadcrumbs'  => array_reverse($breadcrumbs),
11494e35917SGreg Roach            'parent_id'    => $parent_id,
1150e50635cSGreg Roach            'placelist'    => $this->map_data_service->getPlaceListLocation($parent_id),
116*ed612bd3SGreg Roach            'list_module'  => $list_module,
1178504fb2dSGreg Roach            'title'        => $title,
11894e35917SGreg Roach        ]);
11994e35917SGreg Roach    }
12011464183SGreg Roach
12111464183SGreg Roach
12211464183SGreg Roach    /**
12311464183SGreg Roach     * Find all of the places in the hierarchy
12411464183SGreg Roach     *
12511464183SGreg Roach     * @param int $id
12611464183SGreg Roach     *
12711464183SGreg Roach     * @return stdClass[]
12811464183SGreg Roach     */
12911464183SGreg Roach    private function getPlaceListLocation(int $id): array
13011464183SGreg Roach    {
13111464183SGreg Roach        return DB::table('placelocation')
13211464183SGreg Roach            ->where('pl_parent_id', '=', $id)
13311464183SGreg Roach            ->orderBy(new Expression('pl_place /*! COLLATE ' . I18N::collation() . ' */'))
13411464183SGreg Roach            ->get()
13511464183SGreg Roach            ->map(function (stdClass $row): stdClass {
13611464183SGreg Roach                // Find/count places without co-ordinates
13711464183SGreg Roach                $children = $this->childLocationStatus((int) $row->pl_id);
13811464183SGreg Roach
13911464183SGreg Roach                $row->child_count = (int) $children->child_count;
14011464183SGreg Roach                $row->no_coord    = (int) $children->no_coord;
14111464183SGreg Roach
14211464183SGreg Roach                return $row;
14311464183SGreg Roach            })
14411464183SGreg Roach            ->all();
14511464183SGreg Roach    }
14611464183SGreg Roach
14711464183SGreg Roach    /**
14811464183SGreg Roach     * How many children does place have?  How many have co-ordinates?
14911464183SGreg Roach     *
15011464183SGreg Roach     * @param int $parent_id
15111464183SGreg Roach     *
15211464183SGreg Roach     * @return stdClass
15311464183SGreg Roach     */
15411464183SGreg Roach    private function childLocationStatus(int $parent_id): stdClass
15511464183SGreg Roach    {
15611464183SGreg Roach        $prefix = DB::connection()->getTablePrefix();
15711464183SGreg Roach
15811464183SGreg Roach        $expression =
15911464183SGreg Roach            $prefix . 'p0.pl_place IS NOT NULL AND COALESCE(' . $prefix . "p0.pl_lati, '') = '' OR " .
16011464183SGreg Roach            $prefix . 'p1.pl_place IS NOT NULL AND COALESCE(' . $prefix . "p1.pl_lati, '') = '' OR " .
16111464183SGreg Roach            $prefix . 'p2.pl_place IS NOT NULL AND COALESCE(' . $prefix . "p2.pl_lati, '') = '' OR " .
16211464183SGreg Roach            $prefix . 'p3.pl_place IS NOT NULL AND COALESCE(' . $prefix . "p3.pl_lati, '') = '' OR " .
16311464183SGreg Roach            $prefix . 'p4.pl_place IS NOT NULL AND COALESCE(' . $prefix . "p4.pl_lati, '') = '' OR " .
16411464183SGreg Roach            $prefix . 'p5.pl_place IS NOT NULL AND COALESCE(' . $prefix . "p5.pl_lati, '') = '' OR " .
16511464183SGreg Roach            $prefix . 'p6.pl_place IS NOT NULL AND COALESCE(' . $prefix . "p6.pl_lati, '') = '' OR " .
16611464183SGreg Roach            $prefix . 'p7.pl_place IS NOT NULL AND COALESCE(' . $prefix . "p7.pl_lati, '') = '' OR " .
16711464183SGreg Roach            $prefix . 'p8.pl_place IS NOT NULL AND COALESCE(' . $prefix . "p8.pl_lati, '') = '' OR " .
16811464183SGreg Roach            $prefix . 'p9.pl_place IS NOT NULL AND COALESCE(' . $prefix . "p9.pl_lati, '') = ''";
16911464183SGreg Roach
17011464183SGreg Roach        return DB::table('placelocation AS p0')
17111464183SGreg Roach            ->leftJoin('placelocation AS p1', 'p1.pl_parent_id', '=', 'p0.pl_id')
17211464183SGreg Roach            ->leftJoin('placelocation AS p2', 'p2.pl_parent_id', '=', 'p1.pl_id')
17311464183SGreg Roach            ->leftJoin('placelocation AS p3', 'p3.pl_parent_id', '=', 'p2.pl_id')
17411464183SGreg Roach            ->leftJoin('placelocation AS p4', 'p4.pl_parent_id', '=', 'p3.pl_id')
17511464183SGreg Roach            ->leftJoin('placelocation AS p5', 'p5.pl_parent_id', '=', 'p4.pl_id')
17611464183SGreg Roach            ->leftJoin('placelocation AS p6', 'p6.pl_parent_id', '=', 'p5.pl_id')
17711464183SGreg Roach            ->leftJoin('placelocation AS p7', 'p7.pl_parent_id', '=', 'p6.pl_id')
17811464183SGreg Roach            ->leftJoin('placelocation AS p8', 'p8.pl_parent_id', '=', 'p7.pl_id')
17911464183SGreg Roach            ->leftJoin('placelocation AS p9', 'p9.pl_parent_id', '=', 'p8.pl_id')
18011464183SGreg Roach            ->where('p0.pl_parent_id', '=', $parent_id)
18111464183SGreg Roach            ->select([new Expression('COUNT(*) AS child_count'), new Expression('SUM(' . $expression . ') AS no_coord')])
18211464183SGreg Roach            ->first();
18311464183SGreg Roach    }
18494e35917SGreg Roach}
185