Example #1
3
 /**
  * Reset contents of all database tables to initial values, reset caches, etc.
  *
  * Note: this is relatively slow (cca 2 seconds for pg and 7 for mysql) - please use with care!
  *
  * @static
  * @param bool $detectchanges
  *      true  - changes in global state and database are reported as errors
  *      false - no errors reported
  *      null  - only critical problems are reported as errors
  * @return void
  */
 public static function reset_all_data($detectchanges = false)
 {
     global $DB, $CFG, $USER, $SITE, $COURSE, $PAGE, $OUTPUT, $SESSION;
     // Stop any message redirection.
     phpunit_util::stop_message_redirection();
     // Stop any message redirection.
     phpunit_util::stop_phpmailer_redirection();
     // Stop any message redirection.
     phpunit_util::stop_event_redirection();
     // We used to call gc_collect_cycles here to ensure desctructors were called between tests.
     // This accounted for 25% of the total time running phpunit - so we removed it.
     // Show any unhandled debugging messages, the runbare() could already reset it.
     self::display_debugging_messages();
     self::reset_debugging();
     // reset global $DB in case somebody mocked it
     $DB = self::get_global_backup('DB');
     if ($DB->is_transaction_started()) {
         // we can not reset inside transaction
         $DB->force_transaction_rollback();
     }
     $resetdb = self::reset_database();
     $warnings = array();
     if ($detectchanges === true) {
         if ($resetdb) {
             $warnings[] = 'Warning: unexpected database modification, resetting DB state';
         }
         $oldcfg = self::get_global_backup('CFG');
         $oldsite = self::get_global_backup('SITE');
         foreach ($CFG as $k => $v) {
             if (!property_exists($oldcfg, $k)) {
                 $warnings[] = 'Warning: unexpected new $CFG->' . $k . ' value';
             } else {
                 if ($oldcfg->{$k} !== $CFG->{$k}) {
                     $warnings[] = 'Warning: unexpected change of $CFG->' . $k . ' value';
                 }
             }
             unset($oldcfg->{$k});
         }
         if ($oldcfg) {
             foreach ($oldcfg as $k => $v) {
                 $warnings[] = 'Warning: unexpected removal of $CFG->' . $k;
             }
         }
         if ($USER->id != 0) {
             $warnings[] = 'Warning: unexpected change of $USER';
         }
         if ($COURSE->id != $oldsite->id) {
             $warnings[] = 'Warning: unexpected change of $COURSE';
         }
     }
     if (ini_get('max_execution_time') != 0) {
         // This is special warning for all resets because we do not want any
         // libraries to mess with timeouts unintentionally.
         // Our PHPUnit integration is not supposed to change it either.
         if ($detectchanges !== false) {
             $warnings[] = 'Warning: max_execution_time was changed to ' . ini_get('max_execution_time');
         }
         set_time_limit(0);
     }
     // restore original globals
     $_SERVER = self::get_global_backup('_SERVER');
     $CFG = self::get_global_backup('CFG');
     $SITE = self::get_global_backup('SITE');
     $_GET = array();
     $_POST = array();
     $_FILES = array();
     $_REQUEST = array();
     $COURSE = $SITE;
     // reinitialise following globals
     $OUTPUT = new bootstrap_renderer();
     $PAGE = new moodle_page();
     $FULLME = null;
     $ME = null;
     $SCRIPT = null;
     // Empty sessison and set fresh new not-logged-in user.
     \core\session\manager::init_empty_session();
     // reset all static caches
     \core\event\manager::phpunit_reset();
     accesslib_clear_all_caches(true);
     get_string_manager()->reset_caches(true);
     reset_text_filters_cache(true);
     events_get_handlers('reset');
     core_text::reset_caches();
     get_message_processors(false, true);
     filter_manager::reset_caches();
     // Reset internal users.
     core_user::reset_internal_users();
     //TODO MDL-25290: add more resets here and probably refactor them to new core function
     // Reset course and module caches.
     if (class_exists('format_base')) {
         // If file containing class is not loaded, there is no cache there anyway.
         format_base::reset_course_cache(0);
     }
     get_fast_modinfo(0, 0, true);
     // Reset other singletons.
     if (class_exists('core_plugin_manager')) {
         core_plugin_manager::reset_caches(true);
     }
     if (class_exists('\\core\\update\\checker')) {
         \core\update\checker::reset_caches(true);
     }
     if (class_exists('\\core\\update\\deployer')) {
         \core\update\deployer::reset_caches(true);
     }
     // purge dataroot directory
     self::reset_dataroot();
     // restore original config once more in case resetting of caches changed CFG
     $CFG = self::get_global_backup('CFG');
     // inform data generator
     self::get_data_generator()->reset();
     // fix PHP settings
     error_reporting($CFG->debug);
     // verify db writes just in case something goes wrong in reset
     if (self::$lastdbwrites != $DB->perf_get_writes()) {
         error_log('Unexpected DB writes in phpunit_util::reset_all_data()');
         self::$lastdbwrites = $DB->perf_get_writes();
     }
     if ($warnings) {
         $warnings = implode("\n", $warnings);
         trigger_error($warnings, E_USER_WARNING);
     }
 }
