<commit_before>#
# Copyright (C) 2011 Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#

# @API Courses
#
# API for accessing course information.
class CoursesController < ApplicationController
  before_filter :require_user, :only => [:index]
  before_filter :require_user_for_context, :only => [:roster, :roster_user, :locks, :switch_role, :publish_to_sis]

  # @API
  # Returns the list of active courses for the current user.
  #
  # @argument enrollment_type [optional, "teacher"|"student"|"ta"|"observer"|"designer"]
  #   When set, only return courses where the user is enrolled as this type. For
  #   example, set to "teacher" to return only courses where the user is
  #   enrolled as a Teacher.
  #
  # @argument include[] ["needs_grading_count"] Optional information to include with each Course.
  #   When needs_grading_count is given, and the current user has grading
  #   rights, the total number of submissions needing grading for all
  #   assignments is returned.
  #
  # @argument include[] ["syllabus_body"] Optional information to include with each Course.
  #   When syllabus_body is given the user-generated html for the course 
  #   syllabus is returned.
  #
  # @response_field id The unique identifier for the course.
  # @response_field name The name of the course.
  # @response_field course_code The course code.
  # @response_field enrollments A list of enrollments linking the current user
  #   to the course.
  #
  # @response_field needs_grading_count Number of submissions needing grading
  #   for all the course assignments. Only returned if
  #   include[]=needs_grading_count
  #
  # @example_response
  #   [ { 'id': 1, 'name': 'first course', 'course_code': 'first', 'enrollments': [{'type': 'student'}] },
  #     { 'id': 2, 'name': 'second course', 'course_code': 'second', 'enrollments': [{'type': 'teacher'}] } ]
  def index
    respond_to do |format|
      format.html {
        @current_enrollments = @current_user.cached_current_enrollments(:include_enrollment_uuid => session[:enrollment_uuid]).sort_by{|e| [e.active? ? 1 : 0, e.long_name] }
        @past_enrollments = @current_user.enrollments.ended.scoped(:conditions=>"enrollments.workflow_state NOT IN ('invited', 'deleted')")
      }
      format.json {
        enrollments = @current_user.cached_current_enrollments
        if params[:enrollment_type]
          e_type = "#{params[:enrollment_type].capitalize}Enrollment"
          enrollments = enrollments.reject { |e| e.class.name != e_type }
        end

        include_grading = Array(params[:include]).include?('needs_grading_count')
        include_syllabus = Array(params[:include]).include?('syllabus_body')

        hash = []
        enrollments.group_by(&:course_id).each do |course_id, course_enrollments|
          course = course_enrollments.first.course
          hash << course.as_json(
            :include_root => false, :only => %w(id name course_code sis_source_id))
          hash.last['enrollments'] = course_enrollments.map { |e| { :type => e.readable_type.downcase } }
          if include_grading && course_enrollments.any? { |e| e.participating_admin? }
            hash.last['needs_grading_count'] = course.assignments.active.sum('needs_grading_count')
          end
          if include_syllabus
            hash.last['syllabus_body'] = course.syllabus_body
          end
        end
        render :json => hash.to_json
      }
    end
  end
  
  def create
    @account = Account.find(params[:account_id])
    if authorized_action(@account, @current_user, :manage_courses)

      if (sub_account_id = params[:course].delete(:account_id)) && sub_account_id.to_i != @account.id
        @sub_account = @account.find_child(sub_account_id) || raise(ActiveRecord::RecordNotFound)
      end

      if enrollment_term_id = params[:course].delete(:enrollment_term_id)
        params[:course][:enrollment_term] = (@account.root_account || @account).enrollment_terms.find(enrollment_term_id)
      end

      @course = (@sub_account || @account).courses.build(params[:course])
      respond_to do |format|
        if @course.save
          format.html
          format.json { render :json => @course.to_json }
        else
          flash[:error] = t('errors.create_failed', "Course creation failed")
          format.html { redirect_to :root_url }
          format.json { render :json => @course.errors.to_json, :status => :bad_request }
        end
      end
    end
  end
  
  def backup
    get_context
    if authorized_action(@context, @current_user, :update)
      backup_json = @context.backup_to_json
      send_file_headers!( :length=>backup_json.length, :filename=>"#{@context.name.underscore.gsub(/\s/, "_")}_#{Date.today.to_s}_backup.instructure", :disposition => 'attachment', :type => 'application/instructure')
      render :text => proc {|response, output|
        output.write backup_json
      }
    end
  end
  
  def restore
    get_context
    if authorized_action(@context, @current_user, :update)
      respond_to do |format|
        if params[:restore]
          @context.restore_from_json_backup(params[:restore])
          flash[:notice] = t('notices.backup_restored', "Backup Successfully Restored!")
          format.html { redirect_to named_context_url(@context, :context_url) }
        else
          format.html
        end
      end
    end
  end

  def unconclude
    get_context
    if authorized_action(@context, @current_user, :update)
      @context.unconclude
      flash[:notice] = t('notices.unconcluded', "Course un-concluded")
      redirect_to(named_context_url(@context, :context_url))
    end
  end

  include Api::V1::User

  # @API
  # Returns the list of sections for this course.
  #
  # @argument include[] ["students"] Associations to include with the group.
  #
  # @response_field id The unique identifier for the course section.
  # @response_field name The name of the section.
  #
  # @example_response
  #   ?include[]=students
  #
  # [
  #   {
  #     "id": 1,
  #     "name": "Section A",
  #     "students": [...]
  #   },
  #   {
  #     "id": 2,
  #     "name": "Section B",
  #     "students": [...]
  #   }
  # ]
  def sections
    get_context
    if authorized_action(@context, @current_user, :read_roster)
      includes = Array(params[:include])
      include_students = includes.include?('students')

      result = @context.course_sections.map do |section|
        res = section.as_json(:include_root => false,
                              :only => %w(id name))
        if include_students
          proxy = section.enrollments
          if user_json_is_admin?
            proxy = proxy.scoped(:include => { :user => :pseudonym })
          else
            proxy = proxy.scoped(:include => :user)
          end
          res['students'] = proxy.all(:conditions => "type = 'StudentEnrollment'").
            map { |e| user_json(e.user) }
        end
        res
      end

      render :json => result
    end
  end

  # @API
  # Returns the list of students enrolled in this course.
  #
  # @response_field id The unique identifier for the student.
  # @response_field name The full student name.
  # @response_field sis_user_id The SIS id for the user's primary pseudonym.
  #
  # @example_response
  #   [ { 'id': 1, 'name': '<NAME>', 'sis_user_id': null },
  #     { 'id': 2, 'name': '<NAME>', 'sis_user_id': 'from-sis' } ]
  def students
    get_context
    if authorized_action(@context, @current_user, :read_roster)
      proxy = @context.students
      if user_json_is_admin?
        proxy = proxy.scoped(:include => :pseudonym)
      end
      render :json => proxy.map { |u| user_json(u) }
    end
  end

  def api_student_enrollments(context)
    enrollments = context.student_enrollments
    enrollments.map do |e|
      hash = e.user.as_json(:include_root => false, :only => STUDENT_API_FIELDS)
      hash.merge!(
        :secondary_identifier   => e.user.secondary_identifier,
        :computed_final_score   => e.computed_final_score,
        :computed_current_score => e.computed_current_score)
    end
  end<commit_msg>remove unused api controller action<commit_after>#
