diff --git a/blocks/classes/external/fetch_addable_blocks.php b/blocks/classes/external/fetch_addable_blocks.php
index 843ab87e5f7..d649e5114b3 100644
--- a/blocks/classes/external/fetch_addable_blocks.php
+++ b/blocks/classes/external/fetch_addable_blocks.php
@@ -54,7 +54,8 @@ class fetch_addable_blocks extends external_api {
[
'pagecontextid' => new external_value(PARAM_INT, 'The context ID of the page.'),
'pagetype' => new external_value(PARAM_ALPHANUMEXT, 'The type of the page.'),
- 'pagelayout' => new external_value(PARAM_ALPHA, 'The layout of the page.')
+ 'pagelayout' => new external_value(PARAM_ALPHA, 'The layout of the page.'),
+ 'subpage' => new external_value(PARAM_TEXT, 'The subpage identifier', VALUE_DEFAULT, ''),
]
);
}
@@ -65,16 +66,18 @@ class fetch_addable_blocks extends external_api {
* @param int $pagecontextid The context ID of the page
* @param string $pagetype The type of the page
* @param string $pagelayout The layout of the page
+ * @param string $subpage The subpage identifier
* @return array The blocks list
*/
- public static function execute(int $pagecontextid, string $pagetype, string $pagelayout): array {
+ public static function execute(int $pagecontextid, string $pagetype, string $pagelayout, string $subpage = ''): array {
global $PAGE;
$params = self::validate_parameters(self::execute_parameters(),
[
'pagecontextid' => $pagecontextid,
'pagetype' => $pagetype,
- 'pagelayout' => $pagelayout
+ 'pagelayout' => $pagelayout,
+ 'subpage' => $subpage,
]
);
@@ -85,6 +88,8 @@ class fetch_addable_blocks extends external_api {
// We need to manually set the page layout and page type.
$PAGE->set_pagelayout($params['pagelayout']);
$PAGE->set_pagetype($params['pagetype']);
+ $PAGE->set_subpage($params['subpage']);
+
// Firstly, we need to load all currently existing page blocks to later determine which blocks are addable.
$PAGE->blocks->load_blocks(false);
$PAGE->blocks->create_all_block_instances();
diff --git a/blocks/upgrade.txt b/blocks/upgrade.txt
index 16c45fd3029..9b5dedcb15b 100644
--- a/blocks/upgrade.txt
+++ b/blocks/upgrade.txt
@@ -6,6 +6,8 @@ information provided here is intended especially for developers.
* Block block_quiz_results has been completely removed from core.
The Quiz results block is hidden by default since Moodle 2.9. It is recommended to use the Activity results block instead, which works with any type of activity (not just quizzes).
* External function core_block::get_dashboard_blocks has a new parameter to indicate if you want to receive the block on the my/courses page.
+* The `core_block_fetch_addable_blocks` external method accepts an optional `subpage` parameter, in order to correctly
+ calculate available blocks for pages that use this property (e.g. the user dashboard)
=== 3.8 ===
* Block block_community is no longer a part of core.
diff --git a/lib/amd/build/addblockmodal.min.js b/lib/amd/build/addblockmodal.min.js
index c7276e715fe..be04e5e4210 100644
--- a/lib/amd/build/addblockmodal.min.js
+++ b/lib/amd/build/addblockmodal.min.js
@@ -1,2 +1,2 @@
-define ("core/addblockmodal",["exports","core/modal_factory","core/templates","core/str","core/ajax"],function(a,b,c,d,e){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=f(b);c=f(c);e=f(e);function f(a){return a&&a.__esModule?a:{default:a}}function g(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function h(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var i=a.apply(b,c);function f(a){g(i,d,e,f,h,"next",a)}function h(a){g(i,d,e,f,h,"throw",a)}f(void 0)})}}var i={ADD_BLOCK:"[data-key=\"addblock\"]"},j=!1,k=function(a,b,c){document.addEventListener("click",function(d){var e=d.target.closest(i.ADD_BLOCK);if(e){d.preventDefault();var f=null,g=null!==c&&void 0!==c?c:e.dataset.url;l().then(function(c){f=c;var d=m(g,a,b);c.setBody(d);c.show();return d}).catch(function(){f.destroy()})}})},l=function(){return b.default.create({type:b.default.types.CANCEL,title:(0,d.get_string)("addblock")})},m=function(){var a=h(regeneratorRuntime.mark(function a(b,d,e){var f;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:a.next=2;return n(d,e);case 2:f=a.sent;return a.abrupt("return",c.default.render("core/add_block_body",{blocks:f,url:b}));case 4:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}(),n=function(){var a=h(regeneratorRuntime.mark(function a(b,c){var d;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:d={methodname:"core_block_fetch_addable_blocks",args:{pagecontextid:M.cfg.contextid,pagetype:b,pagelayout:c}};return a.abrupt("return",e.default.call([d])[0]);case 2:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}(),o=function(a,b){var c=2.\n\n/**\n * Show an add block modal instead of doing it on a separate page.\n *\n * @module core/addblockmodal\n * @copyright 2016 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalFactory from 'core/modal_factory';\nimport Templates from 'core/templates';\nimport {get_string as getString} from 'core/str';\nimport Ajax from 'core/ajax';\n\nconst SELECTORS = {\n ADD_BLOCK: '[data-key=\"addblock\"]'\n};\n\n// Ensure we only add our listeners once.\nlet listenerEventsRegistered = false;\n\n/**\n * Register related event listeners.\n *\n * @method registerListenerEvents\n * @param {String} pageType The type of the page\n * @param {String} pageLayout The layout of the page\n * @param {String|null} addBlockUrl The add block URL\n */\nconst registerListenerEvents = (pageType, pageLayout, addBlockUrl) => {\n document.addEventListener('click', e => {\n\n const addBlock = e.target.closest(SELECTORS.ADD_BLOCK);\n if (addBlock) {\n e.preventDefault();\n\n let addBlockModal = null;\n let addBlockModalUrl = addBlockUrl ?? addBlock.dataset.url;\n\n buildAddBlockModal()\n .then(modal => {\n addBlockModal = modal;\n const modalBody = renderBlocks(addBlockModalUrl, pageType, pageLayout);\n modal.setBody(modalBody);\n modal.show();\n\n return modalBody;\n })\n .catch(() => {\n addBlockModal.destroy();\n });\n }\n });\n};\n\n/**\n * Method that creates the 'add block' modal.\n *\n * @method buildAddBlockModal\n * @returns {Promise} The modal promise (modal's body will be rendered later).\n */\nconst buildAddBlockModal = () => {\n return ModalFactory.create({\n type: ModalFactory.types.CANCEL,\n title: getString('addblock')\n });\n};\n\n/**\n * Method that renders the list of available blocks.\n *\n * @method renderBlocks\n * @param {String} addBlockUrl The add block URL\n * @param {String} pageType The type of the page\n * @param {String} pageLayout The layout of the page\n * @return {Promise}\n */\nconst renderBlocks = async(addBlockUrl, pageType, pageLayout) => {\n // Fetch all addable blocks in the given page.\n const blocks = await getAddableBlocks(pageType, pageLayout);\n\n return Templates.render('core/add_block_body', {\n blocks: blocks,\n url: addBlockUrl\n });\n};\n\n/**\n * Method that fetches all addable blocks in a given page.\n *\n * @method getAddableBlocks\n * @param {String} pageType The type of the page\n * @param {String} pageLayout The layout of the page\n * @return {Promise}\n */\nconst getAddableBlocks = async(pageType, pageLayout) => {\n const request = {\n methodname: 'core_block_fetch_addable_blocks',\n args: {\n pagecontextid: M.cfg.contextid,\n pagetype: pageType,\n pagelayout: pageLayout\n },\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Set up the actions.\n *\n * @method init\n * @param {String} pageType The type of the page\n * @param {String} pageLayout The layout of the page\n * @param {String|null} addBlockUrl The add block URL\n */\nexport const init = (pageType, pageLayout, addBlockUrl = null) => {\n if (!listenerEventsRegistered) {\n registerListenerEvents(pageType, pageLayout, addBlockUrl);\n listenerEventsRegistered = true;\n }\n};\n"],"file":"addblockmodal.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../src/addblockmodal.js"],"names":["SELECTORS","ADD_BLOCK","listenerEventsRegistered","registerListenerEvents","pageType","pageLayout","addBlockUrl","subPage","document","addEventListener","e","addBlock","target","closest","preventDefault","addBlockModal","addBlockModalUrl","dataset","url","buildAddBlockModal","then","modal","modalBody","renderBlocks","setBody","show","catch","destroy","ModalFactory","create","type","types","CANCEL","title","getAddableBlocks","blocks","Templates","render","request","methodname","args","pagecontextid","M","cfg","contextid","pagetype","pagelayout","subpage","Ajax","call","init"],"mappings":"sMAuBA,OACA,OAEA,O,qXAEMA,CAAAA,CAAS,CAAG,CACdC,SAAS,CAAE,yBADG,C,CAKdC,CAAwB,G,CAWtBC,CAAsB,CAAG,SAACC,CAAD,CAAWC,CAAX,CAAuBC,CAAvB,CAAoCC,CAApC,CAAgD,CAC3EC,QAAQ,CAACC,gBAAT,CAA0B,OAA1B,CAAmC,SAAAC,CAAC,CAAI,CAEpC,GAAMC,CAAAA,CAAQ,CAAGD,CAAC,CAACE,MAAF,CAASC,OAAT,CAAiBb,CAAS,CAACC,SAA3B,CAAjB,CACA,GAAIU,CAAJ,CAAc,CACVD,CAAC,CAACI,cAAF,GADU,GAGNC,CAAAA,CAAa,CAAG,IAHV,CAINC,CAAgB,QAAGV,CAAH,WAAGA,CAAH,CAAGA,CAAH,CAAkBK,CAAQ,CAACM,OAAT,CAAiBC,GAJ7C,CAMVC,CAAkB,GACbC,IADL,CACU,SAAAC,CAAK,CAAI,CACXN,CAAa,CAAGM,CAAhB,CACA,GAAMC,CAAAA,CAAS,CAAGC,CAAY,CAACP,CAAD,CAAmBZ,CAAnB,CAA6BC,CAA7B,CAAyCE,CAAzC,CAA9B,CACAc,CAAK,CAACG,OAAN,CAAcF,CAAd,EACAD,CAAK,CAACI,IAAN,GAEA,MAAOH,CAAAA,CACV,CARL,EASKI,KATL,CASW,UAAM,CACTX,CAAa,CAACY,OAAd,EACH,CAXL,CAYH,CACJ,CAtBD,CAuBH,C,CAQKR,CAAkB,CAAG,UAAM,CAC7B,MAAOS,WAAaC,MAAb,CAAoB,CACvBC,IAAI,CAAEF,UAAaG,KAAb,CAAmBC,MADF,CAEvBC,KAAK,CAAE,iBAAU,UAAV,CAFgB,CAApB,CAIV,C,CAYKV,CAAY,4CAAG,WAAMjB,CAAN,CAAmBF,CAAnB,CAA6BC,CAA7B,CAAyCE,CAAzC,wGAEI2B,CAAAA,CAAgB,CAAC9B,CAAD,CAAWC,CAAX,CAAuBE,CAAvB,CAFpB,QAEX4B,CAFW,iCAIVC,UAAUC,MAAV,CAAiB,qBAAjB,CAAwC,CAC3CF,MAAM,CAAEA,CADmC,CAE3CjB,GAAG,CAAEZ,CAFsC,CAAxC,CAJU,0CAAH,uD,CAmBZ4B,CAAgB,4CAAG,WAAM9B,CAAN,CAAgBC,CAAhB,CAA4BE,CAA5B,yFACf+B,CADe,CACL,CACZC,UAAU,CAAE,iCADA,CAEZC,IAAI,CAAE,CACFC,aAAa,CAAEC,CAAC,CAACC,GAAF,CAAMC,SADnB,CAEFC,QAAQ,CAAEzC,CAFR,CAGF0C,UAAU,CAAEzC,CAHV,CAIF0C,OAAO,CAAExC,CAJP,CAFM,CADK,0BAWdyC,UAAKC,IAAL,CAAU,CAACX,CAAD,CAAV,EAAqB,CAArB,CAXc,0CAAH,uD,CAuBTY,CAAI,CAAG,SAAC9C,CAAD,CAAWC,CAAX,CAA4D,IAArCC,CAAAA,CAAqC,wDAAvB,IAAuB,CAAjBC,CAAiB,wDAAP,EAAO,CAC5E,GAAI,CAACL,CAAL,CAA+B,CAC3BC,CAAsB,CAACC,CAAD,CAAWC,CAAX,CAAuBC,CAAvB,CAAoCC,CAApC,CAAtB,CACAL,CAAwB,GAC3B,CACJ,C","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 * Show an add block modal instead of doing it on a separate page.\n *\n * @module core/addblockmodal\n * @copyright 2016 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalFactory from 'core/modal_factory';\nimport Templates from 'core/templates';\nimport {get_string as getString} from 'core/str';\nimport Ajax from 'core/ajax';\n\nconst SELECTORS = {\n ADD_BLOCK: '[data-key=\"addblock\"]'\n};\n\n// Ensure we only add our listeners once.\nlet listenerEventsRegistered = false;\n\n/**\n * Register related event listeners.\n *\n * @method registerListenerEvents\n * @param {String} pageType The type of the page\n * @param {String} pageLayout The layout of the page\n * @param {String|null} addBlockUrl The add block URL\n * @param {String} subPage The subpage identifier\n */\nconst registerListenerEvents = (pageType, pageLayout, addBlockUrl, subPage) => {\n document.addEventListener('click', e => {\n\n const addBlock = e.target.closest(SELECTORS.ADD_BLOCK);\n if (addBlock) {\n e.preventDefault();\n\n let addBlockModal = null;\n let addBlockModalUrl = addBlockUrl ?? addBlock.dataset.url;\n\n buildAddBlockModal()\n .then(modal => {\n addBlockModal = modal;\n const modalBody = renderBlocks(addBlockModalUrl, pageType, pageLayout, subPage);\n modal.setBody(modalBody);\n modal.show();\n\n return modalBody;\n })\n .catch(() => {\n addBlockModal.destroy();\n });\n }\n });\n};\n\n/**\n * Method that creates the 'add block' modal.\n *\n * @method buildAddBlockModal\n * @returns {Promise} The modal promise (modal's body will be rendered later).\n */\nconst buildAddBlockModal = () => {\n return ModalFactory.create({\n type: ModalFactory.types.CANCEL,\n title: getString('addblock')\n });\n};\n\n/**\n * Method that renders the list of available blocks.\n *\n * @method renderBlocks\n * @param {String} addBlockUrl The add block URL\n * @param {String} pageType The type of the page\n * @param {String} pageLayout The layout of the page\n * @param {String} subPage The subpage identifier\n * @return {Promise}\n */\nconst renderBlocks = async(addBlockUrl, pageType, pageLayout, subPage) => {\n // Fetch all addable blocks in the given page.\n const blocks = await getAddableBlocks(pageType, pageLayout, subPage);\n\n return Templates.render('core/add_block_body', {\n blocks: blocks,\n url: addBlockUrl\n });\n};\n\n/**\n * Method that fetches all addable blocks in a given page.\n *\n * @method getAddableBlocks\n * @param {String} pageType The type of the page\n * @param {String} pageLayout The layout of the page\n * @param {String} subPage The subpage identifier\n * @return {Promise}\n */\nconst getAddableBlocks = async(pageType, pageLayout, subPage) => {\n const request = {\n methodname: 'core_block_fetch_addable_blocks',\n args: {\n pagecontextid: M.cfg.contextid,\n pagetype: pageType,\n pagelayout: pageLayout,\n subpage: subPage,\n },\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Set up the actions.\n *\n * @method init\n * @param {String} pageType The type of the page\n * @param {String} pageLayout The layout of the page\n * @param {String|null} addBlockUrl The add block URL\n * @param {String} subPage The subpage identifier\n */\nexport const init = (pageType, pageLayout, addBlockUrl = null, subPage = '') => {\n if (!listenerEventsRegistered) {\n registerListenerEvents(pageType, pageLayout, addBlockUrl, subPage);\n listenerEventsRegistered = true;\n }\n};\n"],"file":"addblockmodal.min.js"}
\ No newline at end of file
diff --git a/lib/amd/src/addblockmodal.js b/lib/amd/src/addblockmodal.js
index f660948c61b..42ebaf30ffe 100644
--- a/lib/amd/src/addblockmodal.js
+++ b/lib/amd/src/addblockmodal.js
@@ -40,8 +40,9 @@ let listenerEventsRegistered = false;
* @param {String} pageType The type of the page
* @param {String} pageLayout The layout of the page
* @param {String|null} addBlockUrl The add block URL
+ * @param {String} subPage The subpage identifier
*/
-const registerListenerEvents = (pageType, pageLayout, addBlockUrl) => {
+const registerListenerEvents = (pageType, pageLayout, addBlockUrl, subPage) => {
document.addEventListener('click', e => {
const addBlock = e.target.closest(SELECTORS.ADD_BLOCK);
@@ -54,7 +55,7 @@ const registerListenerEvents = (pageType, pageLayout, addBlockUrl) => {
buildAddBlockModal()
.then(modal => {
addBlockModal = modal;
- const modalBody = renderBlocks(addBlockModalUrl, pageType, pageLayout);
+ const modalBody = renderBlocks(addBlockModalUrl, pageType, pageLayout, subPage);
modal.setBody(modalBody);
modal.show();
@@ -87,11 +88,12 @@ const buildAddBlockModal = () => {
* @param {String} addBlockUrl The add block URL
* @param {String} pageType The type of the page
* @param {String} pageLayout The layout of the page
+ * @param {String} subPage The subpage identifier
* @return {Promise}
*/
-const renderBlocks = async(addBlockUrl, pageType, pageLayout) => {
+const renderBlocks = async(addBlockUrl, pageType, pageLayout, subPage) => {
// Fetch all addable blocks in the given page.
- const blocks = await getAddableBlocks(pageType, pageLayout);
+ const blocks = await getAddableBlocks(pageType, pageLayout, subPage);
return Templates.render('core/add_block_body', {
blocks: blocks,
@@ -105,15 +107,17 @@ const renderBlocks = async(addBlockUrl, pageType, pageLayout) => {
* @method getAddableBlocks
* @param {String} pageType The type of the page
* @param {String} pageLayout The layout of the page
+ * @param {String} subPage The subpage identifier
* @return {Promise}
*/
-const getAddableBlocks = async(pageType, pageLayout) => {
+const getAddableBlocks = async(pageType, pageLayout, subPage) => {
const request = {
methodname: 'core_block_fetch_addable_blocks',
args: {
pagecontextid: M.cfg.contextid,
pagetype: pageType,
- pagelayout: pageLayout
+ pagelayout: pageLayout,
+ subpage: subPage,
},
};
@@ -127,10 +131,11 @@ const getAddableBlocks = async(pageType, pageLayout) => {
* @param {String} pageType The type of the page
* @param {String} pageLayout The layout of the page
* @param {String|null} addBlockUrl The add block URL
+ * @param {String} subPage The subpage identifier
*/
-export const init = (pageType, pageLayout, addBlockUrl = null) => {
+export const init = (pageType, pageLayout, addBlockUrl = null, subPage = '') => {
if (!listenerEventsRegistered) {
- registerListenerEvents(pageType, pageLayout, addBlockUrl);
+ registerListenerEvents(pageType, pageLayout, addBlockUrl, subPage);
listenerEventsRegistered = true;
}
};
diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php
index 46cd46478c2..6165d02ff4b 100644
--- a/lib/outputrenderers.php
+++ b/lib/outputrenderers.php
@@ -4973,6 +4973,7 @@ EOD;
'escapedlink' => "?{$url->get_query_string(false)}",
'pageType' => $this->page->pagetype,
'pageLayout' => $this->page->pagelayout,
+ 'subPage' => $this->page->subpage,
]
);
}
diff --git a/lib/templates/add_block_button.mustache b/lib/templates/add_block_button.mustache
index 0f6656fd921..d9a168e66ab 100644
--- a/lib/templates/add_block_button.mustache
+++ b/lib/templates/add_block_button.mustache
@@ -24,7 +24,8 @@
"link" : "/my/index.php?bui_addblock&bui_blockregion=content&sesskey=M3mes",
"escapedlink" : "?bui_addblock&bui_blockregion=content&sesskey=M3mes",
"pageType" : "my-index",
- "pageLayout" : "mydashboard"
+ "pageLayout" : "mydashboard",
+ "subPage": "15"
}
}}
@@ -37,6 +38,6 @@
{{#js}}
// Initialise the JS for the modal window which displays the blocks available to add.
require(['core/addblockmodal'], function(addBlockModal) {
- addBlockModal.init('{{pageType}}', '{{pageLayout}}');
+ addBlockModal.init('{{pageType}}', '{{pageLayout}}', null, '{{subPage}}');
});
{{/js}}