Example #2
0
/**
 * Set highlighted section. Only one section can be highlighted at the time.
 *
 * @param int $courseid course id
 * @param int $marker highlight section with this number, 0 means remove higlightin
 * @return void
 */
function course_set_marker($courseid, $marker)
{
    global $DB;
    $DB->set_field("course", "marker", $marker, array('id' => $courseid));
    format_base::reset_course_cache($courseid);
}
Example #3
0
 /**
  * Reset contents of all database tables to initial values, reset caches, etc.
  */
 public static function reset_all_data()
 {
     // Reset database.
     self::reset_database();
     // Purge dataroot directory.
     self::reset_dataroot();
     // Reset all static caches.
     accesslib_clear_all_caches(true);
     // Reset the nasty strings list used during the last test.
     nasty_strings::reset_used_strings();
     filter_manager::reset_caches();
     // Reset course and module caches.
     if (class_exists('format_base')) {
         // If file containing class is not loaded, there is no cache there anyway.
         format_base::reset_course_cache(0);
     }
     get_fast_modinfo(0, 0, true);
     // Inform data generator.
     self::get_data_generator()->reset();
     // Initialise $CFG with default values. This is needed for behat cli process, so we don't have modified
     // $CFG values from the old run. @see set_config.
     initialise_cfg();
 }
Example #4
0
 /**
  * Loads all of the course sections into the navigation
  *
  * @param global_navigation $navigation
  * @param navigation_node $node The course node within the navigation
  */
 public function extend_course_navigation($navigation, navigation_node $node)
 {
     global $PAGE;
     // if section is specified in course/view.php, make sure it is expanded in navigation
     if ($navigation->includesectionnum === false) {
         $selectedsection = optional_param('section', null, PARAM_INT);
         if ($selectedsection !== null && (!defined('AJAX_SCRIPT') || AJAX_SCRIPT == '0') && $PAGE->url->compare(new moodle_url('/course/view.php'), URL_MATCH_BASE)) {
             $navigation->includesectionnum = $selectedsection;
         }
     }
     parent::extend_course_navigation($navigation, $node);
 }
Example #5
0
 /**
  * Updates format options for a section
  *
  * Section id is expected in $data->id (or $data['id'])
  * If $data does not contain property with the option name, the option will not be updated
  *
  * @param stdClass|array $data return value from {@link moodleform::get_data()} or array with data
  * @return bool whether there were any changes to the options values
  */
 public function update_section_format_options($data)
 {
     $data = (array) $data;
     // Resets the displayed image because changing the section name / details deletes the file.
     // See CONTRIB-4784.
     global $DB;
     $DB->set_field('format_grid_icon', 'displayedimageindex', 0, array('sectionid' => $data['id']));
     return parent::update_section_format_options($data);
 }
Example #6
0
 /**
  * Course-specific information to be output immediately above content on any course page
  *
  * See {@link format_base::course_header()} for usage
  *
  * @return null|renderable null for no output or object with data for plugin renderer
  */
 public function course_content_header()
 {
     global $PAGE;
     // if we are on course view page for particular section, return 'back to parent' control
     if ($this->get_viewed_section()) {
         $section = $this->get_section($this->get_viewed_section());
         if ($section->parent) {
             $sr = $this->find_collapsed_parent($section->parent);
             $text = new lang_string('backtosection', 'format_flexsections', $this->get_section_name($section->parent));
         } else {
             $sr = 0;
             $text = new lang_string('backtocourse', 'format_flexsections', $this->get_course()->fullname);
         }
         $url = $this->get_view_url($section->section, array('sr' => $sr));
         return new format_flexsections_edit_control('backto', $url, strip_tags($text));
     }
     // if we are on module view page, return 'back to section' control
     if ($PAGE->context && $PAGE->context->contextlevel == CONTEXT_MODULE && $PAGE->cm) {
         $sectionnum = $PAGE->cm->sectionnum;
         if ($sectionnum) {
             $text = new lang_string('backtosection', 'format_flexsections', $this->get_section_name($sectionnum));
         } else {
             $text = new lang_string('backtocourse', 'format_flexsections', $this->get_course()->fullname);
         }
         return new format_flexsections_edit_control('backto', $this->get_view_url($sectionnum), strip_tags($text));
     }
     return parent::course_content_header();
 }
