Beispiel #1
0
/**
 * Returns detailed function information
 * @param string|object $function name of external function or record from external_function
 * @param int $strictness IGNORE_MISSING means compatible mode, false returned if record not found, debug message if more found;
 *                        MUST_EXIST means throw exception if no record or multiple records found
 * @return object description or false if not found or exception thrown
 */
function external_function_info($function, $strictness=MUST_EXIST) {
    global $DB, $CFG;

    if (!is_object($function)) {
        if (!$function = $DB->get_record('external_functions', array('name'=>$function), '*', $strictness)) {
            return false;
        }
    }

    //first find and include the ext implementation class
    $function->classpath = empty($function->classpath) ? get_component_directory($function->component).'/externallib.php' : $CFG->dirroot.'/'.$function->classpath;
    if (!file_exists($function->classpath)) {
        throw new coding_exception('Can not find file with external function implementation');
    }
    require_once($function->classpath);

    $function->parameters_method = $function->methodname.'_parameters';
    $function->returns_method    = $function->methodname.'_returns';

    // make sure the implementaion class is ok
    if (!method_exists($function->classname, $function->methodname)) {
        throw new coding_exception('Missing implementation method of '.$function->classname.'::'.$function->methodname);
    }
    if (!method_exists($function->classname, $function->parameters_method)) {
        throw new coding_exception('Missing parameters description');
    }
    if (!method_exists($function->classname, $function->returns_method)) {
        throw new coding_exception('Missing returned values description');
    }

    // fetch the parameters description
    $function->parameters_desc = call_user_func(array($function->classname, $function->parameters_method));
    if (!($function->parameters_desc instanceof external_function_parameters)) {
        throw new coding_exception('Invalid parameters description');
    }

    // fetch the return values description
    $function->returns_desc = call_user_func(array($function->classname, $function->returns_method));
    // null means void result or result is ignored
    if (!is_null($function->returns_desc) and !($function->returns_desc instanceof external_description)) {
        throw new coding_exception('Invalid return description');
    }

    //now get the function description
    //TODO: use localised lang pack descriptions, it would be nice to have
    //      easy to understand descriptions in admin UI,
    //      on the other hand this is still a bit in a flux and we need to find some new naming
    //      conventions for these descriptions in lang packs
    $function->description = null;
    $servicesfile = get_component_directory($function->component).'/db/services.php';
    if (file_exists($servicesfile)) {
        $functions = null;
        include($servicesfile);
        if (isset($functions[$function->name]['description'])) {
            $function->description = $functions[$function->name]['description'];
        }
    }

    return $function;
}
Beispiel #2
0
/**
 * Adds a specified user to a group
 *
 * @param mixed $grouporid  The group id or group object
 * @param mixed $userorid   The user id or user object
 * @param string $component Optional component name e.g. 'enrol_imsenterprise'
 * @param int $itemid Optional itemid associated with component
 * @return bool True if user added successfully or the user is already a
 * member of the group, false otherwise.
 */
function groups_add_member($grouporid, $userorid, $component = null, $itemid = 0)
{
    global $DB;
    if (is_object($userorid)) {
        $userid = $userorid->id;
        $user = $userorid;
    } else {
        $userid = $userorid;
        $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
    }
    if (is_object($grouporid)) {
        $groupid = $grouporid->id;
        $group = $grouporid;
    } else {
        $groupid = $grouporid;
        $group = $DB->get_record('groups', array('id' => $groupid), '*', MUST_EXIST);
    }
    //check if the user a participant of the group course
    if (!is_enrolled(context_course::instance($group->courseid), $userid)) {
        return false;
    }
    if (groups_is_member($groupid, $userid)) {
        return true;
    }
    $member = new stdClass();
    $member->groupid = $groupid;
    $member->userid = $userid;
    $member->timeadded = time();
    $member->component = '';
    $member->itemid = 0;
    // Check the component exists if specified
    if (!empty($component)) {
        $dir = get_component_directory($component);
        if ($dir && is_dir($dir)) {
            // Component exists and can be used
            $member->component = $component;
            $member->itemid = $itemid;
        } else {
            throw new coding_exception('Invalid call to groups_add_member(). An invalid component was specified');
        }
    }
    if ($itemid !== 0 && empty($member->component)) {
        // An itemid can only be specified if a valid component was found
        throw new coding_exception('Invalid call to groups_add_member(). A component must be specified if an itemid is given');
    }
    $DB->insert_record('groups_members', $member);
    //update group info
    $DB->set_field('groups', 'timemodified', $member->timeadded, array('id' => $groupid));
    //trigger groups events
    $eventdata = new stdClass();
    $eventdata->groupid = $groupid;
    $eventdata->userid = $userid;
    $eventdata->component = $member->component;
    $eventdata->itemid = $member->itemid;
    events_trigger('groups_member_added', $eventdata);
    return true;
}
Beispiel #3
0
/**
 * Loads the events definitions for the component (from file). If no
 * events are defined for the component, we simply return an empty array.
 *
 * INTERNAL - to be used from eventslib only
 *
 * @global object
 * @param string $component examples: 'moodle', 'mod/forum', 'block/quiz_results'
 * @return array of capabilities or empty array if not exists
 */
function events_load_def($component)
{
    $defpath = get_component_directory($component) . '/db/events.php';
    $handlers = array();
    if (file_exists($defpath)) {
        require $defpath;
    }
    return $handlers;
}
Beispiel #4
0
/**
 * Loads the events definitions for the component (from file). If no
 * events are defined for the component, we simply return an empty array.
 *
 * INTERNAL - to be used from eventslib only
 *
 * @param string $component examples: 'moodle', 'mod_forum', 'block_quiz_results'
 * @return array of capabilities or empty array if not exists
 */
function events_load_def($component)
{
    global $CFG;
    if ($component === 'unittest') {
        $defpath = $CFG->dirroot . '/lib/simpletest/fixtures/events.php';
    } else {
        $defpath = get_component_directory($component) . '/db/events.php';
    }
    $handlers = array();
    if (file_exists($defpath)) {
        require $defpath;
    }
    // make sure the definitions are valid and complete; tell devs what is wrong
    foreach ($handlers as $eventname => $handler) {
        if ($eventname === 'reset') {
            debugging("'reset' can not be used as event name.");
            unset($handlers['reset']);
            continue;
        }
        if (!is_array($handler)) {
            debugging("Handler of '{$eventname}' must be specified as array'");
            unset($handlers[$eventname]);
            continue;
        }
        if (!isset($handler['handlerfile'])) {
            debugging("Handler of '{$eventname}' must include 'handlerfile' key'");
            unset($handlers[$eventname]);
            continue;
        }
        if (!isset($handler['handlerfunction'])) {
            debugging("Handler of '{$eventname}' must include 'handlerfunction' key'");
            unset($handlers[$eventname]);
            continue;
        }
        if (!isset($handler['schedule'])) {
            $handler['schedule'] = 'instant';
        }
        if ($handler['schedule'] !== 'instant' and $handler['schedule'] !== 'cron') {
            debugging("Handler of '{$eventname}' must include valid 'schedule' type (instant or cron)'");
            unset($handlers[$eventname]);
            continue;
        }
        if (!isset($handler['internal'])) {
            $handler['internal'] = 1;
        }
        $handlers[$eventname] = $handler;
    }
    return $handlers;
}
Beispiel #5
0
 /**
  * Return user information including profile picture + basic site information
  * Note:
  * - no capability checking because we return just known information by logged user
  * @param array $serviceshortnames of service shortnames - the functions of these services will be returned
  * @return array
  */
 public function get_site_info($serviceshortnames = array())
 {
     global $USER, $SITE, $CFG;
     $params = self::validate_parameters(self::get_site_info_parameters(), array('serviceshortnames' => $serviceshortnames));
     $profileimageurl = moodle_url::make_pluginfile_url(get_context_instance(CONTEXT_USER, $USER->id)->id, 'user', 'icon', NULL, '/', 'f1');
     require_once $CFG->dirroot . "/webservice/lib.php";
     $webservice = new webservice();
     //If no service listed always return the mobile one by default
     if (empty($params['serviceshortnames']) and $CFG->enablewebservices) {
         $mobileservice = $webservice->get_external_service_by_shortname(MOODLE_OFFICIAL_MOBILE_SERVICE);
         if ($mobileservice->enabled) {
             $params['serviceshortnames'] = array(MOODLE_OFFICIAL_MOBILE_SERVICE);
             //return mobile service by default
         }
     }
     //retrieve the functions related to the services
     $functions = $webservice->get_external_functions_by_enabled_services($params['serviceshortnames']);
     //built up the returned values of the list of functions
     $componentversions = array();
     $avalaiblefunctions = array();
     foreach ($functions as $function) {
         $functioninfo = array();
         $functioninfo['name'] = $function->name;
         if ($function->component == 'moodle') {
             $version = $CFG->version;
             //moodle version
         } else {
             $versionpath = get_component_directory($function->component) . '/version.php';
             if (is_readable($versionpath)) {
                 //we store the component version once retrieved (so we don't load twice the version.php)
                 if (!isset($componentversions[$function->component])) {
                     include $versionpath;
                     $componentversions[$function->component] = $plugin->version;
                     $version = $plugin->version;
                 } else {
                     $version = $componentversions[$function->component];
                 }
             } else {
                 //function component should always have a version.php,
                 //otherwise the function should have been described with component => 'moodle'
                 throw new moodle_exception('missingversionfile', 'webservice', '', $function->component);
             }
         }
         $functioninfo['version'] = $version;
         $avalaiblefunctions[] = $functioninfo;
     }
     return array('sitename' => $SITE->fullname, 'siteurl' => $CFG->wwwroot, 'username' => $USER->username, 'firstname' => $USER->firstname, 'lastname' => $USER->lastname, 'fullname' => fullname($USER), 'userid' => $USER->id, 'userpictureurl' => $profileimageurl->out(false), 'functions' => $avalaiblefunctions);
 }
Beispiel #6
0
/**
 * Loads the task definitions for the component (from file). If no
 * tasks are defined for the component, we simply return an empty array.
 * @param $component - examples: 'moodle', 'mod_forum', 'block_quiz_results'
 * @return array of tasks or empty array if not exists
 *
 * INTERNAL - to be used from cronlib only
 */
function elis_tasks_load_def($component)
{
    global $CFG;
    if ($component == 'moodle') {
        $defpath = $CFG->libdir . '/db/tasks.php';
        //} else if ($component == 'unittest') {
        //    $defpath = $CFG->libdir.'/simpletest/fixtures/tasks.php';
    } else {
        $defpath = get_component_directory($component) . '/db/tasks.php';
        //error_log("/local/eliscore/lib/tasklib.php::elis_tasks_load_def('{$component}') looking for: {$defpath}");
    }
    $tasks = array();
    if (file_exists($defpath)) {
        require $defpath;
    }
    return $tasks;
}
 /**
  * Determine the module metadata for all moodle YUI modules.
  *
  * This works through all modules capable of serving YUI modules, and attempts to get
  * metadata for each of those modules.
  *
  * @return Array of module metadata
  */
 private function get_moodle_metadata()
 {
     $moodlemodules = array();
     // Core isn't a plugin type or subsystem - handle it seperately.
     if ($module = $this->get_moodle_path_metadata(get_component_directory('core'))) {
         $moodlemodules = array_merge($moodlemodules, $module);
     }
     // Handle other core subsystems.
     $subsystems = get_core_subsystems();
     foreach ($subsystems as $subsystem => $path) {
         if (is_null($path)) {
             continue;
         }
         $path = get_component_directory($subsystem);
         if ($module = $this->get_moodle_path_metadata($path)) {
             $moodlemodules = array_merge($moodlemodules, $module);
         }
     }
     // And finally the plugins.
     $plugintypes = get_plugin_types();
     foreach ($plugintypes as $plugintype => $pathroot) {
         $pluginlist = get_plugin_list($plugintype);
         foreach ($pluginlist as $plugin => $path) {
             if ($module = $this->get_moodle_path_metadata($path)) {
                 $moodlemodules = array_merge($moodlemodules, $module);
             }
         }
     }
     return $moodlemodules;
 }
 /**
  * Find out if JS module present and return details.
  * @param string $component name of component in frankenstyle, ex: core_group, mod_forum
  * @return array description of module or null if not found
  */
 protected function find_module($component)
 {
     global $CFG;
     $module = null;
     if (strpos($component, 'core_') === 0) {
         // must be some core stuff - list here is not complete, this is just the stuff used from multiple places
         // so that we do nto have to repeat the definition of these modules over and over again
         switch ($component) {
             case 'core_filepicker':
                 $module = array('name' => 'core_filepicker', 'fullpath' => '/repository/filepicker.js', 'requires' => array('base', 'node', 'node-event-simulate', 'json', 'async-queue', 'io', 'yui2-button', 'yui2-container', 'yui2-layout', 'yui2-menu', 'yui2-treeview', 'yui2-dragdrop', 'yui2-cookie'), 'strings' => array(array('add', 'repository'), array('back', 'repository'), array('cancel', 'moodle'), array('close', 'repository'), array('cleancache', 'repository'), array('copying', 'repository'), array('date', 'repository'), array('downloadsucc', 'repository'), array('emptylist', 'repository'), array('error', 'repository'), array('federatedsearch', 'repository'), array('filenotnull', 'repository'), array('getfile', 'repository'), array('help', 'moodle'), array('iconview', 'repository'), array('invalidjson', 'repository'), array('linkexternal', 'repository'), array('listview', 'repository'), array('loading', 'repository'), array('login', 'repository'), array('logout', 'repository'), array('noenter', 'repository'), array('noresult', 'repository'), array('manageurl', 'repository'), array('popup', 'repository'), array('preview', 'repository'), array('refresh', 'repository'), array('save', 'repository'), array('saveas', 'repository'), array('saved', 'repository'), array('saving', 'repository'), array('search', 'repository'), array('searching', 'repository'), array('size', 'repository'), array('submit', 'repository'), array('sync', 'repository'), array('title', 'repository'), array('upload', 'repository'), array('uploading', 'repository'), array('xhtmlerror', 'repository'), array('cancel'), array('chooselicense', 'repository'), array('author', 'repository'), array('ok', 'moodle'), array('error', 'moodle'), array('info', 'moodle'), array('norepositoriesavailable', 'repository'), array('norepositoriesexternalavailable', 'repository'), array('nofilesattached', 'repository'), array('filepicker', 'repository'), array('nofilesavailable', 'repository'), array('overwrite', 'repository'), array('renameto', 'repository'), array('fileexists', 'repository'), array('fileexistsdialogheader', 'repository'), array('fileexistsdialog_editor', 'repository'), array('fileexistsdialog_filemanager', 'repository')));
                 break;
             case 'core_comment':
                 $module = array('name' => 'core_comment', 'fullpath' => '/comment/comment.js', 'requires' => array('base', 'io', 'node', 'json', 'yui2-animation', 'overlay'), 'strings' => array(array('confirmdeletecomments', 'admin'), array('yes', 'moodle'), array('no', 'moodle')));
                 break;
             case 'core_role':
                 $module = array('name' => 'core_role', 'fullpath' => '/admin/roles/module.js', 'requires' => array('node', 'cookie'));
                 break;
             case 'core_completion':
                 $module = array('name' => 'core_completion', 'fullpath' => '/course/completion.js');
                 break;
             case 'core_dock':
                 $module = array('name' => 'core_dock', 'fullpath' => '/blocks/dock.js', 'requires' => array('base', 'node', 'event-custom', 'event-mouseenter', 'event-resize'), 'strings' => array(array('addtodock', 'block'), array('undockitem', 'block'), array('undockall', 'block'), array('thisdirectionvertical', 'langconfig')));
                 break;
             case 'core_message':
                 $module = array('name' => 'core_message', 'requires' => array('base', 'node', 'event', 'node-event-simulate'), 'fullpath' => '/message/module.js');
                 break;
             case 'core_group':
                 $module = array('name' => 'core_group', 'fullpath' => '/group/module.js', 'requires' => array('node', 'overlay', 'event-mouseenter'));
                 break;
             case 'core_question_engine':
                 $module = array('name' => 'core_question_engine', 'fullpath' => '/question/qengine.js', 'requires' => array('node', 'event'));
                 break;
             case 'core_rating':
                 $module = array('name' => 'core_rating', 'fullpath' => '/rating/module.js', 'requires' => array('node', 'event', 'overlay', 'io', 'json'));
                 break;
             case 'core_filetree':
                 $module = array('name' => 'core_filetree', 'fullpath' => '/files/module.js', 'requires' => array('node', 'event', 'overlay', 'io', 'json', 'yui2-treeview'));
                 break;
         }
     } else {
         if ($dir = get_component_directory($component)) {
             if (file_exists("{$dir}/module.js")) {
                 if (strpos($dir, $CFG->dirroot . '/') === 0) {
                     $dir = substr($dir, strlen($CFG->dirroot));
                     $module = array('name' => $component, 'fullpath' => "{$dir}/module.js", 'requires' => array());
                 }
             }
         }
     }
     return $module;
 }
Beispiel #9
0
/**
 * Loads the messages definitions for a component from file
 *
 * If no messages are defined for the component, return an empty array.
 * This is an internal function used within messagelib.php
 *
 * @see message_update_providers()
 * @see message_update_processors()
 * @param string $component A moodle component like 'moodle', 'mod_forum', 'block_quiz_results'
 * @return array An array of message providers or empty array if not exists
 */
function message_get_providers_from_file($component) {
    $defpath = get_component_directory($component).'/db/messages.php';

    $messageproviders = array();

    if (file_exists($defpath)) {
        require($defpath);
    }

    foreach ($messageproviders as $name => $messageprovider) {   // Fix up missing values if required
        if (empty($messageprovider['capability'])) {
            $messageproviders[$name]['capability'] = NULL;
        }
        if (empty($messageprovider['defaults'])) {
            $messageproviders[$name]['defaults'] = array();
        }
    }

    return $messageproviders;
}
Beispiel #10
0
                 } else {
                     $birecord = null;
                 }
                 $filefunction = $component . '_pluginfile';
                 if (function_exists($filefunction)) {
                     // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
                     $filefunction($course, $birecord, $context, $filearea, $args, $forcedownload);
                 }
                 send_file_not_found();
             } else {
                 if (strpos($component, '_') === false) {
                     // all core subsystems have to be specified above, no more guessing here!
                     send_file_not_found();
                 } else {
                     // try to serve general plugin file in arbitrary context
                     $dir = get_component_directory($component);
                     if (!file_exists("{$dir}/lib.php")) {
                         send_file_not_found();
                     }
                     include_once "{$dir}/lib.php";
                     $filefunction = $component . '_pluginfile';
                     if (function_exists($filefunction)) {
                         // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
                         $filefunction($course, $cm, $context, $filearea, $args, $forcedownload);
                     }
                     send_file_not_found();
                 }
             }
         }
     }
 }
Beispiel #11
0
    /**
     * Return user information including profile picture + basic site information
     * Note:
     * - no capability checking because we return only known information about logged user
     *
     * @param array $serviceshortnames - DEPRECATED PARAMETER - values will be ignored -
     * it was an original design error, we keep for backward compatibility.
     * @return array site info
     * @since Moodle 2.2
     */
    public static function get_site_info($serviceshortnames = array()) {
        global $USER, $SITE, $CFG, $DB;

        $params = self::validate_parameters(self::get_site_info_parameters(),
                      array('serviceshortnames'=>$serviceshortnames));

        $profileimageurl = moodle_url::make_pluginfile_url(
                context_user::instance($USER->id)->id, 'user', 'icon', null, '/', 'f1');

        // Site information.
        $siteinfo =  array(
            'sitename' => $SITE->fullname,
            'siteurl' => $CFG->wwwroot,
            'username' => $USER->username,
            'firstname' => $USER->firstname,
            'lastname' => $USER->lastname,
            'fullname' => fullname($USER),
            'userid' => $USER->id,
            'userpictureurl' => $profileimageurl->out(false)
        );

        // Retrieve the service and functions from the web service linked to the token
        // If you call this function directly from external (not a web service call),
        // then it will still return site info without information about a service
        // Note: wsusername/wspassword ws authentication is not supported.
        $functions = array();
        if ($CFG->enablewebservices) { // No need to check token if web service are disabled and not a ws call.
            $token = optional_param('wstoken', '', PARAM_ALPHANUM);

            if (!empty($token)) { // No need to run if not a ws call.
                // Retrieve service shortname.
                $servicesql = 'SELECT s.*
                               FROM {external_services} s, {external_tokens} t
                               WHERE t.externalserviceid = s.id AND token = ? AND t.userid = ? AND s.enabled = 1';
                $service = $DB->get_record_sql($servicesql, array($token, $USER->id));

                $siteinfo['downloadfiles'] = $service->downloadfiles;

                if (!empty($service)) {
                    // Return the release and version number for web service users only.
                    $siteinfo['release'] = $CFG->release;
                    $siteinfo['version'] = $CFG->version;
                    // Retrieve the functions.
                    $functionssql = "SELECT f.*
                            FROM {external_functions} f, {external_services_functions} sf
                            WHERE f.name = sf.functionname AND sf.externalserviceid = ?";
                    $functions = $DB->get_records_sql($functionssql, array($service->id));
                } else {
                    throw new coding_exception('No service found in get_site_info: something is buggy, \
                                                it should have fail at the ws server authentication layer.');
                }
            }
        }

        // Build up the returned values of the list of functions.
        $componentversions = array();
        $availablefunctions = array();
        foreach ($functions as $function) {
            $functioninfo = array();
            $functioninfo['name'] = $function->name;
            if ($function->component == 'moodle' || $function->component == 'core') {
                $version = $CFG->version; // Moodle version.
            } else {
                $versionpath = get_component_directory($function->component).'/version.php';
                if (is_readable($versionpath)) {
                    // We store the component version once retrieved (so we don't load twice the version.php).
                    if (!isset($componentversions[$function->component])) {
                        include($versionpath);
                        $componentversions[$function->component] = $plugin->version;
                        $version = $plugin->version;
                    } else {
                        $version = $componentversions[$function->component];
                    }
                } else {
                    // Function component should always have a version.php,
                    // otherwise the function should have been described with component => 'moodle'.
                    throw new moodle_exception('missingversionfile', 'webservice', '', $function->component);
                }
            }
            $functioninfo['version'] = $version;
            $availablefunctions[] = $functioninfo;
        }

        $siteinfo['functions'] = $availablefunctions;

        return $siteinfo;
    }
Beispiel #12
0
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);
    }
Beispiel #13
0
/**
* Function to require any potential callback files, throwing exceptions
* if an issue occurs.
*
* @param string $callbackfile This is the location of the callback file '/mod/forum/locallib.php'
* @param string $class Name of the class containing the callback functions
* activity components should ALWAYS use their name_portfolio_caller
* other locations must use something unique
*/
function portfolio_include_callback_file($callbackfile, $class = null) {
    global $CFG;
    require_once($CFG->libdir . '/adminlib.php');

    // Get the last occurrence of '/' in the file path.
    $pos = strrpos($callbackfile, '/');
    // Get rid of the first slash (if it exists).
    $callbackfile = ltrim($callbackfile, '/');
    // Get a list of valid plugin types.
    $plugintypes = get_plugin_types(false);
    // Assume it is not valid for now.
    $isvalid = false;
    // Go through the plugin types.
    foreach ($plugintypes as $type => $path) {
        if (strrpos($callbackfile, $path) === 0) {
            // Found the plugin type.
            $isvalid = true;
            $plugintype = $type;
            $pluginpath = $path;
        }
    }
    // Throw exception if not a valid component.
    if (!$isvalid) {
        throw new coding_exception('Somehow a non-valid plugin path was passed, could be a hackz0r attempt, exiting.');
    }
    // Keep record of the filename.
    $filename = substr($callbackfile, $pos);
    // Remove the file name.
    $component = trim(substr($callbackfile, 0, $pos), '/');
    // Replace the path with the type.
    $component = str_replace($pluginpath, $plugintype, $component);
    // Ok, replace '/' with '_'.
    $component = str_replace('/', '_', $component);
    // Check that it is a valid component.
    if (!get_component_version($component)) {
        throw new portfolio_button_exception('nocallbackcomponent', 'portfolio', '', $component);
    }

    // Obtain the component's location.
    if (!$componentloc = get_component_directory($component)) {
        throw new portfolio_button_exception('nocallbackcomponent', 'portfolio', '', $component);
    }

    // Check if the filename does not meet any of the expected names.
    if (($filename != 'locallib.php') && ($filename != 'portfoliolib.php') && ($filename != 'portfolio_callback.php')) {
        debugging('Please standardise your plugin by keeping your portfolio callback functionality in the file locallib.php.', DEBUG_DEVELOPER);
    }

    // Throw error if file does not exist.
    if (!file_exists($componentloc . '/' . $filename)) {
        throw new portfolio_button_exception('nocallbackfile', 'portfolio', '', $callbackfile);
    }

    require_once($componentloc . '/' . $filename);

    if (!is_null($class) && !class_exists($class)) {
        throw new portfolio_button_exception('nocallbackclass', 'portfolio', '', $class);
    }
}
/**
 * Called by pluginfile.php to serve files related to the 'question' core
 * component and for files belonging to qtypes.
 *
 * For files that relate to questions in a question_attempt, then we delegate to
 * a function in the component that owns the attempt (for example in the quiz,
 * or in core question preview) to get necessary inforation.
 *
 * (Note that, at the moment, all question file areas relate to questions in
 * attempts, so the If at the start of the last paragraph is always true.)
 *
 * Does not return, either calls send_file_not_found(); or serves the file.
 *
 * @package  core_question
 * @category files
 * @param stdClass $course course settings object
 * @param stdClass $context context object
 * @param string $component the name of the component we are serving files for.
 * @param string $filearea the name of the file area.
 * @param array $args the remaining bits of the file path.
 * @param bool $forcedownload whether the user must be forced to download the file.
 * @param array $options additional options affecting the file serving
 */
function question_pluginfile($course, $context, $component, $filearea, $args, $forcedownload, array $options = array())
{
    global $DB, $CFG;
    if ($filearea === 'questiontext_preview') {
        $component = array_shift($args);
        $questionid = array_shift($args);
        component_callback($component, 'questiontext_preview_pluginfile', array($context, $questionid, $args, $forcedownload, $options));
        send_file_not_found();
    }
    if ($filearea === 'export') {
        list($context, $course, $cm) = get_context_info_array($context->id);
        require_login($course, false, $cm);
        require_once $CFG->dirroot . '/question/editlib.php';
        $contexts = new question_edit_contexts($context);
        // check export capability
        $contexts->require_one_edit_tab_cap('export');
        $category_id = (int) array_shift($args);
        $format = array_shift($args);
        $cattofile = array_shift($args);
        $contexttofile = array_shift($args);
        $filename = array_shift($args);
        // load parent class for import/export
        require_once $CFG->dirroot . '/question/format.php';
        require_once $CFG->dirroot . '/question/editlib.php';
        require_once $CFG->dirroot . '/question/format/' . $format . '/format.php';
        $classname = 'qformat_' . $format;
        if (!class_exists($classname)) {
            send_file_not_found();
        }
        $qformat = new $classname();
        if (!($category = $DB->get_record('question_categories', array('id' => $category_id)))) {
            send_file_not_found();
        }
        $qformat->setCategory($category);
        $qformat->setContexts($contexts->having_one_edit_tab_cap('export'));
        $qformat->setCourse($course);
        if ($cattofile == 'withcategories') {
            $qformat->setCattofile(true);
        } else {
            $qformat->setCattofile(false);
        }
        if ($contexttofile == 'withcontexts') {
            $qformat->setContexttofile(true);
        } else {
            $qformat->setContexttofile(false);
        }
        if (!$qformat->exportpreprocess()) {
            send_file_not_found();
            print_error('exporterror', 'question', $thispageurl->out());
        }
        // export data to moodle file pool
        if (!($content = $qformat->exportprocess(true))) {
            send_file_not_found();
        }
        send_file($content, $filename, 0, 0, true, true, $qformat->mime_type());
    }
    $qubaid = (int) array_shift($args);
    $slot = (int) array_shift($args);
    $module = $DB->get_field('question_usages', 'component', array('id' => $qubaid));
    if ($module === 'core_question_preview') {
        require_once $CFG->dirroot . '/question/previewlib.php';
        return question_preview_question_pluginfile($course, $context, $component, $filearea, $qubaid, $slot, $args, $forcedownload, $options);
    } else {
        $dir = get_component_directory($module);
        if (!file_exists("{$dir}/lib.php")) {
            send_file_not_found();
        }
        include_once "{$dir}/lib.php";
        $filefunction = $module . '_question_pluginfile';
        if (function_exists($filefunction)) {
            $filefunction($course, $context, $component, $filearea, $qubaid, $slot, $args, $forcedownload, $options);
        }
        // Okay, we're here so lets check for function without 'mod_'.
        if (strpos($module, 'mod_') === 0) {
            $filefunctionold = substr($module, 4) . '_question_pluginfile';
            if (function_exists($filefunctionold)) {
                $filefunctionold($course, $context, $component, $filearea, $qubaid, $slot, $args, $forcedownload, $options);
            }
        }
        send_file_not_found();
    }
}
Beispiel #15
0
/**
 * Web service discovery function used during install and upgrade.
 * @param string $component name of component (moodle, mod_assignment, etc.)
 * @return void
 */
function external_update_descriptions($component)
{
    global $DB;
    $defpath = get_component_directory($component) . '/db/services.php';
    if (!file_exists($defpath)) {
        external_delete_descriptions($component);
        return;
    }
    // load new info
    $functions = array();
    $services = array();
    include $defpath;
    // update all function fist
    $dbfunctions = $DB->get_records('external_functions', array('component' => $component));
    foreach ($dbfunctions as $dbfunction) {
        if (empty($functions[$dbfunction->name])) {
            $DB->delete_records('external_functions', array('id' => $dbfunction->id));
            // do not delete functions from external_services_functions, beacuse
            // we want to notify admins when functions used in custom services disappear
            //TODO: this looks wrong, we have to delete it eventually (skodak)
            continue;
        }
        $function = $functions[$dbfunction->name];
        unset($functions[$dbfunction->name]);
        $function['classpath'] = empty($function['classpath']) ? null : $function['classpath'];
        $update = false;
        if ($dbfunction->classname != $function['classname']) {
            $dbfunction->classname = $function['classname'];
            $update = true;
        }
        if ($dbfunction->methodname != $function['methodname']) {
            $dbfunction->methodname = $function['methodname'];
            $update = true;
        }
        if ($dbfunction->classpath != $function['classpath']) {
            $dbfunction->classpath = $function['classpath'];
            $update = true;
        }
        $functioncapabilities = key_exists('capabilities', $function) ? $function['capabilities'] : '';
        if ($dbfunction->capabilities != $functioncapabilities) {
            $dbfunction->capabilities = $functioncapabilities;
            $update = true;
        }
        if ($update) {
            $DB->update_record('external_functions', $dbfunction);
        }
    }
    foreach ($functions as $fname => $function) {
        $dbfunction = new stdClass();
        $dbfunction->name = $fname;
        $dbfunction->classname = $function['classname'];
        $dbfunction->methodname = $function['methodname'];
        $dbfunction->classpath = empty($function['classpath']) ? null : $function['classpath'];
        $dbfunction->component = $component;
        $dbfunction->capabilities = key_exists('capabilities', $function) ? $function['capabilities'] : '';
        $dbfunction->id = $DB->insert_record('external_functions', $dbfunction);
    }
    unset($functions);
    // now deal with services
    $dbservices = $DB->get_records('external_services', array('component' => $component));
    foreach ($dbservices as $dbservice) {
        if (empty($services[$dbservice->name])) {
            $DB->delete_records('external_services_functions', array('externalserviceid' => $dbservice->id));
            $DB->delete_records('external_services_users', array('externalserviceid' => $dbservice->id));
            $DB->delete_records('external_services', array('id' => $dbservice->id));
            continue;
        }
        $service = $services[$dbservice->name];
        unset($services[$dbservice->name]);
        $service['enabled'] = empty($service['enabled']) ? 0 : $service['enabled'];
        $service['requiredcapability'] = empty($service['requiredcapability']) ? null : $service['requiredcapability'];
        $service['restrictedusers'] = !isset($service['restrictedusers']) ? 1 : $service['restrictedusers'];
        $update = false;
        if ($dbservice->enabled != $service['enabled']) {
            $dbservice->enabled = $service['enabled'];
            $update = true;
        }
        if ($dbservice->requiredcapability != $service['requiredcapability']) {
            $dbservice->requiredcapability = $service['requiredcapability'];
            $update = true;
        }
        if ($dbservice->restrictedusers != $service['restrictedusers']) {
            $dbservice->restrictedusers = $service['restrictedusers'];
            $update = true;
        }
        if ($update) {
            $DB->update_record('external_services', $dbservice);
        }
        $functions = $DB->get_records('external_services_functions', array('externalserviceid' => $dbservice->id));
        foreach ($functions as $function) {
            $key = array_search($function->functionname, $service['functions']);
            if ($key === false) {
                $DB->delete_records('external_services_functions', array('id' => $function->id));
            } else {
                unset($service['functions'][$key]);
            }
        }
        foreach ($service['functions'] as $fname) {
            $newf = new stdClass();
            $newf->externalserviceid = $dbservice->id;
            $newf->functionname = $fname;
            $DB->insert_record('external_services_functions', $newf);
        }
        unset($functions);
    }
    foreach ($services as $name => $service) {
        $dbservice = new stdClass();
        $dbservice->name = $name;
        $dbservice->enabled = empty($service['enabled']) ? 0 : $service['enabled'];
        $dbservice->requiredcapability = empty($service['requiredcapability']) ? null : $service['requiredcapability'];
        $dbservice->restrictedusers = !isset($service['restrictedusers']) ? 1 : $service['restrictedusers'];
        $dbservice->component = $component;
        $dbservice->timecreated = time();
        $dbservice->id = $DB->insert_record('external_services', $dbservice);
        foreach ($service['functions'] as $fname) {
            $newf = new stdClass();
            $newf->externalserviceid = $dbservice->id;
            $newf->functionname = $fname;
            $DB->insert_record('external_services_functions', $newf);
        }
    }
}
Beispiel #16
0
/**
 * invoke plugin's callback functions
 *
 * @param string $type Plugin type e.g. 'mod'
 * @param string $name Plugin name
 * @param string $feature Feature code (FEATURE_xx constant)
 * @param string $action Feature's action
 * @param string $options parameters of callback function, should be an array
 * @param mixed $default default value if callback function hasn't been defined
 * @return mixed
 */
