mirror of
https://github.com/moodle/moodle.git
synced 2025-08-06 01:16:44 +02:00
Merge branch 'MDL-54751-master-v5' of https://github.com/snake/moodle
This commit is contained in:
commit
90abff01b3
25 changed files with 725 additions and 25 deletions
|
@ -1063,7 +1063,7 @@ class completion_info {
|
|||
$modinfo = get_fast_modinfo($this->course);
|
||||
$result = array();
|
||||
foreach ($modinfo->get_cms() as $cm) {
|
||||
if ($cm->completion != COMPLETION_TRACKING_NONE) {
|
||||
if ($cm->completion != COMPLETION_TRACKING_NONE && !$cm->deletioninprogress) {
|
||||
$result[$cm->id] = $cm;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -300,6 +300,7 @@
|
|||
<FIELD NAME="completionexpected" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Date at which students are expected to complete this activity. This field is used when displaying student progress."/>
|
||||
<FIELD NAME="showdescription" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Some module types support a 'description' which shows within the module pages. This option controls whether it also displays on the course main page. 0 = does not display (default), 1 = displays"/>
|
||||
<FIELD NAME="availability" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Availability restrictions for viewing this activity, in JSON format. Null if no restrictions."/>
|
||||
<FIELD NAME="deletioninprogress" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
|
|
|
@ -2392,5 +2392,19 @@ function xmldb_main_upgrade($oldversion) {
|
|||
upgrade_main_savepoint(true, 2016110500.00);
|
||||
}
|
||||
|
||||
if ($oldversion < 2016110600.00) {
|
||||
// Define a field 'deletioninprogress' in the 'course_modules' table, to background deletion tasks.
|
||||
$table = new xmldb_table('course_modules');
|
||||
$field = new xmldb_field('deletioninprogress', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'availability');
|
||||
|
||||
// Conditionally launch add field 'deletioninprogress'.
|
||||
if (!$dbman->field_exists($table, $field)) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2016110600.00);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -2215,7 +2215,12 @@ class file_storage {
|
|||
mkdir($trashpath, $this->dirpermissions, true);
|
||||
}
|
||||
rename($contentfile, $trashfile);
|
||||
chmod($trashfile, $this->filepermissions); // fix permissions if needed
|
||||
|
||||
// Fix permissions, only if needed.
|
||||
$currentperms = octdec(substr(decoct(fileperms($trashfile)), -4));
|
||||
if ((int)$this->filepermissions !== $currentperms) {
|
||||
chmod($trashfile, $this->filepermissions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -524,6 +524,14 @@ class grade_item extends grade_object {
|
|||
* @return bool Locked state
|
||||
*/
|
||||
public function is_locked($userid=NULL) {
|
||||
global $CFG;
|
||||
|
||||
// Override for any grade items belonging to activities which are in the process of being deleted.
|
||||
require_once($CFG->dirroot . '/course/lib.php');
|
||||
if (course_module_instance_pending_deletion($this->courseid, $this->itemmodule, $this->iteminstance)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!empty($this->locked)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1393,7 +1401,12 @@ class grade_item extends grade_object {
|
|||
public function get_name($fulltotal=false) {
|
||||
if (strval($this->itemname) !== '') {
|
||||
// MDL-10557
|
||||
return format_string($this->itemname);
|
||||
|
||||
// Make it obvious to users if the course module to which this grade item relates, is currently being removed.
|
||||
$deletionpending = course_module_instance_pending_deletion($this->courseid, $this->itemmodule, $this->iteminstance);
|
||||
$deletionnotice = get_string('gradesmoduledeletionprefix', 'grades');
|
||||
|
||||
return $deletionpending ? format_string($deletionnotice . ' ' . $this->itemname) : format_string($this->itemname);
|
||||
|
||||
} else if ($this->is_course_item()) {
|
||||
return get_string('coursetotal', 'grades');
|
||||
|
|
|
@ -554,8 +554,7 @@ class course_modinfo {
|
|||
|
||||
// Get section data
|
||||
$sections = $DB->get_records('course_sections', array('course' => $course->id), 'section',
|
||||
'section, id, course, name, summary, summaryformat, sequence, visible, ' .
|
||||
'availability');
|
||||
'section, id, course, name, summary, summaryformat, sequence, visible, availability');
|
||||
$compressedsections = array();
|
||||
|
||||
$formatoptionsdef = course_get_format($course)->section_format_options();
|
||||
|
@ -753,6 +752,7 @@ class course_modinfo {
|
|||
* @property-read mixed $customdata Optional custom data stored in modinfo cache for this activity, or null if none
|
||||
* @property-read string $afterlink Extra HTML code to display after link - calculated on request
|
||||
* @property-read string $afterediticons Extra HTML code to display after editing icons (e.g. more icons) - calculated on request
|
||||
* @property-read bool $deletioninprogress True if this course module is scheduled for deletion, false otherwise.
|
||||
*/
|
||||
class cm_info implements IteratorAggregate {
|
||||
/**
|
||||
|
@ -1038,6 +1038,11 @@ class cm_info implements IteratorAggregate {
|
|||
*/
|
||||
private $afterediticons;
|
||||
|
||||
/**
|
||||
* @var bool representing the deletion state of the module. True if the mod is scheduled for deletion.
|
||||
*/
|
||||
private $deletioninprogress;
|
||||
|
||||
/**
|
||||
* List of class read-only properties and their getter methods.
|
||||
* Used by magic functions __get(), __isset(), __empty()
|
||||
|
@ -1089,6 +1094,7 @@ class cm_info implements IteratorAggregate {
|
|||
'uservisible' => 'get_user_visible',
|
||||
'visible' => false,
|
||||
'visibleold' => false,
|
||||
'deletioninprogress' => false
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -1505,7 +1511,7 @@ class cm_info implements IteratorAggregate {
|
|||
static $cmfields = array('id', 'course', 'module', 'instance', 'section', 'idnumber', 'added',
|
||||
'score', 'indent', 'visible', 'visibleold', 'groupmode', 'groupingid',
|
||||
'completion', 'completiongradeitemnumber', 'completionview', 'completionexpected',
|
||||
'showdescription', 'availability');
|
||||
'showdescription', 'availability', 'deletioninprogress');
|
||||
foreach ($cmfields as $key) {
|
||||
$cmrecord->$key = $this->$key;
|
||||
}
|
||||
|
@ -1700,6 +1706,7 @@ class cm_info implements IteratorAggregate {
|
|||
$this->added = isset($mod->added) ? $mod->added : 0;
|
||||
$this->score = isset($mod->score) ? $mod->score : 0;
|
||||
$this->visibleold = isset($mod->visibleold) ? $mod->visibleold : 0;
|
||||
$this->deletioninprogress = isset($mod->deletioninprogress) ? $mod->deletioninprogress : 0;
|
||||
|
||||
// Note: it saves effort and database space to always include the
|
||||
// availability and completion fields, even if availability or completion
|
||||
|
@ -1861,6 +1868,12 @@ class cm_info implements IteratorAggregate {
|
|||
}
|
||||
$this->uservisible = true;
|
||||
|
||||
// If the module is being deleted, set the uservisible state to false and return.
|
||||
if ($this->deletioninprogress) {
|
||||
$this->uservisible = false;
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the user cannot access the activity set the uservisible flag to false.
|
||||
// Additional checks are required to determine whether the activity is entirely hidden or just greyed out.
|
||||
if ((!$this->visible or !$this->get_available()) and
|
||||
|
@ -2465,7 +2478,7 @@ class section_info implements IteratorAggregate {
|
|||
'summary' => '',
|
||||
'summaryformat' => '1', // FORMAT_HTML, but must be a string
|
||||
'visible' => '1',
|
||||
'availability' => null,
|
||||
'availability' => null
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
|
@ -822,4 +822,21 @@ class phpunit_util extends testing_util {
|
|||
return 'en_AU.UTF-8';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes all adhoc tasks in the queue. Useful for testing asynchronous behaviour.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function run_all_adhoc_tasks() {
|
||||
$now = time();
|
||||
while (($task = \core\task\manager::get_next_adhoc_task($now)) !== null) {
|
||||
try {
|
||||
$task->execute();
|
||||
\core\task\manager::adhoc_task_complete($task);
|
||||
} catch (Exception $e) {
|
||||
\core\task\manager::adhoc_task_failed($task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1001,6 +1001,43 @@ class behat_general extends behat_base {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all ad-hoc tasks in the queue.
|
||||
*
|
||||
* This is faster and more reliable than running cron (running cron won't
|
||||
* work more than once in the same test, for instance). However it is
|
||||
* a little less 'realistic'.
|
||||
*
|
||||
* While the task is running, we suppress mtrace output because it makes
|
||||
* the Behat result look ugly.
|
||||
*
|
||||
* @Given /^I run all adhoc tasks$/
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function i_run_all_adhoc_tasks() {
|
||||
// Do setup for cron task.
|
||||
cron_setup_user();
|
||||
|
||||
// Run tasks. Locking is handled by get_next_adhoc_task.
|
||||
$now = time();
|
||||
ob_start(); // Discard task output as not appropriate for Behat output!
|
||||
while (($task = \core\task\manager::get_next_adhoc_task($now)) !== null) {
|
||||
|
||||
try {
|
||||
$task->execute();
|
||||
|
||||
// Mark task complete.
|
||||
\core\task\manager::adhoc_task_complete($task);
|
||||
} catch (Exception $e) {
|
||||
// Mark task failed and throw exception.
|
||||
\core\task\manager::adhoc_task_failed($task);
|
||||
ob_end_clean();
|
||||
throw new DriverException('An adhoc task failed', 0, $e);
|
||||
}
|
||||
}
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that an element and selector type exists in another element and selector type on the current page.
|
||||
*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue