Exemple #1
0
 public function test_create_content()
 {
     global $DB;
     $this->resetAfterTest();
     $this->setAdminUser();
     $course = $this->getDataGenerator()->create_course();
     $wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course));
     $wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki');
     $page1 = $wikigenerator->create_first_page($wiki);
     $page2 = $wikigenerator->create_content($wiki);
     $page3 = $wikigenerator->create_content($wiki, array('title' => 'Custom title', 'tags' => array('Cats', 'mice')));
     unset($wiki->cmid);
     $page4 = $wikigenerator->create_content($wiki, array('tags' => 'Cats, dogs'));
     $subwikis = $DB->get_records('wiki_subwikis', array('wikiid' => $wiki->id), 'id');
     $this->assertEquals(1, count($subwikis));
     $subwikiid = key($subwikis);
     $records = $DB->get_records('wiki_pages', array('subwikiid' => $subwikiid), 'id');
     $this->assertEquals(4, count($records));
     $this->assertEquals($page1->id, $records[$page1->id]->id);
     $this->assertEquals($page2->id, $records[$page2->id]->id);
     $this->assertEquals($page3->id, $records[$page3->id]->id);
     $this->assertEquals('Custom title', $records[$page3->id]->title);
     $this->assertEquals(array('Cats', 'mice'), array_values(core_tag_tag::get_item_tags_array('mod_wiki', 'wiki_pages', $page3->id)));
     $this->assertEquals(array('Cats', 'dogs'), array_values(core_tag_tag::get_item_tags_array('mod_wiki', 'wiki_pages', $page4->id)));
 }
Exemple #2
0
 /**
  * Export this data so it can be used as the context for a mustache template.
  *
  * @param renderer_base $output
  * @return stdClass
  */
 public function export_for_template(renderer_base $output)
 {
     global $CFG;
     require_once $CFG->libdir . '/externallib.php';
     $r = new stdClass();
     $r->id = (int) $this->record->id;
     $r->tagcollid = clean_param($this->record->tagcollid, PARAM_INT);
     $r->rawname = clean_param($this->record->rawname, PARAM_TAG);
     $r->name = clean_param($this->record->name, PARAM_TAG);
     $format = clean_param($this->record->descriptionformat, PARAM_INT);
     list($r->description, $r->descriptionformat) = external_format_text($this->record->description, $format, \context_system::instance()->id, 'core', 'tag', $r->id);
     $r->flag = clean_param($this->record->flag, PARAM_INT);
     if (isset($this->record->official)) {
         $r->official = clean_param($this->record->official, PARAM_INT);
     } else {
         $r->official = $this->record->tagtype === 'official' ? 1 : 0;
     }
     $url = \core_tag_tag::make_url($r->tagcollid, $r->rawname);
     $r->viewurl = $url->out(false);
     $manageurl = new moodle_url('/tag/manage.php', array('sesskey' => sesskey(), 'tagid' => $this->record->id));
     $url = new moodle_url($manageurl);
     $url->param('action', 'changetype');
     $url->param('tagtype', $r->official ? 'default' : 'official');
     $r->changetypeurl = $url->out(false);
     $url = new moodle_url($manageurl);
     $url->param('action', $this->record->flag ? 'resetflag' : 'setflag');
     $r->changeflagurl = $url->out(false);
     return $r;
 }
Exemple #3
0
/**
 * Implements callback inplace_editable() allowing to edit values in-place
 *
 * @param string $itemtype
 * @param int $itemid
 * @param mixed $newvalue
 * @return \core\output\inplace_editable
 */
function core_tag_inplace_editable($itemtype, $itemid, $newvalue)
{
    if ($itemtype === 'tagname') {
        require_capability('moodle/tag:manage', context_system::instance());
        $tag = core_tag_tag::get($itemid, '*', MUST_EXIST);
        $tag->update(array('rawname' => $newvalue));
        return new \core_tag\output\tagname($tag);
    }
}
Exemple #4
0
 /**
  * Custom form validation
  *
  * @param array $data
  * @param array $files
  * @return array
  */
 public function validation($data, $files)
 {
     $errors = parent::validation($data, $files);
     if (isset($data['rawname'])) {
         $newname = core_text::strtolower($data['rawname']);
         $tag = $this->_customdata['tag'];
         if ($tag->name != $newname) {
             // The name has changed, let's make sure it's not another existing tag.
             if (core_tag_tag::get_by_name($tag->tagcollid, $newname)) {
                 // Something exists already, so flag an error.
                 $errors['rawname'] = get_string('namesalreadybeeingused', 'tag');
             }
         }
     }
     return $errors;
 }
Exemple #5
0
 /**
  * Constructor
  *
  * @param core_tag_tag|stdClass $tag
  * @param string $component
  * @param string $itemtype
  * @param string $content
  * @param bool $exclusivemode
  * @param int $fromctx context id where the link was displayed, may be used by callbacks
  *            to display items in the same context first
  * @param int $ctx context id where we need to search for items
  * @param int $rec search items in sub contexts as well
  * @param int $page
  * @param bool $totalpages
  */
 public function __construct($tag, $component, $itemtype, $content, $exclusivemode = false, $fromctx = 0, $ctx = 0, $rec = 1, $page = 0, $totalpages = 1)
 {
     $this->record = new stdClass();
     $this->tag = $tag;
     $tagareas = \core_tag_area::get_areas();
     if (!isset($tagareas[$itemtype][$component])) {
         throw new \coding_exception('Tag area for component ' . $component . ' and itemtype ' . $itemtype . ' is not defined');
     }
     $this->tagarea = $tagareas[$itemtype][$component];
     $this->record->tagid = $tag->id;
     $this->record->ta = $this->tagarea->id;
     $this->record->itemtype = $itemtype;
     $this->record->component = $component;
     $a = (object) array('tagarea' => \core_tag_area::display_name($component, $itemtype), 'tag' => \core_tag_tag::make_display_name($tag));
     if ($exclusivemode) {
         $this->record->title = get_string('itemstaggedwith', 'tag', $a);
     } else {
         $this->record->title = (string) $a->tagarea;
     }
     $this->record->content = $content;
     $this->record->nextpageurl = null;
     $this->record->prevpageurl = null;
     $this->record->exclusiveurl = null;
     $url = core_tag_tag::make_url($tag->tagcollid, $tag->rawname, $exclusivemode, $fromctx, $ctx, $rec);
     $urlparams = array('ta' => $this->tagarea->id);
     if ($totalpages > $page + 1) {
         $this->record->nextpageurl = new moodle_url($url, $urlparams + array('page' => $page + 1));
     }
     if ($page > 0) {
         $this->record->prevpageurl = new moodle_url($url, $urlparams + array('page' => $page - 1));
     }
     if (!$exclusivemode && ($totalpages > 1 || $page)) {
         $this->record->exclusiveurl = new moodle_url($url, $urlparams + array('excl' => 1));
     }
     $this->record->exclusivetext = get_string('exclusivemode', 'tag', $a);
     $this->record->hascontent = $totalpages > 1 || $page || $content;
     $this->record->anchor = $component . '_' . $itemtype;
 }
Exemple #6
0
/**
 * Implements callback to reset course
 *
 * @param stdClass $data
 * @return boolean|array
 */
function wiki_reset_userdata($data)
{
    global $CFG, $DB;
    require_once $CFG->dirroot . '/mod/wiki/pagelib.php';
    require_once $CFG->dirroot . "/mod/wiki/locallib.php";
    $componentstr = get_string('modulenameplural', 'wiki');
    $status = array();
    //get the wiki(s) in this course.
    if (!($wikis = $DB->get_records('wiki', array('course' => $data->courseid)))) {
        return false;
    }
    if (empty($data->reset_wiki_comments) && empty($data->reset_wiki_tags) && empty($data->reset_wiki_pages)) {
        return $status;
    }
    foreach ($wikis as $wiki) {
        if (!($cm = get_coursemodule_from_instance('wiki', $wiki->id, $data->courseid))) {
            continue;
        }
        $context = context_module::instance($cm->id);
        // Remove tags or all pages.
        if (!empty($data->reset_wiki_pages) || !empty($data->reset_wiki_tags)) {
            // Get subwiki information.
            $subwikis = wiki_get_subwikis($wiki->id);
            foreach ($subwikis as $subwiki) {
                // Get existing pages.
                if ($pages = wiki_get_page_list($subwiki->id)) {
                    // If the wiki page isn't selected then we are only removing tags.
                    if (empty($data->reset_wiki_pages)) {
                        // Go through each page and delete the tags.
                        foreach ($pages as $page) {
                            core_tag_tag::remove_all_item_tags('mod_wiki', 'wiki_pages', $page->id);
                        }
                    } else {
                        // Otherwise we are removing pages and tags.
                        wiki_delete_pages($context, $pages, $subwiki->id);
                    }
                }
                if (!empty($data->reset_wiki_pages)) {
                    // Delete any subwikis.
                    $DB->delete_records('wiki_subwikis', array('id' => $subwiki->id), IGNORE_MISSING);
                    // Delete any attached files.
                    $fs = get_file_storage();
                    $fs->delete_area_files($context->id, 'mod_wiki', 'attachments');
                }
            }
            if (!empty($data->reset_wiki_pages)) {
                $status[] = array('component' => $componentstr, 'item' => get_string('deleteallpages', 'wiki'), 'error' => false);
            }
            if (!empty($data->reset_wiki_tags)) {
                $status[] = array('component' => $componentstr, 'item' => get_string('tagsdeleted', 'wiki'), 'error' => false);
            }
        }
        // Remove all comments.
        if (!empty($data->reset_wiki_comments) || !empty($data->reset_wiki_pages)) {
            $DB->delete_records_select('comments', "contextid = ? AND commentarea='wiki_page'", array($context->id));
            if (!empty($data->reset_wiki_comments)) {
                $status[] = array('component' => $componentstr, 'item' => get_string('deleteallcomments'), 'error' => false);
            }
        }
    }
    return $status;
}
Exemple #7
0
 public function test_data_saved()
 {
     global $DB;
     $this->resetAfterTest(true);
     // Create.
     $mode = tool_uploadcourse_processor::MODE_CREATE_NEW;
     $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING;
     $data = array('shortname' => 'c1', 'fullname' => 'Fullname', 'category' => '1', 'visible' => '0', 'startdate' => '8 June 1990', 'idnumber' => '123abc', 'summary' => 'Summary', 'format' => 'weeks', 'theme' => 'afterburner', 'lang' => 'en', 'newsitems' => '7', 'showgrades' => '0', 'showreports' => '1', 'legacyfiles' => '1', 'maxbytes' => '1234', 'groupmode' => '2', 'groupmodeforce' => '1', 'enablecompletion' => '1', 'tags' => 'Cat, Dog', 'role_teacher' => 'Knight', 'role_manager' => 'Jedi', 'enrolment_1' => 'guest', 'enrolment_2' => 'self', 'enrolment_2_roleid' => '1', 'enrolment_3' => 'manual', 'enrolment_3_disable' => '1');
     $this->assertFalse($DB->record_exists('course', array('shortname' => 'c1')));
     $co = new tool_uploadcourse_course($mode, $updatemode, $data);
     $this->assertTrue($co->prepare());
     $co->proceed();
     $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1')));
     $course = $DB->get_record('course', array('shortname' => 'c1'));
     $ctx = context_course::instance($course->id);
     $this->assertEquals($data['fullname'], $course->fullname);
     $this->assertEquals($data['category'], $course->category);
     $this->assertEquals($data['visible'], $course->visible);
     $this->assertEquals(mktime(0, 0, 0, 6, 8, 1990), $course->startdate);
     $this->assertEquals($data['idnumber'], $course->idnumber);
     $this->assertEquals($data['summary'], $course->summary);
     $this->assertEquals($data['format'], $course->format);
     $this->assertEquals($data['theme'], $course->theme);
     $this->assertEquals($data['lang'], $course->lang);
     $this->assertEquals($data['newsitems'], $course->newsitems);
     $this->assertEquals($data['showgrades'], $course->showgrades);
     $this->assertEquals($data['showreports'], $course->showreports);
     $this->assertEquals($data['legacyfiles'], $course->legacyfiles);
     $this->assertEquals($data['maxbytes'], $course->maxbytes);
     $this->assertEquals($data['groupmode'], $course->groupmode);
     $this->assertEquals($data['groupmodeforce'], $course->groupmodeforce);
     $this->assertEquals($data['enablecompletion'], $course->enablecompletion);
     $this->assertEquals($data['tags'], join(', ', core_tag_tag::get_item_tags_array('core', 'course', $course->id)));
     // Roles.
     $roleids = array();
     $roles = get_all_roles();
     foreach ($roles as $role) {
         $roleids[$role->shortname] = $role->id;
     }
     $this->assertEquals('Knight', $DB->get_field_select('role_names', 'name', 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['teacher'])));
     $this->assertEquals('Jedi', $DB->get_field_select('role_names', 'name', 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['manager'])));
     // Enrolment methods.
     $enroldata = array();
     $instances = enrol_get_instances($course->id, false);
     $this->assertCount(3, $instances);
     foreach ($instances as $instance) {
         $enroldata[$instance->enrol] = $instance;
     }
     $this->assertNotEmpty($enroldata['guest']);
     $this->assertEquals(ENROL_INSTANCE_ENABLED, $enroldata['guest']->status);
     $this->assertNotEmpty($enroldata['self']);
     $this->assertEquals($data['enrolment_2_roleid'], $enroldata['self']->roleid);
     $this->assertEquals(ENROL_INSTANCE_ENABLED, $enroldata['self']->status);
     $this->assertNotEmpty($enroldata['manual']);
     $this->assertEquals(ENROL_INSTANCE_DISABLED, $enroldata['manual']->status);
     // Update existing course.
     $cat = $this->getDataGenerator()->create_category();
     $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY;
     $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY;
     $data = array('shortname' => 'c1', 'fullname' => 'Fullname 2', 'category' => $cat->id, 'visible' => '1', 'startdate' => '11 June 1984', 'idnumber' => 'changeidn', 'summary' => 'Summary 2', 'format' => 'topics', 'theme' => 'clean', 'lang' => '', 'newsitems' => '2', 'showgrades' => '1', 'showreports' => '0', 'legacyfiles' => '0', 'maxbytes' => '4321', 'groupmode' => '1', 'groupmodeforce' => '0', 'enablecompletion' => '0', 'role_teacher' => 'Teacher', 'role_manager' => 'Manager', 'enrolment_1' => 'guest', 'enrolment_1_disable' => '1', 'enrolment_2' => 'self', 'enrolment_2_roleid' => '2', 'enrolment_3' => 'manual', 'enrolment_3_delete' => '1');
     $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1')));
     $co = new tool_uploadcourse_course($mode, $updatemode, $data);
     $this->assertTrue($co->prepare());
     $co->proceed();
     $course = $DB->get_record('course', array('shortname' => 'c1'));
     $ctx = context_course::instance($course->id);
     $this->assertEquals($data['fullname'], $course->fullname);
     $this->assertEquals($data['category'], $course->category);
     $this->assertEquals($data['visible'], $course->visible);
     $this->assertEquals(mktime(0, 0, 0, 6, 11, 1984), $course->startdate);
     $this->assertEquals($data['idnumber'], $course->idnumber);
     $this->assertEquals($data['summary'], $course->summary);
     $this->assertEquals($data['format'], $course->format);
     $this->assertEquals($data['theme'], $course->theme);
     $this->assertEquals($data['lang'], $course->lang);
     $this->assertEquals($data['newsitems'], $course->newsitems);
     $this->assertEquals($data['showgrades'], $course->showgrades);
     $this->assertEquals($data['showreports'], $course->showreports);
     $this->assertEquals($data['legacyfiles'], $course->legacyfiles);
     $this->assertEquals($data['maxbytes'], $course->maxbytes);
     $this->assertEquals($data['groupmode'], $course->groupmode);
     $this->assertEquals($data['groupmodeforce'], $course->groupmodeforce);
     $this->assertEquals($data['enablecompletion'], $course->enablecompletion);
     // Roles.
     $roleids = array();
     $roles = get_all_roles();
     foreach ($roles as $role) {
         $roleids[$role->shortname] = $role->id;
     }
     $this->assertEquals('Teacher', $DB->get_field_select('role_names', 'name', 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['teacher'])));
     $this->assertEquals('Manager', $DB->get_field_select('role_names', 'name', 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['manager'])));
     // Enrolment methods.
     $enroldata = array();
     $instances = enrol_get_instances($course->id, false);
     $this->assertCount(2, $instances);
     foreach ($instances as $instance) {
         $enroldata[$instance->enrol] = $instance;
     }
     $this->assertNotEmpty($enroldata['guest']);
     $this->assertEquals(ENROL_INSTANCE_DISABLED, $enroldata['guest']->status);
     $this->assertNotEmpty($enroldata['self']);
     $this->assertEquals($data['enrolment_2_roleid'], $enroldata['self']->roleid);
     $this->assertEquals(ENROL_INSTANCE_ENABLED, $enroldata['self']->status);
 }
