Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1a1ece5

Browse files
committed
Move business logic from PlacemarkControllerV1 to PlacemarkService
1 parent6d06b2c commit1a1ece5

File tree

3 files changed

+160
-177
lines changed

3 files changed

+160
-177
lines changed

‎Sources/App/Controllers/PlacemarkControllerV1.swift‎

Lines changed: 8 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,8 @@ internal struct PlacemarkControllerV1: RouteCollection {
3636
try placemark.register(collection:PlacemarkSubmissionControllerV1())
3737
}
3838

39-
// GET /placemarks/v1/features
40-
routes.get("features", use: listPlacemarkFeatures)
41-
// GET /placemarks/v1/techniques
42-
routes.get("techniques", use: listPlacemarkTechniques)
43-
// GET /placemarks/v1/benefits
44-
routes.get("benefits", use: listPlacemarkBenefits)
45-
// GET /placemarks/v1/hazards
46-
routes.get("hazards", use: listPlacemarkHazards)
39+
// GET /placemarks/v1/properties
40+
routes.get("properties", use: listPlacemarkProperties)
4741
}
4842

4943
func listPlacemarks(req:Request)throws->EventLoopFuture<Page<GEOSwift.Feature>>{
@@ -53,178 +47,23 @@ internal struct PlacemarkControllerV1: RouteCollection {
5347
}
5448
}
5549

56-
func createPlacemarkRaw(req:Request)throws->EventLoopFuture<Placemark.Public>{
57-
letuser=try req.auth.require(UserModel.self, with:.bearer, in: req)
58-
// Validate and decode data
59-
tryPlacemark.Create.validate(content: req)
60-
letcreate=try req.content.decode(Placemark.Create.self)
61-
62-
// Do additional validations
63-
// TODO: Check for near spots (e.g. < 20m)
64-
65-
letplacemarkKindFuture=PlacemarkModel.Kind.query(on: req.db)
66-
.filter(\.$humanId== create.kind.rawValue)
67-
.first()
68-
.unwrap(or:Abort(.notFound, reason:"Placemark type not found"))
69-
70-
// Create Placemark object
71-
letplacemarkFuture= placemarkKindFuture.flatMapThrowing{ kindin
72-
tryPlacemarkModel(
73-
name: create.name,
74-
latitude: create.latitude,
75-
longitude: create.longitude,
76-
kindId: kind.requireID(),
77-
state:.private,
78-
creatorId: user.requireID()
79-
)
80-
}
81-
82-
// Save Placemark in database
83-
letcreatePlacemarkFuture= placemarkFuture.passthroughAfter{ $0.create(on: req.db)}
84-
85-
// Add properties
86-
letaddPropertiesFuture={(details:PlacemarkModel.Details)->EventLoopFuture<Void>in
87-
req.eventLoop.makeSucceededFuture(create.properties)
88-
.sequencedFlatMapEach{ kind, propertyIdsin
89-
req.eventLoop.makeSucceededFuture(propertyIds)
90-
.sequencedFlatMapEach{ propertyIdin
91-
PlacemarkModel.Details.Property.query(on: req.db)
92-
.filter(\.$kind== kind)
93-
.filter(\.$humanId== propertyId)
94-
.first()
95-
.unwrap(or:Abort(
96-
.badRequest,
97-
reason:"Invalid property: {\"kind\":\"\(kind)\",\"id\":\"\(propertyId)\" }"
98-
))
99-
.flatMap{ propertyin
100-
details.$properties.attach(property, method:.ifNotExists, on: req.db)
101-
}
102-
}
103-
}
104-
}
105-
106-
// Create placemark details
107-
letcreateDetailsFuture= createPlacemarkFuture
108-
.passthroughAfter{ placemark->EventLoopFuture<Void>in
109-
letdetails=tryPlacemarkModel.Details(
110-
placemarkId: placemark.requireID(),
111-
caption: create.caption,
112-
images:(create.images??[]).map{ $0.absoluteString}
113-
)
114-
115-
return details.create(on: req.db)
116-
.transform(to: details)
117-
.flatMap(addPropertiesFuture)
118-
}
119-
120-
// Trigger satellite view loading
121-
letloadSatelliteViewFuture= createDetailsFuture
122-
.passthroughAfter{ placemark->EventLoopFuture<Void>in
123-
if req.application.environment==.testing{
124-
return req.eventLoop.makeSucceededFuture(())
125-
}else{
126-
return req.queues(.placemarks)
127-
.dispatch(
128-
PlacemarkSatelliteViewJob.self,
129-
.init(
130-
placemarkId:try placemark.requireID(),
131-
latitude: placemark.latitude,
132-
longitude: placemark.longitude
133-
)
134-
)
135-
}
136-
}
137-
138-
// Trigger location reverse geocoding
139-
letreverseGeocodeLocationFuture= loadSatelliteViewFuture
140-
.passthroughAfter{ placemark->EventLoopFuture<Void>in
141-
if req.application.environment==.testing{
142-
return req.eventLoop.makeSucceededFuture(())
143-
}else{
144-
return req.queues(.placemarks)
145-
.dispatch(
146-
PlacemarkLocationJob.self,
147-
.init(
148-
placemarkId:try placemark.requireID(),
149-
latitude: placemark.latitude,
150-
longitude: placemark.longitude
151-
)
152-
)
153-
}
154-
}
155-
156-
return reverseGeocodeLocationFuture
157-
.flatMap{ $0.asPublic(on: req.db)}
158-
//.flatMap { $0.encodeResponse(status: .created, for: req) }
159-
}
160-
16150
func createPlacemark(req:Request)throws->EventLoopFuture<Response>{
162-
tryself.createPlacemarkRaw(req: req)
51+
tryPlacemarkService(req: req).createPlacemark()
16352
.flatMapThrowing{try $0.asGeoJSON()}
16453
.flatMap{ $0.encodeResponse(status:.created, for: req)}
16554
}
16655

