Allow simple merging of places

This commit is contained in:
Jonny Barnes 2017-05-28 22:45:14 +01:00
parent 71d59bc0d1
commit 451437ed6a
6 changed files with 132 additions and 23 deletions

View file

@ -95,4 +95,55 @@ class PlacesController extends Controller
return redirect('/admin/places');
}
/**
* List the places we can merge with the current place.
*
* @param string Place id
* @return Illuminate\View\Factory view
*/
public function mergeIndex($placeId)
{
$first = Place::find($placeId);
$results = Place::near(new Point($first->latitude, $first->longitude))->get();
$places = [];
foreach ($results as $place) {
if ($place->slug !== $first->slug) {
$places[] = $place;
}
}
return view('admin.places.merge.index', compact('first', 'places'));
}
public function mergeEdit($place1_id, $place2_id)
{
$place1 = Place::find($place1_id);
$place2 = Place::find($place2_id);
return view('admin.places.merge.edit', compact('place1', 'place2'));
}
public function mergeStore(Request $request)
{
$place1 = Place::find($request->input('place1'));
$place2 = Place::find($request->input('place2'));
if ($request->input('delete') === '1') {
foreach ($place1->notes as $note) {
$note->place()->dissociate();
$note->place()->associate($place2->id);
}
$place1->delete();
}
if ($request->input('delete') === '2') {
foreach ($place2->notes as $note) {
$note->place()->dissociate();
$note->place()->associate($place1->id);
}
$place2->delete();
}
return redirect('/admin/places');
}
}

View file

@ -4,6 +4,8 @@ namespace App;
use DB;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Phaza\LaravelPostgis\Geometries\Point;
use MartinBean\Database\Eloquent\Sluggable;
use Phaza\LaravelPostgis\Eloquent\PostgisTrait;
@ -45,33 +47,23 @@ class Place extends Model
}
/**
* Get all places within a specified distance.
* Select places near a given location.
*
* @param float latitude
* @param float longitude
* @param int maximum distance
* @todo Check this shit.
* @param \Illuminate\Database\Eloquent\Builder $query
* @param Point $point
* @param int Distance
* @return \Illuminate\Database\Eloquent\Builder
*/
public static function near(float $lat, float $lng, int $distance)
public function scopeNear(Builder $query, Point $point, $distance = 100)
{
$point = $lng . ' ' . $lat;
$distace = $distance ?? 1000;
$places = DB::select(DB::raw("select
name,
slug,
ST_AsText(location) AS location,
ST_Distance(
ST_GeogFromText('SRID=4326;POINT($point)'),
location
) AS distance
from places
where ST_DWithin(
ST_GeogFromText('SRID=4326;POINT($point)'),
location,
$distance
) ORDER BY distance"));
$field = DB::raw(
sprintf("ST_Distance(%s.location, ST_GeogFromText('%s'))",
$this->getTable(),
$point->toWKT()
)
);
return $places;
return $query->where($field, '<=', $distance)->orderBy($field);
}
/*

View file

@ -119,6 +119,8 @@ Edit Place « Admin CP
<input type="submit" name="edit" value="Edit"><br><br>
<input type="submit" name="delete" value="Delete">
</form>
<p><a href="/admin/places/{{ $id }}/merge">Merge with another place?</a></p>
@stop
@section('scripts')

View file

@ -0,0 +1,47 @@
@extends('master')
@section('title')
Merge Places « Admin CP
@stop
@section('content')
<h1>Merge places</h1>
<p>When a place is deleted, it is removed from the database, and all the notes associated with it, will be re-associated with the other place.</p>
<table>
<tr>
<th></th>
<th>Place 1</th>
<th>Place 2</th>
</tr>
<tr>
<th>Name</th>
<td>{{ $place1->name }}</td>
<td>{{ $place2->name }}</td>
</tr>
<tr>
<th>Description</th>
<td>{{ $place1->description }}</td>
<td>{{ $place2->description }}</td>
</tr>
<tr>
<th>location</th>
<td>{{ $place1->latitude }}, {{ $place1->longitude }}</td>
<td>{{ $place2->latitude }}, {{ $place2->longitude }}</td>
</tr>
<tr>
<th>Foursquare</th>
<td>{{ $place1->foursquare }}</td>
<td>{{ $place2->foursquare }}</td>
</tr>
<tr>
<td></td>
<form action="/admin/places/merge" method="post">
{{ csrf_field() }}
<input type="hidden" name="place1" value="{{ $place1->id }}">
<input type="hidden" name="place2" value="{{ $place2->id }}">
<td><button type="submit" name="delete" value="1">Delete Place 1</button></td>
<td><button type="submit" name="delete" value="2">Delete Place 2</button></td>
</form>
</tr>
</table>
@stop

View file

@ -0,0 +1,14 @@
@extends('master')
@section('title')
Merge Places « Admin CP
@stop
@section('content')
<p>We shall be merging {{ $first->name }}. Its location is <code>Point({{ $first->location }})</code>.</p>
<ul>
@foreach($places as $place)
<li><a href="/admin/places/{{ $first->id }}/merge/{{ $place->id }}">{{ $place->name }}</a></li>
@endforeach
</ul>
@stop

View file

@ -80,6 +80,9 @@ Route::group(['domain' => config('url.longurl')], function () {
Route::post('/', 'PlacesController@store');
Route::get('/{id}/edit', 'PlacesController@edit');
Route::put('/{id}', 'PlacesController@update');
Route::get('/{id}/merge', 'PlacesController@mergeIndex');
Route::get('/{place1_id}/merge/{place2_id}', 'PlacesController@mergeEdit');
Route::post('/merge', 'PlacesController@mergeStore');
Route::delete('/{id}', 'PlacesController@destroy');
});
});