Пример #1
0
 /**
  * Do the job.
  * Throw exceptions on errors (the job will be retried).
  */
 public function execute()
 {
     global $CFG;
     $timenow = time();
     // Run stats as at the end because they are known to take very long time on large sites.
     if (!empty($CFG->enablestats) and empty($CFG->disablestatsprocessing)) {
         require_once $CFG->dirroot . '/lib/statslib.php';
         // Check we're not before our runtime.
         $timetocheck = stats_get_base_daily() + $CFG->statsruntimestarthour * 60 * 60 + $CFG->statsruntimestartminute * 60;
         if ($timenow > $timetocheck) {
             // Process configured number of days as max (defaulting to 31).
             $maxdays = empty($CFG->statsruntimedays) ? 31 : abs($CFG->statsruntimedays);
             if (stats_cron_daily($maxdays)) {
                 if (stats_cron_weekly()) {
                     if (stats_cron_monthly()) {
                         stats_clean_old();
                     }
                 }
             }
             \core_php_time_limit::raise();
         } else {
             mtrace('Next stats run after:' . userdate($timetocheck));
         }
     }
 }
Пример #2
0
 /**
  * Tests for basic use with simple numeric progress.
  */
 public function test_basic()
 {
     $progress = new core_mock_progress();
     // Check values of empty progress things.
     $this->assertFalse($progress->is_in_progress_section());
     // Start progress counting, check basic values and check that update
     // gets called.
     $progress->start_progress('hello', 10);
     $this->assertTrue($progress->was_update_called());
     $this->assertTrue($progress->is_in_progress_section());
     $this->assertEquals('hello', $progress->get_current_description());
     // Check numeric position and indeterminate count.
     $this->assert_min_max(0.0, 0.0, $progress);
     $this->assertEquals(0, $progress->get_progress_count());
     // Make some progress and check that the time limit gets added.
     $progress->step_time();
     core_php_time_limit::get_and_clear_unit_test_data();
     $progress->progress(2);
     $this->assertTrue($progress->was_update_called());
     $this->assertEquals(array(\core\progress\base::TIME_LIMIT_WITHOUT_PROGRESS), core_php_time_limit::get_and_clear_unit_test_data());
     // Check the new value.
     $this->assert_min_max(0.2, 0.2, $progress);
     // Do another progress run at same time, it should be ignored.
     $progress->progress(3);
     $this->assertFalse($progress->was_update_called());
     $this->assert_min_max(0.3, 0.3, $progress);
     // End the section. This should cause an update.
     $progress->end_progress();
     $this->assertTrue($progress->was_update_called());
     // Because there are no sections left open, it thinks we finished.
     $this->assert_min_max(1.0, 1.0, $progress);
     // There was 1 progress call.
     $this->assertEquals(1, $progress->get_progress_count());
 }
Пример #3
0
/**
 * Initiate database transfer.
 * @param moodle_database $sourcedb
 * @param moodle_database $targetdb
 * @param progress_trace $feedback
 * @return void
 */
function tool_dbtransfer_transfer_database(moodle_database $sourcedb, moodle_database $targetdb, progress_trace $feedback = null)
{
    core_php_time_limit::raise();
    \core\session\manager::write_close();
    // Release session.
    $var = new database_mover($sourcedb, $targetdb, true, $feedback);
    $var->export_database(null);
    tool_dbtransfer_rebuild_target_log_actions($targetdb, $feedback);
}
Пример #4
0
 protected function prevent_timeout()
 {
     core_php_time_limit::raise(300);
     if ($this->doingbackup) {
         return;
     }
     echo '.';
     $this->dotcounter += 1;
     if ($this->dotcounter % 100 == 0) {
         echo '<br />';
     }
 }
Пример #5
0
 /**
  * Do the job.
  * Throw exceptions on errors (the job will be retried).
  */
 public function execute()
 {
     global $CFG;
     // Run stats as at the end because they are known to take very long time on large sites.
     if (!empty($CFG->enablestats) and empty($CFG->disablestatsprocessing)) {
         require_once $CFG->dirroot . '/lib/statslib.php';
         // Process configured number of days as max (defaulting to 31).
         $maxdays = empty($CFG->statsruntimedays) ? 31 : abs($CFG->statsruntimedays);
         if (stats_cron_daily($maxdays)) {
             if (stats_cron_weekly()) {
                 if (stats_cron_monthly()) {
                     stats_clean_old();
                 }
             }
         }
         \core_php_time_limit::raise();
     }
 }
 public function test_create_instance()
 {
     global $DB, $USER;
     core_php_time_limit::raise();
     $this->resetAfterTest();
     $this->setAdminUser();
     $course = $this->getDataGenerator()->create_course();
     // There should not be any module for that course first
     $this->assertFalse($DB->record_exists('ratingallocate', array('course' => $course->id)));
     $records = $DB->get_records('ratingallocate_choices', array(), 'id');
     $this->assertEquals(0, count($records));
     // create activity
     $mod = $this->getDataGenerator()->create_module('ratingallocate', array('course' => $course));
     $records = $DB->get_records('ratingallocate', array('course' => $course->id), 'id');
     $this->assertEquals(1, count($records));
     $this->assertTrue(array_key_exists($mod->id, $records));
     $expected_values_db = array('id' => $mod->id, 'course' => $course->id, 'name' => 'Rating Allocation', 'intro' => 'Test ratingallocate 1', 'introformat' => '0', 'timecreated' => reset($records)->{'timecreated'}, 'timemodified' => '0', 'accesstimestart' => reset($records)->{'accesstimestart'}, 'accesstimestop' => reset($records)->{'accesstimestop'}, 'setting' => '{"strategy_yesno":{"maxcrossout":"1"}}', 'strategy' => 'strategy_yesno', 'publishdate' => reset($records)->{'publishdate'}, 'published' => '0', 'notificationsend' => '0', 'algorithmstarttime' => null, 'algorithmstatus' => '0', 'runalgorithmbycron' => '1');
     $this->assertEquals(json_decode(json_encode($expected_values_db, false)), reset($records));
     // must have two choices
     $records = $DB->get_records('ratingallocate_choices', array('ratingallocateid' => $mod->id), 'title');
     $this->assertEquals(2, count($records));
     $choice_ids = array_keys($records);
     $expected_choices = array($choice_ids[0] => (object) array('title' => 'Choice 1', 'id' => $choice_ids[0], 'ratingallocateid' => $mod->id, 'explanation' => 'Some explanatory text for choice 1', 'maxsize' => '10', 'active' => '1'), $choice_ids[1] => (object) array('title' => 'Choice 2', 'id' => $choice_ids[1], 'ratingallocateid' => $mod->id, 'explanation' => 'Some explanatory text for choice 2', 'maxsize' => '5', 'active' => '0'));
     $this->assertEquals($expected_choices, $records);
     // Create an other mod_ratingallocate within the course
     $params = array('course' => $course->id, 'name' => 'Another mod_ratingallocate');
     $mod = $this->getDataGenerator()->create_module('ratingallocate', $params);
     $records = $DB->get_records('ratingallocate', array('course' => $course->id), 'id');
     // are there 2 modules within the course
     $this->assertEquals(2, count($records));
     // is the name correct
     $this->assertEquals('Another mod_ratingallocate', $records[$mod->id]->name);
     $records = $DB->get_records('ratingallocate_choices', array(), 'id');
     $this->assertEquals(4, count($records));
     // other tables
     $records = $DB->get_records('ratingallocate_ratings', array(), 'id');
     $this->assertEquals(0, count($records));
     $records = $DB->get_records('ratingallocate_allocations', array(), 'id');
     $this->assertEquals(0, count($records));
 }
 /**
  * Runs the automated backups if required
  *
  * @global moodle_database $DB
  */
 public static function run_automated_backup($rundirective = self::RUN_ON_SCHEDULE)
 {
     global $CFG, $DB;
     $status = true;
     $emailpending = false;
     $now = time();
     $config = get_config('backup');
     mtrace("Checking automated backup status", '...');
     $state = backup_cron_automated_helper::get_automated_backup_state($rundirective);
     if ($state === backup_cron_automated_helper::STATE_DISABLED) {
         mtrace('INACTIVE');
         return $state;
     } else {
         if ($state === backup_cron_automated_helper::STATE_RUNNING) {
             mtrace('RUNNING');
             if ($rundirective == self::RUN_IMMEDIATELY) {
                 mtrace('Automated backups are already running. If this script is being run by cron this constitues an error. You will need to increase the time between executions within cron.');
             } else {
                 mtrace("automated backup are already running. Execution delayed");
             }
             return $state;
         } else {
             mtrace('OK');
         }
     }
     backup_cron_automated_helper::set_state_running();
     mtrace("Getting admin info");
     $admin = get_admin();
     if (!$admin) {
         mtrace("Error: No admin account was found");
         $state = false;
     }
     if ($status) {
         mtrace("Checking courses");
         mtrace("Skipping deleted courses", '...');
         mtrace(sprintf("%d courses", backup_cron_automated_helper::remove_deleted_courses_from_schedule()));
     }
     if ($status) {
         mtrace('Running required automated backups...');
         cron_trace_time_and_memory();
         // This could take a while!
         core_php_time_limit::raise();
         raise_memory_limit(MEMORY_EXTRA);
         $nextstarttime = backup_cron_automated_helper::calculate_next_automated_backup($admin->timezone, $now);
         $showtime = "undefined";
         if ($nextstarttime > 0) {
             $showtime = date('r', $nextstarttime);
         }
         $rs = $DB->get_recordset('course');
         foreach ($rs as $course) {
             $backupcourse = $DB->get_record('backup_courses', array('courseid' => $course->id));
             if (!$backupcourse) {
                 $backupcourse = new stdClass();
                 $backupcourse->courseid = $course->id;
                 $backupcourse->laststatus = self::BACKUP_STATUS_NOTYETRUN;
                 $DB->insert_record('backup_courses', $backupcourse);
                 $backupcourse = $DB->get_record('backup_courses', array('courseid' => $course->id));
             }
             // The last backup is considered as successful when OK or SKIPPED.
             $lastbackupwassuccessful = ($backupcourse->laststatus == self::BACKUP_STATUS_SKIPPED || $backupcourse->laststatus == self::BACKUP_STATUS_OK) && ($backupcourse->laststarttime > 0 && $backupcourse->lastendtime > 0);
             // Assume that we are not skipping anything.
             $skipped = false;
             $skippedmessage = '';
             // Check if we are going to be running the backup now.
             $shouldrunnow = $backupcourse->nextstarttime > 0 && $backupcourse->nextstarttime < $now || $rundirective == self::RUN_IMMEDIATELY;
             // If config backup_auto_skip_hidden is set to true, skip courses that are not visible.
             if ($shouldrunnow && $config->backup_auto_skip_hidden) {
                 $skipped = $config->backup_auto_skip_hidden && !$course->visible;
                 $skippedmessage = 'Not visible';
             }
             // If config backup_auto_skip_modif_days is set to true, skip courses
             // that have not been modified since the number of days defined.
             if ($shouldrunnow && !$skipped && $lastbackupwassuccessful && $config->backup_auto_skip_modif_days) {
                 $timenotmodifsincedays = $now - $config->backup_auto_skip_modif_days * DAYSECS;
                 // Check log if there were any modifications to the course content.
                 $logexists = self::is_course_modified($course->id, $timenotmodifsincedays);
                 $skipped = $course->timemodified <= $timenotmodifsincedays && !$logexists;
                 $skippedmessage = 'Not modified in the past ' . $config->backup_auto_skip_modif_days . ' days';
             }
             // If config backup_auto_skip_modif_prev is set to true, skip courses
             // that have not been modified since previous backup.
             if ($shouldrunnow && !$skipped && $lastbackupwassuccessful && $config->backup_auto_skip_modif_prev) {
                 // Check log if there were any modifications to the course content.
                 $logexists = self::is_course_modified($course->id, $backupcourse->laststarttime);
                 $skipped = $course->timemodified <= $backupcourse->laststarttime && !$logexists;
                 $skippedmessage = 'Not modified since previous backup';
             }
             // Check if the course is not scheduled to run right now.
             if (!$shouldrunnow) {
                 $backupcourse->nextstarttime = $nextstarttime;
                 $DB->update_record('backup_courses', $backupcourse);
                 mtrace('Skipping ' . $course->fullname . ' (Not scheduled for backup until ' . $showtime . ')');
             } else {
                 if ($skipped) {
                     // Must have been skipped for a reason.
                     $backupcourse->laststatus = self::BACKUP_STATUS_SKIPPED;
                     $backupcourse->nextstarttime = $nextstarttime;
                     $DB->update_record('backup_courses', $backupcourse);
                     mtrace('Skipping ' . $course->fullname . ' (' . $skippedmessage . ')');
                     mtrace('Backup of \'' . $course->fullname . '\' is scheduled on ' . $showtime);
                 } else {
                     // Backup every non-skipped courses.
                     mtrace('Backing up ' . $course->fullname . '...');
                     // We have to send an email because we have included at least one backup.
                     $emailpending = true;
                     // Only make the backup if laststatus isn't 2-UNFINISHED (uncontrolled error).
                     if ($backupcourse->laststatus != self::BACKUP_STATUS_UNFINISHED) {
                         // Set laststarttime.
                         $starttime = time();
                         $backupcourse->laststarttime = time();
                         $backupcourse->laststatus = self::BACKUP_STATUS_UNFINISHED;
                         $DB->update_record('backup_courses', $backupcourse);
                         $backupcourse->laststatus = backup_cron_automated_helper::launch_automated_backup($course, $backupcourse->laststarttime, $admin->id);
                         $backupcourse->lastendtime = time();
                         $backupcourse->nextstarttime = $nextstarttime;
                         $DB->update_record('backup_courses', $backupcourse);
                         if ($backupcourse->laststatus === self::BACKUP_STATUS_OK) {
                             // Clean up any excess course backups now that we have
                             // taken a successful backup.
                             $removedcount = backup_cron_automated_helper::remove_excess_backups($course);
                         }
                     }
                     mtrace("complete - next execution: {$showtime}");
                 }
             }
         }
         $rs->close();
     }
     //Send email to admin if necessary
     if ($emailpending) {
         mtrace("Sending email to admin");
         $message = "";
         $count = backup_cron_automated_helper::get_backup_status_array();
         $haserrors = $count[self::BACKUP_STATUS_ERROR] != 0 || $count[self::BACKUP_STATUS_UNFINISHED] != 0;
         // Build the message text.
         // Summary.
         $message .= get_string('summary') . "\n";
         $message .= "==================================================\n";
         $message .= '  ' . get_string('courses') . '; ' . array_sum($count) . "\n";
         $message .= '  ' . get_string('ok') . '; ' . $count[self::BACKUP_STATUS_OK] . "\n";
         $message .= '  ' . get_string('skipped') . '; ' . $count[self::BACKUP_STATUS_SKIPPED] . "\n";
         $message .= '  ' . get_string('error') . '; ' . $count[self::BACKUP_STATUS_ERROR] . "\n";
         $message .= '  ' . get_string('unfinished') . '; ' . $count[self::BACKUP_STATUS_UNFINISHED] . "\n";
         $message .= '  ' . get_string('warning') . '; ' . $count[self::BACKUP_STATUS_WARNING] . "\n";
         $message .= '  ' . get_string('backupnotyetrun') . '; ' . $count[self::BACKUP_STATUS_NOTYETRUN] . "\n\n";
         //Reference
         if ($haserrors) {
             $message .= "  " . get_string('backupfailed') . "\n\n";
             $dest_url = "{$CFG->wwwroot}/report/backups/index.php";
             $message .= "  " . get_string('backuptakealook', '', $dest_url) . "\n\n";
             //Set message priority
             $admin->priority = 1;
             //Reset unfinished to error
             $DB->set_field('backup_courses', 'laststatus', '0', array('laststatus' => '2'));
         } else {
             $message .= "  " . get_string('backupfinished') . "\n";
         }
         //Build the message subject
         $site = get_site();
         $prefix = format_string($site->shortname, true, array('context' => context_course::instance(SITEID))) . ": ";
         if ($haserrors) {
             $prefix .= "[" . strtoupper(get_string('error')) . "] ";
         }
         $subject = $prefix . get_string('automatedbackupstatus', 'backup');
         //Send the message
         $eventdata = new stdClass();
         $eventdata->modulename = 'moodle';
         $eventdata->userfrom = $admin;
         $eventdata->userto = $admin;
         $eventdata->subject = $subject;
         $eventdata->fullmessage = $message;
         $eventdata->fullmessageformat = FORMAT_PLAIN;
         $eventdata->fullmessagehtml = '';
         $eventdata->smallmessage = '';
         $eventdata->component = 'moodle';
         $eventdata->name = 'backup';
         message_send($eventdata);
     }
     //Everything is finished stop backup_auto_running
     backup_cron_automated_helper::set_state_running(false);
     mtrace('Automated backups complete.');
     return $status;
 }
Пример #8
0
/**
 * Moved from admin/replace.php so that we can use this in cron
 *
 * @param string $search string to look for
 * @param string $replace string to replace
 * @return bool success or fail
 */
function db_replace($search, $replace)
{
    global $DB, $CFG, $OUTPUT;
    // TODO: this is horrible hack, we should do whitelisting and each plugin should be responsible for proper replacing...
    $skiptables = array('config', 'config_plugins', 'config_log', 'upgrade_log', 'log', 'filter_config', 'sessions', 'events_queue', 'repository_instance_config', 'block_instances', '');
    // Turn off time limits, sometimes upgrades can be slow.
    core_php_time_limit::raise();
    if (!($tables = $DB->get_tables())) {
        // No tables yet at all.
        return false;
    }
    foreach ($tables as $table) {
        if (in_array($table, $skiptables)) {
            // Don't process these
            continue;
        }
        if ($columns = $DB->get_columns($table)) {
            $DB->set_debug(true);
            foreach ($columns as $column) {
                $DB->replace_all_text($table, $column, $search, $replace);
            }
            $DB->set_debug(false);
        }
    }
    // delete modinfo caches
    rebuild_course_cache(0, true);
    // TODO: we should ask all plugins to do the search&replace, for now let's do only blocks...
    $blocks = core_component::get_plugin_list('block');
    foreach ($blocks as $blockname => $fullblock) {
        if ($blockname === 'NEWBLOCK') {
            // Someone has unzipped the template, ignore it
            continue;
        }
        if (!is_readable($fullblock . '/lib.php')) {
            continue;
        }
        $function = 'block_' . $blockname . '_global_db_replace';
        include_once $fullblock . '/lib.php';
        if (!function_exists($function)) {
            continue;
        }
        echo $OUTPUT->notification("Replacing in {$blockname} blocks...", 'notifysuccess');
        $function($search, $replace);
        echo $OUTPUT->notification("...finished", 'notifysuccess');
    }
    purge_all_caches();
    return true;
}
 public function test_simple()
 {
     global $DB, $USER;
     core_php_time_limit::raise();
     $this->resetAfterTest();
     $this->setAdminUser();
     $course = $this->getDataGenerator()->create_course();
     $teacher = mod_ratingallocate_generator::create_user_and_enrol($this, $course, true);
     $this->setUser($teacher);
     // There should not be any module for that course first
     $this->assertFalse($DB->record_exists(this_db\ratingallocate::TABLE, array(this_db\ratingallocate::COURSE => $course->id)));
     //set default data for category
     $data = mod_ratingallocate_generator::get_default_values();
     $data['course'] = $course;
     foreach ($data as $name => $value) {
         if (subStr($name, strlen($name) - 7, 7) === 'maxsize') {
             $data[$name] = 2;
         }
         if (subStr($name, strlen($name) - 6, 6) === 'active') {
             $data[$name] = true;
         }
     }
     // create activity
     $mod = $this->getDataGenerator()->create_module(ratingallocate_MOD_NAME, $data);
     $this->assertEquals(2, $DB->count_records(this_db\ratingallocate_choices::TABLE), array(this_db\ratingallocate_choices::ID => $mod->id));
     $student_1 = mod_ratingallocate_generator::create_user_and_enrol($this, $course);
     $student_2 = mod_ratingallocate_generator::create_user_and_enrol($this, $course);
     $student_3 = mod_ratingallocate_generator::create_user_and_enrol($this, $course);
     $student_4 = mod_ratingallocate_generator::create_user_and_enrol($this, $course);
     $ratingallocate = mod_ratingallocate_generator::get_ratingallocate_for_user($this, $mod, $teacher);
     $choices = $ratingallocate->get_rateable_choices();
     $choice1 = reset($choices);
     $choice2 = end($choices);
     //Create preferences
     $prefers_non = array();
     foreach ($choices as $choice) {
         $prefers_non[$choice->{this_db\ratingallocate_choices::ID}] = array(this_db\ratingallocate_ratings::CHOICEID => $choice->{this_db\ratingallocate_choices::ID}, this_db\ratingallocate_ratings::RATING => 0);
     }
     $prefers_first = json_decode(json_encode($prefers_non), true);
     $prefers_first[$choice1->{this_db\ratingallocate_choices::ID}][this_db\ratingallocate_ratings::RATING] = true;
     $prefers_second = json_decode(json_encode($prefers_non), true);
     $prefers_second[$choice2->{this_db\ratingallocate_choices::ID}][this_db\ratingallocate_ratings::RATING] = true;
     //assign preferences
     mod_ratingallocate_generator::save_rating_for_user($this, $mod, $student_1, $prefers_first);
     mod_ratingallocate_generator::save_rating_for_user($this, $mod, $student_2, $prefers_first);
     mod_ratingallocate_generator::save_rating_for_user($this, $mod, $student_3, $prefers_second);
     mod_ratingallocate_generator::save_rating_for_user($this, $mod, $student_4, $prefers_second);
     // allocate choices
     $ratingallocate = mod_ratingallocate_generator::get_ratingallocate_for_user($this, $mod, $teacher);
     $time_needed = $ratingallocate->distrubute_choices();
     $this->assertGreaterThan(0, $time_needed);
     $this->assertLessThan(0.1, $time_needed, 'Allocation is very slow');
     $allocation_count = $ratingallocate->get_choices_with_allocationcount();
     $this->assertCount(2, $allocation_count);
     //Test allocations
     $num_allocations = $DB->count_records(this_db\ratingallocate_allocations::TABLE);
     $this->assertEquals(4, $num_allocations, 'There should be only 4 allocations, since there are only 4 choices.');
     $allocations = $DB->get_records(this_db\ratingallocate_allocations::TABLE, array(this_db\ratingallocate_allocations::RATINGALLOCATEID => $mod->{this_db\ratingallocate::ID}), '');
     // '' /*sort*/, /*fields*/ this_db\ratingallocate_allocations::USERID . ',' . this_db\ratingallocate_allocations::CHOICEID );
     $map_user_id = function ($elem) {
         return $elem->{this_db\ratingallocate_allocations::USERID};
     };
     $alloc1 = self::filter_allocations_by_choice($allocations, $choice1->{this_db\ratingallocate_choices::ID});
     $alloc2 = self::filter_allocations_by_choice($allocations, $choice2->{this_db\ratingallocate_choices::ID});
     //Assert, that student 1 was allocated to choice 1
     $this->assertContains($student_1->id, array_map($map_user_id, $alloc1));
     //Assert, that student 2 was allocated to choice 1
     $this->assertContains($student_2->id, array_map($map_user_id, $alloc1));
     //Assert, that student 3 was allocated to choice 2
     $this->assertContains($student_3->id, array_map($map_user_id, $alloc2));
     //Assert, that student 4 was allocated to choice 2
     $this->assertContains($student_4->id, array_map($map_user_id, $alloc2));
 }
Пример #10
0
 /**
  * Download a zip file of all assignment submissions.
  *
  * @return string - If an error occurs, this will contain the error page.
  */
 protected function download_submissions()
 {
     global $CFG, $DB;
     // More efficient to load this here.
     require_once $CFG->libdir . '/filelib.php';
     // Increase the server timeout to handle the creation and sending of large zip files.
     core_php_time_limit::raise();
     $this->require_view_grades();
     // Load all users with submit.
     $students = get_enrolled_users($this->context, "mod/assign:submit", null, 'u.*', null, null, null, $this->show_only_active_users());
     // Build a list of files to zip.
     $filesforzipping = array();
     $fs = get_file_storage();
     $groupmode = groups_get_activity_groupmode($this->get_course_module());
     // All users.
     $groupid = 0;
     $groupname = '';
     if ($groupmode) {
         $groupid = groups_get_activity_group($this->get_course_module(), true);
         $groupname = groups_get_group_name($groupid) . '-';
     }
     // Construct the zip file name.
     $filename = clean_filename($this->get_course()->shortname . '-' . $this->get_instance()->name . '-' . $groupname . $this->get_course_module()->id . '.zip');
     // Get all the files for each student.
     foreach ($students as $student) {
         $userid = $student->id;
         if (groups_is_member($groupid, $userid) or !$groupmode or !$groupid) {
             // Get the plugins to add their own files to the zip.
             $submissiongroup = false;
             $groupname = '';
             if ($this->get_instance()->teamsubmission) {
                 $submission = $this->get_group_submission($userid, 0, false);
                 $submissiongroup = $this->get_submission_group($userid);
                 if ($submissiongroup) {
                     $groupname = $submissiongroup->name . '-';
                 } else {
                     $groupname = get_string('defaultteam', 'assign') . '-';
                 }
             } else {
                 $submission = $this->get_user_submission($userid, false);
             }
             if ($this->is_blind_marking()) {
                 $prefix = str_replace('_', ' ', $groupname . get_string('participant', 'assign'));
                 $prefix = clean_filename($prefix . '_' . $this->get_uniqueid_for_user($userid) . '_');
             } else {
                 $prefix = str_replace('_', ' ', $groupname . fullname($student));
                 $prefix = clean_filename($prefix . '_' . $this->get_uniqueid_for_user($userid) . '_');
             }
             if ($submission) {
                 foreach ($this->submissionplugins as $plugin) {
                     if ($plugin->is_enabled() && $plugin->is_visible()) {
                         $pluginfiles = $plugin->get_files($submission, $student);
                         foreach ($pluginfiles as $zipfilename => $file) {
                             $subtype = $plugin->get_subtype();
                             $type = $plugin->get_type();
                             $prefixedfilename = clean_filename($prefix . $subtype . '_' . $type . '_' . $zipfilename);
                             $filesforzipping[$prefixedfilename] = $file;
                         }
                     }
                 }
             }
         }
     }
     $result = '';
     if (count($filesforzipping) == 0) {
         $header = new assign_header($this->get_instance(), $this->get_context(), '', $this->get_course_module()->id, get_string('downloadall', 'assign'));
         $result .= $this->get_renderer()->render($header);
         $result .= $this->get_renderer()->notification(get_string('nosubmission', 'assign'));
         $url = new moodle_url('/mod/assign/view.php', array('id' => $this->get_course_module()->id, 'action' => 'grading'));
         $result .= $this->get_renderer()->continue_button($url);
         $result .= $this->view_footer();
     } else {
         if ($zipfile = $this->pack_files($filesforzipping)) {
             \mod_assign\event\all_submissions_downloaded::create_from_assign($this)->trigger();
             // Send file and delete after sending.
             send_temp_file($zipfile, $filename);
             // We will not get here - send_temp_file calls exit.
         }
     }
     return $result;
 }
Пример #11
0
/**
 * Send requested byterange of file.
 *
 * @param resource $handle A file handle
 * @param string $mimetype The mimetype for the output
 * @param array $ranges An array of ranges to send
 * @param string $filesize The size of the content if only one range is used
 */
function byteserving_send_file($handle, $mimetype, $ranges, $filesize)
{
    // better turn off any kind of compression and buffering
    ini_set('zlib.output_compression', 'Off');
    $chunksize = 1 * (1024 * 1024);
    // 1MB chunks - must be less than 2MB!
    if ($handle === false) {
        die;
    }
    if (count($ranges) == 1) {
        //only one range requested
        $length = $ranges[0][2] - $ranges[0][1] + 1;
        header('HTTP/1.1 206 Partial content');
        header('Content-Length: ' . $length);
        header('Content-Range: bytes ' . $ranges[0][1] . '-' . $ranges[0][2] . '/' . $filesize);
        header('Content-Type: ' . $mimetype);
        while (@ob_get_level()) {
            if (!@ob_end_flush()) {
                break;
            }
        }
        fseek($handle, $ranges[0][1]);
        while (!feof($handle) && $length > 0) {
            core_php_time_limit::raise(60 * 60);
            //reset time limit to 60 min - should be enough for 1 MB chunk
            $buffer = fread($handle, $chunksize < $length ? $chunksize : $length);
            echo $buffer;
            flush();
            $length -= strlen($buffer);
        }
        fclose($handle);
        die;
    } else {
        // multiple ranges requested - not tested much
        $totallength = 0;
        foreach ($ranges as $range) {
            $totallength += strlen($range[0]) + $range[2] - $range[1] + 1;
        }
        $totallength += strlen("\r\n--" . BYTESERVING_BOUNDARY . "--\r\n");
        header('HTTP/1.1 206 Partial content');
        header('Content-Length: ' . $totallength);
        header('Content-Type: multipart/byteranges; boundary=' . BYTESERVING_BOUNDARY);
        while (@ob_get_level()) {
            if (!@ob_end_flush()) {
                break;
            }
        }
        foreach ($ranges as $range) {
            $length = $range[2] - $range[1] + 1;
            echo $range[0];
            fseek($handle, $range[1]);
            while (!feof($handle) && $length > 0) {
                core_php_time_limit::raise(60 * 60);
                //reset time limit to 60 min - should be enough for 1 MB chunk
                $buffer = fread($handle, $chunksize < $length ? $chunksize : $length);
                echo $buffer;
                flush();
                $length -= strlen($buffer);
            }
        }
        echo "\r\n--" . BYTESERVING_BOUNDARY . "--\r\n";
        fclose($handle);
        die;
    }
}
Пример #12
0
 /**
  * Sync all meta course links.
  *
  * @param progress_trace $trace
  * @param int $courseid one course, empty mean all
  * @return int 0 means ok, 1 means error, 2 means plugin disabled
  */
 public function sync(progress_trace $trace, $courseid = null)
 {
     global $DB;
     if (!enrol_is_enabled('manual')) {
         $trace->finished();
         return 2;
     }
     // Unfortunately this may take a long time, execution can be interrupted safely here.
     core_php_time_limit::raise();
     raise_memory_limit(MEMORY_HUGE);
     $trace->output('Verifying manual enrolment expiration...');
     $params = array('now' => time(), 'useractive' => ENROL_USER_ACTIVE, 'courselevel' => CONTEXT_COURSE);
     $coursesql = "";
     if ($courseid) {
         $coursesql = "AND e.courseid = :courseid";
         $params['courseid'] = $courseid;
     }
     // Deal with expired accounts.
     $action = $this->get_config('expiredaction', ENROL_EXT_REMOVED_KEEP);
     if ($action == ENROL_EXT_REMOVED_UNENROL) {
         $instances = array();
         $sql = "SELECT ue.*, e.courseid, c.id AS contextid\n                      FROM {user_enrolments} ue\n                      JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'manual')\n                      JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)\n                     WHERE ue.timeend > 0 AND ue.timeend < :now\n                           {$coursesql}";
         $rs = $DB->get_recordset_sql($sql, $params);
         foreach ($rs as $ue) {
             if (empty($instances[$ue->enrolid])) {
                 $instances[$ue->enrolid] = $DB->get_record('enrol', array('id' => $ue->enrolid));
             }
             $instance = $instances[$ue->enrolid];
             // Always remove all manually assigned roles here, this may break enrol_self roles but we do not want hardcoded hacks here.
             role_unassign_all(array('userid' => $ue->userid, 'contextid' => $ue->contextid, 'component' => '', 'itemid' => 0), true);
             $this->unenrol_user($instance, $ue->userid);
             $trace->output("unenrolling expired user {$ue->userid} from course {$instance->courseid}", 1);
         }
         $rs->close();
         unset($instances);
     } else {
         if ($action == ENROL_EXT_REMOVED_SUSPENDNOROLES or $action == ENROL_EXT_REMOVED_SUSPEND) {
             $instances = array();
             $sql = "SELECT ue.*, e.courseid, c.id AS contextid\n                      FROM {user_enrolments} ue\n                      JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'manual')\n                      JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)\n                     WHERE ue.timeend > 0 AND ue.timeend < :now\n                           AND ue.status = :useractive\n                           {$coursesql}";
             $rs = $DB->get_recordset_sql($sql, $params);
             foreach ($rs as $ue) {
                 if (empty($instances[$ue->enrolid])) {
                     $instances[$ue->enrolid] = $DB->get_record('enrol', array('id' => $ue->enrolid));
                 }
                 $instance = $instances[$ue->enrolid];
                 if ($action == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
                     // Remove all manually assigned roles here, this may break enrol_self roles but we do not want hardcoded hacks here.
                     role_unassign_all(array('userid' => $ue->userid, 'contextid' => $ue->contextid, 'component' => '', 'itemid' => 0), true);
                     $this->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED);
                     $trace->output("suspending expired user {$ue->userid} in course {$instance->courseid}, roles unassigned", 1);
                 } else {
                     $this->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED);
                     $trace->output("suspending expired user {$ue->userid} in course {$instance->courseid}, roles kept", 1);
                 }
             }
             $rs->close();
             unset($instances);
         } else {
             // ENROL_EXT_REMOVED_KEEP means no changes.
         }
     }
     $trace->output('...manual enrolment updates finished.');
     $trace->finished();
     return 0;
 }
Пример #13
0
 /**
  * Recursively delete category including all subcategories and courses
  *
  * Function {@link coursecat::can_delete_full()} MUST be called prior
  * to calling this function because there is no capability check
  * inside this function
  *
  * @param boolean $showfeedback display some notices
  * @return array return deleted courses
  * @throws moodle_exception
  */
 public function delete_full($showfeedback = true)
 {
     global $CFG, $DB;
     require_once $CFG->libdir . '/gradelib.php';
     require_once $CFG->libdir . '/questionlib.php';
     require_once $CFG->dirroot . '/cohort/lib.php';
     // Make sure we won't timeout when deleting a lot of courses.
     $settimeout = core_php_time_limit::raise();
     $deletedcourses = array();
     // Get children. Note, we don't want to use cache here because it would be rebuilt too often.
     $children = $DB->get_records('course_categories', array('parent' => $this->id), 'sortorder ASC');
     foreach ($children as $record) {
         $coursecat = new coursecat($record);
         $deletedcourses += $coursecat->delete_full($showfeedback);
     }
     if ($courses = $DB->get_records('course', array('category' => $this->id), 'sortorder ASC')) {
         foreach ($courses as $course) {
             if (!delete_course($course, false)) {
                 throw new moodle_exception('cannotdeletecategorycourse', '', '', $course->shortname);
             }
             $deletedcourses[] = $course;
         }
     }
     // Move or delete cohorts in this context.
     cohort_delete_category($this);
     // Now delete anything that may depend on course category context.
     grade_course_category_delete($this->id, 0, $showfeedback);
     if (!question_delete_course_category($this, 0, $showfeedback)) {
         throw new moodle_exception('cannotdeletecategoryquestions', '', '', $this->get_formatted_name());
     }
     // Finally delete the category and it's context.
     $DB->delete_records('course_categories', array('id' => $this->id));
     $coursecatcontext = context_coursecat::instance($this->id);
     $coursecatcontext->delete();
     cache_helper::purge_by_event('changesincoursecat');
     // Trigger a course category deleted event.
     /* @var \core\event\course_category_deleted $event */
     $event = \core\event\course_category_deleted::create(array('objectid' => $this->id, 'context' => $coursecatcontext, 'other' => array('name' => $this->name)));
     $event->set_coursecat($this);
     $event->trigger();
     // If we deleted $CFG->defaultrequestcategory, make it point somewhere else.
     if ($this->id == $CFG->defaultrequestcategory) {
         set_config('defaultrequestcategory', $DB->get_field('course_categories', 'MIN(id)', array('parent' => 0)));
     }
     return $deletedcourses;
 }
Пример #14
0
/**
 *
 * @param object $glossary
 * @param string $ignored invalid parameter
 * @param int|string $hook
 * @return string
 */
function glossary_generate_export_file($glossary, $ignored = "", $hook = 0)
{
    global $CFG, $DB;
    // Large exports are likely to take their time and memory.
    core_php_time_limit::raise();
    raise_memory_limit(MEMORY_EXTRA);
    $cm = get_coursemodule_from_instance('glossary', $glossary->id, $glossary->course);
    $context = context_module::instance($cm->id);
    $co = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
    $co .= glossary_start_tag("GLOSSARY", 0, true);
    $co .= glossary_start_tag("INFO", 1, true);
    $co .= glossary_full_tag("NAME", 2, false, $glossary->name);
    $co .= glossary_full_tag("INTRO", 2, false, $glossary->intro);
    $co .= glossary_full_tag("INTROFORMAT", 2, false, $glossary->introformat);
    $co .= glossary_full_tag("ALLOWDUPLICATEDENTRIES", 2, false, $glossary->allowduplicatedentries);
    $co .= glossary_full_tag("DISPLAYFORMAT", 2, false, $glossary->displayformat);
    $co .= glossary_full_tag("SHOWSPECIAL", 2, false, $glossary->showspecial);
    $co .= glossary_full_tag("SHOWALPHABET", 2, false, $glossary->showalphabet);
    $co .= glossary_full_tag("SHOWALL", 2, false, $glossary->showall);
    $co .= glossary_full_tag("ALLOWCOMMENTS", 2, false, $glossary->allowcomments);
    $co .= glossary_full_tag("USEDYNALINK", 2, false, $glossary->usedynalink);
    $co .= glossary_full_tag("DEFAULTAPPROVAL", 2, false, $glossary->defaultapproval);
    $co .= glossary_full_tag("GLOBALGLOSSARY", 2, false, $glossary->globalglossary);
    $co .= glossary_full_tag("ENTBYPAGE", 2, false, $glossary->entbypage);
    $co .= glossary_xml_export_files('INTROFILES', 2, $context->id, 'intro', 0);
    if ($entries = $DB->get_records("glossary_entries", array("glossaryid" => $glossary->id))) {
        $co .= glossary_start_tag("ENTRIES", 2, true);
        foreach ($entries as $entry) {
            $permissiongranted = 1;
            if ($hook) {
                switch ($hook) {
                    case "ALL":
                    case "SPECIAL":
                        break;
                    default:
                        $permissiongranted = $entry->concept[strlen($hook) - 1] == $hook;
                        break;
                }
            }
            if ($hook) {
                switch ($hook) {
                    case GLOSSARY_SHOW_ALL_CATEGORIES:
                        break;
                    case GLOSSARY_SHOW_NOT_CATEGORISED:
                        $permissiongranted = !$DB->record_exists("glossary_entries_categories", array("entryid" => $entry->id));
                        break;
                    default:
                        $permissiongranted = $DB->record_exists("glossary_entries_categories", array("entryid" => $entry->id, "categoryid" => $hook));
                        break;
                }
            }
            if ($entry->approved and $permissiongranted) {
                $co .= glossary_start_tag("ENTRY", 3, true);
                $co .= glossary_full_tag("CONCEPT", 4, false, trim($entry->concept));
                $co .= glossary_full_tag("DEFINITION", 4, false, $entry->definition);
                $co .= glossary_full_tag("FORMAT", 4, false, $entry->definitionformat);
                // note: use old name for BC reasons
                $co .= glossary_full_tag("USEDYNALINK", 4, false, $entry->usedynalink);
                $co .= glossary_full_tag("CASESENSITIVE", 4, false, $entry->casesensitive);
                $co .= glossary_full_tag("FULLMATCH", 4, false, $entry->fullmatch);
                $co .= glossary_full_tag("TEACHERENTRY", 4, false, $entry->teacherentry);
                if ($aliases = $DB->get_records("glossary_alias", array("entryid" => $entry->id))) {
                    $co .= glossary_start_tag("ALIASES", 4, true);
                    foreach ($aliases as $alias) {
                        $co .= glossary_start_tag("ALIAS", 5, true);
                        $co .= glossary_full_tag("NAME", 6, false, trim($alias->alias));
                        $co .= glossary_end_tag("ALIAS", 5, true);
                    }
                    $co .= glossary_end_tag("ALIASES", 4, true);
                }
                if ($catentries = $DB->get_records("glossary_entries_categories", array("entryid" => $entry->id))) {
                    $co .= glossary_start_tag("CATEGORIES", 4, true);
                    foreach ($catentries as $catentry) {
                        $category = $DB->get_record("glossary_categories", array("id" => $catentry->categoryid));
                        $co .= glossary_start_tag("CATEGORY", 5, true);
                        $co .= glossary_full_tag("NAME", 6, false, $category->name);
                        $co .= glossary_full_tag("USEDYNALINK", 6, false, $category->usedynalink);
                        $co .= glossary_end_tag("CATEGORY", 5, true);
                    }
                    $co .= glossary_end_tag("CATEGORIES", 4, true);
                }
                // Export files embedded in entries.
                $co .= glossary_xml_export_files('ENTRYFILES', 4, $context->id, 'entry', $entry->id);
                // Export attachments.
                $co .= glossary_xml_export_files('ATTACHMENTFILES', 4, $context->id, 'attachment', $entry->id);
                $co .= glossary_end_tag("ENTRY", 3, true);
            }
        }
        $co .= glossary_end_tag("ENTRIES", 2, true);
    }
    $co .= glossary_end_tag("INFO", 1, true);
    $co .= glossary_end_tag("GLOSSARY", 0, true);
    return $co;
}
Пример #15
0
/**
 * Execute monthly statistics gathering
 * @return boolean success
 */
function stats_cron_monthly()
{
    global $CFG, $DB;
    require_once $CFG->libdir . '/adminlib.php';
    $now = time();
    // read last execution date from db
    if (!($timestart = get_config(NULL, 'statslastmonthly'))) {
        $timestart = stats_get_base_monthly(stats_get_start_from('monthly'));
        set_config('statslastmonthly', $timestart);
    }
    $nextstartmonth = stats_get_next_month_start($timestart);
    // are there any months that need to be processed?
    if ($now < $nextstartmonth) {
        return true;
        // everything ok and up-to-date
    }
    $timeout = empty($CFG->statsmaxruntime) ? 60 * 60 * 24 : $CFG->statsmaxruntime;
    if (!set_cron_lock('statsrunning', $now + $timeout)) {
        return false;
    }
    // fisr delete entries that should not be there yet
    $DB->delete_records_select('stats_monthly', "timeend > {$timestart}");
    $DB->delete_records_select('stats_user_monthly', "timeend > {$timestart}");
    $startmonth = stats_get_base_monthly($now);
    mtrace("Running monthly statistics gathering, starting at {$timestart}:");
    cron_trace_time_and_memory();
    $months = 0;
    while ($now > $nextstartmonth) {
        core_php_time_limit::raise($timeout - 200);
        $months++;
        if ($months > 1) {
            // move the lock
            set_cron_lock('statsrunning', time() + $timeout, true);
        }
        $stattimesql = "timeend > {$timestart} AND timeend <= {$nextstartmonth}";
        $monthstart = time();
        stats_progress('init');
        /// process login info first
        $sql = "INSERT INTO {stats_user_monthly} (stattype, timeend, courseid, userid, statsreads)\n\n                SELECT 'logins', timeend, courseid, userid, SUM(statsreads)\n                  FROM (\n                           SELECT {$nextstartmonth} AS timeend, courseid, userid, statsreads\n                             FROM {stats_user_daily} sd\n                            WHERE stattype = 'logins' AND {$stattimesql}\n                       ) inline_view\n              GROUP BY timeend, courseid, userid\n                HAVING SUM(statsreads) > 0";
        $DB->execute($sql);
        stats_progress('1');
        $sql = "INSERT INTO {stats_monthly} (stattype, timeend, courseid, roleid, stat1, stat2)\n\n                SELECT 'logins' AS stattype, {$nextstartmonth} AS timeend, " . SITEID . " as courseid, 0,\n                       COALESCE((SELECT SUM(statsreads)\n                                   FROM {stats_user_monthly} s1\n                                  WHERE s1.stattype = 'logins' AND timeend = {$nextstartmonth}), 0) AS nstat1,\n                       (SELECT COUNT('x')\n                          FROM {stats_user_monthly} s2\n                         WHERE s2.stattype = 'logins' AND timeend = {$nextstartmonth}) AS nstat2" . $DB->sql_null_from_clause();
        $DB->execute($sql);
        stats_progress('2');
        /// now enrolments averages
        $sql = "INSERT INTO {stats_monthly} (stattype, timeend, courseid, roleid, stat1, stat2)\n\n                SELECT 'enrolments', ntimeend, courseid, roleid, " . $DB->sql_ceil('AVG(stat1)') . ", " . $DB->sql_ceil('AVG(stat2)') . "\n                  FROM (\n                           SELECT {$nextstartmonth} AS ntimeend, courseid, roleid, stat1, stat2\n                             FROM {stats_daily} sd\n                            WHERE stattype = 'enrolments' AND {$stattimesql}\n                       ) inline_view\n              GROUP BY ntimeend, courseid, roleid";
        $DB->execute($sql);
        stats_progress('3');
        /// activity read/write averages
        $sql = "INSERT INTO {stats_monthly} (stattype, timeend, courseid, roleid, stat1, stat2)\n\n                SELECT 'activity', ntimeend, courseid, roleid, SUM(stat1), SUM(stat2)\n                  FROM (\n                           SELECT {$nextstartmonth} AS ntimeend, courseid, roleid, stat1, stat2\n                             FROM {stats_daily}\n                            WHERE stattype = 'activity' AND {$stattimesql}\n                       ) inline_view\n              GROUP BY ntimeend, courseid, roleid";
        $DB->execute($sql);
        stats_progress('4');
        /// user read/write averages
        $sql = "INSERT INTO {stats_user_monthly} (stattype, timeend, courseid, userid, statsreads, statswrites)\n\n                SELECT 'activity', ntimeend, courseid, userid, SUM(statsreads), SUM(statswrites)\n                  FROM (\n                           SELECT {$nextstartmonth} AS ntimeend, courseid, userid, statsreads, statswrites\n                             FROM {stats_user_daily}\n                            WHERE stattype = 'activity' AND {$stattimesql}\n                       ) inline_view\n              GROUP BY ntimeend, courseid, userid";
        $DB->execute($sql);
        stats_progress('5');
        set_config('statslastmonthly', $nextstartmonth);
        $elapsed = time() - $monthstart;
        mtrace(" finished until {$nextstartmonth}: " . userdate($nextstartmonth) . " (in {$elapsed} s)");
        $timestart = $nextstartmonth;
        $nextstartmonth = stats_get_next_month_start($nextstartmonth);
    }
    set_cron_lock('statsrunning', null);
    mtrace("...completed {$months} months of statistics.");
    return true;
}
Пример #16
0
 * @subpackage uploaduser
 * @copyright  2004 onwards Martin Dougiamas (http://dougiamas.com)
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
require '../../../config.php';
require_once $CFG->libdir . '/adminlib.php';
require_once $CFG->libdir . '/csvlib.class.php';
require_once $CFG->dirroot . '/user/profile/lib.php';
require_once $CFG->dirroot . '/user/lib.php';
require_once $CFG->dirroot . '/group/lib.php';
require_once $CFG->dirroot . '/cohort/lib.php';
require_once 'locallib.php';
require_once 'user_form.php';
$iid = optional_param('iid', '', PARAM_INT);
$previewrows = optional_param('previewrows', 10, PARAM_INT);
core_php_time_limit::raise(60 * 60);
// 1 hour should be enough
raise_memory_limit(MEMORY_HUGE);
require_login();
admin_externalpage_setup('tooluploaduser');
require_capability('moodle/site:uploadusers', context_system::instance());
$struserrenamed = get_string('userrenamed', 'tool_uploaduser');
$strusernotrenamedexists = get_string('usernotrenamedexists', 'error');
$strusernotrenamedmissing = get_string('usernotrenamedmissing', 'error');
$strusernotrenamedoff = get_string('usernotrenamedoff', 'error');
$strusernotrenamedadmin = get_string('usernotrenamedadmin', 'error');
$struserupdated = get_string('useraccountupdated', 'tool_uploaduser');
$strusernotupdated = get_string('usernotupdatederror', 'error');
$strusernotupdatednotexists = get_string('usernotupdatednotexists', 'error');
$strusernotupdatedadmin = get_string('usernotupdatedadmin', 'error');
$struseruptodate = get_string('useraccountuptodate', 'tool_uploaduser');
Пример #17
0
 /**
  * Forces synchronisation of all enrolments with LDAP server.
  * It creates courses if the plugin is configured to do so.
  *
  * @param progress_trace $trace
  * @param int|null $onecourse limit sync to one course->id, null if all courses
  * @return void
  */
 public function sync_enrolments(progress_trace $trace, $onecourse = null)
 {
     global $CFG, $DB;
     if (!$this->ldap_connect($trace)) {
         $trace->finished();
         return;
     }
     $ldap_pagedresults = ldap_paged_results_supported($this->get_config('ldap_version'));
     // we may need a lot of memory here
     core_php_time_limit::raise();
     raise_memory_limit(MEMORY_HUGE);
     $oneidnumber = null;
     if ($onecourse) {
         if (!($course = $DB->get_record('course', array('id' => $onecourse), 'id,' . $this->enrol_localcoursefield))) {
             // Course does not exist, nothing to do.
             $trace->output("Requested course {$onecourse} does not exist, no sync performed.");
             $trace->finished();
             return;
         }
         if (empty($course->{$this->enrol_localcoursefield})) {
             $trace->output("Requested course {$onecourse} does not have {$this->enrol_localcoursefield}, no sync performed.");
             $trace->finished();
             return;
         }
         $oneidnumber = ldap_filter_addslashes(core_text::convert($course->idnumber, 'utf-8', $this->get_config('ldapencoding')));
     }
     // Get enrolments for each type of role.
     $roles = get_all_roles();
     $enrolments = array();
     foreach ($roles as $role) {
         // Get all contexts
         $ldap_contexts = explode(';', $this->config->{'contexts_role' . $role->id});
         // Get all the fields we will want for the potential course creation
         // as they are light. Don't get membership -- potentially a lot of data.
         $ldap_fields_wanted = array('dn', $this->config->course_idnumber);
         if (!empty($this->config->course_fullname)) {
             array_push($ldap_fields_wanted, $this->config->course_fullname);
         }
         if (!empty($this->config->course_shortname)) {
             array_push($ldap_fields_wanted, $this->config->course_shortname);
         }
         if (!empty($this->config->course_summary)) {
             array_push($ldap_fields_wanted, $this->config->course_summary);
         }
         array_push($ldap_fields_wanted, $this->config->{'memberattribute_role' . $role->id});
         // Define the search pattern
         $ldap_search_pattern = $this->config->objectclass;
         if ($oneidnumber !== null) {
             $ldap_search_pattern = "(&{$ldap_search_pattern}({$this->config->course_idnumber}={$oneidnumber}))";
         }
         $ldap_cookie = '';
         foreach ($ldap_contexts as $ldap_context) {
             $ldap_context = trim($ldap_context);
             if (empty($ldap_context)) {
                 continue;
                 // Next;
             }
             $flat_records = array();
             do {
                 if ($ldap_pagedresults) {
                     ldap_control_paged_result($this->ldapconnection, $this->config->pagesize, true, $ldap_cookie);
                 }
                 if ($this->config->course_search_sub) {
                     // Use ldap_search to find first user from subtree
                     $ldap_result = @ldap_search($this->ldapconnection, $ldap_context, $ldap_search_pattern, $ldap_fields_wanted);
                 } else {
                     // Search only in this context
                     $ldap_result = @ldap_list($this->ldapconnection, $ldap_context, $ldap_search_pattern, $ldap_fields_wanted);
                 }
                 if (!$ldap_result) {
                     continue;
                     // Next
                 }
                 if ($ldap_pagedresults) {
                     ldap_control_paged_result_response($this->ldapconnection, $ldap_result, $ldap_cookie);
                 }
                 // Check and push results
                 $records = ldap_get_entries($this->ldapconnection, $ldap_result);
                 // LDAP libraries return an odd array, really. fix it:
                 for ($c = 0; $c < $records['count']; $c++) {
                     array_push($flat_records, $records[$c]);
                 }
                 // Free some mem
                 unset($records);
             } while ($ldap_pagedresults && !empty($ldap_cookie));
             // If LDAP paged results were used, the current connection must be completely
             // closed and a new one created, to work without paged results from here on.
             if ($ldap_pagedresults) {
                 $this->ldap_close();
                 $this->ldap_connect($trace);
             }
             if (count($flat_records)) {
                 $ignorehidden = $this->get_config('ignorehiddencourses');
                 foreach ($flat_records as $course) {
                     $course = array_change_key_case($course, CASE_LOWER);
                     $idnumber = $course[$this->config->course_idnumber][0];
                     $trace->output(get_string('synccourserole', 'enrol_ldap', array('idnumber' => $idnumber, 'role_shortname' => $role->shortname)));
                     // Does the course exist in moodle already?
                     $course_obj = $DB->get_record('course', array($this->enrol_localcoursefield => $idnumber));
                     if (empty($course_obj)) {
                         // Course doesn't exist
                         if ($this->get_config('autocreate')) {
                             // Autocreate
                             $trace->output(get_string('createcourseextid', 'enrol_ldap', array('courseextid' => $idnumber)));
                             if (!($newcourseid = $this->create_course($course, $trace))) {
                                 continue;
                             }
                             $course_obj = $DB->get_record('course', array('id' => $newcourseid));
                         } else {
                             $trace->output(get_string('createnotcourseextid', 'enrol_ldap', array('courseextid' => $idnumber)));
                             continue;
                             // Next; skip this one!
                         }
                     } else {
                         // Check if course needs update & update as needed.
                         $this->update_course($course_obj, $course, $trace);
                     }
                     // Enrol & unenrol
                     // Pull the ldap membership into a nice array
                     // this is an odd array -- mix of hash and array --
                     $ldapmembers = array();
                     if (array_key_exists('memberattribute_role' . $role->id, $this->config) && !empty($this->config->{'memberattribute_role' . $role->id}) && !empty($course[$this->config->{'memberattribute_role' . $role->id}])) {
                         // May have no membership!
                         $ldapmembers = $course[$this->config->{'memberattribute_role' . $role->id}];
                         unset($ldapmembers['count']);
                         // Remove oddity ;)
                         // If we have enabled nested groups, we need to expand
                         // the groups to get the real user list. We need to do
                         // this before dealing with 'memberattribute_isdn'.
                         if ($this->config->nested_groups) {
                             $users = array();
                             foreach ($ldapmembers as $ldapmember) {
                                 $grpusers = $this->ldap_explode_group($ldapmember, $this->config->{'memberattribute_role' . $role->id});
                                 $users = array_merge($users, $grpusers);
                             }
                             $ldapmembers = array_unique($users);
                             // There might be duplicates.
                         }
                         // Deal with the case where the member attribute holds distinguished names,
                         // but only if the user attribute is not a distinguished name itself.
                         if ($this->config->memberattribute_isdn && $this->config->idnumber_attribute !== 'dn' && $this->config->idnumber_attribute !== 'distinguishedname') {
                             // We need to retrieve the idnumber for all the users in $ldapmembers,
                             // as the idnumber does not match their dn and we get dn's from membership.
                             $memberidnumbers = array();
                             foreach ($ldapmembers as $ldapmember) {
                                 $result = ldap_read($this->ldapconnection, $ldapmember, '(objectClass=*)', array($this->config->idnumber_attribute));
                                 $entry = ldap_first_entry($this->ldapconnection, $result);
                                 $values = ldap_get_values($this->ldapconnection, $entry, $this->config->idnumber_attribute);
                                 array_push($memberidnumbers, $values[0]);
                             }
                             $ldapmembers = $memberidnumbers;
                         }
                     }
                     // Prune old ldap enrolments
                     // hopefully they'll fit in the max buffer size for the RDBMS
                     $sql = "SELECT u.id as userid, u.username, ue.status,\n                                      ra.contextid, ra.itemid as instanceid\n                                 FROM {user} u\n                                 JOIN {role_assignments} ra ON (ra.userid = u.id AND ra.component = 'enrol_ldap' AND ra.roleid = :roleid)\n                                 JOIN {user_enrolments} ue ON (ue.userid = u.id AND ue.enrolid = ra.itemid)\n                                 JOIN {enrol} e ON (e.id = ue.enrolid)\n                                WHERE u.deleted = 0 AND e.courseid = :courseid ";
                     $params = array('roleid' => $role->id, 'courseid' => $course_obj->id);
                     $context = context_course::instance($course_obj->id);
                     if (!empty($ldapmembers)) {
                         list($ldapml, $params2) = $DB->get_in_or_equal($ldapmembers, SQL_PARAMS_NAMED, 'm', false);
                         $sql .= "AND u.idnumber {$ldapml}";
                         $params = array_merge($params, $params2);
                         unset($params2);
                     } else {
                         $shortname = format_string($course_obj->shortname, true, array('context' => $context));
                         $trace->output(get_string('emptyenrolment', 'enrol_ldap', array('role_shortname' => $role->shortname, 'course_shortname' => $shortname)));
                     }
                     $todelete = $DB->get_records_sql($sql, $params);
                     if (!empty($todelete)) {
                         $transaction = $DB->start_delegated_transaction();
                         foreach ($todelete as $row) {
                             $instance = $DB->get_record('enrol', array('id' => $row->instanceid));
                             switch ($this->get_config('unenrolaction')) {
                                 case ENROL_EXT_REMOVED_UNENROL:
                                     $this->unenrol_user($instance, $row->userid);
                                     $trace->output(get_string('extremovedunenrol', 'enrol_ldap', array('user_username' => $row->username, 'course_shortname' => $course_obj->shortname, 'course_id' => $course_obj->id)));
                                     break;
                                 case ENROL_EXT_REMOVED_KEEP:
                                     // Keep - only adding enrolments
                                     break;
                                 case ENROL_EXT_REMOVED_SUSPEND:
                                     if ($row->status != ENROL_USER_SUSPENDED) {
                                         $DB->set_field('user_enrolments', 'status', ENROL_USER_SUSPENDED, array('enrolid' => $instance->id, 'userid' => $row->userid));
                                         $trace->output(get_string('extremovedsuspend', 'enrol_ldap', array('user_username' => $row->username, 'course_shortname' => $course_obj->shortname, 'course_id' => $course_obj->id)));
                                     }
                                     break;
                                 case ENROL_EXT_REMOVED_SUSPENDNOROLES:
                                     if ($row->status != ENROL_USER_SUSPENDED) {
                                         $DB->set_field('user_enrolments', 'status', ENROL_USER_SUSPENDED, array('enrolid' => $instance->id, 'userid' => $row->userid));
                                     }
                                     role_unassign_all(array('contextid' => $row->contextid, 'userid' => $row->userid, 'component' => 'enrol_ldap', 'itemid' => $instance->id));
                                     $trace->output(get_string('extremovedsuspendnoroles', 'enrol_ldap', array('user_username' => $row->username, 'course_shortname' => $course_obj->shortname, 'course_id' => $course_obj->id)));
                                     break;
                             }
                         }
                         $transaction->allow_commit();
                     }
                     // Insert current enrolments
                     // bad we can't do INSERT IGNORE with postgres...
                     // Add necessary enrol instance if not present yet;
                     $sql = "SELECT c.id, c.visible, e.id as enrolid\n                                  FROM {course} c\n                                  JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'ldap')\n                                 WHERE c.id = :courseid";
                     $params = array('courseid' => $course_obj->id);
                     if (!($course_instance = $DB->get_record_sql($sql, $params, IGNORE_MULTIPLE))) {
                         $course_instance = new stdClass();
                         $course_instance->id = $course_obj->id;
                         $course_instance->visible = $course_obj->visible;
                         $course_instance->enrolid = $this->add_instance($course_instance);
                     }
                     if (!($instance = $DB->get_record('enrol', array('id' => $course_instance->enrolid)))) {
                         continue;
                         // Weird; skip this one.
                     }
                     if ($ignorehidden && !$course_instance->visible) {
                         continue;
                     }
                     $transaction = $DB->start_delegated_transaction();
                     foreach ($ldapmembers as $ldapmember) {
                         $sql = 'SELECT id,username,1 FROM {user} WHERE idnumber = ? AND deleted = 0';
                         $member = $DB->get_record_sql($sql, array($ldapmember));
                         if (empty($member) || empty($member->id)) {
                             $trace->output(get_string('couldnotfinduser', 'enrol_ldap', $ldapmember));
                             continue;
                         }
                         $sql = "SELECT ue.status\n                                     FROM {user_enrolments} ue\n                                     JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'ldap')\n                                    WHERE e.courseid = :courseid AND ue.userid = :userid";
                         $params = array('courseid' => $course_obj->id, 'userid' => $member->id);
                         $userenrolment = $DB->get_record_sql($sql, $params, IGNORE_MULTIPLE);
                         if (empty($userenrolment)) {
                             $this->enrol_user($instance, $member->id, $role->id);
                             // Make sure we set the enrolment status to active. If the user wasn't
                             // previously enrolled to the course, enrol_user() sets it. But if we
                             // configured the plugin to suspend the user enrolments _AND_ remove
                             // the role assignments on external unenrol, then enrol_user() doesn't
                             // set it back to active on external re-enrolment. So set it
                             // unconditionally to cover both cases.
                             $DB->set_field('user_enrolments', 'status', ENROL_USER_ACTIVE, array('enrolid' => $instance->id, 'userid' => $member->id));
                             $trace->output(get_string('enroluser', 'enrol_ldap', array('user_username' => $member->username, 'course_shortname' => $course_obj->shortname, 'course_id' => $course_obj->id)));
                         } else {
                             if (!$DB->record_exists('role_assignments', array('roleid' => $role->id, 'userid' => $member->id, 'contextid' => $context->id, 'component' => 'enrol_ldap', 'itemid' => $instance->id))) {
                                 // This happens when reviving users or when user has multiple roles in one course.
                                 $context = context_course::instance($course_obj->id);
                                 role_assign($role->id, $member->id, $context->id, 'enrol_ldap', $instance->id);
                                 $trace->output("Assign role to user '{$member->username}' in course '{$course_obj->shortname} ({$course_obj->id})'");
                             }
                             if ($userenrolment->status == ENROL_USER_SUSPENDED) {
                                 // Reenable enrolment that was previously disabled. Enrolment refreshed
                                 $DB->set_field('user_enrolments', 'status', ENROL_USER_ACTIVE, array('enrolid' => $instance->id, 'userid' => $member->id));
                                 $trace->output(get_string('enroluserenable', 'enrol_ldap', array('user_username' => $member->username, 'course_shortname' => $course_obj->shortname, 'course_id' => $course_obj->id)));
                             }
                         }
                     }
                     $transaction->allow_commit();
                 }
             }
         }
     }
     @$this->ldap_close();
     $trace->finished();
 }
Пример #18
0
/**
 * Resets the page customisations for all users.
 *
 * @param int $private Either MY_PAGE_PRIVATE or MY_PAGE_PUBLIC.
 * @param string $pagetype Either my-index or user-profile.
 * @return void
 */
function my_reset_page_for_all_users($private = MY_PAGE_PRIVATE, $pagetype = 'my-index') {
    global $DB;

    // This may take a while. Raise the execution time limit.
    core_php_time_limit::raise();

    // Find all the user pages.
    $where = 'userid IS NOT NULL AND private = :private';
    $params = array('private' => $private);
    $pages = $DB->get_recordset_select('my_pages', $where, $params, 'id, userid');
    $blockids = array();

    foreach ($pages as $page) {
        $usercontext = context_user::instance($page->userid);

        // Find all block instances in that page.
        $blockswhere = 'parentcontextid = :parentcontextid AND
            pagetypepattern = :pagetypepattern AND
            (subpagepattern IS NULL OR subpagepattern = :subpagepattern)';
        $blockswhereparams = [
            'parentcontextid' => $usercontext->id,
            'pagetypepattern' => $pagetype,
            'subpagepattern' => $page->id
        ];
        if ($pageblockids = $DB->get_fieldset_select('block_instances', 'id', $blockswhere, $blockswhereparams)) {
            $blockids = array_merge($blockids, $pageblockids);
        }
    }
    $pages->close();

    // Wrap the SQL queries in a transaction.
    $transaction = $DB->start_delegated_transaction();

    // Delete the block instances.
    if (!empty($blockids)) {
        blocks_delete_instances($blockids);
    }

    // Finally delete the pages.
    if (!empty($pages)) {
        $DB->delete_records_select('my_pages', $where, $params);
    }

    // We should be good to go now.
    $transaction->allow_commit();
}
Пример #19
0
/**
 * Upgrade moodle core
 * @param float $version target version
 * @param bool $verbose
 * @return void, may throw exception
 */
function upgrade_core($version, $verbose) {
    global $CFG, $SITE, $DB, $COURSE;

    raise_memory_limit(MEMORY_EXTRA);

    require_once($CFG->libdir.'/db/upgrade.php');    // Defines upgrades

    try {
        // Reset caches before any output.
        cache_helper::purge_all(true);
        purge_all_caches();

        // Upgrade current language pack if we can
        upgrade_language_pack();

        print_upgrade_part_start('moodle', false, $verbose);

        // Pre-upgrade scripts for local hack workarounds.
        $preupgradefile = "$CFG->dirroot/local/preupgrade.php";
        if (file_exists($preupgradefile)) {
            core_php_time_limit::raise();
            require($preupgradefile);
            // Reset upgrade timeout to default.
            upgrade_set_timeout();
        }

        $result = xmldb_main_upgrade($CFG->version);
        if ($version > $CFG->version) {
            // store version if not already there
            upgrade_main_savepoint($result, $version, false);
        }

        // In case structure of 'course' table has been changed and we forgot to update $SITE, re-read it from db.
        $SITE = $DB->get_record('course', array('id' => $SITE->id));
        $COURSE = clone($SITE);

        // perform all other component upgrade routines
        update_capabilities('moodle');
        log_update_descriptions('moodle');
        external_update_descriptions('moodle');
        events_update_definition('moodle');
        \core\task\manager::reset_scheduled_tasks_for_component('moodle');
        message_update_providers('moodle');
        \core\message\inbound\manager::update_handlers_for_component('moodle');
        // Update core definitions.
        cache_helper::update_definitions(true);

        // Purge caches again, just to be sure we arn't holding onto old stuff now.
        cache_helper::purge_all(true);
        purge_all_caches();

        // Clean up contexts - more and more stuff depends on existence of paths and contexts
        context_helper::cleanup_instances();
        context_helper::create_instances(null, false);
        context_helper::build_all_paths(false);
        $syscontext = context_system::instance();
        $syscontext->mark_dirty();

        print_upgrade_part_end('moodle', false, $verbose);
    } catch (Exception $ex) {
        upgrade_handle_exception($ex);
    }
}
Пример #20
0
/**
 * Rebuilds or resets the cached list of course activities stored in MUC.
 *
 * rebuild_course_cache() must NEVER be called from lib/db/upgrade.php.
 * At the same time course cache may ONLY be cleared using this function in
 * upgrade scripts of plugins.
 *
 * During the bulk operations if it is necessary to reset cache of multiple
 * courses it is enough to call {@link increment_revision_number()} for the
 * table 'course' and field 'cacherev' specifying affected courses in select.
 *
 * Cached course information is stored in MUC core/coursemodinfo and is
 * validated with the DB field {course}.cacherev
 *
 * @global moodle_database $DB
 * @param int $courseid id of course to rebuild, empty means all
 * @param boolean $clearonly only clear the cache, gets rebuild automatically on the fly.
 *     Recommended to set to true to avoid unnecessary multiple rebuilding.
 */
function rebuild_course_cache($courseid=0, $clearonly=false) {
    global $COURSE, $SITE, $DB, $CFG;

    // Function rebuild_course_cache() can not be called during upgrade unless it's clear only.
    if (!$clearonly && !upgrade_ensure_not_running(true)) {
        $clearonly = true;
    }

    // Destroy navigation caches
    navigation_cache::destroy_volatile_caches();

    if (class_exists('format_base')) {
        // if file containing class is not loaded, there is no cache there anyway
        format_base::reset_course_cache($courseid);
    }

    $cachecoursemodinfo = cache::make('core', 'coursemodinfo');
    if (empty($courseid)) {
        // Clearing caches for all courses.
        increment_revision_number('course', 'cacherev', '');
        $cachecoursemodinfo->purge();
        course_modinfo::clear_instance_cache();
        // Update global values too.
        $sitecacherev = $DB->get_field('course', 'cacherev', array('id' => SITEID));
        $SITE->cachrev = $sitecacherev;
        if ($COURSE->id == SITEID) {
            $COURSE->cacherev = $sitecacherev;
        } else {
            $COURSE->cacherev = $DB->get_field('course', 'cacherev', array('id' => $COURSE->id));
        }
    } else {
        // Clearing cache for one course, make sure it is deleted from user request cache as well.
        increment_revision_number('course', 'cacherev', 'id = :id', array('id' => $courseid));
        $cachecoursemodinfo->delete($courseid);
        course_modinfo::clear_instance_cache($courseid);
        // Update global values too.
        if ($courseid == $COURSE->id || $courseid == $SITE->id) {
            $cacherev = $DB->get_field('course', 'cacherev', array('id' => $courseid));
            if ($courseid == $COURSE->id) {
                $COURSE->cacherev = $cacherev;
            }
            if ($courseid == $SITE->id) {
                $SITE->cachrev = $cacherev;
            }
        }
    }

    if ($clearonly) {
        return;
    }

    if ($courseid) {
        $select = array('id'=>$courseid);
    } else {
        $select = array();
        core_php_time_limit::raise();  // this could take a while!   MDL-10954
    }

    $rs = $DB->get_recordset("course", $select,'','id,'.join(',', course_modinfo::$cachedfields));
    // Rebuild cache for each course.
    foreach ($rs as $course) {
        course_modinfo::build_course_cache($course);
    }
    $rs->close();
}
Пример #21
0
 /**
  * This function converts all of the base settings for an instance of
  * the old setaskment to the new format. Then it calls each of the plugins
  * to see if they can help upgrade this setaskment.
  * @param int $oldsetaskmentid (don't rely on the old setaskment type even being installed)
  * @param string $log This string gets appended to during the conversion process
  * @return bool true or false
  */
 public function upgrade_setaskment($oldsetaskmentid, &$log)
 {
     global $DB, $CFG, $USER;
     // Steps to upgrade an setaskment.
     core_php_time_limit::raise(ASSIGN_MAX_UPGRADE_TIME_SECS);
     // Get the module details.
     $oldmodule = $DB->get_record('modules', array('name' => 'setaskment'), '*', MUST_EXIST);
     $params = array('module' => $oldmodule->id, 'instance' => $oldsetaskmentid);
     $oldcoursemodule = $DB->get_record('course_modules', $params, '*', MUST_EXIST);
     $oldcontext = context_module::instance($oldcoursemodule->id);
     // We used to check for admin capability, but since Moodle 2.7 this is called
     // during restore of a mod_setaskment module.
     // Also note that we do not check for any mod_setaskment capabilities, because they can
     // be removed so that users don't add new instances of the broken old thing.
     if (!has_capability('mod/setask:addinstance', $oldcontext)) {
         $log = get_string('couldnotcreatenewsetaskmentinstance', 'mod_setask');
         return false;
     }
     // First insert an setask instance to get the id.
     $oldsetaskment = $DB->get_record('setaskment', array('id' => $oldsetaskmentid), '*', MUST_EXIST);
     $oldversion = get_config('setaskment_' . $oldsetaskment->setaskmenttype, 'version');
     $data = new stdClass();
     $data->course = $oldsetaskment->course;
     $data->name = $oldsetaskment->name;
     $data->intro = $oldsetaskment->intro;
     $data->introformat = $oldsetaskment->introformat;
     $data->alwaysshowdescription = 1;
     $data->sendnotifications = $oldsetaskment->emailteachers;
     $data->sendlatenotifications = $oldsetaskment->emailteachers;
     $data->duedate = $oldsetaskment->timedue;
     $data->allowsubmissionsfromdate = $oldsetaskment->timeavailable;
     $data->grade = $oldsetaskment->grade;
     $data->submissiondrafts = $oldsetaskment->resubmit;
     $data->requiresubmissionstatement = 0;
     $data->markingworkflow = 0;
     $data->markingallocation = 0;
     $data->cutoffdate = 0;
     // New way to specify no late submissions.
     if ($oldsetaskment->preventlate) {
         $data->cutoffdate = $data->duedate;
     }
     $data->teamsubmission = 0;
     $data->requireallteammemberssubmit = 0;
     $data->teamsubmissiongroupingid = 0;
     $data->blindmarking = 0;
     $data->attemptreopenmethod = 'none';
     $data->maxattempts = ASSIGN_UNLIMITED_ATTEMPTS;
     $newsetaskment = new setask(null, null, null);
     if (!$newsetaskment->add_instance($data, false)) {
         $log = get_string('couldnotcreatenewsetaskmentinstance', 'mod_setask');
         return false;
     }
     // Now create a new coursemodule from the old one.
     $newmodule = $DB->get_record('modules', array('name' => 'setask'), '*', MUST_EXIST);
     $newcoursemodule = $this->duplicate_course_module($oldcoursemodule, $newmodule->id, $newsetaskment->get_instance()->id);
     if (!$newcoursemodule) {
         $log = get_string('couldnotcreatenewcoursemodule', 'mod_setask');
         return false;
     }
     // Convert the base database tables (setaskment, submission, grade).
     // These are used to store information in case a rollback is required.
     $gradingarea = null;
     $gradingdefinitions = null;
     $gradeidmap = array();
     $completiondone = false;
     $gradesdone = false;
     // From this point we want to rollback on failure.
     $rollback = false;
     try {
         $newsetaskment->set_context(context_module::instance($newcoursemodule->id));
         // The course module has now been created - time to update the core tables.
         // Copy intro files.
         $newsetaskment->copy_area_files_for_upgrade($oldcontext->id, 'mod_setaskment', 'intro', 0, $newsetaskment->get_context()->id, 'mod_setask', 'intro', 0);
         // Get the plugins to do their bit.
         foreach ($newsetaskment->get_submission_plugins() as $plugin) {
             if ($plugin->can_upgrade($oldsetaskment->setaskmenttype, $oldversion)) {
                 $plugin->enable();
                 if (!$plugin->upgrade_settings($oldcontext, $oldsetaskment, $log)) {
                     $rollback = true;
                 }
             } else {
                 $plugin->disable();
             }
         }
         foreach ($newsetaskment->get_feedback_plugins() as $plugin) {
             if ($plugin->can_upgrade($oldsetaskment->setaskmenttype, $oldversion)) {
                 $plugin->enable();
                 if (!$plugin->upgrade_settings($oldcontext, $oldsetaskment, $log)) {
                     $rollback = true;
                 }
             } else {
                 $plugin->disable();
             }
         }
         // See if there is advanced grading upgrades required.
         $gradingarea = $DB->get_record('grading_areas', array('contextid' => $oldcontext->id, 'areaname' => 'submission'), '*', IGNORE_MISSING);
         if ($gradingarea) {
             $params = array('id' => $gradingarea->id, 'contextid' => $newsetaskment->get_context()->id, 'component' => 'mod_setask', 'areaname' => 'submissions');
             $DB->update_record('grading_areas', $params);
             $gradingdefinitions = $DB->get_records('grading_definitions', array('areaid' => $gradingarea->id));
         }
         // Upgrade availability data.
         \core_availability\info::update_dependency_id_across_course($newcoursemodule->course, 'course_modules', $oldcoursemodule->id, $newcoursemodule->id);
         // Upgrade completion data.
         $DB->set_field('course_modules_completion', 'coursemoduleid', $newcoursemodule->id, array('coursemoduleid' => $oldcoursemodule->id));
         $allcriteria = $DB->get_records('course_completion_criteria', array('moduleinstance' => $oldcoursemodule->id));
         foreach ($allcriteria as $criteria) {
             $criteria->module = 'setask';
             $criteria->moduleinstance = $newcoursemodule->id;
             $DB->update_record('course_completion_criteria', $criteria);
         }
         $completiondone = true;
         // Migrate log entries so we don't lose them.
         $logparams = array('cmid' => $oldcoursemodule->id, 'course' => $oldcoursemodule->course);
         $DB->set_field('log', 'module', 'setask', $logparams);
         $DB->set_field('log', 'cmid', $newcoursemodule->id, $logparams);
         // Copy all the submission data (and get plugins to do their bit).
         $oldsubmissions = $DB->get_records('setaskment_submissions', array('setaskment' => $oldsetaskmentid));
         foreach ($oldsubmissions as $oldsubmission) {
             $submission = new stdClass();
             $submission->setaskment = $newsetaskment->get_instance()->id;
             $submission->userid = $oldsubmission->userid;
             $submission->timecreated = $oldsubmission->timecreated;
             $submission->timemodified = $oldsubmission->timemodified;
             $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
             // Because in mod_setaskment there could only be one submission per student, it is always the latest.
             $submission->latest = 1;
             $submission->id = $DB->insert_record('setask_submission', $submission);
             if (!$submission->id) {
                 $log .= get_string('couldnotinsertsubmission', 'mod_setask', $submission->userid);
                 $rollback = true;
             }
             foreach ($newsetaskment->get_submission_plugins() as $plugin) {
                 if ($plugin->can_upgrade($oldsetaskment->setaskmenttype, $oldversion)) {
                     if (!$plugin->upgrade($oldcontext, $oldsetaskment, $oldsubmission, $submission, $log)) {
                         $rollback = true;
                     }
                 }
             }
             if ($oldsubmission->timemarked) {
                 // Submission has been graded - create a grade record.
                 $grade = new stdClass();
                 $grade->setaskment = $newsetaskment->get_instance()->id;
                 $grade->userid = $oldsubmission->userid;
                 $grade->grader = $oldsubmission->teacher;
                 $grade->timemodified = $oldsubmission->timemarked;
                 $grade->timecreated = $oldsubmission->timecreated;
                 $grade->grade = $oldsubmission->grade;
                 if ($oldsubmission->mailed) {
                     // The mailed flag goes in the flags table.
                     $flags = new stdClass();
                     $flags->userid = $oldsubmission->userid;
                     $flags->setaskment = $newsetaskment->get_instance()->id;
                     $flags->mailed = 1;
                     $DB->insert_record('setask_user_flags', $flags);
                 }
                 $grade->id = $DB->insert_record('setask_grades', $grade);
                 if (!$grade->id) {
                     $log .= get_string('couldnotinsertgrade', 'mod_setask', $grade->userid);
                     $rollback = true;
                 }
                 // Copy any grading instances.
                 if ($gradingarea) {
                     $gradeidmap[$grade->id] = $oldsubmission->id;
                     foreach ($gradingdefinitions as $definition) {
                         $params = array('definitionid' => $definition->id, 'itemid' => $oldsubmission->id);
                         $DB->set_field('grading_instances', 'itemid', $grade->id, $params);
                     }
                 }
                 foreach ($newsetaskment->get_feedback_plugins() as $plugin) {
                     if ($plugin->can_upgrade($oldsetaskment->setaskmenttype, $oldversion)) {
                         if (!$plugin->upgrade($oldcontext, $oldsetaskment, $oldsubmission, $grade, $log)) {
                             $rollback = true;
                         }
                     }
                 }
             }
         }
         $newsetaskment->update_calendar($newcoursemodule->id);
         // Reassociate grade_items from the old setaskment instance to the new setask instance.
         // This includes outcome linked grade_items.
         $params = array('setask', $newsetaskment->get_instance()->id, 'setaskment', $oldsetaskment->id);
         $sql = 'UPDATE {grade_items} SET itemmodule = ?, iteminstance = ? WHERE itemmodule = ? AND iteminstance = ?';
         $DB->execute($sql, $params);
         // Create a mapping record to map urls from the old to the new setaskment.
         $mapping = new stdClass();
         $mapping->oldcmid = $oldcoursemodule->id;
         $mapping->oldinstance = $oldsetaskment->id;
         $mapping->newcmid = $newcoursemodule->id;
         $mapping->newinstance = $newsetaskment->get_instance()->id;
         $mapping->timecreated = time();
         $DB->insert_record('setaskment_upgrade', $mapping);
         $gradesdone = true;
     } catch (Exception $exception) {
         $rollback = true;
         $log .= get_string('conversionexception', 'mod_setask', $exception->getMessage());
     }
     if ($rollback) {
         // Roll back the grades changes.
         if ($gradesdone) {
             // Reassociate grade_items from the new setask instance to the old setaskment instance.
             $params = array('setaskment', $oldsetaskment->id, 'setask', $newsetaskment->get_instance()->id);
             $sql = 'UPDATE {grade_items} SET itemmodule = ?, iteminstance = ? WHERE itemmodule = ? AND iteminstance = ?';
             $DB->execute($sql, $params);
         }
         // Roll back the completion changes.
         if ($completiondone) {
             $DB->set_field('course_modules_completion', 'coursemoduleid', $oldcoursemodule->id, array('coursemoduleid' => $newcoursemodule->id));
             $allcriteria = $DB->get_records('course_completion_criteria', array('moduleinstance' => $newcoursemodule->id));
             foreach ($allcriteria as $criteria) {
                 $criteria->module = 'setaskment';
                 $criteria->moduleinstance = $oldcoursemodule->id;
                 $DB->update_record('course_completion_criteria', $criteria);
             }
         }
         // Roll back the log changes.
         $logparams = array('cmid' => $newcoursemodule->id, 'course' => $newcoursemodule->course);
         $DB->set_field('log', 'module', 'setaskment', $logparams);
         $DB->set_field('log', 'cmid', $oldcoursemodule->id, $logparams);
         // Roll back the advanced grading update.
         if ($gradingarea) {
             foreach ($gradeidmap as $newgradeid => $oldsubmissionid) {
                 foreach ($gradingdefinitions as $definition) {
                     $DB->set_field('grading_instances', 'itemid', $oldsubmissionid, array('definitionid' => $definition->id, 'itemid' => $newgradeid));
                 }
             }
             $params = array('id' => $gradingarea->id, 'contextid' => $oldcontext->id, 'component' => 'mod_setaskment', 'areaname' => 'submission');
             $DB->update_record('grading_areas', $params);
         }
         $newsetaskment->delete_instance();
         return false;
     }
     // Delete the old setaskment (use object delete).
     $cm = get_coursemodule_from_id('', $oldcoursemodule->id, $oldcoursemodule->course);
     if ($cm) {
         course_delete_module($cm->id);
     }
     rebuild_course_cache($oldcoursemodule->course);
     return true;
 }
Пример #22
0
 /**
  * Process the file
  * This method should not normally be overidden
  * @param object $category
  * @return bool success
  */
 public function importprocess($category)
 {
     global $USER, $CFG, $DB, $OUTPUT;
     // reset the timer in case file upload was slow
     core_php_time_limit::raise();
     // STAGE 1: Parse the file
     echo $OUTPUT->notification(get_string('parsingquestions', 'question'), 'notifysuccess');
     if (!($lines = $this->readdata($this->filename))) {
         echo $OUTPUT->notification(get_string('cannotread', 'question'));
         return false;
     }
     if (!($questions = $this->readquestions($lines))) {
         // Extract all the questions
         echo $OUTPUT->notification(get_string('noquestionsinfile', 'question'));
         return false;
     }
     // STAGE 2: Write data to database
     echo $OUTPUT->notification(get_string('importingquestions', 'question', $this->count_questions($questions)), 'notifysuccess');
     // check for errors before we continue
     if ($this->stoponerror and $this->importerrors > 0) {
         echo $OUTPUT->notification(get_string('importparseerror', 'question'));
         return true;
     }
     // get list of valid answer grades
     $gradeoptionsfull = question_bank::fraction_options_full();
     // check answer grades are valid
     // (now need to do this here because of 'stop on error': MDL-10689)
     $gradeerrors = 0;
     $goodquestions = array();
     foreach ($questions as $question) {
         if (!empty($question->fraction) and is_array($question->fraction)) {
             $fractions = $question->fraction;
             $invalidfractions = array();
             foreach ($fractions as $key => $fraction) {
                 $newfraction = match_grade_options($gradeoptionsfull, $fraction, $this->matchgrades);
                 if ($newfraction === false) {
                     $invalidfractions[] = $fraction;
                 } else {
                     $fractions[$key] = $newfraction;
                 }
             }
             if ($invalidfractions) {
                 echo $OUTPUT->notification(get_string('invalidgrade', 'question', implode(', ', $invalidfractions)));
                 ++$gradeerrors;
                 continue;
             } else {
                 $question->fraction = $fractions;
             }
         }
         $goodquestions[] = $question;
     }
     $questions = $goodquestions;
     // check for errors before we continue
     if ($this->stoponerror && $gradeerrors > 0) {
         return false;
     }
     // count number of questions processed
     $count = 0;
     foreach ($questions as $question) {
         // Process and store each question
         // reset the php timeout
         core_php_time_limit::raise();
         // check for category modifiers
         if ($question->qtype == 'category') {
             if ($this->catfromfile) {
                 // find/create category object
                 $catpath = $question->category;
                 $newcategory = $this->create_category_path($catpath);
                 if (!empty($newcategory)) {
                     $this->category = $newcategory;
                 }
             }
             continue;
         }
         $question->context = $this->importcontext;
         $count++;
         echo "<hr /><p><b>{$count}</b>. " . $this->format_question_text($question) . "</p>";
         $question->category = $this->category->id;
         $question->stamp = make_unique_id_code();
         // Set the unique code (not to be changed)
         $question->createdby = $USER->id;
         $question->timecreated = time();
         $question->modifiedby = $USER->id;
         $question->timemodified = time();
         $fileoptions = array('subdirs' => false, 'maxfiles' => -1, 'maxbytes' => 0);
         $question->id = $DB->insert_record('question', $question);
         if (isset($question->questiontextitemid)) {
             $question->questiontext = file_save_draft_area_files($question->questiontextitemid, $this->importcontext->id, 'question', 'questiontext', $question->id, $fileoptions, $question->questiontext);
         } else {
             if (isset($question->questiontextfiles)) {
                 foreach ($question->questiontextfiles as $file) {
                     question_bank::get_qtype($question->qtype)->import_file($this->importcontext, 'question', 'questiontext', $question->id, $file);
                 }
             }
         }
         if (isset($question->generalfeedbackitemid)) {
             $question->generalfeedback = file_save_draft_area_files($question->generalfeedbackitemid, $this->importcontext->id, 'question', 'generalfeedback', $question->id, $fileoptions, $question->generalfeedback);
         } else {
             if (isset($question->generalfeedbackfiles)) {
                 foreach ($question->generalfeedbackfiles as $file) {
                     question_bank::get_qtype($question->qtype)->import_file($this->importcontext, 'question', 'generalfeedback', $question->id, $file);
                 }
             }
         }
         $DB->update_record('question', $question);
         $this->questionids[] = $question->id;
         // Now to save all the answers and type-specific options
         $result = question_bank::get_qtype($question->qtype)->save_question_options($question);
         if (!empty($CFG->usetags) && isset($question->tags)) {
             require_once $CFG->dirroot . '/tag/lib.php';
             tag_set('question', $question->id, $question->tags);
         }
         if (!empty($result->error)) {
             echo $OUTPUT->notification($result->error);
             return false;
         }
         if (!empty($result->notice)) {
             echo $OUTPUT->notification($result->notice);
             return true;
         }
         // Give the question a unique version stamp determined by question_hash()
         $DB->set_field('question', 'version', question_hash($question), array('id' => $question->id));
     }
     return true;
 }
Пример #23
0
/**
 * Function to be run periodically according to the scheduled task.
 *
 * Finds all posts that have yet to be mailed out, and mails them
 * out to all subscribers as well as other maintance tasks.
 *
 * NOTE: Since 2.7.2 this function is run by scheduled task rather
 * than standard cron.
 *
 * @todo MDL-44734 The function will be split up into seperate tasks.
 */
function forum_cron()
{
    global $CFG, $USER, $DB;
    $site = get_site();
    // All users that are subscribed to any post that needs sending,
    // please increase $CFG->extramemorylimit on large sites that
    // send notifications to a large number of users.
    $users = array();
    $userscount = 0;
    // Cached user counter - count($users) in PHP is horribly slow!!!
    // Status arrays.
    $mailcount = array();
    $errorcount = array();
    // caches
    $discussions = array();
    $forums = array();
    $courses = array();
    $coursemodules = array();
    $subscribedusers = array();
    // Posts older than 2 days will not be mailed.  This is to avoid the problem where
    // cron has not been running for a long time, and then suddenly people are flooded
    // with mail from the past few weeks or months
    $timenow = time();
    $endtime = $timenow - $CFG->maxeditingtime;
    $starttime = $endtime - 48 * 3600;
    // Two days earlier
    // Get the list of forum subscriptions for per-user per-forum maildigest settings.
    $digestsset = $DB->get_recordset('forum_digests', null, '', 'id, userid, forum, maildigest');
    $digests = array();
    foreach ($digestsset as $thisrow) {
        if (!isset($digests[$thisrow->forum])) {
            $digests[$thisrow->forum] = array();
        }
        $digests[$thisrow->forum][$thisrow->userid] = $thisrow->maildigest;
    }
    $digestsset->close();
    if ($posts = forum_get_unmailed_posts($starttime, $endtime, $timenow)) {
        // Mark them all now as being mailed.  It's unlikely but possible there
        // might be an error later so that a post is NOT actually mailed out,
        // but since mail isn't crucial, we can accept this risk.  Doing it now
        // prevents the risk of duplicated mails, which is a worse problem.
        if (!forum_mark_old_posts_as_mailed($endtime)) {
            mtrace('Errors occurred while trying to mark some posts as being mailed.');
            return false;
            // Don't continue trying to mail them, in case we are in a cron loop
        }
        // checking post validity, and adding users to loop through later
        foreach ($posts as $pid => $post) {
            $discussionid = $post->discussion;
            if (!isset($discussions[$discussionid])) {
                if ($discussion = $DB->get_record('forum_discussions', array('id' => $post->discussion))) {
                    $discussions[$discussionid] = $discussion;
                    \mod_forum\subscriptions::fill_subscription_cache($discussion->forum);
                    \mod_forum\subscriptions::fill_discussion_subscription_cache($discussion->forum);
                } else {
                    mtrace('Could not find discussion ' . $discussionid);
                    unset($posts[$pid]);
                    continue;
                }
            }
            $forumid = $discussions[$discussionid]->forum;
            if (!isset($forums[$forumid])) {
                if ($forum = $DB->get_record('forum', array('id' => $forumid))) {
                    $forums[$forumid] = $forum;
                } else {
                    mtrace('Could not find forum ' . $forumid);
                    unset($posts[$pid]);
                    continue;
                }
            }
            $courseid = $forums[$forumid]->course;
            if (!isset($courses[$courseid])) {
                if ($course = $DB->get_record('course', array('id' => $courseid))) {
                    $courses[$courseid] = $course;
                } else {
                    mtrace('Could not find course ' . $courseid);
                    unset($posts[$pid]);
                    continue;
                }
            }
            if (!isset($coursemodules[$forumid])) {
                if ($cm = get_coursemodule_from_instance('forum', $forumid, $courseid)) {
                    $coursemodules[$forumid] = $cm;
                } else {
                    mtrace('Could not find course module for forum ' . $forumid);
                    unset($posts[$pid]);
                    continue;
                }
            }
            // Caching subscribed users of each forum.
            if (!isset($subscribedusers[$forumid])) {
                $modcontext = context_module::instance($coursemodules[$forumid]->id);
                if ($subusers = \mod_forum\subscriptions::fetch_subscribed_users($forums[$forumid], 0, $modcontext, 'u.*', true)) {
                    foreach ($subusers as $postuser) {
                        // this user is subscribed to this forum
                        $subscribedusers[$forumid][$postuser->id] = $postuser->id;
                        $userscount++;
                        if ($userscount > FORUM_CRON_USER_CACHE) {
                            // Store minimal user info.
                            $minuser = new stdClass();
                            $minuser->id = $postuser->id;
                            $users[$postuser->id] = $minuser;
                        } else {
                            // Cache full user record.
                            forum_cron_minimise_user_record($postuser);
                            $users[$postuser->id] = $postuser;
                        }
                    }
                    // Release memory.
                    unset($subusers);
                    unset($postuser);
                }
            }
            $mailcount[$pid] = 0;
            $errorcount[$pid] = 0;
        }
    }
    if ($users && $posts) {
        $urlinfo = parse_url($CFG->wwwroot);
        $hostname = $urlinfo['host'];
        foreach ($users as $userto) {
            // Terminate if processing of any account takes longer than 2 minutes.
            core_php_time_limit::raise(120);
            mtrace('Processing user ' . $userto->id);
            // Init user caches - we keep the cache for one cycle only, otherwise it could consume too much memory.
            if (isset($userto->username)) {
                $userto = clone $userto;
            } else {
                $userto = $DB->get_record('user', array('id' => $userto->id));
                forum_cron_minimise_user_record($userto);
            }
            $userto->viewfullnames = array();
            $userto->canpost = array();
            $userto->markposts = array();
            // Setup this user so that the capabilities are cached, and environment matches receiving user.
            cron_setup_user($userto);
            // Reset the caches.
            foreach ($coursemodules as $forumid => $unused) {
                $coursemodules[$forumid]->cache = new stdClass();
                $coursemodules[$forumid]->cache->caps = array();
                unset($coursemodules[$forumid]->uservisible);
            }
            foreach ($posts as $pid => $post) {
                $discussion = $discussions[$post->discussion];
                $forum = $forums[$discussion->forum];
                $course = $courses[$forum->course];
                $cm =& $coursemodules[$forum->id];
                // Do some checks to see if we can bail out now.
                // Only active enrolled users are in the list of subscribers.
                // This does not necessarily mean that the user is subscribed to the forum or to the discussion though.
                if (!isset($subscribedusers[$forum->id][$userto->id])) {
                    // The user does not subscribe to this forum.
                    continue;
                }
                if (!\mod_forum\subscriptions::is_subscribed($userto->id, $forum, $post->discussion, $coursemodules[$forum->id])) {
                    // The user does not subscribe to this forum, or to this specific discussion.
                    continue;
                }
                // Don't send email if the forum is Q&A and the user has not posted.
                // Initial topics are still mailed.
                if ($forum->type == 'qanda' && !forum_get_user_posted_time($discussion->id, $userto->id) && $pid != $discussion->firstpost) {
                    mtrace('Did not email ' . $userto->id . ' because user has not posted in discussion');
                    continue;
                }
                // Get info about the sending user.
                if (array_key_exists($post->userid, $users)) {
                    // We might know the user already.
                    $userfrom = $users[$post->userid];
                    if (!isset($userfrom->idnumber)) {
                        // Minimalised user info, fetch full record.
                        $userfrom = $DB->get_record('user', array('id' => $userfrom->id));
                        forum_cron_minimise_user_record($userfrom);
                    }
                } else {
                    if ($userfrom = $DB->get_record('user', array('id' => $post->userid))) {
                        forum_cron_minimise_user_record($userfrom);
                        // Fetch only once if possible, we can add it to user list, it will be skipped anyway.
                        if ($userscount <= FORUM_CRON_USER_CACHE) {
                            $userscount++;
                            $users[$userfrom->id] = $userfrom;
                        }
                    } else {
                        mtrace('Could not find user ' . $post->userid . ', author of post ' . $post->id . '. Unable to send message.');
                        continue;
                    }
                }
                // Note: If we want to check that userto and userfrom are not the same person this is probably the spot to do it.
                // Setup global $COURSE properly - needed for roles and languages.
                cron_setup_user($userto, $course);
                // Fill caches.
                if (!isset($userto->viewfullnames[$forum->id])) {
                    $modcontext = context_module::instance($cm->id);
                    $userto->viewfullnames[$forum->id] = has_capability('moodle/site:viewfullnames', $modcontext);
                }
                if (!isset($userto->canpost[$discussion->id])) {
                    $modcontext = context_module::instance($cm->id);
                    $userto->canpost[$discussion->id] = forum_user_can_post($forum, $discussion, $userto, $cm, $course, $modcontext);
                }
                if (!isset($userfrom->groups[$forum->id])) {
                    if (!isset($userfrom->groups)) {
                        $userfrom->groups = array();
                        if (isset($users[$userfrom->id])) {
                            $users[$userfrom->id]->groups = array();
                        }
                    }
                    $userfrom->groups[$forum->id] = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid);
                    if (isset($users[$userfrom->id])) {
                        $users[$userfrom->id]->groups[$forum->id] = $userfrom->groups[$forum->id];
                    }
                }
                // Make sure groups allow this user to see this email.
                if ($discussion->groupid > 0 and $groupmode = groups_get_activity_groupmode($cm, $course)) {
                    // Groups are being used.
                    if (!groups_group_exists($discussion->groupid)) {
                        // Can't find group - be safe and don't this message.
                        continue;
                    }
                    if (!groups_is_member($discussion->groupid) and !has_capability('moodle/site:accessallgroups', $modcontext)) {
                        // Do not send posts from other groups when in SEPARATEGROUPS or VISIBLEGROUPS.
                        continue;
                    }
                }
                // Make sure we're allowed to see the post.
                if (!forum_user_can_see_post($forum, $discussion, $post, null, $cm)) {
                    mtrace('User ' . $userto->id . ' can not see ' . $post->id . '. Not sending message.');
                    continue;
                }
                // OK so we need to send the email.
                // Does the user want this post in a digest?  If so postpone it for now.
                $maildigest = forum_get_user_maildigest_bulk($digests, $userto, $forum->id);
                if ($maildigest > 0) {
                    // This user wants the mails to be in digest form.
                    $queue = new stdClass();
                    $queue->userid = $userto->id;
                    $queue->discussionid = $discussion->id;
                    $queue->postid = $post->id;
                    $queue->timemodified = $post->created;
                    $DB->insert_record('forum_queue', $queue);
                    continue;
                }
                // Prepare to actually send the post now, and build up the content.
                $cleanforumname = str_replace('"', "'", strip_tags(format_string($forum->name)));
                $userfrom->customheaders = array('Precedence: Bulk', 'List-Id: "' . $cleanforumname . '" <moodleforum' . $forum->id . '@' . $hostname . '>', 'List-Help: ' . $CFG->wwwroot . '/mod/forum/view.php?f=' . $forum->id, 'Message-ID: ' . forum_get_email_message_id($post->id, $userto->id, $hostname), 'X-Course-Id: ' . $course->id, 'X-Course-Name: ' . format_string($course->fullname, true));
                if ($post->parent) {
                    // This post is a reply, so add headers for threading (see MDL-22551).
                    $userfrom->customheaders[] = 'In-Reply-To: ' . forum_get_email_message_id($post->parent, $userto->id, $hostname);
                    $userfrom->customheaders[] = 'References: ' . forum_get_email_message_id($post->parent, $userto->id, $hostname);
                }
                $shortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id)));
                $a = new stdClass();
                $a->courseshortname = $shortname;
                $a->forumname = $cleanforumname;
                $a->subject = format_string($post->subject, true);
                $postsubject = html_to_text(get_string('postmailsubject', 'forum', $a));
                $posttext = forum_make_mail_text($course, $cm, $forum, $discussion, $post, $userfrom, $userto);
                $posthtml = forum_make_mail_html($course, $cm, $forum, $discussion, $post, $userfrom, $userto);
                // Send the post now!
                mtrace('Sending ', '');
                $eventdata = new stdClass();
                $eventdata->component = 'mod_forum';
                $eventdata->name = 'posts';
                $eventdata->userfrom = $userfrom;
                $eventdata->userto = $userto;
                $eventdata->subject = $postsubject;
                $eventdata->fullmessage = $posttext;
                $eventdata->fullmessageformat = FORMAT_PLAIN;
                $eventdata->fullmessagehtml = $posthtml;
                $eventdata->notification = 1;
                // If forum_replytouser is not set then send mail using the noreplyaddress.
                if (empty($CFG->forum_replytouser)) {
                    // Clone userfrom as it is referenced by $users.
                    $cloneduserfrom = clone $userfrom;
                    $cloneduserfrom->email = $CFG->noreplyaddress;
                    $eventdata->userfrom = $cloneduserfrom;
                }
                $smallmessagestrings = new stdClass();
                $smallmessagestrings->user = fullname($userfrom);
                $smallmessagestrings->forumname = "{$shortname}: " . format_string($forum->name, true) . ": " . $discussion->name;
                $smallmessagestrings->message = $post->message;
                // Make sure strings are in message recipients language.
                $eventdata->smallmessage = get_string_manager()->get_string('smallmessage', 'forum', $smallmessagestrings, $userto->lang);
                $contexturl = new moodle_url('/mod/forum/discuss.php', array('d' => $discussion->id), 'p' . $post->id);
                $eventdata->contexturl = $contexturl->out();
                $eventdata->contexturlname = $discussion->name;
                $mailresult = message_send($eventdata);
                if (!$mailresult) {
                    mtrace("Error: mod/forum/lib.php forum_cron(): Could not send out mail for id {$post->id} to user {$userto->id}" . " ({$userto->email}) .. not trying again.");
                    $errorcount[$post->id]++;
                } else {
                    $mailcount[$post->id]++;
                    // Mark post as read if forum_usermarksread is set off.
                    if (!$CFG->forum_usermarksread) {
                        $userto->markposts[$post->id] = $post->id;
                    }
                }
                mtrace('post ' . $post->id . ': ' . $post->subject);
            }
            // Mark processed posts as read.
            forum_tp_mark_posts_read($userto, $userto->markposts);
            unset($userto);
        }
    }
    if ($posts) {
        foreach ($posts as $post) {
            mtrace($mailcount[$post->id] . " users were sent post {$post->id}, '{$post->subject}'");
            if ($errorcount[$post->id]) {
                $DB->set_field('forum_posts', 'mailed', FORUM_MAILED_ERROR, array('id' => $post->id));
            }
        }
    }
    // release some memory
    unset($subscribedusers);
    unset($mailcount);
    unset($errorcount);
    cron_setup_user();
    $sitetimezone = $CFG->timezone;
    // Now see if there are any digest mails waiting to be sent, and if we should send them
    mtrace('Starting digest processing...');
    core_php_time_limit::raise(300);
    // terminate if not able to fetch all digests in 5 minutes
    if (!isset($CFG->digestmailtimelast)) {
        // To catch the first time
        set_config('digestmailtimelast', 0);
    }
    $timenow = time();
    $digesttime = usergetmidnight($timenow, $sitetimezone) + $CFG->digestmailtime * 3600;
    // Delete any really old ones (normally there shouldn't be any)
    $weekago = $timenow - 7 * 24 * 3600;
    $DB->delete_records_select('forum_queue', "timemodified < ?", array($weekago));
    mtrace('Cleaned old digest records');
    if ($CFG->digestmailtimelast < $digesttime and $timenow > $digesttime) {
        mtrace('Sending forum digests: ' . userdate($timenow, '', $sitetimezone));
        $digestposts_rs = $DB->get_recordset_select('forum_queue', "timemodified < ?", array($digesttime));
        if ($digestposts_rs->valid()) {
            // We have work to do
            $usermailcount = 0;
            //caches - reuse the those filled before too
            $discussionposts = array();
            $userdiscussions = array();
            foreach ($digestposts_rs as $digestpost) {
                if (!isset($posts[$digestpost->postid])) {
                    if ($post = $DB->get_record('forum_posts', array('id' => $digestpost->postid))) {
                        $posts[$digestpost->postid] = $post;
                    } else {
                        continue;
                    }
                }
                $discussionid = $digestpost->discussionid;
                if (!isset($discussions[$discussionid])) {
                    if ($discussion = $DB->get_record('forum_discussions', array('id' => $discussionid))) {
                        $discussions[$discussionid] = $discussion;
                    } else {
                        continue;
                    }
                }
                $forumid = $discussions[$discussionid]->forum;
                if (!isset($forums[$forumid])) {
                    if ($forum = $DB->get_record('forum', array('id' => $forumid))) {
                        $forums[$forumid] = $forum;
                    } else {
                        continue;
                    }
                }
                $courseid = $forums[$forumid]->course;
                if (!isset($courses[$courseid])) {
                    if ($course = $DB->get_record('course', array('id' => $courseid))) {
                        $courses[$courseid] = $course;
                    } else {
                        continue;
                    }
                }
                if (!isset($coursemodules[$forumid])) {
                    if ($cm = get_coursemodule_from_instance('forum', $forumid, $courseid)) {
                        $coursemodules[$forumid] = $cm;
                    } else {
                        continue;
                    }
                }
                $userdiscussions[$digestpost->userid][$digestpost->discussionid] = $digestpost->discussionid;
                $discussionposts[$digestpost->discussionid][$digestpost->postid] = $digestpost->postid;
            }
            $digestposts_rs->close();
            /// Finished iteration, let's close the resultset
            // Data collected, start sending out emails to each user
            foreach ($userdiscussions as $userid => $thesediscussions) {
                core_php_time_limit::raise(120);
                // terminate if processing of any account takes longer than 2 minutes
                cron_setup_user();
                mtrace(get_string('processingdigest', 'forum', $userid), '... ');
                // First of all delete all the queue entries for this user
                $DB->delete_records_select('forum_queue', "userid = ? AND timemodified < ?", array($userid, $digesttime));
                // Init user caches - we keep the cache for one cycle only,
                // otherwise it would unnecessarily consume memory.
                if (array_key_exists($userid, $users) and isset($users[$userid]->username)) {
                    $userto = clone $users[$userid];
                } else {
                    $userto = $DB->get_record('user', array('id' => $userid));
                    forum_cron_minimise_user_record($userto);
                }
                $userto->viewfullnames = array();
                $userto->canpost = array();
                $userto->markposts = array();
                // Override the language and timezone of the "current" user, so that
                // mail is customised for the receiver.
                cron_setup_user($userto);
                $postsubject = get_string('digestmailsubject', 'forum', format_string($site->shortname, true));
                $headerdata = new stdClass();
                $headerdata->sitename = format_string($site->fullname, true);
                $headerdata->userprefs = $CFG->wwwroot . '/user/edit.php?id=' . $userid . '&amp;course=' . $site->id;
                $posttext = get_string('digestmailheader', 'forum', $headerdata) . "\n\n";
                $headerdata->userprefs = '<a target="_blank" href="' . $headerdata->userprefs . '">' . get_string('digestmailprefs', 'forum') . '</a>';
                $posthtml = "<head>";
                /*                foreach ($CFG->stylesheets as $stylesheet) {
                                    //TODO: MDL-21120
                                    $posthtml .= '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'" />'."\n";
                                }*/
                $posthtml .= "</head>\n<body id=\"email\">\n";
                $posthtml .= '<p>' . get_string('digestmailheader', 'forum', $headerdata) . '</p><br /><hr size="1" noshade="noshade" />';
                foreach ($thesediscussions as $discussionid) {
                    core_php_time_limit::raise(120);
                    // to be reset for each post
                    $discussion = $discussions[$discussionid];
                    $forum = $forums[$discussion->forum];
                    $course = $courses[$forum->course];
                    $cm = $coursemodules[$forum->id];
                    //override language
                    cron_setup_user($userto, $course);
                    // Fill caches
                    if (!isset($userto->viewfullnames[$forum->id])) {
                        $modcontext = context_module::instance($cm->id);
                        $userto->viewfullnames[$forum->id] = has_capability('moodle/site:viewfullnames', $modcontext);
                    }
                    if (!isset($userto->canpost[$discussion->id])) {
                        $modcontext = context_module::instance($cm->id);
                        $userto->canpost[$discussion->id] = forum_user_can_post($forum, $discussion, $userto, $cm, $course, $modcontext);
                    }
                    $strforums = get_string('forums', 'forum');
                    $canunsubscribe = !\mod_forum\subscriptions::is_forcesubscribed($forum);
                    $canreply = $userto->canpost[$discussion->id];
                    $shortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id)));
                    $posttext .= "\n \n";
                    $posttext .= '=====================================================================';
                    $posttext .= "\n \n";
                    $posttext .= "{$shortname} -> {$strforums} -> " . format_string($forum->name, true);
                    if ($discussion->name != $forum->name) {
                        $posttext .= " -> " . format_string($discussion->name, true);
                    }
                    $posttext .= "\n";
                    $posttext .= $CFG->wwwroot . '/mod/forum/discuss.php?d=' . $discussion->id;
                    $posttext .= "\n";
                    $posthtml .= "<p><font face=\"sans-serif\">" . "<a target=\"_blank\" href=\"{$CFG->wwwroot}/course/view.php?id={$course->id}\">{$shortname}</a> -> " . "<a target=\"_blank\" href=\"{$CFG->wwwroot}/mod/forum/index.php?id={$course->id}\">{$strforums}</a> -> " . "<a target=\"_blank\" href=\"{$CFG->wwwroot}/mod/forum/view.php?f={$forum->id}\">" . format_string($forum->name, true) . "</a>";
                    if ($discussion->name == $forum->name) {
                        $posthtml .= "</font></p>";
                    } else {
                        $posthtml .= " -> <a target=\"_blank\" href=\"{$CFG->wwwroot}/mod/forum/discuss.php?d={$discussion->id}\">" . format_string($discussion->name, true) . "</a></font></p>";
                    }
                    $posthtml .= '<p>';
                    $postsarray = $discussionposts[$discussionid];
                    sort($postsarray);
                    foreach ($postsarray as $postid) {
                        $post = $posts[$postid];
                        if (array_key_exists($post->userid, $users)) {
                            // we might know him/her already
                            $userfrom = $users[$post->userid];
                            if (!isset($userfrom->idnumber)) {
                                $userfrom = $DB->get_record('user', array('id' => $userfrom->id));
                                forum_cron_minimise_user_record($userfrom);
                            }
                        } else {
                            if ($userfrom = $DB->get_record('user', array('id' => $post->userid))) {
                                forum_cron_minimise_user_record($userfrom);
                                if ($userscount <= FORUM_CRON_USER_CACHE) {
                                    $userscount++;
                                    $users[$userfrom->id] = $userfrom;
                                }
                            } else {
                                mtrace('Could not find user ' . $post->userid);
                                continue;
                            }
                        }
                        if (!isset($userfrom->groups[$forum->id])) {
                            if (!isset($userfrom->groups)) {
                                $userfrom->groups = array();
                                if (isset($users[$userfrom->id])) {
                                    $users[$userfrom->id]->groups = array();
                                }
                            }
                            $userfrom->groups[$forum->id] = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid);
                            if (isset($users[$userfrom->id])) {
                                $users[$userfrom->id]->groups[$forum->id] = $userfrom->groups[$forum->id];
                            }
                        }
                        $userfrom->customheaders = array("Precedence: Bulk");
                        $maildigest = forum_get_user_maildigest_bulk($digests, $userto, $forum->id);
                        if ($maildigest == 2) {
                            // Subjects and link only
                            $posttext .= "\n";
                            $posttext .= $CFG->wwwroot . '/mod/forum/discuss.php?d=' . $discussion->id;
                            $by = new stdClass();
                            $by->name = fullname($userfrom);
                            $by->date = userdate($post->modified);
                            $posttext .= "\n" . format_string($post->subject, true) . ' ' . get_string("bynameondate", "forum", $by);
                            $posttext .= "\n---------------------------------------------------------------------";
                            $by->name = "<a target=\"_blank\" href=\"{$CFG->wwwroot}/user/view.php?id={$userfrom->id}&amp;course={$course->id}\">{$by->name}</a>";
                            $posthtml .= '<div><a target="_blank" href="' . $CFG->wwwroot . '/mod/forum/discuss.php?d=' . $discussion->id . '#p' . $post->id . '">' . format_string($post->subject, true) . '</a> ' . get_string("bynameondate", "forum", $by) . '</div>';
                        } else {
                            // The full treatment
                            $posttext .= forum_make_mail_text($course, $cm, $forum, $discussion, $post, $userfrom, $userto, true);
                            $posthtml .= forum_make_mail_post($course, $cm, $forum, $discussion, $post, $userfrom, $userto, false, $canreply, true, false);
                            // Create an array of postid's for this user to mark as read.
                            if (!$CFG->forum_usermarksread) {
                                $userto->markposts[$post->id] = $post->id;
                            }
                        }
                    }
                    $footerlinks = array();
                    if ($canunsubscribe) {
                        $footerlinks[] = "<a href=\"{$CFG->wwwroot}/mod/forum/subscribe.php?id={$forum->id}\">" . get_string("unsubscribe", "forum") . "</a>";
                    } else {
                        $footerlinks[] = get_string("everyoneissubscribed", "forum");
                    }
                    $footerlinks[] = "<a href='{$CFG->wwwroot}/mod/forum/index.php?id={$forum->course}'>" . get_string("digestmailpost", "forum") . '</a>';
                    $posthtml .= "\n<div class='mdl-right'><font size=\"1\">" . implode('&nbsp;', $footerlinks) . '</font></div>';
                    $posthtml .= '<hr size="1" noshade="noshade" /></p>';
                }
                $posthtml .= '</body>';
                if (empty($userto->mailformat) || $userto->mailformat != 1) {
                    // This user DOESN'T want to receive HTML
                    $posthtml = '';
                }
                $attachment = $attachname = '';
                // Directly email forum digests rather than sending them via messaging, use the
                // site shortname as 'from name', the noreply address will be used by email_to_user.
                $mailresult = email_to_user($userto, $site->shortname, $postsubject, $posttext, $posthtml, $attachment, $attachname);
                if (!$mailresult) {
                    mtrace("ERROR: mod/forum/cron.php: Could not send out digest mail to user {$userto->id} " . "({$userto->email})... not trying again.");
                } else {
                    mtrace("success.");
                    $usermailcount++;
                    // Mark post as read if forum_usermarksread is set off
                    forum_tp_mark_posts_read($userto, $userto->markposts);
                }
            }
        }
        /// We have finishied all digest emails, update $CFG->digestmailtimelast
        set_config('digestmailtimelast', $timenow);
    }
    cron_setup_user();
    if (!empty($usermailcount)) {
        mtrace(get_string('digestsentusers', 'forum', $usermailcount));
    }
    if (!empty($CFG->forum_lastreadclean)) {
        $timenow = time();
        if ($CFG->forum_lastreadclean + 24 * 3600 < $timenow) {
            set_config('forum_lastreadclean', $timenow);
            mtrace('Removing old forum read tracking info...');
            forum_tp_clean_read_records();
        }
    } else {
        set_config('forum_lastreadclean', time());
    }
    return true;
}
Пример #24
0
/**
 * Resets the page customisations for all users.
 *
 * @param int $private Either MY_PAGE_PRIVATE or MY_PAGE_PUBLIC.
 * @param string $pagetype Either my-index or user-profile.
 * @return void
 */
function my_reset_page_for_all_users($private = MY_PAGE_PRIVATE, $pagetype = 'my-index')
{
    global $DB;
    // This may take a while. Raise the execution time limit.
    core_php_time_limit::raise();
    // Find all the user pages and all block instances in them.
    $sql = "SELECT bi.id\n        FROM {my_pages} p\n        JOIN {context} ctx ON ctx.instanceid = p.userid AND ctx.contextlevel = :usercontextlevel\n        JOIN {block_instances} bi ON bi.parentcontextid = ctx.id AND\n            bi.pagetypepattern = :pagetypepattern AND\n            (bi.subpagepattern IS NULL OR bi.subpagepattern = " . $DB->sql_concat("''", 'p.id') . ")\n        WHERE p.private = :private";
    $params = array('private' => $private, 'usercontextlevel' => CONTEXT_USER, 'pagetypepattern' => $pagetype);
    $blockids = $DB->get_fieldset_sql($sql, $params);
    // Wrap the SQL queries in a transaction.
    $transaction = $DB->start_delegated_transaction();
    // Delete the block instances.
    if (!empty($blockids)) {
        blocks_delete_instances($blockids);
    }
    // Finally delete the pages.
    $DB->delete_records_select('my_pages', 'userid IS NOT NULL AND private = :private', ['private' => $private]);
    // We should be good to go now.
    $transaction->allow_commit();
    // Trigger dashboard has been reset event.
    $eventparams = array('context' => context_system::instance(), 'other' => array('private' => $private, 'pagetype' => $pagetype));
    $event = \core\event\dashboards_reset::create($eventparams);
    $event->trigger();
}
Пример #25
0
 ** The client connection is not forever though. Once we reach
 ** CHAT_MAX_CLIENT_UPDATES, it will force the client to re-fetch it.
 **
 ** This buys us all the benefits that chatd has, minus the setup,
 ** as we are using apache to do the daemon handling.
 **
 **/
define('CHAT_MAX_CLIENT_UPDATES', 1000);
define('NO_MOODLE_COOKIES', true);
// Session not used here.
define('NO_OUTPUT_BUFFERING', true);
require '../../../config.php';
require '../lib.php';
// We are going to run for a long time.
// Avoid being terminated by php.
core_php_time_limit::raise();
$chatsid = required_param('chat_sid', PARAM_ALPHANUM);
$chatlasttime = optional_param('chat_lasttime', 0, PARAM_INT);
$chatlastrow = optional_param('chat_lastrow', 1, PARAM_INT);
$chatlastid = optional_param('chat_lastid', 0, PARAM_INT);
$url = new moodle_url('/mod/chat/gui_header_js/jsupdated.php', array('chat_sid' => $chatsid));
if ($chatlasttime !== 0) {
    $url->param('chat_lasttime', $chatlasttime);
}
if ($chatlastrow !== 1) {
    $url->param('chat_lastrow', $chatlastrow);
}
if ($chatlastid !== 1) {
    $url->param('chat_lastid', $chatlastid);
}
$PAGE->set_url($url);
Пример #26
0
 private function update_all_languages($lang)
 {
     // TODO: Use above $lang to update a single language pack.
     global $CFG;
     require_once $CFG->libdir . '/filelib.php';
     require_once $CFG->libdir . '/componentlib.class.php';
     \core_php_time_limit::raise();
     $installer = new \lang_installer();
     if (!($availablelangs = $installer->get_remote_list_of_languages())) {
         print_error('cannotdownloadlanguageupdatelist', 'error');
     }
     $md5array = array();
     // (string)langcode => (string)md5
     foreach ($availablelangs as $alang) {
         $md5array[$alang[0]] = $alang[1];
     }
     // filter out unofficial packs
     $currentlangs = array_keys(get_string_manager()->get_list_of_translations(true));
     $updateablelangs = array();
     foreach ($currentlangs as $clang) {
         if (!array_key_exists($clang, $md5array)) {
             $notice_ok[] = get_string('langpackupdateskipped', 'tool_langimport', $clang);
             continue;
         }
         $dest1 = $CFG->dataroot . '/lang/' . $clang;
         $dest2 = $CFG->dirroot . '/lang/' . $clang;
         if (file_exists($dest1 . '/langconfig.php') || file_exists($dest2 . '/langconfig.php')) {
             $updateablelangs[] = $clang;
         }
     }
     // then filter out packs that have the same md5 key
     $neededlangs = array();
     // all the packs that needs updating
     foreach ($updateablelangs as $ulang) {
         if (!$this->is_installed_lang($ulang, $md5array[$ulang])) {
             $neededlangs[] = $ulang;
         }
     }
     make_temp_directory('');
     make_upload_directory('lang');
     // clean-up currently installed versions of the packs
     foreach ($neededlangs as $packindex => $pack) {
         if ($pack == 'en') {
             continue;
         }
         // delete old directories
         $dest1 = $CFG->dataroot . '/lang/' . $pack;
         $dest2 = $CFG->dirroot . '/lang/' . $pack;
         $rm1 = false;
         $rm2 = false;
         if (file_exists($dest1)) {
             if (!remove_dir($dest1)) {
                 $notice_error[] = 'Could not delete old directory ' . $dest1 . ', update of ' . $pack . ' failed, please check permissions.';
                 unset($neededlangs[$packindex]);
                 continue;
             }
         }
         if (file_exists($dest2)) {
             if (!remove_dir($dest2)) {
                 $notice_error[] = 'Could not delete old directory ' . $dest2 . ', update of ' . $pack . ' failed, please check permissions.';
                 unset($neededlangs[$packindex]);
                 continue;
             }
         }
     }
     // install all needed language packs
     $installer->set_queue($neededlangs);
     $results = $installer->run();
     $updated = false;
     // any packs updated?
     foreach ($results as $langcode => $langstatus) {
         switch ($langstatus) {
             case \lang_installer::RESULT_DOWNLOADERROR:
                 $a = new stdClass();
                 $a->url = $installer->lang_pack_url($langcode);
                 $a->dest = $CFG->dataroot . '/lang';
                 print_error('remotedownloaderror', 'error', 'index.php', $a);
                 break;
             case \lang_installer::RESULT_INSTALLED:
                 $updated = true;
                 $notice_ok[] = get_string('langpackinstalled', 'tool_langimport', $langcode);
                 break;
             case \lang_installer::RESULT_UPTODATE:
                 $notice_ok[] = get_string('langpackuptodate', 'tool_langimport', $langcode);
                 break;
         }
     }
     if ($updated) {
         $notice_ok[] = get_string('langupdatecomplete', 'tool_langimport');
     } else {
         $notice_ok[] = get_string('nolangupdateneeded', 'tool_langimport');
     }
     unset($installer);
     get_string_manager()->reset_caches();
 }
