Merge branch 'wip-MDL-4782-master-3' of https://github.com/marinaglancy/moodle
This commit is contained in:
+2
-1
@@ -291,6 +291,7 @@
|
||||
<FIELD NAME="score" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
<FIELD NAME="indent" TYPE="int" LENGTH="5" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
<FIELD NAME="visible" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
|
||||
<FIELD NAME="visibleoncoursepage" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="If stealth visibility is allowed for the course, this controls whether activity is visible on course page"/>
|
||||
<FIELD NAME="visibleold" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
|
||||
<FIELD NAME="groupmode" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
<FIELD NAME="groupingid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
@@ -3442,4 +3443,4 @@
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
</TABLES>
|
||||
</XMLDB>
|
||||
</XMLDB>
|
||||
|
||||
@@ -250,6 +250,30 @@ $functions = array(
|
||||
'type' => 'read',
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
|
||||
),
|
||||
'core_course_get_module' => array(
|
||||
'classname' => 'core_course_external',
|
||||
'methodname' => 'get_module',
|
||||
'classpath' => 'course/externallib.php',
|
||||
'description' => 'Returns html with one activity module on course page',
|
||||
'type' => 'read',
|
||||
'ajax' => true,
|
||||
),
|
||||
'core_course_edit_module' => array(
|
||||
'classname' => 'core_course_external',
|
||||
'methodname' => 'edit_module',
|
||||
'classpath' => 'course/externallib.php',
|
||||
'description' => 'Performs an action on course module (change visibility, duplicate, delete, etc.)',
|
||||
'type' => 'write',
|
||||
'ajax' => true,
|
||||
),
|
||||
'core_course_edit_section' => array(
|
||||
'classname' => 'core_course_external',
|
||||
'methodname' => 'edit_section',
|
||||
'classpath' => 'course/externallib.php',
|
||||
'description' => 'Performs an action on course section (change visibility, set marker, delete)',
|
||||
'type' => 'write',
|
||||
'ajax' => true,
|
||||
),
|
||||
'core_course_get_courses' => array(
|
||||
'classname' => 'core_course_external',
|
||||
'methodname' => 'get_courses',
|
||||
|
||||
@@ -2541,5 +2541,19 @@ function xmldb_main_upgrade($oldversion) {
|
||||
upgrade_main_savepoint(true, 2017021300.00);
|
||||
}
|
||||
|
||||
if ($oldversion < 2017021400.00) {
|
||||
// Define field visibleoncoursepage to be added to course_modules.
|
||||
$table = new xmldb_table('course_modules');
|
||||
$field = new xmldb_field('visibleoncoursepage', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'visible');
|
||||
|
||||
// Conditionally launch add field visibleoncoursepage.
|
||||
if (!$dbman->field_exists($table, $field)) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2017021400.00);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+77
-7
@@ -40,6 +40,15 @@ require_once "$CFG->libdir/form/select.php";
|
||||
*/
|
||||
class MoodleQuickForm_modvisible extends MoodleQuickForm_select{
|
||||
|
||||
/** @var int activity state: visible=0, visibleoncoursepage=any */
|
||||
const HIDE = 0;
|
||||
|
||||
/** @var int activity state: visible=1, visibleoncoursepage=1 */
|
||||
const SHOW = 1;
|
||||
|
||||
/** @var int activity state: visible=1, visibleoncoursepage=0 */
|
||||
const STEALTH = -1;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
@@ -49,8 +58,7 @@ class MoodleQuickForm_modvisible extends MoodleQuickForm_select{
|
||||
* @param array $options ignored
|
||||
*/
|
||||
public function __construct($elementName=null, $elementLabel=null, $attributes=null, $options=null) {
|
||||
// TODO MDL-52313 Replace with the call to parent::__construct().
|
||||
HTML_QuickForm_element::__construct($elementName, $elementLabel, $attributes, null);
|
||||
parent::__construct($elementName, $elementLabel, null, $attributes);
|
||||
$this->_type = 'modvisible';
|
||||
}
|
||||
|
||||
@@ -72,17 +80,79 @@ class MoodleQuickForm_modvisible extends MoodleQuickForm_select{
|
||||
* @param object $caller calling object
|
||||
* @return bool
|
||||
*/
|
||||
function onQuickFormEvent($event, $arg, &$caller)
|
||||
{
|
||||
public function onQuickFormEvent($event, $arg, &$caller) {
|
||||
switch ($event) {
|
||||
case 'createElement':
|
||||
$choices=array();
|
||||
$choices[1] = get_string('show');
|
||||
$choices[0] = get_string('hide');
|
||||
$options = is_array($arg[3]) ? $arg[3] : [];
|
||||
$sectionvisible = array_key_exists('sectionvisible', $options) ? $options['sectionvisible'] : 1;
|
||||
$cm = !empty($options['cm']) ? cm_info::create($options['cm']) : null;
|
||||
$choices = array();
|
||||
if (!$sectionvisible) {
|
||||
// If section is not visible the activity is hidden by default but it can also be made available.
|
||||
$choices[self::HIDE] = get_string('hiddenfromstudents');
|
||||
if (!$cm || $cm->has_view()) {
|
||||
$choices[self::SHOW] = get_string('hiddenoncoursepage');
|
||||
}
|
||||
} else if (!empty($options['allowstealth']) && (!$cm || $cm->has_view())) {
|
||||
// If allowed in this course/section, add a third visibility option
|
||||
// "Available but not displayed on course page".
|
||||
$choices[self::SHOW] = get_string('show');
|
||||
$choices[self::HIDE] = get_string('hiddenfromstudents');
|
||||
$choices[self::STEALTH] = get_string('hiddenoncoursepage');
|
||||
} else {
|
||||
// In the visible section without "stealth" activities allowed it's just "Show" or "Hide".
|
||||
$choices[self::SHOW] = get_string('show');
|
||||
$choices[self::HIDE] = get_string('hide');
|
||||
}
|
||||
$this->load($choices);
|
||||
break;
|
||||
case 'updateValue':
|
||||
// Given two bool values of 'visible' and 'visibleoncoursepage' convert to a single
|
||||
// three-state value (show, hide, hide-on-course-page).
|
||||
$name = $this->getName();
|
||||
$value = $this->_findValue($caller->_constantValues);
|
||||
if (!empty($value) && isset($caller->_constantValues[$name.'oncoursepage']) &&
|
||||
!$caller->_constantValues[$name.'oncoursepage']) {
|
||||
$value = self::STEALTH;
|
||||
}
|
||||
if (null === $value) {
|
||||
if ($caller->isSubmitted()) {
|
||||
break;
|
||||
}
|
||||
$value = $this->_findValue($caller->_defaultValues);
|
||||
if (!empty($value) && isset($caller->_defaultValues[$name.'oncoursepage']) &&
|
||||
!$caller->_defaultValues[$name.'oncoursepage']) {
|
||||
$value = self::STEALTH;
|
||||
}
|
||||
}
|
||||
if ($value !== null) {
|
||||
$this->setSelected($value);
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
return parent::onQuickFormEvent($event, $arg, $caller);
|
||||
}
|
||||
|
||||
/**
|
||||
* As usual, to get the group's value we access its elements and call
|
||||
* their exportValue() methods
|
||||
*
|
||||
* @param array $submitvalues submitted values
|
||||
* @param bool $assoc if true the retured value is associated array
|
||||
* @return mixed
|
||||
*/
|
||||
public function exportValue(&$submitvalues, $assoc = false) {
|
||||
if ($assoc) {
|
||||
$value = parent::exportValue($submitvalues, $assoc);
|
||||
$key = key($value);
|
||||
$v = $value[$key];
|
||||
// Convert three-state dropdown value (show, hide, hide-on-course-page) into the array of two bool values:
|
||||
// array('visible' => x, 'visibleoncoursepage' => y).
|
||||
return array($key => ($v == self::HIDE ? 0 : 1),
|
||||
$key . 'oncoursepage' => ($v == self::STEALTH ? 0 : 1));
|
||||
} else {
|
||||
return parent::exportValue($submitvalues, $assoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+66
-2
@@ -690,6 +690,8 @@ class course_modinfo {
|
||||
* @property-read int $added Time that this course-module was added (unix time) - from course_modules table
|
||||
* @property-read int $visible Visible setting (0 or 1; if this is 0, students cannot see/access the activity) - from
|
||||
* course_modules table
|
||||
* @property-read int $visibleoncoursepage Visible on course page setting - from course_modules table, adjusted to
|
||||
* whether course format allows this module to have the "stealth" mode
|
||||
* @property-read int $visibleold Old visible setting (if the entire section is hidden, the previous value for
|
||||
* visible is stored in this field) - from course_modules table
|
||||
* @property-read int $groupmode Group mode (one of the constants NOGROUPS, SEPARATEGROUPS, or VISIBLEGROUPS) - from
|
||||
@@ -833,6 +835,12 @@ class cm_info implements IteratorAggregate {
|
||||
*/
|
||||
private $visible;
|
||||
|
||||
/**
|
||||
* Visible on course page setting - from course_modules table
|
||||
* @var int
|
||||
*/
|
||||
private $visibleoncoursepage;
|
||||
|
||||
/**
|
||||
* Old visible setting (if the entire section is hidden, the previous value for
|
||||
* visible is stored in this field) - from course_modules table
|
||||
@@ -998,6 +1006,12 @@ class cm_info implements IteratorAggregate {
|
||||
*/
|
||||
private $uservisible;
|
||||
|
||||
/**
|
||||
* True if this course-module is visible to the CURRENT user on the course page
|
||||
* @var bool
|
||||
*/
|
||||
private $uservisibleoncoursepage;
|
||||
|
||||
/**
|
||||
* @var moodle_url
|
||||
*/
|
||||
@@ -1093,6 +1107,7 @@ class cm_info implements IteratorAggregate {
|
||||
'showdescription' => false,
|
||||
'uservisible' => 'get_user_visible',
|
||||
'visible' => false,
|
||||
'visibleoncoursepage' => false,
|
||||
'visibleold' => false,
|
||||
'deletioninprogress' => false
|
||||
);
|
||||
@@ -1388,7 +1403,8 @@ class cm_info implements IteratorAggregate {
|
||||
*/
|
||||
public function get_grouping_label($textclasses = '') {
|
||||
$groupinglabel = '';
|
||||
if (!empty($this->groupingid) && has_capability('moodle/course:managegroups', context_course::instance($this->course))) {
|
||||
if ($this->effectivegroupmode != NOGROUPS && !empty($this->groupingid) &&
|
||||
has_capability('moodle/course:managegroups', context_course::instance($this->course))) {
|
||||
$groupings = groups_get_all_groupings($this->course);
|
||||
$groupinglabel = html_writer::tag('span', '('.format_string($groupings[$this->groupingid]->name).')',
|
||||
array('class' => 'groupinglabel '.$textclasses));
|
||||
@@ -1427,6 +1443,15 @@ class cm_info implements IteratorAggregate {
|
||||
return $this->modinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the section this module belongs to
|
||||
*
|
||||
* @return section_info
|
||||
*/
|
||||
public function get_section_info() {
|
||||
return $this->modinfo->get_section_info($this->sectionnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns course object that was used in the first {@link get_fast_modinfo()} call.
|
||||
*
|
||||
@@ -1509,7 +1534,7 @@ class cm_info implements IteratorAggregate {
|
||||
|
||||
// Standard fields from table course_modules.
|
||||
static $cmfields = array('id', 'course', 'module', 'instance', 'section', 'idnumber', 'added',
|
||||
'score', 'indent', 'visible', 'visibleold', 'groupmode', 'groupingid',
|
||||
'score', 'indent', 'visible', 'visibleoncoursepage', 'visibleold', 'groupmode', 'groupingid',
|
||||
'completion', 'completiongradeitemnumber', 'completionview', 'completionexpected',
|
||||
'showdescription', 'availability', 'deletioninprogress');
|
||||
foreach ($cmfields as $key) {
|
||||
@@ -1685,6 +1710,7 @@ class cm_info implements IteratorAggregate {
|
||||
$this->idnumber = isset($mod->idnumber) ? $mod->idnumber : '';
|
||||
$this->name = $mod->name;
|
||||
$this->visible = $mod->visible;
|
||||
$this->visibleoncoursepage = $mod->visibleoncoursepage;
|
||||
$this->sectionnum = $mod->section; // Note weirdness with name here
|
||||
$this->groupmode = isset($mod->groupmode) ? $mod->groupmode : 0;
|
||||
$this->groupingid = isset($mod->groupingid) ? $mod->groupingid : 0;
|
||||
@@ -1823,6 +1849,34 @@ class cm_info implements IteratorAggregate {
|
||||
return $this->uservisible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this module is visible to the current user on course page
|
||||
*
|
||||
* Activity may be visible on the course page but not available, for example
|
||||
* when it is hidden conditionally but the condition information is displayed.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_visible_on_course_page() {
|
||||
$this->obtain_dynamic_data();
|
||||
return $this->uservisibleoncoursepage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this module is available but hidden from course page
|
||||
*
|
||||
* "Stealth" modules are the ones that are not shown on course page but available by following url.
|
||||
* They are normally also displayed in grade reports and other reports.
|
||||
* Module will be stealth either if visibleoncoursepage=0 or it is a visible module inside the hidden
|
||||
* section.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_stealth() {
|
||||
return !$this->visibleoncoursepage ||
|
||||
($this->visible && ($section = $this->get_section_info()) && !$section->visible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter method for property $available, ensures that dynamic data is retrieved
|
||||
* @return bool
|
||||
@@ -1889,6 +1943,16 @@ class cm_info implements IteratorAggregate {
|
||||
// Ensure activity is completely hidden from the user.
|
||||
$this->availableinfo = '';
|
||||
}
|
||||
|
||||
$this->uservisibleoncoursepage = $this->uservisible &&
|
||||
($this->visibleoncoursepage ||
|
||||
has_capability('moodle/course:manageactivities', $this->get_context(), $userid) ||
|
||||
has_capability('moodle/course:activityvisibility', $this->get_context(), $userid));
|
||||
// Activity that is not available, not hidden from course page and has availability
|
||||
// info is actually visible on the course page (with availability info and without a link).
|
||||
if (!$this->uservisible && $this->visibleoncoursepage && $this->availableinfo) {
|
||||
$this->uservisibleoncoursepage = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-1
@@ -2893,7 +2893,8 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $
|
||||
} else {
|
||||
$url = new moodle_url('/');
|
||||
}
|
||||
redirect($url, get_string('activityiscurrentlyhidden'));
|
||||
redirect($url, get_string('activityiscurrentlyhidden'), null,
|
||||
\core\output\notification::NOTIFY_ERROR);
|
||||
}
|
||||
|
||||
// Set the global $COURSE.
|
||||
|
||||
@@ -1991,7 +1991,7 @@ class global_navigation extends navigation_node {
|
||||
$activity->display = false;
|
||||
} else {
|
||||
$activity->url = $url->out();
|
||||
$activity->display = $cm->uservisible ? true : false;
|
||||
$activity->display = $cm->is_visible_on_course_page() ? true : false;
|
||||
if (self::module_extends_navigation($cm->modname)) {
|
||||
$activity->nodetype = navigation_node::NODETYPE_BRANCH;
|
||||
}
|
||||
@@ -2139,7 +2139,7 @@ class global_navigation extends navigation_node {
|
||||
$activitynode = $coursenode->add(format_string($cm->name), $url, navigation_node::TYPE_ACTIVITY, null, $cm->id, $icon);
|
||||
$activitynode->title(get_string('modulename', $cm->modname));
|
||||
$activitynode->hidden = (!$cm->visible);
|
||||
if (!$cm->uservisible) {
|
||||
if (!$cm->is_visible_on_course_page()) {
|
||||
// Do not show any error here, let the page handle exception that activity is not visible for the current user.
|
||||
// Also there may be no exception at all in case when teacher is logged in as student.
|
||||
$activitynode->display = false;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template core/availability_info
|
||||
|
||||
Moodle template for the course or section availability information.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Example context (json):
|
||||
{ "classes": "", "text": "This activity is not available" }
|
||||
}}
|
||||
{{#text}}
|
||||
<div class="availabilityinfo {{classes}}">{{{text}}}</div>
|
||||
{{/text}}
|
||||
@@ -187,6 +187,7 @@ abstract class testing_module_generator extends component_generator_base {
|
||||
$defaults = array(
|
||||
'section' => 0,
|
||||
'visible' => 1,
|
||||
'visibleoncoursepage' => 1,
|
||||
'cmidnumber' => '',
|
||||
'groupmode' => 0,
|
||||
'groupingid' => 0,
|
||||
|
||||
@@ -55,6 +55,13 @@ class behat_action_menu extends behat_base {
|
||||
}
|
||||
// Gets the node based on the requested selector type and locator.
|
||||
$node = $this->get_node_in_container("css_element", "[role=menuitem][aria-haspopup=true]", $selectortype, $element);
|
||||
|
||||
// Check if it is not already opened.
|
||||
$menunode = $this->find('css', '[aria-labelledby='.$node->getAttribute('id').']');
|
||||
if ($menunode->getAttribute('aria-hidden') === 'false') {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->ensure_node_is_visible($node);
|
||||
$node->click();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user