167-
func getPlacemarkRaw(req:Request)throws->EventLoopFuture<Placemark.Public>{
168-
letplacemarkId=try req.parameters.require("placemarkId", as:UUID.self)
169-
returnPlacemarkModel.find(placemarkId, on: req.db)
170-
.unwrap(or:Abort(.notFound, reason:"Placemark not found"))
171-
.flatMap{ $0.asPublic(on: req.db)}
172-
}
173-
17456
func getPlacemark(req:Request)throws->EventLoopFuture<GEOSwift.Feature>{
175-
trygetPlacemarkRaw(req: req).flatMapThrowing{try $0.asGeoJSON()}
57+
tryPlacemarkService(req: req).getPlacemark()
58+
.flatMapThrowing{try $0.asGeoJSON()}
17659
}
17760

17861
func deletePlacemark(req:Request)throws->EventLoopFuture<HTTPStatus>{
179-
letuser=try req.auth.require(UserModel.self, with:.bearer, in: req)
180-
letplacemarkId=try req.parameters.require("placemarkId", as:UUID.self)
181-
182-
letplacemarkFuture=PlacemarkModel.find(placemarkId, on: req.db)
183-
.unwrap(or:Abort(.notFound, reason:"Placemark not found"))
184-
185-
// Do additional validations
186-
letguardAuthorizedFuture= placemarkFuture.guard({ placemarkin
187-
placemark.$creator.id== user.id
188-
}, else:Abort(.forbidden, reason:"You cannot delete someone else's placemark!"))
189-
190-
letdeleteDetailsFuture= guardAuthorizedFuture
191-
.passthroughAfter{ _in
192-
PlacemarkModel.Details.query(on: req.db)
193-
.with(\.$placemark)
194-
.filter(\.$placemark.$id== placemarkId)
195-
.all()
196-
.flatMap{ $0.delete(on: req.db)}
197-
}
198-
199-
return deleteDetailsFuture
200-
.flatMap{ $0.delete(on: req.db)}
201-
.transform(to:.noContent)
202-
}
203-
204-
func listPlacemarkFeatures(req:Request)->EventLoopFuture<[Placemark.Property.Localized]>{
205-
listProperties(ofKind:.feature, in: req.db)
206-
}
207-
208-
func listPlacemarkTechniques(req:Request)->EventLoopFuture<[Placemark.Property.Localized]>{
209-
listProperties(ofKind:.technique, in: req.db)
210-
}
211-
212-
func listPlacemarkBenefits(req:Request)->EventLoopFuture<[Placemark.Property.Localized]>{
213-
listProperties(ofKind:.benefit, in: req.db)
214-
}
215-
216-
func listPlacemarkHazards(req:Request)->EventLoopFuture<[Placemark.Property.Localized]>{
217-
listProperties(ofKind:.hazard, in: req.db)
62+
tryPlacemarkService(req: req).deletePlacemark()
21863
}
21964