Exemple #8
0
/**
 * Clear a course out completely, deleting all content but don't delete the course itself.
 *
 * This function does not verify any permissions.
 *
 * Please note this function also deletes all user enrolments,
 * enrolment instances and role assignments by default.
 *
 * $options:
 *  - 'keep_roles_and_enrolments' - false by default
 *  - 'keep_groups_and_groupings' - false by default
 *
 * @param int $courseid The id of the course that is being deleted
 * @param bool $showfeedback Whether to display notifications of each action the function performs.
 * @param array $options extra options
 * @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 remove_course_contents($courseid, $showfeedback = true, array $options = null)
{
    global $CFG, $DB, $OUTPUT;
    require_once $CFG->libdir . '/badgeslib.php';
    require_once $CFG->libdir . '/completionlib.php';
    require_once $CFG->libdir . '/questionlib.php';
    require_once $CFG->libdir . '/gradelib.php';
    require_once $CFG->dirroot . '/group/lib.php';
    require_once $CFG->dirroot . '/comment/lib.php';
    require_once $CFG->dirroot . '/rating/lib.php';
    require_once $CFG->dirroot . '/notes/lib.php';
    // Handle course badges.
    badges_handle_course_deletion($courseid);
    // NOTE: these concatenated strings are suboptimal, but it is just extra info...
    $strdeleted = get_string('deleted') . ' - ';
    // Some crazy wishlist of stuff we should skip during purging of course content.
    $options = (array) $options;
    $course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
    $coursecontext = context_course::instance($courseid);
    $fs = get_file_storage();
    // Delete course completion information, this has to be done before grades and enrols.
    $cc = new completion_info($course);
    $cc->clear_criteria();
    if ($showfeedback) {
        echo $OUTPUT->notification($strdeleted . get_string('completion', 'completion'), 'notifysuccess');
    }
    // Remove all data from gradebook - this needs to be done before course modules
    // because while deleting this information, the system may need to reference
    // the course modules that own the grades.
    remove_course_grades($courseid, $showfeedback);
    remove_grade_letters($coursecontext, $showfeedback);
    // Delete course blocks in any all child contexts,
    // they may depend on modules so delete them first.
    $childcontexts = $coursecontext->get_child_contexts();
    // Returns all subcontexts since 2.2.
    foreach ($childcontexts as $childcontext) {
        blocks_delete_all_for_context($childcontext->id);
    }
    unset($childcontexts);
    blocks_delete_all_for_context($coursecontext->id);
    if ($showfeedback) {
        echo $OUTPUT->notification($strdeleted . get_string('type_block_plural', 'plugin'), 'notifysuccess');
    }
    // Get the list of all modules that are properly installed.
    $allmodules = $DB->get_records_menu('modules', array(), '', 'name, id');
    // Delete every instance of every module,
    // this has to be done before deleting of course level stuff.
    $locations = core_component::get_plugin_list('mod');
    foreach ($locations as $modname => $moddir) {
        if ($modname === 'NEWMODULE') {
            continue;
        }
        if (array_key_exists($modname, $allmodules)) {
            $sql = "SELECT cm.*, m.id AS modinstance, m.name, '{$modname}' AS modname\n              FROM {" . $modname . "} m\n                   LEFT JOIN {course_modules} cm ON cm.instance = m.id AND cm.module = :moduleid\n             WHERE m.course = :courseid";
            $instances = $DB->get_records_sql($sql, array('courseid' => $course->id, 'modulename' => $modname, 'moduleid' => $allmodules[$modname]));
            include_once "{$moddir}/lib.php";
            // Shows php warning only if plugin defective.
            $moddelete = $modname . '_delete_instance';
            // Delete everything connected to an instance.
            $moddeletecourse = $modname . '_delete_course';
            // Delete other stray stuff (uncommon).
            if ($instances) {
                foreach ($instances as $cm) {
                    if ($cm->id) {
                        // Delete activity context questions and question categories.
                        question_delete_activity($cm, $showfeedback);
                        // Notify the competency subsystem.
                        \core_competency\api::hook_course_module_deleted($cm);
                    }
                    if (function_exists($moddelete)) {
                        // This purges all module data in related tables, extra user prefs, settings, etc.
                        $moddelete($cm->modinstance);
                    } else {
                        // NOTE: we should not allow installation of modules with missing delete support!
                        debugging("Defective module '{$modname}' detected when deleting course contents: missing function {$moddelete}()!");
                        $DB->delete_records($modname, array('id' => $cm->modinstance));
                    }
                    if ($cm->id) {
                        // Delete cm and its context - orphaned contexts are purged in cron in case of any race condition.
                        context_helper::delete_instance(CONTEXT_MODULE, $cm->id);
                        $DB->delete_records('course_modules', array('id' => $cm->id));
                    }
                }
            }
            if (function_exists($moddeletecourse)) {
                // Execute optional course cleanup callback. Deprecated since Moodle 3.2. TODO MDL-53297 remove in 3.6.
                debugging("Callback delete_course is deprecated. Function {$moddeletecourse} should be converted " . 'to observer of event \\core\\event\\course_content_deleted', DEBUG_DEVELOPER);
                $moddeletecourse($course, $showfeedback);
            }
            if ($instances and $showfeedback) {
                echo $OUTPUT->notification($strdeleted . get_string('pluginname', $modname), 'notifysuccess');
            }
        } else {
            // Ooops, this module is not properly installed, force-delete it in the next block.
        }
    }
    // We have tried to delete everything the nice way - now let's force-delete any remaining module data.
    // Remove all data from availability and completion tables that is associated
    // with course-modules belonging to this course. Note this is done even if the
    // features are not enabled now, in case they were enabled previously.
    $DB->delete_records_select('course_modules_completion', 'coursemoduleid IN (SELECT id from {course_modules} WHERE course=?)', array($courseid));
    // Remove course-module data that has not been removed in modules' _delete_instance callbacks.
    $cms = $DB->get_records('course_modules', array('course' => $course->id));
    $allmodulesbyid = array_flip($allmodules);
    foreach ($cms as $cm) {
        if (array_key_exists($cm->module, $allmodulesbyid)) {
            try {
                $DB->delete_records($allmodulesbyid[$cm->module], array('id' => $cm->instance));
            } catch (Exception $e) {
                // Ignore weird or missing table problems.
            }
        }
        context_helper::delete_instance(CONTEXT_MODULE, $cm->id);
        $DB->delete_records('course_modules', array('id' => $cm->id));
    }
    if ($showfeedback) {
        echo $OUTPUT->notification($strdeleted . get_string('type_mod_plural', 'plugin'), 'notifysuccess');
    }
    // Cleanup the rest of plugins. Deprecated since Moodle 3.2. TODO MDL-53297 remove in 3.6.
    $cleanuplugintypes = array('report', 'coursereport', 'format');
    $callbacks = get_plugins_with_function('delete_course', 'lib.php');
    foreach ($cleanuplugintypes as $type) {
        if (!empty($callbacks[$type])) {
            foreach ($callbacks[$type] as $pluginfunction) {
                debugging("Callback delete_course is deprecated. Function {$pluginfunction} should be converted " . 'to observer of event \\core\\event\\course_content_deleted', DEBUG_DEVELOPER);
                $pluginfunction($course->id, $showfeedback);
            }
            if ($showfeedback) {
                echo $OUTPUT->notification($strdeleted . get_string('type_' . $type . '_plural', 'plugin'), 'notifysuccess');
            }
        }
    }
    // Delete questions and question categories.
    question_delete_course($course, $showfeedback);
    if ($showfeedback) {
        echo $OUTPUT->notification($strdeleted . get_string('questions', 'question'), 'notifysuccess');
    }
    // Make sure there are no subcontexts left - all valid blocks and modules should be already gone.
    $childcontexts = $coursecontext->get_child_contexts();
    // Returns all subcontexts since 2.2.
    foreach ($childcontexts as $childcontext) {
        $childcontext->delete();
    }
    unset($childcontexts);
    // Remove all roles and enrolments by default.
    if (empty($options['keep_roles_and_enrolments'])) {
        // This hack is used in restore when deleting contents of existing course.
        role_unassign_all(array('contextid' => $coursecontext->id, 'component' => ''), true);
        enrol_course_delete($course);
        if ($showfeedback) {
            echo $OUTPUT->notification($strdeleted . get_string('type_enrol_plural', 'plugin'), 'notifysuccess');
        }
    }
    // Delete any groups, removing members and grouping/course links first.
    if (empty($options['keep_groups_and_groupings'])) {
        groups_delete_groupings($course->id, $showfeedback);
        groups_delete_groups($course->id, $showfeedback);
    }
    // Filters be gone!
    filter_delete_all_for_context($coursecontext->id);
    // Notes, you shall not pass!
    note_delete_all($course->id);
    // Die comments!
    comment::delete_comments($coursecontext->id);
    // Ratings are history too.
    $delopt = new stdclass();
    $delopt->contextid = $coursecontext->id;
    $rm = new rating_manager();
    $rm->delete_ratings($delopt);
    // Delete course tags.
    core_tag_tag::remove_all_item_tags('core', 'course', $course->id);
    // Notify the competency subsystem.
    \core_competency\api::hook_course_deleted($course);
    // Delete calendar events.
    $DB->delete_records('event', array('courseid' => $course->id));
    $fs->delete_area_files($coursecontext->id, 'calendar');
    // Delete all related records in other core tables that may have a courseid
    // This array stores the tables that need to be cleared, as
    // table_name => column_name that contains the course id.
    $tablestoclear = array('backup_courses' => 'courseid', 'user_lastaccess' => 'courseid');
    foreach ($tablestoclear as $table => $col) {
        $DB->delete_records($table, array($col => $course->id));
    }
    // Delete all course backup files.
    $fs->delete_area_files($coursecontext->id, 'backup');
    // Cleanup course record - remove links to deleted stuff.
    $oldcourse = new stdClass();
    $oldcourse->id = $course->id;
    $oldcourse->summary = '';
    $oldcourse->cacherev = 0;
    $oldcourse->legacyfiles = 0;
    if (!empty($options['keep_groups_and_groupings'])) {
        $oldcourse->defaultgroupingid = 0;
    }
    $DB->update_record('course', $oldcourse);
    // Delete course sections.
    $DB->delete_records('course_sections', array('course' => $course->id));
    // Delete legacy, section and any other course files.
    $fs->delete_area_files($coursecontext->id, 'course');
    // Files from summary and section.
    // Delete all remaining stuff linked to context such as files, comments, ratings, etc.
    if (empty($options['keep_roles_and_enrolments']) and empty($options['keep_groups_and_groupings'])) {
        // Easy, do not delete the context itself...
        $coursecontext->delete_content();
    } else {
        // Hack alert!!!!
        // We can not drop all context stuff because it would bork enrolments and roles,
        // there might be also files used by enrol plugins...
    }
    // Delete legacy files - just in case some files are still left there after conversion to new file api,
    // also some non-standard unsupported plugins may try to store something there.
    fulldelete($CFG->dataroot . '/' . $course->id);
    // Delete from cache to reduce the cache size especially makes sense in case of bulk course deletion.
    $cachemodinfo = cache::make('core', 'coursemodinfo');
    $cachemodinfo->delete($courseid);
    // Trigger a course content deleted event.
    $event = \core\event\course_content_deleted::create(array('objectid' => $course->id, 'context' => $coursecontext, 'other' => array('shortname' => $course->shortname, 'fullname' => $course->fullname, 'options' => $options)));
    $event->add_record_snapshot('course', $course);
    $event->trigger();
    return true;
}
Exemple #9
0
 /**
  * Deletes this entry from the database. Access control checks must be done by calling code.
  *
  * @return void
  */
 public function delete()
 {
     global $DB;
     $this->delete_attachments();
     $this->remove_associations();
     // Get record to pass onto the event.
     $record = $DB->get_record('post', array('id' => $this->id));
     $DB->delete_records('post', array('id' => $this->id));
     core_tag_tag::remove_all_item_tags('core', 'post', $this->id);
     $event = \core\event\blog_entry_deleted::create(array('objectid' => $this->id, 'relateduserid' => $this->userid));
     $event->add_record_snapshot("post", $record);
     $event->set_blog_entry($this);
     $event->trigger();
 }
