From 883f65555265f1bf435067c46db70148ea8cf6eb Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Sun, 3 Jun 2018 21:15:35 +0800 Subject: [PATCH] MDL-36754 output: Support token pluginfiles in group pic --- lib/tests/moodle_url_test.php | 82 +++++++++++++++++++++++++++++++++++ lib/upgrade.txt | 6 +++ lib/weblib.php | 53 +++++++++++++++++----- 3 files changed, 130 insertions(+), 11 deletions(-) diff --git a/lib/tests/moodle_url_test.php b/lib/tests/moodle_url_test.php index 10a878474be..c5a9be4d0d7 100644 --- a/lib/tests/moodle_url_test.php +++ b/lib/tests/moodle_url_test.php @@ -262,4 +262,86 @@ class core_moodle_url_testcase extends advanced_testcase { $url = new moodle_url('http://www.example.org/some/path/here.php'); $this->assertSame('', $url->get_port()); } + + /** + * Test the make_pluginfile_url function. + * + * @dataProvider make_pluginfile_url_provider + * @param bool $slashargs + * @param array $args Args to be provided to make_pluginfile_url + * @param string $expected The expected result + */ + public function test_make_pluginfile_url($slashargs, $args, $expected) { + global $CFG; + + $this->resetAfterTest(); + + $CFG->slasharguments = $slashargs; + $url = call_user_func_array('moodle_url::make_pluginfile_url', $args); + $this->assertRegexp($expected, $url->out(true)); + } + + /** + * Data provider for make_pluginfile_url tests. + * + * @return array[] + */ + public function make_pluginfile_url_provider() { + $baseurl = "https://www.example.com/moodle/pluginfile.php"; + $tokenbaseurl = "https://www.example.com/moodle/tokenpluginfile.php"; + return [ + 'Standard with slashargs' => [ + 'slashargs' => true, + 'args' => [ + 1, + 'mod_forum', + 'posts', + 422, + '/my/location/', + 'file.png', + ], + 'expected' => "@{$baseurl}/1/mod_forum/posts/422/my/location/file.png@", + ], + 'Standard without slashargs' => [ + 'slashargs' => false, + 'args' => [ + 1, + 'mod_forum', + 'posts', + 422, + '/my/location/', + 'file.png', + ], + 'expected' => "@{$baseurl}\?file=%2F1%2Fmod_forum%2Fposts%2F422%2Fmy%2Flocation%2Ffile.png@", + ], + 'Token included with slashargs' => [ + 'slashargs' => true, + 'args' => [ + 1, + 'mod_forum', + 'posts', + 422, + '/my/location/', + 'file.png', + false, + true, + ], + 'expected' => "@{$tokenbaseurl}/[^/]*/1/mod_forum/posts/422/my/location/file.png@", + ], + 'Token included without slashargs' => [ + 'slashargs' => false, + 'args' => [ + 1, + 'mod_forum', + 'posts', + 422, + '/my/location/', + 'file.png', + false, + true, + ], + 'expected' => "@{$tokenbaseurl}\?file=%2F1%2Fmod_forum%2Fposts%2F422%2Fmy%2Flocation%2Ffile.png&token=[a-z0-9]*@", + ], + ]; + } } diff --git a/lib/upgrade.txt b/lib/upgrade.txt index b5bc0f5055d..a8aebdfc56b 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -3,6 +3,12 @@ information provided here is intended especially for developers. === 3.6 === +* A new token-based version of pluginfile.php has been added which can be used for out-of-session file serving by + setting the `$includetoken` parameter to true on the `moodle_url::make_pluginfile_url()`, and + `moodle_url::make_file_url()` functions. +* The following picture functions have been updated to support use of the new token-based file serving: + - print_group_picture + - get_group_picture_url * Custom AJAX handlers for the form autocomplete fields can now optionally return string in their processResults() callback. If a string is returned, it is displayed instead of the list of suggested items. This can be used, for example, to inform the user that there are too many items matching the current search criteria. diff --git a/lib/weblib.php b/lib/weblib.php index b253d3d10df..6b6c00a4be8 100644 --- a/lib/weblib.php +++ b/lib/weblib.php @@ -773,17 +773,41 @@ class moodle_url { * @param string $pathname * @param string $filename * @param bool $forcedownload + * @param boolean $includetoken Whether to use a user token when displaying this group image. + * If the group picture is included in an e-mail or some other location where the audience is a specific + * user who will not be logged in when viewing, then we use a token to authenticate the user. * @return moodle_url */ public static function make_pluginfile_url($contextid, $component, $area, $itemid, $pathname, $filename, - $forcedownload = false) { - global $CFG; - $urlbase = "$CFG->wwwroot/pluginfile.php"; - if ($itemid === null) { - return self::make_file_url($urlbase, "/$contextid/$component/$area".$pathname.$filename, $forcedownload); + $forcedownload = false, $includetoken = false) { + global $CFG, $USER; + + $path = []; + + if ($includetoken) { + $urlbase = "$CFG->wwwroot/tokenpluginfile.php"; + $token = get_user_key('core_files', $USER->id); + if ($CFG->slasharguments) { + $path[] = $token; + } } else { - return self::make_file_url($urlbase, "/$contextid/$component/$area/$itemid".$pathname.$filename, $forcedownload); + $urlbase = "$CFG->wwwroot/pluginfile.php"; } + $path[] = $contextid; + $path[] = $component; + $path[] = $area; + + if ($itemid !== null) { + $path[] = $itemid; + } + + $path = "/" . implode('/', $path) . "{$pathname}{$filename}"; + + $url = self::make_file_url($urlbase, $path, $forcedownload, $includetoken); + if ($includetoken && empty($CFG->slasharguments)) { + $url->param('token', $token); + } + return $url; } /** @@ -2468,15 +2492,18 @@ function print_collapsible_region_end($return = false) { * @param boolean $large Default small picture, or large. * @param boolean $return If false print picture, otherwise return the output as string * @param boolean $link Enclose image in a link to view specified course? + * @param boolean $includetoken Whether to use a user token when displaying this group image. + * If the group picture is included in an e-mail or some other location where the audience is a specific + * user who will not be logged in when viewing, then we use a token to authenticate the user. * @return string|void Depending on the setting of $return */ -function print_group_picture($group, $courseid, $large=false, $return=false, $link=true) { +function print_group_picture($group, $courseid, $large = false, $return = false, $link = true, $includetoken = false) { global $CFG; if (is_array($group)) { $output = ''; foreach ($group as $g) { - $output .= print_group_picture($g, $courseid, $large, true, $link); + $output .= print_group_picture($g, $courseid, $large, true, $link, $includetoken); } if ($return) { return $output; @@ -2486,7 +2513,7 @@ function print_group_picture($group, $courseid, $large=false, $return=false, $li } } - $pictureurl = get_group_picture_url($group, $courseid, $large); + $pictureurl = get_group_picture_url($group, $courseid, $large, $includetoken); // If there is no picture, do nothing. if (!isset($pictureurl)) { @@ -2519,9 +2546,12 @@ function print_group_picture($group, $courseid, $large=false, $return=false, $li * @param stdClass $group A group object. * @param int $courseid The course ID for the group. * @param bool $large A large or small group picture? Default is small. + * @param boolean $includetoken Whether to use a user token when displaying this group image. + * If the group picture is included in an e-mail or some other location where the audience is a specific + * user who will not be logged in when viewing, then we use a token to authenticate the user. * @return moodle_url Returns the url for the group picture. */ -function get_group_picture_url($group, $courseid, $large = false) { +function get_group_picture_url($group, $courseid, $large = false, $includetoken = false) { global $CFG; $context = context_course::instance($courseid); @@ -2542,7 +2572,8 @@ function get_group_picture_url($group, $courseid, $large = false) { $file = 'f2'; } - $grouppictureurl = moodle_url::make_pluginfile_url($context->id, 'group', 'icon', $group->id, '/', $file); + $grouppictureurl = moodle_url::make_pluginfile_url( + $context->id, 'group', 'icon', $group->id, '/', $file, false, $includetoken); $grouppictureurl->param('rev', $group->picture); return $grouppictureurl; }