220-
privatefunc listProperties(
221-
ofKind kind:Placemark.Property.Kind,
222-
in database:Database
223-
)->EventLoopFuture<[Placemark.Property.Localized]>{
224-
PlacemarkModel.Property.query(on: database)
225-
.filter(\.$kind== kind)
226-
.all()
227-
.flatMapEachThrowing{try $0.localized(in:.en)}
65+
func listPlacemarkProperties(req:Request)throws->EventLoopFuture<[Placemark.Property.Localized]>{
66+
tryPlacemarkService(req: req).listProperties()
22867
}
22968

23069
}

‎Sources/App/Services/PlacemarkService.swift‎

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Vapor
1010
import Fluent
1111
import MonkiMapModel
1212
import Models
13+
import Jobs
1314

1415
internalstructPlacemarkService{
1516

@@ -33,4 +34,151 @@ internal struct PlacemarkService {
3334
}
3435
}
3536

37+
func createPlacemark()throws->EventLoopFuture<Placemark.Public>{
38+
letuser=try req.auth.require(UserModel.self, with:.bearer, in: req)
39+
// Validate and decode data
40+
tryPlacemark.Create.validate(content: req)
41+
letcreate=try req.content.decode(Placemark.Create.self)
42+
43+
// Do additional validations
44+
// TODO: Check for near spots (e.g. < 20m)
45+
46+
letplacemarkKindFuture=PlacemarkModel.Kind.query(on: req.db)
47+
.filter(\.$humanId== create.kind.rawValue)
48+
.first()
49+
.unwrap(or:Abort(.notFound, reason:"Placemark type not found"))
50+
51+
// Create Placemark object
52+
letplacemarkFuture= placemarkKindFuture.flatMapThrowing{ kindin
53+
tryPlacemarkModel(
54+
name: create.name,
55+
latitude: create.latitude,
56+
longitude: create.longitude,
57+
kindId: kind.requireID(),
58+
state:.private,
59+
creatorId: user.requireID()
60+
)
61+
}
62+
63+
// Save Placemark in database
64+
letcreatePlacemarkFuture= placemarkFuture.passthroughAfter{ $0.create(on: req.db)}
65+
66+
// Add properties
67+
letaddPropertiesFuture={(details:PlacemarkModel.Details)->EventLoopFuture<Void>in
68+
req.eventLoop.makeSucceededFuture(create.properties)
69+
.sequencedFlatMapEach{ kind, propertyIdsin
70+
req.eventLoop.makeSucceededFuture(propertyIds)
71+
.sequencedFlatMapEach{ propertyIdin
72+
PlacemarkModel.Details.Property.query(on: req.db)
73+
.filter(\.$kind== kind)
74+
.filter(\.$humanId== propertyId)
75+
.first()
76+
.unwrap(or:Abort(
77+
.badRequest,
78+
reason:"Invalid property: {\"kind\":\"\(kind)\",\"id\":\"\(propertyId)\" }"
79+
))
80+
.flatMap{ propertyin
81+
details.$properties.attach(property, method:.ifNotExists, on: req.db)
82+
}
83+
}
84+
}
85+
}
86+
87+
// Create placemark details
88+
letcreateDetailsFuture= createPlacemarkFuture
89+
.passthroughAfter{ placemark->EventLoopFuture<Void>in
90+
letdetails=tryPlacemarkModel.Details(
91+
placemarkId: placemark.requireID(),
92+
caption: create.caption,
93+
images:(create.images??[]).map{ $0.absoluteString}
94+
)
95+
96+
return details.create(on: req.db)
97+
.transform(to: details)
98+
.flatMap(addPropertiesFuture)
99+
}
100+
101+
// Trigger satellite view loading
102+
letloadSatelliteViewFuture= createDetailsFuture
103+
.passthroughAfter{ placemark->EventLoopFuture<Void>in
104+
if req.application.environment==.testing{
105+
return req.eventLoop.makeSucceededFuture(())
106+
}else{
107+
return req.queues(.placemarks)
108+
.dispatch(
109+
PlacemarkSatelliteViewJob.self,
110+
.init(
111+
placemarkId:try placemark.requireID(),
112+
latitude: placemark.latitude,
113+
longitude: placemark.longitude
114+
)
115+
)
116+
}
117+
}
118+
119+
// Trigger location reverse geocoding
120+
letreverseGeocodeLocationFuture= loadSatelliteViewFuture
121+
.passthroughAfter{ placemark->EventLoopFuture<Void>in
122+
if req.application.environment==.testing{
123+
return req.eventLoop.makeSucceededFuture(())
124+
}else{
125+
return req.queues(.placemarks)
126+
.dispatch(
127+
PlacemarkLocationJob.self,
128+
.init(
129+
placemarkId:try placemark.requireID(),
130+
latitude: placemark.latitude,
131+
longitude: placemark.longitude
132+
)
133+
)
134+
}
135+
}
136+
137+
return reverseGeocodeLocationFuture
138+
.flatMap{ $0.asPublic(on: req.db)}
139+
}
140+
141+
func getPlacemark()throws->EventLoopFuture<Placemark.Public>{
142+
letplacemarkId=try req.parameters.require("placemarkId", as:UUID.self)
143+
144+
returnPlacemarkModel.find(placemarkId, on: req.db)
145+
.unwrap(or:Abort(.notFound, reason:"Placemark not found"))
146+
.flatMap{ $0.asPublic(on: req.db)}
147+
}
148+
149+
func deletePlacemark()throws->EventLoopFuture<HTTPStatus>{
150+
letuser=try req.auth.require(UserModel.self, with:.bearer, in: req)
151+
letplacemarkId=try req.parameters.require("placemarkId", as:UUID.self)
152+
153+
letplacemarkFuture=PlacemarkModel.find(placemarkId, on: req.db)
154+
.unwrap(or:Abort(.notFound, reason:"Placemark not found"))
155+
156+
// Do additional validations
157+
letguardAuthorizedFuture= placemarkFuture.guard({ placemarkin
158+
placemark.$creator.id== user.id
159+
}, else:Abort(.forbidden, reason:"You cannot delete someone else's placemark!"))
160+
161+
letdeleteDetailsFuture= guardAuthorizedFuture
162+
.passthroughAfter{ _in
163+
PlacemarkModel.Details.query(on: req.db)
164+
.with(\.$placemark)
165+
.filter(\.$placemark.$id== placemarkId)
166+
.all()
167+
.flatMap{ $0.delete(on: req.db)}
168+
}
169+
170+
return deleteDetailsFuture
171+
.flatMap{ $0.delete(on: req.db)}
172+
.transform(to:.noContent)
173+
}
174+
175+
func listProperties()throws->EventLoopFuture<[Placemark.Property.Localized]>{
176+
letkind=try req.query.get(Placemark.Property.Kind.self, at:"kind")
177+
178+
returnPlacemarkModel.Property.query(on: req.db)
179+
.filter(\.$kind== kind)
180+
.all()
181+
.flatMapEachThrowing{try $0.localized(in:.en)}
182+
}
183+
36184
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp