/** * Do not instantinate this directly, use {@link grading_manager::get_controller()} * * @param stdClass $context the context of the form * @param string $component the frankenstyle name of the component * @param string $area the name of the gradable area * @param int $areaid the id of the gradable area record */ public function __construct(stdClass $context, $component, $area, $areaid) { global $DB; $this->context = $context; list($type, $name) = normalize_component($component); $this->component = $type . '_' . $name; $this->area = $area; $this->areaid = $areaid; $this->load_definition(); }
function coursereport_engagement_get_plugin_info($manager, $component) { list($type, $name) = normalize_component($component); $plugins = $manager->get_plugins(); if (isset($plugins[$type][$name])) { return $plugins[$type][$name]; } else { return null; } }
/** * Return generator for given plugin * @param string $component * @return mixed plugin data generator */ public function get_plugin_generator($component) { list($type, $plugin) = normalize_component($component); if ($type !== 'mod' and $type !== 'block') { throw new coding_exception("Plugin type {$type} does not support generators yet"); } $dir = get_plugin_directory($type, $plugin); if (!isset($this->generators[$type . '_' . $plugin])) { $lib = "{$dir}/tests/generator/lib.php"; if (!(include_once $lib)) { throw new coding_exception("Plugin {$component} does not support data generator, missing tests/generator/lib"); } $classname = $type . '_' . $plugin . '_generator'; $this->generators[$type . '_' . $plugin] = new $classname($this); } return $this->generators[$type . '_' . $plugin]; }
function definition() { $mform = $this->_form; $current = $this->_customdata['current']; $mform->addElement('header', 'filtersettings', get_string('filter', 'report_customlang')); // Component $options = array(); foreach (report_customlang_utils::list_components() as $component => $normalized) { list($type, $plugin) = normalize_component($normalized); if ($type == 'core' and is_null($plugin)) { $plugin = 'moodle'; } $options[$type][$normalized] = $component . '.php'; } $mform->addElement('selectgroups', 'component', get_string('filtercomponent', 'report_customlang'), $options, array('multiple' => 'multiple', 'size' => 7)); // Customized only $mform->addElement('advcheckbox', 'customized', get_string('filtercustomized', 'report_customlang')); $mform->setType('customized', PARAM_BOOL); $mform->setDefault('customized', 0); // Only helps $mform->addElement('advcheckbox', 'helps', get_string('filteronlyhelps', 'report_customlang')); $mform->setType('helps', PARAM_BOOL); $mform->setDefault('helps', 0); // Modified only $mform->addElement('advcheckbox', 'modified', get_string('filtermodified', 'report_customlang')); $mform->setType('filtermodified', PARAM_BOOL); $mform->setDefault('filtermodified', 0); // Substring $mform->addElement('text', 'substring', get_string('filtersubstring', 'report_customlang')); $mform->setType('substring', PARAM_RAW); // String identifier $mform->addElement('text', 'stringid', get_string('filterstringid', 'report_customlang')); $mform->setType('stringid', PARAM_STRINGID); // Show strings - submit button $mform->addElement('submit', 'submit', get_string('filtershowstrings', 'report_customlang')); }
/** * Return generator for given plugin or component. * @param string $component the component name, e.g. 'mod_forum' or 'core_question'. * @return component_generator_base or rather an instance of the appropriate subclass. */ public function get_plugin_generator($component) { list($type, $plugin) = normalize_component($component); $cleancomponent = $type . '_' . $plugin; if ($cleancomponent != $component) { debugging("Please specify the component you want a generator for as " . "{$cleancomponent}, not {$component}.", DEBUG_DEVELOPER); $component = $cleancomponent; } if (isset($this->generators[$component])) { return $this->generators[$component]; } $dir = get_component_directory($component); $lib = $dir . '/tests/generator/lib.php'; if (!$dir || !is_readable($lib)) { throw new coding_exception("Component {$component} does not support " . "generators yet. Missing tests/generator/lib.php."); } include_once $lib; $classname = $component . '_generator'; if (!class_exists($classname)) { throw new coding_exception("Component {$component} does not support " . "data generators yet. Class {$classname} not found."); } $this->generators[$component] = new $classname($this); return $this->generators[$component]; }
public function test_deprecated_normalize_component() { // Moodle core. $this->assertSame(array('core', null), normalize_component('core')); $this->assertSame(array('core', null), normalize_component('')); $this->assertSame(array('core', null), normalize_component('moodle')); // Moodle core subsystems. $this->assertSame(array('core', 'admin'), normalize_component('admin')); $this->assertSame(array('core', 'admin'), normalize_component('core_admin')); $this->assertSame(array('core', 'admin'), normalize_component('moodle_admin')); // Activity modules and their subplugins. $this->assertSame(array('mod', 'workshop'), normalize_component('workshop')); $this->assertSame(array('mod', 'workshop'), normalize_component('mod_workshop')); $this->assertSame(array('workshopform', 'accumulative'), normalize_component('workshopform_accumulative')); $this->assertSame(array('mod', 'quiz'), normalize_component('quiz')); $this->assertSame(array('quiz', 'grading'), normalize_component('quiz_grading')); $this->assertSame(array('mod', 'data'), normalize_component('data')); $this->assertSame(array('datafield', 'checkbox'), normalize_component('datafield_checkbox')); // Other plugin types. $this->assertSame(array('auth', 'mnet'), normalize_component('auth_mnet')); $this->assertSame(array('enrol', 'self'), normalize_component('enrol_self')); $this->assertSame(array('block', 'html'), normalize_component('block_html')); $this->assertSame(array('block', 'mnet_hosts'), normalize_component('block_mnet_hosts')); $this->assertSame(array('local', 'amos'), normalize_component('local_amos')); $this->assertSame(array('local', 'admin'), normalize_component('local_admin')); // Unknown words without underscore are supposed to be activity modules. $this->assertSame(array('mod', 'whoonearthwouldcomewithsuchastupidnameofcomponent'), normalize_component('whoonearthwouldcomewithsuchastupidnameofcomponent')); // Module names can not contain underscores, this must be a subplugin. $this->assertSame(array('whoonearth', 'wouldcomewithsuchastupidnameofcomponent'), normalize_component('whoonearth_wouldcomewithsuchastupidnameofcomponent')); $this->assertSame(array('whoonearth', 'would_come_withsuchastupidnameofcomponent'), normalize_component('whoonearth_would_come_withsuchastupidnameofcomponent')); }
/** * Adds log entry into upgrade_log table * * @param int $type UPGRADE_LOG_NORMAL, UPGRADE_LOG_NOTICE or UPGRADE_LOG_ERROR * @param string $plugin frankenstyle component name * @param string $info short description text of log entry * @param string $details long problem description * @param string $backtrace string used for errors only * @return void */ function upgrade_log($type, $plugin, $info, $details=null, $backtrace=null) { global $DB, $USER, $CFG; if (empty($plugin)) { $plugin = 'core'; } list($plugintype, $pluginname) = normalize_component($plugin); $component = is_null($pluginname) ? $plugintype : $plugintype . '_' . $pluginname; $backtrace = format_backtrace($backtrace, true); $currentversion = null; $targetversion = null; //first try to find out current version number if ($plugintype === 'core') { //main $currentversion = $CFG->version; $version = null; include("$CFG->dirroot/version.php"); $targetversion = $version; } else if ($plugintype === 'mod') { try { $currentversion = $DB->get_field('modules', 'version', array('name'=>$pluginname)); $currentversion = ($currentversion === false) ? null : $currentversion; } catch (Exception $ignored) { } $cd = get_component_directory($component); if (file_exists("$cd/version.php")) { $module = new stdClass(); $module->version = null; include("$cd/version.php"); $targetversion = $module->version; } } else if ($plugintype === 'block') { try { if ($block = $DB->get_record('block', array('name'=>$pluginname))) { $currentversion = $block->version; } } catch (Exception $ignored) { } $cd = get_component_directory($component); if (file_exists("$cd/version.php")) { $plugin = new stdClass(); $plugin->version = null; include("$cd/version.php"); $targetversion = $plugin->version; } } else { $pluginversion = get_config($component, 'version'); if (!empty($pluginversion)) { $currentversion = $pluginversion; } $cd = get_component_directory($component); if (file_exists("$cd/version.php")) { $plugin = new stdClass(); $plugin->version = null; include("$cd/version.php"); $targetversion = $plugin->version; } } $log = new stdClass(); $log->type = $type; $log->plugin = $component; $log->version = $currentversion; $log->targetversion = $targetversion; $log->info = $info; $log->details = $details; $log->backtrace = $backtrace; $log->userid = $USER->id; $log->timemodified = time(); try { $DB->insert_record('upgrade_log', $log); } catch (Exception $ignored) { // possible during install or 2.0 upgrade } }
/** * @return bool false if the version.php file does not declare required information */ protected function validate_version_php() { if (!isset($this->assertions['plugintype'])) { throw new coding_exception('Required plugin type must be set before calling this'); } if (!isset($this->assertions['moodleversion'])) { throw new coding_exception('Required Moodle version must be set before calling this'); } $fullpath = $this->extractdir . '/' . $this->rootdir . '/version.php'; if (!file_exists($fullpath)) { // This is tolerated for themes only. if ($this->assertions['plugintype'] === 'theme') { $this->add_message(self::DEBUG, 'missingversionphp'); return true; } else { $this->add_message(self::ERROR, 'missingversionphp'); return false; } } $this->versionphp = array(); $info = $this->parse_version_php($fullpath); if ($this->assertions['plugintype'] === 'mod') { $type = 'module'; } else { $type = 'plugin'; } if (!isset($info[$type . '->version'])) { if ($type === 'module' and isset($info['plugin->version'])) { // Expect the activity module using $plugin in version.php instead of $module. $type = 'plugin'; $this->versionphp['version'] = $info[$type . '->version']; $this->add_message(self::INFO, 'pluginversion', $this->versionphp['version']); } else { $this->add_message(self::ERROR, 'missingversion'); return false; } } else { $this->versionphp['version'] = $info[$type . '->version']; $this->add_message(self::INFO, 'pluginversion', $this->versionphp['version']); } if (isset($info[$type . '->requires'])) { $this->versionphp['requires'] = $info[$type . '->requires']; if ($this->versionphp['requires'] > $this->assertions['moodleversion']) { $this->add_message(self::ERROR, 'requiresmoodle', $this->versionphp['requires']); return false; } $this->add_message(self::INFO, 'requiresmoodle', $this->versionphp['requires']); } if (isset($info[$type . '->component'])) { $this->versionphp['component'] = $info[$type . '->component']; list($reqtype, $reqname) = normalize_component($this->versionphp['component']); if ($reqtype !== $this->assertions['plugintype']) { $this->add_message(self::ERROR, 'componentmismatchtype', array('expected' => $this->assertions['plugintype'], 'found' => $reqtype)); return false; } if ($reqname !== $this->rootdir) { $this->add_message(self::ERROR, 'componentmismatchname', $reqname); return false; } $this->add_message(self::INFO, 'componentmatch', $this->versionphp['component']); } if (isset($info[$type . '->maturity'])) { $this->versionphp['maturity'] = $info[$type . '->maturity']; if ($this->versionphp['maturity'] === 'MATURITY_STABLE') { $this->add_message(self::INFO, 'maturity', $this->versionphp['maturity']); } else { $this->add_message(self::WARNING, 'maturity', $this->versionphp['maturity']); } } if (isset($info[$type . '->release'])) { $this->versionphp['release'] = $info[$type . '->release']; $this->add_message(self::INFO, 'release', $this->versionphp['release']); } return true; }
/** * Checks if the given component's directory is writable * * For the purpose of the deployment, the web server process has to have * write access to all files in the component's directory (recursively) and for the * directory itself. * * @see worker::move_directory_source_precheck() * @param string $component normalized component name * @return boolean */ protected function component_writable($component) { list($plugintype, $pluginname) = normalize_component($component); $directory = get_plugin_directory($plugintype, $pluginname); if (is_null($directory)) { throw new coding_exception('Unknown component location', $component); } return $this->directory_writable($directory); }
/** * Returns the active providers for the user specified, based on capability * * @param int $userid id of user * @return array An array of message providers */ function message_get_providers_for_user($userid) { global $DB, $CFG; $systemcontext = context_system::instance(); $providers = get_message_providers(); // Remove all the providers we aren't allowed to see now foreach ($providers as $providerid => $provider) { if (!empty($provider->capability)) { if (!has_capability($provider->capability, $systemcontext, $userid)) { unset($providers[$providerid]); // Not allowed to see this continue; } } // Ensure user is not allowed to configure instantmessage if it is globally disabled. if (!$CFG->messaging && $provider->name == 'instantmessage') { unset($providers[$providerid]); continue; } // If the component is an enrolment plugin, check it is enabled list($type, $name) = normalize_component($provider->component); if ($type == 'enrol') { if (!enrol_is_enabled($name)) { unset($providers[$providerid]); continue; } } } return $providers; }
/** * Returns a localized name of a given plugin * * @param string $plugin name of the plugin, eg mod_workshop or auth_ldap * @return string */ public function plugin_name($plugin) { list($type, $name) = normalize_component($plugin); return $this->pluginsinfo[$type][$name]->displayname; }
/** * Validates a submitted rating * @param array $params submitted data * context => object the context in which the rated items exists [required] * component => The component the rating belongs to [required] * ratingarea => The ratingarea the rating is associated with [required] * itemid => int the ID of the object being rated [required] * scaleid => int the scale from which the user can select a rating. Used for bounds checking. [required] * rating => int the submitted rating * rateduserid => int the id of the user whose items have been rated. NOT the user who submitted the ratings. 0 to update all. [required] * aggregation => int the aggregation method to apply when calculating grades ie RATING_AGGREGATE_AVERAGE [optional] * @return boolean true if the rating is valid. False if callback wasnt found and will throw rating_exception if rating is invalid */ public function check_rating_is_valid($params) { if (!isset($params['context'])) { throw new coding_exception('The context option is a required option when checking rating validity.'); } if (!isset($params['component'])) { throw new coding_exception('The component option is now a required option when checking rating validity'); } if (!isset($params['ratingarea'])) { throw new coding_exception('The ratingarea option is now a required option when checking rating validity'); } if (!isset($params['itemid'])) { throw new coding_exception('The itemid option is now a required option when checking rating validity'); } if (!isset($params['scaleid'])) { throw new coding_exception('The scaleid option is now a required option when checking rating validity'); } if (!isset($params['rateduserid'])) { throw new coding_exception('The rateduserid option is now a required option when checking rating validity'); } list($plugintype, $pluginname) = normalize_component($params['component']); //this looks for a function like forum_rating_validate() in mod_forum lib.php //wrapping the params array in another array as call_user_func_array() expands arrays into multiple arguments $isvalid = plugin_callback($plugintype, $pluginname, 'rating', 'validate', array($params), null); //if null then the callback doesn't exist if ($isvalid === null) { $isvalid = false; debugging('rating validation callback not found for component ' . clean_param($component, PARAM_ALPHANUMEXT)); } return $isvalid; }
try { $autologinguest = true; $setwantsurltome = true; $preventredirect = true; require_login($course, $autologinguest, $cm, $setwantsurltome, $preventredirect); } catch (Exception $e) { if (isguestuser()) { rss_error('rsserrorguest'); } else { rss_error('rsserrorauth'); } } // Work out which component in Moodle we want (from the frankenstyle name) $componentdir = get_component_directory($componentname); list($type, $plugin) = normalize_component($componentname); // Call the component to check/update the feed and tell us the path to the cached file $pathname = null; if (file_exists($componentdir)) { require_once("$componentdir/rsslib.php"); $functionname = $plugin.'_rss_get_feed'; if (function_exists($functionname)) { // $pathname will be null if there was a problem (eg user doesn't have the necessary capabilities) // NOTE:the component providing the feed must do its own capability checks and security $pathname = $functionname($context, $args); } }
/** * Sets the component. * * This method shouldn't be public, changing the component once it has been set potentially * invalidates permission checks. * A coding_error is now thrown if code attempts to change the component. * * @param string $component */ public function set_component($component) { if (!empty($this->component) && $this->component !== $component) { throw new coding_exception('You cannot change the component of a comment once it has been set'); } $this->component = $component; list($this->plugintype, $this->pluginname) = normalize_component($component); }
/** * Decode the request from the Moodle Plugins directory * * @param string $request submitted via 'installaddonrequest' HTTP parameter * @return stdClass|bool false on error, object otherwise */ protected function decode_remote_request($request) { $data = base64_decode($request, true); if ($data === false) { return false; } $data = json_decode($data); if (is_null($data)) { return false; } if (!isset($data->name) or !isset($data->component) or !isset($data->version)) { return false; } $data->name = s(strip_tags($data->name)); if ($data->component !== clean_param($data->component, PARAM_COMPONENT)) { return false; } list($plugintype, $pluginname) = normalize_component($data->component); if ($plugintype === 'core') { return false; } if ($data->component !== $plugintype . '_' . $pluginname) { return false; } // Keep this regex in sync with the one used by the download.moodle.org/api/x.y/pluginfo.php if (!preg_match('/^[0-9]+$/', $data->version)) { return false; } return $data; }
/** * Returns the active providers for the user specified, based on capability * * @param int $userid id of user * @return array An array of message providers */ function message_get_providers_for_user($userid) { global $DB, $CFG; $providers = get_message_providers(); // Ensure user is not allowed to configure instantmessage if it is globally disabled. if (!$CFG->messaging) { foreach ($providers as $providerid => $provider) { if ($provider->name == 'instantmessage') { unset($providers[$providerid]); break; } } } // If the component is an enrolment plugin, check it is enabled foreach ($providers as $providerid => $provider) { list($type, $name) = normalize_component($provider->component); if ($type == 'enrol' && !enrol_is_enabled($name)) { unset($providers[$providerid]); } } // Now we need to check capabilities. We need to eliminate the providers // where the user does not have the corresponding capability anywhere. // Here we deal with the common simple case of the user having the // capability in the system context. That handles $CFG->defaultuserroleid. // For the remaining providers/capabilities, we need to do a more complex // query involving all overrides everywhere. $unsureproviders = array(); $unsurecapabilities = array(); $systemcontext = context_system::instance(); foreach ($providers as $providerid => $provider) { if (empty($provider->capability) || has_capability($provider->capability, $systemcontext, $userid)) { // The provider is relevant to this user. continue; } $unsureproviders[$providerid] = $provider; $unsurecapabilities[$provider->capability] = 1; unset($providers[$providerid]); } if (empty($unsureproviders)) { // More complex checks are not required. return $providers; } // Now check the unsure capabilities. list($capcondition, $params) = $DB->get_in_or_equal(array_keys($unsurecapabilities), SQL_PARAMS_NAMED); $params['userid'] = $userid; $sql = "SELECT DISTINCT rc.capability, 1\n\n FROM {role_assignments} ra\n JOIN {context} actx ON actx.id = ra.contextid\n JOIN {role_capabilities} rc ON rc.roleid = ra.roleid\n JOIN {context} cctx ON cctx.id = rc.contextid\n\n WHERE ra.userid = :userid\n AND rc.capability {$capcondition}\n AND rc.permission > 0\n AND (" . $DB->sql_concat('actx.path', "'/'") . " LIKE " . $DB->sql_concat('cctx.path', "'/%'") . " OR " . $DB->sql_concat('cctx.path', "'/'") . " LIKE " . $DB->sql_concat('actx.path', "'/%'") . ")"; if (!empty($CFG->defaultfrontpageroleid)) { $frontpagecontext = context_course::instance(SITEID); list($capcondition2, $params2) = $DB->get_in_or_equal(array_keys($unsurecapabilities), SQL_PARAMS_NAMED); $params = array_merge($params, $params2); $params['frontpageroleid'] = $CFG->defaultfrontpageroleid; $params['frontpagepathpattern'] = $frontpagecontext->path . '/'; $sql .= "\n UNION\n\n SELECT DISTINCT rc.capability, 1\n\n FROM {role_capabilities} rc\n JOIN {context} cctx ON cctx.id = rc.contextid\n\n WHERE rc.roleid = :frontpageroleid\n AND rc.capability {$capcondition2}\n AND rc.permission > 0\n AND " . $DB->sql_concat('cctx.path', "'/'") . " LIKE :frontpagepathpattern"; } $relevantcapabilities = $DB->get_records_sql_menu($sql, $params); // Add back any providers based on the detailed capability check. foreach ($unsureproviders as $providerid => $provider) { if (array_key_exists($provider->capability, $relevantcapabilities)) { $providers[$providerid] = $provider; } } return $providers; }
/** * Opens and parses/checks a VMoodle instance definition file * @param string $location * */ function vmoodle_parse_csv_nodelist($nodelistlocation = '') { global $CFG; vmoodle_setup_local_config(); $vnodes = array(); if (empty($nodelistlocation)) { $nodelistlocation = $CFG->dataroot . '/vmoodle/nodelist.csv'; } // Decode file. $csv_encode = '/\\&\\#44/'; if (isset($CFG->local_vmoodle_csvseparator)) { $csv_delimiter = '\\' . $config->csvseparator; $csv_delimiter2 = $config->csvseparator; if (isset($CFG->CSV_ENCODE)) { $csv_encode = '/\\&\\#' . $CFG->CSV_ENCODE . '/'; } } else { $csv_delimiter = "\\;"; $csv_delimiter2 = ";"; } /* * File that is used is currently hardcoded here ! * Large files are likely to take their time and memory. Let PHP know * that we'll take longer, and that the process should be recycled soon * to free up memory. */ @set_time_limit(0); @raise_memory_limit("256M"); if (function_exists('apache_child_terminate')) { @apache_child_terminate(); } // Make arrays of valid fields for error checking. $required = array('vhostname' => 1, 'name' => 1, 'shortname' => 1, 'vdatapath' => 1, 'vdbname' => 1, 'vdblogin' => 1, 'vdbpass' => 1); $optional = array('description' => 1, 'vdbhost' => 1, 'vdbpersist' => 1, 'vtemplate' => 1, 'services' => 1, 'enabled' => 1, 'mnet' => 1); $optionalDefaults = array('mnet' => 1, 'vdbtype' => 'mysqli', 'vdbhost' => $CFG->dbhost, 'vdbpersist' => $CFG->dboptions['dbpersist'], 'vdbprefix' => 'mdl_', 'vtemplate' => '', 'enabled' => 1, 'services' => 'default'); $patterns = array(); $metas = array('auth_.*', 'block_.*', 'mod_.*', 'local_.*', 'report_.*', 'format_.*', 'config_.*'); // Get header (field names). $textlib = new core_text(); if (!($fp = fopen($nodelistlocation, 'rb'))) { cli_error(get_string('badnodefile', 'local_vmoodle', $nodelistlocation)); } // Jump any empty or comment line. $text = fgets($fp, 1024); $i = 0; while (vmoodle_is_empty_line_or_format($text, $i == 0)) { $text = fgets($fp, 1024); $i++; } $headers = explode($csv_delimiter2, $text); // Check for valid field names. foreach ($headers as $h) { $header[] = trim($h); $patternized = implode('|', $patterns) . "\\d+"; $metapattern = implode('|', $metas); if (!(isset($required[$h]) or isset($optionalDefaults[$h]) or isset($optional[$h]) or preg_match("/{$patternized}/", $h) or preg_match("/{$metapattern}/", $h))) { cli_error(get_string('invalidfieldname', 'error', $h)); return; } if (isset($required[trim($h)])) { $required[trim($h)] = 0; } } // Check for required fields. foreach ($required as $key => $value) { if ($value) { // Required field missing. cli_error(get_string('fieldrequired', 'error', $key)); return; } } $linenum = 2; // Since header is line 1. // Take some from admin profile, other fixed by hardcoded defaults. while (!feof($fp)) { // Make a new base record. $vnode = new StdClass(); foreach ($optionalDefaults as $key => $value) { $vnode->{$key} = $value; } // Commas within a field should be encoded as , (for comma separated csv files). // Semicolon within a field should be encoded as ; (for semicolon separated csv files). $text = fgets($fp, 1024); if (vmoodle_is_empty_line_or_format($text, false)) { $i++; continue; } $valueset = explode($csv_delimiter2, $text); $f = 0; foreach ($valueset as $value) { // Decode encoded commas. $key = $headers[$f]; // Do we have a global config ? if (preg_match('/^config_/', $key)) { $smartkey = str_replace('config_', '', $key); $vnode->config->{$smartkey} = trim($value); $f++; continue; } // Do we have a plugin config ? /* * plugin configs will come as f.e. "auth_cas|server" key * */ if (strpos($key, '|') > 0) { list($component, $key) = explode('|', $key); list($type, $plugin) = normalize_component($component); if (!isset($vnode->{$type})) { $vnode->{$type} = new StdClass(); } if (!isset($vnode->{$type}->{$plugin})) { $vnode->{$type}->{$plugin} = new StdClass(); } $vnode->{$type}->{$plugin}->{$key} = preg_replace($csv_encode, $csv_delimiter2, trim($value)); $f++; continue; } $vnode->{$key} = preg_replace($csv_encode, $csv_delimiter2, trim($value)); $f++; } $vnodes[] = $vnode; } return $vnodes; }
/** * Get String returns a requested string * * @param string $identifier The identifier of the string to search for * @param string $component The module the string is associated with * @param string|object|array $a An object, string or number that can be used * within translation strings * @param string $lang moodle translation language, NULL means use current * @return string The String ! */ public function get_string($identifier, $component = '', $a = NULL, $lang = NULL) { $this->countgetstring++; // there are very many uses of these time formating strings without the 'langconfig' component, // it would not be reasonable to expect that all of them would be converted during 2.0 migration static $langconfigstrs = array('strftimedate' => 1, 'strftimedatefullshort' => 1, 'strftimedateshort' => 1, 'strftimedatetime' => 1, 'strftimedatetimeshort' => 1, 'strftimedaydate' => 1, 'strftimedaydatetime' => 1, 'strftimedayshort' => 1, 'strftimedaytime' => 1, 'strftimemonthyear' => 1, 'strftimerecent' => 1, 'strftimerecentfull' => 1, 'strftimetime' => 1); if (empty($component)) { if (isset($langconfigstrs[$identifier])) { $component = 'langconfig'; } else { $component = 'moodle'; } } if ($lang === NULL) { $lang = current_language(); } $string = $this->load_component_strings($component, $lang); if (!isset($string[$identifier])) { if ($component === 'pix' or $component === 'core_pix') { // this component contains only alt tags for emoticons, // not all of them are supposed to be defined return ''; } if ($identifier === 'parentlanguage' and ($component === 'langconfig' or $component === 'core_langconfig')) { // parentlanguage is a special string, undefined means use English if not defined return 'en'; } if ($this->usediskcache) { // maybe the on-disk cache is dirty - let the last attempt be to find the string in original sources, // do NOT write the results to disk cache because it may end up in race conditions see MDL-31904 $this->usediskcache = false; $string = $this->load_component_strings($component, $lang, true); $this->usediskcache = true; } if (!isset($string[$identifier])) { // the string is still missing - should be fixed by developer list($plugintype, $pluginname) = normalize_component($component); if ($plugintype == 'core') { $file = "lang/en/{$component}.php"; } else { if ($plugintype == 'mod') { $file = "mod/{$pluginname}/lang/en/{$pluginname}.php"; } else { $path = get_plugin_directory($plugintype, $pluginname); $file = "{$path}/lang/en/{$plugintype}_{$pluginname}.php"; } } debugging("Invalid get_string() identifier: '{$identifier}' or component '{$component}'. " . "Perhaps you are missing \$string['{$identifier}'] = ''; in {$file}?", DEBUG_DEVELOPER); return "[[{$identifier}]]"; } } $string = $string[$identifier]; if ($a !== NULL) { // Process array's and objects (except lang_strings) if (is_array($a) or is_object($a) && !$a instanceof lang_string) { $a = (array) $a; $search = array(); $replace = array(); foreach ($a as $key => $value) { if (is_int($key)) { // we do not support numeric keys - sorry! continue; } if (is_array($value) or is_object($value) && !$value instanceof lang_string) { // we support just string or lang_string as value continue; } $search[] = '{$a->' . $key . '}'; $replace[] = (string) $value; } if ($search) { $string = str_replace($search, $replace, $string); } } else { $string = str_replace('{$a}', (string) $a, $string); } } return $string; }
/** * Load all strings for one component * @param string $component The module the string is associated with * @param string $lang * @param bool $disablecache Do not use caches, force fetching the strings from sources * @param bool $disablelocal Do not use customized strings in xx_local language packs * @return array of all string for given component and lang */ public function load_component_strings($component, $lang, $disablecache = false, $disablelocal = false) { global $CFG; list($plugintype, $pluginname) = normalize_component($component); if ($plugintype == 'core' and is_null($pluginname)) { $component = 'core'; } else { $component = $plugintype . '_' . $pluginname; } if (!$disablecache) { // try in-memory cache first if (isset($this->cache[$lang][$component])) { $this->countmemcache++; return $this->cache[$lang][$component]; } // try on-disk cache then if ($this->usediskcache and file_exists($this->cacheroot . "/{$lang}/{$component}.php")) { $this->countdiskcache++; include $this->cacheroot . "/{$lang}/{$component}.php"; return $this->cache[$lang][$component]; } } // no cache found - let us merge all possible sources of the strings if ($plugintype === 'core') { $file = $pluginname; if ($file === null) { $file = 'moodle'; } $string = array(); // first load english pack if (!file_exists("{$CFG->dirroot}/lang/en/{$file}.php")) { return array(); } include "{$CFG->dirroot}/lang/en/{$file}.php"; $originalkeys = array_keys($string); $originalkeys = array_flip($originalkeys); // and then corresponding local if present and allowed if (!$disablelocal and file_exists("{$this->localroot}/en_local/{$file}.php")) { include "{$this->localroot}/en_local/{$file}.php"; } // now loop through all langs in correct order $deps = $this->get_language_dependencies($lang); foreach ($deps as $dep) { // the main lang string location if (file_exists("{$this->otherroot}/{$dep}/{$file}.php")) { include "{$this->otherroot}/{$dep}/{$file}.php"; } if (!$disablelocal and file_exists("{$this->localroot}/{$dep}_local/{$file}.php")) { include "{$this->localroot}/{$dep}_local/{$file}.php"; } } } else { if (!($location = get_plugin_directory($plugintype, $pluginname)) or !is_dir($location)) { return array(); } if ($plugintype === 'mod') { // bloody mod hack $file = $pluginname; } else { $file = $plugintype . '_' . $pluginname; } $string = array(); // first load English pack if (!file_exists("{$location}/lang/en/{$file}.php")) { //English pack does not exist, so do not try to load anything else return array(); } include "{$location}/lang/en/{$file}.php"; $originalkeys = array_keys($string); $originalkeys = array_flip($originalkeys); // and then corresponding local english if present if (!$disablelocal and file_exists("{$this->localroot}/en_local/{$file}.php")) { include "{$this->localroot}/en_local/{$file}.php"; } // now loop through all langs in correct order $deps = $this->get_language_dependencies($lang); foreach ($deps as $dep) { // legacy location - used by contrib only if (file_exists("{$location}/lang/{$dep}/{$file}.php")) { include "{$location}/lang/{$dep}/{$file}.php"; } // the main lang string location if (file_exists("{$this->otherroot}/{$dep}/{$file}.php")) { include "{$this->otherroot}/{$dep}/{$file}.php"; } // local customisations if (!$disablelocal and file_exists("{$this->localroot}/{$dep}_local/{$file}.php")) { include "{$this->localroot}/{$dep}_local/{$file}.php"; } } } // we do not want any extra strings from other languages - everything must be in en lang pack $string = array_intersect_key($string, $originalkeys); // now we have a list of strings from all possible sources. put it into both in-memory and on-disk // caches so we do not need to do all this merging and dependencies resolving again $this->cache[$lang][$component] = $string; if ($this->usediskcache) { check_dir_exists("{$this->cacheroot}/{$lang}"); file_put_contents("{$this->cacheroot}/{$lang}/{$component}.php", "<?php \$this->cache['{$lang}']['{$component}'] = " . var_export($string, true) . ";"); } return $string; }
/** * @param string $component frankenstyle component name. * @return plugin_information|null the corresponding plugin information. */ public function get_plugin_info($component) { list($type, $name) = normalize_component($component); $plugins = $this->get_plugins(); if (isset($plugins[$type][$name])) { return $plugins[$type][$name]; } else { return null; } }
/** * Returns the list of gradable areas provided by the given component * * This performs a callback to the library of the relevant plugin to obtain * the list of supported areas. * * @param string $component normalized component name * @return array of (string)areacode => (string)localized title of the area */ public static function available_areas($component) { global $CFG; list($plugintype, $pluginname) = normalize_component($component); if ($component === 'core_grading') { return array(); } else { if ($plugintype === 'mod') { return plugin_callback('mod', $pluginname, 'grading', 'areas_list', null, array()); } else { throw new coding_exception('Unsupported area location'); } } }
public function set_component($component) { $this->component = $component; list($this->plugintype, $this->pluginname) = normalize_component($component); return null; }
/** * Gather a list of dndupload handlers from the different mods * * @param object $course The course this is being added to (to check course_allowed_module() ) */ public function __construct($course, $modnames = null) { global $CFG; // Add some default types to handle. // Note: 'Files' type is hard-coded into the Javascript as this needs to be ... // ... treated a little differently. $this->add_type('url', array('url', 'text/uri-list', 'text/x-moz-url'), get_string('addlinkhere', 'moodle'), get_string('nameforlink', 'moodle'), 10); $this->add_type('text/html', array('text/html'), get_string('addpagehere', 'moodle'), get_string('nameforpage', 'moodle'), 20); $this->add_type('text', array('text', 'text/plain'), get_string('addpagehere', 'moodle'), get_string('nameforpage', 'moodle'), 30); // Loop through all modules to find handlers. $mods = get_plugin_list_with_function('mod', 'dndupload_register'); foreach ($mods as $component => $funcname) { list($modtype, $modname) = normalize_component($component); if ($modnames && !array_key_exists($modname, $modnames)) { continue; // Module is deactivated (hidden) at the site level. } if (!course_allowed_module($course, $modname)) { continue; // User does not have permission to add this module to the course. } $resp = $funcname(); if (!$resp) { continue; } if (isset($resp['files'])) { foreach ($resp['files'] as $file) { $this->add_file_handler($file['extension'], $modname, $file['message']); } } if (isset($resp['addtypes'])) { foreach ($resp['addtypes'] as $type) { if (isset($type['priority'])) { $priority = $type['priority']; } else { $priority = 100; } $this->add_type($type['identifier'], $type['datatransfertypes'], $type['addmessage'], $type['namemessage'], $priority); } } if (isset($resp['types'])) { foreach ($resp['types'] as $type) { $this->add_type_handler($type['identifier'], $modname, $type['message']); } } } }
/** * Given the list of changes in available updates, pick those to send to site admins * * @param array $changes as returned by {@link self::compare_responses()} * @return array of available_update_info objects to send to site admins */ protected function cron_notifications(array $changes) { global $CFG; $notifications = array(); $pluginman = plugin_manager::instance(); $plugins = $pluginman->get_plugins(true); foreach ($changes as $component => $componentchanges) { if (empty($componentchanges)) { continue; } $componentupdates = $this->get_update_info($component, array('minmaturity' => $CFG->updateminmaturity, 'notifybuilds' => $CFG->updatenotifybuilds)); if (empty($componentupdates)) { continue; } // notify only about those $componentchanges that are present in $componentupdates // to respect the preferences foreach ($componentchanges as $componentchange) { foreach ($componentupdates as $componentupdate) { if ($componentupdate->version == $componentchange['version']) { if ($component == 'core') { // in case of 'core' this is enough, we already know that the // $componentupdate is a real update with higher version $notifications[] = $componentupdate; } else { // use the plugin_manager to check if the reported $componentchange // is a real update with higher version. such a real update must be // present in the 'availableupdates' property of one of the component's // available_update_info object list($plugintype, $pluginname) = normalize_component($component); if (!empty($plugins[$plugintype][$pluginname]->availableupdates)) { foreach ($plugins[$plugintype][$pluginname]->availableupdates as $availableupdate) { if ($availableupdate->version == $componentchange['version']) { $notifications[] = $componentupdate; } } } } } } } } return $notifications; }
/** * Writes strings into a local language pack file * * @param string $component the name of the component * @param array $strings */ protected static function dump_strings($lang, $component, $strings) { global $CFG; if ($lang !== clean_param($lang, PARAM_LANG)) { debugging('Unable to dump local strings for non-installed language pack .' . s($lang)); return false; } if ($component !== clean_param($component, PARAM_COMPONENT)) { throw new coding_exception('Incorrect component name'); } if (!($filename = self::get_component_filename($component))) { debugging('Unable to find the filename for the component ' . s($component)); return false; } if ($filename !== clean_param($filename, PARAM_FILE)) { throw new coding_exception('Incorrect file name ' . s($filename)); } list($package, $subpackage) = normalize_component($component); $packageinfo = " * @package {$package}"; if (!is_null($subpackage)) { $packageinfo .= "\n * @subpackage {$subpackage}"; } $filepath = self::get_localpack_location($lang); $filepath = $filepath . '/' . $filename; if (!is_dir(dirname($filepath))) { check_dir_exists(dirname($filepath)); } if (!($f = fopen($filepath, 'w'))) { debugging('Unable to write ' . s($filepath)); return false; } fwrite($f, <<<EOF <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Local language pack from {$CFG->wwwroot} * {$packageinfo} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); EOF ); foreach ($strings as $stringid => $text) { if ($stringid !== clean_param($stringid, PARAM_STRINGID)) { debugging('Invalid string identifier ' . s($stringid)); continue; } fwrite($f, '$string[\'' . $stringid . '\'] = '); fwrite($f, var_export($text, true)); fwrite($f, ";\n"); } fclose($f); }
/** * Returns the version of installed component * * @param string $component component name * @param string $source either 'disk' or 'installed' - where to get the version information from * @return string|bool version number or false if the component is not found */ function get_component_version($component, $source = 'installed') { global $CFG, $DB; list($type, $name) = normalize_component($component); // moodle core or a core subsystem if ($type === 'core') { if ($source === 'installed') { if (empty($CFG->version)) { return false; } else { return $CFG->version; } } else { if (!is_readable($CFG->dirroot . '/version.php')) { return false; } else { $version = null; //initialize variable for IDEs include $CFG->dirroot . '/version.php'; return $version; } } } // activity module if ($type === 'mod') { if ($source === 'installed') { return $DB->get_field('modules', 'version', array('name' => $name)); } else { $mods = get_plugin_list('mod'); if (empty($mods[$name]) or !is_readable($mods[$name] . '/version.php')) { return false; } else { $module = new stdclass(); include $mods[$name] . '/version.php'; return $module->version; } } } // block if ($type === 'block') { if ($source === 'installed') { return $DB->get_field('block', 'version', array('name' => $name)); } else { $blocks = get_plugin_list('block'); if (empty($blocks[$name]) or !is_readable($blocks[$name] . '/version.php')) { return false; } else { $plugin = new stdclass(); include $blocks[$name] . '/version.php'; return $plugin->version; } } } // all other plugin types if ($source === 'installed') { return get_config($type . '_' . $name, 'version'); } else { $plugins = get_plugin_list($type); if (empty($plugins[$name])) { return false; } else { $plugin = new stdclass(); include $plugins[$name] . '/version.php'; return $plugin->version; } } }
/** * Update a grade item and, optionally, student grades * * @param string $source The source of the grade update * @param int $courseid The course id * @param string $component Component name * @param int $activityid The activity id * @param int $itemnumber The item number * @param array $grades Array of grades * @param array $itemdetails Array of item details * @return int A status flag * @since Moodle 2.7 */ public static function update_grades($source, $courseid, $component, $activityid, $itemnumber, $grades = array(), $itemdetails = array()) { global $CFG; $params = self::validate_parameters(self::update_grades_parameters(), array('source' => $source, 'courseid' => $courseid, 'component' => $component, 'activityid' => $activityid, 'itemnumber' => $itemnumber, 'grades' => $grades, 'itemdetails' => $itemdetails)); list($itemtype, $itemmodule) = normalize_component($params['component']); if (!($cm = get_coursemodule_from_id($itemmodule, $activityid))) { throw new moodle_exception('invalidcoursemodule'); } $iteminstance = $cm->instance; $coursecontext = context_course::instance($params['courseid']); try { self::validate_context($coursecontext); } catch (Exception $e) { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $params['courseid']; throw new moodle_exception('errorcoursecontextnotvalid', 'webservice', '', $exceptionparam); } $hidinggrades = false; $editinggradeitem = false; $editinggrades = false; $gradestructure = array(); foreach ($grades as $grade) { $editinggrades = true; $gradestructure[$grade['studentid']] = array('userid' => $grade['studentid'], 'rawgrade' => $grade['grade']); } if (!empty($params['itemdetails'])) { if (isset($params['itemdetails']['hidden'])) { $hidinggrades = true; } else { $editinggradeitem = true; } } if ($editinggradeitem && !has_capability('moodle/grade:manage', $coursecontext)) { throw new moodle_exception('nopermissiontoviewgrades', 'error', '', null, 'moodle/grade:manage required to edit grade information'); } if ($hidinggrades && !has_capability('moodle/grade:hide', $coursecontext) && !has_capability('moodle/grade:hide', $coursecontext)) { throw new moodle_exception('nopermissiontoviewgrades', 'error', '', null, 'moodle/grade:hide required to hide grade items'); } if ($editinggrades && !has_capability('moodle/grade:edit', $coursecontext)) { throw new moodle_exception('nopermissiontoviewgrades', 'error', '', null, 'moodle/grade:edit required to edit grades'); } return grade_update($params['source'], $params['courseid'], $itemtype, $itemmodule, $iteminstance, $itemnumber, $gradestructure, $params['itemdetails']); }
require_once(dirname(__FILE__) . '/../../config.php'); // PARAM_STRINGID ensures this is a valid string ID, which should make // this safe to use. (Otherwise an attacker could include ../ or the like). $topic = required_param('topic', PARAM_STRINGID); $component = required_param('component', PARAM_SAFEDIR); $lang = current_language( ); $PAGE->set_url( '/blocks/marginalia/help.php' ); $PAGE->set_pagelayout( 'popup' ); $PAGE->set_context( get_context_instance( CONTEXT_SYSTEM ) ); $PAGE->requires->css( '/blocks/marginalia/help.css' ); echo $OUTPUT->header( ); list( $plugintype, $pluginname ) = normalize_component( $component ); $location = get_plugin_directory( $plugintype, $pluginname ); // Once something matches, break from the while. // Otherwise fall down to the next case. do { $path = "$location/lang/$lang/help/$topic.html"; if ( $location && file_exists( $path ) ) { include( $path ); break; } $path = "$location/lang/en/help/$topic.html"; if ( $location && file_exists( $path ) )
/** * This gets the mod/block/course/core etc strings. * * @param string $component * @param int $contextlevel * @return string|bool String is success, false if failed */ function get_component_string($component, $contextlevel) { if ($component === 'moodle' or $component === 'core') { switch ($contextlevel) { // TODO: this should probably use context level names instead case CONTEXT_SYSTEM: return get_string('coresystem'); case CONTEXT_USER: return get_string('users'); case CONTEXT_COURSECAT: return get_string('categories'); case CONTEXT_COURSE: return get_string('course'); case CONTEXT_MODULE: return get_string('activities'); case CONTEXT_BLOCK: return get_string('block'); default: print_error('unknowncontext'); } } list($type, $name) = normalize_component($component); $dir = get_plugin_directory($type, $name); if (!file_exists($dir)) { // plugin not installed, bad luck, there is no way to find the name return $component . ' ???'; } switch ($type) { // TODO: this is really hacky, anyway it should be probably moved to lib/pluginlib.php case 'quiz': return get_string($name . ':componentname', $component); // insane hack!!! // insane hack!!! case 'repository': return get_string('repository', 'repository') . ': ' . get_string('pluginname', $component); case 'gradeimport': return get_string('gradeimport', 'grades') . ': ' . get_string('pluginname', $component); case 'gradeexport': return get_string('gradeexport', 'grades') . ': ' . get_string('pluginname', $component); case 'gradereport': return get_string('gradereport', 'grades') . ': ' . get_string('pluginname', $component); case 'webservice': return get_string('webservice', 'webservice') . ': ' . get_string('pluginname', $component); case 'block': return get_string('block') . ': ' . get_string('pluginname', basename($component)); case 'mod': if (get_string_manager()->string_exists('pluginname', $component)) { return get_string('activity') . ': ' . get_string('pluginname', $component); } else { return get_string('activity') . ': ' . get_string('modulename', $component); } default: return get_string('pluginname', $component); } }
public function test_normalize_component() { // moodle core $this->assertEqual(normalize_component('moodle'), array('core', null)); $this->assertEqual(normalize_component('core'), array('core', null)); // moodle core subsystems $this->assertEqual(normalize_component('admin'), array('core', 'admin')); $this->assertEqual(normalize_component('core_admin'), array('core', 'admin')); // activity modules and their subplugins $this->assertEqual(normalize_component('workshop'), array('mod', 'workshop')); $this->assertEqual(normalize_component('mod_workshop'), array('mod', 'workshop')); $this->assertEqual(normalize_component('workshopform_accumulative'), array('workshopform', 'accumulative')); $this->assertEqual(normalize_component('quiz'), array('mod', 'quiz')); $this->assertEqual(normalize_component('quiz_grading'), array('quiz', 'grading')); $this->assertEqual(normalize_component('data'), array('mod', 'data')); $this->assertEqual(normalize_component('datafield_checkbox'), array('datafield', 'checkbox')); // other plugin types $this->assertEqual(normalize_component('auth_mnet'), array('auth', 'mnet')); $this->assertEqual(normalize_component('enrol_self'), array('enrol', 'self')); $this->assertEqual(normalize_component('block_html'), array('block', 'html')); $this->assertEqual(normalize_component('block_mnet_hosts'), array('block', 'mnet_hosts')); $this->assertEqual(normalize_component('local_amos'), array('local', 'amos')); // unknown components are supposed to be activity modules $this->assertEqual(normalize_component('whothefuckwouldcomewithsuchastupidnameofcomponent'), array('mod', 'whothefuckwouldcomewithsuchastupidnameofcomponent')); $this->assertEqual(normalize_component('whothefuck_wouldcomewithsuchastupidnameofcomponent'), array('mod', 'whothefuck_wouldcomewithsuchastupidnameofcomponent')); $this->assertEqual(normalize_component('whothefuck_would_come_withsuchastupidnameofcomponent'), array('mod', 'whothefuck_would_come_withsuchastupidnameofcomponent')); }