MDL-85433 singleactivity: Support multiple activities
This commit is contained in:
@@ -69,7 +69,7 @@ Feature: Edit activities in Additional activities block
|
||||
And I log in as "admin"
|
||||
And I am on site homepage
|
||||
And I turn editing mode on
|
||||
And I should see "My forum name" in the "block_site_main_menu_section" "region"
|
||||
And I should see "My forum name" in the "Additional activities" "block"
|
||||
And I should not see "My forum name" in the "region-main" "region"
|
||||
When I open "My forum name" actions menu
|
||||
And I click on "Move" "link" in the "My forum name" activity
|
||||
@@ -78,7 +78,7 @@ Feature: Edit activities in Additional activities block
|
||||
And I should see "Site" in the "Move activity" "dialogue"
|
||||
And I click on "Site" "link" in the "Move activity" "dialogue"
|
||||
Then I should see "My forum name" in the "region-main" "region"
|
||||
And I should not see "My forum name" in the "block_site_main_menu_section" "region"
|
||||
And I should not see "My forum name" in the "Additional activities" "block"
|
||||
|
||||
@javascript
|
||||
Scenario: The move activity modal allow to move from the main content to the Additional activities block
|
||||
@@ -94,7 +94,7 @@ Feature: Edit activities in Additional activities block
|
||||
And I log in as "admin"
|
||||
And I am on site homepage
|
||||
And I turn editing mode on
|
||||
And I should not see "My forum name" in the "block_site_main_menu_section" "region"
|
||||
And I should not see "My forum name" in the "Additional activities" "block"
|
||||
And I should see "My forum name" in the "region-main" "region"
|
||||
When I open "My forum name" actions menu
|
||||
And I click on "Move" "link" in the "My forum name" activity
|
||||
@@ -103,7 +103,7 @@ Feature: Edit activities in Additional activities block
|
||||
And I should see "Site" in the "Move activity" "dialogue"
|
||||
And I click on "Block" "link" in the "Move activity" "dialogue"
|
||||
Then I should not see "My forum name" in the "region-main" "region"
|
||||
And I should see "My forum name" in the "block_site_main_menu_section" "region"
|
||||
And I should see "My forum name" in the "Additional activities" "block"
|
||||
|
||||
@javascript
|
||||
Scenario: Admin can delete an activity in the Additional activities block
|
||||
@@ -118,11 +118,11 @@ Feature: Edit activities in Additional activities block
|
||||
And I log in as "admin"
|
||||
And I am on site homepage
|
||||
And I turn editing mode on
|
||||
And I should see "My forum name" in the "block_site_main_menu_section" "region"
|
||||
And I should see "My forum name" in the "Additional activities" "block"
|
||||
When I open "My forum name" actions menu
|
||||
And I choose "Delete" in the open action menu
|
||||
And I click on "Delete" "button" in the "Delete activity?" "dialogue"
|
||||
Then I should not see "My forum name" in the "block_site_main_menu_section" "region"
|
||||
Then I should not see "My forum name" in the "Additional activities" "block"
|
||||
|
||||
@javascript
|
||||
Scenario: Admin can duplicate an activity in the Additional activities block
|
||||
@@ -137,10 +137,10 @@ Feature: Edit activities in Additional activities block
|
||||
And I log in as "admin"
|
||||
And I am on site homepage
|
||||
And I turn editing mode on
|
||||
And I should see "My forum name" in the "block_site_main_menu_section" "region"
|
||||
And I should see "My forum name" in the "Additional activities" "block"
|
||||
When I open "My forum name" actions menu
|
||||
And I choose "Duplicate" in the open action menu
|
||||
Then I should see "My forum name (copy)" in the "block_site_main_menu_section" "region"
|
||||
Then I should see "My forum name (copy)" in the "Additional activities" "block"
|
||||
|
||||
@javascript
|
||||
Scenario: Admin can move right and left an activity in the Additional activities block
|
||||
@@ -155,7 +155,7 @@ Feature: Edit activities in Additional activities block
|
||||
And I log in as "admin"
|
||||
And I am on site homepage
|
||||
And I turn editing mode on
|
||||
And I should see "My forum name" in the "block_site_main_menu_section" "region"
|
||||
And I should see "My forum name" in the "Additional activities" "block"
|
||||
When I open "My forum name" actions menu
|
||||
And "Move right" "link" should be visible
|
||||
And "Move left" "link" should not be visible
|
||||
|
||||
@@ -1106,12 +1106,6 @@ class stateactions {
|
||||
throw new moodle_exception('emptysectionids', 'core', null, $info);
|
||||
}
|
||||
|
||||
// No section actions are allowed if course format does not support sections.
|
||||
$courseformat = course_get_format($course->id);
|
||||
if (!$courseformat->uses_sections()) {
|
||||
throw new moodle_exception('sectionactionnotsupported', 'core', null, $info);
|
||||
}
|
||||
|
||||
list($insql, $inparams) = $DB->get_in_or_equal($sectionids, SQL_PARAMS_NAMED);
|
||||
|
||||
// Check if all the given sections exist.
|
||||
|
||||
@@ -27,5 +27,9 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
include_course_ajax($course);
|
||||
|
||||
$courserenderer = $PAGE->get_renderer('format_singleactivity');
|
||||
echo $courserenderer->display($course, $section != 0);
|
||||
|
||||
@@ -27,10 +27,7 @@ $string['activitytype_help'] = 'Choose the type of activity or resource to use i
|
||||
$string['defactivitytype'] = 'Default type of activity';
|
||||
$string['defactivitytypedesc'] = 'Specify the activity type that will be selected by default when creating a new course';
|
||||
$string['erroractivitytype'] = 'Type of activity is not set up in Course settings';
|
||||
$string['orphaned'] = 'Orphaned';
|
||||
$string['orphanedwarning'] = 'These activities are unreachable by users!';
|
||||
$string['plugin_description'] = 'The course displays only one activity on the course page. You can add more activities in the Additional activities block';
|
||||
$string['pluginname'] = 'Single activity';
|
||||
$string['plugin_description'] = 'The course contains only one activity or resource.';
|
||||
$string['sectionname'] = '';
|
||||
$string['warningchangeformat'] = 'When changing the existing course format to "Single activity" make sure that you removed all extra activities from the course including "Announcements". Note that sections structure may be modified.';
|
||||
$string['privacy:metadata'] = 'The Single activity format plugin does not store any personal data.';
|
||||
|
||||
@@ -14,14 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains main class for the course format singleactivity
|
||||
*
|
||||
* @package format_singleactivity
|
||||
* @copyright 2012 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use core_courseformat\sectiondelegate;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
@@ -34,8 +26,8 @@ require_once($CFG->dirroot. '/course/format/lib.php');
|
||||
* @copyright 2012 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class format_singleactivity extends core_courseformat\base {
|
||||
/** @var cm_info the current activity. Use get_activity() to retrieve it. */
|
||||
class format_singleactivity extends core_courseformat\base implements core_courseformat\main_activity_interface {
|
||||
/** @var cm_info the current activity. Use get_main_activity() to retrieve it. */
|
||||
private $activity = false;
|
||||
|
||||
/** @var int The category ID guessed from the form data. */
|
||||
@@ -51,7 +43,7 @@ class format_singleactivity extends core_courseformat\base {
|
||||
* 'sr' (int) ignored by this format
|
||||
* @return null|moodle_url
|
||||
*/
|
||||
public function get_view_url($section, $options = array()) {
|
||||
public function get_view_url($section, $options = []) {
|
||||
return new moodle_url('/course/view.php', ['id' => $this->courseid]);
|
||||
}
|
||||
|
||||
@@ -62,58 +54,7 @@ class format_singleactivity extends core_courseformat\base {
|
||||
* @param navigation_node $node The course node within the navigation
|
||||
*/
|
||||
public function extend_course_navigation($navigation, navigation_node $node) {
|
||||
// Display orphaned activities for the users who can see them.
|
||||
$context = context_course::instance($this->courseid);
|
||||
if (has_capability('moodle/course:viewhiddensections', $context)) {
|
||||
$modinfo = get_fast_modinfo($this->courseid);
|
||||
if (!empty($modinfo->sections[1])) {
|
||||
$section1 = $modinfo->get_section_info(1);
|
||||
// Show orphaned activities.
|
||||
$orphanednode = $node->add(get_string('orphaned', 'format_singleactivity'),
|
||||
$this->get_view_url(1), navigation_node::TYPE_SECTION, null, $section1->id);
|
||||
$orphanednode->nodetype = navigation_node::NODETYPE_BRANCH;
|
||||
$orphanednode->add_class('orphaned');
|
||||
foreach ($modinfo->sections[1] as $cmid) {
|
||||
if (has_capability('moodle/course:viewhiddenactivities', context_module::instance($cmid))) {
|
||||
$this->navigation_add_activity($orphanednode, $modinfo->cms[$cmid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a course module to the navigation node
|
||||
*
|
||||
* This is basically copied from function global_navigation::load_section_activities()
|
||||
* because it is not accessible from outside.
|
||||
*
|
||||
* @param navigation_node $node
|
||||
* @param cm_info $cm
|
||||
* @return null|navigation_node
|
||||
*/
|
||||
protected function navigation_add_activity(navigation_node $node, $cm) {
|
||||
if (!$cm->uservisible) {
|
||||
return null;
|
||||
}
|
||||
$action = $cm->url;
|
||||
if (!$action) {
|
||||
// Do not add to navigation activity without url (i.e. labels).
|
||||
return null;
|
||||
}
|
||||
$activityname = format_string($cm->name, true, array('context' => context_module::instance($cm->id)));
|
||||
if ($cm->icon) {
|
||||
$icon = new pix_icon($cm->icon, $cm->modfullname, $cm->iconcomponent);
|
||||
} else {
|
||||
$icon = new pix_icon('monologo', $cm->modfullname, $cm->modname);
|
||||
}
|
||||
$activitynode = $node->add($activityname, $action, navigation_node::TYPE_ACTIVITY, null, $cm->id, $icon);
|
||||
if (global_navigation::module_extends_navigation($cm->modname)) {
|
||||
$activitynode->nodetype = navigation_node::NODETYPE_BRANCH;
|
||||
} else {
|
||||
$activitynode->nodetype = navigation_node::NODETYPE_LEAF;
|
||||
}
|
||||
return $activitynode;
|
||||
// SingleActivity course format does not extend navigation, it uses site_main_menu block instead.
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,11 +64,10 @@ class format_singleactivity extends core_courseformat\base {
|
||||
* each of values is an array of block names (for left and right side columns)
|
||||
*/
|
||||
public function get_default_blocks() {
|
||||
// No blocks for this format because course view page is not displayed anyway.
|
||||
return array(
|
||||
BLOCK_POS_LEFT => array(),
|
||||
BLOCK_POS_RIGHT => array()
|
||||
);
|
||||
return [
|
||||
BLOCK_POS_LEFT => ['site_main_menu'],
|
||||
BLOCK_POS_RIGHT => [],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,12 +116,12 @@ class format_singleactivity extends core_courseformat\base {
|
||||
|
||||
if ($courseformatoptions === false) {
|
||||
$config = get_config('format_singleactivity');
|
||||
$courseformatoptions = array(
|
||||
'activitytype' => array(
|
||||
$courseformatoptions = [
|
||||
'activitytype' => [
|
||||
'default' => $config->activitytype,
|
||||
'type' => PARAM_TEXT,
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
|
||||
if (!empty($availabletypes) && !isset($availabletypes[$config->activitytype])) {
|
||||
$courseformatoptions['activitytype']['default'] = array_keys($availabletypes)[0];
|
||||
@@ -189,15 +129,15 @@ class format_singleactivity extends core_courseformat\base {
|
||||
}
|
||||
|
||||
if ($foreditform && !isset($courseformatoptions['activitytype']['label'])) {
|
||||
$courseformatoptionsedit = array(
|
||||
'activitytype' => array(
|
||||
$courseformatoptionsedit = [
|
||||
'activitytype' => [
|
||||
'label' => new lang_string('activitytype', 'format_singleactivity'),
|
||||
'help' => 'activitytype',
|
||||
'help_component' => 'format_singleactivity',
|
||||
'element_type' => 'select',
|
||||
'element_attributes' => array($availabletypes),
|
||||
),
|
||||
);
|
||||
'element_attributes' => [$availabletypes],
|
||||
],
|
||||
];
|
||||
$courseformatoptions = array_merge_recursive($courseformatoptions, $courseformatoptionsedit);
|
||||
}
|
||||
return $courseformatoptions;
|
||||
@@ -215,109 +155,15 @@ class format_singleactivity extends core_courseformat\base {
|
||||
* @return array array of references to the added form elements
|
||||
*/
|
||||
public function create_edit_form_elements(&$mform, $forsection = false) {
|
||||
global $PAGE;
|
||||
|
||||
if (!$this->course && $submitvalues = $mform->getSubmitValues()) {
|
||||
$this->categoryid = $submitvalues['category'];
|
||||
}
|
||||
|
||||
$elements = parent::create_edit_form_elements($mform, $forsection);
|
||||
if (!$forsection && ($course = $PAGE->course) && !empty($course->format) &&
|
||||
$course->format !== 'site' && $course->format !== 'singleactivity') {
|
||||
// This is the existing course in other format, display a warning.
|
||||
$element = $mform->addElement('static', '', '',
|
||||
html_writer::tag('span', get_string('warningchangeformat', 'format_singleactivity'),
|
||||
array('class' => 'error')));
|
||||
array_unshift($elements, $element);
|
||||
}
|
||||
|
||||
return $elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that current active activity is in section 0
|
||||
*
|
||||
* All other activities are moved to section 1 that will be displayed as 'Orphaned'.
|
||||
* It may be needed after the course format was changed or activitytype in
|
||||
* course settings has been changed.
|
||||
*
|
||||
* @return null|cm_info current activity
|
||||
*/
|
||||
public function reorder_activities() {
|
||||
course_create_sections_if_missing($this->courseid, array(0, 1));
|
||||
foreach ($this->get_sections() as $sectionnum => $section) {
|
||||
if (($sectionnum && $section->visible) ||
|
||||
(!$sectionnum && !$section->visible)) {
|
||||
// Make sure that 0 section is visible and all others are hidden.
|
||||
set_section_visible($this->courseid, $sectionnum, $sectionnum == 0);
|
||||
}
|
||||
}
|
||||
$modinfo = get_fast_modinfo($this->courseid);
|
||||
|
||||
// Find the current activity (first activity with the specified type in all course activities).
|
||||
$activitytype = $this->get_activitytype();
|
||||
$activity = null;
|
||||
if (!empty($activitytype)) {
|
||||
foreach ($modinfo->sections as $sectionnum => $cmlist) {
|
||||
foreach ($cmlist as $cmid) {
|
||||
if ($modinfo->cms[$cmid]->modname === $activitytype) {
|
||||
$activity = $modinfo->cms[$cmid];
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the current activity is in the 0-section.
|
||||
$changed = false;
|
||||
if ($activity && $activity->sectionnum != 0) {
|
||||
moveto_module($activity, $modinfo->get_section_info(0));
|
||||
$changed = true;
|
||||
}
|
||||
if ($activity && !$activity->visible) {
|
||||
set_coursemodule_visible($activity->id, 1);
|
||||
$changed = true;
|
||||
}
|
||||
if ($changed) {
|
||||
// Cache was reset so get modinfo again.
|
||||
$modinfo = get_fast_modinfo($this->courseid);
|
||||
}
|
||||
|
||||
// Move all other activities into section 1 (the order must be kept).
|
||||
$hasvisibleactivities = false;
|
||||
$firstorphanedcm = null;
|
||||
foreach ($modinfo->sections as $sectionnum => $cmlist) {
|
||||
if ($sectionnum && !empty($cmlist) && $firstorphanedcm === null) {
|
||||
$firstorphanedcm = reset($cmlist);
|
||||
}
|
||||
foreach ($cmlist as $cmid) {
|
||||
if ($sectionnum > 1) {
|
||||
// These module types cannot be moved from section 0.
|
||||
if (!$modinfo->cms[$cmid]->is_of_type_that_can_display()) {
|
||||
continue;
|
||||
}
|
||||
moveto_module($modinfo->get_cm($cmid), $modinfo->get_section_info(1));
|
||||
} else if (!$hasvisibleactivities && $sectionnum == 1 && $modinfo->get_cm($cmid)->visible) {
|
||||
$hasvisibleactivities = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($modinfo->sections[0])) {
|
||||
foreach ($modinfo->sections[0] as $cmid) {
|
||||
// These module types cannot be moved from section 0.
|
||||
if (!$modinfo->cms[$cmid]->is_of_type_that_can_display()) {
|
||||
continue;
|
||||
}
|
||||
if (!$activity || $cmid != $activity->id) {
|
||||
moveto_module($modinfo->get_cm($cmid), $modinfo->get_section_info(1), $firstorphanedcm);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($hasvisibleactivities) {
|
||||
set_section_visible($this->courseid, 1, false);
|
||||
}
|
||||
return $activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of activity type used for this course
|
||||
*
|
||||
@@ -334,16 +180,36 @@ class format_singleactivity extends core_courseformat\base {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current activity if exists
|
||||
*
|
||||
* @return null|cm_info
|
||||
*/
|
||||
protected function get_activity() {
|
||||
#[\Override]
|
||||
public function get_main_activity(): ?\cm_info {
|
||||
if ($this->activity === false) {
|
||||
$this->activity = $this->reorder_activities();
|
||||
$modinfo = get_fast_modinfo($this->courseid);
|
||||
|
||||
// Find the current activity (first activity with the specified type in all course activities).
|
||||
$activitytype = $this->get_activitytype();
|
||||
if (!empty($activitytype) && !empty($modinfo->sections)) {
|
||||
// Get the first activity of the specified type, but only if it is in the 0-section.
|
||||
$cmlist = $modinfo->sections[0];
|
||||
foreach ($cmlist as $cmid) {
|
||||
if ($modinfo->cms[$cmid]->modname === $activitytype) {
|
||||
$this->activity = $modinfo->cms[$cmid];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the current activity is visible.
|
||||
if ($this->activity && !$this->activity->visible) {
|
||||
set_coursemodule_visible($this->activity->id, 1);
|
||||
}
|
||||
}
|
||||
return $this->activity;
|
||||
|
||||
if ($this->activity !== false) {
|
||||
return $this->activity;
|
||||
}
|
||||
|
||||
// No activity found, return null.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -352,7 +218,7 @@ class format_singleactivity extends core_courseformat\base {
|
||||
* Here we ignore the modules that do not have a page of their own or need sections,
|
||||
* like the label or subsection.
|
||||
*
|
||||
* @return array array($module => $name of the module).
|
||||
* @return array [$module => $name of the module].
|
||||
*/
|
||||
public static function get_supported_activities() {
|
||||
$availabletypes = get_module_types_names();
|
||||
@@ -385,7 +251,7 @@ class format_singleactivity extends core_courseformat\base {
|
||||
}
|
||||
$libfile = "$CFG->dirroot/mod/$modname/lib.php";
|
||||
if (!file_exists($libfile)) {
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -434,8 +300,6 @@ class format_singleactivity extends core_courseformat\base {
|
||||
* If everything is configured correctly, user is redirected from the
|
||||
* default course view page to the activity view page.
|
||||
*
|
||||
* "Section 1" is the administrative page to manage orphaned activities
|
||||
*
|
||||
* If user is on course view page and there is no module added to the course
|
||||
* and the user has 'moodle/course:manageactivities' capability, redirect to create module
|
||||
* form.
|
||||
@@ -452,24 +316,18 @@ class format_singleactivity extends core_courseformat\base {
|
||||
// This is a request to turn editing mode on or off, do not redirect here, /course/view.php will do redirection.
|
||||
return;
|
||||
}
|
||||
$cm = $this->get_activity();
|
||||
$cursection = optional_param('section', null, PARAM_INT);
|
||||
if (!empty($cursection) && has_capability('moodle/course:viewhiddensections',
|
||||
context_course::instance($this->courseid))) {
|
||||
// Display orphaned activities (course view page, section 1).
|
||||
return;
|
||||
}
|
||||
$cm = $this->get_main_activity();
|
||||
if (!$this->get_activitytype()) {
|
||||
if (has_capability('moodle/course:update', context_course::instance($this->courseid))) {
|
||||
// Teacher is redirected to edit course page.
|
||||
$url = new moodle_url('/course/edit.php', array('id' => $this->courseid));
|
||||
$url = new moodle_url('/course/edit.php', ['id' => $this->courseid]);
|
||||
redirect($url, get_string('erroractivitytype', 'format_singleactivity'));
|
||||
} else {
|
||||
// Student sees an empty course page.
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ($cm === null) {
|
||||
if ($cm == null) {
|
||||
if ($this->can_add_activity()) {
|
||||
// This is a user who has capability to create an activity.
|
||||
if ($this->activity_has_subtypes()) {
|
||||
@@ -477,13 +335,20 @@ class format_singleactivity extends core_courseformat\base {
|
||||
if (optional_param('addactivity', 0, PARAM_INT)) {
|
||||
return;
|
||||
} else {
|
||||
$url = new moodle_url('/course/view.php', array('id' => $this->courseid, 'addactivity' => 1));
|
||||
$url = new moodle_url('/course/view.php', ['id' => $this->courseid, 'addactivity' => 1]);
|
||||
redirect($url);
|
||||
}
|
||||
}
|
||||
// Redirect to the add activity form.
|
||||
$url = new moodle_url('/course/mod.php', array('id' => $this->courseid,
|
||||
'section' => 0, 'sesskey' => sesskey(), 'add' => $this->get_activitytype()));
|
||||
$url = new moodle_url(
|
||||
'/course/mod.php',
|
||||
[
|
||||
'id' => $this->courseid,
|
||||
'section' => 0,
|
||||
'sesskey' => sesskey(),
|
||||
'add' => $this->get_activitytype(),
|
||||
],
|
||||
);
|
||||
redirect($url);
|
||||
} else {
|
||||
// Student views an empty course page.
|
||||
@@ -511,7 +376,7 @@ class format_singleactivity extends core_courseformat\base {
|
||||
public function page_set_cm(moodle_page $page) {
|
||||
global $PAGE;
|
||||
parent::page_set_cm($page);
|
||||
if ($PAGE == $page && ($cm = $this->get_activity()) &&
|
||||
if ($PAGE == $page && ($cm = $this->get_main_activity()) &&
|
||||
$cm->uservisible &&
|
||||
($cm->id === $page->cm->id) &&
|
||||
($activitynode = $page->navigation->find($cm->id, navigation_node::TYPE_ACTIVITY)) &&
|
||||
@@ -535,11 +400,7 @@ class format_singleactivity extends core_courseformat\base {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the course has a front page.
|
||||
*
|
||||
* @return boolean false
|
||||
*/
|
||||
#[\Override]
|
||||
public function has_view_page() {
|
||||
return false;
|
||||
}
|
||||
@@ -554,4 +415,62 @@ class format_singleactivity extends core_courseformat\base {
|
||||
// Return everything (nothing to hide).
|
||||
return $this->get_format_options();
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function supports_ajax() {
|
||||
// All home page is rendered in the backend, we only need an ajax editor components in edit mode.
|
||||
// This will also prevent redirecting to the login page when a guest tries to access the site,
|
||||
// and will make the home page loading faster.
|
||||
$ajaxsupport = new stdClass();
|
||||
$ajaxsupport->capable = $this->show_editor();
|
||||
return $ajaxsupport;
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function supports_components() {
|
||||
return true;
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function uses_sections() {
|
||||
return false;
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function get_section_name($section) {
|
||||
$section = $this->get_section($section);
|
||||
if ($section->is_delegated()) {
|
||||
return $section->name;
|
||||
}
|
||||
// The single activity only uses one section inside the additional activities block.
|
||||
return get_string('pluginname', 'format_singleactivity');
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function get_sectionnum(): int {
|
||||
// SingleActivity format uses only section 0.
|
||||
return 0;
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function allow_stealth_module_visibility($cm, $section) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a specific section is visible to the current user.
|
||||
*
|
||||
* The single activity format does only have the section zero
|
||||
* and subsections (delegated sections).
|
||||
*
|
||||
* @param section_info $section the section modinfo
|
||||
* @return bool;
|
||||
*/
|
||||
#[\Override]
|
||||
public function is_section_visible(section_info $section): bool {
|
||||
$visible = parent::is_section_visible($section);
|
||||
// Social format does only use section 0 as a normal section.
|
||||
// Any other included section should be a delegated one (subsections).
|
||||
return $visible && ($section->sectionnum == 0 || $section->is_delegated());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
.format-singleactivity .tree_item.orphaned a {
|
||||
color: red;
|
||||
}
|
||||
@@ -19,53 +19,30 @@ Feature: Activity navigation in a single activity course
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | section |
|
||||
| forum | Forum 1 | Test forum description | C1 | forum1 | 0 |
|
||||
| assign | Assignment 1 | Test assignment description | C1 | assign1 | 0 |
|
||||
| lesson | Lesson 1 | Test lesson description | C1 | lesson1 | 0 |
|
||||
| forum | Forum 1 | Test forum description | C1 | forum1 | 0 |
|
||||
|
||||
Scenario: Step through hidden activities in the course as a teacher.
|
||||
Scenario: Step through activities in the course as a teacher
|
||||
Given I log in as "teacher1"
|
||||
When I am on "Course 1" course homepage
|
||||
# The first activity (Forum 1) won't have the previous activity link.
|
||||
Then "#prev-activity-link" "css_element" should not exist
|
||||
And I should see "Assignment 1 (hidden)" in the "#next-activity-link" "css_element"
|
||||
And I follow "Assignment 1 (hidden)"
|
||||
And I should see "Assignment 1" in the "#next-activity-link" "css_element"
|
||||
And I follow "Assignment 1"
|
||||
And I should see "Forum 1" in the "#prev-activity-link" "css_element"
|
||||
And I should see "Lesson 1 (hidden)" in the "#next-activity-link" "css_element"
|
||||
And I follow "Lesson 1 (hidden)"
|
||||
And I should see "Assignment 1 (hidden)" in the "#prev-activity-link" "css_element"
|
||||
And I should see "Lesson 1" in the "#next-activity-link" "css_element"
|
||||
And I follow "Lesson 1"
|
||||
And I should see "Assignment 1" in the "#prev-activity-link" "css_element"
|
||||
And "#next-activity-link" "css_element" should not exist
|
||||
|
||||
Scenario: Jump to a hidden activity as a teacher
|
||||
Given I log in as "teacher1"
|
||||
When I am on "Course 1" course homepage
|
||||
Then "Jump to..." "field" should exist
|
||||
# The current activity (Forum 1) will not be listed.
|
||||
And the "Jump to..." select box should not contain "Forum 1"
|
||||
# Check drop down menu contents.
|
||||
And the "Jump to..." select box should contain "Assignment 1 (hidden)"
|
||||
And the "Jump to..." select box should contain "Lesson 1 (hidden)"
|
||||
# Jump to a hidden activity somewhere in the middle.
|
||||
When I select "Assignment 1 (hidden)" from the "Jump to..." singleselect
|
||||
Then I should see "Assignment 1"
|
||||
And I should see "Forum 1" in the "#prev-activity-link" "css_element"
|
||||
And I should see "Lesson 1 (hidden)" in the "#next-activity-link" "css_element"
|
||||
# Jump to the first activity.
|
||||
And I select "Forum 1" from the "Jump to..." singleselect
|
||||
And I should see "Assignment 1 (hidden)" in the "#next-activity-link" "css_element"
|
||||
But "#prev-activity-link" "css_element" should not exist
|
||||
# Jump to the last activity.
|
||||
And I select "Lesson 1 (hidden)" from the "Jump to..." singleselect
|
||||
And I should see "Assignment 1 (hidden)" in the "#prev-activity-link" "css_element"
|
||||
But "#next-activity-link" "css_element" should not exist
|
||||
|
||||
Scenario: The activity navigation controls are not available as a student.
|
||||
Scenario: The activity navigation controls are available as a student
|
||||
Given I log in as "student1"
|
||||
And I am on "Course 1" course homepage
|
||||
# The first activity won't have the previous activity link.
|
||||
Then "#prev-activity-link" "css_element" should not exist
|
||||
And "#next-activity-link" "css_element" should not exist
|
||||
And "Jump to..." "field" should not exist
|
||||
And "#next-activity-link" "css_element" should exist
|
||||
And "Jump to..." "field" should exist
|
||||
|
||||
Scenario: The activity navigation asks for login to guest user
|
||||
Given I log in as "guest"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
@format @format_singleactivity
|
||||
@format @format_singleactivity @block_site_main_menu
|
||||
Feature: Courses can be created in Single Activity mode
|
||||
In order to create a single activity course
|
||||
As a manager
|
||||
I need to create courses and set default values on them
|
||||
|
||||
Scenario: Create a course as a custom course creator
|
||||
Scenario: Create a course using Single Activity format as a custom course creator
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| kevin | Kevin | the | kevin@example.com |
|
||||
@@ -26,14 +26,21 @@ Feature: Courses can be created in Single Activity mode
|
||||
And I press "Add a new course"
|
||||
And I set the following fields to these values:
|
||||
| Course full name | My first course |
|
||||
| Course short name | myfirstcourse |
|
||||
| Format | Single activity |
|
||||
| Course short name | C1 |
|
||||
| Format | Single activity |
|
||||
And I press "Update format"
|
||||
Then I should see "Quiz" in the "Type of activity" "field"
|
||||
And I should see "Forum" in the "Type of activity" "field"
|
||||
# Check that not all the activity types are in the dropdown.
|
||||
And I should not see "Text and media" in the "Type of activity" "field"
|
||||
And I should not see "Subsection" in the "Type of activity" "field"
|
||||
And I set the field "Type of activity" to "Quiz"
|
||||
And I set the field "Type of activity" to "Assignment"
|
||||
And I press "Save and display"
|
||||
And I should see "New Quiz"
|
||||
And I should see "New Assignment"
|
||||
And I set the field "Assignment name" to "My assignment"
|
||||
And I press "Save and return to course"
|
||||
And the following "blocks" exist:
|
||||
| blockname | contextlevel | reference | pagetypepattern | defaultregion |
|
||||
| site_main_menu | Course | C1 | * | site-pre |
|
||||
And I should see "My first course" in the "page-header" "region"
|
||||
And I should see "My assignment" in the "Additional activities" "block"
|
||||
|
||||
@@ -1,26 +1,67 @@
|
||||
@format @format_singleactivity
|
||||
@format @format_singleactivity @block_site_main_menu
|
||||
Feature: Edit format course to Single Activity format
|
||||
In order to set the format course to single activity course
|
||||
As a teacher
|
||||
I need to edit the course settings and see the dropdown type activity
|
||||
|
||||
Scenario: Edit a format course as a teacher
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | summary | format |
|
||||
| Course 1 | C1 | <p>Course summary</p> | topics |
|
||||
| fullname | shortname | format | activitytype |
|
||||
| Course 1 | C1 | singleactivity | assign |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | section |
|
||||
| assign | Assignment 1 | Test assignment description | C1 | assign1 | 0 |
|
||||
| forum | Forum 1 | Test forum description | C1 | forum1 | 0 |
|
||||
|
||||
@javascript
|
||||
Scenario: Add subsections and move activities in Single activity course format
|
||||
Given I log in as "teacher1"
|
||||
When I am on "Course 1" course homepage with editing mode on
|
||||
And I click on "Add content" "button" in the ".block_site_main_menu .footer" "css_element"
|
||||
And I click on "Subsection" "link" in the ".dropdown-menu.show" "css_element"
|
||||
Then I should see "New subsection" in the "Additional activities" "block"
|
||||
And I open "Forum 1" actions menu
|
||||
And I click on "Move" "link" in the "Forum 1" activity
|
||||
And I click on "New subsection" "link" in the "Move activity" "dialogue"
|
||||
And I should see "Forum 1" in the "New subsection" "section"
|
||||
|
||||
Scenario: Change activity type in Single activity course format
|
||||
# Navigate to any course page, like groups, to guarantee that Course settings are displayed in boost and classic themes.
|
||||
Given I am on the "Course 1" "groups" page logged in as "teacher1"
|
||||
When I navigate to "Settings" in current page administration
|
||||
# If there is an existing activity, it will be used as main activity.
|
||||
And I set the following fields to these values:
|
||||
| Type of activity | Forum |
|
||||
And I press "Save and display"
|
||||
Then I should see "Test forum description" in the "page-content" "region"
|
||||
# However, if there is no existing activity, the new activity form will be displayed.
|
||||
But I am on the "Course 1" "groups" page logged in as "teacher1"
|
||||
And I navigate to "Settings" in current page administration
|
||||
And I set the following fields to these values:
|
||||
| Type of activity | Quiz |
|
||||
And I press "Save and display"
|
||||
And I should see "New Quiz"
|
||||
|
||||
Scenario: Edit a format course as a teacher
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | summary | format |
|
||||
| Course 2 | C2 | Course summary | topics |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C2 | editingteacher |
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I am on "Course 2" course homepage
|
||||
When I navigate to "Settings" in current page administration
|
||||
And I set the following fields to these values:
|
||||
| Course full name | My first course |
|
||||
| Course short name | myfirstcourse |
|
||||
| Format | Single activity |
|
||||
| Course short name | myfirstcourse |
|
||||
| Format | Single activity |
|
||||
And I press "Update format"
|
||||
Then I should see "Forum" in the "Type of activity" "field"
|
||||
# Check that not all the activity types are in the dropdown.
|
||||
|
||||
@@ -38,7 +38,7 @@ final class format_singleactivity_test extends \advanced_testcase {
|
||||
// Generate a course with two sections (0 and 1) and two modules.
|
||||
$generator = $this->getDataGenerator();
|
||||
$course1 = $generator->create_course(['format' => 'singleactivity']);
|
||||
course_create_sections_if_missing($course1, [0, 1]);
|
||||
course_create_sections_if_missing($course1, [0]);
|
||||
|
||||
$data = (object)['id' => $course1->id];
|
||||
$format = course_get_format($course1);
|
||||
|
||||
+2
-2
@@ -110,8 +110,8 @@ final class get_state_test extends \externallib_advanced_testcase {
|
||||
// User won't see the hidden sections. Remove them from the total.
|
||||
$visiblesections = $visiblesections - count($hiddensections);
|
||||
}
|
||||
if ($format == 'social') {
|
||||
$visiblesections = 1; // But Social format has one section visible.
|
||||
if ($format == 'social' || $format == 'singleactivity') {
|
||||
$visiblesections = 1; // But Social and Single activity formats have only one section visible.
|
||||
}
|
||||
|
||||
// Social course format automatically creates a forum activity.
|
||||
|
||||
@@ -64,11 +64,11 @@ final class state_test extends \advanced_testcase {
|
||||
$this->setAdminUser();
|
||||
$courseformat = course_get_format($course->id);
|
||||
$modinfo = $courseformat->get_modinfo();
|
||||
$issocialformat = $courseformat->get_format() === 'social';
|
||||
$supportsections = $format !== 'social' && $format !== 'singleactivity';
|
||||
|
||||
// Only create activities if the course format is not social.
|
||||
// There's no course home page (and sections) for social course format.
|
||||
if (!$issocialformat || $format == 'theunittest') {
|
||||
if ($supportsections) {
|
||||
// Add some activities to the course.
|
||||
$this->getDataGenerator()->create_module('page', ['course' => $course->id], ['section' => 1,
|
||||
'visible' => 1]);
|
||||
@@ -111,7 +111,7 @@ final class state_test extends \advanced_testcase {
|
||||
$sections = $modinfo->get_section_info_all();
|
||||
|
||||
foreach ($sections as $key => $section) {
|
||||
if (!$issocialformat || $format == 'theunittest') {
|
||||
if ($supportsections) {
|
||||
$this->assertEquals($section->id, $result->course->sectionlist[$key]);
|
||||
if (!empty($section->uservisible)) {
|
||||
$sectionstate = new $sectionclass($courseformat, $section);
|
||||
|
||||
@@ -110,7 +110,9 @@ final class stateactions_test extends \advanced_testcase {
|
||||
private function translate_references(array $references, array $values): array {
|
||||
$result = [];
|
||||
foreach ($values as $value) {
|
||||
$result[] = $references[$value];
|
||||
if (array_key_exists($value, $references)) {
|
||||
$result[] = $references[$value];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
@@ -209,8 +211,13 @@ final class stateactions_test extends \advanced_testcase {
|
||||
): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create a course with 3 sections, 1 of them hidden.
|
||||
$course = $this->create_course($format, 3, [2]);
|
||||
if ($format === 'singleactivity') {
|
||||
// Single activity format does not have sections.
|
||||
$course = $this->create_course($format, 0, []);
|
||||
} else {
|
||||
// Create a course with 3 sections, 1 of them hidden.
|
||||
$course = $this->create_course($format, 3, [2]);
|
||||
}
|
||||
|
||||
$references = $this->course_references($course);
|
||||
|
||||
@@ -226,11 +233,19 @@ final class stateactions_test extends \advanced_testcase {
|
||||
$count++;
|
||||
}
|
||||
|
||||
// Add some activities to the course. One visible and one hidden in both sections 1 and 2.
|
||||
$references["cm0"] = $this->create_activity($course->id, 'assign', 1, true);
|
||||
$references["cm1"] = $this->create_activity($course->id, 'book', 1, false);
|
||||
$references["cm2"] = $this->create_activity($course->id, 'glossary', 2, true);
|
||||
$references["cm3"] = $this->create_activity($course->id, 'page', 2, false);
|
||||
if ($format === 'singleactivity') {
|
||||
// Add some activities to the course. One visible and one hidden in section 0.
|
||||
$references['cm0'] = $this->create_activity($course->id, 'forum', 0, true);
|
||||
$references['cm1'] = $this->create_activity($course->id, 'book', 0, false);
|
||||
} else {
|
||||
// Add some activities to the course. One visible and one hidden in sections 0, 1 and 2.
|
||||
$references['cm0'] = $this->create_activity($course->id, 'forum', 0, true);
|
||||
$references['cm1'] = $this->create_activity($course->id, 'book', 0, false);
|
||||
$references['cm2'] = $this->create_activity($course->id, 'assign', 1, true);
|
||||
$references['cm3'] = $this->create_activity($course->id, 'book', 1, false);
|
||||
$references['cm4'] = $this->create_activity($course->id, 'glossary', 2, true);
|
||||
$references['cm5'] = $this->create_activity($course->id, 'page', 2, false);
|
||||
}
|
||||
|
||||
if ($expectedexception) {
|
||||
$this->expectException(moodle_exception::class);
|
||||
@@ -315,17 +330,23 @@ final class stateactions_test extends \advanced_testcase {
|
||||
* @return array the testing scenarios
|
||||
*/
|
||||
public static function course_state_provider(string $format): array {
|
||||
$expectedexception = ($format === 'singleactivity');
|
||||
$expectedexception = false;
|
||||
|
||||
$cms = ['cm0', 'cm1', 'cm2', 'cm3'];
|
||||
$studentcms = ['cm0', 'cm2'];
|
||||
// All sections and cms that the user can access to.
|
||||
$usersections = ['section0', 'section1', 'section2', 'section3'];
|
||||
|
||||
$studentcms = ['cm0'];
|
||||
if ($format === 'social') {
|
||||
$cms = ['initialcm0', 'cm0', 'cm1', 'cm2', 'cm3'];
|
||||
$studentcms = ['initialcm0', 'cm0'];
|
||||
$usersections = ['section0']; // Social format only uses section 0 (for all users).
|
||||
if ($format === 'singleactivity') {
|
||||
// Single activity format does not have sections.
|
||||
$cms = ['cm0', 'cm1'];
|
||||
$usersections = ['section0'];
|
||||
$studentcms = ['cm0'];
|
||||
} else if ($format === 'social') {
|
||||
// Social format only uses section 0 (for all users).
|
||||
$cms = ['initialcm0', 'cm0', 'cm1', 'cm2', 'cm3', 'cm4', 'cm5'];
|
||||
$studentcms = ['initialcm0', 'cm0', 'cm2'];
|
||||
$usersections = ['section0'];
|
||||
} else {
|
||||
$cms = ['cm0', 'cm1', 'cm2', 'cm3', 'cm4', 'cm5'];
|
||||
$usersections = ['section0', 'section1', 'section2', 'section3'];
|
||||
}
|
||||
|
||||
return [
|
||||
@@ -383,20 +404,23 @@ final class stateactions_test extends \advanced_testcase {
|
||||
* @return array the testing scenarios
|
||||
*/
|
||||
public static function section_state_provider(string $format, string $role): array {
|
||||
// Social format will raise an exception and debug messages because it does not
|
||||
// use sections and it does not provide a renderer.
|
||||
$expectedexception = ($format === 'singleactivity');
|
||||
|
||||
// All sections and cms that the user can access to.
|
||||
$usersections = ['section0', 'section1', 'section2', 'section3'];
|
||||
$usercms = ['cm0', 'cm1', 'cm2', 'cm3'];
|
||||
$usercms = ['cm0', 'cm1', 'cm2', 'cm3', 'cm4', 'cm5'];
|
||||
if ($role == 'student') {
|
||||
$usersections = ['section0', 'section1', 'section3'];
|
||||
$usercms = ['cm0'];
|
||||
$usercms = ['cm0', 'cm2'];
|
||||
}
|
||||
if ($format === 'social') {
|
||||
// Social format only uses section 0 (for all users).
|
||||
$usersections = ['section0'];
|
||||
$usercms = ['initialcm0', ...$usercms];
|
||||
$usersections = ['section0']; // Social format only uses section 0 (for all users).
|
||||
} else if ($format === 'singleactivity') {
|
||||
// Single activity format does not have sections.
|
||||
$usersections = ['section0'];
|
||||
$usercms = ($role == 'student') ? ['cm0'] : ['cm0', 'cm1'];
|
||||
}
|
||||
|
||||
return [
|
||||
@@ -420,9 +444,9 @@ final class stateactions_test extends \advanced_testcase {
|
||||
'expectedresults' => [
|
||||
'course' => [],
|
||||
'section' => array_intersect(['section0'], $usersections),
|
||||
'cm' => ($format == 'social') ? ['initialcm0'] : [],
|
||||
'cm' => array_intersect(['initialcm0', 'cm0', 'cm1'], $usercms),
|
||||
],
|
||||
'expectedexception' => $expectedexception,
|
||||
'expectedexception' => false,
|
||||
],
|
||||
"$role $format section_state visible section" => [
|
||||
'format' => $format,
|
||||
@@ -434,7 +458,7 @@ final class stateactions_test extends \advanced_testcase {
|
||||
'expectedresults' => [
|
||||
'course' => [],
|
||||
'section' => array_intersect(['section1'], $usersections),
|
||||
'cm' => array_intersect(['cm0', 'cm1'], $usercms),
|
||||
'cm' => array_intersect(['cm2', 'cm3'], $usercms),
|
||||
],
|
||||
'expectedexception' => $expectedexception,
|
||||
],
|
||||
@@ -448,7 +472,7 @@ final class stateactions_test extends \advanced_testcase {
|
||||
'expectedresults' => [
|
||||
'course' => [],
|
||||
'section' => array_intersect(['section2'], $usersections),
|
||||
'cm' => array_intersect(['cm2', 'cm3'], $usercms),
|
||||
'cm' => array_intersect(['cm4', 'cm5'], $usercms),
|
||||
],
|
||||
'expectedexception' => $expectedexception,
|
||||
],
|
||||
@@ -462,7 +486,7 @@ final class stateactions_test extends \advanced_testcase {
|
||||
'expectedresults' => [
|
||||
'course' => [],
|
||||
'section' => array_intersect(['section1', 'section3'], $usersections),
|
||||
'cm' => array_intersect(['cm0', 'cm1'], $usercms),
|
||||
'cm' => array_intersect(['cm2', 'cm3'], $usercms),
|
||||
],
|
||||
'expectedexception' => $expectedexception,
|
||||
],
|
||||
@@ -486,7 +510,7 @@ final class stateactions_test extends \advanced_testcase {
|
||||
'expectedresults' => [
|
||||
'course' => [],
|
||||
'section' => array_intersect(['section1', 'section3'], $usersections),
|
||||
'cm' => array_intersect(['cm0', 'cm1'], $usercms),
|
||||
'cm' => array_intersect(['cm2', 'cm3'], $usercms),
|
||||
],
|
||||
'expectedexception' => $expectedexception,
|
||||
],
|
||||
@@ -495,12 +519,12 @@ final class stateactions_test extends \advanced_testcase {
|
||||
'role' => $role,
|
||||
'method' => 'section_state',
|
||||
'params' => [
|
||||
'ids' => ['section3'], 'targetsectionid' => null, 'targetcmid' => 'cm1'
|
||||
'ids' => ['section3'], 'targetsectionid' => null, 'targetcmid' => 'cm3',
|
||||
],
|
||||
'expectedresults' => [
|
||||
'course' => [],
|
||||
'section' => array_intersect(['section3'], $usersections),
|
||||
'cm' => array_intersect(['cm1'], $usercms),
|
||||
'cm' => array_intersect(['cm3'], $usercms),
|
||||
],
|
||||
'expectedexception' => $expectedexception,
|
||||
],
|
||||
@@ -515,16 +539,22 @@ final class stateactions_test extends \advanced_testcase {
|
||||
* @return array the testing scenarios
|
||||
*/
|
||||
public static function cm_state_provider(string $format, string $role): array {
|
||||
$expectedexception = ($format === 'singleactivity');
|
||||
|
||||
// All sections and cms that the user can access to.
|
||||
$usersections = ['section0', 'section1', 'section2', 'section3'];
|
||||
$usercms = ['cm0', 'cm1', 'cm2', 'cm3'];
|
||||
$usercms = ['cm0', 'cm1', 'cm2', 'cm3', 'cm4', 'cm5'];
|
||||
if ($role == 'student') {
|
||||
$usersections = ['section0', 'section1', 'section3'];
|
||||
$usercms = ['cm0'];
|
||||
$usercms = ['cm0', 'cm2'];
|
||||
}
|
||||
if ($format === 'social') {
|
||||
$usercms = ['initialcm0', ...$usercms];
|
||||
$usersections = ['section0']; // Social format only uses section 0 (for all users).
|
||||
} else if ($format === 'singleactivity') {
|
||||
// Single activity format does not have sections.
|
||||
$usersections = ['section0'];
|
||||
$usercms = ($role == 'student') ? ['cm0'] : ['cm0', 'cm1'];
|
||||
}
|
||||
|
||||
return [
|
||||
@@ -547,7 +577,7 @@ final class stateactions_test extends \advanced_testcase {
|
||||
],
|
||||
'expectedresults' => [
|
||||
'course' => [],
|
||||
'section' => array_intersect(['section1'], $usersections),
|
||||
'section' => array_intersect(['section0'], $usersections),
|
||||
'cm' => array_intersect(['cm0'], $usercms),
|
||||
],
|
||||
'expectedexception' => false,
|
||||
@@ -561,7 +591,7 @@ final class stateactions_test extends \advanced_testcase {
|
||||
],
|
||||
'expectedresults' => [
|
||||
'course' => [],
|
||||
'section' => array_intersect(['section1'], $usersections),
|
||||
'section' => array_intersect(['section0'], $usersections),
|
||||
'cm' => array_intersect(['cm1'], $usercms),
|
||||
],
|
||||
'expectedexception' => false,
|
||||
@@ -571,42 +601,42 @@ final class stateactions_test extends \advanced_testcase {
|
||||
'role' => $role,
|
||||
'method' => 'cm_state',
|
||||
'params' => [
|
||||
'ids' => ['cm0', 'cm2'], 'targetsectionid' => null, 'targetcmid' => null
|
||||
'ids' => ['cm2', 'cm4'], 'targetsectionid' => null, 'targetcmid' => null,
|
||||
],
|
||||
'expectedresults' => [
|
||||
'course' => [],
|
||||
'section' => array_intersect(['section1', 'section2'], $usersections),
|
||||
'cm' => array_intersect(['cm0', 'cm2'], $usercms),
|
||||
'cm' => array_intersect(['cm2', 'cm4'], $usercms),
|
||||
],
|
||||
'expectedexception' => false,
|
||||
'expectedexception' => $expectedexception,
|
||||
],
|
||||
"$role $format cm_state using targetsection" => [
|
||||
'format' => $format,
|
||||
'role' => $role,
|
||||
'method' => 'cm_state',
|
||||
'params' => [
|
||||
'ids' => ['cm0'], 'targetsectionid' => 'section2', 'targetcmid' => null
|
||||
'ids' => ['cm2'], 'targetsectionid' => 'section2', 'targetcmid' => null,
|
||||
],
|
||||
'expectedresults' => [
|
||||
'course' => [],
|
||||
'section' => array_intersect(['section1', 'section2'], $usersections),
|
||||
'cm' => array_intersect(['cm0'], $usercms),
|
||||
'cm' => array_intersect(['cm2'], $usercms),
|
||||
],
|
||||
'expectedexception' => ($format === 'singleactivity'),
|
||||
'expectedexception' => $expectedexception,
|
||||
],
|
||||
"$role $format cm_state using targetcm" => [
|
||||
'format' => $format,
|
||||
'role' => $role,
|
||||
'method' => 'cm_state',
|
||||
'params' => [
|
||||
'ids' => ['cm0'], 'targetsectionid' => null, 'targetcmid' => 'cm3'
|
||||
'ids' => ['cm2'], 'targetsectionid' => null, 'targetcmid' => 'cm5',
|
||||
],
|
||||
'expectedresults' => [
|
||||
'course' => [],
|
||||
'section' => array_intersect(['section1', 'section2'], $usersections),
|
||||
'cm' => array_intersect(['cm0', 'cm3'], $usercms),
|
||||
'cm' => array_intersect(['cm2', 'cm5'], $usercms),
|
||||
],
|
||||
'expectedexception' => false,
|
||||
'expectedexception' => $expectedexception,
|
||||
],
|
||||
"$role $format cm_state using an invalid cm" => [
|
||||
'format' => $format,
|
||||
|
||||
@@ -103,12 +103,12 @@ final class permission_test extends advanced_testcase {
|
||||
'format' => 'topics',
|
||||
'expected' => false,
|
||||
],
|
||||
'Format does not support components' => [
|
||||
'Single activity supports subsections too' => [
|
||||
'ismoddisabled' => false,
|
||||
'missingcapability' => false,
|
||||
'isdelegated' => false,
|
||||
'format' => 'singleactivity',
|
||||
'expected' => false,
|
||||
'expected' => true,
|
||||
],
|
||||
'Plugin enabled, with capability, not inside a delegated section' => [
|
||||
'ismoddisabled' => false,
|
||||
@@ -119,4 +119,27 @@ final class permission_test extends advanced_testcase {
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that subsection cannot be added when the course format does not support components.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_can_add_subsection_unsupported_components(
|
||||
): void {
|
||||
global $SITE;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
course_create_sections_if_missing($SITE, [0, 1]);
|
||||
$courseformat = course_get_format($SITE);
|
||||
$targetsection = $courseformat->get_modinfo()->get_section_info(0);
|
||||
|
||||
$user = $this->getDataGenerator()->create_and_enrol($SITE, 'editingteacher');
|
||||
|
||||
$this->setUser($user);
|
||||
$this->assertEquals(false, permission::can_add_subsection($targetsection, (int)$user->id));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user