Exemple #10
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));
    }
}
Exemple #11
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);
 }
Exemple #12
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);
 }
Exemple #13
0
$usercontext = context_user::instance($USER->id);
switch ($action) {
    case 'addinterest':
        if (!core_tag_tag::is_enabled('core', 'user')) {
            print_error('tagdisabled');
        }
        $tag = required_param('tag', PARAM_TAG);
        core_tag_tag::add_item_tag('core', 'user', $USER->id, $usercontext, $tag);
        $tc = core_tag_area::get_collection('core', 'user');
        redirect(core_tag_tag::make_url($tc, $tag));
        break;
    case 'removeinterest':
        if (!core_tag_tag::is_enabled('core', 'user')) {
            print_error('tagdisabled');
        }
        $tag = required_param('tag', PARAM_TAG);
        core_tag_tag::remove_item_tag('core', 'user', $USER->id, $tag);
        $tc = core_tag_area::get_collection('core', 'user');
        redirect(core_tag_tag::make_url($tc, $tag));
        break;
    case 'flaginappropriate':
        require_capability('moodle/tag:flag', context_system::instance());
        $id = required_param('id', PARAM_INT);
        $tagobject = core_tag_tag::get($id, '*', MUST_EXIST);
        $tagobject->flag();
        redirect($tagobject->get_view_url(), get_string('responsiblewillbenotified', 'tag'));
        break;
    default:
        print_error('unknowaction');
        break;
}
Exemple #14
0
/**
 * Private function to factor common code out of get_question_options().
 *
 * @param object $question the question to tidy.
 * @param boolean $loadtags load the question tags from the tags table. Optional, default false.
 */
function _tidy_question($question, $loadtags = false)
{
    global $CFG;
    // Load question-type specific fields.
    if (!question_bank::is_qtype_installed($question->qtype)) {
        $question->questiontext = html_writer::tag('p', get_string('warningmissingtype', 'qtype_missingtype')) . $question->questiontext;
    }
    question_bank::get_qtype($question->qtype)->get_question_options($question);
    // Convert numeric fields to float. (Prevents these being displayed as 1.0000000.)
    $question->defaultmark += 0;
    $question->penalty += 0;
    if (isset($question->_partiallyloaded)) {
        unset($question->_partiallyloaded);
    }
    if ($loadtags && core_tag_tag::is_enabled('core_question', 'question')) {
        $question->tags = core_tag_tag::get_item_tags_array('core_question', 'question', $question->id);
    }
}
Exemple #15
0
 /**
  * Moves existing tags associated with an item type to another tag collection
  *
  * @param string $component
  * @param string $itemtype
  * @param int $tagcollid
  */
 public static function move_tags($component, $itemtype, $tagcollid)
 {
     global $DB;
     $params = array('itemtype1' => $itemtype, 'component1' => $component, 'itemtype2' => $itemtype, 'component2' => $component, 'tagcollid1' => $tagcollid, 'tagcollid2' => $tagcollid);
     // Find all collections that need to be cleaned later.
     $sql = "SELECT DISTINCT t.tagcollid " . "FROM {tag_instance} ti " . "JOIN {tag} t ON t.id = ti.tagid AND t.tagcollid <> :tagcollid1 " . "WHERE ti.itemtype = :itemtype2 AND ti.component = :component2 ";
     $cleanupcollections = $DB->get_fieldset_sql($sql, $params);
     // Find all tags that are related to the tags being moved and make sure they are present in the target tagcoll.
     // This query is a little complicated because Oracle does not allow to run SELECT DISTINCT on CLOB fields.
     $sql = "SELECT name, rawname, description, descriptionformat, userid, tagtype, flag " . "FROM {tag} WHERE id IN " . "(SELECT r.id " . "FROM {tag_instance} ti " . "JOIN {tag} t ON t.id = ti.tagid AND t.tagcollid <> :tagcollid1 " . "JOIN {tag_instance} tr ON tr.itemtype = 'tag' and tr.component = 'core' AND tr.itemid = t.id " . "JOIN {tag} r ON r.id = tr.tagid " . "LEFT JOIN {tag} re ON re.name = r.name AND re.tagcollid = :tagcollid2 " . "WHERE ti.itemtype = :itemtype2 AND ti.component = :component2 " . "    AND re.id IS NULL)";
     // We need related tags that ARE NOT present in the target tagcoll.
     $result = $DB->get_records_sql($sql, $params);
     foreach ($result as $tag) {
         $tag->tagcollid = $tagcollid;
         $tag->id = $DB->insert_record('tag', $tag);
         \core\event\tag_created::create_from_tag($tag);
     }
     // Find all tags that need moving and have related tags, remember their related tags.
     $sql = "SELECT t.name AS tagname, r.rawname AS relatedtag " . "FROM {tag_instance} ti " . "JOIN {tag} t ON t.id = ti.tagid AND t.tagcollid <> :tagcollid1 " . "JOIN {tag_instance} tr ON t.id = tr.tagid AND tr.itemtype = 'tag' and tr.component = 'core' " . "JOIN {tag} r ON r.id = tr.itemid " . "WHERE ti.itemtype = :itemtype2 AND ti.component = :component2 " . "ORDER BY t.id, tr.ordering ";
     $relatedtags = array();
     $result = $DB->get_recordset_sql($sql, $params);
     foreach ($result as $record) {
         $relatedtags[$record->tagname][] = $record->relatedtag;
     }
     $result->close();
     // Find all tags that are used for this itemtype/component and are not present in the target tag collection.
     // This query is a little complicated because Oracle does not allow to run SELECT DISTINCT on CLOB fields.
     $sql = "SELECT id, name, rawname, description, descriptionformat, userid, tagtype, flag\n                FROM {tag} WHERE id IN\n                (SELECT t.id\n                FROM {tag_instance} ti\n                JOIN {tag} t ON t.id = ti.tagid AND t.tagcollid <> :tagcollid1\n                LEFT JOIN {tag} tt ON tt.name = t.name AND tt.tagcollid = :tagcollid2\n                WHERE ti.itemtype = :itemtype2 AND ti.component = :component2\n                    AND tt.id IS NULL)";
     $movedtags = array();
     // Keep track of moved tags so we don't hit DB index violation.
     $result = $DB->get_records_sql($sql, $params);
     foreach ($result as $tag) {
         $originaltagid = $tag->id;
         if (array_key_exists($tag->name, $movedtags)) {
             // Case of corrupted data when the same tag was in several collections.
             $tag->id = $movedtags[$tag->name];
         } else {
             // Copy the tag into the new collection.
             unset($tag->id);
             $tag->tagcollid = $tagcollid;
             $tag->id = $DB->insert_record('tag', $tag);
             \core\event\tag_created::create_from_tag($tag);
             $movedtags[$tag->name] = $tag->id;
         }
         $DB->execute("UPDATE {tag_instance} SET tagid = ? WHERE tagid = ? AND itemtype = ? AND component = ?", array($tag->id, $originaltagid, $itemtype, $component));
     }
     // Find all tags that are used for this itemtype/component and are already present in the target tag collection.
     $sql = "SELECT DISTINCT t.id, tt.id AS targettagid\n                FROM {tag_instance} ti\n                JOIN {tag} t ON t.id = ti.tagid AND t.tagcollid <> :tagcollid1\n                JOIN {tag} tt ON tt.name = t.name AND tt.tagcollid = :tagcollid2\n                WHERE ti.itemtype = :itemtype2 AND ti.component = :component2";
     $result = $DB->get_records_sql($sql, $params);
     foreach ($result as $tag) {
         $DB->execute("UPDATE {tag_instance} SET tagid = ? WHERE tagid = ? AND itemtype = ? AND component = ?", array($tag->targettagid, $tag->id, $itemtype, $component));
     }
     // Add related tags to the moved tags.
     if ($relatedtags) {
         $tags = core_tag_tag::get_by_name_bulk($tagcollid, array_keys($relatedtags));
         foreach ($tags as $tag) {
             $tag->add_related_tags($relatedtags[$tag->name]);
         }
     }
     if ($cleanupcollections) {
         core_tag_collection::cleanup_unused_tags($cleanupcollections);
     }
     // Reset caches.
     cache::make('core', 'tags')->delete('tag_area');
 }
