diff --git a/fuel/app/classes/controller/widgets.php b/fuel/app/classes/controller/widgets.php index 4a55d0048..cffbfb47f 100644 --- a/fuel/app/classes/controller/widgets.php +++ b/fuel/app/classes/controller/widgets.php @@ -343,6 +343,7 @@ protected function _play_widget($inst_id = false, $demo=false, $is_embedded=fals // create the play $play_id = \Materia\Api::session_play_create($inst_id, $context_id); + $play_state = \Materia\Session_Play::get_play_state($play_id) ?: ''; if ($play_id instanceof \Materia\Msg) { @@ -350,7 +351,7 @@ protected function _play_widget($inst_id = false, $demo=false, $is_embedded=fals throw new HttpServerErrorException; } - $this->display_widget($inst, $play_id, $is_embedded); + $this->display_widget($inst, $play_id, $is_embedded, $play_state); } /** @@ -456,7 +457,7 @@ protected function build_widget_login_messages($inst) return [$summary, $desc, $status['open']]; } - protected function display_widget(\Materia\Widget_Instance $inst, $play_id=false, $is_embedded=false) + protected function display_widget(\Materia\Widget_Instance $inst, $play_id=false, $is_embedded=false, $play_state=null) { Css::push_group(['core', 'widget_play']); Js::push_group(['angular', 'materia', 'student']); @@ -467,6 +468,7 @@ protected function display_widget(\Materia\Widget_Instance $inst, $play_id=false } Js::push_inline('var PLAY_ID = "'.$play_id.'";'); + Js::push_inline("var PLAY_STATE = '".$play_state."';"); $this->add_s3_config_to_response(); $this->theme->get_template() ->set('title', $inst->name.' '.$inst->widget->name) diff --git a/fuel/app/classes/materia/api/v1.php b/fuel/app/classes/materia/api/v1.php index 7b4d9de38..1850b920e 100644 --- a/fuel/app/classes/materia/api/v1.php +++ b/fuel/app/classes/materia/api/v1.php @@ -385,6 +385,7 @@ static public function play_activity_get($start = 0, $range = 6) // but we don't want to include that in the results $play = new Session_Play(); $plays = $play->get_plays_by_user_id(\Model_User::find_current_id(), $start, $range + 1); + trace($plays); $count = count($plays); if ($count > $range) $plays = array_slice($plays, 0, $range); return [ @@ -393,6 +394,20 @@ static public function play_activity_get($start = 0, $range = 6) ]; } + static public function play_state_save($play_id, $state) + { + $inst = self::_get_instance_for_play_id($play_id); + if ( ! $inst->playable_by_current_user()) return Msg::no_login(); + if ($inst->guest_access) return; + + $encoded_state = base64_encode(json_encode($state)); + + \DB::update('log_play') + ->value('last_state', $encoded_state) + ->where('id', $play_id) + ->execute(); + } + static public function play_logs_save($play_id, $logs, $preview_inst_id = null) { if ( ! $preview_inst_id) diff --git a/fuel/app/classes/materia/session/play.php b/fuel/app/classes/materia/session/play.php index ddf0a6325..9b156f26b 100644 --- a/fuel/app/classes/materia/session/play.php +++ b/fuel/app/classes/materia/session/play.php @@ -31,6 +31,7 @@ class Session_Play public $referrer_url; public $score; public $user_id; + public $last_state; /** * NEEDS DOCUMENTAION @@ -60,6 +61,7 @@ public function start($user_id=0, $inst_id=0, $context_id=false, $is_preview=fal 'ip_address' => \Input::ip(), 'referrer' => \Input::referrer(), ]; + $this->last_state = $this->unfinished_play_state() ?: ''; // @TODO: This is a hack - assuming 'lti_message_type' in POST or 'token' in GET implies an LTI. // Essentially true but fragile. @@ -104,6 +106,32 @@ protected static function set_user_is_playing() \Session::set('user_is_playing', true); } + public static function get_play_state($play_id) + { + $last_state = \DB::select('last_state') + ->from('log_play') + ->where('id', $play_id) + ->execute(); + if ( ! empty($last_state[0])) return base64_decode($last_state[0]['last_state']); + return false; + } + + //used to grab the most recent saved state from an unfinished play of this instance by this user + protected function unfinished_play_state() + { + $last_state = \DB::select('last_state') + ->from('log_play') + ->where('inst_id', $this->inst_id) + ->where('user_id', $this->user_id) + ->where('is_complete', '0') + ->where('last_state', '!=', '') + ->order_by('created_at', 'desc') + ->limit(1) + ->execute(); + if ( ! empty($last_state[0])) return $last_state[0]['last_state']; + return false; + } + protected static function start_preview($inst_id) { $previews = \Session::get('widgetPreviews', [0 => '']); @@ -154,7 +182,8 @@ protected function insert_play($hash) 'auth' => $this->auth, 'referrer_url' => $this->referrer_url, 'context_id' => $this->context_id, - 'semester' => $this->semester + 'semester' => $this->semester, + 'last_state' => $this->last_state ]) ->execute(); @@ -427,7 +456,8 @@ public function get_plays_by_user_id($user_id, $start, $range) 'p.is_complete', 'p.inst_id', ['w.name', 'widget_name'], - ['i.name', 'inst_name'] + ['i.name', 'inst_name'], + 'p.last_state' ) ->from( ['log_play', 'p']) ->join( ['widget_instance', 'i'], 'LEFT') diff --git a/fuel/app/migrations/040_add_play_state_to_log_play.php b/fuel/app/migrations/040_add_play_state_to_log_play.php new file mode 100644 index 000000000..a7bea16cc --- /dev/null +++ b/fuel/app/migrations/040_add_play_state_to_log_play.php @@ -0,0 +1,21 @@ + ['type' => 'longblob'], + ] + ); + } + + public function down() + { + \DBUtil::drop_fields('log_play', ['last_state']); + } +}