diff --git a/app/controllers/submissions_api_controller.rb b/app/controllers/submissions_api_controller.rb index a5d98562f32..33cd48dbb24 100644 --- a/app/controllers/submissions_api_controller.rb +++ b/app/controllers/submissions_api_controller.rb @@ -181,7 +181,7 @@ class SubmissionsApiController < ApplicationController end end - # @API Grade a submission + # @API Grade or comment on a submission # # Comment on and/or update the grading for a student's assignment submission. # If any submission or rubric_assessment arguments are provided, the user @@ -192,6 +192,13 @@ class SubmissionsApiController < ApplicationController # # @argument comment[group_comment] [Boolean] Whether or not this comment should be sent to the entire group (defaults to false). Ignored if this is not a group assignment or if no text_comment is provided. # + # @argument comment[media_comment_id] Add an audio/video comment to the submission. + # Media comments can be added via this API, however, note that there + # is not yet an API to generate or list existing media comments, so this + # functionality is currently of limited use. + # + # @argument comment[media_comment_type] ["audio"|"video"] The type of media comment being added. + # # @argument submission[posted_grade] Assign a score to the submission, # updating both the "score" and "grade" fields on the submission record. # This parameter can be passed in a few different formats: @@ -278,11 +285,6 @@ class SubmissionsApiController < ApplicationController if comment.is_a?(Hash) comment = { :comment => comment[:text_comment], :author => @current_user }.merge( - # Undocumented API feature: adding media comments given the kaltura - # media id. Eventually we'll expose a public API for media comments, - # but we need to implement a way to abstract it away from kaltura and - # make it generic. This will probably involve a proxy outside of - # rails. comment.slice(:media_comment_id, :media_comment_type, :group_comment) ).with_indifferent_access @assignment.update_submission(@submission.user, comment) diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 6e43305592a..8d231a7cab3 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -239,8 +239,7 @@ class SubmissionsController < ApplicationController # one or more previously uploaded files residing in the submitting user's # files section (or the group's files section, for group assignments). # - # There is not yet an API for listing a user's or group's files, or - # uploading files for submission. This API is coming soon. + # To upload a new file to submit, see the submissions {api:SubmissionsApiController#create_file Upload a file API}. # # Requires a submission_type of "online_upload". # diff --git a/app/models/media_object.rb b/app/models/media_object.rb index 373fc923db8..4ae3418944b 100644 --- a/app/models/media_object.rb +++ b/app/models/media_object.rb @@ -155,7 +155,27 @@ class MediaObject < ActiveRecord::Base build_media_objects(res, root_account_id) end end - + + def self.media_id_exists?(media_id) + client = Kaltura::ClientV3.new + client.startSession(Kaltura::SessionType::ADMIN) + info = client.mediaGet(media_id) + return !!info[:id] + end + + def self.ensure_media_object(media_id, create_opts = {}) + if !by_media_id(media_id).any? + self.send_later_enqueue_args(:create_if_id_exists, { :priority => Delayed::LOW_PRIORITY }, media_id, create_opts) + end + end + + # typically call this in a delayed job, since it has to contact kaltura + def self.create_if_id_exists(media_id, create_opts = {}) + if media_id_exists?(media_id) && !by_media_id(media_id).any? + create!(create_opts.merge(:media_id => media_id)) + end + end + def update_title_on_kaltura client = Kaltura::ClientV3.new client.startSession(Kaltura::SessionType::ADMIN) @@ -251,7 +271,6 @@ class MediaObject < ActiveRecord::Base def data self.read_attribute(:data) || self.write_attribute(:data, {}) end - def viewed! send_later(:updated_viewed_at_and_retrieve_details, Time.now) if !self.data[:last_viewed_at] || self.data[:last_viewed_at] > 1.hour.ago diff --git a/app/models/submission.rb b/app/models/submission.rb index 9f71f4458ed..3d0a602e27e 100644 --- a/app/models/submission.rb +++ b/app/models/submission.rb @@ -106,6 +106,7 @@ class Submission < ActiveRecord::Base after_save :update_final_score after_save :submit_to_turnitin_later after_save :update_admins_if_just_submitted + after_save :check_for_media_object after_save :update_quiz_submission def self.needs_grading_trigger_sql @@ -481,6 +482,15 @@ class Submission < ActiveRecord::Base end true end + + def check_for_media_object + if self.media_comment_id.present? && self.media_comment_id_changed? + MediaObject.ensure_media_object(self.media_comment_id, { + :user => self.user, + :context => self.user, + }) + end + end def submission_history res = [] diff --git a/app/models/submission_comment.rb b/app/models/submission_comment.rb index 4fd4168670b..3dcaa6e00a2 100644 --- a/app/models/submission_comment.rb +++ b/app/models/submission_comment.rb @@ -27,8 +27,6 @@ class SubmissionComment < ActiveRecord::Base has_many :associated_attachments, :class_name => 'Attachment', :as => :context has_many :submission_comment_participants, :dependent => :destroy has_many :messages, :as => :context, :dependent => :destroy - # too bad, this wont work. - # has_many :comments_in_group, :class_name => "SubmissionComment", :foreign_key => "group_comment_id", :primary_key => "group_comment_id", :dependent => :destroy, :conditions => lambda{|sc| "id !=#{sc.id}"} validates_length_of :comment, :maximum => maximum_text_length, :allow_nil => true, :allow_blank => true validates_length_of :comment, :minimum => 1, :allow_nil => true, :allow_blank => true @@ -37,6 +35,7 @@ class SubmissionComment < ActiveRecord::Base before_save :infer_details after_save :update_submission + after_save :check_for_media_object after_destroy :delete_other_comments_in_this_group after_create :update_participants after_create { |c| c.submission.create_or_update_conversations!(:create) if c.send_to_conversations? } @@ -62,6 +61,15 @@ class SubmissionComment < ActiveRecord::Base self.media_comment_id && self.media_comment_type end + def check_for_media_object + if self.media_comment? && self.media_comment_id_changed? + MediaObject.ensure_media_object(self.media_comment_id, { + :user => self.author, + :context => self.author, + }) + end + end + on_create_send_to_streams do if self.submission if self.author_id == self.submission.user_id @@ -209,8 +217,4 @@ class SubmissionComment < ActiveRecord::Base named_scope :for_context, lambda{|context| {:conditions => ['submission_comments.context_id = ? AND submission_comments.context_type = ?', context.id, context.class.to_s] } } - # protected :infer_details - # named_scope :for, lambda {|user| - # {:conditions => ['(submission_comments.recipient_id IS NULL OR submission_comments.recipient_id = ?)', (user ? user.id : 0)]} - # } end diff --git a/spec/models/media_object_spec.rb b/spec/models/media_object_spec.rb index 08385301c2e..17b9569a306 100644 --- a/spec/models/media_object_spec.rb +++ b/spec/models/media_object_spec.rb @@ -50,4 +50,31 @@ describe MediaObject do @a2.reload.file_state.should == 'available' end end + + describe ".ensure_media_object" do + it "should not create if the media object exists already" do + MediaObject.create!(:context => user, :media_id => "test") + expect { + MediaObject.ensure_media_object("test", {}) + }.to change(Delayed::Job, :count).by(0) + end + + it "should not create if the media id doesn't exist in kaltura" do + MediaObject.expects(:media_id_exists?).with("test").returns(false) + expect { + MediaObject.ensure_media_object("test", {}) + run_jobs + }.to change(MediaObject, :count).by(0) + end + + it "should create the media object" do + MediaObject.expects(:media_id_exists?).with("test").returns(true) + expect { + MediaObject.ensure_media_object("test", { :context => user }) + run_jobs + }.to change(MediaObject, :count).by(1) + obj = MediaObject.by_media_id("test").first + obj.context.should == @user + end + end end diff --git a/spec/models/submission_comment_spec.rb b/spec/models/submission_comment_spec.rb index edb31904dec..cea8a6fb5e9 100644 --- a/spec/models/submission_comment_spec.rb +++ b/spec/models/submission_comment_spec.rb @@ -158,6 +158,14 @@ This text has a http://www.google.com link in it... @item.data.submission_comments[0].formatted_body.should eql(@comment.formatted_body(250)) end + it "should ensure the media object exists" do + assignment_model + se = @course.enroll_student(user) + @submission = @assignment.submit_homework(se.user, :body => 'some message') + MediaObject.expects(:ensure_media_object).with("fake", { :context => se.user, :user => se.user }) + @comment = @submission.add_comment(:author => se.user, :media_comment_type => 'audio', :media_comment_id => 'fake') + end + context "conversations" do before do assignment_model diff --git a/spec/models/submission_spec.rb b/spec/models/submission_spec.rb index 98eb45b5443..7e6cac0ebfc 100644 --- a/spec/models/submission_spec.rb +++ b/spec/models/submission_spec.rb @@ -104,6 +104,13 @@ describe Submission do @submission.conversation_groups.should eql @submission.conversation_groups.uniq end + it "should ensure the media object exists" do + assignment_model + se = @course.enroll_student(user) + MediaObject.expects(:ensure_media_object).with("fake", { :context => se.user, :user => se.user }) + @submission = @assignment.submit_homework(se.user, :media_comment_id => "fake", :media_comment_type => "audio") + end + context "Discussion Topic" do it "should use correct date for its submitted_at value" do course_with_student_logged_in(:active_all => true)