If the following image displays correctly, set your ";
+ echo "Administration->Server->HTTP ";
+ echo "setting for slasharguments to file.php/1/pic.jpg: ";
+ echo "
\n";
+ echo "
Otherwise set it to file.php?file=/1/pic.jpg ";
+ echo "It should display correctly as ";
+ echo "
\n";
+ echo "
If neither equation image displays correctly, please seek ";
+ echo "further help at moodle.org at the ";
+ echo "";
+ echo "Mathematics Tools Forum
";
+}
+
?>
Algebra Filter Debugger
-
Please enter an algebraic expression without any surrounding @@ into
- the text box below. (Click here for help.)
-
-
-
-
+
Please enter an algebraic expression without any surrounding @@ into
+ the text box below. (Click here for help.)
+
First here is a brief overview on how the algebra filter works. It
- takes an algebra expression and first translates it into TeX. It first
- looks for the TeX translation in the Moodle database in the table cache_filters
- in the field rawtext. If not found, it passes the algebraic expression to the
- Perl script algebra2tex.pl, which also uses the Perl library AlgParser.pm.
- It then saves the TeX translation in the database for subsequent uses and
- passes the TeX to the mimetex executable to be converted to a gif image.
- Here are a few common things that can go wrong and some suggestions on how
- you might try to fix them.
+takes an algebra expression and first translates it into TeX. It first
+looks for the TeX translation in the Moodle database in the table cache_filters
+in the field rawtext. If not found, it passes the algebraic expression to the
+Perl script algebra2tex.pl, which also uses the Perl library AlgParser.pm.
+It then saves the TeX translation in the database for subsequent uses and
+passes the TeX to the mimetex executable to be converted to a gif image.
+Here are a few common things that can go wrong and some suggestions on how
+you might try to fix them.
-
Something had gone wrong on a previous occasion when the filter tried to
- translate this expression. Then the database entry for that expression contains
- a bad TeX translation in the rawtext field (usually blank). You can fix this
- by clicking on "Delete DB Entry"
-
The First Stage TeX Translation gives a "No text output available"
- message. If your server is running Windows, this may be due to the fact that
- you haven't installed Perl or didn't install it correctly. If your server is
- running some version of Unix (e.g. Linux), then this may be due to your Perl
- binary being installed in a nonstandard location. To fix this edit the first
- line of the algebra2tex.pl script. Another possible problem which may affect
- both Unix and Windows servers is that the web server doesn't have execute permission
- on the algebra2tex.pl script. In that case change permissions accordingly
-
The Second Stage TeX Translation produces malformed TeX. This indicates
- a bug in the algebra filter. Post the original algebraic expression and the
- bad TeX translation in the
- Mathematics Tools forum in the Using Moodle course on moodle.org.
-
The TeX to gif image conversion process does not work. If your server is
- running Unix, a likely cause is that the mimetex binary you are using is
- incompatible with your operating system. You can try compiling it from the
- C sources downloaded from
- http://www.forkosh.com/mimetex.zip. Lastly check the execute permissions
- on your mimetex binary, as outlined in item 2 above.
+
Something had gone wrong on a previous occasion when the filter tried to
+translate this expression. Then the database entry for that expression contains
+a bad TeX translation in the rawtext field (usually blank). You can fix this
+by clicking on "Delete DB Entry"
+
The First Stage TeX Translation gives a "No text output available"
+message. If your server is running Windows, this may be due to the fact that
+you haven't installed Perl or didn't install it correctly. If your server is
+running some version of Unix (e.g. Linux), then this may be due to your Perl
+binary being installed in a nonstandard location. To fix this edit the first
+line of the algebra2tex.pl script. Another possible problem which may affect
+both Unix and Windows servers is that the web server doesn't have execute permission
+on the algebra2tex.pl script. In that case change permissions accordingly
+
The Second Stage TeX Translation produces malformed TeX. This indicates
+a bug in the algebra filter. Post the original algebraic expression and the
+bad TeX translation in the
+Mathematics Tools forum in the Using Moodle course on moodle.org.
+
The TeX to gif image conversion process does not work. If your server is
+running Unix, a likely cause is that the mimetex binary you are using is
+incompatible with your operating system. You can try compiling it from the
+C sources downloaded from
+http://www.forkosh.com/mimetex.zip. Lastly check the execute permissions
+on your mimetex binary, as outlined in item 2 above.
diff --git a/filter/algebra/classes/text_filter.php b/filter/algebra/classes/text_filter.php
index 574d1285ced..63a6064db61 100644
--- a/filter/algebra/classes/text_filter.php
+++ b/filter/algebra/classes/text_filter.php
@@ -230,7 +230,12 @@ class text_filter extends \core_filters\text_filter {
$anchorcontents = '';
if ($imagefile) {
$anchorcontents .= "slasharguments) {
+ // Use this method if possible for better caching.
+ $anchorcontents .= "$CFG->wwwroot/filter/algebra/pix.php/$imagefile";
+ } else {
+ $anchorcontents .= "$CFG->wwwroot/filter/algebra/pix.php?file=$imagefile";
+ }
$anchorcontents .= "\" $style />";
$imagefound = file_exists("$CFG->dataroot/filter/algebra/$imagefile");
diff --git a/filter/tex/classes/text_filter.php b/filter/tex/classes/text_filter.php
index 35140b75872..ff58dc5dd7d 100644
--- a/filter/tex/classes/text_filter.php
+++ b/filter/tex/classes/text_filter.php
@@ -186,7 +186,12 @@ class text_filter extends \core_filters\text_filter {
// Build the output.
$anchorcontents = "slasharguments) {
+ // Use this method if possible for better client-side caching.
+ $anchorcontents .= "$CFG->wwwroot/filter/tex/pix.php/$imagefile";
+ } else {
+ $anchorcontents .= "$CFG->wwwroot/filter/tex/pix.php?file=$imagefile";
+ }
$anchorcontents .= "\" $style/>";
$imagefound = file_exists("$CFG->dataroot/filter/tex/$imagefile");
diff --git a/filter/tex/texdebug.php b/filter/tex/texdebug.php
index 62fe9a925dd..25481b3101e 100644
--- a/filter/tex/texdebug.php
+++ b/filter/tex/texdebug.php
@@ -89,6 +89,12 @@
tex2image($texexp);
}
+ // Action: Check Slasharguments
+ if ($action=='SlashArguments') {
+ slasharguments($texexp);
+ exit;
+ }
+
// Action: Show Tex command line output
if ($action=='ShowImageTex') {
TexOutput($texexp, true);
@@ -287,6 +293,23 @@
return $output;
}
+ function slasharguments($texexp) {
+ global $CFG;
+ $admin = $CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=http';
+ $image = tex2image($texexp,true);
+ echo "
If the following image displays correctly, set your ";
+ echo "Administration->Server->HTTP ";
+ echo "setting for slasharguments to file.php/1/pic.jpg: ";
+ echo "wwwroot/filter/tex/pix.php/$image\" align=\"absmiddle\">
\n";
+ echo "
Otherwise set it to file.php?file=/1/pic.jpg ";
+ echo "It should display correctly as ";
+ echo "wwwroot/filter/tex/pix.php?file=$image\" align=\"absmiddle\">
\n";
+ echo "
If neither equation image displays correctly, please seek ";
+ echo "further help at moodle.org at the ";
+ echo "";
+ echo "Mathematics Tools Forum
";
+ }
+
?>
@@ -312,6 +335,8 @@
+
+
diff --git a/lang/en/admin.php b/lang/en/admin.php
index 31eecddf3f0..2edff4d2ce9 100644
--- a/lang/en/admin.php
+++ b/lang/en/admin.php
@@ -382,6 +382,7 @@ $string['configsitedefaultlicensehelp'] = 'The default licence for publishing co
$string['configsitemailcharset'] = 'This setting specifies the default charset for all emails sent from the site.';
$string['configsitemaxcategorydepth'] = 'Maximum category depth';
$string['configsitemaxcategorydepthhelp'] = 'This specifies the maximum depth of child categories expanded when displaying categories or combo list. Deeper level categories will appear as links and user can expand them with AJAX request.';
+$string['configslasharguments'] = '\'Slash arguments\' (using PATH_INFO) is required for SCORM packages and multiple-file resources to display correctly. If your web server doesn\'t support \'slash arguments\' and you are unable to configure it, this setting can be disabled, though it will result in things not working. Note: The use of \'slash arguments\' will be required in future versions of Moodle.';
$string['configsmtpauthtype'] = 'This sets the authentication type to use on SMTP server.';
$string['configsmtpoauthservice'] = 'Select the OAuth 2 service that is configured to talk to the SMTP server. If the service doesn\'t exist yet, you will need to create it. Note that you need to set the SMTP Auth Type to XOAUTH2.';
$string['configsmtphosts'] = 'Give the full name of one or more local SMTP servers that Moodle should use to send mail (eg \'mail.a.com\' or \'mail.a.com;mail.b.com\'). To specify a non-default port (i.e other than port 25), you can use the [server]:[port] syntax (eg \'mail.a.com:587\'). For secure connections, port 465 is usually used with SSL, port 587 is usually used with TLS, specify security protocol below if required. If you leave this field blank, Moodle will use the PHP default method of sending mail.';
@@ -1310,6 +1311,8 @@ $string['sitepolicyguest_help'] = 'The URL of the site policy that all guests mu
$string['sitesectionhelp'] = 'Display a section at the top of the page where you can add custom content.';
$string['sixtyfourbitsrequired'] = 'It has been detected that your site is not using a 64-bit PHP version. You are required to upgrade your system (operating system, PHP...) before installing this Moodle version.';
$string['sixtyfourbitswarning'] = 'It has been detected that your site is not using a 64-bit PHP version. It is recommended that you upgrade your site to ensure future compatibility.';
+$string['slasharguments'] = 'Use slash arguments';
+$string['slashargumentswarning'] = 'It is recommended that the use of slash arguments is enabled. In future it will be required. For more details, see the documentation Using slash arguments.';
$string['smallscreensonly'] = 'Small screens only';
$string['smtp'] = 'SMTP';
$string['smtpauthtype'] = 'SMTP Auth Type';
@@ -1656,11 +1659,8 @@ $string['moodleservices'] = 'Moodle services';
$string['moodleservices_help'] = 'Make sure you get the best from your Moodle learning environment by using these Moodle services:';
// Deprecated since Moodle 4.5.
-$string['configslasharguments'] = '\'Slash arguments\' (using PATH_INFO) is required for SCORM packages and multiple-file resources to display correctly. If your web server doesn\'t support \'slash arguments\' and you are unable to configure it, this setting can be disabled, though it will result in things not working. Note: The use of \'slash arguments\' will be required in future versions of Moodle.';
$string['registration_help'] = 'By registering:
* You will receive security alerts
* You can activate mobile app push notifications from your site
* You are contributing to our Moodle statistics of the worldwide community';
-$string['slasharguments'] = 'Use slash arguments';
-$string['slashargumentswarning'] = 'It is recommended that the use of slash arguments is enabled. In future it will be required. For more details, see the documentation Using slash arguments.';
diff --git a/lang/en/deprecated.txt b/lang/en/deprecated.txt
index 194f064f1fd..5d8b2e53361 100644
--- a/lang/en/deprecated.txt
+++ b/lang/en/deprecated.txt
@@ -134,6 +134,3 @@ filterbothactive,core_grades
filterbyname,core_grades
filterfirstactive,core_grades
filterlastactive,core_grades
-configslasharguments,core_admin
-slasharguments,core_admin
-slashargumentswarning,core_admin
diff --git a/lib/amd/build/url.min.js b/lib/amd/build/url.min.js
index 2d2e913bf30..182a191f41c 100644
--- a/lib/amd/build/url.min.js
+++ b/lib/amd/build/url.min.js
@@ -6,6 +6,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 2.9
*/
-define("core/url",["jquery","core/config"],(function($,config){return{fileUrl:function(relativeScript,slashArg){var url=config.wwwroot+relativeScript;return"/"!=slashArg.charAt(0)&&(slashArg="/"+slashArg),url+=slashArg},relativeUrl:function(relativePath,params,includeSessKey){if(0===relativePath.indexOf("http:")||0===relativePath.indexOf("https:")||relativePath.indexOf("://")>=0)throw new Error("relativeUrl function does not accept absolute urls");"/"!=relativePath.charAt(0)&&(relativePath="/"+relativePath),"admin"!==config.admin&&(relativePath=relativePath.replace(/^\/admin\//,"/"+config.admin+"/")),params=params||{},includeSessKey&&(params.sesskey=config.sesskey);var queryString="";return Object.keys(params).length&&(queryString=$.map(params,(function(value,param){return param+"="+value})).join("&")),""!==queryString?config.wwwroot+relativePath+"?"+queryString:config.wwwroot+relativePath},imageUrl:function(imagename,component){return M.util.image_url(imagename,component)}}}));
+define("core/url",["jquery","core/config"],(function($,config){return{fileUrl:function(relativeScript,slashArg){var url=config.wwwroot+relativeScript;return"/"!=slashArg.charAt(0)&&(slashArg="/"+slashArg),config.slasharguments?url+=slashArg:url+="?file="+encodeURIComponent(slashArg),url},relativeUrl:function(relativePath,params,includeSessKey){if(0===relativePath.indexOf("http:")||0===relativePath.indexOf("https:")||relativePath.indexOf("://")>=0)throw new Error("relativeUrl function does not accept absolute urls");"/"!=relativePath.charAt(0)&&(relativePath="/"+relativePath),"admin"!==config.admin&&(relativePath=relativePath.replace(/^\/admin\//,"/"+config.admin+"/")),params=params||{},includeSessKey&&(params.sesskey=config.sesskey);var queryString="";return Object.keys(params).length&&(queryString=$.map(params,(function(value,param){return param+"="+value})).join("&")),""!==queryString?config.wwwroot+relativePath+"?"+queryString:config.wwwroot+relativePath},imageUrl:function(imagename,component){return M.util.image_url(imagename,component)}}}));
//# sourceMappingURL=url.min.js.map
\ No newline at end of file
diff --git a/lib/amd/build/url.min.js.map b/lib/amd/build/url.min.js.map
index 74951a8f560..e76a3879fba 100644
--- a/lib/amd/build/url.min.js.map
+++ b/lib/amd/build/url.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"url.min.js","sources":["../src/url.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * URL utility functions.\n *\n * @module core/url\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 2.9\n */\ndefine(['jquery', 'core/config'], function($, config) {\n\n\n return /** @alias module:core/url */ {\n // Public variables and functions.\n /**\n * Construct a file url\n *\n * @method fileUrl\n * @param {string} relativeScript\n * @param {string} slashArg\n * @return {string}\n */\n fileUrl: function(relativeScript, slashArg) {\n\n var url = config.wwwroot + relativeScript;\n\n // Force a /\n if (slashArg.charAt(0) != '/') {\n slashArg = '/' + slashArg;\n }\n url += slashArg;\n return url;\n },\n\n /**\n * Take a path relative to the moodle basedir and do some fixing (see class moodle_url in php).\n *\n * @method relativeUrl\n * @param {string} relativePath The path relative to the moodle basedir.\n * @param {object} params The query parameters for the URL.\n * @param {bool} includeSessKey Add the session key to the query params.\n * @return {string}\n */\n relativeUrl: function(relativePath, params, includeSessKey) {\n\n if (relativePath.indexOf('http:') === 0 || relativePath.indexOf('https:') === 0 || relativePath.indexOf('://') >= 0) {\n throw new Error('relativeUrl function does not accept absolute urls');\n }\n\n // Fix non-relative paths;\n if (relativePath.charAt(0) != '/') {\n relativePath = '/' + relativePath;\n }\n\n // Fix admin urls.\n if (config.admin !== 'admin') {\n relativePath = relativePath.replace(/^\\/admin\\//, '/' + config.admin + '/');\n }\n\n params = params || {};\n if (includeSessKey) {\n params.sesskey = config.sesskey;\n }\n\n var queryString = '';\n if (Object.keys(params).length) {\n queryString = $.map(params, function(value, param) {\n return param + '=' + value;\n }).join('&');\n }\n\n if (queryString !== '') {\n return config.wwwroot + relativePath + '?' + queryString;\n } else {\n return config.wwwroot + relativePath;\n }\n },\n\n /**\n * Wrapper for image_url function.\n *\n * @method imageUrl\n * @param {string} imagename The image name (e.g. t/edit).\n * @param {string} component The component (e.g. mod_feedback).\n * @return {string}\n */\n imageUrl: function(imagename, component) {\n return M.util.image_url(imagename, component);\n }\n };\n});\n"],"names":["define","$","config","fileUrl","relativeScript","slashArg","url","wwwroot","charAt","relativeUrl","relativePath","params","includeSessKey","indexOf","Error","admin","replace","sesskey","queryString","Object","keys","length","map","value","param","join","imageUrl","imagename","component","M","util","image_url"],"mappings":";;;;;;;;AAuBAA,kBAAO,CAAC,SAAU,gBAAgB,SAASC,EAAGC,cAGL,CAUjCC,QAAS,SAASC,eAAgBC,cAE1BC,IAAMJ,OAAOK,QAAUH,qBAGD,KAAtBC,SAASG,OAAO,KAChBH,SAAW,IAAMA,UAErBC,KAAOD,UAaXI,YAAa,SAASC,aAAcC,OAAQC,mBAEF,IAAlCF,aAAaG,QAAQ,UAAqD,IAAnCH,aAAaG,QAAQ,WAAmBH,aAAaG,QAAQ,QAAU,QACxG,IAAIC,MAAM,sDAIU,KAA1BJ,aAAaF,OAAO,KACpBE,aAAe,IAAMA,cAIJ,UAAjBR,OAAOa,QACPL,aAAeA,aAAaM,QAAQ,aAAc,IAAMd,OAAOa,MAAQ,MAG3EJ,OAASA,QAAU,GACfC,iBACAD,OAAOM,QAAUf,OAAOe,aAGxBC,YAAc,UACdC,OAAOC,KAAKT,QAAQU,SACpBH,YAAcjB,EAAEqB,IAAIX,QAAQ,SAASY,MAAOC,cACjCA,MAAQ,IAAMD,SACtBE,KAAK,MAGQ,KAAhBP,YACOhB,OAAOK,QAAUG,aAAe,IAAMQ,YAEtChB,OAAOK,QAAUG,cAYhCgB,SAAU,SAASC,UAAWC,kBACnBC,EAAEC,KAAKC,UAAUJ,UAAWC"}
\ No newline at end of file
+{"version":3,"file":"url.min.js","sources":["../src/url.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * URL utility functions.\n *\n * @module core/url\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 2.9\n */\ndefine(['jquery', 'core/config'], function($, config) {\n\n\n return /** @alias module:core/url */ {\n // Public variables and functions.\n /**\n * Construct a file url\n *\n * @method fileUrl\n * @param {string} relativeScript\n * @param {string} slashArg\n * @return {string}\n */\n fileUrl: function(relativeScript, slashArg) {\n\n var url = config.wwwroot + relativeScript;\n\n // Force a /\n if (slashArg.charAt(0) != '/') {\n slashArg = '/' + slashArg;\n }\n if (config.slasharguments) {\n url += slashArg;\n } else {\n url += '?file=' + encodeURIComponent(slashArg);\n }\n return url;\n },\n\n /**\n * Take a path relative to the moodle basedir and do some fixing (see class moodle_url in php).\n *\n * @method relativeUrl\n * @param {string} relativePath The path relative to the moodle basedir.\n * @param {object} params The query parameters for the URL.\n * @param {bool} includeSessKey Add the session key to the query params.\n * @return {string}\n */\n relativeUrl: function(relativePath, params, includeSessKey) {\n\n if (relativePath.indexOf('http:') === 0 || relativePath.indexOf('https:') === 0 || relativePath.indexOf('://') >= 0) {\n throw new Error('relativeUrl function does not accept absolute urls');\n }\n\n // Fix non-relative paths;\n if (relativePath.charAt(0) != '/') {\n relativePath = '/' + relativePath;\n }\n\n // Fix admin urls.\n if (config.admin !== 'admin') {\n relativePath = relativePath.replace(/^\\/admin\\//, '/' + config.admin + '/');\n }\n\n params = params || {};\n if (includeSessKey) {\n params.sesskey = config.sesskey;\n }\n\n var queryString = '';\n if (Object.keys(params).length) {\n queryString = $.map(params, function(value, param) {\n return param + '=' + value;\n }).join('&');\n }\n\n if (queryString !== '') {\n return config.wwwroot + relativePath + '?' + queryString;\n } else {\n return config.wwwroot + relativePath;\n }\n },\n\n /**\n * Wrapper for image_url function.\n *\n * @method imageUrl\n * @param {string} imagename The image name (e.g. t/edit).\n * @param {string} component The component (e.g. mod_feedback).\n * @return {string}\n */\n imageUrl: function(imagename, component) {\n return M.util.image_url(imagename, component);\n }\n };\n});\n"],"names":["define","$","config","fileUrl","relativeScript","slashArg","url","wwwroot","charAt","slasharguments","encodeURIComponent","relativeUrl","relativePath","params","includeSessKey","indexOf","Error","admin","replace","sesskey","queryString","Object","keys","length","map","value","param","join","imageUrl","imagename","component","M","util","image_url"],"mappings":";;;;;;;;AAuBAA,kBAAO,CAAC,SAAU,gBAAgB,SAASC,EAAGC,cAGL,CAUjCC,QAAS,SAASC,eAAgBC,cAE1BC,IAAMJ,OAAOK,QAAUH,qBAGD,KAAtBC,SAASG,OAAO,KAChBH,SAAW,IAAMA,UAEjBH,OAAOO,eACPH,KAAOD,SAEPC,KAAO,SAAWI,mBAAmBL,UAElCC,KAYXK,YAAa,SAASC,aAAcC,OAAQC,mBAEF,IAAlCF,aAAaG,QAAQ,UAAqD,IAAnCH,aAAaG,QAAQ,WAAmBH,aAAaG,QAAQ,QAAU,QACxG,IAAIC,MAAM,sDAIU,KAA1BJ,aAAaJ,OAAO,KACpBI,aAAe,IAAMA,cAIJ,UAAjBV,OAAOe,QACPL,aAAeA,aAAaM,QAAQ,aAAc,IAAMhB,OAAOe,MAAQ,MAG3EJ,OAASA,QAAU,GACfC,iBACAD,OAAOM,QAAUjB,OAAOiB,aAGxBC,YAAc,UACdC,OAAOC,KAAKT,QAAQU,SACpBH,YAAcnB,EAAEuB,IAAIX,QAAQ,SAASY,MAAOC,cACjCA,MAAQ,IAAMD,SACtBE,KAAK,MAGQ,KAAhBP,YACOlB,OAAOK,QAAUK,aAAe,IAAMQ,YAEtClB,OAAOK,QAAUK,cAYhCgB,SAAU,SAASC,UAAWC,kBACnBC,EAAEC,KAAKC,UAAUJ,UAAWC"}
\ No newline at end of file
diff --git a/lib/amd/src/url.js b/lib/amd/src/url.js
index a9f6e5886b6..47929eed9a5 100644
--- a/lib/amd/src/url.js
+++ b/lib/amd/src/url.js
@@ -42,7 +42,11 @@ define(['jquery', 'core/config'], function($, config) {
if (slashArg.charAt(0) != '/') {
slashArg = '/' + slashArg;
}
- url += slashArg;
+ if (config.slasharguments) {
+ url += slashArg;
+ } else {
+ url += '?file=' + encodeURIComponent(slashArg);
+ }
return url;
},
diff --git a/lib/classes/output/requirements/page_requirements_manager.php b/lib/classes/output/requirements/page_requirements_manager.php
index 4d0c1e7552b..e6b86afd28b 100644
--- a/lib/classes/output/requirements/page_requirements_manager.php
+++ b/lib/classes/output/requirements/page_requirements_manager.php
@@ -174,12 +174,15 @@ class page_requirements_manager {
public function __construct() {
global $CFG;
+ // You may need to set up URL rewrite rule because oversized URLs might not be allowed by web server.
+ $sep = empty($CFG->yuislasharguments) ? '?' : '/';
+
$this->yui3loader = new stdClass();
$this->YUI_config = new yui();
// Set up some loader options.
$this->yui3loader->local_base = $CFG->wwwroot . '/lib/yuilib/' . $CFG->yui3version . '/';
- $this->yui3loader->local_comboBase = $CFG->wwwroot . '/theme/yui_combo.php/';
+ $this->yui3loader->local_comboBase = $CFG->wwwroot . '/theme/yui_combo.php' . $sep;
$this->yui3loader->base = $this->yui3loader->local_base;
$this->yui3loader->comboBase = $this->yui3loader->local_comboBase;
@@ -208,7 +211,7 @@ class page_requirements_manager {
$this->YUI_config->add_group('yui2', [
// Loader configuration for our 2in3.
'base' => $CFG->wwwroot . '/lib/yuilib/2in3/' . $CFG->yui2version . '/build/',
- 'comboBase' => $CFG->wwwroot . '/theme/yui_combo.php/',
+ 'comboBase' => $CFG->wwwroot . '/theme/yui_combo.php' . $sep,
'combine' => $this->yui3loader->combine,
'ext' => false,
'root' => '2in3/' . $CFG->yui2version . '/build/',
@@ -222,9 +225,9 @@ class page_requirements_manager {
$configname = $this->YUI_config->set_config_source('lib/yui/config/moodle.js');
$this->YUI_config->add_group('moodle', [
'name' => 'moodle',
- 'base' => $CFG->wwwroot . '/theme/yui_combo.php/m/' . $jsrev . '/',
+ 'base' => $CFG->wwwroot . '/theme/yui_combo.php' . $sep . 'm/' . $jsrev . '/',
'combine' => $this->yui3loader->combine,
- 'comboBase' => $CFG->wwwroot . '/theme/yui_combo.php/',
+ 'comboBase' => $CFG->wwwroot . '/theme/yui_combo.php' . $sep,
'ext' => false,
'root' => 'm/' . $jsrev . '/', // Add the rev to the root path so that we can control caching.
'patterns' => [
@@ -239,7 +242,7 @@ class page_requirements_manager {
'name' => 'gallery',
'base' => $CFG->wwwroot . '/lib/yuilib/gallery/',
'combine' => $this->yui3loader->combine,
- 'comboBase' => $CFG->wwwroot . '/theme/yui_combo.php/',
+ 'comboBase' => $CFG->wwwroot . '/theme/yui_combo.php' . $sep,
'ext' => false,
'root' => 'gallery/' . $jsrev . '/',
'patterns' => [
@@ -318,6 +321,7 @@ class page_requirements_manager {
'sessiontimeout' => $CFG->sessiontimeout,
'sessiontimeoutwarning' => $CFG->sessiontimeoutwarning,
'themerev' => theme_get_revision(),
+ 'slasharguments' => (int)(!empty($CFG->slasharguments)),
'theme' => $page->theme->name,
'iconsystemmodule' => $iconsystem->get_amd_name(),
'jsrev' => $this->get_jsrev(),
@@ -602,9 +606,23 @@ class page_requirements_manager {
debugging("Invalid file '$file' specified in jQuery plugin '$plugin' in component '$component'");
continue;
}
- $url = new moodle_url("/theme/jquery.php");
- $url->set_slashargument("/$component/$file");
-
+ if (!empty($CFG->slasharguments)) {
+ $url = new moodle_url("/theme/jquery.php");
+ $url->set_slashargument("/$component/$file");
+ } else {
+ // This is not really good, we need slasharguments for relative links, this means no caching...
+ $path = realpath("$componentdir/jquery/$file");
+ if (strpos($path, $CFG->dirroot) === 0) {
+ $url = $CFG->wwwroot . preg_replace('/^' . preg_quote($CFG->dirroot, '/') . '/', '', $path);
+ // Replace all occurences of backslashes characters in url to forward slashes.
+ $url = str_replace('\\', '/', $url);
+ $url = new moodle_url($url);
+ } else {
+ // Bad luck, fix your server!
+ debugging("Moodle jQuery integration requires 'slasharguments' setting to be enabled.");
+ continue;
+ }
+ }
$this->jqueryplugins[$plugin]->urls[] = $url;
}
@@ -751,9 +769,13 @@ class page_requirements_manager {
}
if (substr($url, -3) === '.js') {
$jsrev = $this->get_jsrev();
- $returnurl = new moodle_url('/lib/javascript.php');
- $returnurl->set_slashargument('/' . $jsrev . $url);
- return $returnurl;
+ if (empty($CFG->slasharguments)) {
+ return new moodle_url('/lib/javascript.php', ['rev' => $jsrev, 'jsfile' => $url]);
+ } else {
+ $returnurl = new moodle_url('/lib/javascript.php');
+ $returnurl->set_slashargument('/' . $jsrev . $url);
+ return $returnurl;
+ }
} else {
return new moodle_url($url);
}
@@ -1447,8 +1469,11 @@ class page_requirements_manager {
$requirejsconfig = file_get_contents($CFG->dirroot . '/lib/requirejs/moodle-config.js');
- // No extension required.
- $jsextension = '';
+ // No extension required unless slash args is disabled.
+ $jsextension = '.js';
+ if (!empty($CFG->slasharguments)) {
+ $jsextension = '';
+ }
$minextension = '.min';
if (!$cachejs) {
diff --git a/lib/classes/output/theme_config.php b/lib/classes/output/theme_config.php
index 5f47351ef0e..ae937078c93 100644
--- a/lib/classes/output/theme_config.php
+++ b/lib/classes/output/theme_config.php
@@ -682,7 +682,15 @@ class theme_config {
}
$url = new moodle_url("/theme/styles.php");
- $url->set_slashargument("/{$this->name}/{$rev}/{$type}", 'noparam');
+ if (!empty($CFG->slasharguments)) {
+ $url->set_slashargument("/{$this->name}/{$rev}/{$type}", 'noparam', true);
+ } else {
+ $url->params([
+ 'theme' => $this->name,
+ 'rev' => $rev,
+ 'type' => $type,
+ ]);
+ }
} else {
$url = new moodle_url('/theme/styles_debug.php', [
'theme' => $this->name,
@@ -817,17 +825,30 @@ class theme_config {
$rev .= "_{$themesubrevision}";
}
- $slashargs = '';
- if (!$svg) {
- // We add a simple /_s to the start of the path.
- // The underscore is used to ensure that it isn't a valid theme name.
- $slashargs .= '/_s' . $slashargs;
+ if (!empty($CFG->slasharguments)) {
+ $slashargs = '';
+ if (!$svg) {
+ // We add a simple /_s to the start of the path.
+ // The underscore is used to ensure that it isn't a valid theme name.
+ $slashargs .= '/_s' . $slashargs;
+ }
+ $slashargs .= '/' . $this->name . '/' . $rev . '/' . $filename;
+ if ($separate) {
+ $slashargs .= '/chunk0';
+ }
+ $url->set_slashargument($slashargs, 'noparam', true);
+ } else {
+ $params = ['theme' => $this->name, 'rev' => $rev, 'type' => $filename];
+ if (!$svg) {
+ // We add an SVG param so that we know not to serve SVG images.
+ // We do this because all modern browsers support SVG and this param will one day be removed.
+ $params['svg'] = '0';
+ }
+ if ($separate) {
+ $params['chunk'] = '0';
+ }
+ $url->params($params);
}
- $slashargs .= '/' . $this->name . '/' . $rev . '/' . $filename;
- if ($separate) {
- $slashargs .= '/chunk0';
- }
- $url->set_slashargument($slashargs, 'noparam');
$urls[] = $url;
} else {
$baseurl = new moodle_url('/theme/styles_debug.php');
@@ -1436,9 +1457,9 @@ class theme_config {
return null;
}
- if ($rev > 0) {
+ if (!empty($CFG->slasharguments) && $rev > 0) {
$url = new moodle_url("/theme/javascript.php");
- $url->set_slashargument('/' . $this->name . '/' . $rev . '/' . $params['type'], 'noparam');
+ $url->set_slashargument('/' . $this->name . '/' . $rev . '/' . $params['type'], 'noparam', true);
return $url;
} else {
return new moodle_url('/theme/javascript.php', $params);
@@ -1676,14 +1697,14 @@ class theme_config {
$params['image'] = $imagename;
$url = new moodle_url("/theme/image.php");
- if ($rev > 0) {
+ if (!empty($CFG->slasharguments) && $rev > 0) {
$path = '/' . $params['theme'] . '/' . $params['component'] . '/' . $params['rev'] . '/' . $params['image'];
if (!$svg) {
// We add a simple /_s to the start of the path.
// The underscore is used to ensure that it isn't a valid theme name.
$path = '/_s' . $path;
}
- $url->set_slashargument($path, 'noparam');
+ $url->set_slashargument($path, 'noparam', true);
} else {
if (!$svg) {
// We add an SVG param so that we know not to serve SVG images.
@@ -1722,9 +1743,9 @@ class theme_config {
$params['font'] = $font;
$url = new moodle_url("/theme/font.php");
- if ($rev > 0) {
+ if (!empty($CFG->slasharguments) && $rev > 0) {
$path = '/' . $params['theme'] . '/' . $params['component'] . '/' . $params['rev'] . '/' . $params['font'];
- $url->set_slashargument($path, 'noparam');
+ $url->set_slashargument($path, 'noparam', true);
} else {
$url->params($params);
}
diff --git a/lib/classes/url.php b/lib/classes/url.php
index 39dbd627e27..d55ee3688db 100644
--- a/lib/classes/url.php
+++ b/lib/classes/url.php
@@ -580,21 +580,24 @@ class url {
*
* @param string $path usually file path
* @param string $parameter name of page parameter if slasharguments not supported
- * @param bool|null $supported This parameter has been deprecated since 4.5 and should not be used anymore.
- * @todo Final deprecation on Moodle 6.0. See MDL-82768.
+ * @param bool $supported usually null, then it depends on $CFG->slasharguments, use true or false for other servers
*/
- public function set_slashargument($path, $parameter = 'file', ?bool $supported = null) {
- if ($supported !== null) {
- debugging(
- 'Deprecated argument passed to ' . __FUNCTION__,
- DEBUG_DEVELOPER,
- );
+ public function set_slashargument($path, $parameter = 'file', $supported = null) {
+ global $CFG;
+ if (is_null($supported)) {
+ $supported = !empty($CFG->slasharguments);
+ }
+
+ if ($supported) {
+ $parts = explode('/', $path);
+ $parts = array_map('rawurlencode', $parts);
+ $path = implode('/', $parts);
+ $this->slashargument = $path;
+ unset($this->params[$parameter]);
+ } else {
+ $this->slashargument = '';
+ $this->params[$parameter] = $path;
}
- $parts = explode('/', $path);
- $parts = array_map('rawurlencode', $parts);
- $path = implode('/', $parts);
- $this->slashargument = $path;
- unset($this->params[$parameter]);
}
// Static factory methods.
@@ -697,7 +700,9 @@ class url {
$urlbase = "$CFG->wwwroot/tokenpluginfile.php";
$userid = $includetoken === true ? $USER->id : $includetoken;
$token = get_user_key('core_files', $userid);
- $path[] = $token;
+ if ($CFG->slasharguments) {
+ $path[] = $token;
+ }
} else {
$urlbase = "$CFG->wwwroot/pluginfile.php";
}
@@ -711,7 +716,10 @@ class url {
$path = "/" . implode('/', $path) . "{$pathname}{$filename}";
- $url = self::make_file_url($urlbase, $path, $forcedownload);
+ $url = self::make_file_url($urlbase, $path, $forcedownload, $includetoken);
+ if ($includetoken && empty($CFG->slasharguments)) {
+ $url->param('token', $token);
+ }
return $url;
}
@@ -823,20 +831,16 @@ class url {
*
* By default the path includes slash-arguments (for example,
* '/myfile.php/extra/arguments') so it is what you would expect from a
- * URL path.
+ * URL path. If you don't want this behaviour, you can opt to exclude the
+ * slash arguments. (Be careful: if the $CFG variable slasharguments is
+ * disabled, these URLs will have a different format and you may need to
+ * look at the 'file' parameter too.)
*
- * @param bool|null $includeslashargument This parameter has been deprecated since 4.5 and should not be used anymore.
- * Final deprecation on Moodle 6.0. See MDL-82768.
+ * @param bool $includeslashargument If true, includes slash arguments
* @return string Path of URL
*/
- public function get_path(?bool $includeslashargument = null) {
- if ($includeslashargument !== null) {
- debugging(
- 'The includeslashargument argument has been deprecated. Please remove it from your method calls.',
- DEBUG_DEVELOPER,
- );
- }
- return $this->path . $this->slashargument;
+ public function get_path($includeslashargument = true) {
+ return $this->path . ($includeslashargument ? $this->slashargument : '');
}
/**
diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php
index 9b101d05901..38fa2575155 100644
--- a/lib/db/upgrade.php
+++ b/lib/db/upgrade.php
@@ -1445,5 +1445,13 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2024092600.00);
}
+ if ($oldversion < 2024100100.01) {
+ // Set the slasharguments to 1 as default.
+ set_config('slasharguments', 1);
+
+ // Main savepoint reached.
+ upgrade_main_savepoint(true, 2024100100.01);
+ }
+
return true;
}
diff --git a/lib/deprecatedlib.php b/lib/deprecatedlib.php
index 1ee6fa379b1..b55e87cf00f 100644
--- a/lib/deprecatedlib.php
+++ b/lib/deprecatedlib.php
@@ -785,30 +785,3 @@ function plagiarism_get_file_results(): void {
function plagiarism_update_status(): void {
\core\deprecation::emit_deprecation_if_present(__FUNCTION__);
}
-
-/**
- * Method used to check the usage of slasharguments config and display a warning message.
- *
- * @param environment_results $result object to update, if relevant.
- * @return environment_results|null updated results or null if slasharguments is disabled.
- *
- * @deprecated Since Moodle 4.5
- * @todo Final deprecation on Moodle 6.0. See MDL-82768.
- */
-#[\core\attribute\deprecated(
- since: '4.5',
- mdl: 'MDL-62640',
- reason: 'Removed the option to disable slash arguments (slashargs)',
-)]
-function check_slasharguments(environment_results $result) {
- \core\deprecation::emit_deprecation_if_present(__FUNCTION__);
- global $CFG;
-
- if (!during_initial_install() && empty($CFG->slasharguments)) {
- $result->setInfo('slasharguments');
- $result->setStatus(false);
- return $result;
- }
-
- return null;
-}
diff --git a/lib/filelib.php b/lib/filelib.php
index 09bcb166a91..c6e3ccd9718 100644
--- a/lib/filelib.php
+++ b/lib/filelib.php
@@ -73,12 +73,20 @@ function file_encode_url($urlbase, $path, $forcedownload=false, $https=false) {
//TODO: deprecate this
- $parts = explode('/', $path);
- $parts = array_map('rawurlencode', $parts);
- $path = implode('/', $parts);
- $return = $urlbase . $path;
- if ($forcedownload) {
- $return .= '?forcedownload=1';
+ if ($CFG->slasharguments) {
+ $parts = explode('/', $path);
+ $parts = array_map('rawurlencode', $parts);
+ $path = implode('/', $parts);
+ $return = $urlbase.$path;
+ if ($forcedownload) {
+ $return .= '?forcedownload=1';
+ }
+ } else {
+ $path = rawurlencode($path);
+ $return = $urlbase.'?file='.$path;
+ if ($forcedownload) {
+ $return .= '&forcedownload=1';
+ }
}
if ($https) {
@@ -496,7 +504,13 @@ function file_rewrite_pluginfile_urls($text, $file, $contextid, $component, $fil
$finalfile = basename($file);
$tokenfile = "token{$finalfile}";
$file = substr($file, 0, strlen($file) - strlen($finalfile)) . $tokenfile;
- $baseurl = "{$CFG->wwwroot}/{$file}/{$token}";
+ $baseurl = "{$CFG->wwwroot}/{$file}";
+
+ if (!$CFG->slasharguments) {
+ $baseurl .= "?token={$token}&file=";
+ } else {
+ $baseurl .= "/{$token}";
+ }
}
$baseurl .= "/{$contextid}/{$component}/{$filearea}/";
diff --git a/lib/javascript-static.js b/lib/javascript-static.js
index 04c835ef6ab..c74d5a4a865 100644
--- a/lib/javascript-static.js
+++ b/lib/javascript-static.js
@@ -42,10 +42,17 @@ M.util.image_url = function(imagename, component) {
}
var url = M.cfg.wwwroot + '/theme/image.php';
- if (!M.cfg.svgicons) {
- url += '/_s';
+ if (M.cfg.themerev > 0 && M.cfg.slasharguments == 1) {
+ if (!M.cfg.svgicons) {
+ url += '/_s';
+ }
+ url += '/' + M.cfg.theme + '/' + component + '/' + M.cfg.themerev + '/' + imagename;
+ } else {
+ url += '?theme=' + M.cfg.theme + '&component=' + component + '&rev=' + M.cfg.themerev + '&image=' + imagename;
+ if (!M.cfg.svgicons) {
+ url += '&svg=0';
+ }
}
- url += '/' + M.cfg.theme + '/' + component + '/' + M.cfg.themerev + '/' + imagename;
return url;
};
diff --git a/lib/tests/filelib_test.php b/lib/tests/filelib_test.php
index 1b1d48d8e70..ff7fdf3256f 100644
--- a/lib/tests/filelib_test.php
+++ b/lib/tests/filelib_test.php
@@ -1317,7 +1317,9 @@ EOF;
* Test file_rewrite_pluginfile_urls with includetoken.
*/
public function test_file_rewrite_pluginfile_urls_includetoken(): void {
- global $USER;
+ global $USER, $CFG;
+
+ $CFG->slasharguments = true;
$this->resetAfterTest();
@@ -1360,6 +1362,43 @@ EOF;
$this->assertEquals($expectedtext, $finaltext);
}
+ /**
+ * Test file_rewrite_pluginfile_urls with includetoken with slasharguments disabled..
+ */
+ public function test_file_rewrite_pluginfile_urls_includetoken_no_slashargs(): void {
+ global $USER, $CFG;
+
+ $CFG->slasharguments = false;
+
+ $this->resetAfterTest();
+
+ $syscontext = \context_system::instance();
+ $originaltext = 'Fake test with an image ';
+ $options = ['includetoken' => true];
+
+ // Rewrite the content. This will generate a new token.
+ $finaltext = file_rewrite_pluginfile_urls(
+ $originaltext, 'pluginfile.php', $syscontext->id, 'user', 'private', 0, $options);
+
+ $token = get_user_key('core_files', $USER->id);
+ $expectedurl = new \moodle_url("/tokenpluginfile.php");
+ $expectedurl .= "?token={$token}&file=/{$syscontext->id}/user/private/0/image.png";
+ $expectedtext = "Fake test with an image ";
+ $this->assertEquals($expectedtext, $finaltext);
+
+ // Do it again - the second time will use an existing token.
+ $finaltext = file_rewrite_pluginfile_urls(
+ $originaltext, 'pluginfile.php', $syscontext->id, 'user', 'private', 0, $options);
+ $this->assertEquals($expectedtext, $finaltext);
+
+ // Now undo.
+ $options['reverse'] = true;
+ $finaltext = file_rewrite_pluginfile_urls($finaltext, 'pluginfile.php', $syscontext->id, 'user', 'private', 0, $options);
+
+ // Compare the final text is the same that the original.
+ $this->assertEquals($originaltext, $finaltext);
+ }
+
/**
* Helpter function to create draft files
*
@@ -2005,36 +2044,6 @@ EOF;
],
];
}
-
- /**
- * Tests the file_encode_url function to ensure it generates the correct URLs.
- *
- * @dataProvider file_encode_url_provider
- * @covers ::file_encode_url()
- *
- * @param string $urlbase The base URL to be used in the encoding.
- * @param string $path The path to be appended to the base URL.
- * @param bool $forcedownload Whether to force the file to download.
- * @param bool $https Whether to use HTTPS for the URL.
- * @param string $expected The expected URL after encoding.
- * @return void
- */
- public function test_file_encode_url(string $urlbase, string $path, bool $forcedownload, bool $https, string $expected): void {
- $actual = file_encode_url($urlbase, $path, $forcedownload, $https);
- $this->assertSame($expected, $actual);
- }
-
- /**
- * Provides data sets for test_file_encode_url.
- */
- public static function file_encode_url_provider(): array {
- return [
- ['http://local.test/', '1/1', false, false, 'http://local.test/1/1'],
- ['http://local.test/', '1/number two', true, false, 'http://local.test/1/number%20two?forcedownload=1'],
- ['http://local.test/', 'number@one/3', true, true, 'https://local.test/number%40one/3?forcedownload=1'],
- ];
- }
-
}
/**
diff --git a/lib/tests/outputcomponents_test.php b/lib/tests/outputcomponents_test.php
index 3965005881b..94d40347ae7 100644
--- a/lib/tests/outputcomponents_test.php
+++ b/lib/tests/outputcomponents_test.php
@@ -136,6 +136,7 @@ final class outputcomponents_test extends \advanced_testcase {
// Verify new install contains expected defaults.
$this->assertSame(theme_config::DEFAULT_THEME, $CFG->theme);
+ $this->assertEquals(1, $CFG->slasharguments);
$this->assertEquals(1, $CFG->themerev);
$this->assertEquals(0, $CFG->themedesignermode);
$this->assertSame('https://www.example.com/moodle', $CFG->wwwroot);
@@ -304,13 +305,14 @@ final class outputcomponents_test extends \advanced_testcase {
// Test non-slashargument images.
set_config('theme', 'classic');
$CFG->wwwroot = str_replace('https:', 'http:', $CFG->wwwroot);
+ $CFG->slasharguments = 0;
$page = new \moodle_page();
$page->set_url('/user/profile.php');
$page->set_context(\context_system::instance());
$renderer = $page->get_renderer('core');
$up3 = new user_picture($user3);
- $this->assertSame($CFG->wwwroot.'/theme/image.php/classic/core/1/u/f2', $up3->get_url($page, $renderer)->out(false));
+ $this->assertSame($CFG->wwwroot.'/theme/image.php?theme=classic&component=core&rev=1&image=u%2Ff2', $up3->get_url($page, $renderer)->out(false));
}
public function test_empty_menu(): void {
diff --git a/lib/tests/outputrequirementslib_test.php b/lib/tests/outputrequirementslib_test.php
index d4867bafb4e..32535a6a17f 100644
--- a/lib/tests/outputrequirementslib_test.php
+++ b/lib/tests/outputrequirementslib_test.php
@@ -61,13 +61,16 @@ final class outputrequirementslib_test extends \advanced_testcase {
/**
* Test for the jquery_plugin method.
*
- * Test to make sure that backslashes are not generated.
+ * Test to make sure that backslashes are not generated with either slasharguments set to on or off.
*/
public function test_jquery_plugin(): void {
- global $PAGE;
+ global $CFG, $PAGE;
$this->resetAfterTest();
+ // With slasharguments on.
+ $CFG->slasharguments = 1;
+
$page = new \moodle_page();
$requirements = $page->requires;
// Assert successful method call.
@@ -79,6 +82,20 @@ final class outputrequirementslib_test extends \advanced_testcase {
$requirecode = $requirements->get_top_of_body_code($renderer);
// Make sure that the generated code does not contain backslashes.
$this->assertFalse(strpos($requirecode, '\\'), "Output contains backslashes: " . $requirecode);
+
+ // With slasharguments off.
+ $CFG->slasharguments = 0;
+
+ $page = new \moodle_page();
+ $requirements = $page->requires;
+ // Assert successful method call.
+ $this->assertTrue($requirements->jquery_plugin('jquery'));
+ $this->assertTrue($requirements->jquery_plugin('ui'));
+
+ // Get the code containing the required jquery plugins.
+ $requirecode = $requirements->get_top_of_body_code($renderer);
+ // Make sure that the generated code does not contain backslashes.
+ $this->assertFalse(strpos($requirecode, '\\'), "Output contains backslashes: " . $requirecode);
}
/**
@@ -117,6 +134,7 @@ final class outputrequirementslib_test extends \advanced_testcase {
* Test the actual URL through which a JavaScript file is served.
*
* @param \moodle_url $moodleurl The moodle_url instance pointing to a web resource.
+ * @param int $cfgslashargs The value to force $CFG->slasharguments.
* @param string $expected The expected output URL.
* @throws ReflectionException if the class does not exist.
* @see \page_requirements_manager::js_fix_url()
@@ -124,12 +142,18 @@ final class outputrequirementslib_test extends \advanced_testcase {
* @covers \page_requirements_manager::js_fix_url
* @dataProvider js_fix_url_moodle_url_provider
*/
- public function test_js_fix_url_moodle_url(\moodle_url $moodleurl, string $expected): void {
+ public function test_js_fix_url_moodle_url(\moodle_url $moodleurl, int $cfgslashargs, string $expected): void {
+ global $CFG;
+ $defaultslashargs = $CFG->slasharguments;
+
+ $CFG->slasharguments = $cfgslashargs;
$rc = new \ReflectionClass(\page_requirements_manager::class);
$rcm = $rc->getMethod('js_fix_url');
$requires = new \page_requirements_manager();
$actualmoodleurl = $rcm->invokeArgs($requires, [$moodleurl]);
$this->assertEquals($expected, $actualmoodleurl->out(false));
+
+ $CFG->slasharguments = $defaultslashargs;
}
/**
@@ -145,30 +169,47 @@ final class outputrequirementslib_test extends \advanced_testcase {
$libdir = rtrim($CFG->libdir, '/');
$admin = "/{$CFG->admin}/"; // Deprecated, just for coverage purposes.
+ // Note: $CFG->slasharguments is enabled by default; it will be a forced setting one day (MDL-62640).
return [
'Environment XML file' => [
new \moodle_url('/admin/environment.xml'),
- $wwwroot . $admin . 'environment.xml',
+ 0,
+ $wwwroot . $admin . 'environment.xml'
],
'Google Maps CDN (HTTPS)' => [
new \moodle_url('https://maps.googleapis.com/maps/api/js', ['key' => 'googlemapkey3', 'sensor' => 'false']),
- 'https://maps.googleapis.com/maps/api/js?key=googlemapkey3&sensor=false',
+ 1,
+ 'https://maps.googleapis.com/maps/api/js?key=googlemapkey3&sensor=false'
],
'Google Maps CDN (HTTP)' => [
new \moodle_url('http://maps.googleapis.com/maps/api/js', ['key' => 'googlemapkey3', 'sensor' => 'false']),
- 'http://maps.googleapis.com/maps/api/js?key=googlemapkey3&sensor=false',
+ 0,
+ 'http://maps.googleapis.com/maps/api/js?key=googlemapkey3&sensor=false'
],
- 'H5P JS internal resource' => [
+ 'H5P JS internal resource (slasharguments on)' => [
new \moodle_url('/h5p/js/embed.js'),
- $wwwroot . '/lib/javascript.php/1/h5p/js/embed.js',
+ 1,
+ $wwwroot . '/lib/javascript.php/1/h5p/js/embed.js'
+ ],
+ 'H5P JS internal resource (slasharguments off)' => [
+ new \moodle_url('/h5p/js/embed.js'),
+ 0,
+ $wwwroot . '/lib/javascript.php?rev=1&jsfile=%2Fh5p%2Fjs%2Fembed.js'
],
'A custom Moodle CSS Handler' => [
new \moodle_url('/mod/data/css.php?d=1234567890'),
- $wwwroot . '/mod/data/css.php?d=1234567890',
+ 1,
+ $wwwroot . '/mod/data/css.php?d=1234567890'
],
- 'A custom Moodle JS Handler' => [
+ 'A custom Moodle JS Handler (slasharguments on)' => [
new \moodle_url('/mod/data/js.php?d=1234567890'),
- $wwwroot . '/mod/data/js.php?d=1234567890',
+ 1,
+ $wwwroot . '/mod/data/js.php?d=1234567890'
+ ],
+ 'A custom Moodle JS Handler (slasharguments off)' => [
+ new \moodle_url('/mod/data/js.php?d=1234567890'),
+ 0,
+ $wwwroot . '/mod/data/js.php?d=1234567890'
],
];
}
@@ -177,18 +218,25 @@ final class outputrequirementslib_test extends \advanced_testcase {
* Test the actual url through which a JavaScript file is served.
*
* @param string $url The URL pointing to a web resource.
+ * @param int $cfgslashargs The value to force $CFG->slasharguments.
* @param string $expected The expected output URL.
* @throws ReflectionException if the class does not exist.
* @see \page_requirements_manager::js_fix_url()
* @covers \page_requirements_manager::js_fix_url
* @dataProvider js_fix_url_plain_string_provider
*/
- public function test_js_fix_url_plain_string(string $url, string $expected): void {
+ public function test_js_fix_url_plain_string(string $url, int $cfgslashargs, string $expected): void {
+ global $CFG;
+ $defaultslashargs = $CFG->slasharguments;
+
+ $CFG->slasharguments = $cfgslashargs;
$rc = new \ReflectionClass(\page_requirements_manager::class);
$rcm = $rc->getMethod('js_fix_url');
$requires = new \page_requirements_manager();
$actualmoodleurl = $rcm->invokeArgs($requires, [$url]);
$this->assertEquals($expected, $actualmoodleurl->out(false));
+
+ $CFG->slasharguments = $defaultslashargs;
}
/**
@@ -202,34 +250,47 @@ final class outputrequirementslib_test extends \advanced_testcase {
$wwwroot = rtrim($CFG->wwwroot, '/');
$admin = "/{$CFG->admin}/"; // Deprecated, just for coverage purposes.
+ // Note: $CFG->slasharguments is enabled by default; it will be a forced setting one day (MDL-62640).
return [
'Environment XML file' => [
'/admin/environment.xml',
- $wwwroot . $admin . 'environment.xml',
+ 0,
+ $wwwroot . $admin . 'environment.xml'
],
'Data JS' => [
'/mod/data/data.js',
- $wwwroot . '/lib/javascript.php/1/mod/data/data.js',
+ 1,
+ $wwwroot . '/lib/javascript.php/1/mod/data/data.js'
],
'SCORM Request JS' => [
'/mod/scorm/request.js',
- $wwwroot . '/lib/javascript.php/1/mod/scorm/request.js',
+ 1,
+ $wwwroot . '/lib/javascript.php/1/mod/scorm/request.js'
],
'Wiki Editors Buttons JS' => [
'/mod/wiki/editors/wiki/buttons.js',
- $wwwroot . '/lib/javascript.php/1/mod/wiki/editors/wiki/buttons.js',
+ 1,
+ $wwwroot . '/lib/javascript.php/1/mod/wiki/editors/wiki/buttons.js'
],
'A non-JS internal resource' => [
'/theme/boost/pix/favicon.ico',
- $wwwroot . '/theme/boost/pix/favicon.ico',
+ 0,
+ $wwwroot . '/theme/boost/pix/favicon.ico'
],
'A custom Moodle CSS Handler' => [
'/mod/data/css.php?d=1234567890',
- $wwwroot . '/mod/data/css.php?d=1234567890',
+ 1,
+ $wwwroot . '/mod/data/css.php?d=1234567890'
],
- 'A custom Moodle JS Handler' => [
+ 'A custom Moodle JS Handler (slasharguments on)' => [
'/mod/data/js.php?d=1234567890',
- $wwwroot . '/mod/data/js.php?d=1234567890',
+ 1,
+ $wwwroot . '/mod/data/js.php?d=1234567890'
+ ],
+ 'A custom Moodle JS Handler (slasharguments off)' => [
+ '/mod/data/js.php?d=1234567890',
+ 0,
+ $wwwroot . '/mod/data/js.php?d=1234567890'
],
];
}
diff --git a/lib/tests/url_test.php b/lib/tests/url_test.php
index d96dc1dd946..5b4cd2a6e31 100644
--- a/lib/tests/url_test.php
+++ b/lib/tests/url_test.php
@@ -68,6 +68,7 @@ final class url_test extends \advanced_testcase {
$url = new url('http://www.example.org/pluginfile.php/slash/arguments');
$this->assertSame('/pluginfile.php/slash/arguments', $url->get_path());
+ $this->assertSame('/pluginfile.php', $url->get_path(false));
}
public function test_round_trip(): void {
@@ -303,12 +304,16 @@ final class url_test extends \advanced_testcase {
* 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(array $args, string $expected): void {
+ public function test_make_pluginfile_url($slashargs, $args, $expected): void {
+ global $CFG;
+
$this->resetAfterTest();
+ $CFG->slasharguments = $slashargs;
$url = call_user_func_array([url::class, 'make_pluginfile_url'], $args);
$this->assertMatchesRegularExpression($expected, $url->out(true));
}
@@ -323,6 +328,7 @@ final class url_test extends \advanced_testcase {
$tokenbaseurl = "https://www.example.com/moodle/tokenpluginfile.php";
return [
'Standard with slashargs' => [
+ 'slashargs' => true,
'args' => [
1,
'mod_forum',
@@ -333,7 +339,20 @@ final class url_test extends \advanced_testcase {
],
'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',
@@ -346,6 +365,21 @@ final class url_test extends \advanced_testcase {
],
'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/tests/weblib_test.php b/lib/tests/weblib_test.php
index 91d946a0cdd..1a5d4f84553 100644
--- a/lib/tests/weblib_test.php
+++ b/lib/tests/weblib_test.php
@@ -824,90 +824,125 @@ EXPECTED;
* Data provider for test_get_file_argument.
*/
public static function provider_get_file_argument() {
- return [
+ return array(
// Serving SCORM content w/o HTTP GET params.
- [
- [
+ array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/3854/mod_scorm/content/1/swf.html',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/3854/mod_scorm/content/1/swf.html',
- ],
- '/3854/mod_scorm/content/1/swf.html',
- ],
+ ), 0, '/3854/mod_scorm/content/1/swf.html'),
+ array(array(
+ 'SERVER_SOFTWARE' => 'Apache',
+ 'SERVER_PORT' => '80',
+ 'REQUEST_METHOD' => 'GET',
+ 'REQUEST_URI' => '/pluginfile.php/3854/mod_scorm/content/1/swf.html',
+ 'SCRIPT_NAME' => '/pluginfile.php',
+ 'PATH_INFO' => '/3854/mod_scorm/content/1/swf.html',
+ ), 1, '/3854/mod_scorm/content/1/swf.html'),
// Serving SCORM content w/ HTTP GET 'file' as first param.
- [
- [
+ array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/3854/mod_scorm/content/1/swf.html?file=video_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/3854/mod_scorm/content/1/swf.html',
- ],
- '/3854/mod_scorm/content/1/swf.html',
- ],
+ ), 0, '/3854/mod_scorm/content/1/swf.html'),
+ array(array(
+ 'SERVER_SOFTWARE' => 'Apache',
+ 'SERVER_PORT' => '80',
+ 'REQUEST_METHOD' => 'GET',
+ 'REQUEST_URI' => '/pluginfile.php/3854/mod_scorm/content/1/swf.html?file=video_.swf',
+ 'SCRIPT_NAME' => '/pluginfile.php',
+ 'PATH_INFO' => '/3854/mod_scorm/content/1/swf.html',
+ ), 1, '/3854/mod_scorm/content/1/swf.html'),
// Serving SCORM content w/ HTTP GET 'file' not as first param.
- [
- [
+ array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/3854/mod_scorm/content/1/swf.html?foo=bar&file=video_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/3854/mod_scorm/content/1/swf.html',
- ],
- '/3854/mod_scorm/content/1/swf.html',
- ],
+ ), 0, '/3854/mod_scorm/content/1/swf.html'),
+ array(array(
+ 'SERVER_SOFTWARE' => 'Apache',
+ 'SERVER_PORT' => '80',
+ 'REQUEST_METHOD' => 'GET',
+ 'REQUEST_URI' => '/pluginfile.php/3854/mod_scorm/content/1/swf.html?foo=bar&file=video_.swf',
+ 'SCRIPT_NAME' => '/pluginfile.php',
+ 'PATH_INFO' => '/3854/mod_scorm/content/1/swf.html',
+ ), 1, '/3854/mod_scorm/content/1/swf.html'),
// Serving content from a generic activity w/ HTTP GET 'file', still forcing slash arguments.
- [
- [
+ array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/3854/whatever/content/1/swf.html?file=video_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/3854/whatever/content/1/swf.html',
- ],
- '/3854/whatever/content/1/swf.html',
- ],
+ ), 0, '/3854/whatever/content/1/swf.html'),
+ array(array(
+ 'SERVER_SOFTWARE' => 'Apache',
+ 'SERVER_PORT' => '80',
+ 'REQUEST_METHOD' => 'GET',
+ 'REQUEST_URI' => '/pluginfile.php/3854/whatever/content/1/swf.html?file=video_.swf',
+ 'SCRIPT_NAME' => '/pluginfile.php',
+ 'PATH_INFO' => '/3854/whatever/content/1/swf.html',
+ ), 1, '/3854/whatever/content/1/swf.html'),
// Serving content from a generic activity w/ HTTP GET 'file', still forcing slash arguments (edge case).
- [
- [
+ array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/?file=video_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/',
- ],
- 'video_.swf',
- ],
+ ), 0, 'video_.swf'),
+ array(array(
+ 'SERVER_SOFTWARE' => 'Apache',
+ 'SERVER_PORT' => '80',
+ 'REQUEST_METHOD' => 'GET',
+ 'REQUEST_URI' => '/pluginfile.php/?file=video_.swf',
+ 'SCRIPT_NAME' => '/pluginfile.php',
+ 'PATH_INFO' => '/',
+ ), 1, 'video_.swf'),
// Serving content from a generic activity w/ HTTP GET 'file', w/o forcing slash arguments.
- [
- [
+ array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php?file=%2F3854%2Fwhatever%2Fcontent%2F1%2Fswf.html%3Ffile%3Dvideo_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
- ],
- '/3854/whatever/content/1/swf.html?file=video_.swf',
- ],
- ];
+ ), 0, '/3854/whatever/content/1/swf.html?file=video_.swf'),
+ array(array(
+ 'SERVER_SOFTWARE' => 'Apache',
+ 'SERVER_PORT' => '80',
+ 'REQUEST_METHOD' => 'GET',
+ 'REQUEST_URI' => '/pluginfile.php?file=%2F3854%2Fwhatever%2Fcontent%2F1%2Fswf.html%3Ffile%3Dvideo_.swf',
+ 'SCRIPT_NAME' => '/pluginfile.php',
+ ), 1, '/3854/whatever/content/1/swf.html?file=video_.swf'),
+ );
}
/**
* Tests for get_file_argument() function.
*
* @param array $server mockup for $_SERVER.
- * @param string $expected Expected value.
+ * @param string $cfgslasharguments slasharguments setting.
+ * @param string|false $expected Expected value.
* @dataProvider provider_get_file_argument
* @covers ::get_file_argument
*/
- public function test_get_file_argument(array $server, string $expected): void {
+ public function test_get_file_argument($server, $cfgslasharguments, $expected): void {
+ global $CFG;
+
+ // Overwrite the related settings.
+ $currentsetting = $CFG->slasharguments;
+ $CFG->slasharguments = $cfgslasharguments;
// Mock global $_SERVER.
$currentserver = isset($_SERVER) ? $_SERVER : null;
$_SERVER = $server;
@@ -930,6 +965,7 @@ EXPECTED;
$this->assertEquals($expected, get_file_argument());
// Restore the current settings and global values.
+ $CFG->slasharguments = $currentsetting;
if (is_null($currentserver)) {
unset($_SERVER);
} else {
diff --git a/lib/upgradelib.php b/lib/upgradelib.php
index 772f2ca47a5..a6728d06681 100644
--- a/lib/upgradelib.php
+++ b/lib/upgradelib.php
@@ -2278,6 +2278,24 @@ function check_database_storage_engine(environment_results $result) {
return null;
}
+/**
+ * Method used to check the usage of slasharguments config and display a warning message.
+ *
+ * @param environment_results $result object to update, if relevant.
+ * @return environment_results|null updated results or null if slasharguments is disabled.
+ */
+function check_slasharguments(environment_results $result){
+ global $CFG;
+
+ if (!during_initial_install() && empty($CFG->slasharguments)) {
+ $result->setInfo('slasharguments');
+ $result->setStatus(false);
+ return $result;
+ }
+
+ return null;
+}
+
/**
* This function verifies if the database has tables using innoDB Antelope row format.
*
diff --git a/mod/scorm/lang/en/deprecated.txt b/mod/scorm/lang/en/deprecated.txt
index 5dba63a9916..161293a8cc2 100644
--- a/mod/scorm/lang/en/deprecated.txt
+++ b/mod/scorm/lang/en/deprecated.txt
@@ -1,2 +1 @@
completionscorerequired_help,mod_scorm
-slashargs,mod_scorm
diff --git a/mod/scorm/lang/en/scorm.php b/mod/scorm/lang/en/scorm.php
index 089073ae23e..ba0096706f1 100644
--- a/mod/scorm/lang/en/scorm.php
+++ b/mod/scorm/lang/en/scorm.php
@@ -406,6 +406,7 @@ $string['sided'] = 'To the side';
$string['skipview'] = 'Student skip content structure page';
$string['skipview_help'] = 'This setting specifies whether the content structure page should ever be skipped (not displayed). If the package contains only one learning object, the content structure page can always be skipped.';
$string['skipviewdesc'] = 'This preference sets the default for when to skip content structure for a page';
+$string['slashargs'] = 'WARNING: slash arguments is disabled on this site and objects may not function as expected!';
$string['stagesize'] = 'Stage size';
$string['stagesize_help'] = 'These two settings specify the frame/window width and height for the learning objects.';
$string['started'] = 'Started on';
@@ -457,6 +458,3 @@ $string['youmustselectastatus'] = 'You must select a status to require';
// Deprecated since Moodle 4.3.
$string['completionscorerequired_help'] = 'Enabling this setting will require a user to have at least the minimum score entered to be marked complete in this SCORM activity, as well as any other Activity Completion requirements.';
-
-// Deprecated since Moodle 4.5.
-$string['slashargs'] = 'WARNING: slash arguments is disabled on this site and objects may not function as expected!';
diff --git a/mod/scorm/mod_form.php b/mod/scorm/mod_form.php
index a847e91059c..83336afb2df 100644
--- a/mod/scorm/mod_form.php
+++ b/mod/scorm/mod_form.php
@@ -29,6 +29,10 @@ class mod_scorm_mod_form extends moodleform_mod {
$mform = $this->_form;
+ if (!$CFG->slasharguments) {
+ $mform->addElement('static', '', '', $OUTPUT->notification(get_string('slashargs', 'scorm'), 'notifyproblem'));
+ }
+
$mform->addElement('header', 'general', get_string('general', 'form'));
// Name.
diff --git a/mod/wiki/locallib.php b/mod/wiki/locallib.php
index b5e5cdbd328..b06909e896e 100644
--- a/mod/wiki/locallib.php
+++ b/mod/wiki/locallib.php
@@ -736,6 +736,9 @@ function wiki_parser_real_path($url, $context, $component, $filearea, $swid) {
} else {
$file = 'pluginfile.php';
+ if (!$CFG->slasharguments) {
+ $file = $file . '?file=';
+ }
$baseurl = "$CFG->wwwroot/$file/{$context->id}/$component/$filearea/$swid/";
// it is a file in current file area
return $baseurl . $url;
diff --git a/mod/wiki/tests/lib_test.php b/mod/wiki/tests/lib_test.php
index adf0e2bc136..69a495297a7 100644
--- a/mod/wiki/tests/lib_test.php
+++ b/mod/wiki/tests/lib_test.php
@@ -922,26 +922,4 @@ class lib_test extends \advanced_testcase {
return \calendar_event::create($event);
}
-
- /**
- * Tests the wiki_parser_real_path function to ensure it correctly resolves URLs.
- *
- * @covers ::wiki_parser_real_path()
- */
- public function test_wiki_parser_real_path(): void {
- global $CFG;
- $this->resetAfterTest();
-
- // Create the activity.
- $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
- $wiki = $this->getDataGenerator()->create_module('wiki', ['course' => $course->id]);
- $context = \context_module::instance($wiki->cmid);
-
- $moodleurl = new \moodle_url('/mod/wiki/view.php', ['id' => 2]);
- $url = wiki_parser_real_path($moodleurl->out(), $context, 'mod_wiki', 'attachments', 3);
- $this->assertSame("{$CFG->wwwroot}/mod/wiki/view.php?id=2", $url);
-
- $url = wiki_parser_real_path('mod/wiki/view.php?id=2', $context, 'mod_wiki', 'attachments', 3);
- $this->assertSame("{$CFG->wwwroot}/pluginfile.php/{$context->id}/mod_wiki/attachments/3/mod/wiki/view.php?id=2", $url);
- }
}
diff --git a/version.php b/version.php
index 698ab87928a..55e6af1cfe0 100644
--- a/version.php
+++ b/version.php
@@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
-$version = 2024100100.00; // YYYYMMDD = weekly release date of this DEV branch.
+$version = 2024100100.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.
$release = '4.5rc1 (Build: 20241001)'; // Human-friendly version name