/** * Returns array of relevant context capability records. * * @return array */ public function get_capabilities() { global $DB, $CFG; $sort = 'ORDER BY contextlevel,component,name'; // To group them sensibly for display $cm = $DB->get_record('course_modules', array('id'=>$this->_instanceid)); $module = $DB->get_record('modules', array('id'=>$cm->module)); $subcaps = array(); $subpluginsfile = "$CFG->dirroot/mod/$module->name/db/subplugins.php"; if (file_exists($subpluginsfile)) { $subplugins = array(); // should be redefined in the file include($subpluginsfile); if (!empty($subplugins)) { foreach (array_keys($subplugins) as $subplugintype) { foreach (array_keys(core_component::get_plugin_list($subplugintype)) as $subpluginname) { $subcaps = array_merge($subcaps, array_keys(load_capability_def($subplugintype.'_'.$subpluginname))); } } } } $modfile = "$CFG->dirroot/mod/$module->name/lib.php"; $extracaps = array(); if (file_exists($modfile)) { include_once($modfile); $modfunction = $module->name.'_get_extra_capabilities'; if (function_exists($modfunction)) { $extracaps = $modfunction(); } } $extracaps = array_merge($subcaps, $extracaps); $extra = ''; list($extra, $params) = $DB->get_in_or_equal( $extracaps, SQL_PARAMS_NAMED, 'cap0', true, ''); if (!empty($extra)) { $extra = "OR name $extra"; } $sql = "SELECT * FROM {capabilities} WHERE (contextlevel = ".CONTEXT_MODULE." AND (component = :component OR component = 'moodle')) $extra"; $params['component'] = "mod_$module->name"; return $DB->get_records_sql($sql.' '.$sort, $params); }
/** * Returns array of relevant context capability records. * * @return array */ public function get_capabilities() { global $DB, $CFG; $sort = 'ORDER BY contextlevel,component,name'; // To group them sensibly for display $cm = $DB->get_record('course_modules', array('id' => $this->_instanceid)); $module = $DB->get_record('modules', array('id' => $cm->module)); $subcaps = array(); $subpluginsfile = "{$CFG->dirroot}/mod/{$module->name}/db/subplugins.php"; if (file_exists($subpluginsfile)) { $subplugins = array(); // should be redefined in the file include $subpluginsfile; if (!empty($subplugins)) { foreach (array_keys($subplugins) as $subplugintype) { foreach (array_keys(get_plugin_list($subplugintype)) as $subpluginname) { $subcaps = array_merge($subcaps, array_keys(load_capability_def($subplugintype . '_' . $subpluginname))); } } } } $modfile = "{$CFG->dirroot}/mod/{$module->name}/lib.php"; if (file_exists($modfile)) { include_once $modfile; $modfunction = $module->name . '_get_extra_capabilities'; if (function_exists($modfunction)) { $extracaps = $modfunction(); } } if (empty($extracaps)) { $extracaps = array(); } $extracaps = array_merge($subcaps, $extracaps); // All modules allow viewhiddenactivities. This is so you can hide // the module then override to allow specific roles to see it. // The actual check is in course page so not module-specific $extracaps[] = "moodle/course:viewhiddenactivities"; list($extra, $params) = $DB->get_in_or_equal($extracaps, SQL_PARAMS_NAMED, 'cap0'); $extra = "OR name {$extra}"; $sql = "SELECT *\n FROM {capabilities}\n WHERE (contextlevel = " . CONTEXT_MODULE . "\n AND component = :component)\n {$extra}"; $params['component'] = "mod_{$module->name}"; return $DB->get_records_sql($sql . ' ' . $sort, $params); }
/** * Updates the capabilities table with the component capability definitions. * If no parameters are given, the function updates the core moodle * capabilities. * * Note that the absence of the db/access.php capabilities definition file * will cause any stored capabilities for the component to be removed from * the database. * * @param $component - examples: 'moodle', 'mod/forum', 'block/quiz_results' * @return boolean true if success, exception in case of any problems */ function update_capabilities($component = 'moodle') { global $DB; $storedcaps = array(); $filecaps = load_capability_def($component); $cachedcaps = get_cached_capabilities($component); if ($cachedcaps) { foreach ($cachedcaps as $cachedcap) { array_push($storedcaps, $cachedcap->name); // update risk bitmasks and context levels in existing capabilities if needed if (array_key_exists($cachedcap->name, $filecaps)) { if (!array_key_exists('riskbitmask', $filecaps[$cachedcap->name])) { $filecaps[$cachedcap->name]['riskbitmask'] = 0; // no risk if not specified } if ($cachedcap->riskbitmask != $filecaps[$cachedcap->name]['riskbitmask']) { $updatecap = new object(); $updatecap->id = $cachedcap->id; $updatecap->riskbitmask = $filecaps[$cachedcap->name]['riskbitmask']; $DB->update_record('capabilities', $updatecap); } if (!array_key_exists('contextlevel', $filecaps[$cachedcap->name])) { $filecaps[$cachedcap->name]['contextlevel'] = 0; // no context level defined } if ($cachedcap->contextlevel != $filecaps[$cachedcap->name]['contextlevel']) { $updatecap = new object(); $updatecap->id = $cachedcap->id; $updatecap->contextlevel = $filecaps[$cachedcap->name]['contextlevel']; $DB->update_record('capabilities', $updatecap); } } } } // Are there new capabilities in the file definition? $newcaps = array(); foreach ($filecaps as $filecap => $def) { if (!$storedcaps || $storedcaps && in_array($filecap, $storedcaps) === false) { if (!array_key_exists('riskbitmask', $def)) { $def['riskbitmask'] = 0; // no risk if not specified } $newcaps[$filecap] = $def; } } // Add new capabilities to the stored definition. foreach ($newcaps as $capname => $capdef) { $capability = new object(); $capability->name = $capname; $capability->captype = $capdef['captype']; $capability->contextlevel = $capdef['contextlevel']; $capability->component = $component; $capability->riskbitmask = $capdef['riskbitmask']; $DB->insert_record('capabilities', $capability, false); if (isset($capdef['clonepermissionsfrom']) && in_array($capdef['clonepermissionsfrom'], $storedcaps)) { if ($rolecapabilities = $DB->get_records('role_capabilities', array('capability' => $capdef['clonepermissionsfrom']))) { foreach ($rolecapabilities as $rolecapability) { //assign_capability will update rather than insert if capability exists if (!assign_capability($capname, $rolecapability->permission, $rolecapability->roleid, $rolecapability->contextid, true)) { notify('Could not clone capabilities for ' . $capname); } } } // Do we need to assign the new capabilities to roles that have the // legacy capabilities moodle/legacy:* as well? // we ignore legacy key if we have cloned permissions } else { if (isset($capdef['legacy']) && is_array($capdef['legacy']) && !assign_legacy_capabilities($capname, $capdef['legacy'])) { notify('Could not assign legacy capabilities for ' . $capname); } } } // Are there any capabilities that have been removed from the file // definition that we need to delete from the stored capabilities and // role assignments? capabilities_cleanup($component, $filecaps); // reset static caches is_valid_capability('reset', false); return true; }
/** * Extracts the relevant capabilities given a contextid. * All case based, example an instance of forum context. * Will fetch all forum related capabilities, while course contexts * Will fetch all capabilities * * capabilities * `name` varchar(150) NOT NULL, * `captype` varchar(50) NOT NULL, * `contextlevel` int(10) NOT NULL, * `component` varchar(100) NOT NULL, * * @param object context * @return array */ function fetch_context_capabilities($context) { global $DB, $CFG; $sort = 'ORDER BY contextlevel,component,name'; // To group them sensibly for display $params = array(); switch ($context->contextlevel) { case CONTEXT_SYSTEM: // all $SQL = "SELECT *\n FROM {capabilities}"; break; case CONTEXT_USER: $extracaps = array('moodle/grade:viewall'); list($extra, $params) = $DB->get_in_or_equal($extracaps, SQL_PARAMS_NAMED, 'cap'); $SQL = "SELECT *\n FROM {capabilities}\n WHERE contextlevel = " . CONTEXT_USER . "\n OR name {$extra}"; break; case CONTEXT_COURSECAT: // course category context and bellow $SQL = "SELECT *\n FROM {capabilities}\n WHERE contextlevel IN (" . CONTEXT_COURSECAT . "," . CONTEXT_COURSE . "," . CONTEXT_MODULE . "," . CONTEXT_BLOCK . ")"; break; case CONTEXT_COURSE: // course context and bellow $SQL = "SELECT *\n FROM {capabilities}\n WHERE contextlevel IN (" . CONTEXT_COURSE . "," . CONTEXT_MODULE . "," . CONTEXT_BLOCK . ")"; break; case CONTEXT_MODULE: // mod caps $cm = $DB->get_record('course_modules', array('id' => $context->instanceid)); $module = $DB->get_record('modules', array('id' => $cm->module)); $subcaps = array(); $subpluginsfile = "{$CFG->dirroot}/mod/{$module->name}/db/subplugins.php"; if (file_exists($subpluginsfile)) { $subplugins = array(); // should be redefined in the file include $subpluginsfile; if (!empty($subplugins)) { foreach (array_keys($subplugins) as $subplugintype) { foreach (array_keys(get_plugin_list($subplugintype)) as $subpluginname) { $subcaps = array_merge($subcaps, array_keys(load_capability_def($subplugintype . '_' . $subpluginname))); } } } } $modfile = "{$CFG->dirroot}/mod/{$module->name}/lib.php"; if (file_exists($modfile)) { include_once $modfile; $modfunction = $module->name . '_get_extra_capabilities'; if (function_exists($modfunction)) { $extracaps = $modfunction(); } } if (empty($extracaps)) { $extracaps = array(); } $extracaps = array_merge($subcaps, $extracaps); // All modules allow viewhiddenactivities. This is so you can hide // the module then override to allow specific roles to see it. // The actual check is in course page so not module-specific $extracaps[] = "moodle/course:viewhiddenactivities"; list($extra, $params) = $DB->get_in_or_equal($extracaps, SQL_PARAMS_NAMED, 'cap0'); $extra = "OR name {$extra}"; $SQL = "SELECT *\n FROM {capabilities}\n WHERE (contextlevel = " . CONTEXT_MODULE . "\n AND component = :component)\n {$extra}"; $params['component'] = "mod_{$module->name}"; break; case CONTEXT_BLOCK: // block caps $bi = $DB->get_record('block_instances', array('id' => $context->instanceid)); $extra = ''; $extracaps = block_method_result($bi->blockname, 'get_extra_capabilities'); if ($extracaps) { list($extra, $params) = $DB->get_in_or_equal($extracaps, SQL_PARAMS_NAMED, 'cap'); $extra = "OR name {$extra}"; } $SQL = "SELECT *\n FROM {capabilities}\n WHERE (contextlevel = " . CONTEXT_BLOCK . "\n AND component = :component)\n {$extra}"; $params['component'] = 'block_' . $bi->blockname; break; default: return false; } if (!($records = $DB->get_records_sql($SQL . ' ' . $sort, $params))) { $records = array(); } return $records; }
/** * Makes sure that we can still call the Moodle API method * load_capability_def() when plugin is installed (see CONTRIB-5561). */ public function test_load_capability_def() { // Calling this twice will invoke a fatal error before CONTRIB-5561 is // patched. load_capability_def('mod_dataform'); load_capability_def('mod_dataform'); }
/** * Updates the capabilities table with the component capability definitions. * If no parameters are given, the function updates the core moodle * capabilities. * * Note that the absence of the db/access.php capabilities definition file * will cause any stored capabilities for the component to be removed from * the database. * * @param string $component examples: 'moodle', 'mod/forum', 'block/quiz_results' * @return boolean true if success, exception in case of any problems */ function update_capabilities($component = 'moodle') { global $DB, $OUTPUT, $ACCESSLIB_PRIVATE; $storedcaps = array(); $filecaps = load_capability_def($component); $cachedcaps = get_cached_capabilities($component); if ($cachedcaps) { foreach ($cachedcaps as $cachedcap) { array_push($storedcaps, $cachedcap->name); // update risk bitmasks and context levels in existing capabilities if needed if (array_key_exists($cachedcap->name, $filecaps)) { if (!array_key_exists('riskbitmask', $filecaps[$cachedcap->name])) { $filecaps[$cachedcap->name]['riskbitmask'] = 0; // no risk if not specified } if ($cachedcap->captype != $filecaps[$cachedcap->name]['captype']) { $updatecap = new stdClass(); $updatecap->id = $cachedcap->id; $updatecap->captype = $filecaps[$cachedcap->name]['captype']; $DB->update_record('capabilities', $updatecap); } if ($cachedcap->riskbitmask != $filecaps[$cachedcap->name]['riskbitmask']) { $updatecap = new stdClass(); $updatecap->id = $cachedcap->id; $updatecap->riskbitmask = $filecaps[$cachedcap->name]['riskbitmask']; $DB->update_record('capabilities', $updatecap); } if (!array_key_exists('contextlevel', $filecaps[$cachedcap->name])) { $filecaps[$cachedcap->name]['contextlevel'] = 0; // no context level defined } if ($cachedcap->contextlevel != $filecaps[$cachedcap->name]['contextlevel']) { $updatecap = new stdClass(); $updatecap->id = $cachedcap->id; $updatecap->contextlevel = $filecaps[$cachedcap->name]['contextlevel']; $DB->update_record('capabilities', $updatecap); } } } } // Are there new capabilities in the file definition? $newcaps = array(); foreach ($filecaps as $filecap => $def) { if (!$storedcaps || $storedcaps && in_array($filecap, $storedcaps) === false) { if (!array_key_exists('riskbitmask', $def)) { $def['riskbitmask'] = 0; // no risk if not specified } $newcaps[$filecap] = $def; } } // Add new capabilities to the stored definition. foreach ($newcaps as $capname => $capdef) { $capability = new stdClass(); $capability->name = $capname; $capability->captype = $capdef['captype']; $capability->contextlevel = $capdef['contextlevel']; $capability->component = $component; $capability->riskbitmask = $capdef['riskbitmask']; $DB->insert_record('capabilities', $capability, false); if (isset($capdef['clonepermissionsfrom']) && in_array($capdef['clonepermissionsfrom'], $storedcaps)) { if ($rolecapabilities = $DB->get_records('role_capabilities', array('capability' => $capdef['clonepermissionsfrom']))) { foreach ($rolecapabilities as $rolecapability) { //assign_capability will update rather than insert if capability exists if (!assign_capability($capname, $rolecapability->permission, $rolecapability->roleid, $rolecapability->contextid, true)) { echo $OUTPUT->notification('Could not clone capabilities for ' . $capname); } } } // we ignore archetype key if we have cloned permissions } else { if (isset($capdef['archetypes']) && is_array($capdef['archetypes'])) { assign_legacy_capabilities($capname, $capdef['archetypes']); // 'legacy' is for backward compatibility with 1.9 access.php } else { if (isset($capdef['legacy']) && is_array($capdef['legacy'])) { assign_legacy_capabilities($capname, $capdef['legacy']); } } } } // Are there any capabilities that have been removed from the file // definition that we need to delete from the stored capabilities and // role assignments? capabilities_cleanup($component, $filecaps); // reset static caches $ACCESSLIB_PRIVATE->capabilities = null; return true; }
/** * Updates the capabilities table with the component capability definitions. * If no parameters are given, the function updates the core moodle * capabilities. * * Note that the absence of the db/access.php capabilities definition file * will cause any stored capabilities for the component to be removed from * the database. * * @param $component - examples: 'moodle', 'mod/forum', 'block/quiz_results' * @return boolean */ function update_capabilities($component = 'moodle') { $storedcaps = array(); $filecaps = load_capability_def($component); $cachedcaps = get_cached_capabilities($component); if ($cachedcaps) { foreach ($cachedcaps as $cachedcap) { array_push($storedcaps, $cachedcap->name); // update risk bitmasks and context levels in existing capabilities if needed if (array_key_exists($cachedcap->name, $filecaps)) { if (!array_key_exists('riskbitmask', $filecaps[$cachedcap->name])) { $filecaps[$cachedcap->name]['riskbitmask'] = 0; // no risk if not specified } if ($cachedcap->riskbitmask != $filecaps[$cachedcap->name]['riskbitmask']) { $updatecap = new object(); $updatecap->id = $cachedcap->id; $updatecap->riskbitmask = $filecaps[$cachedcap->name]['riskbitmask']; if (!update_record('capabilities', $updatecap)) { return false; } } if (!array_key_exists('contextlevel', $filecaps[$cachedcap->name])) { $filecaps[$cachedcap->name]['contextlevel'] = 0; // no context level defined } if ($cachedcap->contextlevel != $filecaps[$cachedcap->name]['contextlevel']) { $updatecap = new object(); $updatecap->id = $cachedcap->id; $updatecap->contextlevel = $filecaps[$cachedcap->name]['contextlevel']; if (!update_record('capabilities', $updatecap)) { return false; } } } } } // Are there new capabilities in the file definition? $newcaps = array(); foreach ($filecaps as $filecap => $def) { if (!$storedcaps || $storedcaps && in_array($filecap, $storedcaps) === false) { if (!array_key_exists('riskbitmask', $def)) { $def['riskbitmask'] = 0; // no risk if not specified } $newcaps[$filecap] = $def; } } // Add new capabilities to the stored definition. foreach ($newcaps as $capname => $capdef) { $capability = new object(); $capability->name = $capname; $capability->captype = $capdef['captype']; $capability->contextlevel = $capdef['contextlevel']; $capability->component = $component; $capability->riskbitmask = $capdef['riskbitmask']; if (!insert_record('capabilities', $capability, false, 'id')) { return false; } // Do we need to assign the new capabilities to roles that have the // legacy capabilities moodle/legacy:* as well? if (isset($capdef['legacy']) && is_array($capdef['legacy']) && !assign_legacy_capabilities($capname, $capdef['legacy'])) { notify('Could not assign legacy capabilities for ' . $capname); } } // Are there any capabilities that have been removed from the file // definition that we need to delete from the stored capabilities and // role assignments? capabilities_cleanup($component, $filecaps); return true; }