Exemplo n.º 1
0
 /**
  * Test search_courses
  */
 public function test_search_courses()
 {
     global $DB;
     $this->resetAfterTest(true);
     $this->setAdminUser();
     $generatedcourses = array();
     $coursedata1['fullname'] = 'FIRST COURSE';
     $course1 = self::getDataGenerator()->create_course($coursedata1);
     $coursedata2['fullname'] = 'SECOND COURSE';
     $course2 = self::getDataGenerator()->create_course($coursedata2);
     // Search by name.
     $results = core_course_external::search_courses('search', 'FIRST');
     $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
     $this->assertEquals($coursedata1['fullname'], $results['courses'][0]['fullname']);
     $this->assertCount(1, $results['courses']);
     // Create the forum.
     $record = new stdClass();
     $record->introformat = FORMAT_HTML;
     $record->course = $course2->id;
     // Set Aggregate type = Average of ratings.
     $forum = self::getDataGenerator()->create_module('forum', $record);
     // Search by module.
     $results = core_course_external::search_courses('modulelist', 'forum');
     $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
     $this->assertEquals(1, $results['total']);
     // Enable coursetag option.
     set_config('block_tags_showcoursetags', true);
     // Add tag 'TAG-LABEL ON SECOND COURSE' to Course2.
     core_tag_tag::set_item_tags('core', 'course', $course2->id, context_course::instance($course2->id), array('TAG-LABEL ON SECOND COURSE'));
     $taginstance = $DB->get_record('tag_instance', array('itemtype' => 'course', 'itemid' => $course2->id), '*', MUST_EXIST);
     // Search by tagid.
     $results = core_course_external::search_courses('tagid', $taginstance->tagid);
     $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
     $this->assertEquals($coursedata2['fullname'], $results['courses'][0]['fullname']);
     // Search by block (use news_items default block).
     $blockid = $DB->get_field('block', 'id', array('name' => 'news_items'));
     $results = core_course_external::search_courses('blocklist', $blockid);
     $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
     $this->assertEquals(2, $results['total']);
     // Now as a normal user.
     $user = self::getDataGenerator()->create_user();
     // Add a 3rd, hidden, course we shouldn't see, even when enrolled as student.
     $coursedata3['fullname'] = 'HIDDEN COURSE';
     $coursedata3['visible'] = 0;
     $course3 = self::getDataGenerator()->create_course($coursedata3);
     $this->getDataGenerator()->enrol_user($user->id, $course3->id, 'student');
     $this->getDataGenerator()->enrol_user($user->id, $course2->id, 'student');
     $this->setUser($user);
     $results = core_course_external::search_courses('search', 'FIRST');
     $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
     $this->assertCount(1, $results['courses']);
     $this->assertEquals(1, $results['total']);
     $this->assertEquals($coursedata1['fullname'], $results['courses'][0]['fullname']);
     // Check that we can see both without the limit to enrolled setting.
     $results = core_course_external::search_courses('search', 'COURSE', 0, 0, array(), 0);
     $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
     $this->assertCount(2, $results['courses']);
     $this->assertEquals(2, $results['total']);
     // Check that we only see our enrolled course when limiting.
     $results = core_course_external::search_courses('search', 'COURSE', 0, 0, array(), 1);
     $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
     $this->assertCount(1, $results['courses']);
     $this->assertEquals(1, $results['total']);
     $this->assertEquals($coursedata2['fullname'], $results['courses'][0]['fullname']);
     // Search by block (use news_items default block). Should fail (only admins allowed).
     $this->setExpectedException('required_capability_exception');
     $results = core_course_external::search_courses('blocklist', $blockid);
 }
Exemplo n.º 2
0
/**
 * Updates a users interests.
 *
 * @param stdClass $user
 * @param array $interests
 */
function useredit_update_interests($user, $interests)
{
    core_tag_tag::set_item_tags('core', 'user', $user->id, context_user::instance($user->id), $interests);
}
Exemplo n.º 3
0
/**
 * Set the tags assigned to a record.  This overwrites the current tags.
 *
 * This function is meant to be fed the string coming up from the user interface, which contains all tags assigned to a record.
 *
 * Due to API change $component and $contextid are now required. Instead of
 * calling  this function you can use {@link core_tag_tag::set_item_tags()} or
 * {@link core_tag_tag::set_related_tags()}
 *
 * @package core_tag
 * @deprecated since 3.1
 * @param string $itemtype the type of record to tag ('post' for blogs, 'user' for users, 'tag' for tags, etc.)
 * @param int $itemid the id of the record to tag
 * @param array $tags the array of tags to set on the record. If given an empty array, all tags will be removed.
 * @param string|null $component the component that was tagged
 * @param int|null $contextid the context id of where this tag was assigned
 * @return bool|null
 */
function tag_set($itemtype, $itemid, $tags, $component = null, $contextid = null)
{
    debugging('Function tag_set() is deprecated. Use ' . ' core_tag_tag::set_item_tags() instead', DEBUG_DEVELOPER);
    if ($itemtype === 'tag') {
        return core_tag_tag::get($itemid, '*', MUST_EXIST)->set_related_tags($tags);
    } else {
        $context = $contextid ? context::instance_by_id($contextid) : context_system::instance();
        return core_tag_tag::set_item_tags($component, $itemtype, $itemid, $context, $tags);
    }
}
Exemplo n.º 4
0
 public function test_move_tags_with_related()
 {
     global $DB;
     list($collid1, $collid2, $user1, $user2, $blogpost) = $this->prepare_move_tags();
     // Set Tag1 to be related to Tag2 and Tag4 (in collection 1).
     core_tag_tag::get_by_name($collid1, 'Tag1')->set_related_tags(array('Tag2', 'Tag4'));
     // Set collection for 'post' tag area to be collection 2 and add some tags there.
     $tagareablog = $DB->get_record('tag_area', array('itemtype' => 'post', 'component' => 'core'));
     core_tag_area::update($tagareablog, array('tagcollid' => $collid2));
     core_tag_tag::set_item_tags('core', 'post', $blogpost->id, context_system::instance(), array('TAG1', 'Tag3'));
     // Move 'user' area from collection 1 to collection 2, make sure tags were moved completely.
     $tagarea = $DB->get_record('tag_area', array('itemtype' => 'user', 'component' => 'core'));
     core_tag_area::update($tagarea, array('tagcollid' => $collid2));
     $this->assertEquals(array('Tag1', 'Tag2', 'Tag4'), $DB->get_fieldset_select('tag', 'rawname', 'tagcollid = ? ORDER BY name', array($collid1)));
     $this->assertEquals(array('TAG1', 'Tag2', 'Tag3', 'Tag4', 'Tag5'), $DB->get_fieldset_select('tag', 'rawname', 'tagcollid = ? ORDER BY name', array($collid2)));
     $this->assertEquals(array('TAG1', 'Tag2'), array_values(core_tag_tag::get_item_tags_array('core', 'user', $user1->id)));
     $this->assertEquals(array('Tag2', 'Tag3'), array_values(core_tag_tag::get_item_tags_array('core', 'user', $user2->id)));
     $tag11 = core_tag_tag::get_by_name($collid1, 'Tag1');
     $related11 = tag_get_related_tags($tag11->id, TAG_RELATED_MANUAL);
     $this->assertDebuggingCalled();
     $related11 = array_map('core_tag_tag::make_display_name', $related11);
     sort($related11);
     // Order of related tags may be random.
     $this->assertEquals('Tag2, Tag4', join(', ', $related11));
     $tag21 = core_tag_tag::get_by_name($collid2, 'TAG1');
     $related21 = tag_get_related_tags($tag21->id, TAG_RELATED_MANUAL);
     $this->assertDebuggingCalled();
     $related21 = array_map('core_tag_tag::make_display_name', $related21);
     sort($related21);
     // Order of related tags may be random.
     $this->assertEquals('Tag2, Tag4', join(', ', $related21));
 }
Exemplo n.º 5
0
/**
 * Given a record in the {blog_external} table, checks the blog's URL
 * for new entries not yet copied into Moodle.
 * Also attempts to identify and remove deleted blog entries
 *
 * @param object $externalblog
 * @return boolean False if the Feed is invalid
 */
function blog_sync_external_entries($externalblog)
{
    global $CFG, $DB;
    require_once $CFG->libdir . '/simplepie/moodle_simplepie.php';
    $rss = new moodle_simplepie();
    $rssfile = $rss->registry->create('File', array($externalblog->url));
    $filetest = $rss->registry->create('Locator', array($rssfile));
    if (!$filetest->is_feed($rssfile)) {
        $externalblog->failedlastsync = 1;
        $DB->update_record('blog_external', $externalblog);
        return false;
    } else {
        if (!empty($externalblog->failedlastsync)) {
            $externalblog->failedlastsync = 0;
            $DB->update_record('blog_external', $externalblog);
        }
    }
    $rss->set_feed_url($externalblog->url);
    $rss->init();
    if (empty($rss->data)) {
        return null;
    }
    // Used to identify blog posts that have been deleted from the source feed.
    $oldesttimestamp = null;
    $uniquehashes = array();
    foreach ($rss->get_items() as $entry) {
        // If filtertags are defined, use them to filter the entries by RSS category.
        if (!empty($externalblog->filtertags)) {
            $containsfiltertag = false;
            $categories = $entry->get_categories();
            $filtertags = explode(',', $externalblog->filtertags);
            $filtertags = array_map('trim', $filtertags);
            $filtertags = array_map('strtolower', $filtertags);
            if (!empty($categories)) {
                foreach ($categories as $category) {
                    if (in_array(trim(strtolower($category->term)), $filtertags)) {
                        $containsfiltertag = true;
                    }
                }
            }
            if (!$containsfiltertag) {
                continue;
            }
        }
        $uniquehashes[] = $entry->get_permalink();
        $newentry = new stdClass();
        $newentry->userid = $externalblog->userid;
        $newentry->module = 'blog_external';
        $newentry->content = $externalblog->id;
        $newentry->uniquehash = $entry->get_permalink();
        $newentry->publishstate = 'site';
        $newentry->format = FORMAT_HTML;
        // Clean subject of html, just in case.
        $newentry->subject = clean_param($entry->get_title(), PARAM_TEXT);
        // Observe 128 max chars in DB.
        // TODO: +1 to raise this to 255.
        if (core_text::strlen($newentry->subject) > 128) {
            $newentry->subject = core_text::substr($newentry->subject, 0, 125) . '...';
        }
        $newentry->summary = $entry->get_description();
        // Used to decide whether to insert or update.
        // Uses enty permalink plus creation date if available.
        $existingpostconditions = array('uniquehash' => $entry->get_permalink());
        // Our DB doesnt allow null creation or modified timestamps so check the external blog supplied one.
        $entrydate = $entry->get_date('U');
        if (!empty($entrydate)) {
            $existingpostconditions['created'] = $entrydate;
        }
        // The post ID or false if post not found in DB.
        $postid = $DB->get_field('post', 'id', $existingpostconditions);
        $timestamp = null;
        if (empty($entrydate)) {
            $timestamp = time();
        } else {
            $timestamp = $entrydate;
        }
        // Only set created if its a new post so we retain the original creation timestamp if the post is edited.
        if ($postid === false) {
            $newentry->created = $timestamp;
        }
        $newentry->lastmodified = $timestamp;
        if (empty($oldesttimestamp) || $timestamp < $oldesttimestamp) {
            // Found an older post.
            $oldesttimestamp = $timestamp;
        }
        if (core_text::strlen($newentry->uniquehash) > 255) {
            // The URL for this item is too long for the field. Rather than add
            // the entry without the link we will skip straight over it.
            // RSS spec says recommended length 500, we use 255.
            debugging('External blog entry skipped because of oversized URL', DEBUG_DEVELOPER);
            continue;
        }
        if ($postid === false) {
            $id = $DB->insert_record('post', $newentry);
            // Set tags.
            if ($tags = core_tag_tag::get_item_tags_array('core', 'blog_external', $externalblog->id)) {
                core_tag_tag::set_item_tags('core', 'post', $id, context_user::instance($externalblog->userid), $tags);
            }
        } else {
            $newentry->id = $postid;
            $DB->update_record('post', $newentry);
        }
    }
    // Look at the posts we have in the database to check if any of them have been deleted from the feed.
    // Only checking posts within the time frame returned by the rss feed. Older items may have been deleted or
    // may just not be returned anymore. We can't tell the difference so we leave older posts alone.
    $sql = "SELECT id, uniquehash\n              FROM {post}\n             WHERE module = 'blog_external'\n                   AND " . $DB->sql_compare_text('content') . " = " . $DB->sql_compare_text(':blogid') . "\n                   AND created > :ts";
    $dbposts = $DB->get_records_sql($sql, array('blogid' => $externalblog->id, 'ts' => $oldesttimestamp));
    $todelete = array();
    foreach ($dbposts as $dbpost) {
        if (!in_array($dbpost->uniquehash, $uniquehashes)) {
            $todelete[] = $dbpost->id;
        }
    }
    $DB->delete_records_list('post', 'id', $todelete);
    $DB->update_record('blog_external', array('id' => $externalblog->id, 'timefetched' => time()));
}
Exemplo n.º 6
0
 /**
  * Tests the function that deletes a course module
  *
  * @param string $type The type of module for the test
  * @param array $options The options for the module creation
  * @dataProvider provider_course_delete_module
  */
 public function test_course_delete_module($type, $options)
 {
     global $DB;
     $this->resetAfterTest(true);
     $this->setAdminUser();
     // Create course and modules.
     $course = $this->getDataGenerator()->create_course(array('numsections' => 5));
     $options['course'] = $course->id;
     // Generate an assignment with due date (will generate a course event).
     $module = $this->getDataGenerator()->create_module($type, $options);
     // Get the module context.
     $modcontext = context_module::instance($module->cmid);
     // Verify context exists.
     $this->assertInstanceOf('context_module', $modcontext);
     // Make module specific messes.
     switch ($type) {
         case 'assign':
             // Add some tags to this assignment.
             core_tag_tag::set_item_tags('mod_assign', 'assign', $module->id, $modcontext, array('Tag 1', 'Tag 2', 'Tag 3'));
             core_tag_tag::set_item_tags('core', 'course_modules', $module->cmid, $modcontext, array('Tag 3', 'Tag 4', 'Tag 5'));
             // Confirm the tag instances were added.
             $criteria = array('component' => 'mod_assign', 'itemtype' => 'assign', 'contextid' => $modcontext->id);
             $this->assertEquals(3, $DB->count_records('tag_instance', $criteria));
             $criteria = array('component' => 'core', 'itemtype' => 'course_modules', 'contextid' => $modcontext->id);
             $this->assertEquals(3, $DB->count_records('tag_instance', $criteria));
             // Verify event assignment event has been generated.
             $eventcount = $DB->count_records('event', array('instance' => $module->id, 'modulename' => $type));
             $this->assertEquals(1, $eventcount);
             break;
         case 'quiz':
             $qgen = $this->getDataGenerator()->get_plugin_generator('core_question');
             $qcat = $qgen->create_question_category(array('contextid' => $modcontext->id));
             $questions = array($qgen->create_question('shortanswer', null, array('category' => $qcat->id)), $qgen->create_question('shortanswer', null, array('category' => $qcat->id)));
             $this->expectOutputRegex('/' . get_string('unusedcategorydeleted', 'question') . '/');
             break;
         default:
             break;
     }
     // Run delete..
     course_delete_module($module->cmid);
     // Verify the context has been removed.
     $this->assertFalse(context_module::instance($module->cmid, IGNORE_MISSING));
     // Verify the course_module record has been deleted.
     $cmcount = $DB->count_records('course_modules', array('id' => $module->cmid));
     $this->assertEmpty($cmcount);
     // Test clean up of module specific messes.
     switch ($type) {
         case 'assign':
             // Verify event assignment events have been removed.
             $eventcount = $DB->count_records('event', array('instance' => $module->id, 'modulename' => $type));
             $this->assertEmpty($eventcount);
             // Verify the tag instances were deleted.
             $criteria = array('component' => 'mod_assign', 'contextid' => $modcontext->id);
             $this->assertEquals(0, $DB->count_records('tag_instance', $criteria));
             $criteria = array('component' => 'core', 'itemtype' => 'course_modules', 'contextid' => $modcontext->id);
             $this->assertEquals(0, $DB->count_records('tag_instance', $criteria));
             break;
         case 'quiz':
             // Verify category deleted.
             $criteria = array('contextid' => $modcontext->id);
             $this->assertEquals(0, $DB->count_records('question_categories', $criteria));
             // Verify questions deleted.
             $criteria = array('category' => $qcat->id);
             $this->assertEquals(0, $DB->count_records('question', $criteria));
             break;
         default:
             break;
     }
 }
Exemplo n.º 7
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;
     // Raise time and memory, as importing can be quite intensive.
     core_php_time_limit::raise();
     raise_memory_limit(MEMORY_EXTRA);
     // 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
         $transaction = $DB->start_delegated_transaction();
         // 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;
                 }
             }
             $transaction->allow_commit();
             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' => true, '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 (isset($question->tags)) {
             core_tag_tag::set_item_tags('core_question', 'question', $question->id, $question->context, $question->tags);
         }
         if (!empty($result->error)) {
             echo $OUTPUT->notification($result->error);
             // Can't use $transaction->rollback(); since it requires an exception,
             // and I don't want to rewrite this code to change the error handling now.
             $DB->force_transaction_rollback();
             return false;
         }
         $transaction->allow_commit();
         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;
 }
Exemplo n.º 8
0
 protected function print_save()
 {
     global $CFG, $USER, $OUTPUT, $PAGE;
     $url = $CFG->wwwroot . '/mod/wiki/edit.php?pageid=' . $this->page->id;
     if (!empty($this->section)) {
         $url .= "&section=" . urlencode($this->section);
     }
     $params = array('attachmentoptions' => page_wiki_edit::$attachmentoptions, 'format' => $this->format, 'version' => $this->versionnumber, 'contextid' => $this->modcontext->id);
     if ($this->format != 'html') {
         $params['fileitemid'] = $this->page->id;
         $params['component'] = 'mod_wiki';
         $params['filearea'] = 'attachments';
     }
     $form = new mod_wiki_edit_form($url, $params);
     $save = false;
     $data = false;
     if ($data = $form->get_data()) {
         if ($this->format == 'html') {
             $data = file_postupdate_standard_editor($data, 'newcontent', page_wiki_edit::$attachmentoptions, $this->modcontext, 'mod_wiki', 'attachments', $this->subwiki->id);
         }
         if (isset($this->section)) {
             $save = wiki_save_section($this->page, $this->section, $data->newcontent, $USER->id);
         } else {
             $save = wiki_save_page($this->page, $data->newcontent, $USER->id);
         }
     }
     if ($save && $data) {
         core_tag_tag::set_item_tags('mod_wiki', 'wiki_pages', $this->page->id, $this->modcontext, $data->tags);
         $message = '<p>' . get_string('saving', 'wiki') . '</p>';
         if (!empty($save['sections'])) {
             foreach ($save['sections'] as $s) {
                 $message .= '<p>' . get_string('repeatedsection', 'wiki', $s) . '</p>';
             }
         }
         if ($this->versionnumber + 1 != $save['version']) {
             $message .= '<p>' . get_string('wrongversionsave', 'wiki') . '</p>';
         }
         if (isset($errors) && !empty($errors)) {
             foreach ($errors as $e) {
                 $message .= "<p>" . get_string('filenotuploadederror', 'wiki', $e->get_filename()) . "</p>";
             }
         }
         //deleting old locks
         wiki_delete_locks($this->page->id, $USER->id, $this->section);
         $url = new moodle_url('/mod/wiki/view.php', array('pageid' => $this->page->id, 'group' => $this->subwiki->groupid));
         redirect($url);
     } else {
         print_error('savingerror', 'wiki');
     }
 }
Exemplo n.º 9
0
require_login();
// Check capabilities but do not call require_login($course) - the user does not have to be enrolled.
$context = context_course::instance($course->id);
if (!$course->visible and !has_capability('moodle/course:viewhiddencourses', $context)) {
    print_error('coursehidden', '', $CFG->wwwroot . '/');
}
require_capability('moodle/course:tag', $context);
if (!core_tag_tag::is_enabled('core', 'course')) {
    print_error('tagsaredisabled', 'tag');
}
$PAGE->set_course($course);
$PAGE->set_pagelayout('incourse');
$PAGE->set_url('/course/tags.php', array('id' => $course->id));
$PAGE->set_title(get_string('coursetags', 'tag'));
$PAGE->set_heading($course->fullname);
$form = new coursetags_form();
$data = array('id' => $course->id, 'tags' => core_tag_tag::get_item_tags_array('core', 'course', $course->id));
$form->set_data($data);
$redirecturl = $returnurl ? new moodle_url($returnurl) : course_get_url($course);
if ($form->is_cancelled()) {
    redirect($redirecturl);
} else {
    if ($data = $form->get_data()) {
        core_tag_tag::set_item_tags('core', 'course', $course->id, context_course::instance($course->id), $data->tags);
        redirect($redirecturl);
    }
}
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('coursetags', 'tag'));
$form->display();
echo $OUTPUT->footer();
Exemplo n.º 10
0
 /**
  * Given one restoreid, create in DB all the users present
  * in backup_ids having newitemid = 0, as far as
  * precheck_included_users() have left them there
  * ready to be created. Also, annotate their newids
  * once created for later reference.
  *
  * This function will start and end a new progress section in the progress
  * object.
  *
  * @param string $basepath Base path of unzipped backup
  * @param string $restoreid Restore ID
  * @param int $userid Default userid for files
  * @param \core\progress\base $progress Object used for progress tracking
  */
 public static function create_included_users($basepath, $restoreid, $userid, \core\progress\base $progress)
 {
     global $CFG, $DB;
     $progress->start_progress('Creating included users');
     $authcache = array();
     // Cache to get some bits from authentication plugins
     $languages = get_string_manager()->get_list_of_translations();
     // Get languages for quick search later
     $themes = get_list_of_themes();
     // Get themes for quick search later
     // Iterate over all the included users with newitemid = 0, have to create them
     $rs = $DB->get_recordset('backup_ids_temp', array('backupid' => $restoreid, 'itemname' => 'user', 'newitemid' => 0), '', 'itemid, parentitemid, info');
     foreach ($rs as $recuser) {
         $progress->progress();
         $user = (object) backup_controller_dbops::decode_backup_temp_info($recuser->info);
         // if user lang doesn't exist here, use site default
         if (!array_key_exists($user->lang, $languages)) {
             $user->lang = $CFG->lang;
         }
         // if user theme isn't available on target site or they are disabled, reset theme
         if (!empty($user->theme)) {
             if (empty($CFG->allowuserthemes) || !in_array($user->theme, $themes)) {
                 $user->theme = '';
             }
         }
         // if user to be created has mnet auth and its mnethostid is $CFG->mnet_localhost_id
         // that's 100% impossible as own server cannot be accesed over mnet. Change auth to email/manual
         if ($user->auth == 'mnet' && $user->mnethostid == $CFG->mnet_localhost_id) {
             // Respect registerauth
             if ($CFG->registerauth == 'email') {
                 $user->auth = 'email';
             } else {
                 $user->auth = 'manual';
             }
         }
         unset($user->mnethosturl);
         // Not needed anymore
         // Disable pictures based on global setting
         if (!empty($CFG->disableuserimages)) {
             $user->picture = 0;
         }
         // We need to analyse the AUTH field to recode it:
         //   - if the auth isn't enabled in target site, $CFG->registerauth will decide
         //   - finally, if the auth resulting isn't enabled, default to 'manual'
         if (!is_enabled_auth($user->auth)) {
             if ($CFG->registerauth == 'email') {
                 $user->auth = 'email';
             } else {
                 $user->auth = 'manual';
             }
         }
         if (!is_enabled_auth($user->auth)) {
             // Final auth check verify, default to manual if not enabled
             $user->auth = 'manual';
         }
         // Now that we know the auth method, for users to be created without pass
         // if password handling is internal and reset password is available
         // we set the password to "restored" (plain text), so the login process
         // will know how to handle that situation in order to allow the user to
         // recover the password. MDL-20846
         if (empty($user->password)) {
             // Only if restore comes without password
             if (!array_key_exists($user->auth, $authcache)) {
                 // Not in cache
                 $userauth = new stdClass();
                 $authplugin = get_auth_plugin($user->auth);
                 $userauth->preventpassindb = $authplugin->prevent_local_passwords();
                 $userauth->isinternal = $authplugin->is_internal();
                 $userauth->canresetpwd = $authplugin->can_reset_password();
                 $authcache[$user->auth] = $userauth;
             } else {
                 $userauth = $authcache[$user->auth];
                 // Get from cache
             }
             // Most external plugins do not store passwords locally
             if (!empty($userauth->preventpassindb)) {
                 $user->password = AUTH_PASSWORD_NOT_CACHED;
                 // If Moodle is responsible for storing/validating pwd and reset functionality is available, mark
             } else {
                 if ($userauth->isinternal and $userauth->canresetpwd) {
                     $user->password = '******';
                 }
             }
         }
         // Creating new user, we must reset the policyagreed always
         $user->policyagreed = 0;
         // Set time created if empty
         if (empty($user->timecreated)) {
             $user->timecreated = time();
         }
         // Done, let's create the user and annotate its id
         $newuserid = $DB->insert_record('user', $user);
         self::set_backup_ids_record($restoreid, 'user', $recuser->itemid, $newuserid);
         // Let's create the user context and annotate it (we need it for sure at least for files)
         // but for deleted users that don't have a context anymore (MDL-30192). We are done for them
         // and nothing else (custom fields, prefs, tags, files...) will be created.
         if (empty($user->deleted)) {
             $newuserctxid = $user->deleted ? 0 : context_user::instance($newuserid)->id;
             self::set_backup_ids_record($restoreid, 'context', $recuser->parentitemid, $newuserctxid);
             // Process custom fields
             if (isset($user->custom_fields)) {
                 // if present in backup
                 foreach ($user->custom_fields['custom_field'] as $udata) {
                     $udata = (object) $udata;
                     // If the profile field has data and the profile shortname-datatype is defined in server
                     if ($udata->field_data) {
                         if ($field = $DB->get_record('user_info_field', array('shortname' => $udata->field_name, 'datatype' => $udata->field_type))) {
                             /// Insert the user_custom_profile_field
                             $rec = new stdClass();
                             $rec->userid = $newuserid;
                             $rec->fieldid = $field->id;
                             $rec->data = $udata->field_data;
                             $DB->insert_record('user_info_data', $rec);
                         }
                     }
                 }
             }
             // Process tags
             if (core_tag_tag::is_enabled('core', 'user') && isset($user->tags)) {
                 // If enabled in server and present in backup.
                 $tags = array();
                 foreach ($user->tags['tag'] as $usertag) {
                     $usertag = (object) $usertag;
                     $tags[] = $usertag->rawname;
                 }
                 core_tag_tag::set_item_tags('core', 'user', $newuserid, context_user::instance($newuserid), $tags);
             }
             // Process preferences
             if (isset($user->preferences)) {
                 // if present in backup
                 foreach ($user->preferences['preference'] as $preference) {
                     $preference = (object) $preference;
                     // Prepare the record and insert it
                     $preference->userid = $newuserid;
                     $status = $DB->insert_record('user_preferences', $preference);
                 }
             }
             // Special handling for htmleditor which was converted to a preference.
             if (isset($user->htmleditor)) {
                 if ($user->htmleditor == 0) {
                     $preference = new stdClass();
                     $preference->userid = $newuserid;
                     $preference->name = 'htmleditor';
                     $preference->value = 'textarea';
                     $status = $DB->insert_record('user_preferences', $preference);
                 }
             }
             // Create user files in pool (profile, icon, private) by context
             restore_dbops::send_files_to_pool($basepath, $restoreid, 'user', 'icon', $recuser->parentitemid, $userid, null, null, null, false, $progress);
             restore_dbops::send_files_to_pool($basepath, $restoreid, 'user', 'profile', $recuser->parentitemid, $userid, null, null, null, false, $progress);
         }
     }
     $rs->close();
     $progress->end_progress();
 }
Exemplo n.º 11
0
/**
 * Update the module info.
 * This function doesn't check the user capabilities. It updates the course module and the module instance.
 * Then execute common action to create/update module process (trigger event, rebuild cache, save plagiarism settings...).
 *
 * @param object $cm course module
 * @param object $moduleinfo module info
 * @param object $course course of the module
 * @param object $mform - the mform is required by some specific module in the function MODULE_update_instance(). This is due to a hack in this function.
 * @return array list of course module and module info.
 */
function update_moduleinfo($cm, $moduleinfo, $course, $mform = null)
{
    global $DB, $CFG;
    $data = new stdClass();
    if ($mform) {
        $data = $mform->get_data();
    }
    // Attempt to include module library before we make any changes to DB.
    include_modulelib($moduleinfo->modulename);
    $moduleinfo->course = $course->id;
    $moduleinfo = set_moduleinfo_defaults($moduleinfo);
    if (!empty($course->groupmodeforce) or !isset($moduleinfo->groupmode)) {
        $moduleinfo->groupmode = $cm->groupmode;
        // Keep original.
    }
    // Update course module first.
    $cm->groupmode = $moduleinfo->groupmode;
    if (isset($moduleinfo->groupingid)) {
        $cm->groupingid = $moduleinfo->groupingid;
    }
    $completion = new completion_info($course);
    if ($completion->is_enabled()) {
        // Completion settings that would affect users who have already completed
        // the activity may be locked; if so, these should not be updated.
        if (!empty($moduleinfo->completionunlocked)) {
            $cm->completion = $moduleinfo->completion;
            $cm->completiongradeitemnumber = $moduleinfo->completiongradeitemnumber;
            $cm->completionview = $moduleinfo->completionview;
        }
        // The expected date does not affect users who have completed the activity,
        // so it is safe to update it regardless of the lock status.
        $cm->completionexpected = $moduleinfo->completionexpected;
    }
    if (!empty($CFG->enableavailability)) {
        // This code is used both when submitting the form, which uses a long
        // name to avoid clashes, and by unit test code which uses the real
        // name in the table.
        if (property_exists($moduleinfo, 'availabilityconditionsjson')) {
            if ($moduleinfo->availabilityconditionsjson !== '') {
                $cm->availability = $moduleinfo->availabilityconditionsjson;
            } else {
                $cm->availability = null;
            }
        } else {
            if (property_exists($moduleinfo, 'availability')) {
                $cm->availability = $moduleinfo->availability;
            }
        }
        // If there is any availability data, verify it.
        if ($cm->availability) {
            $tree = new \core_availability\tree(json_decode($cm->availability));
            // Save time and database space by setting null if the only data
            // is an empty tree.
            if ($tree->is_empty()) {
                $cm->availability = null;
            }
        }
    }
    if (isset($moduleinfo->showdescription)) {
        $cm->showdescription = $moduleinfo->showdescription;
    } else {
        $cm->showdescription = 0;
    }
    $DB->update_record('course_modules', $cm);
    $modcontext = context_module::instance($moduleinfo->coursemodule);
    // Update embedded links and save files.
    if (plugin_supports('mod', $moduleinfo->modulename, FEATURE_MOD_INTRO, true)) {
        $moduleinfo->intro = file_save_draft_area_files($moduleinfo->introeditor['itemid'], $modcontext->id, 'mod_' . $moduleinfo->modulename, 'intro', 0, array('subdirs' => true), $moduleinfo->introeditor['text']);
        $moduleinfo->introformat = $moduleinfo->introeditor['format'];
        unset($moduleinfo->introeditor);
    }
    // Get the a copy of the grade_item before it is modified incase we need to scale the grades.
    $oldgradeitem = null;
    $newgradeitem = null;
    if (!empty($data->grade_rescalegrades) && $data->grade_rescalegrades == 'yes') {
        // Fetch the grade item before it is updated.
        $oldgradeitem = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => $moduleinfo->modulename, 'iteminstance' => $moduleinfo->instance, 'itemnumber' => 0, 'courseid' => $moduleinfo->course));
    }
    $updateinstancefunction = $moduleinfo->modulename . "_update_instance";
    if (!$updateinstancefunction($moduleinfo, $mform)) {
        print_error('cannotupdatemod', '', course_get_url($course, $cm->section), $moduleinfo->modulename);
    }
    // This needs to happen AFTER the grademin/grademax have already been updated.
    if (!empty($data->grade_rescalegrades) && $data->grade_rescalegrades == 'yes') {
        // Get the grade_item after the update call the activity to scale the grades.
        $newgradeitem = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => $moduleinfo->modulename, 'iteminstance' => $moduleinfo->instance, 'itemnumber' => 0, 'courseid' => $moduleinfo->course));
        if ($newgradeitem && $oldgradeitem->gradetype == GRADE_TYPE_VALUE && $newgradeitem->gradetype == GRADE_TYPE_VALUE) {
            $params = array($course, $cm, $oldgradeitem->grademin, $oldgradeitem->grademax, $newgradeitem->grademin, $newgradeitem->grademax);
            if (!component_callback('mod_' . $moduleinfo->modulename, 'rescale_activity_grades', $params)) {
                print_error('cannotreprocessgrades', '', course_get_url($course, $cm->section), $moduleinfo->modulename);
            }
        }
    }
    // Make sure visibility is set correctly (in particular in calendar).
    if (has_capability('moodle/course:activityvisibility', $modcontext)) {
        set_coursemodule_visible($moduleinfo->coursemodule, $moduleinfo->visible);
    }
    if (isset($moduleinfo->cmidnumber)) {
        // Label.
        // Set cm idnumber - uniqueness is already verified by form validation.
        set_coursemodule_idnumber($moduleinfo->coursemodule, $moduleinfo->cmidnumber);
    }
    // Update module tags.
    if (core_tag_tag::is_enabled('core', 'course_modules') && isset($moduleinfo->tags)) {
        core_tag_tag::set_item_tags('core', 'course_modules', $moduleinfo->coursemodule, $modcontext, $moduleinfo->tags);
    }
    // Now that module is fully updated, also update completion data if required.
    // (this will wipe all user completion data and recalculate it)
    if ($completion->is_enabled() && !empty($moduleinfo->completionunlocked)) {
        $completion->reset_all_state($cm);
    }
    $cm->name = $moduleinfo->name;
    \core\event\course_module_updated::create_from_cm($cm, $modcontext)->trigger();
    $moduleinfo = edit_module_post_actions($moduleinfo, $course);
    return array($cm, $moduleinfo);
}
Exemplo n.º 12
0
 /**
  * Test the tag deleted event
  */
 public function test_tag_deleted()
 {
     global $DB;
     $this->setAdminUser();
     // Create a course and a user.
     $course = $this->getDataGenerator()->create_course();
     $user = $this->getDataGenerator()->create_user();
     // Create tag we are going to delete.
     $tag = $this->getDataGenerator()->create_tag();
     // Trigger and capture the event for deleting a tag.
     $sink = $this->redirectEvents();
     tag_delete($tag->id);
     $this->assertDebuggingCalled();
     $events = $sink->get_events();
     $event = reset($events);
     // Check that the tag was deleted and the event data is valid.
     $this->assertEquals(0, $DB->count_records('tag'));
     $this->assertInstanceOf('\\core\\event\\tag_deleted', $event);
     $this->assertEquals(context_system::instance(), $event->get_context());
     // Create two tags we are going to delete to ensure passing multiple tags work.
     $tag = $this->getDataGenerator()->create_tag();
     $tag2 = $this->getDataGenerator()->create_tag();
     // Trigger and capture the events for deleting multiple tags.
     $sink = $this->redirectEvents();
     tag_delete(array($tag->id, $tag2->id));
     $this->assertDebuggingCalled();
     $events = $sink->get_events();
     // Check that the tags were deleted and the events data is valid.
     $this->assertEquals(0, $DB->count_records('tag'));
     foreach ($events as $event) {
         $this->assertInstanceOf('\\core\\event\\tag_deleted', $event);
         $this->assertEquals(context_system::instance(), $event->get_context());
     }
     // Add a tag instance to a course.
     core_tag_tag::add_item_tag('core', 'course', $course->id, context_course::instance($course->id), 'cat', $user->id);
     // Trigger and capture the event for deleting a personal tag for a user for a course.
     $sink = $this->redirectEvents();
     core_tag_tag::remove_item_tag('core', 'course', $course->id, 'cat', $user->id);
     $events = $sink->get_events();
     $event = $events[1];
     // Check that the tag was deleted and the event data is valid.
     $this->assertEquals(0, $DB->count_records('tag'));
     $this->assertInstanceOf('\\core\\event\\tag_deleted', $event);
     $this->assertEquals(context_system::instance(), $event->get_context());
     // Add the tag instance to the course again as it was deleted.
     core_tag_tag::add_item_tag('core', 'course', $course->id, context_course::instance($course->id), 'dog', $user->id);
     // Trigger and capture the event for deleting all tags in a course.
     $sink = $this->redirectEvents();
     core_tag_tag::remove_all_item_tags('core', 'course', $course->id);
     $events = $sink->get_events();
     $event = $events[1];
     // Check that the tag was deleted and the event data is valid.
     $this->assertEquals(0, $DB->count_records('tag'));
     $this->assertInstanceOf('\\core\\event\\tag_deleted', $event);
     $this->assertEquals(context_system::instance(), $event->get_context());
     // Add multiple tag instances now and check that it still works.
     core_tag_tag::set_item_tags('core', 'course', $course->id, context_course::instance($course->id), array('fish', 'hamster'), $user->id);
     // Trigger and capture the event for deleting all tags in a course.
     $sink = $this->redirectEvents();
     core_tag_tag::remove_all_item_tags('core', 'course', $course->id);
     $events = $sink->get_events();
     $events = array($events[1], $events[3]);
     // Check that the tags were deleted and the events data is valid.
     $this->assertEquals(0, $DB->count_records('tag'));
     foreach ($events as $event) {
         $this->assertInstanceOf('\\core\\event\\tag_deleted', $event);
         $this->assertEquals(context_system::instance(), $event->get_context());
     }
 }
Exemplo n.º 13
0
 /**
  * Generates a page in wiki.
  *
  * @param stdClass wiki object returned from create_instance (if known)
  * @param stdClass|array $record data to insert as wiki entry.
  * @return stdClass
  * @throws coding_exception if neither $record->wikiid nor $wiki->id is specified
  */
 public function create_page($wiki, $record = array())
 {
     global $CFG, $USER;
     require_once $CFG->dirroot . '/mod/wiki/locallib.php';
     $this->pagecount++;
     $record = (array) $record + array('title' => 'wiki page ' . $this->pagecount, 'wikiid' => $wiki->id, 'subwikiid' => 0, 'group' => 0, 'content' => 'Wiki page content ' . $this->pagecount, 'format' => $wiki->defaultformat);
     if (empty($record['wikiid']) && empty($record['subwikiid'])) {
         throw new coding_exception('wiki page generator requires either wikiid or subwikiid');
     }
     if (!$record['subwikiid']) {
         if (!isset($record['userid'])) {
             $record['userid'] = $wiki->wikimode == 'individual' ? $USER->id : 0;
         }
         if ($subwiki = wiki_get_subwiki_by_group($record['wikiid'], $record['group'], $record['userid'])) {
             $record['subwikiid'] = $subwiki->id;
         } else {
             $record['subwikiid'] = wiki_add_subwiki($record['wikiid'], $record['group'], $record['userid']);
         }
     }
     $wikipage = wiki_get_page_by_title($record['subwikiid'], $record['title']);
     if (!$wikipage) {
         $pageid = wiki_create_page($record['subwikiid'], $record['title'], $record['format'], $USER->id);
         $wikipage = wiki_get_page($pageid);
     }
     $rv = wiki_save_page($wikipage, $record['content'], $USER->id);
     if (array_key_exists('tags', $record)) {
         $tags = is_array($record['tags']) ? $record['tags'] : preg_split('/,/', $record['tags']);
         if (empty($wiki->cmid)) {
             $cm = get_coursemodule_from_instance('wiki', $wiki->id, isset($wiki->course) ? $wiki->course : 0);
             $wiki->cmid = $cm->id;
         }
         core_tag_tag::set_item_tags('mod_wiki', 'wiki_pages', $wikipage->id, context_module::instance($wiki->cmid), $tags);
     }
     return $rv['page'];
 }
Exemplo n.º 14
0
/**
 * Update a course.
 *
 * Please note this functions does not verify any access control,
 * the calling code is responsible for all validation (usually it is the form definition).
 *
 * @param object $data  - all the data needed for an entry in the 'course' table
 * @param array $editoroptions course description editor options
 * @return void
 */