Example #7
0
 /**
  * Prepares the templateable object to display section name
  *
  * @param \section_info|\stdClass $section
  * @param bool $linkifneeded
  * @param bool $editable
  * @param null|lang_string|string $edithint
  * @param null|lang_string|string $editlabel
  * @return \core\output\inplace_editable
  */
 public function inplace_editable_render_section_name($section, $linkifneeded = true, $editable = null, $edithint = null, $editlabel = null)
 {
     if (empty($edithint)) {
         $edithint = new lang_string('editsectionname', 'format_topics');
     }
     if (empty($editlabel)) {
         $title = get_section_name($section->course, $section);
         $editlabel = new lang_string('newsectionname', 'format_topics', $title);
     }
     return parent::inplace_editable_render_section_name($section, $linkifneeded, $editable, $edithint, $editlabel);
 }
 /**
  * Tests that all section options are copied when the course format is changed.
  * None of the data is copied.
  *
  * It is a future enhancement to copy;
  * 1. Only the relevant options.
  * 2. Only the data associated with relevant options.
  */
 public function test_course_format_options_restore_new_format()
 {
     global $DB, $CFG;
     $this->resetAfterTest(true);
     $this->setAdminUser();
     $CFG->enableavailability = true;
     $CFG->enablecompletion = true;
     // Create a course with some availability data set.
     $generator = $this->getDataGenerator();
     $course = $generator->create_course(array('format' => 'test_cs2_options', 'numsections' => 3, 'enablecompletion' => COMPLETION_ENABLED), array('createsections' => true));
     $newcourse = $generator->create_course(array('format' => 'test_cs_options', 'numsections' => 3, 'enablecompletion' => COMPLETION_ENABLED), array('createsections' => true));
     $courseobject = format_base::instance($course->id);
     $section = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 1), '*', MUST_EXIST);
     $data = array('id' => $section->id, 'numdaystocomplete' => 2, 'secondparameter' => 8);
     $courseobject->update_section_format_options($data);
     // Backup and restore it.
     $this->backup_and_restore($course, $newcourse);
     $newcourseobject = format_base::instance($newcourse->id);
     $sectionoptions = $newcourseobject->get_format_options(1);
     $this->assertArrayHasKey('numdaystocomplete', $sectionoptions);
     $this->assertArrayHasKey('secondparameter', $sectionoptions);
     $this->assertEquals(0, $sectionoptions['numdaystocomplete']);
     $this->assertEquals(0, $sectionoptions['secondparameter']);
 }
Example #9
0
 /**
  * Reset contents of all database tables to initial values, reset caches, etc.
  *
  * Note: this is relatively slow (cca 2 seconds for pg and 7 for mysql) - please use with care!
  *
  * @static
  * @param bool $logchanges log changes in global state and database in error log
  * @return void
  */
 public static function reset_all_data($logchanges = false)
 {
     global $DB, $CFG, $USER, $SITE, $COURSE, $PAGE, $OUTPUT, $SESSION;
     // Stop any message redirection.
     phpunit_util::stop_message_redirection();
     // Release memory and indirectly call destroy() methods to release resource handles, etc.
     gc_collect_cycles();
     // Show any unhandled debugging messages, the runbare() could already reset it.
     self::display_debugging_messages();
     self::reset_debugging();
     // reset global $DB in case somebody mocked it
     $DB = self::get_global_backup('DB');
     if ($DB->is_transaction_started()) {
         // we can not reset inside transaction
         $DB->force_transaction_rollback();
     }
     $resetdb = self::reset_database();
     $warnings = array();
     if ($logchanges) {
         if ($resetdb) {
             $warnings[] = 'Warning: unexpected database modification, resetting DB state';
         }
         $oldcfg = self::get_global_backup('CFG');
         $oldsite = self::get_global_backup('SITE');
         foreach ($CFG as $k => $v) {
             if (!property_exists($oldcfg, $k)) {
                 $warnings[] = 'Warning: unexpected new $CFG->' . $k . ' value';
             } else {
                 if ($oldcfg->{$k} !== $CFG->{$k}) {
                     $warnings[] = 'Warning: unexpected change of $CFG->' . $k . ' value';
                 }
             }
             unset($oldcfg->{$k});
         }
         if ($oldcfg) {
             foreach ($oldcfg as $k => $v) {
                 $warnings[] = 'Warning: unexpected removal of $CFG->' . $k;
             }
         }
         if ($USER->id != 0) {
             $warnings[] = 'Warning: unexpected change of $USER';
         }
         if ($COURSE->id != $oldsite->id) {
             $warnings[] = 'Warning: unexpected change of $COURSE';
         }
     }
     // restore original globals
     $_SERVER = self::get_global_backup('_SERVER');
     $CFG = self::get_global_backup('CFG');
     $SITE = self::get_global_backup('SITE');
     $COURSE = $SITE;
     // reinitialise following globals
     $OUTPUT = new bootstrap_renderer();
     $PAGE = new moodle_page();
     $FULLME = null;
     $ME = null;
     $SCRIPT = null;
     $SESSION = new stdClass();
     $_SESSION['SESSION'] =& $SESSION;
     // set fresh new not-logged-in user
     $user = new stdClass();
     $user->id = 0;
     $user->mnethostid = $CFG->mnet_localhost_id;
     session_set_user($user);
     // reset all static caches
     accesslib_clear_all_caches(true);
     get_string_manager()->reset_caches(true);
     reset_text_filters_cache(true);
     events_get_handlers('reset');
     textlib::reset_caches();
     if (class_exists('repository')) {
         repository::reset_caches();
     }
     filter_manager::reset_caches();
     //TODO MDL-25290: add more resets here and probably refactor them to new core function
     // Reset course and module caches.
     if (class_exists('format_base')) {
         // If file containing class is not loaded, there is no cache there anyway.
         format_base::reset_course_cache(0);
     }
     get_fast_modinfo(0, 0, true);
     // Reset other singletons.
     if (class_exists('plugin_manager')) {
         plugin_manager::reset_caches(true);
     }
     if (class_exists('available_update_checker')) {
         available_update_checker::reset_caches(true);
     }
     if (class_exists('available_update_deployer')) {
         available_update_deployer::reset_caches(true);
     }
     // purge dataroot directory
     self::reset_dataroot();
     // restore original config once more in case resetting of caches changed CFG
     $CFG = self::get_global_backup('CFG');
     // inform data generator
     self::get_data_generator()->reset();
     // fix PHP settings
     error_reporting($CFG->debug);
     // verify db writes just in case something goes wrong in reset
     if (self::$lastdbwrites != $DB->perf_get_writes()) {
         error_log('Unexpected DB writes in phpunit_util::reset_all_data()');
         self::$lastdbwrites = $DB->perf_get_writes();
     }
     if ($warnings) {
         $warnings = implode("\n", $warnings);
         trigger_error($warnings, E_USER_WARNING);
     }
 }
 /**
  * Tests that all section options are copied when the course format is changed.
  * None of the data is copied.
  *
  * It is a future enhancement to copy;
  * 1. Only the relevant options.
  * 2. Only the data associated with relevant options.
  */
 public function test_course_format_options_restore_new_format()
 {
     global $DB, $CFG;
     $this->resetAfterTest(true);
     $this->setAdminUser();
     // Create a source course using the test_cs2_options format.
     $generator = $this->getDataGenerator();
     $course = $generator->create_course(array('format' => 'test_cs2_options', 'numsections' => 3, 'enablecompletion' => COMPLETION_ENABLED), array('createsections' => true));
     // Create a target course using test_cs_options format.
     $newcourse = $generator->create_course(array('format' => 'test_cs_options', 'numsections' => 3, 'enablecompletion' => COMPLETION_ENABLED), array('createsections' => true));
     // Set section 2 to have both options, and a name.
     $courseobject = format_base::instance($course->id);
     $section = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 2), '*', MUST_EXIST);
     $data = array('id' => $section->id, 'numdaystocomplete' => 2, 'secondparameter' => 8);
     $courseobject->update_section_format_options($data);
     $DB->set_field('course_sections', 'name', 'Frogs', array('id' => $section->id));
     // Backup and restore to the new course using 'add to existing' so it
     // keeps the current (test_cs_options) format.
     $this->backup_and_restore($course, $newcourse, backup::TARGET_EXISTING_ADDING);
     // Check that the section contains the options suitable for the new
     // format and that even the one with the same name as from the old format
     // has NOT been set.
     $newcourseobject = format_base::instance($newcourse->id);
     $sectionoptions = $newcourseobject->get_format_options(2);
     $this->assertArrayHasKey('numdaystocomplete', $sectionoptions);
     $this->assertArrayNotHasKey('secondparameter', $sectionoptions);
     $this->assertEquals(0, $sectionoptions['numdaystocomplete']);
     // However, the name should have been changed, as this does not depend
     // on the format.
     $modinfo = get_fast_modinfo($newcourse->id);
     $section = $modinfo->get_section_info(2);
     $this->assertEquals('Frogs', $section->name);
 }
Example #11
0
/**
 * Rebuilds the cached list of course activities stored in the database
 * @param int $courseid - id of course to rebuild, empty means all
 * @param boolean $clearonly - only clear the modinfo fields, gets rebuild automatically on the fly
 */
function rebuild_course_cache($courseid = 0, $clearonly = false)
{
    global $COURSE, $SITE, $DB, $CFG;
    // 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);
    }
    if ($clearonly) {
        if (empty($courseid)) {
            $DB->set_field('course', 'modinfo', null);
            $DB->set_field('course', 'sectioncache', null);
        } else {
            // Clear both fields in one update
            $resetobj = (object) array('id' => $courseid, 'modinfo' => null, 'sectioncache' => null);
            $DB->update_record('course', $resetobj);
        }
        // update cached global COURSE too ;-)
        if ($courseid == $COURSE->id or empty($courseid)) {
            $COURSE->modinfo = null;
            $COURSE->sectioncache = null;
        }
        if ($courseid == $SITE->id) {
            $SITE->modinfo = null;
            $SITE->sectioncache = null;
        }
        // reset the fast modinfo cache
        get_fast_modinfo($courseid, 0, true);
        return;
    }
    require_once "{$CFG->dirroot}/course/lib.php";
    if ($courseid) {
        $select = array('id' => $courseid);
    } else {
        $select = array();
        @set_time_limit(0);
        // this could take a while!   MDL-10954
    }
    $rs = $DB->get_recordset("course", $select, '', 'id,fullname');
    foreach ($rs as $course) {
        $modinfo = serialize(get_array_of_activities($course->id));
        $sectioncache = serialize(course_modinfo::build_section_cache($course->id));
        $updateobj = (object) array('id' => $course->id, 'modinfo' => $modinfo, 'sectioncache' => $sectioncache);
        $DB->update_record("course", $updateobj);
        // update cached global COURSE too ;-)
        if ($course->id == $COURSE->id) {
            $COURSE->modinfo = $modinfo;
            $COURSE->sectioncache = $sectioncache;
        }
        if ($course->id == $SITE->id) {
            $SITE->modinfo = $modinfo;
            $SITE->sectioncache = $sectioncache;
        }
    }
    $rs->close();
    // reset the fast modinfo cache
    get_fast_modinfo($courseid, 0, true);
}
Example #12
0
 /**
  * Save the new setting
  *
  * @param string $data The new value to save
  * @return string empty or error message
  */
 public function write_setting($data)
 {
     global $DB, $SITE;
     $record = new stdClass();
     $record->id = $SITE->id;
     $record->{$this->name} = $data;
     $record->timemodified = time();
     $SITE->{$this->name} = $data;
     course_get_format($SITE)->update_course_format_options($record);
     $DB->update_record('course', $record);
     // There is something wrong in cache updates somewhere, let's reset everything.
     format_base::reset_course_cache();
     return '';
 }
Example #13
0
 /**
  * Is the section passed in the current section?
  *
  * @param stdClass $section The course_section entry from the DB
  * @return bool true if the section is current
  */
 public function is_section_current($section)
 {
     $tcsettings = $this->get_settings();
     if ($tcsettings['layoutstructure'] == 2 || $tcsettings['layoutstructure'] == 3) {
         if ($section->section < 1) {
             return false;
         }
         $timenow = time();
         $dates = $this->format_collblct_get_section_dates($section, $this->get_course());
         return $timenow >= $dates->start && $timenow < $dates->end;
     } else {
         if ($tcsettings['layoutstructure'] == 5) {
             if ($section->section < 1) {
                 return false;
             }
             $timenow = time();
             $day = $this->format_collblct_get_section_day($section, $this->get_course());
             $onedayseconds = 86400;
             return $timenow >= $day && $timenow < $day + $onedayseconds;
         } else {
             return parent::is_section_current($section);
         }
     }
 }
