]> git.openstreetmap.org Git - rails.git/blob - app/controllers/api/tracepoints_controller.rb
Refactor api controllers to inherit from a common ApiController
[rails.git] / app / controllers / api / tracepoints_controller.rb
1 module Api
2   class TracepointsController < ApiController
3     before_action :api_deny_access_handler
4
5     authorize_resource
6
7     before_action :check_api_readable
8     around_action :api_call_handle_error, :api_call_timeout
9
10     # Get an XML response containing a list of tracepoints that have been uploaded
11     # within the specified bounding box, and in the specified page.
12     def index
13       # retrieve the page number
14       page = params["page"].to_s.to_i
15
16       unless page >= 0
17         report_error("Page number must be greater than or equal to 0")
18         return
19       end
20
21       offset = page * Settings.tracepoints_per_page
22
23       # Figure out the bbox
24       # check boundary is sane and area within defined
25       # see /config/application.yml
26       begin
27         bbox = BoundingBox.from_bbox_params(params)
28         bbox.check_boundaries
29         bbox.check_size
30       rescue StandardError => err
31         report_error(err.message)
32         return
33       end
34
35       # get all the points
36       ordered_points = Tracepoint.bbox(bbox).joins(:trace).where(:gpx_files => { :visibility => %w[trackable identifiable] }).order("gpx_id DESC, trackid ASC, timestamp ASC")
37       unordered_points = Tracepoint.bbox(bbox).joins(:trace).where(:gpx_files => { :visibility => %w[public private] }).order("gps_points.latitude", "gps_points.longitude", "gps_points.timestamp")
38       points = ordered_points.union_all(unordered_points).offset(offset).limit(Settings.tracepoints_per_page)
39
40       doc = XML::Document.new
41       doc.encoding = XML::Encoding::UTF_8
42       root = XML::Node.new "gpx"
43       root["version"] = "1.0"
44       root["creator"] = "OpenStreetMap.org"
45       root["xmlns"] = "http://www.topografix.com/GPX/1/0"
46
47       doc.root = root
48
49       # initialise these variables outside of the loop so that they
50       # stay in scope and don't get free'd up by the GC during the
51       # loop.
52       gpx_id = -1
53       trackid = -1
54       track = nil
55       trkseg = nil
56       anon_track = nil
57       anon_trkseg = nil
58       gpx_file = nil
59       timestamps = false
60
61       points.each do |point|
62         if gpx_id != point.gpx_id
63           gpx_id = point.gpx_id
64           trackid = -1
65           gpx_file = Trace.find(gpx_id)
66
67           if gpx_file.trackable?
68             track = XML::Node.new "trk"
69             doc.root << track
70             timestamps = true
71
72             if gpx_file.identifiable?
73               track << (XML::Node.new("name") << gpx_file.name)
74               track << (XML::Node.new("desc") << gpx_file.description)
75               track << (XML::Node.new("url") << url_for(:controller => "/traces", :action => "show", :display_name => gpx_file.user.display_name, :id => gpx_file.id))
76             end
77           else
78             # use the anonymous track segment if the user hasn't allowed
79             # their GPX points to be tracked.
80             timestamps = false
81             if anon_track.nil?
82               anon_track = XML::Node.new "trk"
83               doc.root << anon_track
84             end
85             track = anon_track
86           end
87         end
88
89         if trackid != point.trackid
90           if gpx_file.trackable?
91             trkseg = XML::Node.new "trkseg"
92             track << trkseg
93             trackid = point.trackid
94           else
95             if anon_trkseg.nil?
96               anon_trkseg = XML::Node.new "trkseg"
97               anon_track << anon_trkseg
98             end
99             trkseg = anon_trkseg
100           end
101         end
102
103         trkseg << point.to_xml_node(timestamps)
104       end
105
106       response.headers["Content-Disposition"] = "attachment; filename=\"tracks.gpx\""
107
108       render :xml => doc.to_s
109     end
110   end
111 end