+ before_filter :authorize_web
+ before_filter :set_locale
+ before_filter :require_user, :only => [:mine, :create, :edit, :delete, :make_public]
+ before_filter :authorize, :only => [:api_details, :api_data, :api_create]
+ before_filter :check_database_readable, :except => [:api_details, :api_data, :api_create]
+ before_filter :check_database_writable, :only => [:create, :edit, :delete, :make_public]
+ before_filter :check_api_readable, :only => [:api_details, :api_data]
+ before_filter :check_api_writable, :only => [:api_create]
+
+ # Counts and selects pages of GPX traces for various criteria (by user, tags, public etc.).
+ # target_user - if set, specifies the user to fetch traces for. if not set will fetch all traces
+ def list(target_user = nil, action = "list")
+ # from display name, pick up user id if one user's traces only
+ display_name = params[:display_name]
+ if target_user.nil? and !display_name.blank?
+ target_user = User.find(:first, :conditions => [ "visible = ? and display_name = ?", true, display_name])
+ if target_user.nil?
+ @not_found_user = display_name
+ render :action => 'no_such_user', :status => :not_found
+ return
+ end
+ end
+
+ # set title
+ if target_user.nil?
+ @title = "Public GPS traces"
+ elsif @user and @user == target_user
+ @title = "Your GPS traces"
+ else
+ @title = "Public GPS traces from #{target_user.display_name}"
+ end
+
+ @title += " tagged with #{params[:tag]}" if params[:tag]
+
+ # four main cases:
+ # 1 - all traces, logged in = all public traces + all user's (i.e + all mine)
+ # 2 - all traces, not logged in = all public traces
+ # 3 - user's traces, logged in as same user = all user's traces
+ # 4 - user's traces, not logged in as that user = all user's public traces
+ if target_user.nil? # all traces
+ if @user
+ conditions = ["(gpx_files.public = ? OR gpx_files.user_id = ?)", true, @user.id] #1
+ else
+ conditions = ["gpx_files.public = ?", true] #2
+ end
+ else
+ if @user and @user == target_user
+ conditions = ["gpx_files.user_id = ?", @user.id] #3 (check vs user id, so no join + can't pick up non-public traces by changing name)
+ else
+ conditions = ["gpx_files.public = ? AND gpx_files.user_id = ?", true, target_user.id] #4
+ end
+ end
+
+ if params[:tag]
+ @tag = params[:tag]
+
+ files = Tracetag.find_all_by_tag(params[:tag]).collect { |tt| tt.gpx_id }
+
+ if files.length > 0
+ conditions[0] += " AND gpx_files.id IN (#{files.join(',')})"
+ else
+ conditions[0] += " AND 0 = 1"
+ end
+ end
+
+ conditions[0] += " AND gpx_files.visible = ?"
+ conditions << true
+
+ @trace_pages, @traces = paginate(:traces,
+ :include => [:user, :tags],
+ :conditions => conditions,
+ :order => "gpx_files.timestamp DESC",
+ :per_page => 20)
+
+ # put together SET of tags across traces, for related links
+ tagset = Hash.new
+ if @traces
+ @traces.each do |trace|
+ trace.tags.reload if params[:tag] # if searched by tag, ActiveRecord won't bring back other tags, so do explicitly here
+ trace.tags.each do |tag|
+ tagset[tag.tag] = tag.tag
+ end
+ end
+ end
+
+ # final helper vars for view
+ @action = action
+ @display_name = target_user.display_name if target_user
+ @all_tags = tagset.values