mirror of
https://github.com/moodle/moodle.git
synced 2025-08-04 08:26:37 +02:00
MDL-63465 blocks: New WS core_blocks_get_dashboard_blocks
This commit is contained in:
parent
3cced42eb3
commit
0f8b26043f
5 changed files with 295 additions and 33 deletions
|
@ -39,6 +39,68 @@ require_once("$CFG->libdir/externallib.php");
|
||||||
*/
|
*/
|
||||||
class core_block_external extends external_api {
|
class core_block_external extends external_api {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a block structure.
|
||||||
|
*
|
||||||
|
* @return external_single_structure a block single structure.
|
||||||
|
* @since Moodle 3.6
|
||||||
|
*/
|
||||||
|
private static function get_block_structure() {
|
||||||
|
return new external_single_structure(
|
||||||
|
array(
|
||||||
|
'instanceid' => new external_value(PARAM_INT, 'Block instance id.'),
|
||||||
|
'name' => new external_value(PARAM_PLUGIN, 'Block name.'),
|
||||||
|
'region' => new external_value(PARAM_ALPHANUMEXT, 'Block region.'),
|
||||||
|
'positionid' => new external_value(PARAM_INT, 'Position id.'),
|
||||||
|
'collapsible' => new external_value(PARAM_BOOL, 'Whether the block is collapsible.'),
|
||||||
|
'dockable' => new external_value(PARAM_BOOL, 'Whether the block is dockable.'),
|
||||||
|
'weight' => new external_value(PARAM_INT, 'Used to order blocks within a region.', VALUE_OPTIONAL),
|
||||||
|
'visible' => new external_value(PARAM_BOOL, 'Whether the block is visible.', VALUE_OPTIONAL),
|
||||||
|
), 'Block information.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience function for getting all the blocks of the current $PAGE.
|
||||||
|
*
|
||||||
|
* @param bool $includeinvisible Whether to include not visible blocks or not
|
||||||
|
* @return array Block information
|
||||||
|
* @since Moodle 3.6
|
||||||
|
*/
|
||||||
|
private static function get_all_current_page_blocks($includeinvisible = false) {
|
||||||
|
global $PAGE, $OUTPUT;
|
||||||
|
|
||||||
|
// Load the block instances for all the regions.
|
||||||
|
$PAGE->blocks->load_blocks($includeinvisible);
|
||||||
|
$PAGE->blocks->create_all_block_instances();
|
||||||
|
|
||||||
|
$allblocks = array();
|
||||||
|
$blocks = $PAGE->blocks->get_content_for_all_regions($OUTPUT);
|
||||||
|
foreach ($blocks as $region => $regionblocks) {
|
||||||
|
$regioninstances = $PAGE->blocks->get_blocks_for_region($region);
|
||||||
|
// Index block instances to retrieve required info.
|
||||||
|
$blockinstances = array();
|
||||||
|
foreach ($regioninstances as $ri) {
|
||||||
|
$blockinstances[$ri->instance->id] = $ri->instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($regionblocks as $bc) {
|
||||||
|
$allblocks[] = [
|
||||||
|
'instanceid' => $bc->blockinstanceid,
|
||||||
|
'name' => $blockinstances[$bc->blockinstanceid]->blockname,
|
||||||
|
'region' => $region,
|
||||||
|
'positionid' => $bc->blockpositionid,
|
||||||
|
'collapsible' => (bool) $bc->collapsible,
|
||||||
|
'dockable' => (bool) $bc->dockable,
|
||||||
|
'weight' => $blockinstances[$bc->blockinstanceid]->weight,
|
||||||
|
'visible' => $blockinstances[$bc->blockinstanceid]->visible,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $allblocks;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns description of get_course_blocks parameters.
|
* Returns description of get_course_blocks parameters.
|
||||||
*
|
*
|
||||||
|
@ -62,7 +124,7 @@ class core_block_external extends external_api {
|
||||||
* @since Moodle 3.3
|
* @since Moodle 3.3
|
||||||
*/
|
*/
|
||||||
public static function get_course_blocks($courseid) {
|
public static function get_course_blocks($courseid) {
|
||||||
global $OUTPUT, $PAGE;
|
global $PAGE;
|
||||||
|
|
||||||
$warnings = array();
|
$warnings = array();
|
||||||
$params = self::validate_parameters(self::get_course_blocks_parameters(), ['courseid' => $courseid]);
|
$params = self::validate_parameters(self::get_course_blocks_parameters(), ['courseid' => $courseid]);
|
||||||
|
@ -82,27 +144,10 @@ class core_block_external extends external_api {
|
||||||
$PAGE->set_pagetype('course-view-' . $course->format);
|
$PAGE->set_pagetype('course-view-' . $course->format);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the block instances for all the regions.
|
$allblocks = self::get_all_current_page_blocks();
|
||||||
$PAGE->blocks->load_blocks();
|
|
||||||
$PAGE->blocks->create_all_block_instances();
|
|
||||||
|
|
||||||
$finalblocks = array();
|
|
||||||
$blocks = $PAGE->blocks->get_content_for_all_regions($OUTPUT);
|
|
||||||
foreach ($blocks as $region => $regionblocks) {
|
|
||||||
foreach ($regionblocks as $bc) {
|
|
||||||
$finalblocks[] = [
|
|
||||||
'instanceid' => $bc->blockinstanceid,
|
|
||||||
'name' => $bc->attributes['data-block'],
|
|
||||||
'region' => $region,
|
|
||||||
'positionid' => $bc->blockpositionid,
|
|
||||||
'collapsible' => (bool) $bc->collapsible,
|
|
||||||
'dockable' => (bool) $bc->dockable,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'blocks' => $finalblocks,
|
'blocks' => $allblocks,
|
||||||
'warnings' => $warnings
|
'warnings' => $warnings
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -117,21 +162,91 @@ class core_block_external extends external_api {
|
||||||
|
|
||||||
return new external_single_structure(
|
return new external_single_structure(
|
||||||
array(
|
array(
|
||||||
'blocks' => new external_multiple_structure(
|
'blocks' => new external_multiple_structure(self::get_block_structure(), 'List of blocks in the course.'),
|
||||||
new external_single_structure(
|
|
||||||
array(
|
|
||||||
'instanceid' => new external_value(PARAM_INT, 'Block instance id.'),
|
|
||||||
'name' => new external_value(PARAM_PLUGIN, 'Block name.'),
|
|
||||||
'region' => new external_value(PARAM_ALPHANUMEXT, 'Block region.'),
|
|
||||||
'positionid' => new external_value(PARAM_INT, 'Position id.'),
|
|
||||||
'collapsible' => new external_value(PARAM_BOOL, 'Whether the block is collapsible.'),
|
|
||||||
'dockable' => new external_value(PARAM_BOOL, 'hether the block is dockable.'),
|
|
||||||
), 'Block information.'
|
|
||||||
), 'List of blocks in the course.'
|
|
||||||
),
|
|
||||||
'warnings' => new external_warnings(),
|
'warnings' => new external_warnings(),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns description of get_dashboard_blocks parameters.
|
||||||
|
*
|
||||||
|
* @return external_function_parameters
|
||||||
|
* @since Moodle 3.6
|
||||||
|
*/
|
||||||
|
public static function get_dashboard_blocks_parameters() {
|
||||||
|
return new external_function_parameters(
|
||||||
|
array(
|
||||||
|
'userid' => new external_value(PARAM_INT, 'User id (optional), default is current user.', VALUE_DEFAULT, 0)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns blocks information for the given user dashboard.
|
||||||
|
*
|
||||||
|
* @param int $userid The user id to retrive the blocks from, optional, default is to current user.
|
||||||
|
* @return array Blocks list and possible warnings
|
||||||
|
* @throws moodle_exception
|
||||||
|
* @since Moodle 3.6
|
||||||
|
*/
|
||||||
|
public static function get_dashboard_blocks($userid = 0) {
|
||||||
|
global $CFG, $USER, $PAGE;
|
||||||
|
|
||||||
|
require_once($CFG->dirroot . '/my/lib.php');
|
||||||
|
|
||||||
|
$warnings = array();
|
||||||
|
$params = self::validate_parameters(self::get_dashboard_blocks_parameters(), ['userid' => $userid]);
|
||||||
|
|
||||||
|
$userid = $params['userid'];
|
||||||
|
if (empty($userid)) {
|
||||||
|
$userid = $USER->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($USER->id != $userid) {
|
||||||
|
// We must check if the current user can view other users dashboard.
|
||||||
|
require_capability('moodle/site:config', context_system::instance());
|
||||||
|
$user = core_user::get_user($userid, '*', MUST_EXIST);
|
||||||
|
core_user::require_active_user($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
$context = context_user::instance($userid);;
|
||||||
|
self::validate_context($context);
|
||||||
|
|
||||||
|
// Get the My Moodle page info. Should always return something unless the database is broken.
|
||||||
|
if (!$currentpage = my_get_page($userid, MY_PAGE_PRIVATE)) {
|
||||||
|
throw new moodle_exception('mymoodlesetup');
|
||||||
|
}
|
||||||
|
|
||||||
|
$PAGE->set_context($context);
|
||||||
|
$PAGE->set_pagelayout('mydashboard');
|
||||||
|
$PAGE->set_pagetype('my-index');
|
||||||
|
$PAGE->blocks->add_region('content'); // Need to add this special regition to retrieve the central blocks.
|
||||||
|
$PAGE->set_subpage($currentpage->id);
|
||||||
|
|
||||||
|
// Load the block instances in the current $PAGE for all the regions.
|
||||||
|
$returninvisible = has_capability('moodle/my:manageblocks', $context) ? true : false;
|
||||||
|
$allblocks = self::get_all_current_page_blocks($returninvisible);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'blocks' => $allblocks,
|
||||||
|
'warnings' => $warnings
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns description of get_dashboard_blocks result values.
|
||||||
|
*
|
||||||
|
* @return external_single_structure
|
||||||
|
* @since Moodle 3.6
|
||||||
|
*/
|
||||||
|
public static function get_dashboard_blocks_returns() {
|
||||||
|
|
||||||
|
return new external_single_structure(
|
||||||
|
array(
|
||||||
|
'blocks' => new external_multiple_structure(self::get_block_structure(), 'List of blocks in the dashboard.'),
|
||||||
|
'warnings' => new external_warnings(),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ defined('MOODLE_INTERNAL') || die();
|
||||||
global $CFG;
|
global $CFG;
|
||||||
|
|
||||||
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
|
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
|
||||||
|
require_once($CFG->dirroot . '/my/lib.php');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* External block functions unit tests
|
* External block functions unit tests
|
||||||
|
@ -138,4 +139,140 @@ class core_block_externallib_testcase extends externallib_advanced_testcase {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test user get default dashboard blocks.
|
||||||
|
*/
|
||||||
|
public function test_get_dashboard_blocks_default_dashboard() {
|
||||||
|
global $PAGE, $DB;
|
||||||
|
$this->resetAfterTest(true);
|
||||||
|
|
||||||
|
$user = $this->getDataGenerator()->create_user();
|
||||||
|
$PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set.
|
||||||
|
|
||||||
|
// Get the expected default blocks.
|
||||||
|
$alldefaultblocksordered = $DB->get_records_menu('block_instances',
|
||||||
|
array('pagetypepattern' => 'my-index'), 'defaultregion, defaultweight ASC', 'id, blockname');
|
||||||
|
|
||||||
|
$this->setUser($user);
|
||||||
|
|
||||||
|
// Check for the default blocks.
|
||||||
|
$result = core_block_external::get_dashboard_blocks($user->id);
|
||||||
|
// We need to execute the return values cleaning process to simulate the web service server.
|
||||||
|
$result = external_api::clean_returnvalue(core_block_external::get_dashboard_blocks_returns(), $result);
|
||||||
|
// Expect all blogs except learning plans one (no learning plans to show).
|
||||||
|
$this->assertCount(count($alldefaultblocksordered) - 1, $result['blocks']);
|
||||||
|
$returnedblocks = array();
|
||||||
|
foreach ($result['blocks'] as $block) {
|
||||||
|
// Check all the returned blocks are in the expected blocks array.
|
||||||
|
$this->assertContains($block['name'], $alldefaultblocksordered);
|
||||||
|
$returnedblocks[] = $block['name'];
|
||||||
|
}
|
||||||
|
// Remove lp block.
|
||||||
|
array_shift($alldefaultblocksordered);
|
||||||
|
// Check that we received the blocks in the expected order.
|
||||||
|
$this->assertEquals(array_values($alldefaultblocksordered), $returnedblocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test user get default dashboard blocks including a sticky block.
|
||||||
|
*/
|
||||||
|
public function test_get_dashboard_blocks_default_dashboard_including_sticky_block() {
|
||||||
|
global $PAGE, $DB;
|
||||||
|
$this->resetAfterTest(true);
|
||||||
|
|
||||||
|
$user = $this->getDataGenerator()->create_user();
|
||||||
|
$PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set.
|
||||||
|
|
||||||
|
// Get the expected default blocks.
|
||||||
|
$alldefaultblocks = $DB->get_records_menu('block_instances', array('pagetypepattern' => 'my-index'), '', 'id, blockname');
|
||||||
|
|
||||||
|
// Now, add a sticky block.
|
||||||
|
$page = new moodle_page();
|
||||||
|
$page->set_context(context_system::instance());
|
||||||
|
$page->set_pagetype('my-index');
|
||||||
|
$page->set_url(new moodle_url('/'));
|
||||||
|
$page->blocks->add_region('side-pre');
|
||||||
|
$page->blocks->load_blocks();
|
||||||
|
$page->blocks->add_block('myprofile', 'side-pre', 0, true, '*');
|
||||||
|
|
||||||
|
$this->setUser($user);
|
||||||
|
|
||||||
|
// Check for the default blocks plus the sticky.
|
||||||
|
$result = core_block_external::get_dashboard_blocks($user->id);
|
||||||
|
// We need to execute the return values cleaning process to simulate the web service server.
|
||||||
|
$result = external_api::clean_returnvalue(core_block_external::get_dashboard_blocks_returns(), $result);
|
||||||
|
// Expect all blogs plus sticky one except learning plans one (no learning plans to show).
|
||||||
|
$this->assertCount(count($alldefaultblocks), $result['blocks']);
|
||||||
|
$found = false;
|
||||||
|
foreach ($result['blocks'] as $block) {
|
||||||
|
if ($block['name'] == 'myprofile') {
|
||||||
|
$this->assertEquals('side-pre', $block['region']);
|
||||||
|
$found = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Check that the block is in the expected blocks array.
|
||||||
|
$this->assertContains($block['name'], $alldefaultblocks);
|
||||||
|
}
|
||||||
|
$this->assertTrue($found);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test admin get user's custom dashboard blocks.
|
||||||
|
*/
|
||||||
|
public function test_get_dashboard_blocks_custom_user_dashboard() {
|
||||||
|
global $PAGE, $DB;
|
||||||
|
$this->resetAfterTest(true);
|
||||||
|
|
||||||
|
$user = $this->getDataGenerator()->create_user();
|
||||||
|
$PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set.
|
||||||
|
|
||||||
|
// Get the expected default blocks.
|
||||||
|
$alldefaultblocks = $DB->get_records_menu('block_instances', array('pagetypepattern' => 'my-index'), '', 'id, blockname');
|
||||||
|
|
||||||
|
// Add a custom block.
|
||||||
|
$page = new moodle_page();
|
||||||
|
$page->set_context(context_user::instance($user->id));
|
||||||
|
$page->set_pagelayout('mydashboard');
|
||||||
|
$page->set_pagetype('my-index');
|
||||||
|
$page->blocks->add_region('content');
|
||||||
|
$currentpage = my_get_page($user->id, MY_PAGE_PRIVATE);
|
||||||
|
$page->set_subpage($currentpage->id);
|
||||||
|
$page->blocks->load_blocks();
|
||||||
|
$page->blocks->add_block('myprofile', 'content', 0, false);
|
||||||
|
|
||||||
|
$this->setAdminUser();
|
||||||
|
|
||||||
|
// Check for the new block as admin for a user.
|
||||||
|
$result = core_block_external::get_dashboard_blocks($user->id);
|
||||||
|
// We need to execute the return values cleaning process to simulate the web service server.
|
||||||
|
$result = external_api::clean_returnvalue(core_block_external::get_dashboard_blocks_returns(), $result);
|
||||||
|
// Expect all default blogs plys the one we added except learning plans one (no learning plans to show).
|
||||||
|
$this->assertCount(count($alldefaultblocks), $result['blocks']);
|
||||||
|
$found = false;
|
||||||
|
foreach ($result['blocks'] as $block) {
|
||||||
|
if ($block['name'] == 'myprofile') {
|
||||||
|
$this->assertEquals('content', $block['region']);
|
||||||
|
$found = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Check that the block is in the expected blocks array.
|
||||||
|
$this->assertContains($block['name'], $alldefaultblocks);
|
||||||
|
}
|
||||||
|
$this->assertTrue($found);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test user tries to get other user blocks not having permission.
|
||||||
|
*/
|
||||||
|
public function test_get_dashboard_blocks_other_user_missing_permissions() {
|
||||||
|
$this->resetAfterTest(true);
|
||||||
|
|
||||||
|
$user1 = $this->getDataGenerator()->create_user();
|
||||||
|
$user2 = $this->getDataGenerator()->create_user();
|
||||||
|
|
||||||
|
$this->setUser($user1);
|
||||||
|
|
||||||
|
$this->expectException('moodle_exception');
|
||||||
|
core_block_external::get_dashboard_blocks($user2->id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ information provided here is intended especially for developers.
|
||||||
=== 3.6 ===
|
=== 3.6 ===
|
||||||
|
|
||||||
* The timeline view from block_myoverview has been split out into block_timeline.
|
* The timeline view from block_myoverview has been split out into block_timeline.
|
||||||
|
* External function core_blocks::get_course_blocks now returns the block visible status and weight for ordering.
|
||||||
|
|
||||||
=== 3.4 ===
|
=== 3.4 ===
|
||||||
|
|
||||||
|
|
|
@ -2214,6 +2214,15 @@ $functions = array(
|
||||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
|
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
'core_block_get_dashboard_blocks' => array(
|
||||||
|
'classname' => 'core_block_external',
|
||||||
|
'methodname' => 'get_dashboard_blocks',
|
||||||
|
'description' => 'Returns blocks information for the given user dashboard.',
|
||||||
|
'type' => 'read',
|
||||||
|
'capabilities' => '',
|
||||||
|
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
|
||||||
|
),
|
||||||
|
|
||||||
// Filters functions.
|
// Filters functions.
|
||||||
'core_filters_get_available_in_context' => array(
|
'core_filters_get_available_in_context' => array(
|
||||||
'classname' => 'core_filters\external',
|
'classname' => 'core_filters\external',
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
defined('MOODLE_INTERNAL') || die();
|
defined('MOODLE_INTERNAL') || die();
|
||||||
|
|
||||||
$version = 2018101100.00; // YYYYMMDD = weekly release date of this DEV branch.
|
$version = 2018101100.01; // YYYYMMDD = weekly release date of this DEV branch.
|
||||||
// RR = release increments - 00 in DEV branches.
|
// RR = release increments - 00 in DEV branches.
|
||||||
// .XX = incremental changes.
|
// .XX = incremental changes.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue