mirror of
https://github.com/moodle/moodle.git
synced 2025-02-25 20:43:33 +01:00
Merge branch 'MDL-82259-main' of https://github.com/aanabit/moodle
This commit is contained in:
commit
d11eaeefb9
10
.upgradenotes/MDL-82259-2024072314533865.yml
Normal file
10
.upgradenotes/MDL-82259-2024072314533865.yml
Normal file
@ -0,0 +1,10 @@
|
||||
issueNumber: MDL-82259
|
||||
notes:
|
||||
core_course:
|
||||
- message: >-
|
||||
i_open_section_edit_menu(), i_show_section(), i_hide_section(),
|
||||
i_wait_until_section_is_available(),
|
||||
show_section_link_exists(), hide_section_link_exists() and
|
||||
section_exists() functions have been improved to accept not only section
|
||||
number but also section name.
|
||||
type: improved
|
@ -17,6 +17,7 @@
|
||||
namespace core_courseformat\local;
|
||||
|
||||
|
||||
use core_courseformat\sectiondelegatemodule;
|
||||
use course_modinfo;
|
||||
/**
|
||||
* Course module course format actions.
|
||||
@ -26,8 +27,44 @@ use course_modinfo;
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class cmactions extends baseactions {
|
||||
/**
|
||||
* Update a course delegated section linked to the given module.
|
||||
*
|
||||
* @param \stdClass $cm
|
||||
* @param array $sectionfields to change in section database record.
|
||||
* @param bool $rebuildcache If true (default), perform a partial cache purge and rebuild.
|
||||
* @return bool true if any delegated section has been updated, false otherwise.
|
||||
*/
|
||||
protected function update_delegated(
|
||||
\stdClass $cm,
|
||||
array $sectionfields,
|
||||
bool $rebuildcache = true
|
||||
): bool {
|
||||
|
||||
if (!sectiondelegatemodule::has_delegate_class('mod_' . $cm->modname)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Propagate the changes to delegated section.
|
||||
$cminfo = \cm_info::create($cm);
|
||||
if (!$delegatedsection = $cminfo->get_delegated_section_info()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sectionactions = new sectionactions($this->course);
|
||||
$sectionactions->update($delegatedsection, $sectionfields);
|
||||
|
||||
if ($rebuildcache) {
|
||||
course_modinfo::purge_course_section_cache_by_id($cm->course, $delegatedsection->id);
|
||||
rebuild_course_cache($cm->course, false, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename a course module.
|
||||
*
|
||||
* @param int $cmid the course module id.
|
||||
* @param string $name the new name.
|
||||
* @return bool true if the course module was renamed, false otherwise.
|
||||
@ -64,12 +101,16 @@ class cmactions extends baseactions {
|
||||
]
|
||||
);
|
||||
$cm->name = $name;
|
||||
$fields = new \stdClass();
|
||||
$fields->name = $name;
|
||||
|
||||
\core\event\course_module_updated::create_from_cm($cm)->trigger();
|
||||
|
||||
course_modinfo::purge_course_module_cache($cm->course, $cm->id);
|
||||
rebuild_course_cache($cm->course, false, true);
|
||||
|
||||
$this->update_delegated($cm, ['name' => $name]);
|
||||
|
||||
// Modules may add some logic to renaming.
|
||||
$modinfo = get_fast_modinfo($cm->course);
|
||||
\core\di::get(\core\hook\manager::class)->dispatch(
|
||||
@ -87,4 +128,100 @@ class cmactions extends baseactions {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a course module.
|
||||
*
|
||||
* @param int $cmid the course module id.
|
||||
* @param int $visible state of the module
|
||||
* @param int $visibleoncoursepage state of the module on the course page
|
||||
* @param bool $rebuildcache If true (default), perform a partial cache purge and rebuild.
|
||||
* @return bool whether course module was updated
|
||||
*/
|
||||
public function set_visibility(int $cmid, int $visible, int $visibleoncoursepage = 1, bool $rebuildcache = true): bool {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->libdir.'/gradelib.php');
|
||||
require_once($CFG->dirroot.'/calendar/lib.php');
|
||||
|
||||
if (!$cm = get_coursemodule_from_id('', $cmid, 0, false, MUST_EXIST)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create events and propagate visibility to associated grade items if the value has changed.
|
||||
// Only do this if it's changed to avoid accidently overwriting manual showing/hiding of student grades.
|
||||
if ($cm->visible == $visible && $cm->visibleoncoursepage == $visibleoncoursepage) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$modulename = $DB->get_field('modules', 'name', ['id' => $cm->module])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Updating visible and visibleold to keep them in sync. Only changing a section visibility will
|
||||
// affect visibleold to allow for an original visibility restore. See set_section_visible().
|
||||
$cminfo = (object)[
|
||||
'id' => $cmid,
|
||||
'visible' => $visible,
|
||||
'visibleoncoursepage' => $visibleoncoursepage,
|
||||
'visibleold' => $visible,
|
||||
];
|
||||
|
||||
$DB->update_record('course_modules', $cminfo);
|
||||
$DB->update_record(
|
||||
$cm->modname,
|
||||
(object)[
|
||||
'id' => $cm->instance,
|
||||
'timemodified' => time(),
|
||||
]
|
||||
);
|
||||
|
||||
$fields = ['visible' => $visible, 'visibleold' => $visible];
|
||||
$this->update_delegated($cm, $fields, false);
|
||||
|
||||
if ($rebuildcache) {
|
||||
\course_modinfo::purge_course_module_cache($cm->course, $cm->id);
|
||||
rebuild_course_cache($cm->course, false, true);
|
||||
}
|
||||
|
||||
if ($cm->visible == $visible) {
|
||||
// There is nothing else to change.
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($events = $DB->get_records('event', ['instance' => $cm->instance, 'modulename' => $modulename])) {
|
||||
foreach ($events as $event) {
|
||||
if ($visible) {
|
||||
$event = new \calendar_event($event);
|
||||
$event->toggle_visibility(true);
|
||||
} else {
|
||||
$event = new \calendar_event($event);
|
||||
$event->toggle_visibility(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hide the associated grade items so the teacher doesn't also have to go to the gradebook and hide them there.
|
||||
// Note that this must be done after updating the row in course_modules, in case
|
||||
// the modules grade_item_update function needs to access $cm->visible.
|
||||
$supportsgrade = plugin_supports('mod', $modulename, FEATURE_CONTROLS_GRADE_VISIBILITY) &&
|
||||
component_callback_exists('mod_' . $modulename, 'grade_item_update');
|
||||
if ($supportsgrade) {
|
||||
$instance = $DB->get_record($modulename, ['id' => $cm->instance], '*', MUST_EXIST);
|
||||
component_callback('mod_' . $modulename, 'grade_item_update', [$instance]);
|
||||
} else {
|
||||
$gradeitems = \grade_item::fetch_all([
|
||||
'itemtype' => 'mod',
|
||||
'itemmodule' => $modulename,
|
||||
'iteminstance' => $cm->instance,
|
||||
'courseid' => $cm->course,
|
||||
]);
|
||||
if ($gradeitems) {
|
||||
foreach ($gradeitems as $gradeitem) {
|
||||
$gradeitem->set_hidden(!$visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -404,6 +404,18 @@ class sectionactions extends baseactions {
|
||||
|
||||
$modules = explode(',', $sectioninfo->sequence);
|
||||
$cmids = [];
|
||||
|
||||
// In case the section is delegated by a module, we change also the visibility for the source module.
|
||||
if ($sectioninfo->is_delegated()) {
|
||||
$delegateinstance = $sectioninfo->get_component_instance();
|
||||
// We only return sections delegated by course modules. Sections delegated to other
|
||||
// types of components must implement their own methods to get the section.
|
||||
if ($delegateinstance && ($delegateinstance instanceof \core_courseformat\sectiondelegatemodule)) {
|
||||
$delegator = $delegateinstance->get_cm();
|
||||
$modules[] = $delegator->id;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($modules as $moduleid) {
|
||||
$cm = get_coursemodule_from_id(null, $moduleid, $this->course->id);
|
||||
if (!$cm) {
|
||||
|
@ -121,6 +121,52 @@ class delegatedcontrolmenu extends basecontrolmenu {
|
||||
];
|
||||
}
|
||||
|
||||
// Hide/Show uses module functionality.
|
||||
// Hide/Show options will be available for subsections inside visible sections only.
|
||||
$parentsection = $cm->get_section_info();
|
||||
$availablevisibility = has_capability('moodle/course:sectionvisibility', $coursecontext, $user) && $parentsection->visible;
|
||||
if ($availablevisibility) {
|
||||
$url = clone($baseurl);
|
||||
if (!is_null($sectionreturn)) {
|
||||
$url->param('sr', $format->get_sectionid());
|
||||
}
|
||||
$strhidefromothers = get_string('hidefromothers', 'format_' . $course->format);
|
||||
$strshowfromothers = get_string('showfromothers', 'format_' . $course->format);
|
||||
if ($section->visible) { // Show the hide/show eye.
|
||||
$url->param('hide', $section->section);
|
||||
$controls['visiblity'] = [
|
||||
'url' => $url,
|
||||
'icon' => 'i/show',
|
||||
'name' => $strhidefromothers,
|
||||
'pixattr' => ['class' => ''],
|
||||
'attr' => [
|
||||
'class' => 'editing_showhide',
|
||||
'data-sectionreturn' => $sectionreturn,
|
||||
'data-action' => ($usecomponents) ? 'sectionHide' : 'hide',
|
||||
'data-id' => $section->id,
|
||||
'data-swapname' => $strshowfromothers,
|
||||
'data-swapicon' => 'i/show',
|
||||
],
|
||||
];
|
||||
} else {
|
||||
$url->param('show', $section->section);
|
||||
$controls['visiblity'] = [
|
||||
'url' => $url,
|
||||
'icon' => 'i/hide',
|
||||
'name' => $strshowfromothers,
|
||||
'pixattr' => ['class' => ''],
|
||||
'attr' => [
|
||||
'class' => 'editing_showhide',
|
||||
'data-sectionreturn' => $sectionreturn,
|
||||
'data-action' => ($usecomponents) ? 'sectionShow' : 'show',
|
||||
'data-id' => $section->id,
|
||||
'data-swapname' => $strhidefromothers,
|
||||
'data-swapicon' => 'i/hide',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Delete deletes the module.
|
||||
// Only show the view link if we are not already in the section view page.
|
||||
if (!$isheadersection && $hasmanageactivities) {
|
||||
|
@ -149,7 +149,7 @@ abstract class sectiondelegatemodule extends sectiondelegate {
|
||||
controlmenu $controlmenu,
|
||||
renderer_base $output,
|
||||
): ?action_menu {
|
||||
$controlmenuclass = $format->get_output_classname('content\\cm\\controlmenu');
|
||||
$controlmenuclass = $format->get_output_classname('content\\cm\\delegatedcontrolmenu');
|
||||
$controlmenu = new $controlmenuclass(
|
||||
$format,
|
||||
$this->sectioninfo,
|
||||
|
@ -542,8 +542,18 @@ class stateactions {
|
||||
course_modinfo::purge_course_modules_cache($course->id, $ids);
|
||||
rebuild_course_cache($course->id, false, true);
|
||||
|
||||
$delegatedsections = [];
|
||||
foreach ($cms as $cm) {
|
||||
$updates->add_cm_put($cm->id);
|
||||
if (!$delegatedsection = $cm->get_delegated_section_info()) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($delegatedsection->id, $delegatedsections)) {
|
||||
$delegatedsections[] = $delegatedsection->id;
|
||||
}
|
||||
}
|
||||
foreach ($delegatedsections as $sectionid => $section) {
|
||||
$updates->add_section_put($sectionid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"menu": "<a href=\"#\" class=\"d-inline-block dropdown-toggle icon-no-margin\">Edit<b class=\"caret\"></b></a>",
|
||||
"menu": "<a href=\"#\" data-toggle=\"dropdown\" class=\"d-inline-block dropdown-toggle icon-no-margin\">Edit<b class=\"caret\"></b></a>",
|
||||
"hasmenu": true
|
||||
}
|
||||
}}
|
||||
|
@ -679,74 +679,15 @@ function set_downloadcontent(int $id, bool $downloadcontent): bool {
|
||||
* and rebuilt as appropriate. Consider using this if set_coursemodule_visible is called multiple times
|
||||
* (e.g. in a loop).
|
||||
*
|
||||
* @param int $id of the module
|
||||
* @param int $cmid course module id
|
||||
* @param int $visible state of the module
|
||||
* @param int $visibleoncoursepage state of the module on the course page
|
||||
* @param bool $rebuildcache If true (default), perform a partial cache purge and rebuild.
|
||||
* @return bool false when the module was not found, true otherwise
|
||||
*/
|
||||
function set_coursemodule_visible($id, $visible, $visibleoncoursepage = 1, bool $rebuildcache = true) {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->libdir.'/gradelib.php');
|
||||
require_once($CFG->dirroot.'/calendar/lib.php');
|
||||
|
||||
if (!$cm = $DB->get_record('course_modules', array('id'=>$id))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create events and propagate visibility to associated grade items if the value has changed.
|
||||
// Only do this if it's changed to avoid accidently overwriting manual showing/hiding of student grades.
|
||||
if ($cm->visible == $visible && $cm->visibleoncoursepage == $visibleoncoursepage) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$modulename = $DB->get_field('modules', 'name', array('id'=>$cm->module))) {
|
||||
return false;
|
||||
}
|
||||
if (($cm->visible != $visible) &&
|
||||
($events = $DB->get_records('event', array('instance' => $cm->instance, 'modulename' => $modulename)))) {
|
||||
foreach($events as $event) {
|
||||
if ($visible) {
|
||||
$event = new calendar_event($event);
|
||||
$event->toggle_visibility(true);
|
||||
} else {
|
||||
$event = new calendar_event($event);
|
||||
$event->toggle_visibility(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Updating visible and visibleold to keep them in sync. Only changing a section visibility will
|
||||
// affect visibleold to allow for an original visibility restore. See set_section_visible().
|
||||
$cminfo = new stdClass();
|
||||
$cminfo->id = $id;
|
||||
$cminfo->visible = $visible;
|
||||
$cminfo->visibleoncoursepage = $visibleoncoursepage;
|
||||
$cminfo->visibleold = $visible;
|
||||
$DB->update_record('course_modules', $cminfo);
|
||||
|
||||
// Hide the associated grade items so the teacher doesn't also have to go to the gradebook and hide them there.
|
||||
// Note that this must be done after updating the row in course_modules, in case
|
||||
// the modules grade_item_update function needs to access $cm->visible.
|
||||
if ($cm->visible != $visible &&
|
||||
plugin_supports('mod', $modulename, FEATURE_CONTROLS_GRADE_VISIBILITY) &&
|
||||
component_callback_exists('mod_' . $modulename, 'grade_item_update')) {
|
||||
$instance = $DB->get_record($modulename, array('id' => $cm->instance), '*', MUST_EXIST);
|
||||
component_callback('mod_' . $modulename, 'grade_item_update', array($instance));
|
||||
} else if ($cm->visible != $visible) {
|
||||
$grade_items = grade_item::fetch_all(array('itemtype'=>'mod', 'itemmodule'=>$modulename, 'iteminstance'=>$cm->instance, 'courseid'=>$cm->course));
|
||||
if ($grade_items) {
|
||||
foreach ($grade_items as $grade_item) {
|
||||
$grade_item->set_hidden(!$visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($rebuildcache) {
|
||||
\course_modinfo::purge_course_module_cache($cm->course, $cm->id);
|
||||
rebuild_course_cache($cm->course, false, true);
|
||||
}
|
||||
return true;
|
||||
function set_coursemodule_visible($cmid, $visible, $visibleoncoursepage = 1, bool $rebuildcache = true) {
|
||||
$coursecontext = context_module::instance($cmid)->get_course_context();
|
||||
return formatactions::cm($coursecontext->instanceid)->set_visibility($cmid, $visible, $visibleoncoursepage, $rebuildcache);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -305,26 +305,26 @@ class behat_course extends behat_base {
|
||||
/**
|
||||
* Opens a section edit menu if it is not already opened.
|
||||
*
|
||||
* @Given /^I open section "(?P<section_number>\d+)" edit menu$/
|
||||
* @Given /^I open section "(?P<section>(?:[^"]|\\")*)" edit menu$/
|
||||
* @throws DriverException The step is not available when Javascript is disabled
|
||||
* @param string $sectionnumber
|
||||
* @param string|int $section
|
||||
*/
|
||||
public function i_open_section_edit_menu($sectionnumber) {
|
||||
public function i_open_section_edit_menu($section) {
|
||||
if (!$this->running_javascript()) {
|
||||
throw new DriverException('Section edit menu not available when Javascript is disabled');
|
||||
}
|
||||
|
||||
// Wait for section to be available, before clicking on the menu.
|
||||
$this->i_wait_until_section_is_available($sectionnumber);
|
||||
$this->i_wait_until_section_is_available($section);
|
||||
|
||||
// If it is already opened we do nothing.
|
||||
$xpath = $this->section_exists($sectionnumber);
|
||||
$xpath .= "/descendant::div[contains(@class, 'section-actions')]/descendant::a[contains(@data-toggle, 'dropdown')]";
|
||||
$xpath = $this->section_exists($section);
|
||||
$xpath .= "/descendant::div[contains(@class, 'section-actions')]/descendant::a[@data-toggle='dropdown']";
|
||||
|
||||
$exception = new ExpectationException('Section "' . $sectionnumber . '" was not found', $this->getSession());
|
||||
$exception = new ExpectationException('Section "' . $section . '" was not found', $this->getSession());
|
||||
$menu = $this->find('xpath', $xpath, $exception);
|
||||
$menu->click();
|
||||
$this->i_wait_until_section_is_available($sectionnumber);
|
||||
$this->i_wait_until_section_is_available($section);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -404,34 +404,45 @@ class behat_course extends behat_base {
|
||||
/**
|
||||
* Shows the specified hidden section. You need to be in the course page and on editing mode.
|
||||
*
|
||||
* @Given /^I show section "(?P<section_number>\d+)"$/
|
||||
* @param int $sectionnumber
|
||||
* @Given /^I show section "(?P<section>(?:[^"]|\\")*)"$/
|
||||
* @param int|string $section
|
||||
*/
|
||||
public function i_show_section($sectionnumber) {
|
||||
$showlink = $this->show_section_link_exists($sectionnumber);
|
||||
public function i_show_section($section) {
|
||||
// Ensures the section exists.
|
||||
$xpath = $this->section_exists($section);
|
||||
// We need to know the course format as the text strings depends on them.
|
||||
$courseformat = $this->get_course_format();
|
||||
$strshow = get_string('showfromothers', $courseformat);
|
||||
|
||||
// Ensure section edit menu is open before interacting with it.
|
||||
|
||||
// If javascript is on, link is inside a menu.
|
||||
if ($this->running_javascript()) {
|
||||
$this->i_open_section_edit_menu($sectionnumber);
|
||||
$this->i_open_section_edit_menu($section);
|
||||
}
|
||||
$showlink->click();
|
||||
|
||||
// Ensure the click is using the action menu and not the visibility badge.
|
||||
$xpath .= "//*[@role='menu']";
|
||||
|
||||
// Click on hide link.
|
||||
$this->execute('behat_general::i_click_on_in_the',
|
||||
[$strshow, "link", $this->escape($xpath), "xpath_element"]
|
||||
);
|
||||
|
||||
if ($this->running_javascript()) {
|
||||
$this->getSession()->wait(self::get_timeout() * 1000, self::PAGE_READY_JS);
|
||||
$this->i_wait_until_section_is_available($sectionnumber);
|
||||
$this->i_wait_until_section_is_available($section);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides the specified visible section. You need to be in the course page and on editing mode.
|
||||
*
|
||||
* @Given /^I hide section "(?P<section_number>\d+)"$/
|
||||
* @param int $sectionnumber
|
||||
* @Given /^I hide section "(?P<section>(?:[^"]|\\")*)"$/
|
||||
* @param int|string $section
|
||||
*/
|
||||
public function i_hide_section($sectionnumber) {
|
||||
public function i_hide_section($section) {
|
||||
// Ensures the section exists.
|
||||
$xpath = $this->section_exists($sectionnumber);
|
||||
|
||||
$xpath = $this->section_exists($section);
|
||||
// We need to know the course format as the text strings depends on them.
|
||||
$courseformat = $this->get_course_format();
|
||||
if (get_string_manager()->string_exists('hidefromothers', $courseformat)) {
|
||||
@ -442,17 +453,17 @@ class behat_course extends behat_base {
|
||||
|
||||
// If javascript is on, link is inside a menu.
|
||||
if ($this->running_javascript()) {
|
||||
$this->i_open_section_edit_menu($sectionnumber);
|
||||
$this->i_open_section_edit_menu($section);
|
||||
}
|
||||
|
||||
// Click on delete link.
|
||||
// Click on hide link.
|
||||
$this->execute('behat_general::i_click_on_in_the',
|
||||
array($strhide, "link", $this->escape($xpath), "xpath_element")
|
||||
);
|
||||
|
||||
if ($this->running_javascript()) {
|
||||
$this->getSession()->wait(self::get_timeout() * 1000, self::PAGE_READY_JS);
|
||||
$this->i_wait_until_section_is_available($sectionnumber);
|
||||
$this->i_wait_until_section_is_available($section);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1234,14 +1245,14 @@ class behat_course extends behat_base {
|
||||
* Hopefully we would not require test writers to use this step
|
||||
* and we will manage it from other step definitions.
|
||||
*
|
||||
* @Given /^I wait until section "(?P<section_number>\d+)" is available$/
|
||||
* @param int $sectionnumber
|
||||
* @Given /^I wait until section "(?P<section>(?:[^"]|\\")*)" is available$/
|
||||
* @param int|string $section
|
||||
* @return void
|
||||
*/
|
||||
public function i_wait_until_section_is_available($sectionnumber) {
|
||||
public function i_wait_until_section_is_available($section) {
|
||||
|
||||
// Looks for a hidden lightbox or a non-existent lightbox in that section.
|
||||
$sectionxpath = $this->section_exists($sectionnumber);
|
||||
$sectionxpath = $this->section_exists($section);
|
||||
$hiddenlightboxxpath = $sectionxpath . "/descendant::div[contains(concat(' ', @class, ' '), ' lightbox ')][contains(@style, 'display: none')]" .
|
||||
" | " .
|
||||
$sectionxpath . "[count(child::div[contains(@class, 'lightbox')]) = 0]";
|
||||
@ -1282,10 +1293,26 @@ class behat_course extends behat_base {
|
||||
* Checks if the course section exists.
|
||||
*
|
||||
* @throws ElementNotFoundException Thrown by behat_base::find
|
||||
* @param int|string $section Section number or name to look for.
|
||||
* @return string The xpath of the section.
|
||||
*/
|
||||
protected function section_exists($section) {
|
||||
|
||||
if (is_numeric($section)) {
|
||||
return $this->section_number_exists($section);
|
||||
}
|
||||
|
||||
return $this->section_name_exists($section);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the course section number exists.
|
||||
*
|
||||
* @throws ElementNotFoundException Thrown by behat_base::find
|
||||
* @param int $sectionnumber
|
||||
* @return string The xpath of the section.
|
||||
*/
|
||||
protected function section_exists($sectionnumber) {
|
||||
protected function section_number_exists(int $sectionnumber): string {
|
||||
|
||||
// Just to give more info in case it does not exist.
|
||||
$xpath = "//li[@id='section-" . $sectionnumber . "']";
|
||||
@ -1295,17 +1322,39 @@ class behat_course extends behat_base {
|
||||
return $xpath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the section name exists.
|
||||
*
|
||||
* @throws ElementNotFoundException Thrown by behat_base::find
|
||||
* @param string $sectionname
|
||||
* @return string The xpath of the section.
|
||||
*/
|
||||
protected function section_name_exists(string $sectionname): string {
|
||||
// Let's try to find section or subsection in course page.
|
||||
$xpath = "//li[@data-for='section']//*[@data-for='section_title' and contains(normalize-space(.), '" . $sectionname ."')]";
|
||||
$exception = new ElementNotFoundException($this->getSession(), "Section $sectionname ");
|
||||
try {
|
||||
$this->find('xpath', $xpath, $exception);
|
||||
} catch (ElementNotFoundException $e) {
|
||||
// Let's try to find section in section page.
|
||||
$xpath = "//header[@id='page-header' and contains(normalize-space(.), '" . $sectionname ."')]";
|
||||
$this->find('xpath', $xpath, $exception);
|
||||
}
|
||||
|
||||
return $xpath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the show section icon or throws an exception.
|
||||
*
|
||||
* @throws ElementNotFoundException Thrown by behat_base::find
|
||||
* @param int $sectionnumber
|
||||
* @param int|string $section Section number or name to look for.
|
||||
* @return NodeElement
|
||||
*/
|
||||
protected function show_section_link_exists($sectionnumber) {
|
||||
protected function show_section_link_exists($section) {
|
||||
|
||||
// Gets the section xpath and ensure it exists.
|
||||
$xpath = $this->section_exists($sectionnumber);
|
||||
$xpath = $this->section_exists($section);
|
||||
|
||||
// We need to know the course format as the text strings depends on them.
|
||||
$courseformat = $this->get_course_format();
|
||||
@ -1324,13 +1373,13 @@ class behat_course extends behat_base {
|
||||
* Returns the hide section icon link if it exists or throws exception.
|
||||
*
|
||||
* @throws ElementNotFoundException Thrown by behat_base::find
|
||||
* @param int $sectionnumber
|
||||
* @param int|string $section Section number or name to look for.
|
||||
* @return NodeElement
|
||||
*/
|
||||
protected function hide_section_link_exists($sectionnumber) {
|
||||
protected function hide_section_link_exists($section) {
|
||||
|
||||
// Gets the section xpath and ensure it exists.
|
||||
$xpath = $this->section_exists($sectionnumber);
|
||||
$xpath = $this->section_exists($section);
|
||||
|
||||
// We need to know the course format as the text strings depends on them.
|
||||
$courseformat = $this->get_course_format();
|
||||
@ -1370,6 +1419,10 @@ class behat_course extends behat_base {
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
if (strstr($bodyid, 'page-course-view-section-') !== false) {
|
||||
return 'format_' . str_replace('page-course-view-section-', '', $bodyid);
|
||||
}
|
||||
|
||||
return 'format_' . str_replace('page-course-view-', '', $bodyid);
|
||||
}
|
||||
|
||||
|
@ -33,10 +33,10 @@ Feature: The module menu replaces the delegated section menu
|
||||
And I should not see "Assign roles"
|
||||
And I should not see "Highlight"
|
||||
And I should see "Edit settings"
|
||||
# Duplicate, Move and Show/Hide are not implemented yet.
|
||||
# Duplicate and Move are not implemented yet.
|
||||
And I should not see "Move"
|
||||
And I should not see "Duplicate"
|
||||
And I should not see "Hide"
|
||||
And I should see "Hide"
|
||||
# Delete option for subsection page is not implemented yet.
|
||||
And I should not see "Delete"
|
||||
And I should see "Permalink"
|
||||
@ -50,12 +50,11 @@ Feature: The module menu replaces the delegated section menu
|
||||
And I should not see "Highlight"
|
||||
And I should see "View"
|
||||
And I should see "Edit settings"
|
||||
# Duplicate, Move and Show/Hide are not implemented yet.
|
||||
# Duplicate and Move are not implemented yet.
|
||||
And I should not see "Move"
|
||||
And I should not see "Duplicate"
|
||||
And I should not see "Hide"
|
||||
And I should see "Hide"
|
||||
And I should see "Delete"
|
||||
And I should see "Permalink"
|
||||
|
||||
@javascript
|
||||
Scenario: The action menu for subsection module in section page has less options than a regular activity
|
||||
@ -67,10 +66,10 @@ Feature: The module menu replaces the delegated section menu
|
||||
And I should not see "Highlight"
|
||||
And I should see "View"
|
||||
And I should see "Edit settings"
|
||||
# Duplicate, Move and Show/Hide are not implemented yet.
|
||||
# Duplicate and Move are not implemented yet.
|
||||
And I should not see "Move"
|
||||
And I should not see "Duplicate"
|
||||
And I should not see "Hide"
|
||||
And I should see "Hide"
|
||||
And I should see "Delete"
|
||||
And I should see "Permalink"
|
||||
|
||||
@ -157,3 +156,54 @@ Feature: The module menu replaces the delegated section menu
|
||||
# Subsection page. Open the section header action menu.
|
||||
And I click on "Edit" "icon" in the "[data-region='header-actions-container']" "css_element"
|
||||
And "Delete" "link" should not exist in the "[data-region='header-actions-container']" "css_element"
|
||||
|
||||
@javascript
|
||||
Scenario: Hide/Show option in subsection action menu
|
||||
Given I turn editing mode on
|
||||
And I should not see "Hidden from students"
|
||||
And I open "Subsection1" actions menu
|
||||
When I choose "Hide" in the open action menu
|
||||
Then I should see "Hidden from students"
|
||||
Given I am on the "C1 > Subsection1" "course > section" page
|
||||
And I should see "Hidden from students"
|
||||
# Subsection page. Open the section header action menu.
|
||||
And I click on "Edit" "icon" in the "[data-region='header-actions-container']" "css_element"
|
||||
And I choose "Show" in the open action menu
|
||||
And I should not see "Hidden from students"
|
||||
And I click on "Section 1" "link" in the ".breadcrumb" "css_element"
|
||||
And I should not see "Hidden from students"
|
||||
# Section page. Open Subsection1 module action menu.
|
||||
And I open "Subsection1" actions menu
|
||||
And I choose "Hide" in the open action menu
|
||||
And I should see "Hidden from students"
|
||||
|
||||
@javascript
|
||||
Scenario: Hide/Show option in course page action menu for subsections
|
||||
Given I am on the "C1" "Course" page
|
||||
And I turn editing mode on
|
||||
When I hide section "Subsection1"
|
||||
Then I should see "Hidden from students"
|
||||
And I show section "Subsection1"
|
||||
And I should not see "Hidden from students"
|
||||
|
||||
@javascript
|
||||
Scenario: Hide/Show option in subsection page action menu for subsections
|
||||
Given I am on the "C1 > Subsection1" "course > section" page
|
||||
And I turn editing mode on
|
||||
When I hide section "Subsection1"
|
||||
Then I should see "Hidden from students"
|
||||
And I show section "Subsection1"
|
||||
And I should not see "Hidden from students"
|
||||
|
||||
@javascript
|
||||
Scenario: Subsections can't change visibility in hidden sections.
|
||||
Given I am on the "C1" "Course" page
|
||||
And I turn editing mode on
|
||||
And I hide section "Section 1"
|
||||
When I open section "Subsection1" edit menu
|
||||
Then I should not see "Hide"
|
||||
And I should not see "Show"
|
||||
And I am on the "C1 > Section 1" "course > section" page
|
||||
And I open section "Subsection1" edit menu
|
||||
And I should not see "Hide"
|
||||
And I should not see "Show"
|
||||
|
@ -66,7 +66,7 @@ final class sectiondelegate_test extends \advanced_testcase {
|
||||
|
||||
// Highlight is only present in section menu (not module), so they shouldn't be found in the result.
|
||||
// Duplicate is not implemented yet, so they shouldn't be found in the result.
|
||||
// The possible options are: View, Edit, Delete and Permalink.
|
||||
// The possible options are: View, Edit, Show, Hide, Delete and Permalink.
|
||||
if (get_string_manager()->string_exists('editsection', 'format_'.$format->get_format())) {
|
||||
$streditsection = get_string('editsection', 'format_'.$format->get_format());
|
||||
} else {
|
||||
@ -75,9 +75,12 @@ final class sectiondelegate_test extends \advanced_testcase {
|
||||
$allowedoptions = [
|
||||
get_string('view'),
|
||||
$streditsection,
|
||||
get_string('hidefromothers', 'format_' . $course->format),
|
||||
get_string('showfromothers', 'format_' . $course->format),
|
||||
get_string('delete'),
|
||||
get_string('sectionlink', 'course'),
|
||||
];
|
||||
|
||||
// The default section menu should be different for the delegated section menu.
|
||||
$result = $delegated->get_section_action_menu($format, $controlmenu, $renderer);
|
||||
foreach ($result->get_secondary_actions() as $secondaryaction) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user