diff --git a/lang/en/repository.php b/lang/en/repository.php index 1a89457bfbb..53825f5c098 100644 --- a/lang/en/repository.php +++ b/lang/en/repository.php @@ -155,6 +155,7 @@ $string['linkexternal'] = 'Link external'; $string['listview'] = 'View as list'; $string['loading'] = 'Loading...'; $string['login'] = 'Login to your account'; +$string['logintoaccount'] = 'Login to your {$a} account'; $string['logout'] = 'Logout'; $string['lostsource'] = 'Error. Source is missing. {$a}'; $string['makefileinternal'] = 'Make a copy of the file'; diff --git a/lib/filelib.php b/lib/filelib.php index 28faa7eaae8..20112a00a5f 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -972,7 +972,9 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea if (!empty($repoid)) { $context = context::instance_by_id($contextid, MUST_EXIST); $repo = repository::get_repository_by_id($repoid, $context); - + if (!empty($options)) { + $repo->options = $options; + } $file_record['repositoryid'] = $repoid; // This hook gives the repo a place to do some house cleaning, and update the $reference before it's saved // to the file store. E.g. transfer ownership of the file to a system account etc. @@ -3886,9 +3888,10 @@ class curl_cache { * @param null|string $preview the preview mode, defaults to serving the original file * @param boolean $offline If offline is requested - don't serve a redirect to an external file, return a file suitable for viewing * offline (e.g. mobile app). + * @param bool $embed Whether this file will be served embed into an iframe. * @todo MDL-31088 file serving improments */ -function file_pluginfile($relativepath, $forcedownload, $preview = null, $offline = false) { +function file_pluginfile($relativepath, $forcedownload, $preview = null, $offline = false, $embed = false) { global $DB, $CFG, $USER; // relative path must start with '/' if (!$relativepath) { @@ -3912,7 +3915,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null, $offlin $fs = get_file_storage(); - $sendfileoptions = ['preview' => $preview, 'offline' => $offline]; + $sendfileoptions = ['preview' => $preview, 'offline' => $offline, 'embed' => $embed]; // ======================================================================================================================== if ($component === 'blog') { diff --git a/mod/resource/locallib.php b/mod/resource/locallib.php index 0dd1f1fe2a3..7629859ea4f 100644 --- a/mod/resource/locallib.php +++ b/mod/resource/locallib.php @@ -93,8 +93,11 @@ function resource_display_embed($resource, $cm, $course, $file) { $code = $mediamanager->embed_url($moodleurl, $title, 0, 0, $embedoptions); } else { + // We need a way to discover if we are loading remote docs inside an iframe. + $moodleurl->param('embed', 1); + // anything else - just try object tag enlarged as much as possible - $code = resourcelib_embed_general($fullurl, $title, $clicktoopen, $mimetype); + $code = resourcelib_embed_general($moodleurl, $title, $clicktoopen, $mimetype); } resource_print_header($resource, $cm, $course); @@ -525,7 +528,11 @@ function resource_set_mainfile($data) { $context = context_module::instance($cmid); if ($draftitemid) { - file_save_draft_area_files($draftitemid, $context->id, 'mod_resource', 'content', 0, array('subdirs'=>true)); + $options = array('subdirs' => true, 'embed' => false); + if ($data->display == RESOURCELIB_DISPLAY_EMBED) { + $options['embed'] = true; + } + file_save_draft_area_files($draftitemid, $context->id, 'mod_resource', 'content', 0, $options); } $files = $fs->get_area_files($context->id, 'mod_resource', 'content', 0, 'sortorder', false); if (count($files) == 1) { diff --git a/pluginfile.php b/pluginfile.php index 9148b624447..3d6d542496e 100644 --- a/pluginfile.php +++ b/pluginfile.php @@ -36,5 +36,5 @@ $preview = optional_param('preview', null, PARAM_ALPHANUM); // Offline means download the file from the repository and serve it, even if it was an external link. // The repository may have to export the file to an offline format. $offline = optional_param('offline', 0, PARAM_BOOL); - -file_pluginfile($relativepath, $forcedownload, $preview, $offline); +$embed = optional_param('embed', 0, PARAM_BOOL); +file_pluginfile($relativepath, $forcedownload, $preview, $offline, $embed); diff --git a/repository/googledocs/lib.php b/repository/googledocs/lib.php index 0c340e833e7..401c71d56f6 100644 --- a/repository/googledocs/lib.php +++ b/repository/googledocs/lib.php @@ -131,6 +131,33 @@ class repository_googledocs extends repository { } } + /** + * Print the login in a popup. + * + * @param array|null $attr Custom attributes to be applied to popup div. + */ + public function print_login_popup($attr = null) { + global $OUTPUT, $PAGE; + + $client = $this->get_user_oauth_client(false); + $url = new moodle_url($client->get_login_url()); + $state = $url->get_param('state') . '&reloadparent=true'; + $url->param('state', $state); + + $PAGE->set_pagelayout('embedded'); + echo $OUTPUT->header(); + + $repositoryname = get_string('pluginname', 'repository_googledocs'); + + $button = new single_button($url, get_string('logintoaccount', 'repository', $repositoryname), 'post', true); + $button->add_action(new popup_action('click', $url, 'Login')); + $button->class = 'mdl-align'; + $button = $OUTPUT->render($button); + echo html_writer::div($button, '', $attr); + + echo $OUTPUT->footer(); + } + /** * Build the breadcrumb from a path. * @@ -613,8 +640,15 @@ class repository_googledocs extends repository { $storedfile->get_filename(), $forcedownload); $url->param('sesskey', sesskey()); - $userauth = $this->get_user_oauth_client($url); + $param = ($options['embed'] == true) ? false : $url; + $userauth = $this->get_user_oauth_client($param); if (!$userauth->is_logged_in()) { + if ($options['embed'] == true) { + // Due to Same-origin policy, we cannot redirect to googledocs login page. + // If the requested file is embed and the user is not logged in, add option to log in using a popup. + $this->print_login_popup(['style' => 'margin-top: 250px']); + exit; + } redirect($userauth->get_login_url()); } if ($userauth === false) { diff --git a/repository/onedrive/lib.php b/repository/onedrive/lib.php index 4a341fa352e..796bdc0f877 100644 --- a/repository/onedrive/lib.php +++ b/repository/onedrive/lib.php @@ -127,6 +127,33 @@ class repository_onedrive extends repository { } } + /** + * Print the login in a popup. + * + * @param array|null $attr Custom attributes to be applied to popup div. + */ + public function print_login_popup($attr = null) { + global $OUTPUT, $PAGE; + + $client = $this->get_user_oauth_client(false); + $url = new moodle_url($client->get_login_url()); + $state = $url->get_param('state') . '&reloadparent=true'; + $url->param('state', $state); + + $PAGE->set_pagelayout('embedded'); + echo $OUTPUT->header(); + + $repositoryname = get_string('pluginname', 'repository_onedrive'); + + $button = new single_button($url, get_string('logintoaccount', 'repository', $repositoryname), 'post', true); + $button->add_action(new popup_action('click', $url, 'Login')); + $button->class = 'mdl-align'; + $button = $OUTPUT->render($button); + echo html_writer::div($button, '', $attr); + + echo $OUTPUT->footer(); + } + /** * Build the breadcrumb from a path. * @@ -564,8 +591,16 @@ class repository_onedrive extends repository { $storedfile->get_filename(), $forcedownload); $url->param('sesskey', sesskey()); - $userauth = $this->get_user_oauth_client($url); + $param = ($options['embed'] == true) ? false : $url; + $userauth = $this->get_user_oauth_client($param); + if (!$userauth->is_logged_in()) { + if ($options['embed'] == true) { + // Due to Same-origin policy, we cannot redirect to onedrive login page. + // If the requested file is embed and the user is not logged in, add option to log in using a popup. + $this->print_login_popup(['style' => 'margin-top: 250px']); + exit; + } redirect($userauth->get_login_url()); } if ($userauth === false) { @@ -703,8 +738,10 @@ class repository_onedrive extends repository { * @return boolean */ protected function set_file_sharing_anyone_with_link_can_read(\repository_onedrive\rest $client, $fileid) { + + $type = (isset($this->options['embed']) && $this->options['embed'] == true) ? 'embed' : 'view'; $updateread = [ - 'type' => 'view', + 'type' => $type, 'scope' => 'anonymous' ]; $params = ['fileid' => $fileid]; diff --git a/repository/repository_callback.php b/repository/repository_callback.php index 83fb5e38e57..19cb9fa7aa3 100644 --- a/repository/repository_callback.php +++ b/repository/repository_callback.php @@ -69,6 +69,23 @@ $repo->callback(); // manually. $strhttpsbug = json_encode(get_string('cannotaccessparentwin', 'repository')); $strrefreshnonjs = get_string('refreshnonjsfilepicker', 'repository'); +$reloadparent = optional_param('reloadparent', false, PARAM_BOOL); +// If this request is coming from a popup, close window and reload parent window. +if ($reloadparent == true) { + $js = << + + + + + +EOD; + die($js); +} + $js =<<