Пример #27
0
 /**
  * Sync all meta course links.
  *
  * @param progress_trace $trace
  * @param int $courseid one course, empty mean all
  * @return int 0 means ok, 1 means error, 2 means plugin disabled
  */
 public function sync(progress_trace $trace, $courseid = null)
 {
     global $DB;
     if (!enrol_is_enabled('self')) {
         $trace->finished();
         return 2;
     }
     // Unfortunately this may take a long time, execution can be interrupted safely here.
     core_php_time_limit::raise();
     raise_memory_limit(MEMORY_HUGE);
     $trace->output('Verifying self-enrolments...');
     $params = array('now' => time(), 'useractive' => ENROL_USER_ACTIVE, 'courselevel' => CONTEXT_COURSE);
     $coursesql = "";
     if ($courseid) {
         $coursesql = "AND e.courseid = :courseid";
         $params['courseid'] = $courseid;
     }
     // Note: the logic of self enrolment guarantees that user logged in at least once (=== u.lastaccess set)
     //       and that user accessed course at least once too (=== user_lastaccess record exists).
     // First deal with users that did not log in for a really long time - they do not have user_lastaccess records.
     $sql = "SELECT e.*, ue.userid\n                  FROM {user_enrolments} ue\n                  JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'self' AND e.customint2 > 0)\n                  JOIN {user} u ON u.id = ue.userid\n                 WHERE :now - u.lastaccess > e.customint2\n                       {$coursesql}";
     $rs = $DB->get_recordset_sql($sql, $params);
     foreach ($rs as $instance) {
         $userid = $instance->userid;
         unset($instance->userid);
         $this->unenrol_user($instance, $userid);
         $days = $instance->customint2 / 60 * 60 * 24;
         $trace->output("unenrolling user {$userid} from course {$instance->courseid} as they have did not log in for at least {$days} days", 1);
     }
     $rs->close();
     // Now unenrol from course user did not visit for a long time.
     $sql = "SELECT e.*, ue.userid\n                  FROM {user_enrolments} ue\n                  JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'self' AND e.customint2 > 0)\n                  JOIN {user_lastaccess} ul ON (ul.userid = ue.userid AND ul.courseid = e.courseid)\n                 WHERE :now - ul.timeaccess > e.customint2\n                       {$coursesql}";
     $rs = $DB->get_recordset_sql($sql, $params);
     foreach ($rs as $instance) {
         $userid = $instance->userid;
         unset($instance->userid);
         $this->unenrol_user($instance, $userid);
         $days = $instance->customint2 / 60 * 60 * 24;
         $trace->output("unenrolling user {$userid} from course {$instance->courseid} as they have did not access course for at least {$days} days", 1);
     }
     $rs->close();
     $trace->output('...user self-enrolment updates finished.');
     $trace->finished();
     $this->process_expirations($trace, $courseid);
     return 0;
 }
