/** * Stores CSS in a file at the given path. * * This function either succeeds or throws an exception. * * @param theme_config $theme The theme that the CSS belongs to. * @param string $csspath The path to store the CSS at. * @param array $cssfiles The CSS files to store. */ function css_store_css(theme_config $theme, $csspath, array $cssfiles) { global $CFG; // Check if both the CSS optimiser is enabled and the theme supports it. if (!empty($CFG->enablecssoptimiser) && $theme->supportscssoptimisation) { // This is an experimental feature introduced in Moodle 2.3 // The CSS optimiser organises the CSS in order to reduce the overall number // of rules and styles being sent to the client. It does this by collating // the CSS before it is cached removing excess styles and rules and stripping // out any extraneous content such as comments and empty rules. $optimiser = new css_optimiser; $css = ''; foreach ($cssfiles as $file) { $css .= file_get_contents($file)."\n"; } $css = $theme->post_process($css); $css = $optimiser->process($css); // If cssoptimisestats is set then stats from the optimisation are collected // and output at the beginning of the CSS if (!empty($CFG->cssoptimiserstats)) { $css = $optimiser->output_stats_css().$css; } } else { // This is the default behaviour. // The cssoptimise setting was introduced in Moodle 2.3 and will hopefully // in the future be changed from an experimental setting to the default. // The css_minify_css will method will use the Minify library remove // comments, additional whitespace and other minor measures to reduce the // the overall CSS being sent. // However it has the distinct disadvantage of having to minify the CSS // before running the post process functions. Potentially things may break // here if theme designers try to push things with CSS post processing. $css = $theme->post_process(css_minify_css($cssfiles)); } clearstatcache(); if (!file_exists(dirname($csspath))) { @mkdir(dirname($csspath), $CFG->directorypermissions, true); } // Prevent serving of incomplete file from concurrent request, // the rename() should be more atomic than fwrite(). ignore_user_abort(true); if ($fp = fopen($csspath.'.tmp', 'xb')) { fwrite($fp, $css); fclose($fp); rename($csspath.'.tmp', $csspath); @chmod($csspath, $CFG->filepermissions); @unlink($csspath.'.tmp'); // just in case anything fails } ignore_user_abort(false); if (connection_aborted()) { die; } }
/** * Retrieve the list of available filter options. * * @return array An array whose keys are the valid options * And whose values are the values to display */ public static function get_filter_options() { $manager = \core_plugin_manager::instance(); $themes = $manager->get_installed_plugins('theme'); $options = []; foreach (array_keys($themes) as $themename) { try { $theme = \theme_config::load($themename); } catch (Exception $e) { // Bad theme, just skip it for now. continue; } if ($themename !== $theme->name) { // Obsoleted or broken theme, just skip for now. continue; } if ($theme->hidefromselector) { // The theme doesn't want to be shown in the theme selector and as theme // designer mode is switched off we will respect that decision. continue; } $options[$theme->name] = get_string('pluginname', "theme_{$theme->name}"); } return $options; }
/** * Helper function for getting a list of valid template directories for a specific component. * * @param string $component The component to search * @param string $themename The current theme name * @return string[] List of valid directories for templates for this compoonent. Directories are not checked for existence. */ public static function get_template_directories_for_component($component, $themename = '') { global $CFG, $PAGE; // Default the param. if ($themename == '') { $themename = $PAGE->theme->name; } // Clean params for safety. $component = clean_param($component, PARAM_COMPONENT); $themename = clean_param($themename, PARAM_COMPONENT); // Validate the component. $dirs = array(); $compdirectory = core_component::get_component_directory($component); if (!$compdirectory) { throw new coding_exception("Component was not valid: " . s($component)); } // Find the parent themes. $parents = array(); if ($themename === $PAGE->theme->name) { $parents = $PAGE->theme->parents; } else { $themeconfig = theme_config::load($themename); $parents = $themeconfig->parents; } // First check the theme. $dirs[] = $CFG->dirroot . '/theme/' . $themename . '/templates/' . $component . '/'; // Now check the parent themes. // Search each of the parent themes second. foreach ($parents as $parent) { $dirs[] = $CFG->dirroot . '/theme/' . $parent . '/templates/' . $component . '/'; } $dirs[] = $compdirectory . '/templates/'; return $dirs; }
/** * Essentials is a basic child theme of Essential to help you as a theme * developer create your own child theme of Essential. * * @package theme_essentials * @copyright 2015 Gareth J Barnard * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ function theme_essentials_process_css($css, $theme) { /* Change to 'true' if you want to use Essential's settings after removing the '$THEME->parents_exclude_sheets' in config.php. Then to get the alternive colours back, renove the overridden method 'custom_menu_themecolours' in the 'theme_essentials_core_renderer' class in the 'core_renderer.php' file in the 'classes' folder. */ $usingessentialsettings = false; if ($usingessentialsettings) { if (file_exists("{$CFG->dirroot}/theme/essential/lib.php")) { require_once "{$CFG->dirroot}/theme/essential/lib.php"; } else { if (!empty($CFG->themedir) and file_exists("{$CFG->themedir}/essential/lib.php")) { require_once "{$CFG->themedir}/essential/lib.php"; } } // else will just fail when cannot find theme_essential_process_css! static $parenttheme; if (empty($parenttheme)) { $parenttheme = theme_config::load('essential'); } $css = theme_essential_process_css($css, $parenttheme); } // If you have your own settings, then add them here. // Finally return processed CSS return $css; }
function theme_clean_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) { if ($context->contextlevel == CONTEXT_SYSTEM and $filearea === 'logo') { $theme = theme_config::load('clean'); return $theme->setting_file_serve('logo', $args, $forcedownload, $options); } else { send_file_not_found(); } }
/** * Return a list of details about installed templates. * * @param string $component Filter the list to a single component. * @param string $search Search string to optionally filter the list of templates. * @param string $themename The name of the current theme. * @return array[string] Where each template is in the form "component/templatename". */ public static function list_templates($component = '', $search = '', $themename = '') { global $CFG, $PAGE; if (empty($themename)) { $themename = $PAGE->theme->name; } $themeconfig = \theme_config::load($themename); $templatedirs = array(); $results = array(); if ($component !== '') { // Just look at one component for templates. $dirs = mustache_template_finder::get_template_directories_for_component($component, $themename); $templatedirs[$component] = $dirs; } else { // Look at all the templates dirs for core. $templatedirs['core'] = mustache_template_finder::get_template_directories_for_component('core', $themename); // Look at all the templates dirs for subsystems. $subsystems = core_component::get_core_subsystems(); foreach ($subsystems as $subsystem => $dir) { $dir .= '/templates'; if (is_dir($dir)) { $dirs = mustache_template_finder::get_template_directories_for_component('core_' . $subsystem, $themename); $templatedirs['core_' . $subsystem] = $dirs; } } // Look at all the templates dirs for plugins. $plugintypes = core_component::get_plugin_types(); foreach ($plugintypes as $type => $dir) { $plugins = core_component::get_plugin_list_with_file($type, 'templates', false); foreach ($plugins as $plugin => $dir) { if ($type == 'theme' && $plugin != $themename && !in_array($plugin, $themeconfig->parents)) { continue; } if (!empty($dir) && is_dir($dir)) { $pluginname = $type . '_' . $plugin; $dirs = mustache_template_finder::get_template_directories_for_component($pluginname, $themename); $templatedirs[$pluginname] = $dirs; } } } } foreach ($templatedirs as $templatecomponent => $dirs) { foreach ($dirs as $dir) { // List it. $files = glob($dir . '/*.mustache'); foreach ($files as $file) { $templatename = basename($file, '.mustache'); if ($search == '' || strpos($templatename, $search) !== false) { $results[$templatecomponent . '/' . $templatename] = 1; } } } } $results = array_keys($results); sort($results); return $results; }
/** * Serves any files associated with the theme settings. * * @param stdClass $course. * @param stdClass $cm. * @param context $context. * @param string $filearea. * @param array $args. * @param bool $forcedownload. * @param array $options. * @return bool. */ function theme_essential_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) { static $theme; if (empty($theme)) { $theme = theme_config::load('essential'); } if ($context->contextlevel == CONTEXT_SYSTEM) { if ($filearea === 'logo') { return $theme->setting_file_serve('logo', $args, $forcedownload, $options); } else { if ($filearea === 'style') { theme_essential_serve_css($args[1]); } else { if ($filearea === 'headerbackground') { return $theme->setting_file_serve('headerbackground', $args, $forcedownload, $options); } else { if ($filearea === 'pagebackground') { return $theme->setting_file_serve('pagebackground', $args, $forcedownload, $options); } else { if ($filearea === 'favicon') { return $theme->setting_file_serve('favicon', $args, $forcedownload, $options); } else { if (preg_match("/^fontfile(eot|otf|svg|ttf|woff|woff2)(heading|body)\$/", $filearea)) { // http://www.regexr.com/. return $theme->setting_file_serve($filearea, $args, $forcedownload, $options); } else { if (preg_match("/^(marketing|slide)[1-9][0-9]*image\$/", $filearea)) { return $theme->setting_file_serve($filearea, $args, $forcedownload, $options); } else { if ($filearea === 'iphoneicon') { return $theme->setting_file_serve('iphoneicon', $args, $forcedownload, $options); } else { if ($filearea === 'iphoneretinaicon') { return $theme->setting_file_serve('iphoneretinaicon', $args, $forcedownload, $options); } else { if ($filearea === 'ipadicon') { return $theme->setting_file_serve('ipadicon', $args, $forcedownload, $options); } else { if ($filearea === 'ipadretinaicon') { return $theme->setting_file_serve('ipadretinaicon', $args, $forcedownload, $options); } else { send_file_not_found(); } } } } } } } } } } } } else { send_file_not_found(); } }
public function __construct(moodle_page $page, $target) { parent::__construct($page, $target); static $theme; if (empty($theme)) { $theme = theme_config::load('essential'); } $this->enablecategoryicon = !empty($theme->settings->enablecategoryicon) ? $theme->settings->enablecategoryicon : false; }
private static function get_child_theme_config() { if (!self::$checkedchildtheme) { global $PAGE; if (in_array('essential', $PAGE->theme->parents)) { $themename = $PAGE->theme->name; self::$childtheme = \theme_config::load($themename); self::$checkedchildtheme = true; } } return self::$childtheme; }
/** * Serves any files associated with the theme settings. * * @param stdClass $course * @param stdClass $cm * @param context $context * @param string $filearea * @param array $args * @param bool $forcedownload * @param array $options * @return bool */ function theme_clean_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) { if ($context->contextlevel == CONTEXT_SYSTEM and $filearea === 'logo' || $filearea === 'smalllogo') { $theme = theme_config::load('clean'); // By default, theme files must be cache-able by both browsers and proxies. if (!array_key_exists('cacheability', $options)) { $options['cacheability'] = 'public'; } return $theme->setting_file_serve($filearea, $args, $forcedownload, $options); } else { send_file_not_found(); } }
/** * Stores CSS in a file at the given path. * * This function either succeeds or throws an exception. * * @param theme_config $theme The theme that the CSS belongs to. * @param string $csspath The path to store the CSS at. * @param array $cssfiles The CSS files to store. */ function css_store_css(theme_config $theme, $csspath, array $cssfiles) { global $CFG; if (!empty($CFG->enablecssoptimiser)) { // This is an experimental feature introduced in Moodle 2.3 // The CSS optimiser organises the CSS in order to reduce the overall number // of rules and styles being sent to the client. It does this by collating // the CSS before it is cached removing excess styles and rules and stripping // out any extraneous content such as comments and empty rules. $optimiser = new css_optimiser(); $css = ''; foreach ($cssfiles as $file) { $css .= file_get_contents($file) . "\n"; } $css = $theme->post_process($css); $css = $optimiser->process($css); // If cssoptimisestats is set then stats from the optimisation are collected // and output at the beginning of the CSS if (!empty($CFG->cssoptimiserstats)) { $css = $optimiser->output_stats_css() . $css; } } else { // This is the default behaviour. // The cssoptimise setting was introduced in Moodle 2.3 and will hopefully // in the future be changed from an experimental setting to the default. // The css_minify_css will method will use the Minify library remove // comments, additional whitespace and other minor measures to reduce the // the overall CSS being sent. // However it has the distinct disadvantage of having to minify the CSS // before running the post process functions. Potentially things may break // here if theme designers try to push things with CSS post processing. $css = $theme->post_process(css_minify_css($cssfiles)); } check_dir_exists(dirname($csspath)); $fp = fopen($csspath, 'w'); fwrite($fp, $css); fclose($fp); }
/** * Essentials is a basic child theme of Essential to help you as a theme * developer create your own child theme of Essential. * * @package theme_essentials * @copyright 2015 Gareth J Barnard * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ function theme_essentials_process_css($css, $theme) { // Change to 'true' if you want to use Essential's settings after removing the '$THEME->parents_exclude_sheets' in config.php. $usingessentialsettings = false; if ($usingessentialsettings) { require_once dirname(__FILE__) . '/../essential/lib.php'; static $parenttheme; if (empty($parenttheme)) { $parenttheme = theme_config::load('essential'); } $css = theme_essential_process_css($css, $parenttheme); } // If you have your own settings, then add them here. // Finally return processed CSS return $css; }
/** * Serves any files associated with the theme settings. * * @param stdClass $course. * @param stdClass $cm. * @param context $context. * @param string $filearea. * @param array $args. * @param bool $forcedownload. * @param array $options. * @return bool. */ function theme_essentials_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) { static $theme; if (empty($theme)) { $theme = theme_config::load('essentials'); } if ($context->contextlevel == CONTEXT_SYSTEM) { if ($filearea === 'logo') { return $theme->setting_file_serve('logo', $args, $forcedownload, $options); } else { send_file_not_found(); } } else { send_file_not_found(); } }
/** * Returns settings as formatted text * * @param string $setting * @param string $format = false * @param string $theme = null * @return string */ public function get_setting($setting, $format = false, $theme = null) { if (empty($theme)) { $theme = theme_config::load('adaptable'); } if (empty($theme->settings->$setting)) { return false; } else if (!$format) { return $theme->settings->$setting; } else if ($format === 'format_text') { return format_text($theme->settings->$setting, FORMAT_PLAIN); } else if ($format === 'format_html') { return format_text($theme->settings->$setting, FORMAT_HTML, array('trusted' => true)); } else { return format_string($theme->settings->$setting); } }
function theme_lambda_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) { if ($context->contextlevel == CONTEXT_SYSTEM) { $theme = theme_config::load('lambda'); if ($filearea === 'logo') { return $theme->setting_file_serve('logo', $args, $forcedownload, $options); } else { if ($filearea === 'pagebackground') { return $theme->setting_file_serve('pagebackground', $args, $forcedownload, $options); } else { if ($filearea === 'slide1image') { return $theme->setting_file_serve('slide1image', $args, $forcedownload, $options); } else { if ($filearea === 'slide2image') { return $theme->setting_file_serve('slide2image', $args, $forcedownload, $options); } else { if ($filearea === 'slide3image') { return $theme->setting_file_serve('slide3image', $args, $forcedownload, $options); } else { if ($filearea === 'slide4image') { return $theme->setting_file_serve('slide4image', $args, $forcedownload, $options); } else { if ($filearea === 'slide5image') { return $theme->setting_file_serve('slide5image', $args, $forcedownload, $options); } else { if (substr($filearea, 0, 15) === 'carousel_image_') { return $theme->setting_file_serve($filearea, $args, $forcedownload, $options); } else { send_file_not_found(); } } } } } } } } } else { send_file_not_found(); } }
/** * This function will test directives used to serve SVG images to make sure * this are making the right decisions. */ public function test_svg_image_use() { global $CFG; $this->resetAfterTest(); // The two required tests. $this->assertTrue(file_exists($CFG->dirroot . '/pix/i/test.svg')); $this->assertTrue(file_exists($CFG->dirroot . '/pix/i/test.png')); $theme = theme_config::load(theme_config::DEFAULT_THEME); // First up test the forced setting. $imagefile = $theme->resolve_image_location('i/test', 'moodle', true); $this->assertSame('test.svg', basename($imagefile)); $imagefile = $theme->resolve_image_location('i/test', 'moodle', false); $this->assertSame('test.png', basename($imagefile)); // Now test the use of the svgicons config setting. // We need to clone the theme as usesvg property is calculated only once. $testtheme = clone $theme; $CFG->svgicons = true; $imagefile = $testtheme->resolve_image_location('i/test', 'moodle', null); $this->assertSame('test.svg', basename($imagefile)); $CFG->svgicons = false; // We need to clone the theme as usesvg property is calculated only once. $testtheme = clone $theme; $imagefile = $testtheme->resolve_image_location('i/test', 'moodle', null); $this->assertSame('test.png', basename($imagefile)); unset($CFG->svgicons); // Finally test a few user agents. $useragents = array('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)' => false, 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)' => false, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0)' => false, 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)' => false, 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)' => true, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/5.0)' => false, 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0; Touch)' => true, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; Trident/6.0; Touch; .NET4.0E; .NET4.0C; Tablet PC 2.0)' => true, 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0)' => true, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)' => true, 'Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/534.17 (KHTML, like Gecko) Chrome/11.0.652.0 Safari/534.17' => true, 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1' => true, 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1' => true, 'Mozilla/5.0 (Windows NT 6.1; rv:1.9) Gecko/20100101 Firefox/4.0' => true, 'Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0.1' => true, 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1' => true, 'Opera/9.80 (X11; Linux x86_64; U; en) Presto/2.10.289 Version/12.02' => false, 'Mozilla/5.0 (Linux; U; Android 0.5; en-us) AppleWebKit/522+ (KHTML, like Gecko) Safari/419.3' => false, 'Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; HTC Vision Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' => false, 'Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13' => true, 'Mozilla/5.0 (Linux; Android 4.3; it-it; SAMSUNG GT-I9505/I9505XXUEMJ7 Build/JSS15J) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.5 Chrome/28.0.1500.94 Mobile Safari/537.36' => true); foreach ($useragents as $agent => $expected) { core_useragent::instance(true, $agent); // We need to clone the theme as usesvg property is calculated only once. $testtheme = clone $theme; $imagefile = $testtheme->resolve_image_location('i/test', 'moodle', null); if ($expected) { $this->assertSame('test.svg', basename($imagefile), 'Incorrect image returned for user agent `' . $agent . '`'); } else { $this->assertSame('test.png', basename($imagefile), 'Incorrect image returned for user agent `' . $agent . '`'); } } }
/** * Serves any files associated with the theme settings. * * @param stdClass $course * @param stdClass $cm * @param context $context * @param string $filearea * @param array $args * @param bool $forcedownload * @param array $options * @return bool */ function theme_bcu_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) { static $theme; if (empty($theme)) { $theme = theme_config::load('bcu'); } if ($context->contextlevel == CONTEXT_SYSTEM) { if ($filearea === 'logo') { return $theme->setting_file_serve('logo', $args, $forcedownload, $options); } else { if ($filearea === 'style') { theme_essential_serve_css($args[1]); } else { if ($filearea === 'pagebackground') { return $theme->setting_file_serve('pagebackground', $args, $forcedownload, $options); } else { if (preg_match("/p[1-9][0-9]/", $filearea) !== false) { return $theme->setting_file_serve($filearea, $args, $forcedownload, $options); } else { if (substr($filearea, 0, 9) === 'marketing' && substr($filearea, 10, 5) === 'image') { return $theme->setting_file_serve($filearea, $args, $forcedownload, $options); } else { if ($filearea === 'iphoneicon') { return $theme->setting_file_serve('iphoneicon', $args, $forcedownload, $options); } else { if ($filearea === 'iphoneretinaicon') { return $theme->setting_file_serve('iphoneretinaicon', $args, $forcedownload, $options); } else { if ($filearea === 'ipadicon') { return $theme->setting_file_serve('ipadicon', $args, $forcedownload, $options); } else { if ($filearea === 'ipadretinaicon') { return $theme->setting_file_serve('ipadretinaicon', $args, $forcedownload, $options); } else { if ($filearea === 'fontfilettfheading') { return $theme->setting_file_serve('fontfilettfheading', $args, $forcedownload, $options); } else { if ($filearea === 'fontfilettfbody') { return $theme->setting_file_serve('fontfilettfbody', $args, $forcedownload, $options); } else { send_file_not_found(); } } } } } } } } } } } } else { send_file_not_found(); } }
/** * 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(); } \core\session\manager::write_close(); // Unlock session during file serving. 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(); } \core\session\manager::write_close(); // Unlock session during file serving. 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(); } \core\session\manager::write_close(); // Unlock session during file serving. send_stored_file($file, 60 * 60, 0, true, array('preview' => $preview)); } else { send_file_not_found(); } // ======================================================================================================================== } else { if ($component === 'badges') { require_once $CFG->libdir . '/badgeslib.php'; $badgeid = (int) array_shift($args); $badge = new badge($badgeid); $filename = array_pop($args); if ($filearea === 'badgeimage') { if ($filename !== 'f1' && $filename !== 'f2') { send_file_not_found(); } if (!($file = $fs->get_file($context->id, 'badges', 'badgeimage', $badge->id, '/', $filename . '.png'))) { send_file_not_found(); } \core\session\manager::write_close(); send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview)); } else { if ($filearea === 'userbadge' and $context->contextlevel == CONTEXT_USER) { if (!($file = $fs->get_file($context->id, 'badges', 'userbadge', $badge->id, '/', $filename . '.png'))) { send_file_not_found(); } \core\session\manager::write_close(); send_stored_file($file, 60 * 60, 0, true, array('preview' => $preview)); } } // ======================================================================================================================== } 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(); } // 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(); } \core\session\manager::write_close(); // Unlock session during file serving. 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(); } \core\session\manager::write_close(); // Unlock session during file serving. send_stored_file($file, 0, 0, true, 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. This does not apply to the front page. if ($course->id != SITEID && !is_enrolled($context) && !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' || $event->eventtype === 'site') { // Ok. Please note that the event type 'site' still uses a course context. } 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(); } \core\session\manager::write_close(); // Unlock session during file serving. 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', null); send_file($imagefile, basename($imagefile), 60 * 60 * 24 * 14); } $options = array('preview' => $preview); if (empty($CFG->forcelogin) && empty($CFG->forceloginforprofileimage)) { // Profile images should be cache-able by both browsers and proxies according // to $CFG->forcelogin and $CFG->forceloginforprofileimage. $options['cacheability'] = 'public'; } send_stored_file($file, 60 * 60 * 24 * 365, 0, false, $options); // 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(); } \core\session\manager::write_close(); // Unlock session during file serving. 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(); } \core\session\manager::write_close(); // Unlock session during file serving. 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(); } \core\session\manager::write_close(); // Unlock session during file serving. 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(); } \core\session\manager::write_close(); // Unlock session during file serving. 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(); } \core\session\manager::write_close(); // Unlock session during file serving. 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' || $filearea === 'overviewfiles') { if ($CFG->forcelogin) { require_login(); } $filename = array_pop($args); $filepath = $args ? '/' . implode('/', $args) . '/' : '/'; if (!($file = $fs->get_file($context->id, 'course', $filearea, 0, $filepath, $filename)) or $file->is_directory()) { send_file_not_found(); } \core\session\manager::write_close(); // Unlock session during file serving. 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(); } $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(); } \core\session\manager::write_close(); // Unlock session during file serving. send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview)); } else { send_file_not_found(); } } } else { if ($component === 'cohort') { $cohortid = (int) array_shift($args); $cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST); $cohortcontext = context::instance_by_id($cohort->contextid); // The context in the file URL must be either cohort context or context of the course underneath the cohort's context. if ($context->id != $cohort->contextid && ($context->contextlevel != CONTEXT_COURSE || !in_array($cohort->contextid, $context->get_parent_context_ids()))) { send_file_not_found(); } // User is able to access cohort if they have view cap on cohort level or // the cohort is visible and they have view cap on course level. $canview = has_capability('moodle/cohort:view', $cohortcontext) || $cohort->visible && has_capability('moodle/cohort:view', $context); if ($filearea === 'description' && $canview) { $filename = array_pop($args); $filepath = $args ? '/' . implode('/', $args) . '/' : '/'; if (($file = $fs->get_file($cohortcontext->id, 'cohort', 'description', $cohort->id, $filepath, $filename)) && !$file->is_directory()) { \core\session\manager::write_close(); // Unlock session during file serving. send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview)); } } 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(); } \core\session\manager::write_close(); // Unlock session during file serving. 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(); } } \core\session\manager::write_close(); // Unlock session during file serving. 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(); } \core\session\manager::write_close(); // Unlock session during file serving. 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(); } \core\session\manager::write_close(); // Unlock session during file serving. 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(); } \core\session\manager::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(); } \core\session\manager::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(); } \core\session\manager::write_close(); // Unlock session during file serving. 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(); } \core\session\manager::write_close(); // Unlock session during file serving. 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(); } // finally send the file send_stored_file($file, null, 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(); } if ($context->get_course_context(false)) { // If block is in course context, then check if user has capability to access course. require_course_login($course); } else { if ($CFG->forcelogin) { // If user is logged out, bp record will not be visible, even if the user would have access if logged in. require_login(); } } $bprecord = $DB->get_record('block_positions', array('contextid' => $context->id, 'blockinstanceid' => $context->instanceid)); // 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 = core_component::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(); } } } } } } } } } } } } } } } } } }
/** * Returns a list of valid and compatible themes * * @return array */ function get_list_of_themes() { global $CFG; $themes = array(); if (!empty($CFG->themelist)) { // Use admin's list of themes. $themelist = explode(',', $CFG->themelist); } else { $themelist = array_keys(core_component::get_plugin_list("theme")); } foreach ($themelist as $key => $themename) { $theme = theme_config::load($themename); $themes[$themename] = $theme; } core_collator::asort_objects_by_method($themes, 'get_theme_name'); return $themes; }
/** * Loads the theme config from config.php file. * * @param string $themename * @param stdClass $settings from config_plugins table * @param boolean $parentscheck true to also check the parents. . * @return stdClass The theme configuration */ private static function find_theme_config($themename, $settings, $parentscheck = true) { // We have to use the variable name $THEME (upper case) because that // is what is used in theme config.php files. if (!($dir = theme_config::find_theme_location($themename))) { return null; } $THEME = new stdClass(); $THEME->name = $themename; $THEME->dir = $dir; $THEME->settings = $settings; global $CFG; // just in case somebody tries to use $CFG in theme config include "{$THEME->dir}/config.php"; // verify the theme configuration is OK if (!is_array($THEME->parents)) { // parents option is mandatory now return null; } else { // We use $parentscheck to only check the direct parents (avoid infinite loop). if ($parentscheck) { // Find all parent theme configs. foreach ($THEME->parents as $parent) { $parentconfig = theme_config::find_theme_config($parent, $settings, false); if (empty($parentconfig)) { return null; } } } } return $THEME; }
/** * Return list of themes which can be set in moodle. * * @return array list of themes with tests. */ protected function get_list_of_themes() { $selectablethemes = array(); // Get all themes installed on site. $themes = core_component::get_plugin_list('theme'); ksort($themes); foreach ($themes as $themename => $themedir) { // Load the theme config. try { $theme = theme_config::load($themename); } catch (Exception $e) { // Bad theme, just skip it for now. continue; } if ($themename !== $theme->name) { // Obsoleted or broken theme, just skip for now. continue; } if ($theme->hidefromselector) { // The theme doesn't want to be shown in the theme selector and as theme // designer mode is switched off we will respect that decision. continue; } if ($themename == theme_config::DEFAULT_THEME) { // Don't include default theme, as default suite will be running with this theme. continue; } $selectablethemes[] = $themename; } return $selectablethemes; }
/** * Method for use by Moodle core to set up the theme. Do not * use this in your own code. * * Make sure the right theme for this page is loaded. Tell our * blocks_manager about the theme block regions, and then, if * we are $PAGE, set up the global $OUTPUT. */ public function initialise_theme_and_output() { global $OUTPUT, $PAGE, $SITE; if (!empty($this->_wherethemewasinitialised)) { return; } if (!during_initial_install()) { // detect PAGE->context mess $this->magic_get_context(); } if (!$this->_course && !during_initial_install()) { $this->set_course($SITE); } if (is_null($this->_theme)) { $themename = $this->resolve_theme(); $this->_theme = theme_config::load($themename); $this->_layout_options = $this->_theme->pagelayout_options($this->pagelayout); } $this->_theme->setup_blocks($this->pagelayout, $this->blocks); if ($this === $PAGE) { $OUTPUT = $this->get_renderer('core'); } $this->_wherethemewasinitialised = debug_backtrace(); }
// initialise ME's // This must presently come AFTER $USER has been set up. initialise_fullme(); // Late profiling, only happening if early one wasn't started if (!empty($CFG->profilingenabled)) { require_once $CFG->libdir . '/xhprof/xhprof_moodle.php'; if (profiling_start()) { register_shutdown_function('profiling_stop'); } } // Process theme change in the URL. if (!empty($CFG->allowthemechangeonurl) and !empty($_GET['theme'])) { // we have to use _GET directly because we do not want this to interfere with _POST $urlthemename = optional_param('theme', '', PARAM_SAFEDIR); try { $themeconfig = theme_config::load($urlthemename); // Makes sure the theme can be loaded without errors. if ($themeconfig->name === $urlthemename) { $SESSION->theme = $urlthemename; } else { unset($SESSION->theme); } unset($themeconfig); unset($urlthemename); } catch (Exception $e) { debugging('Failed to set the theme from the URL.', DEBUG_DEVELOPER, $e->getTrace()); } } unset($urlthemename); // Ensure a valid theme is set. if (!isset($CFG->theme)) {
/** * Get original site cover image file. * * @return stored_file | bool (false) */ public static function site_coverimage_original() { $theme = \theme_config::load('snap'); $filename = $theme->settings->poster; if ($filename) { $syscontextid = \context_system::instance()->id; $fullpath = "/{$syscontextid}/theme_snap/poster/0{$filename}"; $fs = get_file_storage(); return $fs->get_file_by_hash(sha1($fullpath)); } else { return false; } }
/** * Method for use by Moodle core to set up the theme. Do not * use this in your own code. * * Make sure the right theme for this page is loaded. Tell our * blocks_manager about the theme block regions, and then, if * we are $PAGE, set up the global $OUTPUT. * * @return void */ public function initialise_theme_and_output() { global $OUTPUT, $PAGE, $SITE, $CFG; if (!empty($this->_wherethemewasinitialised)) { return; } if (!during_initial_install()) { // Detect PAGE->context mess. $this->magic_get_context(); } if (!$this->_course && !during_initial_install()) { $this->set_course($SITE); } if (is_null($this->_theme)) { $themename = $this->resolve_theme(); $this->_theme = theme_config::load($themename); } $this->_theme->setup_blocks($this->pagelayout, $this->blocks); if ($this->_theme->enable_dock && !empty($CFG->allowblockstodock)) { $this->requires->strings_for_js(array('addtodock', 'undockitem', 'dockblock', 'undockblock', 'undockall', 'hidedockpanel', 'hidepanel'), 'block'); $this->requires->string_for_js('thisdirectionvertical', 'langconfig'); $this->requires->yui_module('moodle-core-dock-loader', 'M.core.dock.loader.initLoader'); } if ($this === $PAGE) { $target = null; if ($this->pagelayout === 'maintenance') { // If the page is using the maintenance layout then we're going to force target to maintenance. // This leads to a special core renderer that is designed to block access to API's that are likely unavailable for this // page layout. $target = RENDERER_TARGET_MAINTENANCE; } $OUTPUT = $this->get_renderer('core', null, $target); } $this->_wherethemewasinitialised = debug_backtrace(); }
/** * Returns a list of valid and compatible themes * * @global object * @return array */ function get_list_of_themes() { global $CFG; $themes = array(); if (!empty($CFG->themelist)) { // use admin's list of themes $themelist = explode(',', $CFG->themelist); } else { $themelist = array_keys(get_plugin_list("theme")); } foreach ($themelist as $key => $themename) { $theme = theme_config::load($themename); $themes[$themename] = $theme; } asort($themes); return $themes; }
/** * Constructor * * @param moodle_page $page the page we are doing output for. * @param string $target one of rendering target constants */ public function __construct(\moodle_page $page, $target) { parent::__construct($page, $target); $this->themeconfig = array(\theme_config::load('essential')); }
/** * Loads the theme config from config.php file. * * @param string $themename * @param stdClass $settings from config_plugins table * @return stdClass The theme configuration */ private static function find_theme_config($themename, $settings) { // We have to use the variable name $THEME (upper case) because that // is what is used in theme config.php files. if (!($dir = theme_config::find_theme_location($themename))) { return null; } $THEME = new stdClass(); $THEME->name = $themename; $THEME->dir = $dir; $THEME->settings = $settings; global $CFG; // just in case somebody tries to use $CFG in theme config include "{$THEME->dir}/config.php"; // verify the theme configuration is OK if (!is_array($THEME->parents)) { // parents option is mandatory now return null; } return $THEME; }
$themelocked = theme_is_device_locked($device); $table->id = 'adminthemeselector'; $table->head = array(get_string('theme'), get_string('info')); $themes = array(); if ($themelocked) { $heading = get_string('currenttheme', 'admin'); $themename = theme_get_locked_theme_for_device($device); $themedirectory = core_component::get_plugin_directory('theme', $themename); $themes[$themename] = $themedirectory; } else { $themes = core_component::get_plugin_list('theme'); } foreach ($themes as $themename => $themedir) { // Load the theme config. try { $theme = theme_config::load($themename); } catch (Exception $e) { // Bad theme, just skip it for now. continue; } if ($themename !== $theme->name) { // Obsoleted or broken theme, just skip for now. continue; } if (empty($CFG->themedesignermode) && $theme->hidefromselector) { // The theme doesn't want to be shown in the theme selector and as theme // designer mode is switched off we will respect that decision. continue; } $strthemename = get_string('pluginname', 'theme_' . $themename); // Build the table row, and also a list of items to go in the second cell.
/** * Serves any files associated with the theme settings. * * @param stdClass $theme null or theme object. * @param string $setting setting name for the admin_setting_configstoredfile setting. * @param string $filearea filearea for the admin_setting_configstoredfile setting. * @return bool|array false if not an image / no file uploaded or array of image dimensions and mime type as returned by 'get_imageinfo()' of 'stored_file.php'. */ function theme_campus_get_image_dimensions($theme, $setting, $filearea) { if ($theme == null) { $theme = theme_config::load('campus'); } if (empty($theme->settings->{$setting})) { return false; } $filepath = $theme->settings->{$setting}; $syscontext = context_system::instance(); $fullpath = "/{$syscontext->id}/theme_campus/{$filearea}/0" . $filepath; $fullpath = rtrim($fullpath, '/'); $fs = get_file_storage(); if ($file = $fs->get_file_by_hash(sha1($fullpath))) { if ($imageinfo = $file->get_imageinfo()) { return $imageinfo; // E.g. Array ( [width] => 150 [height] => 106 [mimetype] => image/jpeg ). } } return false; }