Exemple #16
0
/**
 * Returns the correlated tags of a tag, retrieved from the tag_correlation table. Make sure cron runs, otherwise the table will be
 * empty and this function won't return anything.
 *
 * Correlated tags are calculated in cron based on existing tag instances.
 *
 * @package core_tag
 * @deprecated since 3.1
 * @param   int      $tagid   is a single tag id
 * @param   int      $notused  this argument is no longer used
 * @return  array    an array of tag objects or an empty if no correlated tags are found
 */
function tag_get_correlated($tagid, $notused = null)
{
    debugging('Method tag_get_correlated() is deprecated, ' . 'use core_tag_tag::get_correlated_tags()', DEBUG_DEVELOPER);
    $result = array();
    if ($tag = core_tag_tag::get($tagid)) {
        $tags = $tag->get_correlated_tags(true);
        // Convert to objects for backward-compatibility.
        foreach ($tags as $id => $tag) {
            $result[$id] = $tag->to_object();
        }
    }
    return $result;
}
Exemple #17
0
 /**
  * Test functions core_tag_tag::create_if_missing() and core_tag_tag::get_by_name_bulk().
  */
 public function test_create_get()
 {
     $tagset = array('Cat', ' Dog  ', '<Mouse', '<>', 'mouse', 'Dog');
     $collid = core_tag_collection::get_default();
     $tags = core_tag_tag::create_if_missing($collid, $tagset);
     $this->assertEquals(array('cat', 'dog', 'mouse'), array_keys($tags));
     $this->assertEquals('Dog', $tags['dog']->rawname);
     $this->assertEquals('mouse', $tags['mouse']->rawname);
     // Case of the last tag wins.
     $tags2 = core_tag_tag::create_if_missing($collid, array('CAT', 'Elephant'));
     $this->assertEquals(array('cat', 'elephant'), array_keys($tags2));
     $this->assertEquals('Cat', $tags2['cat']->rawname);
     $this->assertEquals('Elephant', $tags2['elephant']->rawname);
     $this->assertEquals($tags['cat']->id, $tags2['cat']->id);
     // Tag 'cat' already existed and was not created again.
     $tags3 = core_tag_tag::get_by_name_bulk($collid, $tagset);
     $this->assertEquals(array('cat', 'dog', 'mouse'), array_keys($tags3));
     $this->assertEquals('Dog', $tags3['dog']->rawname);
     $this->assertEquals('mouse', $tags3['mouse']->rawname);
 }
