diff --git a/app/Place.php b/app/Place.php index 0e1e0c9b..52576b81 100644 --- a/app/Place.php +++ b/app/Place.php @@ -76,6 +76,19 @@ class Place extends Model return $query->where($field, '<=', $distance)->orderBy($field); } + public function scopeWhereExternalURL(Builder $query, string $url) + { + $type = $this->getType($url); + if ($type === null) { + // we haven’t set a type, therefore result must be empty set + // id can’t be null, so this will return empty set + return $query->whereNull('id'); + } + return $query->where('external_urls', '@>', json_encode([ + $type => $url + ])); + } + /** * Get the latitude from the `location` property. * @@ -115,4 +128,31 @@ class Place extends Model { return config('app.shorturl') . '/places/' . $this->slug; } + + public function setExternalUrlsAttribute($value) + { + $type = $this->getType($value); + if ($type === null) { + throw new \Exception('Unkown external url type'); + } + $already = []; + if (array_key_exists('external_urls', $this->attributes)) { + $already = json_decode($this->attributes['external_urls'], true); + } + $already[$type] = $value; + $this->attributes['external_urls'] = json_encode($already); + } + + private function getType(string $url): ?string + { + $host = parse_url($url, PHP_URL_HOST); + if (ends_with($host, 'foursquare.com') === true) { + return 'foursquare'; + } + if (ends_with($host, 'openstreetmap.org') === true) { + return 'osm'; + } + + return null; + } } diff --git a/app/Services/PlaceService.php b/app/Services/PlaceService.php index 98158167..2a823f33 100644 --- a/app/Services/PlaceService.php +++ b/app/Services/PlaceService.php @@ -46,12 +46,8 @@ class PlaceService public function createPlaceFromCheckin(array $checkin): Place { //check if the place exists if from swarm - if (array_key_exists('url', $checkin['properties']) && ends_with(parse_url($checkin['properties']['url'][0], PHP_URL_HOST), 'foursquare.com')) { - $place = Place::where( - 'external_urls', - '@>', - json_encode(['foursquare' => $checkin['properties']['url'][0]]) - )->get(); + if (array_key_exists('url', $checkin['properties'])) { + $place = Place::whereExternalURL($checkin['properties']['url'][0])->get(); if (count($place) === 1) { return $place->first(); } @@ -64,9 +60,7 @@ class PlaceService } $place = new Place(); $place->name = $checkin['properties']['name'][0]; - if (ends_with(parse_url($checkin['properties']['url'][0], PHP_URL_HOST), 'foursquare.com')) { - $place->foursquare = $checkin['properties']['url'][0]; - } + $place->external_urls = $checkin['properties']['url'][0]; $place->location = new Point( (float) $checkin['properties']['latitude'][0], (float) $checkin['properties']['longitude'][0] diff --git a/changelog.md b/changelog.md index 29a0c216..8a1cd4d1 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,8 @@ # Changelog +## Version {next} + - Transition to using a JSON column for external urls of places + ## Version 0.5.19 (2017-06-27) - Fix error in App\\WebMention.php diff --git a/tests/Feature/SwarmTest.php b/tests/Feature/SwarmTest.php index 16ae8cbe..9f395adf 100644 --- a/tests/Feature/SwarmTest.php +++ b/tests/Feature/SwarmTest.php @@ -44,7 +44,7 @@ class SwarmTest extends TestCase ->assertStatus(201) ->assertJson(['response' => 'created']); $this->assertDatabaseHas('places', [ - 'foursquare' => 'https://foursquare.com/v/123456' + 'external_urls' => '{"foursquare": "https://foursquare.com/v/123456"}' ]); $this->assertDatabaseHas('notes', [ 'swarm_url' => 'https://www.swarmapp.com/checkin/abc'