function update_course($data, $editoroptions = NULL)
{
    global $DB, $CFG;
    $data->timemodified = time();
    $oldcourse = course_get_format($data->id)->get_course();
    $context = context_course::instance($oldcourse->id);
    if ($editoroptions) {
        $data = file_postupdate_standard_editor($data, 'summary', $editoroptions, $context, 'course', 'summary', 0);
    }
    if ($overviewfilesoptions = course_overviewfiles_options($data->id)) {
        $data = file_postupdate_standard_filemanager($data, 'overviewfiles', $overviewfilesoptions, $context, 'course', 'overviewfiles', 0);
    }
    // Check we don't have a duplicate shortname.
    if (!empty($data->shortname) && $oldcourse->shortname != $data->shortname) {
        if ($DB->record_exists_sql('SELECT id from {course} WHERE shortname = ? AND id <> ?', array($data->shortname, $data->id))) {
            throw new moodle_exception('shortnametaken', '', '', $data->shortname);
        }
    }
    // Check we don't have a duplicate idnumber.
    if (!empty($data->idnumber) && $oldcourse->idnumber != $data->idnumber) {
        if ($DB->record_exists_sql('SELECT id from {course} WHERE idnumber = ? AND id <> ?', array($data->idnumber, $data->id))) {
            throw new moodle_exception('courseidnumbertaken', '', '', $data->idnumber);
        }
    }
    if (!isset($data->category) or empty($data->category)) {
        // prevent nulls and 0 in category field
        unset($data->category);
    }
    $changesincoursecat = $movecat = (isset($data->category) and $oldcourse->category != $data->category);
    if (!isset($data->visible)) {
        // data not from form, add missing visibility info
        $data->visible = $oldcourse->visible;
    }
    if ($data->visible != $oldcourse->visible) {
        // reset the visibleold flag when manually hiding/unhiding course
        $data->visibleold = $data->visible;
        $changesincoursecat = true;
    } else {
        if ($movecat) {
            $newcategory = $DB->get_record('course_categories', array('id' => $data->category));
            if (empty($newcategory->visible)) {
                // make sure when moving into hidden category the course is hidden automatically
                $data->visible = 0;
            }
        }
    }
    // Update with the new data
    $DB->update_record('course', $data);
    // make sure the modinfo cache is reset
    rebuild_course_cache($data->id);
    // update course format options with full course data
    course_get_format($data->id)->update_course_format_options($data, $oldcourse);
    $course = $DB->get_record('course', array('id' => $data->id));
    if ($movecat) {
        $newparent = context_coursecat::instance($course->category);
        $context->update_moved($newparent);
    }
    $fixcoursesortorder = $movecat || isset($data->sortorder) && $oldcourse->sortorder != $data->sortorder;
    if ($fixcoursesortorder) {
        fix_course_sortorder();
    }
    // purge appropriate caches in case fix_course_sortorder() did not change anything
    cache_helper::purge_by_event('changesincourse');
    if ($changesincoursecat) {
        cache_helper::purge_by_event('changesincoursecat');
    }
    // Test for and remove blocks which aren't appropriate anymore
    blocks_remove_inappropriate($course);
    // Save any custom role names.
    save_local_role_names($course->id, $data);
    // update enrol settings
    enrol_course_updated(false, $course, $data);
    // Update course tags.
    if (isset($data->tags)) {
        core_tag_tag::set_item_tags('core', 'course', $course->id, context_course::instance($course->id), $data->tags);
    }
    // Trigger a course updated event.
    $event = \core\event\course_updated::create(array('objectid' => $course->id, 'context' => context_course::instance($course->id), 'other' => array('shortname' => $course->shortname, 'fullname' => $course->fullname)));
    $event->set_legacy_logdata(array($course->id, 'course', 'update', 'edit.php?id=' . $course->id, $course->id));
    $event->trigger();
    if ($oldcourse->format !== $course->format) {
        // Remove all options stored for the previous format
        // We assume that new course format migrated everything it needed watching trigger
        // 'course_updated' and in method format_XXX::update_course_format_options()
        $DB->delete_records('course_format_options', array('courseid' => $course->id, 'format' => $oldcourse->format));
    }
}
Exemplo n.º 15
0
            case 'edit':
                if ($data->id && $DB->record_exists('blog_external', array('id' => $data->id))) {
                    $rss = new moodle_simplepie($data->url);
                    $external->id = $data->id;
                    $external->name = empty($data->name) ? $rss->get_title() : $data->name;
                    $external->description = empty($data->description) ? $rss->get_description() : $data->description;
                    $external->userid = $USER->id;
                    $external->url = $data->url;
                    $external->filtertags = !empty($data->filtertags) ? $data->filtertags : null;
                    $external->timemodified = time();
                    $DB->update_record('blog_external', $external);
                    // Log this action.
                    $eventparms = array('context' => $context, 'objectid' => $external->id, 'other' => array('url' => $external->url));
                    $event = \core\event\blog_external_updated::create($eventparms);
                    $event->trigger();
                    core_tag_tag::set_item_tags('core', 'blog_external', $external->id, context_user::instance($external->userid), $data->autotags);
                } else {
                    print_error('wrongexternalid', 'blog');
                }
                break;
            default:
                print_error('invalidaction');
        }
        redirect($returnurl);
    }
}
navigation_node::override_active_url(new moodle_url('/blog/external_blogs.php'));
$PAGE->navbar->add(get_string('addnewexternalblog', 'blog'));
$PAGE->set_heading(fullname($USER));
$PAGE->set_title("{$SITE->shortname}: {$strblogs}: {$strexternalblogs}");
echo $OUTPUT->header();
Exemplo n.º 16
0
 /**
  * Updates this entry in the database. Access control checks must be done by calling code.
  *
  * @param array       $params            Entry parameters.
  * @param moodleform  $form              Used for attachments.
  * @param array       $summaryoptions    Summary options.
  * @param array       $attachmentoptions Attachment options.
  *
  * @return void
  */
 public function edit($params = array(), $form = null, $summaryoptions = array(), $attachmentoptions = array())
 {
     global $CFG, $DB;
     $sitecontext = context_system::instance();
     $entry = $this;
     $this->form = $form;
     foreach ($params as $var => $val) {
         $entry->{$var} = $val;
     }
     $entry = file_postupdate_standard_editor($entry, 'summary', $summaryoptions, $sitecontext, 'blog', 'post', $entry->id);
     $entry = file_postupdate_standard_filemanager($entry, 'attachment', $attachmentoptions, $sitecontext, 'blog', 'attachment', $entry->id);
     if (!empty($CFG->useblogassociations)) {
         $entry->add_associations();
     }
     $entry->lastmodified = time();
     // Update record.
     $DB->update_record('post', $entry);
     core_tag_tag::set_item_tags('core', 'post', $entry->id, context_user::instance($this->userid), $entry->tags);
     $event = \core\event\blog_entry_updated::create(array('objectid' => $entry->id, 'relateduserid' => $entry->userid));
     $event->set_blog_entry($entry);
     $event->trigger();
 }