Exemple #18
0
        redirect($PAGE->url);
        break;
    case 'changetype':
        require_sesskey();
        if ($tagid && $tagobject->update(array('isstandard' => $isstandard ? 1 : 0))) {
            redirect(new moodle_url($PAGE->url, array('notice' => 'typechanged')));
        }
        redirect($PAGE->url);
        break;
    case 'addstandardtag':
        require_sesskey();
        $tagobjects = null;
        if ($tagcoll) {
            $otagsadd = optional_param('otagsadd', '', PARAM_RAW);
            $newtags = preg_split('/\\s*,\\s*/', trim($otagsadd), -1, PREG_SPLIT_NO_EMPTY);
            $tagobjects = core_tag_tag::create_if_missing($tagcoll->id, $newtags, true);
        }
        foreach ($tagobjects as $tagobject) {
            if (!$tagobject->isstandard) {
                $tagobject->update(array('isstandard' => 1));
            }
        }
        redirect(new moodle_url($PAGE->url, $tagobjects ? array('notice' => 'added') : null));
        break;
}
echo $OUTPUT->header();
if ($notice && get_string_manager()->string_exists($notice, 'tag')) {
    echo $OUTPUT->notification(get_string($notice, 'tag'), 'notifysuccess');
}
if (!$tagcoll) {
    // Tag collection is not specified. Display the overview of tag collections and tag areas.
Exemple #19
0
/**
 * Powerful function that is used by edit and editadvanced to add common form elements/rules/etc.
 *
 * @param moodleform $mform
 * @param array $editoroptions
 * @param array $filemanageroptions
 * @param stdClass $user
 */
function useredit_shared_definition(&$mform, $editoroptions, $filemanageroptions, $user)
{
    global $CFG, $USER, $DB;
    if ($user->id > 0) {
        useredit_load_preferences($user, false);
    }
    $strrequired = get_string('required');
    $stringman = get_string_manager();
    // Add the necessary names.
    foreach (useredit_get_required_name_fields() as $fullname) {
        $mform->addElement('text', $fullname, get_string($fullname), 'maxlength="100" size="30"');
        if ($stringman->string_exists('missing' . $fullname, 'core')) {
            $strmissingfield = get_string('missing' . $fullname, 'core');
        } else {
            $strmissingfield = $strrequired;
        }
        $mform->addRule($fullname, $strmissingfield, 'required', null, 'client');
        $mform->setType($fullname, PARAM_NOTAGS);
    }
    $enabledusernamefields = useredit_get_enabled_name_fields();
    // Add the enabled additional name fields.
    foreach ($enabledusernamefields as $addname) {
        $mform->addElement('text', $addname, get_string($addname), 'maxlength="100" size="30"');
        $mform->setType($addname, PARAM_NOTAGS);
    }
    // Do not show email field if change confirmation is pending.
    if ($user->id > 0 and !empty($CFG->emailchangeconfirmation) and !empty($user->preference_newemail)) {
        $notice = get_string('emailchangepending', 'auth', $user);
        $notice .= '<br /><a href="edit.php?cancelemailchange=1&amp;id=' . $user->id . '">' . get_string('emailchangecancel', 'auth') . '</a>';
        $mform->addElement('static', 'emailpending', get_string('email'), $notice);
    } else {
        $mform->addElement('text', 'email', get_string('email'), 'maxlength="100" size="30"');
        $mform->addRule('email', $strrequired, 'required', null, 'client');
        $mform->setType('email', PARAM_RAW_TRIMMED);
    }
    $choices = array();
    $choices['0'] = get_string('emaildisplayno');
    $choices['1'] = get_string('emaildisplayyes');
    $choices['2'] = get_string('emaildisplaycourse');
    $mform->addElement('select', 'maildisplay', get_string('emaildisplay'), $choices);
    $mform->setDefault('maildisplay', core_user::get_property_default('maildisplay'));
    $mform->addElement('text', 'city', get_string('city'), 'maxlength="120" size="21"');
    $mform->setType('city', PARAM_TEXT);
    if (!empty($CFG->defaultcity)) {
        $mform->setDefault('city', $CFG->defaultcity);
    }
    $choices = get_string_manager()->get_list_of_countries();
    $choices = array('' => get_string('selectacountry') . '...') + $choices;
    $mform->addElement('select', 'country', get_string('selectacountry'), $choices);
    if (!empty($CFG->country)) {
        $mform->setDefault('country', core_user::get_property_default('country'));
    }
    if (isset($CFG->forcetimezone) and $CFG->forcetimezone != 99) {
        $choices = core_date::get_list_of_timezones($CFG->forcetimezone);
        $mform->addElement('static', 'forcedtimezone', get_string('timezone'), $choices[$CFG->forcetimezone]);
        $mform->addElement('hidden', 'timezone');
        $mform->setType('timezone', core_user::get_property_type('timezone'));
    } else {
        $choices = core_date::get_list_of_timezones($user->timezone, true);
        $mform->addElement('select', 'timezone', get_string('timezone'), $choices);
    }
    if (!empty($CFG->allowuserthemes)) {
        $choices = array();
        $choices[''] = get_string('default');
        $themes = get_list_of_themes();
        foreach ($themes as $key => $theme) {
            if (empty($theme->hidefromselector)) {
                $choices[$key] = get_string('pluginname', 'theme_' . $theme->name);
            }
        }
        $mform->addElement('select', 'theme', get_string('preferredtheme'), $choices);
    }
    $mform->addElement('editor', 'description_editor', get_string('userdescription'), null, $editoroptions);
    $mform->setType('description_editor', PARAM_CLEANHTML);
    $mform->addHelpButton('description_editor', 'userdescription');
    if (empty($USER->newadminuser)) {
        $mform->addElement('header', 'moodle_picture', get_string('pictureofuser'));
        $mform->setExpanded('moodle_picture', true);
        if (!empty($CFG->enablegravatar)) {
            $mform->addElement('html', html_writer::tag('p', get_string('gravatarenabled')));
        }
        $mform->addElement('static', 'currentpicture', get_string('currentpicture'));
        $mform->addElement('checkbox', 'deletepicture', get_string('delete'));
        $mform->setDefault('deletepicture', 0);
        $mform->addElement('filemanager', 'imagefile', get_string('newpicture'), '', $filemanageroptions);
        $mform->addHelpButton('imagefile', 'newpicture');
        $mform->addElement('text', 'imagealt', get_string('imagealt'), 'maxlength="100" size="30"');
        $mform->setType('imagealt', PARAM_TEXT);
    }
    // Display user name fields that are not currenlty enabled here if there are any.
    $disabledusernamefields = useredit_get_disabled_name_fields($enabledusernamefields);
    if (count($disabledusernamefields) > 0) {
        $mform->addElement('header', 'moodle_additional_names', get_string('additionalnames'));
        foreach ($disabledusernamefields as $allname) {
            $mform->addElement('text', $allname, get_string($allname), 'maxlength="100" size="30"');
            $mform->setType($allname, PARAM_NOTAGS);
        }
    }
    if (core_tag_tag::is_enabled('core', 'user') and empty($USER->newadminuser)) {
        $mform->addElement('header', 'moodle_interests', get_string('interests'));
        $mform->addElement('tags', 'interests', get_string('interestslist'), array('itemtype' => 'user', 'component' => 'core'));
        $mform->addHelpButton('interests', 'interestslist');
    }
    // Moodle optional fields.
    $mform->addElement('header', 'moodle_optional', get_string('optional', 'form'));
    $mform->addElement('text', 'url', get_string('webpage'), 'maxlength="255" size="50"');
    $mform->setType('url', core_user::get_property_type('url'));
    $mform->addElement('text', 'icq', get_string('icqnumber'), 'maxlength="15" size="25"');
    $mform->setType('icq', core_user::get_property_type('icq'));
    $mform->setForceLtr('icq');
    $mform->addElement('text', 'skype', get_string('skypeid'), 'maxlength="50" size="25"');
    $mform->setType('skype', core_user::get_property_type('skype'));
    $mform->setForceLtr('skype');
    $mform->addElement('text', 'aim', get_string('aimid'), 'maxlength="50" size="25"');
    $mform->setType('aim', core_user::get_property_type('aim'));
    $mform->setForceLtr('aim');
    $mform->addElement('text', 'yahoo', get_string('yahooid'), 'maxlength="50" size="25"');
    $mform->setType('yahoo', core_user::get_property_type('yahoo'));
    $mform->setForceLtr('yahoo');
    $mform->addElement('text', 'msn', get_string('msnid'), 'maxlength="50" size="25"');
    $mform->setType('msn', core_user::get_property_type('msn'));
    $mform->setForceLtr('msn');
    $mform->addElement('text', 'idnumber', get_string('idnumber'), 'maxlength="255" size="25"');
    $mform->setType('idnumber', core_user::get_property_type('idnumber'));
    $mform->addElement('text', 'institution', get_string('institution'), 'maxlength="255" size="25"');
    $mform->setType('institution', core_user::get_property_type('institution'));
    $mform->addElement('text', 'department', get_string('department'), 'maxlength="255" size="25"');
    $mform->setType('department', core_user::get_property_type('department'));
    $mform->addElement('text', 'phone1', get_string('phone1'), 'maxlength="20" size="25"');
    $mform->setType('phone1', core_user::get_property_type('phone1'));
    $mform->setForceLtr('phone1');
    $mform->addElement('text', 'phone2', get_string('phone2'), 'maxlength="20" size="25"');
    $mform->setType('phone2', core_user::get_property_type('phone2'));
    $mform->setForceLtr('phone2');
    $mform->addElement('text', 'address', get_string('address'), 'maxlength="255" size="25"');
    $mform->setType('address', core_user::get_property_type('address'));
}
Exemple #20
0
 protected function process_tag($data)
 {
     global $CFG, $DB;
     $data = (object) $data;
     $newquestion = $this->get_new_parentid('question');
     $questioncreated = (bool) $this->get_mappingid('question_created', $this->get_old_parentid('question'));
     if (!$questioncreated) {
         // This question already exists in the question bank. Nothing for us to do.
         return;
     }
     if (core_tag_tag::is_enabled('core_question', 'question')) {
         $tagname = $data->rawname;
         // Get the category, so we can then later get the context.
         $categoryid = $this->get_new_parentid('question_category');
         if (empty($this->cachedcategory) || $this->cachedcategory->id != $categoryid) {
             $this->cachedcategory = $DB->get_record('question_categories', array('id' => $categoryid));
         }
         // Add the tag to the question.
         core_tag_tag::add_item_tag('core_question', 'question', $newquestion, context::instance_by_id($this->cachedcategory->contextid), $tagname);
     }
 }
Exemple #21
0
                    $entry->courseassoc = $assocrec->contextid;
                    break;
                case CONTEXT_MODULE:
                    $entry->modassoc = $assocrec->contextid;
                    break;
            }
        }
    }
}
$summaryoptions = array('maxfiles' => 99, 'maxbytes' => $CFG->maxbytes, 'trusttext' => true, 'context' => $sitecontext, 'subdirs' => file_area_contains_subdirs($sitecontext, 'blog', 'post', $entry->id));
$attachmentoptions = array('subdirs' => false, 'maxfiles' => 99, 'maxbytes' => $CFG->maxbytes);
$blogeditform = new blog_edit_form(null, compact('entry', 'summaryoptions', 'attachmentoptions', 'sitecontext', 'courseid', 'modid'));
$entry = file_prepare_standard_editor($entry, 'summary', $summaryoptions, $sitecontext, 'blog', 'post', $entry->id);
$entry = file_prepare_standard_filemanager($entry, 'attachment', $attachmentoptions, $sitecontext, 'blog', 'attachment', $entry->id);
if (!empty($entry->id)) {
    $entry->tags = core_tag_tag::get_item_tags_array('core', 'post', $entry->id);
}
$entry->action = $action;
// Set defaults.
$blogeditform->set_data($entry);
if ($blogeditform->is_cancelled()) {
    redirect($returnurl);
} else {
    if ($data = $blogeditform->get_data()) {
        switch ($action) {
            case 'add':
                $blogentry = new blog_entry(null, $data, $blogeditform);
                $blogentry->add();
                $blogentry->edit($data, $blogeditform, $summaryoptions, $attachmentoptions);
                break;
            case 'edit':
Exemple #22
0
 /**
  * Get tags by their ids
  *
  * @param array $params
  */
 public static function get_tagindex($params)
 {
     global $PAGE;
     // Validate and normalize parameters.
     $tagindex = self::validate_parameters(self::get_tagindex_parameters(), array('tagindex' => $params));
     $params = $tagindex['tagindex'] + array('excl' => 0, 'from' => 0, 'ctx' => 0, 'rec' => 1, 'page' => 0);
     // Login to the course / module if applicable.
     $context = $params['ctx'] ? context::instance_by_id($params['ctx']) : context_system::instance();
     require_login(null, false, null, false, true);
     self::validate_context($context);
     $tag = core_tag_tag::get_by_name($params['tc'], $params['tag'], '*', MUST_EXIST);
     $tagareas = core_tag_collection::get_areas($params['tc']);
     $tagindex = $tag->get_tag_index($tagareas[$params['ta']], $params['excl'], $params['from'], $params['ctx'], $params['rec'], $params['page']);
     $renderer = $PAGE->get_renderer('core');
     return $tagindex->export_for_template($renderer);
 }
Exemple #23
0
/**
 * Generate any blog RSS feed via one function
 *
 * @param stdClass $context The context of the blog for which the feed it being generated
 * @param array    $args    An array of arguements needed to build the feed (contextid, token, componentname, type, id, tagid)
 */
function blog_rss_get_feed($context, $args)
{
    global $CFG, $SITE, $DB;
    if (empty($CFG->enableblogs)) {
        debugging('Blogging disabled on this site, RSS feeds are not available');
        return null;
    }
    if (empty($CFG->enablerssfeeds)) {
        debugging('Sorry, RSS feeds are disabled on this site');
        return '';
    }
    if ($CFG->bloglevel == BLOG_SITE_LEVEL) {
        if (isguestuser()) {
            debugging(get_string('nopermissiontoshow', 'error'));
            return '';
        }
    }
    $sitecontext = context_system::instance();
    if (!has_capability('moodle/blog:view', $sitecontext)) {
        return null;
    }
    $type = clean_param($args[3], PARAM_ALPHA);
    $id = clean_param($args[4], PARAM_INT);
    // Could be groupid / courseid  / userid  depending on $type.
    $tagid = 0;
    if ($args[5] != 'rss.xml') {
        $tagid = clean_param($args[5], PARAM_INT);
    } else {
        $tagid = 0;
    }
    $filename = blog_rss_file_name($type, $id, $tagid);
    if (file_exists($filename)) {
        if (filemtime($filename) + 3600 > time()) {
            return $filename;
            // It's already done so we return cached version.
        }
    }
    $courseid = $groupid = $userid = null;
    switch ($type) {
        case 'site':
            break;
        case 'course':
            $courseid = $id;
            break;
        case 'group':
            $groupid = $id;
            break;
        case 'user':
            $userid = $id;
            break;
    }
    // Get all the entries from the database.
    require_once $CFG->dirroot . '/blog/locallib.php';
    $blogheaders = blog_get_headers($courseid, $groupid, $userid, $tagid);
    $bloglisting = new blog_listing($blogheaders['filters']);
    $blogentries = $bloglisting->get_entries();
    // Now generate an array of RSS items.
    if ($blogentries) {
        $items = array();
        foreach ($blogentries as $blogentry) {
            $item = new stdClass();
            $item->author = fullname($DB->get_record('user', array('id' => $blogentry->userid)));
            // TODO: this is slow.
            $item->title = $blogentry->subject;
            $item->pubdate = $blogentry->lastmodified;
            $item->link = $CFG->wwwroot . '/blog/index.php?entryid=' . $blogentry->id;
            $summary = file_rewrite_pluginfile_urls($blogentry->summary, 'pluginfile.php', $sitecontext->id, 'blog', 'post', $blogentry->id);
            $item->description = format_text($summary, $blogentry->format);
            if ($blogtags = core_tag_tag::get_item_tags_array('core', 'post', $blogentry->id)) {
                $item->tags = $blogtags;
                $item->tagscheme = $CFG->wwwroot . '/tag';
            }
            $items[] = $item;
        }
        $articles = rss_add_items($items);
        // Change structure to XML.
    } else {
        $articles = '';
    }
    // Get header and footer information.
    switch ($type) {
        case 'user':
            $info = fullname($DB->get_record('user', array('id' => $id), get_all_user_name_fields(true)));
            break;
        case 'course':
            $info = $DB->get_field('course', 'fullname', array('id' => $id));
            $info = format_string($info, true, array('context' => context_course::instance($id)));
            break;
        case 'site':
            $info = format_string($SITE->fullname, true, array('context' => context_course::instance(SITEID)));
            break;
        case 'group':
            $group = groups_get_group($id);
            $info = $group->name;
            // TODO: $DB->get_field('groups', 'name', array('id' => $id)).
            break;
        default:
            $info = '';
            break;
    }
    if ($tagid) {
        $info .= ': ' . $DB->get_field('tags', 'text', array('id' => $tagid));
    }
    $header = rss_standard_header(get_string($type . 'blog', 'blog', $info), $CFG->wwwroot . '/blog/index.php', get_string('intro', 'blog'));
    $footer = rss_standard_footer();
    // Save the XML contents to file.
    $rssdata = $header . $articles . $footer;
    if (blog_rss_save_file($type, $id, $tagid, $rssdata)) {
        return $filename;
    } else {
        return false;
        // Couldn't find it or make it.
    }
}
Exemple #24
0
 /**
  * Permanently deletes all non-standard tags that no longer have any instances pointing to them
  *
  * @param array $collections optional list of tag collections ids to cleanup
  */
 public static function cleanup_unused_tags($collections = null)
 {
     global $DB, $CFG;
     $params = array();
     $sql = "SELECT tg.id FROM {tag} tg LEFT OUTER JOIN {tag_instance} ti ON ti.tagid = tg.id\n                WHERE ti.id IS NULL AND tg.isstandard = 0";
     if ($collections) {
         list($sqlcoll, $params) = $DB->get_in_or_equal($collections, SQL_PARAMS_NAMED);
         $sql .= " AND tg.tagcollid " . $sqlcoll;
     }
     if ($unusedtags = $DB->get_fieldset_sql($sql, $params)) {
         core_tag_tag::delete_tags($unusedtags);
     }
 }
Exemple #25
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');
     }
 }
 /**
  * Testing function course_get_tagged_course_modules - search tagged course modules
  */
 public function test_course_get_tagged_course_modules()
 {
     global $DB;
     $this->resetAfterTest();
     $course3 = $this->getDataGenerator()->create_course();
     $course2 = $this->getDataGenerator()->create_course();
     $course1 = $this->getDataGenerator()->create_course();
     $cm11 = $this->getDataGenerator()->create_module('assign', array('course' => $course1->id, 'tags' => 'Cat, Dog'));
     $cm12 = $this->getDataGenerator()->create_module('page', array('course' => $course1->id, 'tags' => 'Cat, Mouse', 'visible' => 0));
     $cm13 = $this->getDataGenerator()->create_module('page', array('course' => $course1->id, 'tags' => 'Cat, Mouse, Dog'));
     $cm21 = $this->getDataGenerator()->create_module('forum', array('course' => $course2->id, 'tags' => 'Cat, Mouse'));
     $cm31 = $this->getDataGenerator()->create_module('forum', array('course' => $course3->id, 'tags' => 'Cat, Mouse'));
     // Admin is able to view everything.
     $this->setAdminUser();
     $res = course_get_tagged_course_modules(core_tag_tag::get_by_name(0, 'Cat'), false, 0, 0, 1, 0);
     $this->assertRegExp('/' . $cm11->name . '/', $res->content);
     $this->assertRegExp('/' . $cm12->name . '/', $res->content);
     $this->assertRegExp('/' . $cm13->name . '/', $res->content);
     $this->assertRegExp('/' . $cm21->name . '/', $res->content);
     $this->assertRegExp('/' . $cm31->name . '/', $res->content);
     // Results from course1 are returned before results from course2.
     $this->assertTrue(strpos($res->content, $cm11->name) < strpos($res->content, $cm21->name));
     // Ordinary user is not able to see anything.
     $user = $this->getDataGenerator()->create_user();
     $this->setUser($user);
     $res = course_get_tagged_course_modules(core_tag_tag::get_by_name(0, 'Cat'), false, 0, 0, 1, 0);
     $this->assertNull($res);
     // Enrol user as student in course1 and course2.
     $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
     $this->getDataGenerator()->enrol_user($user->id, $course1->id, $roleids['student']);
     $this->getDataGenerator()->enrol_user($user->id, $course2->id, $roleids['student']);
     core_tag_index_builder::reset_caches();
     // Searching in the course context returns visible modules in this course.
     $context = context_course::instance($course1->id);
     $res = course_get_tagged_course_modules(core_tag_tag::get_by_name(0, 'Cat'), false, 0, $context->id, 1, 0);
     $this->assertRegExp('/' . $cm11->name . '/', $res->content);
     $this->assertNotRegExp('/' . $cm12->name . '/', $res->content);
     $this->assertRegExp('/' . $cm13->name . '/', $res->content);
     $this->assertNotRegExp('/' . $cm21->name . '/', $res->content);
     $this->assertNotRegExp('/' . $cm31->name . '/', $res->content);
     // Searching FROM the course context returns visible modules in all courses.
     $context = context_course::instance($course2->id);
     $res = course_get_tagged_course_modules(core_tag_tag::get_by_name(0, 'Cat'), false, $context->id, 0, 1, 0);
     $this->assertRegExp('/' . $cm11->name . '/', $res->content);
     $this->assertNotRegExp('/' . $cm12->name . '/', $res->content);
     $this->assertRegExp('/' . $cm13->name . '/', $res->content);
     $this->assertRegExp('/' . $cm21->name . '/', $res->content);
     $this->assertNotRegExp('/' . $cm31->name . '/', $res->content);
     // No access to course3.
     // Results from course2 are returned before results from course1.
     $this->assertTrue(strpos($res->content, $cm21->name) < strpos($res->content, $cm11->name));
     // Enrol user in course1 as a teacher - now he should be able to see hidden module.
     $this->getDataGenerator()->enrol_user($user->id, $course1->id, $roleids['editingteacher']);
     get_fast_modinfo(0, 0, true);
     $context = context_course::instance($course1->id);
     $res = course_get_tagged_course_modules(core_tag_tag::get_by_name(0, 'Cat'), false, $context->id, 0, 1, 0);
     $this->assertRegExp('/' . $cm12->name . '/', $res->content);
     // Create more modules and try pagination.
     $cm14 = $this->getDataGenerator()->create_module('assign', array('course' => $course1->id, 'tags' => 'Cat, Dog'));
     $cm15 = $this->getDataGenerator()->create_module('page', array('course' => $course1->id, 'tags' => 'Cat, Mouse', 'visible' => 0));
     $cm16 = $this->getDataGenerator()->create_module('page', array('course' => $course1->id, 'tags' => 'Cat, Mouse, Dog'));
     $context = context_course::instance($course1->id);
     $res = course_get_tagged_course_modules(core_tag_tag::get_by_name(0, 'Cat'), false, 0, $context->id, 1, 0);
     $this->assertRegExp('/' . $cm11->name . '/', $res->content);
     $this->assertRegExp('/' . $cm12->name . '/', $res->content);
     $this->assertRegExp('/' . $cm13->name . '/', $res->content);
     $this->assertNotRegExp('/' . $cm21->name . '/', $res->content);
     $this->assertRegExp('/' . $cm14->name . '/', $res->content);
     $this->assertRegExp('/' . $cm15->name . '/', $res->content);
     $this->assertNotRegExp('/' . $cm16->name . '/', $res->content);
     $this->assertNotRegExp('/' . $cm31->name . '/', $res->content);
     // No access to course3.
     $this->assertEmpty($res->prevpageurl);
     $this->assertNotEmpty($res->nextpageurl);
     $res = course_get_tagged_course_modules(core_tag_tag::get_by_name(0, 'Cat'), false, 0, $context->id, 1, 1);
     $this->assertNotRegExp('/' . $cm11->name . '/', $res->content);
     $this->assertNotRegExp('/' . $cm12->name . '/', $res->content);
     $this->assertNotRegExp('/' . $cm13->name . '/', $res->content);
     $this->assertNotRegExp('/' . $cm21->name . '/', $res->content);
     $this->assertNotRegExp('/' . $cm14->name . '/', $res->content);
     $this->assertNotRegExp('/' . $cm15->name . '/', $res->content);
     $this->assertRegExp('/' . $cm16->name . '/', $res->content);
     $this->assertNotRegExp('/' . $cm31->name . '/', $res->content);
     // No access to course3.
     $this->assertNotEmpty($res->prevpageurl);
     $this->assertEmpty($res->nextpageurl);
 }
 /**
  * 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();
 }
Exemple #28
0
function wiki_print_page_content($page, $context, $subwikiid)
{
    global $OUTPUT, $CFG;
    if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
        $content = wiki_refresh_cachedcontent($page);
        $page = $content['page'];
    }
    if (isset($content)) {
        $box = '';
        foreach ($content['sections'] as $s) {
            $box .= '<p>' . get_string('repeatedsection', 'wiki', $s) . '</p>';
        }
        if (!empty($box)) {
            echo $OUTPUT->box($box);
        }
    }
    $html = file_rewrite_pluginfile_urls($page->cachedcontent, 'pluginfile.php', $context->id, 'mod_wiki', 'attachments', $subwikiid);
    $html = format_text($html, FORMAT_MOODLE, array('overflowdiv' => true, 'allowid' => true));
    echo $OUTPUT->box($html);
    echo $OUTPUT->tag_list(core_tag_tag::get_item_tags('mod_wiki', 'wiki_pages', $page->id), null, 'wiki-tags');
    wiki_increment_pageviews($page);
}
    }
}
// Guest can not edit.
if (isguestuser()) {
    print_error('guestnoeditprofile');
}
// The user profile we are editing.
if (!($user = $DB->get_record('user', array('id' => $userid)))) {
    print_error('invaliduserid');
}
// Guest can not be edited.
if (isguestuser($user)) {
    print_error('guestnoeditprofile');
}
// User interests separated by commas.
$user->interests = core_tag_tag::get_item_tags_array('core', 'user', $user->id);
// Remote users cannot be edited. We have to perform the strict
// user_not_fully_set_up() check, otherwise the remote user could end up in
// endless loop between user/view.php and herein. Note that required custom
// fields are not supported in MNet environment anyway.
if (is_mnet_remote_user($user)) {
    if (user_not_fully_set_up($user, true)) {
        $hostwwwroot = $DB->get_field('mnet_host', 'wwwroot', array('id' => $user->mnethostid));
        print_error('usernotfullysetup', 'mnet', '', $hostwwwroot);
    }
    redirect($CFG->wwwroot . "/user/view.php?course={$course->id}");
}
// Load the appropriate auth plugin.
$userauth = get_auth_plugin($user->auth);
if (!$userauth->can_edit_profile()) {
    print_error('noprofileedit', 'auth');
Exemple #30
0
 /**
  * Handle showing/processing the submission from the block editing form.
  * @return boolean true if the form was submitted and the new config saved. Does not
  *      return if the editing form was displayed. False otherwise.
  */
 public function process_url_edit()
 {
     global $CFG, $DB, $PAGE, $OUTPUT;
     $blockid = optional_param('bui_editid', null, PARAM_INT);
     if (!$blockid) {
         return false;
     }
     require_sesskey();
     require_once $CFG->dirroot . '/blocks/edit_form.php';
     $block = $this->find_instance($blockid);
     if (!$block->user_can_edit() && !$this->page->user_can_edit_blocks()) {
         throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('editblock'));
     }
     $editpage = new moodle_page();
     $editpage->set_pagelayout('admin');
     $editpage->set_course($this->page->course);
     //$editpage->set_context($block->context);
     $editpage->set_context($this->page->context);
     if ($this->page->cm) {
         $editpage->set_cm($this->page->cm);
     }
     $editurlbase = str_replace($CFG->wwwroot . '/', '/', $this->page->url->out_omit_querystring());
     $editurlparams = $this->page->url->params();
     $editurlparams['bui_editid'] = $blockid;
     $editpage->set_url($editurlbase, $editurlparams);
     $editpage->set_block_actions_done();
     // At this point we are either going to redirect, or display the form, so
     // overwrite global $PAGE ready for this. (Formslib refers to it.)
     $PAGE = $editpage;
     //some functions like MoodleQuickForm::addHelpButton use $OUTPUT so we need to replace that to
     $output = $editpage->get_renderer('core');
     $OUTPUT = $output;
     $formfile = $CFG->dirroot . '/blocks/' . $block->name() . '/edit_form.php';
     if (is_readable($formfile)) {
         require_once $formfile;
         $classname = 'block_' . $block->name() . '_edit_form';
         if (!class_exists($classname)) {
             $classname = 'block_edit_form';
         }
     } else {
         $classname = 'block_edit_form';
     }
     $mform = new $classname($editpage->url, $block, $this->page);
     $mform->set_data($block->instance);
     if ($mform->is_cancelled()) {
         redirect($this->page->url);
     } else {
         if ($data = $mform->get_data()) {
             $bi = new stdClass();
             $bi->id = $block->instance->id;
             // This may get overwritten by the special case handling below.
             $bi->pagetypepattern = $data->bui_pagetypepattern;
             $bi->showinsubcontexts = (bool) $data->bui_contexts;
             if (empty($data->bui_subpagepattern) || $data->bui_subpagepattern == '%@NULL@%') {
                 $bi->subpagepattern = null;
             } else {
                 $bi->subpagepattern = $data->bui_subpagepattern;
             }
             $systemcontext = context_system::instance();
             $frontpagecontext = context_course::instance(SITEID);
             $parentcontext = context::instance_by_id($data->bui_parentcontextid);
             // Updating stickiness and contexts.  See MDL-21375 for details.
             if (has_capability('moodle/site:manageblocks', $parentcontext)) {
                 // Check permissions in destination
                 // Explicitly set the default context
                 $bi->parentcontextid = $parentcontext->id;
                 if ($data->bui_editingatfrontpage) {
                     // The block is being edited on the front page
                     // The interface here is a special case because the pagetype pattern is
                     // totally derived from the context menu.  Here are the excpetions.   MDL-30340
                     switch ($data->bui_contexts) {
                         case BUI_CONTEXTS_ENTIRE_SITE:
                             // The user wants to show the block across the entire site
                             $bi->parentcontextid = $systemcontext->id;
                             $bi->showinsubcontexts = true;
                             $bi->pagetypepattern = '*';
                             break;
                         case BUI_CONTEXTS_FRONTPAGE_SUBS:
                             // The user wants the block shown on the front page and all subcontexts
                             $bi->parentcontextid = $frontpagecontext->id;
                             $bi->showinsubcontexts = true;
                             $bi->pagetypepattern = '*';
                             break;
                         case BUI_CONTEXTS_FRONTPAGE_ONLY:
                             // The user want to show the front page on the frontpage only
                             $bi->parentcontextid = $frontpagecontext->id;
                             $bi->showinsubcontexts = false;
                             $bi->pagetypepattern = 'site-index';
                             // This is the only relevant page type anyway but we'll set it explicitly just
                             // in case the front page grows site-index-* subpages of its own later
                             break;
                     }
                 }
             }
             $bits = explode('-', $bi->pagetypepattern);
             // hacks for some contexts
             if ($parentcontext->contextlevel == CONTEXT_COURSE && $parentcontext->instanceid != SITEID) {
                 // For course context
                 // is page type pattern is mod-*, change showinsubcontext to 1
                 if ($bits[0] == 'mod' || $bi->pagetypepattern == '*') {
                     $bi->showinsubcontexts = 1;
                 } else {
                     $bi->showinsubcontexts = 0;
                 }
             } else {
                 if ($parentcontext->contextlevel == CONTEXT_USER) {
                     // for user context
                     // subpagepattern should be null
                     if ($bits[0] == 'user' or $bits[0] == 'my') {
                         // we don't need subpagepattern in usercontext
                         $bi->subpagepattern = null;
                     }
                 }
             }
             $bi->defaultregion = $data->bui_defaultregion;
             $bi->defaultweight = $data->bui_defaultweight;
             $DB->update_record('block_instances', $bi);
             if (!empty($block->config)) {
                 $config = clone $block->config;
             } else {
                 $config = new stdClass();
             }
             foreach ($data as $configfield => $value) {
                 if (strpos($configfield, 'config_') !== 0) {
                     continue;
                 }
                 $field = substr($configfield, 7);
                 $config->{$field} = $value;
             }
             $block->instance_config_save($config);
             $bp = new stdClass();
             $bp->visible = $data->bui_visible;
             $bp->region = $data->bui_region;
             $bp->weight = $data->bui_weight;
             $needbprecord = !$data->bui_visible || $data->bui_region != $data->bui_defaultregion || $data->bui_weight != $data->bui_defaultweight;
             if ($block->instance->blockpositionid && !$needbprecord) {
                 $DB->delete_records('block_positions', array('id' => $block->instance->blockpositionid));
             } else {
                 if ($block->instance->blockpositionid && $needbprecord) {
                     $bp->id = $block->instance->blockpositionid;
                     $DB->update_record('block_positions', $bp);
                 } else {
                     if ($needbprecord) {
                         $bp->blockinstanceid = $block->instance->id;
                         $bp->contextid = $this->page->context->id;
                         $bp->pagetype = $this->page->pagetype;
                         if ($this->page->subpage) {
                             $bp->subpage = $this->page->subpage;
                         } else {
                             $bp->subpage = '';
                         }
                         $DB->insert_record('block_positions', $bp);
                     }
                 }
             }
             redirect($this->page->url);
         } else {
             $strheading = get_string('blockconfiga', 'moodle', $block->get_title());
             $editpage->set_title($strheading);
             $editpage->set_heading($strheading);
             $bits = explode('-', $this->page->pagetype);
             if ($bits[0] == 'tag' && !empty($this->page->subpage)) {
                 // better navbar for tag pages
                 $editpage->navbar->add(get_string('tags'), new moodle_url('/tag/'));
                 $tag = core_tag_tag::get($this->page->subpage);
                 // tag search page doesn't have subpageid
                 if ($tag) {
                     $editpage->navbar->add($tag->get_display_name(), $tag->get_view_url());
                 }
             }
             $editpage->navbar->add($block->get_title());
             $editpage->navbar->add(get_string('configuration'));
             echo $output->header();
             echo $output->heading($strheading, 2);
             $mform->display();
             echo $output->footer();
             exit;
         }
     }
 }