Example #14
0
 /**
  * Adds format options elements to the course/section edit form
  *
  * This function is called from {@link course_edit_form::definition_after_data()}
  *
  * @param MoodleQuickForm $mform form the elements are added to
  * @param bool $forsection 'true' if this is a section edit form, 'false' if this is course edit form
  * @return array array of references to the added form elements
  */
 public function create_edit_form_elements(&$mform, $forsection = true)
 {
     global $PAGE, $CFG;
     if ($PAGE->pagetype == 'course-edit') {
         $elements = parent::create_edit_form_elements($mform, $forsection);
         // Increase the number of sections combo box values if the user has increased the number of sections
         // using the icon on the course page beyond course 'maxsections' or course 'maxsections' has been
         // reduced below the number of sections already set for the course on the site administration course
         // defaults page.  This is so that the number of sections is not reduced leaving unintended orphaned
         // activities / resources.
         if (!$forsection) {
             $maxsections = get_config('moodlecourse', 'maxsections');
             $numsections = $mform->getElementValue('numsections');
             $numsections = $numsections[0];
             if ($numsections > $maxsections) {
                 $element = $mform->getElement('numsections');
                 for ($i = $maxsections + 1; $i <= $numsections; $i++) {
                     $element->addOption("{$i}", $i);
                 }
             }
         }
         return $elements;
     } else {
         $validationerror = optional_param('validationerror', null, PARAM_INT);
         $mform->addElement('header', 'gpssettings', new lang_string('editsection_geo_heading', 'format_gps'));
         $mform->addHelpButton('gpssettings', 'gpshelp', 'format_gps');
         if ($validationerror == 'yes') {
             $error = html_writer::div(new lang_string('validationerror', 'format_gps'), 'bold red error');
             $errorlabel = html_writer::div(new lang_string('error'), 'bold red error');
             $mform->addElement('static', 'validationerrror', $errorlabel, $error);
             $mform->addHelpButton('validationerrror', 'errorhelp', 'format_gps');
         }
         $mform->addElement('checkbox', 'format_gps_restricted', new lang_string('active', 'format_gps'));
         $mform->setDefault('format_gps_restricted', FORMAT_GPS_UNRESTRICTED);
         $attributes = array('size' => '100', 'width' => '500', 'maxlength' => '100');
         $mform->addElement('text', 'format_gps_address', new lang_string('address', 'format_gps'), $attributes);
         $mform->setType('format_gps_address', PARAM_TEXT);
         $mform->addElement('text', 'format_gps_latitude', new lang_string('latitude', 'format_gps'));
         $mform->addElement('text', 'format_gps_longitude', new lang_string('longitude', 'format_gps'));
         $mform->addRule('format_gps_address', null, 'maxlength', 255, 'client');
         $mform->addRule('format_gps_longitude', null, 'numeric', null, 'client');
         $mform->addRule('format_gps_longitude', null, 'numeric', null, 'client');
         $mform->addRule('format_gps_latitude', null, 'numeric', null, 'client');
         $mform->setType('format_gps_latitude', PARAM_FLOAT);
         $mform->setType('format_gps_longitude', PARAM_FLOAT);
         $mform->disabledIf('format_gps_address', 'format_gps_restricted', 'notchecked');
         $mform->disabledIf('format_gps_latitude', 'format_gps_restricted', 'notchecked');
         $mform->disabledIf('format_gps_longitude', 'format_gps_restricted', 'notchecked');
     }
 }
Example #15
0
/**
 * Delete a course, including all related data from the database, and any associated files.
 *
 * @param mixed $courseorid The id of the course or course object to delete.
 * @param bool $showfeedback Whether to display notifications of each action the function performs.
 * @return bool true if all the removals succeeded. false if there were any failures. If this
 *             method returns false, some of the removals will probably have succeeded, and others
 *             failed, but you have no way of knowing which.
 */
function delete_course($courseorid, $showfeedback = true)
{
    global $DB;
    if (is_object($courseorid)) {
        $courseid = $courseorid->id;
        $course = $courseorid;
    } else {
        $courseid = $courseorid;
        if (!($course = $DB->get_record('course', array('id' => $courseid)))) {
            return false;
        }
    }
    $context = context_course::instance($courseid);
    // Frontpage course can not be deleted!!
    if ($courseid == SITEID) {
        return false;
    }
    // Allow plugins to use this course before we completely delete it.
    if ($pluginsfunction = get_plugins_with_function('pre_course_delete')) {
        foreach ($pluginsfunction as $plugintype => $plugins) {
            foreach ($plugins as $pluginfunction) {
                $pluginfunction($course);
            }
        }
    }
    // Make the course completely empty.
    remove_course_contents($courseid, $showfeedback);
    // Delete the course and related context instance.
    context_helper::delete_instance(CONTEXT_COURSE, $courseid);
    $DB->delete_records("course", array("id" => $courseid));
    $DB->delete_records("course_format_options", array("courseid" => $courseid));
    // Reset all course related caches here.
    if (class_exists('format_base', false)) {
        format_base::reset_course_cache($courseid);
    }
    // Trigger a course deleted event.
    $event = \core\event\course_deleted::create(array('objectid' => $course->id, 'context' => $context, 'other' => array('shortname' => $course->shortname, 'fullname' => $course->fullname, 'idnumber' => $course->idnumber)));
    $event->add_record_snapshot('course', $course);
    $event->trigger();
    return true;
}
Example #16
0
 /**
  * Returns the list of blocks to be automatically added for the newly created course
  *
  * This function checks the existence of the file config.php in the course format folder.
  * If file exists and contains the code
  * $format['defaultblocks'] = 'leftblock1,leftblock2:rightblock1,rightblock2';
  * these blocks are used, otherwise parent function is called
  *
  * @return array of default blocks, must contain two keys BLOCK_POS_LEFT and BLOCK_POS_RIGHT
  *     each of values is an array of block names (for left and right side columns)
  */
 public function get_default_blocks()
 {
     global $CFG;
     $formatconfig = $CFG->dirroot . '/course/format/' . $this->format . '/config.php';
     $format = array();
     // initialize array in external file
     if (is_readable($formatconfig)) {
         include $formatconfig;
     }
     if (!empty($format['defaultblocks'])) {
         return blocks_parse_default_blocks_list($format['defaultblocks']);
     }
     return parent::get_default_blocks();
 }
