Example #1
0
 public function test_js_files()
 {
     global $CFG;
     $testfile1 = "{$CFG->tempdir}/test1.js";
     $testfile2 = "{$CFG->tempdir}/test2.js";
     $testfile3 = "{$CFG->tempdir}/test3.js";
     $js1 = "\nfunction hm()\n{\n}\n";
     $js2 = "function oh(){}";
     file_put_contents($testfile1, $js1);
     file_put_contents($testfile2, $js2);
     $files = array($testfile1, $testfile2);
     $this->assertSame("function hm(){};\nfunction oh(){}", core_minify::js_files($files));
     $files = array($testfile1, $testfile2, $testfile3);
     $this->assertStringStartsWith("function hm(){};\nfunction oh(){};\n\n\n// Cannot read JS file ", @core_minify::js_files($files));
     unlink($testfile1);
     unlink($testfile2);
 }
Example #2
0
/**
 * Minify CSS files.
 *
 * @deprecated since 2.6
 *
 * @param array $files
 * @return string
 */
function css_minify_css($files)
{
    debugging('css_minify_css() is deprecated, use core_minify::css_files() or core_minify::css() instead.');
    return core_minify::css_files($files);
}
 /**
  * Get the whole css stylesheet for production mode.
  *
  * NOTE: this method is not expected to be used from any addons.
  *
  * @return string CSS markup, already optimised and compressed
  */
 public function get_css_content()
 {
     global $CFG;
     require_once $CFG->dirroot . '/lib/csslib.php';
     $csscontent = '';
     foreach ($this->get_css_files(false) as $type => $value) {
         foreach ($value as $identifier => $val) {
             if (is_array($val)) {
                 foreach ($val as $v) {
                     $csscontent .= file_get_contents($v) . "\n";
                 }
             } else {
                 if ($type === 'theme' && $identifier === $this->lessfile) {
                     // We need the content from LESS because this is the LESS file from the theme.
                     $csscontent .= $this->get_css_content_from_less(false);
                 } else {
                     $csscontent .= file_get_contents($val) . "\n";
                 }
             }
         }
     }
     $csscontent = $this->post_process($csscontent);
     if (!empty($CFG->enablecssoptimiser) && $this->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();
         $csscontent = $optimiser->process($csscontent);
     } else {
         $csscontent = core_minify::css($csscontent);
     }
     return $csscontent;
 }
 /**
  * Allow setting of the config function described in {@see set_config_function} from a file.
  * The contents of this file are then passed to set_config_function.
  *
  * When jsrev is positive, the function is minified and stored in a MUC cache for subsequent uses.
  *
  * @param $file The path to the JavaScript function used for YUI configuration.
  * @return String the name of the function to use in the group pattern configuration.
  */
 public function set_config_source($file)
 {
     global $CFG;
     $cache = cache::make('core', 'yuimodules');
     // Attempt to get the metadata from the cache.
     $keyname = 'configfn_' . $file;
     $fullpath = $CFG->dirroot . '/' . $file;
     if (!isset($CFG->jsrev) || $CFG->jsrev == -1) {
         $cache->delete($keyname);
         $configfn = file_get_contents($fullpath);
     } else {
         $configfn = $cache->get($keyname);
         if ($configfn === false) {
             require_once $CFG->libdir . '/jslib.php';
             $configfn = core_minify::js_files(array($fullpath));
             $cache->set($keyname, $configfn);
         }
     }
     return $this->set_config_function($configfn);
 }
Example #5
0
if ($rev > 0 and file_exists($candidate)) {
    if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) || !empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
        // we do not actually need to verify the etag value because our files
        // never change in cache because we increment the rev parameter
        js_send_unmodified(filemtime($candidate), $etag);
    }
    js_send_cached($candidate, $etag);
}
//=================================================================================
// ok, now we need to start normal moodle script, we need to load all libs and $DB
define('ABORT_AFTER_CONFIG_CANCEL', true);
define('NO_MOODLE_COOKIES', true);
// Session not used here
define('NO_UPGRADE_CHECK', true);
// Ignore upgrade check
require "{$CFG->dirroot}/lib/setup.php";
$theme = theme_config::load($themename);
$themerev = theme_get_revision();
if ($themerev <= 0 or $rev != $themerev) {
    // Do not send caching headers if they do not request current revision,
    // we do not want to pollute browser caches with outdated JS.
    js_send_uncached($theme->javascript_content($type));
}
make_localcache_directory('theme', false);
js_write_cache_file_content($candidate, core_minify::js_files($theme->javascript_files($type)));
// Verify nothing failed in cache file creation.
clearstatcache();
if (file_exists($candidate)) {
    js_send_cached($candidate, $etag);
}
js_send_uncached($theme->javascript_content($type));
Example #6
0
 /**
  * Get the whole css stylesheet for production mode.
  *
  * NOTE: this method is not expected to be used from any addons.
  *
  * @return string CSS markup compressed
  */
 public function get_css_content()
 {
     $csscontent = '';
     foreach ($this->get_css_files(false) as $type => $value) {
         foreach ($value as $identifier => $val) {
             if (is_array($val)) {
                 foreach ($val as $v) {
                     $csscontent .= file_get_contents($v) . "\n";
                 }
             } else {
                 if ($type === 'theme' && $identifier === $this->scssfile) {
                     // We need the content from SCSS because this is the SCSS file from the theme.
                     $csscontent .= $this->get_css_content_from_scss(false);
                 } else {
                     if ($type === 'theme' && $identifier === $this->lessfile) {
                         // We need the content from LESS because this is the LESS file from the theme.
                         $csscontent .= $this->get_css_content_from_less(false);
                     } else {
                         $csscontent .= file_get_contents($val) . "\n";
                     }
                 }
             }
         }
     }
     $csscontent = $this->post_process($csscontent);
     $csscontent = core_minify::css($csscontent);
     return $csscontent;
 }
