Skip to content

Commit

Permalink
MDL-43952 Javascript: Support invalidation of browser caches for YUI …
Browse files Browse the repository at this point in the history
…patching

This will also force files loaded from the CDN to instead come from the
local distribution since those patches will not be included in the CDN
release.

Please see the documentation at http://docs.moodle.org/dev/YUI/Patching for
important on using these changes.
  • Loading branch information
andrewnicols committed Feb 4, 2014
1 parent 183515d commit aea2973
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 11 deletions.
62 changes: 62 additions & 0 deletions lib/outputrequirementslib.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,15 @@ public function __construct() {
$this->YUI_config->comboBase = $this->yui3loader->comboBase;
$this->YUI_config->combine = $this->yui3loader->combine;

// If we've had to patch any YUI modules between releases, we must override the YUI configuration to include them.
// For important information on patching YUI modules, please see http://docs.moodle.org/dev/YUI/Patching.
if (!empty($CFG->yuipatchedmodules) && !empty($CFG->yuipatchlevel)) {
$this->YUI_config->define_patched_core_modules($this->yui3loader->local_comboBase,
$CFG->yui3version,
$CFG->yuipatchlevel,
$CFG->yuipatchedmodules);
}

$configname = $this->YUI_config->set_config_source('lib/yui/config/yui2.js');
$this->YUI_config->add_group('yui2', array(
// Loader configuration for our 2in3, for now ignores $CFG->useexternalyui.
Expand Down Expand Up @@ -1773,6 +1782,59 @@ private function get_moodle_path_metadata($path) {
}
return $modules;
}

/**
* Define YUI modules which we have been required to patch between releases.
*
* We must do this because we aggressively cache content on the browser, and we must also override use of the
* external CDN which will serve the true authoritative copy of the code without our patches.
*
* @param String combobase The local combobase
* @param String yuiversion The current YUI version
* @param Int patchlevel The patch level we're working to for YUI
* @param Array patchedmodules An array containing the names of the patched modules
* @return void
*/
public function define_patched_core_modules($combobase, $yuiversion, $patchlevel, $patchedmodules) {
// The version we use is suffixed with a patchlevel so that we can get additional revisions between YUI releases.
$subversion = $yuiversion . '_' . $patchlevel;

if ($this->comboBase == $combobase) {
// If we are using the local combobase in the loader, we can add a group and still make use of the combo
// loader. We just need to specify a different root which includes a slightly different YUI version number
// to include our patchlevel.
$patterns = array();
$modules = array();
foreach ($patchedmodules as $modulename) {
// We must define the pattern and module here so that the loader uses our group configuration instead of
// the standard module definition. We may lose some metadata provided by upstream but this will be
// loaded when the module is loaded anyway.
$patterns[$modulename] = array(
'group' => 'yui-patched',
);
$modules[$modulename] = array();
}

// Actually add the patch group here.
$this->add_group('yui-patched', array(
'combine' => true,
'root' => $subversion . '/',
'patterns' => $patterns,
'modules' => $modules,
));

} else {
// The CDN is in use - we need to instead use the local combobase for this module and override the modules
// definition. We cannot use the local base - we must use the combobase because we cannot invalidate the
// local base in browser caches.
$fullpathbase = $combobase . $subversion . '/';
foreach ($patchedmodules as $modulename) {
$this->modules[$modulename] = array(
'fullpath' => $fullpathbase . $modulename . '/' . $modulename . '-min.js'
);
}
}
}
}

/**
Expand Down
9 changes: 9 additions & 0 deletions lib/setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,15 @@
$CFG->yui2version = '2.9.0';
$CFG->yui3version = '3.13.0';

// Patching the upstream YUI release.
// For important information on patching YUI modules, please see http://docs.moodle.org/dev/YUI/Patching.
// If we need to patch a YUI modules between official YUI releases, the yuipatchlevel will need to be manually
// incremented here. The module will also need to be listed in the yuipatchedmodules.
// When upgrading to a subsequent version of YUI, these should be reset back to 0 and an empty array.
$CFG->yuipatchlevel = 0;
$CFG->yuipatchedmodules = array(
);

// Store settings from config.php in array in $CFG - we can use it later to detect problems and overrides.
if (!isset($CFG->config_php_settings)) {
$CFG->config_php_settings = (array)$CFG;
Expand Down
3 changes: 3 additions & 0 deletions lib/yuilib/readme_moodle.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Description of import of various YUI libraries into Moodle:
* update lib/thrirdpartylibs.xml
* verify our simpleyui rollup contents in /theme/yui_combo.php

If you need to patch the YUI library between its official releases, you *must* read
http://docs.moodle.org/dev/YUI/Patching.

3/ YUI3 Gallery version gallery-2013.10.02-20-26:
* selective copy of the "build" directory for the checked out tag of yui3-gallery.
Unit test code coverage files (*-coverage.js) are removed but no other changes are made.
Expand Down
18 changes: 15 additions & 3 deletions theme/yui_combo.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@
continue;
}

// Allow support for revisions on YUI between official releases.
// We can just discard the subrevision since it is only used to invalidate the browser cache.
$yuipatchedversion = explode('_', $revision);
$yuiversion = $yuipatchedversion[0];

$yuimodules = array(
// Include everything from original SimpleYUI,
// this list can be built using http://yuilibrary.com/yui/configurator/ by selecting all modules
Expand Down Expand Up @@ -193,14 +198,14 @@
if ($type === 'js') {
$newparts = array();
foreach ($yuimodules as $module) {
$newparts[] = $revision . '/' . $module . '/' . $module . $filesuffix;
$newparts[] = $yuiversion . '/' . $module . '/' . $module . $filesuffix;
}
$newparts[] = 'yuiuseall/yuiuseall';
$parts = array_merge($newparts, $parts);
} else {
$newparts = array();
foreach ($yuimodules as $module) {
$candidate = $revision . '/' . $module . '/assets/skins/sam/' . $module . '.css';
$candidate = $yuiversion . '/' . $module . '/assets/skins/sam/' . $module . '.css';
if (!file_exists("$CFG->libdir/yuilib/$candidate")) {
continue;
}
Expand Down Expand Up @@ -306,10 +311,17 @@
$filecontent = "var Y = YUI().use('*');";

} else {
if ($version != $CFG->yui3version) {
// Allow support for revisions on YUI between official releases.
// We can just discard the subrevision since it is only used to invalidate the browser cache.
$yuipatchedversion = explode('_', $version);
$yuiversion = $yuipatchedversion[0];
if ($yuiversion != $CFG->yui3version) {
$content .= "\n// Wrong yui version $part!\n";
continue;
}
$newpart = explode('/', $part);
$newpart[0] = $yuiversion;
$part = implode('/', $newpart);
$contentfile = "$CFG->libdir/yuilib/$part";
}
if (!file_exists($contentfile) or !is_file($contentfile)) {
Expand Down
22 changes: 14 additions & 8 deletions theme/yui_image.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,21 @@
} else if ($version == 'gallery' && count($parts) >= 3) {
list($revision, $module, , , , $image) = $parts;
$imagepath = "$CFG->dirroot/lib/yuilib/gallery/$module/assets/skins/sam/$image";
} else if (count($parts) == 1 && ($version == $CFG->yui3version || $version == $CFG->yui2version)) {
list($image) = $parts;
if ($version == $CFG->yui3version) {
$imagepath = "$CFG->dirroot/lib/yuilib/$CFG->yui3version/assets/skins/sam/$image";
} else {
$imagepath = "$CFG->dirroot/lib/yuilib/2in3/$CFG->yui2version/build/assets/skins/sam/$image";
}
} else {
yui_image_not_found();
// Allow support for revisions on YUI between official releases.
// We can just discard the subrevision since it is only used to invalidate the browser cache.
$yuipatchedversion = explode('_', $version);
$yuiversion = $yuipatchedversion[0];
if (count($parts) == 1 && ($yuiversion == $CFG->yui3version || $yuiversion == $CFG->yui2version)) {
list($image) = $parts;
if ($yuiversion == $CFG->yui3version) {
$imagepath = "$CFG->dirroot/lib/yuilib/$CFG->yui3version/assets/skins/sam/$image";
} else {
$imagepath = "$CFG->dirroot/lib/yuilib/2in3/$CFG->yui2version/build/assets/skins/sam/$image";
}
} else {
yui_image_not_found();
}
}

if (!file_exists($imagepath)) {
Expand Down

0 comments on commit aea2973

Please sign in to comment.