function plugin_callback($type, $name, $feature, $action, $options = null, $default=null) {
    global $CFG;

    $name = clean_param($name, PARAM_SAFEDIR);
    $function = $name.'_'.$feature.'_'.$action;
    $file = get_component_directory($type . '_' . $name) . '/lib.php';

    // Load library and look for function
    if (file_exists($file)) {
        require_once($file);
    }
    if (function_exists($function)) {
        // Function exists, so just return function result
        $ret = call_user_func_array($function, (array)$options);
        if (is_null($ret)) {
            return $default;
        } else {
            return $ret;
        }
    }
    return $default;
}
Beispiel #17
0
/**
 * This function delegates file serving to individual plugins
 *
 * @param string $relativepath
 * @param bool $forcedownload
 * @param null|string $preview the preview mode, defaults to serving the original file
 * @todo MDL-31088 file serving improments
 */
function file_pluginfile($relativepath, $forcedownload, $preview = null)
{
    global $DB, $CFG, $USER;
    // relative path must start with '/'
    if (!$relativepath) {
        print_error('invalidargorconf');
    } else {
        if ($relativepath[0] != '/') {
            print_error('pathdoesnotstartslash');
        }
    }
    // extract relative path components
    $args = explode('/', ltrim($relativepath, '/'));
    if (count($args) < 3) {
        // always at least context, component and filearea
        print_error('invalidarguments');
    }
    $contextid = (int) array_shift($args);
    $component = clean_param(array_shift($args), PARAM_COMPONENT);
    $filearea = clean_param(array_shift($args), PARAM_AREA);
    list($context, $course, $cm) = get_context_info_array($contextid);
    $fs = get_file_storage();
    // ========================================================================================================================
    if ($component === 'blog') {
        // Blog file serving
        if ($context->contextlevel != CONTEXT_SYSTEM) {
            send_file_not_found();
        }
        if ($filearea !== 'attachment' and $filearea !== 'post') {
            send_file_not_found();
        }
        if (empty($CFG->enableblogs)) {
            print_error('siteblogdisable', 'blog');
        }
        $entryid = (int) array_shift($args);
        if (!($entry = $DB->get_record('post', array('module' => 'blog', 'id' => $entryid)))) {
            send_file_not_found();
        }
        if ($CFG->bloglevel < BLOG_GLOBAL_LEVEL) {
            require_login();
            if (isguestuser()) {
                print_error('noguest');
            }
            if ($CFG->bloglevel == BLOG_USER_LEVEL) {
                if ($USER->id != $entry->userid) {
                    send_file_not_found();
                }
            }
        }
        if ($entry->publishstate === 'public') {
            if ($CFG->forcelogin) {
                require_login();
            }
        } else {
            if ($entry->publishstate === 'site') {
                require_login();
                //ok
            } else {
                if ($entry->publishstate === 'draft') {
                    require_login();
                    if ($USER->id != $entry->userid) {
                        send_file_not_found();
                    }
                }
            }
        }
        $filename = array_pop($args);
        $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
        if (!($file = $fs->get_file($context->id, $component, $filearea, $entryid, $filepath, $filename)) or $file->is_directory()) {
            send_file_not_found();
        }
        send_stored_file($file, 10 * 60, 0, true, array('preview' => $preview));
        // download MUST be forced - security!
        // ========================================================================================================================
    } else {
        if ($component === 'grade') {
            if (($filearea === 'outcome' or $filearea === 'scale') and $context->contextlevel == CONTEXT_SYSTEM) {
                // Global gradebook files
                if ($CFG->forcelogin) {
                    require_login();
                }
                $fullpath = "/{$context->id}/{$component}/{$filearea}/" . implode('/', $args);
                if (!($file = $fs->get_file_by_hash(sha1($fullpath))) or $file->is_directory()) {
                    send_file_not_found();
                }
                session_get_instance()->write_close();
                // unlock session during fileserving
                send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
            } else {
                if ($filearea === 'feedback' and $context->contextlevel == CONTEXT_COURSE) {
                    //TODO: nobody implemented this yet in grade edit form!!
                    send_file_not_found();
                    if ($CFG->forcelogin || $course->id != SITEID) {
                        require_login($course);
                    }
                    $fullpath = "/{$context->id}/{$component}/{$filearea}/" . implode('/', $args);
                    if (!($file = $fs->get_file_by_hash(sha1($fullpath))) or $file->is_directory()) {
                        send_file_not_found();
                    }
                    session_get_instance()->write_close();
                    // unlock session during fileserving
                    send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
                } else {
                    send_file_not_found();
                }
            }
            // ========================================================================================================================
        } else {
            if ($component === 'tag') {
                if ($filearea === 'description' and $context->contextlevel == CONTEXT_SYSTEM) {
                    // All tag descriptions are going to be public but we still need to respect forcelogin
                    if ($CFG->forcelogin) {
                        require_login();
                    }
                    $fullpath = "/{$context->id}/tag/description/" . implode('/', $args);
                    if (!($file = $fs->get_file_by_hash(sha1($fullpath))) or $file->is_directory()) {
                        send_file_not_found();
                    }
                    session_get_instance()->write_close();
                    // unlock session during fileserving
                    send_stored_file($file, 60 * 60, 0, true, array('preview' => $preview));
                } else {
                    send_file_not_found();
                }
                // ========================================================================================================================
            } else {
                if ($component === 'calendar') {
                    if ($filearea === 'event_description' and $context->contextlevel == CONTEXT_SYSTEM) {
                        // All events here are public the one requirement is that we respect forcelogin
                        if ($CFG->forcelogin) {
                            require_login();
                        }
                        // Get the event if from the args array
                        $eventid = array_shift($args);
                        // Load the event from the database
                        if (!($event = $DB->get_record('event', array('id' => (int) $eventid, 'eventtype' => 'site')))) {
                            send_file_not_found();
                        }
                        // Check that we got an event and that it's userid is that of the user
                        // Get the file and serve if successful
                        $filename = array_pop($args);
                        $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                        if (!($file = $fs->get_file($context->id, $component, $filearea, $eventid, $filepath, $filename)) or $file->is_directory()) {
                            send_file_not_found();
                        }
                        session_get_instance()->write_close();
                        // unlock session during fileserving
                        send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
                    } else {
                        if ($filearea === 'event_description' and $context->contextlevel == CONTEXT_USER) {
                            // Must be logged in, if they are not then they obviously can't be this user
                            require_login();
                            // Don't want guests here, potentially saves a DB call
                            if (isguestuser()) {
                                send_file_not_found();
                            }
                            // Get the event if from the args array
                            $eventid = array_shift($args);
                            // Load the event from the database - user id must match
                            if (!($event = $DB->get_record('event', array('id' => (int) $eventid, 'userid' => $USER->id, 'eventtype' => 'user')))) {
                                send_file_not_found();
                            }
                            // Get the file and serve if successful
                            $filename = array_pop($args);
                            $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                            if (!($file = $fs->get_file($context->id, $component, $filearea, $eventid, $filepath, $filename)) or $file->is_directory()) {
                                send_file_not_found();
                            }
                            session_get_instance()->write_close();
                            // unlock session during fileserving
                            send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
                        } else {
                            if ($filearea === 'event_description' and $context->contextlevel == CONTEXT_COURSE) {
                                // Respect forcelogin and require login unless this is the site.... it probably
                                // should NEVER be the site
                                if ($CFG->forcelogin || $course->id != SITEID) {
                                    require_login($course);
                                }
                                // Must be able to at least view the course
                                if (!is_enrolled($context) and !is_viewing($context)) {
                                    //TODO: hmm, do we really want to block guests here?
                                    send_file_not_found();
                                }
                                // Get the event id
                                $eventid = array_shift($args);
                                // Load the event from the database we need to check whether it is
                                // a) valid course event
                                // b) a group event
                                // Group events use the course context (there is no group context)
                                if (!($event = $DB->get_record('event', array('id' => (int) $eventid, 'courseid' => $course->id)))) {
                                    send_file_not_found();
                                }
                                // If its a group event require either membership of view all groups capability
                                if ($event->eventtype === 'group') {
                                    if (!has_capability('moodle/site:accessallgroups', $context) && !groups_is_member($event->groupid, $USER->id)) {
                                        send_file_not_found();
                                    }
                                } else {
                                    if ($event->eventtype === 'course') {
                                        //ok
                                    } else {
                                        // some other type
                                        send_file_not_found();
                                    }
                                }
                                // If we get this far we can serve the file
                                $filename = array_pop($args);
                                $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                if (!($file = $fs->get_file($context->id, $component, $filearea, $eventid, $filepath, $filename)) or $file->is_directory()) {
                                    send_file_not_found();
                                }
                                session_get_instance()->write_close();
                                // unlock session during fileserving
                                send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
                            } else {
                                send_file_not_found();
                            }
                        }
                    }
                    // ========================================================================================================================
                } else {
                    if ($component === 'user') {
                        if ($filearea === 'icon' and $context->contextlevel == CONTEXT_USER) {
                            if (count($args) == 1) {
                                $themename = theme_config::DEFAULT_THEME;
                                $filename = array_shift($args);
                            } else {
                                $themename = array_shift($args);
                                $filename = array_shift($args);
                            }
                            // fix file name automatically
                            if ($filename !== 'f1' and $filename !== 'f2' and $filename !== 'f3') {
                                $filename = 'f1';
                            }
                            if ((!empty($CFG->forcelogin) and !isloggedin()) || !empty($CFG->forceloginforprofileimage) && (!isloggedin() || isguestuser())) {
                                // protect images if login required and not logged in;
                                // also if login is required for profile images and is not logged in or guest
                                // do not use require_login() because it is expensive and not suitable here anyway
                                $theme = theme_config::load($themename);
                                redirect($theme->pix_url('u/' . $filename, 'moodle'));
                                // intentionally not cached
                            }
                            if (!($file = $fs->get_file($context->id, 'user', 'icon', 0, '/', $filename . '.png'))) {
                                if (!($file = $fs->get_file($context->id, 'user', 'icon', 0, '/', $filename . '.jpg'))) {
                                    if ($filename === 'f3') {
                                        // f3 512x512px was introduced in 2.3, there might be only the smaller version.
                                        if (!($file = $fs->get_file($context->id, 'user', 'icon', 0, '/', 'f1.png'))) {
                                            $file = $fs->get_file($context->id, 'user', 'icon', 0, '/', 'f1.jpg');
                                        }
                                    }
                                }
                            }
                            if (!$file) {
                                // bad reference - try to prevent future retries as hard as possible!
                                if ($user = $DB->get_record('user', array('id' => $context->instanceid), 'id, picture')) {
                                    if ($user->picture > 0) {
                                        $DB->set_field('user', 'picture', 0, array('id' => $user->id));
                                    }
                                }
                                // no redirect here because it is not cached
                                $theme = theme_config::load($themename);
                                $imagefile = $theme->resolve_image_location('u/' . $filename, 'moodle');
                                send_file($imagefile, basename($imagefile), 60 * 60 * 24 * 14);
                            }
                            send_stored_file($file, 60 * 60 * 24 * 365, 0, false, array('preview' => $preview));
                            // enable long caching, there are many images on each page
                        } else {
                            if ($filearea === 'private' and $context->contextlevel == CONTEXT_USER) {
                                require_login();
                                if (isguestuser()) {
                                    send_file_not_found();
                                }
                                if ($USER->id !== $context->instanceid) {
                                    send_file_not_found();
                                }
                                $filename = array_pop($args);
                                $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                if (!($file = $fs->get_file($context->id, $component, $filearea, 0, $filepath, $filename)) or $file->is_directory()) {
                                    send_file_not_found();
                                }
                                session_get_instance()->write_close();
                                // unlock session during fileserving
                                send_stored_file($file, 0, 0, true, array('preview' => $preview));
                                // must force download - security!
                            } else {
                                if ($filearea === 'profile' and $context->contextlevel == CONTEXT_USER) {
                                    if ($CFG->forcelogin) {
                                        require_login();
                                    }
                                    $userid = $context->instanceid;
                                    if ($USER->id == $userid) {
                                        // always can access own
                                    } else {
                                        if (!empty($CFG->forceloginforprofiles)) {
                                            require_login();
                                            if (isguestuser()) {
                                                send_file_not_found();
                                            }
                                            // we allow access to site profile of all course contacts (usually teachers)
                                            if (!has_coursecontact_role($userid) && !has_capability('moodle/user:viewdetails', $context)) {
                                                send_file_not_found();
                                            }
                                            $canview = false;
                                            if (has_capability('moodle/user:viewdetails', $context)) {
                                                $canview = true;
                                            } else {
                                                $courses = enrol_get_my_courses();
                                            }
                                            while (!$canview && count($courses) > 0) {
                                                $course = array_shift($courses);
                                                if (has_capability('moodle/user:viewdetails', context_course::instance($course->id))) {
                                                    $canview = true;
                                                }
                                            }
                                        }
                                    }
                                    $filename = array_pop($args);
                                    $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                    if (!($file = $fs->get_file($context->id, $component, $filearea, 0, $filepath, $filename)) or $file->is_directory()) {
                                        send_file_not_found();
                                    }
                                    session_get_instance()->write_close();
                                    // unlock session during fileserving
                                    send_stored_file($file, 0, 0, true, array('preview' => $preview));
                                    // must force download - security!
                                } else {
                                    if ($filearea === 'profile' and $context->contextlevel == CONTEXT_COURSE) {
                                        $userid = (int) array_shift($args);
                                        $usercontext = context_user::instance($userid);
                                        if ($CFG->forcelogin) {
                                            require_login();
                                        }
                                        if (!empty($CFG->forceloginforprofiles)) {
                                            require_login();
                                            if (isguestuser()) {
                                                print_error('noguest');
                                            }
                                            //TODO: review this logic of user profile access prevention
                                            if (!has_coursecontact_role($userid) and !has_capability('moodle/user:viewdetails', $usercontext)) {
                                                print_error('usernotavailable');
                                            }
                                            if (!has_capability('moodle/user:viewdetails', $context) && !has_capability('moodle/user:viewdetails', $usercontext)) {
                                                print_error('cannotviewprofile');
                                            }
                                            if (!is_enrolled($context, $userid)) {
                                                print_error('notenrolledprofile');
                                            }
                                            if (groups_get_course_groupmode($course) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
                                                print_error('groupnotamember');
                                            }
                                        }
                                        $filename = array_pop($args);
                                        $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                        if (!($file = $fs->get_file($usercontext->id, 'user', 'profile', 0, $filepath, $filename)) or $file->is_directory()) {
                                            send_file_not_found();
                                        }
                                        session_get_instance()->write_close();
                                        // unlock session during fileserving
                                        send_stored_file($file, 0, 0, true, array('preview' => $preview));
                                        // must force download - security!
                                    } else {
                                        if ($filearea === 'backup' and $context->contextlevel == CONTEXT_USER) {
                                            require_login();
                                            if (isguestuser()) {
                                                send_file_not_found();
                                            }
                                            $userid = $context->instanceid;
                                            if ($USER->id != $userid) {
                                                send_file_not_found();
                                            }
                                            $filename = array_pop($args);
                                            $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                            if (!($file = $fs->get_file($context->id, 'user', 'backup', 0, $filepath, $filename)) or $file->is_directory()) {
                                                send_file_not_found();
                                            }
                                            session_get_instance()->write_close();
                                            // unlock session during fileserving
                                            send_stored_file($file, 0, 0, true, array('preview' => $preview));
                                            // must force download - security!
                                        } else {
                                            send_file_not_found();
                                        }
                                    }
                                }
                            }
                        }
                        // ========================================================================================================================
                    } else {
                        if ($component === 'coursecat') {
                            if ($context->contextlevel != CONTEXT_COURSECAT) {
                                send_file_not_found();
                            }
                            if ($filearea === 'description') {
                                if ($CFG->forcelogin) {
                                    // no login necessary - unless login forced everywhere
                                    require_login();
                                }
                                $filename = array_pop($args);
                                $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                if (!($file = $fs->get_file($context->id, 'coursecat', 'description', 0, $filepath, $filename)) or $file->is_directory()) {
                                    send_file_not_found();
                                }
                                session_get_instance()->write_close();
                                // unlock session during fileserving
                                send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
                            } else {
                                send_file_not_found();
                            }
                            // ========================================================================================================================
                        } else {
                            if ($component === 'course') {
                                if ($context->contextlevel != CONTEXT_COURSE) {
                                    send_file_not_found();
                                }
                                if ($filearea === 'summary') {
                                    if ($CFG->forcelogin) {
                                        require_login();
                                    }
                                    $filename = array_pop($args);
                                    $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                    if (!($file = $fs->get_file($context->id, 'course', 'summary', 0, $filepath, $filename)) or $file->is_directory()) {
                                        send_file_not_found();
                                    }
                                    session_get_instance()->write_close();
                                    // unlock session during fileserving
                                    send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
                                } else {
                                    if ($filearea === 'section') {
                                        if ($CFG->forcelogin) {
                                            require_login($course);
                                        } else {
                                            if ($course->id != SITEID) {
                                                require_login($course);
                                            }
                                        }
                                        $sectionid = (int) array_shift($args);
                                        if (!($section = $DB->get_record('course_sections', array('id' => $sectionid, 'course' => $course->id)))) {
                                            send_file_not_found();
                                        }
                                        if ($course->numsections < $section->section) {
                                            if (!has_capability('moodle/course:update', $context)) {
                                                // block access to unavailable sections if can not edit course
                                                send_file_not_found();
                                            }
                                        }
                                        $filename = array_pop($args);
                                        $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                        if (!($file = $fs->get_file($context->id, 'course', 'section', $sectionid, $filepath, $filename)) or $file->is_directory()) {
                                            send_file_not_found();
                                        }
                                        session_get_instance()->write_close();
                                        // unlock session during fileserving
                                        send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
                                    } else {
                                        send_file_not_found();
                                    }
                                }
                            } else {
                                if ($component === 'group') {
                                    if ($context->contextlevel != CONTEXT_COURSE) {
                                        send_file_not_found();
                                    }
                                    require_course_login($course, true, null, false);
                                    $groupid = (int) array_shift($args);
                                    $group = $DB->get_record('groups', array('id' => $groupid, 'courseid' => $course->id), '*', MUST_EXIST);
                                    if ($course->groupmodeforce and $course->groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context) and !groups_is_member($group->id, $USER->id)) {
                                        // do not allow access to separate group info if not member or teacher
                                        send_file_not_found();
                                    }
                                    if ($filearea === 'description') {
                                        require_login($course);
                                        $filename = array_pop($args);
                                        $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                        if (!($file = $fs->get_file($context->id, 'group', 'description', $group->id, $filepath, $filename)) or $file->is_directory()) {
                                            send_file_not_found();
                                        }
                                        session_get_instance()->write_close();
                                        // unlock session during fileserving
                                        send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
                                    } else {
                                        if ($filearea === 'icon') {
                                            $filename = array_pop($args);
                                            if ($filename !== 'f1' and $filename !== 'f2') {
                                                send_file_not_found();
                                            }
                                            if (!($file = $fs->get_file($context->id, 'group', 'icon', $group->id, '/', $filename . '.png'))) {
                                                if (!($file = $fs->get_file($context->id, 'group', 'icon', $group->id, '/', $filename . '.jpg'))) {
                                                    send_file_not_found();
                                                }
                                            }
                                            session_get_instance()->write_close();
                                            // unlock session during fileserving
                                            send_stored_file($file, 60 * 60, 0, false, array('preview' => $preview));
                                        } else {
                                            send_file_not_found();
                                        }
                                    }
                                } else {
                                    if ($component === 'grouping') {
                                        if ($context->contextlevel != CONTEXT_COURSE) {
                                            send_file_not_found();
                                        }
                                        require_login($course);
                                        $groupingid = (int) array_shift($args);
                                        // note: everybody has access to grouping desc images for now
                                        if ($filearea === 'description') {
                                            $filename = array_pop($args);
                                            $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                            if (!($file = $fs->get_file($context->id, 'grouping', 'description', $groupingid, $filepath, $filename)) or $file->is_directory()) {
                                                send_file_not_found();
                                            }
                                            session_get_instance()->write_close();
                                            // unlock session during fileserving
                                            send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
                                        } else {
                                            send_file_not_found();
                                        }
                                        // ========================================================================================================================
                                    } else {
                                        if ($component === 'backup') {
                                            if ($filearea === 'course' and $context->contextlevel == CONTEXT_COURSE) {
                                                require_login($course);
                                                require_capability('moodle/backup:downloadfile', $context);
                                                $filename = array_pop($args);
                                                $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                                if (!($file = $fs->get_file($context->id, 'backup', 'course', 0, $filepath, $filename)) or $file->is_directory()) {
                                                    send_file_not_found();
                                                }
                                                session_get_instance()->write_close();
                                                // unlock session during fileserving
                                                send_stored_file($file, 0, 0, $forcedownload, array('preview' => $preview));
                                            } else {
                                                if ($filearea === 'section' and $context->contextlevel == CONTEXT_COURSE) {
                                                    require_login($course);
                                                    require_capability('moodle/backup:downloadfile', $context);
                                                    $sectionid = (int) array_shift($args);
                                                    $filename = array_pop($args);
                                                    $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                                    if (!($file = $fs->get_file($context->id, 'backup', 'section', $sectionid, $filepath, $filename)) or $file->is_directory()) {
                                                        send_file_not_found();
                                                    }
                                                    session_get_instance()->write_close();
                                                    send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
                                                } else {
                                                    if ($filearea === 'activity' and $context->contextlevel == CONTEXT_MODULE) {
                                                        require_login($course, false, $cm);
                                                        require_capability('moodle/backup:downloadfile', $context);
                                                        $filename = array_pop($args);
                                                        $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                                        if (!($file = $fs->get_file($context->id, 'backup', 'activity', 0, $filepath, $filename)) or $file->is_directory()) {
                                                            send_file_not_found();
                                                        }
                                                        session_get_instance()->write_close();
                                                        send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
                                                    } else {
                                                        if ($filearea === 'automated' and $context->contextlevel == CONTEXT_COURSE) {
                                                            // Backup files that were generated by the automated backup systems.
                                                            require_login($course);
                                                            require_capability('moodle/site:config', $context);
                                                            $filename = array_pop($args);
                                                            $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                                            if (!($file = $fs->get_file($context->id, 'backup', 'automated', 0, $filepath, $filename)) or $file->is_directory()) {
                                                                send_file_not_found();
                                                            }
                                                            session_get_instance()->write_close();
                                                            // unlock session during fileserving
                                                            send_stored_file($file, 0, 0, $forcedownload, array('preview' => $preview));
                                                        } else {
                                                            send_file_not_found();
                                                        }
                                                    }
                                                }
                                            }
                                            // ========================================================================================================================
                                        } else {
                                            if ($component === 'question') {
                                                require_once $CFG->libdir . '/questionlib.php';
                                                question_pluginfile($course, $context, 'question', $filearea, $args, $forcedownload);
                                                send_file_not_found();
                                                // ========================================================================================================================
                                            } else {
                                                if ($component === 'grading') {
                                                    if ($filearea === 'description') {
                                                        // files embedded into the form definition description
                                                        if ($context->contextlevel == CONTEXT_SYSTEM) {
                                                            require_login();
                                                        } else {
                                                            if ($context->contextlevel >= CONTEXT_COURSE) {
                                                                require_login($course, false, $cm);
                                                            } else {
                                                                send_file_not_found();
                                                            }
                                                        }
                                                        $formid = (int) array_shift($args);
                                                        $sql = "SELECT ga.id\n                FROM {grading_areas} ga\n                JOIN {grading_definitions} gd ON (gd.areaid = ga.id)\n                WHERE gd.id = ? AND ga.contextid = ?";
                                                        $areaid = $DB->get_field_sql($sql, array($formid, $context->id), IGNORE_MISSING);
                                                        if (!$areaid) {
                                                            send_file_not_found();
                                                        }
                                                        $fullpath = "/{$context->id}/{$component}/{$filearea}/{$formid}/" . implode('/', $args);
                                                        if (!($file = $fs->get_file_by_hash(sha1($fullpath))) or $file->is_directory()) {
                                                            send_file_not_found();
                                                        }
                                                        session_get_instance()->write_close();
                                                        // unlock session during fileserving
                                                        send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
                                                    }
                                                    // ========================================================================================================================
                                                } else {
                                                    if (strpos($component, 'mod_') === 0) {
                                                        $modname = substr($component, 4);
                                                        if (!file_exists("{$CFG->dirroot}/mod/{$modname}/lib.php")) {
                                                            send_file_not_found();
                                                        }
                                                        require_once "{$CFG->dirroot}/mod/{$modname}/lib.php";
                                                        if ($context->contextlevel == CONTEXT_MODULE) {
                                                            if ($cm->modname !== $modname) {
                                                                // somebody tries to gain illegal access, cm type must match the component!
                                                                send_file_not_found();
                                                            }
                                                        }
                                                        if ($filearea === 'intro') {
                                                            if (!plugin_supports('mod', $modname, FEATURE_MOD_INTRO, true)) {
                                                                send_file_not_found();
                                                            }
                                                            require_course_login($course, true, $cm);
                                                            // all users may access it
                                                            $filename = array_pop($args);
                                                            $filepath = $args ? '/' . implode('/', $args) . '/' : '/';
                                                            if (!($file = $fs->get_file($context->id, 'mod_' . $modname, 'intro', 0, $filepath, $filename)) or $file->is_directory()) {
                                                                send_file_not_found();
                                                            }
                                                            $lifetime = isset($CFG->filelifetime) ? $CFG->filelifetime : 86400;
                                                            // finally send the file
                                                            send_stored_file($file, $lifetime, 0, false, array('preview' => $preview));
                                                        }
                                                        $filefunction = $component . '_pluginfile';
                                                        $filefunctionold = $modname . '_pluginfile';
                                                        if (function_exists($filefunction)) {
                                                            // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
                                                            $filefunction($course, $cm, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
                                                        } else {
                                                            if (function_exists($filefunctionold)) {
                                                                // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
                                                                $filefunctionold($course, $cm, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
                                                            }
                                                        }
                                                        send_file_not_found();
                                                        // ========================================================================================================================
                                                    } else {
                                                        if (strpos($component, 'block_') === 0) {
                                                            $blockname = substr($component, 6);
                                                            // note: no more class methods in blocks please, that is ....
                                                            if (!file_exists("{$CFG->dirroot}/blocks/{$blockname}/lib.php")) {
                                                                send_file_not_found();
                                                            }
                                                            require_once "{$CFG->dirroot}/blocks/{$blockname}/lib.php";
                                                            if ($context->contextlevel == CONTEXT_BLOCK) {
                                                                $birecord = $DB->get_record('block_instances', array('id' => $context->instanceid), '*', MUST_EXIST);
                                                                if ($birecord->blockname !== $blockname) {
                                                                    // somebody tries to gain illegal access, cm type must match the component!
                                                                    send_file_not_found();
                                                                }
                                                                $bprecord = $DB->get_record('block_positions', array('blockinstanceid' => $context->instanceid), 'visible');
                                                                // User can't access file, if block is hidden or doesn't have block:view capability
                                                                if ($bprecord && !$bprecord->visible || !has_capability('moodle/block:view', $context)) {
                                                                    send_file_not_found();
                                                                }
                                                            } else {
                                                                $birecord = null;
                                                            }
                                                            $filefunction = $component . '_pluginfile';
                                                            if (function_exists($filefunction)) {
                                                                // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
                                                                $filefunction($course, $birecord, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
                                                            }
                                                            send_file_not_found();
                                                            // ========================================================================================================================
                                                        } else {
                                                            if (strpos($component, '_') === false) {
                                                                // all core subsystems have to be specified above, no more guessing here!
                                                                send_file_not_found();
                                                            } else {
                                                                // try to serve general plugin file in arbitrary context
                                                                $dir = get_component_directory($component);
                                                                if (!file_exists("{$dir}/lib.php")) {
                                                                    send_file_not_found();
                                                                }
                                                                include_once "{$dir}/lib.php";
                                                                $filefunction = $component . '_pluginfile';
                                                                if (function_exists($filefunction)) {
                                                                    // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
                                                                    $filefunction($course, $cm, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
                                                                }
                                                                send_file_not_found();
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
Beispiel #18
0
 /**
  * Assign roles
  *
  * This has to be called after enrolments processing.
  *
  * @param mixed $data
  * @return void
  */
 public function process_assignment($data)
 {
     global $DB;
     $data = (object) $data;
     // Check roleid, userid are one of the mapped ones
     if (!($newroleid = $this->get_mappingid('role', $data->roleid))) {
         return;
     }
     if (!($newuserid = $this->get_mappingid('user', $data->userid))) {
         return;
     }
     if (!$DB->record_exists('user', array('id' => $newuserid, 'deleted' => 0))) {
         // Only assign roles to not deleted users
         return;
     }
     if (!($contextid = $this->task->get_contextid())) {
         return;
     }
     if (empty($data->component)) {
         // assign standard manual roles
         // TODO: role_assign() needs one userid param to be able to specify our restore userid
         role_assign($newroleid, $newuserid, $contextid);
     } else {
         if (strpos($data->component, 'enrol_') === 0) {
             // Deal with enrolment roles - ignore the component and just find out the instance via new id,
             // it is possible that enrolment was restored using different plugin type.
             if (!isset($this->plugins)) {
                 $this->plugins = enrol_get_plugins(true);
             }
             if ($enrolid = $this->get_mappingid('enrol', $data->itemid)) {
                 if ($instance = $DB->get_record('enrol', array('id' => $enrolid))) {
                     if (isset($this->plugins[$instance->enrol])) {
                         $this->plugins[$instance->enrol]->restore_role_assignment($instance, $newroleid, $newuserid, $contextid);
                     }
                 }
             }
         } else {
             $data->roleid = $newroleid;
             $data->userid = $newuserid;
             $data->contextid = $contextid;
             $dir = get_component_directory($data->component);
             if ($dir and is_dir($dir)) {
                 if (component_callback($data->component, 'restore_role_assignment', array($this, $data), true)) {
                     return;
                 }
             }
             // Bad luck, plugin could not restore the data, let's add normal membership.
             role_assign($data->roleid, $data->userid, $data->contextid);
             $message = "Restore of '{$data->component}/{$data->itemid}' role assignments is not supported, using manual role assignments instead.";
             debugging($message);
             $this->log($message, backup::LOG_WARNING);
         }
     }
 }
Beispiel #19
0
 /**
  * Find out if JS module present and return details.
  *
  * @param string $component name of component in frankenstyle, ex: core_group, mod_forum
  * @return array description of module or null if not found
  */
 protected function find_module($component)
 {
     global $CFG, $PAGE;
     $module = null;
     if (strpos($component, 'core_') === 0) {
         // Must be some core stuff - list here is not complete, this is just the stuff used from multiple places
         // so that we do nto have to repeat the definition of these modules over and over again.
         switch ($component) {
             case 'core_filepicker':
                 $module = array('name' => 'core_filepicker', 'fullpath' => '/repository/filepicker.js', 'requires' => array('base', 'node', 'node-event-simulate', 'json', 'async-queue', 'io-base', 'io-upload-iframe', 'io-form', 'yui2-treeview', 'panel', 'cookie', 'datatable', 'datatable-sort', 'resize-plugin', 'dd-plugin', 'moodle-core_filepicker'), 'strings' => array(array('lastmodified', 'moodle'), array('name', 'moodle'), array('type', 'repository'), array('size', 'repository'), array('invalidjson', 'repository'), array('error', 'moodle'), array('info', 'moodle'), array('nofilesattached', 'repository'), array('filepicker', 'repository'), array('logout', 'repository'), array('nofilesavailable', 'repository'), array('norepositoriesavailable', 'repository'), array('fileexistsdialogheader', 'repository'), array('fileexistsdialog_editor', 'repository'), array('fileexistsdialog_filemanager', 'repository'), array('renameto', 'repository'), array('referencesexist', 'repository')));
                 break;
             case 'core_comment':
                 $module = array('name' => 'core_comment', 'fullpath' => '/comment/comment.js', 'requires' => array('base', 'io-base', 'node', 'json', 'yui2-animation', 'overlay'), 'strings' => array(array('confirmdeletecomments', 'admin'), array('yes', 'moodle'), array('no', 'moodle')));
                 break;
             case 'core_role':
                 $module = array('name' => 'core_role', 'fullpath' => '/admin/roles/module.js', 'requires' => array('node', 'cookie'));
                 break;
             case 'core_completion':
                 $module = array('name' => 'core_completion', 'fullpath' => '/course/completion.js');
                 break;
             case 'core_dock':
                 $module = array('name' => 'core_dock', 'fullpath' => '/blocks/dock.js', 'requires' => array('base', 'node', 'event-custom', 'event-mouseenter', 'event-resize'), 'strings' => array(array('addtodock', 'block'), array('undockitem', 'block'), array('undockall', 'block'), array('thisdirectionvertical', 'langconfig')));
                 break;
             case 'core_message':
                 $module = array('name' => 'core_message', 'requires' => array('base', 'node', 'event', 'node-event-simulate'), 'fullpath' => '/message/module.js');
                 break;
             case 'core_group':
                 $module = array('name' => 'core_group', 'fullpath' => '/group/module.js', 'requires' => array('node', 'overlay', 'event-mouseenter'));
                 break;
             case 'core_question_engine':
                 $module = array('name' => 'core_question_engine', 'fullpath' => '/question/qengine.js', 'requires' => array('node', 'event'));
                 break;
             case 'core_rating':
                 $module = array('name' => 'core_rating', 'fullpath' => '/rating/module.js', 'requires' => array('node', 'event', 'overlay', 'io-base', 'json'));
                 break;
             case 'core_dndupload':
                 $module = array('name' => 'core_dndupload', 'fullpath' => '/lib/form/dndupload.js', 'requires' => array('node', 'event', 'json', 'core_filepicker'), 'strings' => array(array('uploadformlimit', 'moodle'), array('droptoupload', 'moodle'), array('maxfilesreached', 'moodle'), array('dndenabled_inbox', 'moodle'), array('fileexists', 'moodle')));
                 break;
         }
     } else {
         if ($dir = get_component_directory($component)) {
             if (file_exists("{$dir}/module.js")) {
                 if (strpos($dir, $CFG->dirroot . '/') === 0) {
                     $dir = substr($dir, strlen($CFG->dirroot));
                     $module = array('name' => $component, 'fullpath' => "{$dir}/module.js", 'requires' => array());
                 }
             }
         }
     }
     return $module;
 }
Beispiel #20
0
    /**
     * 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];
    }
Beispiel #21
0
/**
 * Automatically clean-up all plugin data and remove the plugin DB tables
 *
 * @param string $type The plugin type, eg. 'mod', 'qtype', 'workshopgrading' etc.
 * @param string $name The plugin name, eg. 'forum', 'multichoice', 'accumulative' etc.
 * @uses global $OUTPUT to produce notices and other messages
 * @return void
 */
function uninstall_plugin($type, $name)
{
    global $CFG, $DB, $OUTPUT;
    // recursively uninstall all module/editor subplugins first
    if ($type === 'mod' || $type === 'editor') {
        $base = get_component_directory($type . '_' . $name);
        if (file_exists("{$base}/db/subplugins.php")) {
            $subplugins = array();
            include "{$base}/db/subplugins.php";
            foreach ($subplugins as $subplugintype => $dir) {
                $instances = get_plugin_list($subplugintype);
                foreach ($instances as $subpluginname => $notusedpluginpath) {
                    uninstall_plugin($subplugintype, $subpluginname);
                }
            }
        }
    }
    $component = $type . '_' . $name;
    // eg. 'qtype_multichoice' or 'workshopgrading_accumulative' or 'mod_forum'
    if ($type === 'mod') {
        $pluginname = $name;
        // eg. 'forum'
        if (get_string_manager()->string_exists('modulename', $component)) {
            $strpluginname = get_string('modulename', $component);
        } else {
            $strpluginname = $component;
        }
    } else {
        $pluginname = $component;
        if (get_string_manager()->string_exists('pluginname', $component)) {
            $strpluginname = get_string('pluginname', $component);
        } else {
            $strpluginname = $component;
        }
    }
    echo $OUTPUT->heading($pluginname);
    $plugindirectory = get_plugin_directory($type, $name);
    $uninstalllib = $plugindirectory . '/db/uninstall.php';
    if (file_exists($uninstalllib)) {
        require_once $uninstalllib;
        $uninstallfunction = 'xmldb_' . $pluginname . '_uninstall';
        // eg. 'xmldb_workshop_uninstall()'
        if (function_exists($uninstallfunction)) {
            if (!$uninstallfunction()) {
                echo $OUTPUT->notification('Encountered a problem running uninstall function for ' . $pluginname);
            }
        }
    }
    if ($type === 'mod') {
        // perform cleanup tasks specific for activity modules
        if (!($module = $DB->get_record('modules', array('name' => $name)))) {
            print_error('moduledoesnotexist', 'error');
        }
        // delete all the relevant instances from all course sections
        if ($coursemods = $DB->get_records('course_modules', array('module' => $module->id))) {
            foreach ($coursemods as $coursemod) {
                if (!delete_mod_from_section($coursemod->id, $coursemod->section)) {
                    echo $OUTPUT->notification("Could not delete the {$strpluginname} with id = {$coursemod->id} from section {$coursemod->section}");
                }
            }
        }
        // clear course.modinfo for courses that used this module
        $sql = "UPDATE {course}\n                   SET modinfo=''\n                 WHERE id IN (SELECT DISTINCT course\n                                FROM {course_modules}\n                               WHERE module=?)";
        $DB->execute($sql, array($module->id));
        // delete all the course module records
        $DB->delete_records('course_modules', array('module' => $module->id));
        // delete module contexts
        if ($coursemods) {
            foreach ($coursemods as $coursemod) {
                if (!delete_context(CONTEXT_MODULE, $coursemod->id)) {
                    echo $OUTPUT->notification("Could not delete the context for {$strpluginname} with id = {$coursemod->id}");
                }
            }
        }
        // delete the module entry itself
        $DB->delete_records('modules', array('name' => $module->name));
        // cleanup the gradebook
        require_once $CFG->libdir . '/gradelib.php';
        grade_uninstalled_module($module->name);
        // Perform any custom uninstall tasks
        if (file_exists($CFG->dirroot . '/mod/' . $module->name . '/lib.php')) {
            require_once $CFG->dirroot . '/mod/' . $module->name . '/lib.php';
            $uninstallfunction = $module->name . '_uninstall';
            if (function_exists($uninstallfunction)) {
                debugging("{$uninstallfunction}() has been deprecated. Use the plugin's db/uninstall.php instead", DEBUG_DEVELOPER);
                if (!$uninstallfunction()) {
                    echo $OUTPUT->notification('Encountered a problem running uninstall function for ' . $module->name . '!');
                }
            }
        }
    } else {
        if ($type === 'enrol') {
            // NOTE: this is a bit brute force way - it will not trigger events and hooks properly
            // nuke all role assignments
            role_unassign_all(array('component' => $component));
            // purge participants
            $DB->delete_records_select('user_enrolments', "enrolid IN (SELECT id FROM {enrol} WHERE enrol = ?)", array($name));
            // purge enrol instances
            $DB->delete_records('enrol', array('enrol' => $name));
            // tweak enrol settings
            if (!empty($CFG->enrol_plugins_enabled)) {
                $enabledenrols = explode(',', $CFG->enrol_plugins_enabled);
                $enabledenrols = array_unique($enabledenrols);
                $enabledenrols = array_flip($enabledenrols);
                unset($enabledenrols[$name]);
                $enabledenrols = array_flip($enabledenrols);
                if (is_array($enabledenrols)) {
                    set_config('enrol_plugins_enabled', implode(',', $enabledenrols));
                }
            }
        } else {
            if ($type === 'block') {
                if ($block = $DB->get_record('block', array('name' => $name))) {
                    // Inform block it's about to be deleted
                    if (file_exists("{$CFG->dirroot}/blocks/{$block->name}/block_{$block->name}.php")) {
                        $blockobject = block_instance($block->name);
                        if ($blockobject) {
                            $blockobject->before_delete();
                            //only if we can create instance, block might have been already removed
                        }
                    }
                    // First delete instances and related contexts
                    $instances = $DB->get_records('block_instances', array('blockname' => $block->name));
                    foreach ($instances as $instance) {
                        blocks_delete_instance($instance);
                    }
                    // Delete block
                    $DB->delete_records('block', array('id' => $block->id));
                }
            }
        }
    }
    // perform clean-up task common for all the plugin/subplugin types
    //delete the web service functions and pre-built services
    require_once $CFG->dirroot . '/lib/externallib.php';
    external_delete_descriptions($component);
    // delete calendar events
    $DB->delete_records('event', array('modulename' => $pluginname));
    // delete all the logs
    $DB->delete_records('log', array('module' => $pluginname));
    // delete log_display information
    $DB->delete_records('log_display', array('component' => $component));
    // delete the module configuration records
    unset_all_config_for_plugin($pluginname);
    // delete message provider
    message_provider_uninstall($component);
    // delete message processor
    if ($type === 'message') {
        message_processor_uninstall($name);
    }
    // delete the plugin tables
    $xmldbfilepath = $plugindirectory . '/db/install.xml';
    drop_plugin_tables($component, $xmldbfilepath, false);
    if ($type === 'mod' or $type === 'block') {
        // non-frankenstyle table prefixes
        drop_plugin_tables($name, $xmldbfilepath, false);
    }
    // delete the capabilities that were defined by this module
    capabilities_cleanup($component);
    // remove event handlers and dequeue pending events
    events_uninstall($component);
    echo $OUTPUT->notification(get_string('success'), 'notifysuccess');
}
/**
 * Function to require any potential callback files, throwing exceptions
 * if an issue occurs.
 *
 * @param string $component This is the name of the component in Moodle, eg 'mod_forum'
 * @param string $class Name of the class containing the callback functions
 *     activity components should ALWAYS use their name_portfolio_caller
 *     other locations must use something unique
 */
function portfolio_include_callback_file($component, $class = null)
{
    global $CFG;
    require_once $CFG->libdir . '/adminlib.php';
    // It's possible that they are passing a file path rather than passing a component.
    // We want to try and convert this to a component name, eg. mod_forum.
    $pos = strrpos($component, '/');
    if ($pos !== false) {
        // Get rid of the first slash (if it exists).
        $component = ltrim($component, '/');
        // Get a list of valid plugin types.
        $plugintypes = get_plugin_types(false);
        // Assume it is not valid for now.
        $isvalid = false;
        // Go through the plugin types.
        foreach ($plugintypes as $type => $path) {
            if (strrpos($component, $path) === 0) {
                // Found the plugin type.
                $isvalid = true;
                $plugintype = $type;
                $pluginpath = $path;
            }
        }
        // Throw exception if not a valid component.
        if (!$isvalid) {
            throw new coding_exception('Somehow a non-valid plugin path was passed, could be a hackz0r attempt, exiting.');
        }
        // Remove the file name.
        $component = trim(substr($component, 0, $pos), '/');
        // Replace the path with the type.
        $component = str_replace($pluginpath, $plugintype, $component);
        // Ok, replace '/' with '_'.
        $component = str_replace('/', '_', $component);
        // Place a debug message saying the third parameter should be changed.
        debugging('The third parameter sent to the function set_callback_options should be the component name, not a file path, please update this.', DEBUG_DEVELOPER);
    }
    // Check that it is a valid component.
    if (!get_component_version($component)) {
        throw new portfolio_button_exception('nocallbackcomponent', 'portfolio', '', $component);
    }
    // Obtain the component's location.
    if (!($componentloc = get_component_directory($component))) {
        throw new portfolio_button_exception('nocallbackcomponent', 'portfolio', '', $component);
    }
    // Check if the component contains the necessary file for the portfolio plugin.
    // These are locallib.php, portfoliolib.php and portfolio_callback.php.
    $filefound = false;
    if (file_exists($componentloc . '/locallib.php')) {
        $filefound = true;
        require_once $componentloc . '/locallib.php';
    }
    if (file_exists($componentloc . '/portfoliolib.php')) {
        $filefound = true;
        debugging('Please standardise your plugin by renaming your portfolio callback file to locallib.php, or if that file already exists moving the portfolio functionality there.', DEBUG_DEVELOPER);
        require_once $componentloc . '/portfoliolib.php';
    }
    if (file_exists($componentloc . '/portfolio_callback.php')) {
        $filefound = true;
        debugging('Please standardise your plugin by renaming your portfolio callback file to locallib.php, or if that file already exists moving the portfolio functionality there.', DEBUG_DEVELOPER);
        require_once $componentloc . '/portfolio_callback.php';
    }
    // Ensure that we found a file we can use, if not throw an exception.
    if (!$filefound) {
        throw new portfolio_button_exception('nocallbackfile', 'portfolio', '', $component);
    }
    if (!is_null($class) && !class_exists($class)) {
        throw new portfolio_button_exception('nocallbackclass', 'portfolio', '', $class);
    }
}
Beispiel #23
0
 private function recreate_table($component, $tablename)
 {
     global $DB;
     unset($DB->donesetup);
     $manager = $DB->get_manager();
     $filename = get_component_directory($component) . "/db/install.xml";
     $xmldbfile = new xmldb_file($filename);
     if (!$xmldbfile->fileExists()) {
         throw new ddl_exception('ddlxmlfileerror', null, 'File does not exist');
     }
     $loaded = $xmldbfile->loadXMLStructure();
     if (!$loaded || !$xmldbfile->isLoaded()) {
         // Show info about the error if we can find it.
         if ($structure =& $xmldbfile->getStructure()) {
             if ($errors = $structure->getAllErrors()) {
                 throw new ddl_exception('ddlxmlfileerror', null, 'Errors found in XMLDB file: ' . implode(', ', $errors));
             }
         }
         throw new ddl_exception('ddlxmlfileerror', null, 'not loaded??');
     }
     $structure = $xmldbfile->getStructure();
     $table = $structure->getTable($tablename);
     $manager->create_table($table);
     $DB->donesetup = true;
 }
Beispiel #24
0
/**
 * 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
    }
}
Beispiel #25
0
     continue;
 }
 //debug($bits);
 $version = array_shift($bits);
 if ($version == 'moodle') {
     //TODO: this is a ugly hack because we should not load any libs here!
     define('MOODLE_INTERNAL', true);
     require_once $CFG->libdir . '/moodlelib.php';
     $revision = (int) array_shift($bits);
     if ($revision === -1) {
         // Revision -1 says please don't cache the JS
         $cache = false;
     }
     $frankenstyle = array_shift($bits);
     $filename = array_pop($bits);
     $dir = get_component_directory($frankenstyle);
     if ($mimetype == 'text/css') {
         $bits[] = 'assets';
         $bits[] = 'skins';
         $bits[] = 'sam';
     }
     $contentfile = $dir . '/yui/' . join('/', $bits) . '/' . $filename;
 } else {
     if ($version != $CFG->yui3version and $version != $CFG->yui2version and $version != 'gallery') {
         $content .= "\n// Wrong yui version {$part}!\n";
         continue;
     }
     $contentfile = "{$CFG->libdir}/yui/{$part}";
 }
 if (!file_exists($contentfile) or !is_file($contentfile)) {
     $content .= "\n// Combo resource {$part} not found!\n";
 public function test_deprecated_get_component_directory()
 {
     $plugintypes = core_component::get_plugin_types();
     foreach ($plugintypes as $plugintype => $fulldir) {
         $plugins = core_component::get_plugin_list($plugintype);
         foreach ($plugins as $pluginname => $plugindir) {
             $this->assertSame($plugindir, get_component_directory($plugintype . '_' . $pluginname));
         }
     }
     $subsystems = core_component::get_core_subsystems();
     foreach ($subsystems as $subsystem => $fulldir) {
         $this->assertSame($fulldir, get_component_directory('core_' . $subsystem));
     }
 }
Beispiel #27
0
/**
 * Executes cron functions for a specific type of plugin.
 *
 * @param string $plugintype Plugin type (e.g. 'report')
 * @param string $description If specified, will display 'Starting (whatever)'
 *   and 'Finished (whatever)' lines, otherwise does not display
 */
function cron_execute_plugin_type($plugintype, $description = null)
{
    global $DB;
    // Get list from plugin => function for all plugins
    $plugins = get_plugin_list_with_function($plugintype, 'cron');
    // Modify list for backward compatibility (different files/names)
    $plugins = cron_bc_hack_plugin_functions($plugintype, $plugins);
    // Return if no plugins with cron function to process
    if (!$plugins) {
        return;
    }
    if ($description) {
        mtrace('Starting ' . $description);
    }
    foreach ($plugins as $component => $cronfunction) {
        $dir = get_component_directory($component);
        // Get cron period if specified in version.php, otherwise assume every cron
        $cronperiod = 0;
        if (file_exists("{$dir}/version.php")) {
            $plugin = new stdClass();
            include "{$dir}/version.php";
            if (isset($plugin->cron)) {
                $cronperiod = $plugin->cron;
            }
        }
        // Using last cron and cron period, don't run if it already ran recently
        $lastcron = get_config($component, 'lastcron');
        if ($cronperiod && $lastcron) {
            if ($lastcron + $cronperiod > time()) {
                // do not execute cron yet
                continue;
            }
        }
        mtrace('Processing cron function for ' . $component . '...');
        $pre_dbqueries = $DB->perf_get_queries();
        $pre_time = microtime(true);
        $cronfunction();
        mtrace("done. (" . ($DB->perf_get_queries() - $pre_dbqueries) . " dbqueries, " . round(microtime(true) - $pre_time, 2) . " seconds)");
        set_config('lastcron', time(), $component);
        @set_time_limit(0);
    }
    if ($description) {
        mtrace('Finished ' . $description);
    }
}
Beispiel #28
0
/**
 * Called by pluginfile.php to serve files related to the 'question' core
 * component and for files belonging to qtypes.
 *
 * For files that relate to questions in a question_attempt, then we delegate to
 * a function in the component that owns the attempt (for example in the quiz,
 * or in core question preview) to get necessary inforation.
 *
 * (Note that, at the moment, all question file areas relate to questions in
 * attempts, so the If at the start of the last paragraph is always true.)
 *
 * Does not return, either calls send_file_not_found(); or serves the file.
 *
 * @param object $course course settings object
 * @param object $context context object
 * @param string $component the name of the component we are serving files for.
 * @param string $filearea the name of the file area.
 * @param array $args the remaining bits of the file path.
 * @param bool $forcedownload whether the user must be forced to download the file.
 */
function question_pluginfile($course, $context, $component, $filearea, $args, $forcedownload)
{
    global $DB, $CFG;
    list($context, $course, $cm) = get_context_info_array($context->id);
    require_login($course, false, $cm);
    if ($filearea === 'export') {
        require_once $CFG->dirroot . '/question/editlib.php';
        $contexts = new question_edit_contexts($context);
        // check export capability
        $contexts->require_one_edit_tab_cap('export');
        $category_id = (int) array_shift($args);
        $format = array_shift($args);
        $cattofile = array_shift($args);
        $contexttofile = array_shift($args);
        $filename = array_shift($args);
        // load parent class for import/export
        require_once $CFG->dirroot . '/question/format.php';
        require_once $CFG->dirroot . '/question/editlib.php';
        require_once $CFG->dirroot . '/question/format/' . $format . '/format.php';
        $classname = 'qformat_' . $format;
        if (!class_exists($classname)) {
            send_file_not_found();
        }
        $qformat = new $classname();
        if (!($category = $DB->get_record('question_categories', array('id' => $category_id)))) {
            send_file_not_found();
        }
        $qformat->setCategory($category);
        $qformat->setContexts($contexts->having_one_edit_tab_cap('export'));
        $qformat->setCourse($course);
        if ($cattofile == 'withcategories') {
            $qformat->setCattofile(true);
        } else {
            $qformat->setCattofile(false);
        }
        if ($contexttofile == 'withcontexts') {
            $qformat->setContexttofile(true);
        } else {
            $qformat->setContexttofile(false);
        }
        if (!$qformat->exportpreprocess()) {
            send_file_not_found();
            print_error('exporterror', 'question', $thispageurl->out());
        }
        // export data to moodle file pool
        if (!($content = $qformat->exportprocess(true))) {
            send_file_not_found();
        }
        //DEBUG
        //echo '<textarea cols=90 rows=20>';
        //echo $content;
        //echo '</textarea>';
        //die;
        send_file($content, $filename, 0, 0, true, true, $qformat->mime_type());
    }
    $attemptid = (int) array_shift($args);
    $questionid = (int) array_shift($args);
    if ($attemptid === 0) {
        // preview
        require_once $CFG->dirroot . '/question/previewlib.php';
        return question_preview_question_pluginfile($course, $context, $component, $filearea, $attemptid, $questionid, $args, $forcedownload);
    } else {
        $module = $DB->get_field('question_attempts', 'modulename', array('id' => $attemptid));
        $dir = get_component_directory($module);
        if (!file_exists("{$dir}/lib.php")) {
            send_file_not_found();
        }
        include_once "{$dir}/lib.php";
        $filefunction = $module . '_question_pluginfile';
        if (!function_exists($filefunction)) {
            send_file_not_found();
        }
        $filefunction($course, $context, $component, $filearea, $attemptid, $questionid, $args, $forcedownload);
        send_file_not_found();
    }
}
Beispiel #29
0
/**
 * Returns the human-readable, translated version of the capability.
 * Basically a big switch statement.
 *
 * @param string $capabilityname e.g. mod/choice:readresponses
 * @return string
 */
function get_capability_string($capabilityname)
{
    // Typical capability name is 'plugintype/pluginname:capabilityname'
    list($type, $name, $capname) = preg_split('|[/:]|', $capabilityname);
    if ($type === 'moodle') {
        $component = 'core_role';
    } else {
        if ($type === 'quizreport') {
            //ugly hack!!
            $component = 'quiz_' . $name;
        } else {
            $component = $type . '_' . $name;
        }
    }
    $stringname = $name . ':' . $capname;
    if ($component === 'core_role' or get_string_manager()->string_exists($stringname, $component)) {
        return get_string($stringname, $component);
    }
    $dir = get_component_directory($component);
    if (!file_exists($dir)) {
        // plugin broken or does not exist, do not bother with printing of debug message
        return $capabilityname . ' ???';
    }
    // something is wrong in plugin, better print debug
    return get_string($stringname, $component);
}
Beispiel #30
0
/**
 * Invoke component's callback functions
 *
 * @param string $component frankenstyle component name, e.g. 'mod_quiz'
 * @param string $function the rest of the function name, e.g. 'cron' will end up calling 'mod_quiz_cron'
 * @param array $params parameters of callback function
 * @param mixed $default default value if callback function hasn't been defined, or if it retursn null.
 * @return mixed
 */
function component_callback($component, $function, array $params = array(), $default = null)
{
    global $CFG;
    // this is needed for require_once() below
    $cleancomponent = clean_param($component, PARAM_COMPONENT);
    if (empty($cleancomponent)) {
        throw new coding_exception('Invalid component used in plugin/component_callback():' . $component);
    }
    $component = $cleancomponent;
    list($type, $name) = normalize_component($component);
    $component = $type . '_' . $name;
    $oldfunction = $name . '_' . $function;
    $function = $component . '_' . $function;
    $dir = get_component_directory($component);
    if (empty($dir)) {
        throw new coding_exception('Invalid component used in plugin/component_callback():' . $component);
    }
    // Load library and look for function
    if (file_exists($dir . '/lib.php')) {
        require_once $dir . '/lib.php';
    }
    if (!function_exists($function) and function_exists($oldfunction)) {
        if ($type !== 'mod' and $type !== 'core') {
            debugging("Please use new function name {$function} instead of legacy {$oldfunction}");
        }
        $function = $oldfunction;
    }
    if (function_exists($function)) {
        // Function exists, so just return function result
        $ret = call_user_func_array($function, $params);
        if (is_null($ret)) {
            return $default;
        } else {
            return $ret;
        }
    }
    return $default;
}