Example #17
0
 /**
  * Adds format options elements to the course/section edit form.
  *
  * This function is called from {@link course_edit_form::definition_after_data()}.
  *
  * @param MoodleQuickForm $mform form the elements are added to.
  * @param bool $forsection 'true' if this is a section edit form, 'false' if this is course edit form.
  * @return array array of references to the added form elements.
  */
 public function create_edit_form_elements(&$mform, $forsection = false)
 {
     $elements = parent::create_edit_form_elements($mform, $forsection);
     // Increase the number of sections combo box values if the user has increased the number of sections
     // using the icon on the course page beyond course 'maxsections' or course 'maxsections' has been
     // reduced below the number of sections already set for the course on the site administration course
     // defaults page.  This is so that the number of sections is not reduced leaving unintended orphaned
     // activities / resources.
     if (!$forsection) {
         $maxsections = get_config('moodlecourse', 'maxsections');
         $numsections = $mform->getElementValue('numsections');
         $numsections = $numsections[0];
         if ($numsections > $maxsections) {
             $element = $mform->getElement('numsections');
             for ($i = $maxsections + 1; $i <= $numsections; $i++) {
                 $element->addOption("{$i}", $i);
             }
         }
     }
     return $elements;
 }
Example #18
0
 /**
  * Reset contents of all database tables to initial values, reset caches, etc.
  */
 public static function reset_all_data()
 {
     // Reset database.
     self::reset_database();
     // Purge dataroot directory.
     self::reset_dataroot();
     // Reset all static caches.
     accesslib_clear_all_caches(true);
     // Reset the nasty strings list used during the last test.
     nasty_strings::reset_used_strings();
     filter_manager::reset_caches();
     // Reset course and module caches.
     if (class_exists('format_base')) {
         // If file containing class is not loaded, there is no cache there anyway.
         format_base::reset_course_cache(0);
     }
     get_fast_modinfo(0, 0, true);
     // Inform data generator.
     self::get_data_generator()->reset();
 }
Example #19
0
 /**
  * Allows course format to execute code on moodle_page::set_cm()
  *
  * If we are inside the main module for this course, remove extra node level
  * from navigation: substitute course node with activity node, move all children
  *
  * @param moodle_page $page instance of page calling set_cm
  */
 public function page_set_cm(moodle_page $page)
 {
     global $PAGE;
     parent::page_set_cm($page);
     if ($PAGE == $page && ($cm = $this->get_activity()) && $cm->uservisible && $cm->id === $page->cm->id && ($activitynode = $page->navigation->find($cm->id, navigation_node::TYPE_ACTIVITY)) && ($node = $page->navigation->find($page->course->id, navigation_node::TYPE_COURSE))) {
         // Substitute course node with activity node, move all children.
         $node->action = $activitynode->action;
         $node->type = $activitynode->type;
         $node->id = $activitynode->id;
         $node->key = $activitynode->key;
         $node->isactive = $node->isactive || $activitynode->isactive;
         $node->icon = null;
         if ($activitynode->children->count()) {
             foreach ($activitynode->children as &$child) {
                 $child->remove();
                 $node->add_node($child);
             }
         } else {
             $node->search_for_active_node();
         }
         $activitynode->remove();
     }
 }
Example #20
0
    /**
     * Is the section passed in the current section?
     *
     * @param stdClass $section The course_section entry from the DB
     * @return bool true if the section is current
     */
    public function is_section_current($section) {
        $tcsettings = $this->get_settings();
        if (($tcsettings['layoutstructure'] == 2) || ($tcsettings['layoutstructure'] == 3)) {
            if ($section->section < 1) {
                return false;
            }

            $timenow = time();
            $dates = $this->format_topcoll_get_section_dates($section, $this->get_course());

            return (($timenow >= $dates->start) && ($timenow < $dates->end));
        } else if ($tcsettings['layoutstructure'] == 5) {
            if ($section->section < 1) {
                return false;
            }

            $timenow = time();
            $day = $this->format_topcoll_get_section_day($section, $this->get_course());
            $onedayseconds = 86400;
            return (($timenow >= $day) && ($timenow < ($day + $onedayseconds)));
        } else {
            return parent::is_section_current($section);
        }
    }
