summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/Http/RequestHandlers/MapDataDelete.php2
-rw-r--r--app/Http/RequestHandlers/MapDataDeleteUnused.php61
-rw-r--r--app/Http/RequestHandlers/MapDataImportAction.php11
-rw-r--r--app/Http/Routes/WebRoutes.php2
-rw-r--r--app/Services/MapDataService.php107
5 files changed, 136 insertions, 47 deletions
diff --git a/app/Http/RequestHandlers/MapDataDelete.php b/app/Http/RequestHandlers/MapDataDelete.php
index ba7c7b3949..ddeb4c67b6 100644
--- a/app/Http/RequestHandlers/MapDataDelete.php
+++ b/app/Http/RequestHandlers/MapDataDelete.php
@@ -28,7 +28,7 @@ use function redirect;
use function route;
/**
- * Delete a place location from the control panel.
+ * Delete a location from the control panel.
*/
class MapDataDelete implements RequestHandlerInterface
{
diff --git a/app/Http/RequestHandlers/MapDataDeleteUnused.php b/app/Http/RequestHandlers/MapDataDeleteUnused.php
new file mode 100644
index 0000000000..1b57b012e6
--- /dev/null
+++ b/app/Http/RequestHandlers/MapDataDeleteUnused.php
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2021 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Http\RequestHandlers;
+
+use Fisharebest\Webtrees\PlaceLocation;
+use Fisharebest\Webtrees\Services\MapDataService;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+use function redirect;
+use function route;
+
+/**
+ * Delete unused locations from the control panel.
+ */
+class MapDataDeleteUnused implements RequestHandlerInterface
+{
+ private MapDataService $map_data_service;
+
+ /**
+ * Dependency injection.
+ *
+ * @param MapDataService $map_data_service
+ */
+ public function __construct(MapDataService $map_data_service)
+ {
+ $this->map_data_service = $map_data_service;
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ *
+ * @return ResponseInterface
+ */
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $this->map_data_service->deleteUnusedLocations(null, [0]);
+
+ $url = route(MapDataList::class);
+
+ return redirect($url);
+ }
+}
diff --git a/app/Http/RequestHandlers/MapDataImportAction.php b/app/Http/RequestHandlers/MapDataImportAction.php
index 52cd2ebbc5..51b358ea9b 100644
--- a/app/Http/RequestHandlers/MapDataImportAction.php
+++ b/app/Http/RequestHandlers/MapDataImportAction.php
@@ -88,7 +88,6 @@ class MapDataImportAction implements RequestHandlerInterface
$serverfile = $params['serverfile'] ?? '';
$options = $params['import-options'] ?? '';
- $clear_database = (bool) ($params['cleardatabase'] ?? false);
$local_file = $request->getUploadedFiles()['localfile'] ?? null;
$places = [];
@@ -155,16 +154,6 @@ class MapDataImportAction implements RequestHandlerInterface
fclose($fp);
- if ($clear_database) {
- // Child places are deleted via on-delete-cascade...
- DB::table('place_location')
- ->whereNull('parent_id')
- ->delete();
-
- // Automatically import any new/missing places.
- $this->map_data_service->importMissingLocations();
- }
-
$added = 0;
$updated = 0;
diff --git a/app/Http/Routes/WebRoutes.php b/app/Http/Routes/WebRoutes.php
index 0d168907a8..1ce7fb721b 100644
--- a/app/Http/Routes/WebRoutes.php
+++ b/app/Http/Routes/WebRoutes.php
@@ -147,6 +147,7 @@ use Fisharebest\Webtrees\Http\RequestHandlers\ManageMediaPage;
use Fisharebest\Webtrees\Http\RequestHandlers\ManageTrees;
use Fisharebest\Webtrees\Http\RequestHandlers\MapDataAdd;
use Fisharebest\Webtrees\Http\RequestHandlers\MapDataDelete;
+use Fisharebest\Webtrees\Http\RequestHandlers\MapDataDeleteUnused;
use Fisharebest\Webtrees\Http\RequestHandlers\MapDataEdit;
use Fisharebest\Webtrees\Http\RequestHandlers\MapDataExportCSV;
use Fisharebest\Webtrees\Http\RequestHandlers\MapDataExportGeoJson;
@@ -380,6 +381,7 @@ class WebRoutes
$router->post(UsersCleanupAction::class, '/users-cleanup');
$router->get(MapDataAdd::class, '/map-data-add{/parent_id}');
$router->post(MapDataDelete::class, '/map-data-delete/{place_id}');
+ $router->post(MapDataDeleteUnused::class, '/map-data-delete-unused');
$router->get(MapDataEdit::class, '/map-data-edit/{place_id}');
$router->get(MapDataExportCSV::class, '/map-data-csv{/parent_id}');
$router->get(MapDataExportGeoJson::class, '/map-data-geojson{/parent_id}');
diff --git a/app/Services/MapDataService.php b/app/Services/MapDataService.php
index 174d1efd0a..747a0d6a6a 100644
--- a/app/Services/MapDataService.php
+++ b/app/Services/MapDataService.php
@@ -19,13 +19,13 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Services;
+use Fisharebest\Webtrees\FlashMessages;
use Fisharebest\Webtrees\Gedcom;
use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\PlaceLocation;
use Illuminate\Database\Capsule\Manager as DB;
use Illuminate\Database\Query\Expression;
use Illuminate\Support\Collection;
-use stdClass;
use function abs;
use function array_filter;
@@ -74,7 +74,7 @@ class MapDataService
*
* @param PlaceLocation $location
*
- * @return array<string,array<stdClass>>
+ * @return array<string,array<object>>
*/
public function activePlaces(PlaceLocation $location): array
{
@@ -124,7 +124,7 @@ class MapDataService
'p8.p_place AS part_8',
])
->get()
- ->map(static function (stdClass $row): string {
+ ->map(static function (object $row): string {
return implode(Gedcom::PLACE_SEPARATOR, array_filter((array) $row));
});
@@ -149,7 +149,7 @@ class MapDataService
'p8.place AS part_8',
])
->get()
- ->map(static function (stdClass $row): string {
+ ->map(static function (object $row): string {
return implode(Gedcom::PLACE_SEPARATOR, array_filter((array) $row));
});
@@ -161,37 +161,9 @@ class MapDataService
}
/**
- * Find all active places that match a location
- *
- * @param PlaceLocation $location
- *
- * @return array<string>
- */
- private function placeIdsForLocation(PlaceLocation $location): array
- {
- $hierarchy = [];
-
- while ($location->id() !== null) {
- array_unshift($hierarchy, $location->locationName());
- $location = $location->parent();
- }
-
- $place_ids = ['0'];
-
- foreach ($hierarchy as $place_name) {
- $place_ids = DB::table('places')
- ->whereIn('p_parent_id', $place_ids)
- ->where('p_place', '=', $place_name)
- ->groupBy(['p_id'])
- ->pluck('p_id')
- ->all();
- }
-
- return $place_ids;
- }
-
- /**
* @param int $id
+ *
+ * @return void
*/
public function deleteRecursively(int $id): void
{
@@ -202,6 +174,41 @@ class MapDataService
}
/**
+ * @param int|null $parent_location_id
+ * @param array<int> $parent_place_ids
+ *
+ * @return void
+ */
+ public function deleteUnusedLocations(?int $parent_location_id, array $parent_place_ids): void
+ {
+ if ($parent_location_id === null) {
+ $location_query = DB::table('place_location')
+ ->whereNull('parent_id');
+ } else {
+ $location_query = DB::table('place_location')
+ ->where('parent_id', '=', $parent_location_id);
+ }
+
+ foreach ($location_query->get() as $location) {
+ $places = DB::table('places')
+ ->whereIn('p_parent_id', $parent_place_ids)
+ ->where('p_place', '=', $location->place)
+ ->get();
+
+ if ($places->isEmpty()) {
+ FlashMessages::addMessage(I18N::translate('ā€œ%sā€ has been deleted.', e($location->place)));
+
+ DB::table('place_location')
+ ->where('id', '=', $location->id)
+ ->delete();
+ } else {
+ $place_ids = $places->map(static fn(object $place): int => (int) $place->p_id)->all();
+ $this->deleteUnusedLocations((int) $location->id, $place_ids);
+ }
+ }
+ }
+
+ /**
* Find a list of child places.
* How many children does each child place have? How many have co-ordinates?
*
@@ -252,7 +259,7 @@ class MapDataService
new Expression('SUM(' . $expression . ') AS no_coord'),
])
->get()
- ->map(static function (stdClass $row): stdClass {
+ ->map(static function (object $row): object {
$row->child_count = (int) $row->child_count;
$row->no_coord = (int) $row->no_coord;
$row->key = mb_strtolower($row->place);
@@ -282,6 +289,36 @@ class MapDataService
}
/**
+ * Find all active places that match a location
+ *
+ * @param PlaceLocation $location
+ *
+ * @return array<string>
+ */
+ private function placeIdsForLocation(PlaceLocation $location): array
+ {
+ $hierarchy = [];
+
+ while ($location->id() !== null) {
+ array_unshift($hierarchy, $location->locationName());
+ $location = $location->parent();
+ }
+
+ $place_ids = ['0'];
+
+ foreach ($hierarchy as $place_name) {
+ $place_ids = DB::table('places')
+ ->whereIn('p_parent_id', $place_ids)
+ ->where('p_place', '=', $place_name)
+ ->groupBy(['p_id'])
+ ->pluck('p_id')
+ ->all();
+ }
+
+ return $place_ids;
+ }
+
+ /**
* @param float $degrees
* @param string $positive
* @param string $negative