Exemplo n.º 17
0
 /**
  * Testing function core_tag_tag::combine_tags() when correlated tags are present.
  */
 public function test_combine_tags_with_correlated()
 {
     $task = new \core\task\tag_cron_task();
     $tags = $this->prepare_correlated();
     $task->compute_correlations();
     // Now 'cat' is correlated with 'cats'.
     // Also 'dog', 'dogs' and 'puppy' are correlated.
     // There is a manual relation between 'cat' and 'kitten'.
     // See function test_correlations() for assertions.
     // Combine tags 'dog' and 'kitten' into 'cat' and make sure that cat is now correlated with dogs and puppy.
     $tags['cat']->combine_tags(array($tags['dog'], $tags['kitten']));
     $correlatedtags = $this->get_correlated_tags_names($tags['cat']);
     $this->assertEquals(['cats', 'dogs', 'puppy'], $correlatedtags);
     $correlatedtags = $this->get_correlated_tags_names($tags['dogs']);
     $this->assertEquals(['cat', 'puppy'], $correlatedtags);
     $correlatedtags = $this->get_correlated_tags_names($tags['puppy']);
     $this->assertEquals(['cat', 'dogs'], $correlatedtags);
     // Add tag that does not have any correlations.
     $user7 = $this->getDataGenerator()->create_user();
     core_tag_tag::set_item_tags('core', 'user', $user7->id, context_user::instance($user7->id), array('hippo'));
     $tags['hippo'] = core_tag_tag::get_by_name(core_tag_collection::get_default(), 'hippo', '*');
     // Combine tag 'cat' into 'hippo'. Now 'hippo' should have the same correlations 'cat' used to have and also
     // tags 'dogs' and 'puppy' should have 'hippo' in correlations.
     $tags['hippo']->combine_tags(array($tags['cat']));
     $correlatedtags = $this->get_correlated_tags_names($tags['hippo']);
     $this->assertEquals(['cats', 'dogs', 'puppy'], $correlatedtags);
     $correlatedtags = $this->get_correlated_tags_names($tags['dogs']);
     $this->assertEquals(['hippo', 'puppy'], $correlatedtags);
     $correlatedtags = $this->get_correlated_tags_names($tags['puppy']);
     $this->assertEquals(['dogs', 'hippo'], $correlatedtags);
 }
Exemplo n.º 18
0
 /**
  * This function tests that the functions responsible for moving questions to
  * different contexts also updates the tag instances associated with the questions.
  */
 public function test_altering_tag_instance_context()
 {
     global $CFG, $DB;
     // Set to admin user.
     $this->setAdminUser();
     // Create two course categories - we are going to delete one of these later and will expect
     // all the questions belonging to the course in the deleted category to be moved.
     $coursecat1 = $this->getDataGenerator()->create_category();
     $coursecat2 = $this->getDataGenerator()->create_category();
     // Create a couple of categories and questions.
     $context1 = context_coursecat::instance($coursecat1->id);
     $context2 = context_coursecat::instance($coursecat2->id);
     $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
     $questioncat1 = $questiongenerator->create_question_category(array('contextid' => $context1->id));
     $questioncat2 = $questiongenerator->create_question_category(array('contextid' => $context2->id));
     $question1 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat1->id));
     $question2 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat1->id));
     $question3 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat2->id));
     $question4 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat2->id));
     // Now lets tag these questions.
     core_tag_tag::set_item_tags('core_question', 'question', $question1->id, $context1, array('tag 1', 'tag 2'));
     core_tag_tag::set_item_tags('core_question', 'question', $question2->id, $context1, array('tag 3', 'tag 4'));
     core_tag_tag::set_item_tags('core_question', 'question', $question3->id, $context2, array('tag 5', 'tag 6'));
     core_tag_tag::set_item_tags('core_question', 'question', $question4->id, $context2, array('tag 7', 'tag 8'));
     // Test moving the questions to another category.
     question_move_questions_to_category(array($question1->id, $question2->id), $questioncat2->id);
     // Test that all tag_instances belong to one context.
     $this->assertEquals(8, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid)));
     // Test moving them back.
     question_move_questions_to_category(array($question1->id, $question2->id), $questioncat1->id);
     // Test that all tag_instances are now reset to how they were initially.
     $this->assertEquals(4, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat1->contextid)));
     $this->assertEquals(4, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid)));
     // Now test moving a whole question category to another context.
     question_move_category_to_context($questioncat1->id, $questioncat1->contextid, $questioncat2->contextid);
     // Test that all tag_instances belong to one context.
     $this->assertEquals(8, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid)));
     // Now test moving them back.
     question_move_category_to_context($questioncat1->id, $questioncat2->contextid, context_coursecat::instance($coursecat1->id)->id);
     // Test that all tag_instances are now reset to how they were initially.
     $this->assertEquals(4, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat1->contextid)));
     $this->assertEquals(4, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid)));
     // Now we want to test deleting the course category and moving the questions to another category.
     question_delete_course_category($coursecat1, $coursecat2, false);
     // Test that all tag_instances belong to one context.
     $this->assertEquals(8, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid)));
     // Create a course.
     $course = $this->getDataGenerator()->create_course();
     // Create some question categories and questions in this course.
     $coursecontext = context_course::instance($course->id);
     $questioncat = $questiongenerator->create_question_category(array('contextid' => $coursecontext->id));
     $question1 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat->id));
     $question2 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat->id));
     // Add some tags to these questions.
     core_tag_tag::set_item_tags('core_question', 'question', $question1->id, $coursecontext, array('tag 1', 'tag 2'));
     core_tag_tag::set_item_tags('core_question', 'question', $question2->id, $coursecontext, array('tag 1', 'tag 2'));
     // Create a course that we are going to restore the other course to.
     $course2 = $this->getDataGenerator()->create_course();
     // Create backup file and save it to the backup location.
     $bc = new backup_controller(backup::TYPE_1COURSE, $course->id, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_GENERAL, 2);
     $bc->execute_plan();
     $results = $bc->get_results();
     $file = $results['backup_destination'];
     $fp = get_file_packer('application/vnd.moodle.backup');
     $filepath = $CFG->dataroot . '/temp/backup/test-restore-course';
     $file->extract_to_pathname($fp, $filepath);
     $bc->destroy();
     // Now restore the course.
     $rc = new restore_controller('test-restore-course', $course2->id, backup::INTERACTIVE_NO, backup::MODE_GENERAL, 2, backup::TARGET_NEW_COURSE);
     $rc->execute_precheck();
     $rc->execute_plan();
     // Get the created question category.
     $restoredcategory = $DB->get_record('question_categories', array('contextid' => context_course::instance($course2->id)->id), '*', MUST_EXIST);
     // Check that there are two questions in the restored to course's context.
     $this->assertEquals(2, $DB->count_records('question', array('category' => $restoredcategory->id)));
     $rc->destroy();
 }
Exemplo n.º 19
0
     $contextid = $category->contextid;
 }
 // Ensure we redirect back to the category the question is being saved into.
 $returnurl->param('category', $fromform->category);
 // We are acutally saving the question.
 if (!empty($question->id)) {
     question_require_capability_on($question, 'edit');
 } else {
     require_capability('moodle/question:add', context::instance_by_id($contextid));
     if (!empty($fromform->makecopy) && !$question->formoptions->cansaveasnew) {
         print_error('nopermissions', '', '', 'edit');
     }
 }
 $question = $qtypeobj->save_question($question, $fromform);
 if (isset($fromform->tags)) {
     core_tag_tag::set_item_tags('core_question', 'question', $question->id, context::instance_by_id($contextid), $fromform->tags);
 }
 // Purge this question from the cache.
 question_bank::notify_question_edited($question->id);
 // If we are saving and continuing to edit the question.
 if (!empty($fromform->updatebutton)) {
     $url->param('id', $question->id);
     $url->remove_params('makecopy');
     redirect($url);
 }
 if ($qtypeobj->finished_edit_wizard($fromform)) {
     if ($inpopup) {
         echo $OUTPUT->notification(get_string('changessaved'), '');
         close_window(3);
     } else {
         $returnurl->param('lastchanged', $question->id);