# Copyright (C) 2011 Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#

# @API Courses
#
# API for accessing course information.
class CoursesController < ApplicationController
  before_filter :require_user, :only => [:index]
  before_filter :require_user_for_context, :only => [:roster, :roster_user, :locks, :switch_role, :publish_to_sis]

  # @API
  # Returns the list of active courses for the current user.
  #
  # @argument enrollment_type [optional, "teacher"|"student"|"ta"|"observer"|"designer"]
  #   When set, only return courses where the user is enrolled as this type. For
  #   example, set to "teacher" to return only courses where the user is
  #   enrolled as a Teacher.
  #
  # @argument include[] ["needs_grading_count"] Optional information to include with each Course.
  #   When needs_grading_count is given, and the current user has grading
  #   rights, the total number of submissions needing grading for all
  #   assignments is returned.
  #
  # @argument include[] ["syllabus_body"] Optional information to include with each Course.
  #   When syllabus_body is given the user-generated html for the course 
  #   syllabus is returned.
  #
  # @response_field id The unique identifier for the course.
  # @response_field name The name of the course.
  # @response_field course_code The course code.
  # @response_field enrollments A list of enrollments linking the current user
  #   to the course.
  #
  # @response_field needs_grading_count Number of submissions needing grading
  #   for all the course assignments. Only returned if
  #   include[]=needs_grading_count
  #
  # @example_response
  #   [ { 'id': 1, 'name': 'first course', 'course_code': 'first', 'enrollments': [{'type': 'student'}] },
  #     { 'id': 2, 'name': 'second course', 'course_code': 'second', 'enrollments': [{'type': 'teacher'}] } ]
  def index
    respond_to do |format|
      format.html {
        @current_enrollments = @current_user.cached_current_enrollments(:include_enrollment_uuid => session[:enrollment_uuid]).sort_by{|e| [e.active? ? 1 : 0, e.long_name] }
        @past_enrollments = @current_user.enrollments.ended.scoped(:conditions=>"enrollments.workflow_state NOT IN ('invited', 'deleted')")
      }
      format.json {
        enrollments = @current_user.cached_current_enrollments
        if params[:enrollment_type]
          e_type = "#{params[:enrollment_type].capitalize}Enrollment"
          enrollments = enrollments.reject { |e| e.class.name != e_type }
        end

        include_grading = Array(params[:include]).include?('needs_grading_count')
        include_syllabus = Array(params[:include]).include?('syllabus_body')

        hash = []
        enrollments.group_by(&:course_id).each do |course_id, course_enrollments|
          course = course_enrollments.first.course
          hash << course.as_json(
            :include_root => false, :only => %w(id name course_code sis_source_id))
          hash.last['enrollments'] = course_enrollments.map { |e| { :type => e.readable_type.downcase } }
          if include_grading && course_enrollments.any? { |e| e.participating_admin? }
            hash.last['needs_grading_count'] = course.assignments.active.sum('needs_grading_count')
          end
          if include_syllabus
            hash.last['syllabus_body'] = course.syllabus_body
          end
        end
        render :json => hash.to_json
      }
    end
  end
  
  def create
    @account = Account.find(params[:account_id])
    if authorized_action(@account, @current_user, :manage_courses)

      if (sub_account_id = params[:course].delete(:account_id)) && sub_account_id.to_i != @account.id
        @sub_account = @account.find_child(sub_account_id) || raise(ActiveRecord::RecordNotFound)
      end

      if enrollment_term_id = params[:course].delete(:enrollment_term_id)
        params[:course][:enrollment_term] = (@account.root_account || @account).enrollment_terms.find(enrollment_term_id)
      end

      @course = (@sub_account || @account).courses.build(params[:course])
      respond_to do |format|
        if @course.save
          format.html
          format.json { render :json => @course.to_json }
        else
          flash[:error] = t('errors.create_failed', "Course creation failed")
          format.html { redirect_to :root_url }
          format.json { render :json => @course.errors.to_json, :status => :bad_request }
        end
      end
    end
  end
  
  def backup
    get_context
    if authorized_action(@context, @current_user, :update)
      backup_json = @context.backup_to_json
      send_file_headers!( :length=>backup_json.length, :filename=>"#{@context.name.underscore.gsub(/\s/, "_")}_#{Date.today.to_s}_backup.instructure", :disposition => 'attachment', :type => 'application/instructure')
      render :text => proc {|response, output|
        output.write backup_json
      }
    end
  end
  
  def restore
    get_context
    if authorized_action(@context, @current_user, :update)
      respond_to do |format|
        if params[:restore]
          @context.restore_from_json_backup(params[:restore])
          flash[:notice] = t('notices.backup_restored', "Backup Successfully Restored!")
          format.html { redirect_to named_context_url(@context, :context_url) }
        else
          format.html
        end
      end
    end
  end

  def unconclude
    get_context
    if authorized_action(@context, @current_user, :update)
      @context.unconclude
      flash[:notice] = t('notices.unconcluded', "Course un-concluded")
      redirect_to(named_context_url(@context, :context_url))
    end
  end

  include Api::V1::User

  # @API
  # Returns the list of sections for this course.
  #
  # @argument include[] ["students"] Associations to include with the group.
  #
  # @response_field id The unique identifier for the course section.
  # @response_field name The name of the section.
  #
  # @example_response
  #   ?include[]=students
  #
  # [
  #   {
  #     "id": 1,
  #     "name": "Section A",
  #     "students": [...]
  #   },
  #   {
  #     "id": 2,
  #     "name": "Section B",
  #     "students": [...]
  #   }
  # ]
  def sections
    get_context
    if authorized_action(@context, @current_user, :read_roster)
      includes = Array(params[:include])
      include_students = includes.include?('students')

      result = @context.course_sections.map do |section|
        res = section.as_json(:include_root => false,
                              :only => %w(id name))
        if include_students
          proxy = section.enrollments
          if user_json_is_admin?
            proxy = proxy.scoped(:include => { :user => :pseudonym })
          else
            proxy = proxy.scoped(:include => :user)
          end
          res['students'] = proxy.all(:conditions => "type = 'StudentEnrollment'").
            map { |e| user_json(e.user) }
        end
        res
      end

      render :json => result
    end
  end

  # @API
  # Returns the list of students enrolled in this course.
  #
  # @response_field id The unique identifier for the student.
  # @response_field name The full student name.
  # @response_field sis_user_id The SIS id for the user's primary pseudonym.
  #
  # @example_response
  #   [ { 'id': 1, 'name': '<NAME>', 'sis_user_id': null },
  #     { 'id': 2, 'name': '<NAME>', 'sis_user_id': 'from-sis' } ]
  def students
    get_context
    if authorized_action(@context, @current_user, :read_roster)
      proxy = @context.students
      if user_json_is_admin?
        proxy = proxy.scoped(:include => :pseudonym)
      end
      render :json => proxy.map { |u| user_json(u) }
    end
  end
{'fraction_non_alphanumeric': 0.1139188313600754, 'fraction_numerical': 0.0016492902161748247, 'mean_word_length': 3.0763505402160862, 'pattern_counts': {'":': 12, '<': 15, '<?xml version=': 0, '>': 64, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2475875', 'n_tokens_mistral': 5273, 'n_tokens_neox': 5165, 'n_words': 1362}