/** * Export this data so it can be used as the context for a mustache template. * * @param renderer_base $output Renderer base. * @return stdClass */ public function export_for_template(renderer_base $output) { $related = array('context' => $this->framework->get_context(), 'framework' => $this->framework, 'linkedcourses' => $this->courses, 'relatedcompetencies' => $this->relatedcompetencies, 'competency' => $this->competency); $exporter = new competency_summary_exporter($this->competency, $related); $data = $exporter->export($output); return $data; }
/** * Convenience method to instantiate the event. * * @param competency_framework $framework The framework. * @return self */ public static final function create_from_framework(competency_framework $framework) { if (!$framework->get_id()) { throw new \coding_exception('The competency framework ID must be set.'); } $event = static::create(array('contextid' => $framework->get_contextid(), 'objectid' => $framework->get_id())); $event->add_record_snapshot(competency_framework::TABLE, $framework->to_record()); return $event; }
/** * Construct this renderable. * * @param \core_competency\competency_framework $framework Competency framework. * @param string $search Search string. * @param context $pagecontext The page context. */ public function __construct($framework, $search, $pagecontext) { $this->framework = $framework; $this->pagecontext = $pagecontext; $this->search = $search; $addpage = new single_button(new moodle_url('/admin/tool/lp/editcompetencyframework.php'), get_string('addnewcompetency', 'tool_lp')); $this->navigation[] = $addpage; $this->canmanage = has_capability('moodle/competency:competencymanage', $framework->get_context()); }
/** * This function extends the category navigation to add learning plan links. * * @param navigation_node $navigation The navigation node to extend * @param context $coursecategorycontext The context of the course category */ function tool_lp_extend_navigation_category_settings($navigation, $coursecategorycontext) { if (!get_config('core_competency', 'enabled')) { return false; } // We check permissions before renderring the links. $templatereadcapability = \core_competency\template::can_read_context($coursecategorycontext); $competencyreadcapability = \core_competency\competency_framework::can_read_context($coursecategorycontext); if (!$templatereadcapability && !$competencyreadcapability) { return false; } // The link to the learning plan page. if ($templatereadcapability) { $title = get_string('templates', 'tool_lp'); $path = new moodle_url("/admin/tool/lp/learningplans.php", array('pagecontextid' => $coursecategorycontext->id)); $settingsnode = navigation_node::create($title, $path, navigation_node::TYPE_SETTING, null, null, new pix_icon('i/competencies', '')); if (isset($settingsnode)) { $navigation->add_node($settingsnode); } } // The link to the competency frameworks page. if ($competencyreadcapability) { $title = get_string('competencyframeworks', 'tool_lp'); $path = new moodle_url("/admin/tool/lp/competencyframeworks.php", array('pagecontextid' => $coursecategorycontext->id)); $settingsnode = navigation_node::create($title, $path, navigation_node::TYPE_SETTING, null, null, new pix_icon('i/competencies', '')); if (isset($settingsnode)) { $navigation->add_node($settingsnode); } } }
/** * Construct this renderable. * * @param context $pagecontext The page context */ public function __construct(context $pagecontext) { $this->pagecontext = $pagecontext; if (competency_framework::can_manage_context($this->pagecontext)) { $addpage = new single_button(new moodle_url('/admin/tool/lp/editcompetencyframework.php', array('pagecontextid' => $this->pagecontext->id)), get_string('addnewcompetencyframework', 'tool_lp'), 'get'); $this->navigation[] = $addpage; } $this->competencyframeworks = api::list_frameworks('shortname', 'ASC', 0, 0, $this->pagecontext); }
public function test_create_framework() { $this->resetAfterTest(true); $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency'); $this->assertEquals(0, competency_framework::count_records()); $framework = $lpg->create_framework(); $framework = $lpg->create_framework(); $this->assertEquals(2, competency_framework::count_records()); $this->assertInstanceOf('\\core_competency\\competency_framework', $framework); }
public function test_delete_framework() { $this->resetAfterTest(true); $dg = $this->getDataGenerator(); $lpg = $dg->get_plugin_generator('core_competency'); $this->setAdminUser(); $u1 = $dg->create_user(); $f1 = $lpg->create_framework(); $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id())); $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id())); $c2id = $c2->get_id(); $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1->get_id())); $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1a->get_id())); $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1b->get_id())); $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1b->get_id())); // If we delete framework, the related competencies relations and evidences should be deleted. // Create related competencies using one of c1a competency descendants. $rc = $lpg->create_related_competency(array('competencyid' => $c2->get_id(), 'relatedcompetencyid' => $c11b->get_id())); $this->assertEquals($c11b->get_id(), $rc->get_relatedcompetencyid()); // Creating a standard evidence with minimal information. $uc2 = $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $c11b->get_id())); $evidence = $lpg->create_evidence(array('usercompetencyid' => $uc2->get_id())); $this->assertEquals($uc2->get_id(), $evidence->get_usercompetencyid()); $uc2->delete(); $this->assertTrue(api::delete_framework($f1->get_id())); $this->assertFalse(competency_framework::record_exists($f1->get_id())); // Check that all competencies were also deleted. $this->assertFalse(competency::record_exists($c1->get_id())); $this->assertFalse(competency::record_exists($c2->get_id())); $this->assertFalse(competency::record_exists($c1a->get_id())); $this->assertFalse(competency::record_exists($c1b->get_id())); $this->assertFalse(competency::record_exists($c11b->get_id())); $this->assertFalse(competency::record_exists($c12b->get_id())); // Check if evidence are also deleted. $this->assertEquals(0, \core_competency\user_evidence_competency::count_records(array('competencyid' => $c11b->get_id()))); // Check if related conpetency relation is deleted. $this->assertEquals(0, count(\core_competency\related_competency::get_multiple_relations(array($c2id)))); // Delete a simple framework. $f2 = $lpg->create_framework(); $this->assertTrue(api::delete_framework($f2->get_id())); $this->assertFalse(competency_framework::record_exists($f2->get_id())); }
/** * Process a course module competency. * * @param array $data The data. */ public function process_course_module_competency($data) { $data = (object) $data; // Mapping the competency by ID numbers. $framework = \core_competency\competency_framework::get_record(array('idnumber' => $data->frameworkidnumber)); if (!$framework) { return; } $competency = \core_competency\competency::get_record(array('idnumber' => $data->idnumber, 'competencyframeworkid' => $framework->get_id())); if (!$competency) { return; } $params = array('competencyid' => $competency->get_id(), 'cmid' => $this->task->get_moduleid()); $query = 'competencyid = :competencyid AND cmid = :cmid'; $existing = \core_competency\course_module_competency::record_exists_select($query, $params); if (!$existing) { // Sortorder is ignored by precaution, anyway we should walk through the records in the right order. $record = (object) $params; $record->ruleoutcome = $data->ruleoutcome; $coursemodulecompetency = new \core_competency\course_module_competency(0, $record); $coursemodulecompetency->create(); } }
/** * Perform a search based on the provided filters and return a paginated list of records. * * Requires moodle/competency:competencyview capability at the system context. * * @param context $context The parent context of the frameworks. * @param string $includes Defines what other contexts to fetch frameworks from. * Accepted values are: * - children: All descendants * - parents: All parents, grand parents, etc... * - self: Context passed only. * @return int */ public static function count_frameworks($context, $includes) { global $DB; static::require_enabled(); // Get all the relevant contexts. $contexts = self::get_related_contexts($context, $includes, array('moodle/competency:competencyview', 'moodle/competency:competencymanage')); if (empty($contexts)) { throw new required_capability_exception($context, 'moodle/competency:competencyview', 'nopermissions', ''); } // OK - all set. list($insql, $inparams) = $DB->get_in_or_equal(array_keys($contexts), SQL_PARAMS_NAMED); return competency_framework::count_records_select("contextid {$insql}", $inparams); }
/** * Create a new framework. * * @param array|stdClass $record * @return competency_framework */ public function create_framework($record = null) { $generator = phpunit_util::get_data_generator(); $this->frameworkcount++; $i = $this->frameworkcount; $record = (object) $record; if (!isset($record->shortname)) { $record->shortname = "Framework shortname {$i}"; } if (!isset($record->idnumber)) { $record->idnumber = "frm{$i}"; } if (!isset($record->description)) { $record->description = "Framework {$i} description "; } if (!isset($record->descriptionformat)) { $record->descriptionformat = FORMAT_HTML; } if (!isset($record->visible)) { $record->visible = 1; } if (!isset($record->scaleid)) { if (isset($record->scaleconfiguration)) { throw new coding_exception('Scale configuration must be provided with a scale.'); } if (!$this->scale) { $this->scale = $generator->create_scale(array('scale' => 'A,B,C,D')); } $record->scaleid = $this->scale->id; } if (!isset($record->scaleconfiguration)) { $scale = grade_scale::fetch(array('id' => $record->scaleid)); $values = $scale->load_items(); foreach ($values as $key => $value) { // Add a key (make the first value 1). $values[$key] = array('id' => $key + 1, 'name' => $value); } if (count($values) < 2) { throw new coding_exception('Please provide the scale configuration for one-item scales.'); } $scaleconfig = array(); // Last item is proficient. $item = array_pop($values); array_unshift($scaleconfig, array('id' => $item['id'], 'proficient' => 1)); // Second-last item is default and proficient. $item = array_pop($values); array_unshift($scaleconfig, array('id' => $item['id'], 'scaledefault' => 1, 'proficient' => 1)); array_unshift($scaleconfig, array('scaleid' => $record->scaleid)); $record->scaleconfiguration = json_encode($scaleconfig); } if (is_array($record->scaleconfiguration) || is_object($record->scaleconfiguration)) { // Conveniently encode the config. $record->scaleconfiguration = json_encode($record->scaleconfiguration); } if (!isset($record->contextid)) { $record->contextid = context_system::instance()->id; } $framework = new competency_framework(0, $record); $framework->create(); return $framework; }
/** * Set-up a competency page. * * Example: * list($title, $subtitle) = page_helper::setup_for_competency($pagecontextid, $url, $competency, $pagetitle); * echo $OUTPUT->heading($title); * echo $OUTPUT->heading($subtitle, 3); * * @param int $pagecontextid The page context ID. * @param moodle_url $url The current page. * @param \core_competency\competency_framework $framework The competency framework. * @param \core_competency\competency $competency The competency, if any. * @param \core_competency\competency $parent The parent competency, if any. * @return array With the following: * - Page title * - Page sub title * - Return URL (main competencies page) * @throws coding_exception */ public static function setup_for_competency($pagecontextid, moodle_url $url, $framework, $competency = null, $parent = null) { global $PAGE, $SITE; // Set page context. $pagecontext = context::instance_by_id($pagecontextid); $PAGE->set_context($pagecontext); // Set page heading. if ($pagecontext->contextlevel == CONTEXT_SYSTEM) { $heading = $SITE->fullname; } else { if ($pagecontext->contextlevel == CONTEXT_COURSECAT) { $heading = $pagecontext->get_context_name(); } else { throw new coding_exception('Unexpected context!'); } } $PAGE->set_heading($heading); // Set override active url. $frameworksurl = new moodle_url('/admin/tool/lp/competencyframeworks.php', ['pagecontextid' => $pagecontextid]); $PAGE->navigation->override_active_url($frameworksurl); // Set return url. $returnurloptions = ['competencyframeworkid' => $framework->get_id(), 'pagecontextid' => $pagecontextid]; $returnurl = new moodle_url('/admin/tool/lp/competencies.php', $returnurloptions); $PAGE->navbar->add($framework->get_shortname(), $returnurl); // Set page layout. $PAGE->set_pagelayout('admin'); if (empty($competency)) { // Add mode. $title = format_string($framework->get_shortname(), true, ['context' => $pagecontext]); // Set the sub-title for add mode. $level = $parent ? $parent->get_level() + 1 : 1; $subtitle = get_string('taxonomy_add_' . $framework->get_taxonomy($level), 'tool_lp'); } else { // Edit mode. $title = format_string($competency->get_shortname(), true, ['context' => $competency->get_context()]); // Add competency name to breadcrumbs, if available. $PAGE->navbar->add($title); // Set the sub-title for edit mode. $subtitle = get_string('taxonomy_edit_' . $framework->get_taxonomy($competency->get_level()), 'tool_lp'); } // Set page title. $PAGE->set_title($title); // Set page url. $PAGE->set_url($url); // Add editing mode link to breadcrumbs, if available. if (!empty($subtitle)) { $PAGE->navbar->add($subtitle, $url); } return [$title, $subtitle, $returnurl]; }
protected function get_other_values(renderer_base $output) { $result = new stdClass(); $context = $this->related['context']; $courses = $this->related['linkedcourses']; $linkedcourses = array(); foreach ($courses as $course) { $context = context_course::instance($course->id); $exporter = new course_summary_exporter($course, array('context' => $context)); $courseexport = $exporter->export($output); array_push($linkedcourses, $courseexport); } $result->linkedcourses = $linkedcourses; $result->hascourses = count($linkedcourses) > 0; $relatedcompetencies = array(); foreach ($this->related['relatedcompetencies'] as $competency) { $exporter = new competency_exporter($competency, array('context' => $context)); $competencyexport = $exporter->export($output); array_push($relatedcompetencies, $competencyexport); } $result->relatedcompetencies = $relatedcompetencies; $result->hasrelatedcompetencies = count($relatedcompetencies) > 0; $competency = $this->related['competency']; $exporter = new competency_exporter($competency, array('context' => $context)); $result->competency = $exporter->export($output); $exporter = new competency_framework_exporter($this->related['framework']); $result->framework = $exporter->export($output); $scaleconfiguration = $this->related['framework']->get_scaleconfiguration(); $scaleid = $this->related['framework']->get_scaleid(); if ($competency->get_scaleid()) { $scaleconfiguration = $competency->get_scaleconfiguration(); $scaleid = $competency->get_scaleid(); } $result->scaleconfiguration = $scaleconfiguration; $result->scaleid = $scaleid; $level = $competency->get_level(); $taxonomy = $this->related['framework']->get_taxonomy($level); $result->taxonomyterm = (string) competency_framework::get_taxonomies_list()[$taxonomy]; // Competency path. $exporter = new competency_path_exporter(['ancestors' => $competency->get_ancestors(), 'framework' => $this->related['framework'], 'context' => $context]); $result->comppath = $exporter->export($output); return (array) $result; }
/** * Validate the competency framework ID. * * @param int $value The framework ID. * @return true|lang_string */ protected function validate_competencyframeworkid($value) { // During update. if ($this->get_id()) { // Ensure that we are not trying to move the competency across frameworks. if ($this->beforeupdate->get_competencyframeworkid() != $value) { return new lang_string('invaliddata', 'error'); } } else { // During create. // Check that the framework exists. if (!competency_framework::record_exists($value)) { return new lang_string('invaliddata', 'error'); } } return true; }
/** * Define the form - called by parent constructor */ public function definition() { global $PAGE; $mform = $this->_form; $context = $this->_customdata['context']; $framework = $this->get_persistent(); $mform->addElement('hidden', 'contextid'); $mform->setType('contextid', PARAM_INT); $mform->setConstant('contextid', $context->id); $mform->addElement('header', 'generalhdr', get_string('general')); // Name. $mform->addElement('text', 'shortname', get_string('shortname', 'tool_lp'), 'maxlength="100"'); $mform->setType('shortname', PARAM_TEXT); $mform->addRule('shortname', null, 'required', null, 'client'); $mform->addRule('shortname', get_string('maximumchars', '', 100), 'maxlength', 100, 'client'); // Description. $mform->addElement('editor', 'description', get_string('description', 'tool_lp'), array('rows' => 4)); $mform->setType('description', PARAM_RAW); // ID number. $mform->addElement('text', 'idnumber', get_string('idnumber', 'tool_lp'), 'maxlength="100"'); $mform->setType('idnumber', PARAM_RAW); $mform->addRule('idnumber', null, 'required', null, 'client'); $mform->addRule('idnumber', get_string('maximumchars', '', 100), 'maxlength', 100, 'client'); $scales = get_scales_menu(); $scaleid = $mform->addElement('select', 'scaleid', get_string('scale', 'tool_lp'), $scales); $mform->setType('scaleid', PARAM_INT); $mform->addHelpButton('scaleid', 'scale', 'tool_lp'); $mform->addRule('scaleid', null, 'required', null, 'client'); if ($framework && $framework->has_user_competencies()) { // The scale is used so we "freeze" the element. Though, the javascript code for the scale // configuration requires this field so we only disable it. It is fine as setting the value // as a constant will ensure that nobody can change it. And it's validated in the persistent anyway. $scaleid->updateAttributes(array('readonly' => 'readonly')); $mform->setConstant('scaleid', $framework->get_scaleid()); } $mform->addElement('button', 'scaleconfigbutton', get_string('configurescale', 'tool_lp')); // Add js. $mform->addElement('hidden', 'scaleconfiguration', '', array('id' => 'tool_lp_scaleconfiguration')); $mform->setType('scaleconfiguration', PARAM_RAW); $PAGE->requires->js_call_amd('tool_lp/scaleconfig', 'init', array('#id_scaleid', '#tool_lp_scaleconfiguration', '#id_scaleconfigbutton')); $mform->addElement('selectyesno', 'visible', get_string('visible', 'tool_lp')); $mform->setDefault('visible', true); $mform->addHelpButton('visible', 'visible', 'tool_lp'); $mform->addElement('static', 'context', get_string('category', 'tool_lp')); $mform->setDefault('context', $context->get_context_name(false)); $mform->addElement('header', 'taxonomyhdr', get_string('taxonomies', 'tool_lp')); $taxonomies = \core_competency\competency_framework::get_taxonomies_list(); $taxdefaults = array(); $taxcount = max($framework ? $framework->get_depth() : 4, 4); for ($i = 1; $i <= $taxcount; $i++) { $mform->addElement('select', "taxonomies[{$i}]", get_string('levela', 'tool_lp', $i), $taxonomies); $taxdefaults[$i] = \core_competency\competency_framework::TAXONOMY_COMPETENCY; } // Not using taxonomies[n] here or it would takes precedence over set_data(array('taxonomies' => ...)). $mform->setDefault('taxonomies', $taxdefaults); $this->add_action_buttons(true, get_string('savechanges', 'tool_lp')); }
/** * Adapt creating competency from framework idnumber or frameworkid. * * @param array $data * @return array */ protected function preprocess_competency($data) { if (isset($data['framework'])) { $framework = competency_framework::get_record(array('idnumber' => $data['framework'])); if ($framework) { $data['competencyframeworkid'] = $framework->get_id(); } else { $framework = competency_framework::get_record(array('id' => $data['framework'])); if ($framework) { $data['competencyframeworkid'] = $framework->get_id(); } else { throw new Exception('Could not resolve framework with idnumber or id : "' . $data['category'] . '"'); } } } unset($data['framework']); return $data; }
/** * Set the value of this element. * * @param string|array $value The value to set. * @return boolean */ public function setValue($value) { global $DB; $values = (array) $value; $ids = array(); foreach ($values as $onevalue) { if (!$this->optionExists($onevalue) && $onevalue !== '_qf__force_multiselect_submission') { array_push($ids, $onevalue); } } if (empty($ids)) { return $this->setSelected(array()); } // Logic here is simulating API. $toselect = array(); list($insql, $inparams) = $DB->get_in_or_equal($ids, SQL_PARAMS_NAMED, 'param'); $frameworks = competency_framework::get_records_select("id {$insql}", $inparams, 'shortname'); foreach ($frameworks as $framework) { if (!has_any_capability(array('moodle/competency:competencyview', 'moodle/competency:competencymanage'), $framework->get_context())) { continue; } else { if ($this->onlyvisible && !$framework->get_visible()) { continue; } } $this->addOption($framework->get_shortname() . ' ' . $framework->get_idnumber(), $framework->get_id()); array_push($toselect, $framework->get_id()); } return $this->setSelected($toselect); }
* @package tool_lp * @copyright 2015 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once __DIR__ . '/../../../config.php'; require_once $CFG->libdir . '/adminlib.php'; $id = required_param('competencyframeworkid', PARAM_INT); $pagecontextid = required_param('pagecontextid', PARAM_INT); // Reference to the context we came from. $search = optional_param('search', '', PARAM_RAW); require_login(); \core_competency\api::require_enabled(); $pagecontext = context::instance_by_id($pagecontextid); $framework = \core_competency\api::read_framework($id); $context = $framework->get_context(); if (!\core_competency\competency_framework::can_read_context($context)) { throw new required_capability_exception($context, 'moodle/competency:competencyview', 'nopermissions', ''); } $title = get_string('competencies', 'core_competency'); $pagetitle = get_string('competenciesforframework', 'tool_lp', $framework->get_shortname()); // Set up the page. $url = new moodle_url("/admin/tool/lp/competencies.php", array('competencyframeworkid' => $framework->get_id(), 'pagecontextid' => $pagecontextid)); $frameworksurl = new moodle_url('/admin/tool/lp/competencyframeworks.php', array('pagecontextid' => $pagecontextid)); $PAGE->navigation->override_active_url($frameworksurl); $PAGE->set_context($pagecontext); $PAGE->set_pagelayout('admin'); $PAGE->set_url($url); $PAGE->navbar->add($framework->get_shortname(), $url); $PAGE->set_title($title); $PAGE->set_heading($title); $output = $PAGE->get_renderer('tool_lp');