Example #21
0
 /**
  * Save the new setting
  *
  * @param string $data The new value to save
  * @return string empty or error message
  */
 public function write_setting($data)
 {
     global $DB, $SITE, $COURSE;
     $record = new stdClass();
     $record->id = $SITE->id;
     $record->{$this->name} = $data;
     $record->timemodified = time();
     course_get_format($SITE)->update_course_format_options($record);
     $DB->update_record('course', $record);
     // Reset caches.
     $SITE = $DB->get_record('course', array('id' => $SITE->id), '*', MUST_EXIST);
     if ($SITE->id == $COURSE->id) {
         $COURSE = $SITE;
     }
     format_base::reset_course_cache($SITE->id);
     return '';
 }
Example #22
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();
}
Example #23
0
 /**
  * Resets cache for the course (or all caches)
  * To be called from {@link rebuild_course_cache()}
  *
  * @param int $courseid
  */
 public static final function reset_course_cache($courseid = 0)
 {
     if ($courseid) {
         if (isset(self::$instances[$courseid])) {
             foreach (self::$instances[$courseid] as $format => $object) {
                 // in case somebody keeps the reference to course format object
                 self::$instances[$courseid][$format]->course = false;
                 self::$instances[$courseid][$format]->formatoptions = array();
             }
             unset(self::$instances[$courseid]);
         }
     } else {
         self::$instances = array();
     }
 }
 protected function set_chapters()
 {
     $this->chapters = (object) [];
     $this->chapters->listlarge = $this->course->numsections > 9 ? 'list-large' : '';
     $this->chapters->chapters = [];
     $canviewhidden = has_capability('moodle/course:viewhiddensections', context_course::instance($this->course->id));
     $modinfo = get_fast_modinfo($this->course);
     foreach ($modinfo->get_section_info_all() as $section => $thissection) {
         if ($section > $this->course->numsections) {
             continue;
         }
         // Students - If course hidden sections completely invisible & section is hidden, and you cannot
         // see hidden things, bale out.
         if ($this->course->hiddensections && !$thissection->visible && !$canviewhidden) {
             continue;
         }
         $conditional = $this->is_section_conditional($thissection);
         $chapter = new course_toc_chapter();
         $chapter->outputlink = true;
         if ($canviewhidden) {
             // Teachers.
             if ($conditional) {
                 $chapter->availabilityclass = 'text-danger';
                 $chapter->availabilitystatus = get_string('conditional', 'theme_snap');
             }
             if (!$thissection->visible) {
                 $chapter->availabilityclass = 'text-warning';
                 $chapter->availabilitystatus = get_string('notpublished', 'theme_snap');
             }
         } else {
             // Students.
             if ($conditional && !$thissection->uservisible && !$thissection->availableinfo) {
                 // Conditional section, totally hidden from user so skip.
                 continue;
             }
             if ($conditional && $thissection->availableinfo) {
                 $chapter->availabilityclass = 'text-danger';
                 $chapter->availabilitystatus = get_string('conditional', 'theme_snap');
             }
             if (!$conditional && !$thissection->visible) {
                 // Hidden section collapsed, so show as text in TOC.
                 $chapter->outputlink = false;
                 $chapter->availabilityclass = 'text-warning';
                 $chapter->availabilitystatus = get_string('notavailable');
             }
         }
         $chapter->title = get_section_name($this->course, $section);
         if ($chapter->title == get_string('general')) {
             $chapter->title = get_string('introduction', 'theme_snap');
         }
         if ($this->format->is_section_current($section)) {
             $chapter->iscurrent = true;
         }
         if ($chapter->outputlink) {
             $singlepage = $this->course->format !== 'folderview';
             if ($singlepage) {
                 $chapter->url = '#section-' . $section;
             } else {
                 if ($section > 0) {
                     $chapter->url = course_get_url($this->course, $section, ['navigation' => true, 'sr' => $section]);
                 } else {
                     // We need to create the url for section 0, or a hash will get returned.
                     $chapter->url = new moodle_url('/course/view.php', ['id' => $this->course->id, 'section' => $section]);
                 }
             }
         }
         $chapter->progress = new course_toc_progress($this->course, $thissection);
         $this->chapters->chapters[] = $chapter;
     }
 }