Passed
Push — develop ( 5f211d...930448 )
by Greg
13:36 queued 06:57
created

MapDataExportGeoJson::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2021 webtrees development team
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16
 */
17
18
declare(strict_types=1);
19
20
namespace Fisharebest\Webtrees\Http\RequestHandlers;
21
22
use Fisharebest\Webtrees\Gedcom;
23
use Fisharebest\Webtrees\PlaceLocation;
24
use Fisharebest\Webtrees\Services\MapDataService;
25
use Illuminate\Database\Capsule\Manager as DB;
26
use Psr\Http\Message\ResponseInterface;
27
use Psr\Http\Message\ServerRequestInterface;
28
use Psr\Http\Server\RequestHandlerInterface;
29
30
use function addcslashes;
31
use function array_reverse;
32
use function array_unshift;
33
use function count;
34
use function implode;
35
use function preg_replace;
36
use function response;
37
38
/**
39
 * Export geographic data.
40
 */
41
class MapDataExportGeoJson implements RequestHandlerInterface
42
{
43
    /** @var MapDataService */
44
    private $map_data_service;
45
46
    /**
47
     * Dependency injection.
48
     *
49
     * @param MapDataService $map_data_service
50
     */
51
    public function __construct(MapDataService $map_data_service)
52
    {
53
        $this->map_data_service = $map_data_service;
54
    }
55
56
    /**
57
     * @param ServerRequestInterface $request
58
     *
59
     * @return ResponseInterface
60
     */
61
    public function handle(ServerRequestInterface $request): ResponseInterface
62
    {
63
        $parent_id = $request->getAttribute('parent_id');
64
65
        if ($parent_id === null) {
66
            $parent = new PlaceLocation('');
67
        } else {
68
            $parent = $this->map_data_service->findById((int) $parent_id);
69
        }
70
71
        for ($tmp = $parent, $hierarchy = []; $tmp->id() !== null; $tmp = $tmp->parent()) {
72
            $hierarchy[] = $tmp->locationName();
73
        }
74
75
        // Create the file name
76
        $filename = preg_replace('/[^\p{L}]+/u', '-', $hierarchy[0] ?? 'Global') . '.geojson';
77
78
        // Recursively search for child places
79
        $features = [];
80
        $queue    = [[
81
            $parent->id(), array_reverse($hierarchy), $parent->latitude(), $parent->longitude()
82
        ]];
83
84
        while ($queue !== []) {
85
            [$id, $hierarchy, $latitude, $longitude] = array_shift($queue);
86
87
            if ($latitude !== null && !$longitude !== null) {
88
                $features[] = [
89
                    'type'       => 'Feature',
90
                    'geometry'   => [
91
                        'type'        => 'Point',
92
                        'coordinates' => [
93
                            $longitude,
94
                            $latitude,
95
                        ],
96
                    ],
97
                    'properties' => [
98
                        'name' => implode(Gedcom::PLACE_SEPARATOR, array_reverse($hierarchy)),
99
                    ],
100
                ];
101
            }
102
103
            $query = DB::table('place_location');
104
            // Data for the next level.
105
106
            if ($id === null) {
107
                $query->whereNull('parent_id');
108
            } else {
109
                $query->where('parent_id', '=', $id);
110
            }
111
112
            $rows = $query
113
                ->orderBy('place', 'DESC')
114
                ->select(['id', 'place', 'latitude', 'longitude'])
115
                ->get();
116
117
            $next_level = count($hierarchy);
118
119
            foreach ($rows as $row) {
120
                $hierarchy[$next_level] = $row->place;
121
                array_unshift($queue, [$row->id, $hierarchy, $row->latitude, $row->longitude]);
122
            }
123
        }
124
125
        $geojson = [
126
            'type'     => 'FeatureCollection',
127
            'features' => $features,
128
        ];
129
130
        $filename = addcslashes($filename, '"');
131
132
        return response($geojson)
133
            ->withHeader('Content-Type', 'application/vnd.geo+json')
134
            ->withHeader('Content-Disposition', 'attachment; filename="' . $filename . '"');
135
    }
136
}
137