Example #7
0
    // If-Modified-Since requests so there is no need to handle them specially.
    header('Expires: ' . date('r', time() + 365 * 24 * 3600));
    header('Cache-Control: max-age=' . 365 * 24 * 3600);
    // Pragma is set to no-cache by default so must be overridden.
    header('Pragma:');
}
// Get the right MIME type.
$mimetype = mimeinfo('type', $file);
// For JS files, these can be minified and stored in cache.
if ($mimetype === 'application/x-javascript' && $allowcache) {
    // The cached file is stored without version number etc. This is okay
    // because $CFG->cachedir is cleared each time there is a plugin update,
    // such as a new version of a tinymce plugin.
    // Flatten filename and include cache location.
    $cache = $CFG->cachedir . '/editor_tinymce/pluginjs';
    $cachefile = $cache . '/' . $tinymceplugin . str_replace('/', '_', $innerpath);
    // If it doesn't exist, minify it and save to that location.
    if (!file_exists($cachefile)) {
        $content = core_minify::js_files(array($file));
        js_write_cache_file_content($cachefile, $content);
    }
    $file = $cachefile;
} else {
    if ($mimetype === 'text/html') {
        header('X-UA-Compatible: IE=edge');
    }
}
// Serve file.
header('Content-Length: ' . filesize($file));
header('Content-Type: ' . $mimetype);
readfile($file);
    $jsfiles[] = $jsfile;
}
if (!$jsfiles) {
    // bad luck - no valid files
    die;
}
$etag = sha1($rev . implode(',', $jsfiles));
// Use the caching only for meaningful revision numbers which prevents future cache poisoning.
if ($rev > 0 and $rev < time() + 60 * 60) {
    $candidate = $CFG->localcachedir . '/js/' . $etag;
    if (file_exists($candidate)) {
        if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) || !empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
            // we do not actually need to verify the etag value because our files
            // never change in cache because we increment the rev parameter
            js_send_unmodified(filemtime($candidate), $etag);
        }
        js_send_cached($candidate, $etag);
    } else {
        js_write_cache_file_content($candidate, core_minify::js_files($jsfiles));
        // verify nothing failed in cache file creation
        clearstatcache();
        if (file_exists($candidate)) {
            js_send_cached($candidate, $etag);
        }
    }
}
$content = '';
foreach ($jsfiles as $jsfile) {
    $content .= file_get_contents($jsfile) . "\n";
}
js_send_uncached($content, $etag);
Example #9
0
/**
 * 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.
 * @param bool $chunk If set to true these files will be chunked to ensure
 *      that no one file contains more than 4095 selectors.
 * @param string $chunkurl If the CSS is be chunked then we need to know the URL
 *      to use for the chunked files.
 */
function css_store_css(theme_config $theme, $csspath, array $cssfiles, $chunk = false, $chunkurl = null)
{
    global $CFG;
    $css = '';
    foreach ($cssfiles as $file) {
        $css .= file_get_contents($file) . "\n";
    }
    // 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 = $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);
        $css = core_minify::css($css);
    }
    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);
    // First up write out the single file for all those using decent browsers.
    css_write_file($csspath, $css);
    if ($chunk) {
        // If we need to chunk the CSS for browsers that are sub-par.
        $css = css_chunk_by_selector_count($css, $chunkurl);
        $files = count($css);
        $count = 1;
        foreach ($css as $content) {
            if ($count === $files) {
                // If there is more than one file and this IS the last file.
                $filename = preg_replace('#\\.css$#', '.0.css', $csspath);
            } else {
                // If there is more than one file and this is not the last file.
                $filename = preg_replace('#\\.css$#', '.' . $count . '.css', $csspath);
            }
            $count++;
            css_write_file($filename, $content);
        }
    }
    ignore_user_abort(false);
    if (connection_aborted()) {
        die;
    }
}