Пример #28
0
 function update_field()
 {
     global $DB, $OUTPUT;
     // Get the old field data so that we can check whether the thumbnail dimensions have changed
     $oldfield = $DB->get_record('data_fields', array('id' => $this->field->id));
     $DB->update_record('data_fields', $this->field);
     // Have the thumbnail dimensions changed?
     if ($oldfield && ($oldfield->param4 != $this->field->param4 || $oldfield->param5 != $this->field->param5)) {
         // Check through all existing records and update the thumbnail
         if ($contents = $DB->get_records('data_content', array('fieldid' => $this->field->id))) {
             $fs = get_file_storage();
             if (count($contents) > 20) {
                 echo $OUTPUT->notification(get_string('resizingimages', 'data'), 'notifysuccess');
                 echo "\n\n";
                 // To make sure that ob_flush() has the desired effect
                 ob_flush();
             }
             foreach ($contents as $content) {
                 if (!($file = $fs->get_file($this->context->id, 'mod_data', 'content', $content->id, '/', $content->content))) {
                     continue;
                 }
                 if ($thumbfile = $fs->get_file($this->context->id, 'mod_data', 'content', $content->id, '/', 'thumb_' . $content->content)) {
                     $thumbfile->delete();
                 }
                 core_php_time_limit::raise(300);
                 // Might be slow!
                 $this->update_thumbnail($content, $file);
             }
         }
     }
     return true;
 }
Пример #29
0
 /**
  * Executes the backup
  * @return void Throws and exception of completes
  */
 public function execute_plan()
 {
     // Basic/initial prevention against time/memory limits
     core_php_time_limit::raise(1 * 60 * 60);
     // 1 hour for 1 course initially granted
     raise_memory_limit(MEMORY_EXTRA);
     // If this is not a course backup, inform the plan we are not
     // including all the activities for sure. This will affect any
     // task/step executed conditionally to stop including information
     // for section and activity backup. MDL-28180.
     if ($this->get_type() !== backup::TYPE_1COURSE) {
         $this->log('notifying plan about excluded activities by type', backup::LOG_DEBUG);
         $this->plan->set_excluding_activities();
     }
     return $this->plan->execute();
 }
Пример #30
0
/**
 * Import events from an iCalendar object into a course calendar.
 *
 * @param stdClass $ical The iCalendar object.
 * @param int $courseid The course ID for the calendar.
 * @param int $subscriptionid The subscription ID.
 * @return string A log of the import progress, including errors.
 */
function calendar_import_icalendar_events($ical, $courseid, $subscriptionid = null)
{
    global $DB;
    $return = '';
    $eventcount = 0;
    $updatecount = 0;
    // Large calendars take a while...
    if (!CLI_SCRIPT) {
        core_php_time_limit::raise(300);
    }
    // Mark all events in a subscription with a zero timestamp.
    if (!empty($subscriptionid)) {
        $sql = "UPDATE {event} SET timemodified = :time WHERE subscriptionid = :id";
        $DB->execute($sql, array('time' => 0, 'id' => $subscriptionid));
    }
    // Grab the timezone from the iCalendar file to be used later.
    if (isset($ical->properties['X-WR-TIMEZONE'][0]->value)) {
        $timezone = $ical->properties['X-WR-TIMEZONE'][0]->value;
    } else {
        $timezone = 'UTC';
    }
    foreach ($ical->components['VEVENT'] as $event) {
        $res = calendar_add_icalendar_event($event, $courseid, $subscriptionid, $timezone);
        switch ($res) {
            case CALENDAR_IMPORT_EVENT_UPDATED:
                $updatecount++;
                break;
            case CALENDAR_IMPORT_EVENT_INSERTED:
                $eventcount++;
                break;
            case 0:
                $return .= '<p>' . get_string('erroraddingevent', 'calendar') . ': ' . (empty($event->properties['SUMMARY']) ? '(' . get_string('notitle', 'calendar') . ')' : $event->properties['SUMMARY'][0]->value) . " </p>\n";
                break;
        }
    }
    $return .= "<p> " . get_string('eventsimported', 'calendar', $eventcount) . "</p>";
    $return .= "<p> " . get_string('eventsupdated', 'calendar', $updatecount) . "</p>";
    // Delete remaining zero-marked events since they're not in remote calendar.
    if (!empty($subscriptionid)) {
        $deletecount = $DB->count_records('event', array('timemodified' => 0, 'subscriptionid' => $subscriptionid));
        if (!empty($deletecount)) {
            $sql = "DELETE FROM {event} WHERE timemodified = :time AND subscriptionid = :id";
            $DB->execute($sql, array('time' => 0, 'id' => $subscriptionid));
            $return .= "<p> " . get_string('eventsdeleted', 'calendar') . ": {$deletecount} </p>\n";
        }
    }
    return $return;
}