Added support for aggregating and caching library assets
parent
1bf393a9af
commit
00686b733d
|
@ -148,6 +148,104 @@ class DefaultStorage implements \H5P\FileStorage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will concatenate all JavaScrips and Stylesheets into two files in order
|
||||||
|
* to improve page performance.
|
||||||
|
*
|
||||||
|
* @param array $files
|
||||||
|
* A set of all the assets required for content to display
|
||||||
|
* @param string $key
|
||||||
|
* Hashed key for cached asset
|
||||||
|
*/
|
||||||
|
public function cacheAssets(&$files, $key) {
|
||||||
|
foreach ($files as $type => $assets) {
|
||||||
|
$content = '';
|
||||||
|
|
||||||
|
foreach ($assets as $asset) {
|
||||||
|
// Get content from asset file
|
||||||
|
$assetContent = file_get_contents($this->path . $asset->path);
|
||||||
|
$cssRelPath = preg_replace('/[^\/]+$/', '', $asset->path);
|
||||||
|
|
||||||
|
// Get file content and concatenate
|
||||||
|
if ($type === 'scripts') {
|
||||||
|
$content .= $assetContent . ";\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Rewrite relative URLs used inside stylesheets
|
||||||
|
$content .= preg_replace_callback(
|
||||||
|
'/url\([\'"]?([^"\')]+)[\'"]?\)/i',
|
||||||
|
function ($matches) use ($cssRelPath) {
|
||||||
|
return substr($matches[1], 0, 3) !== '../' ? $matches[0] : 'url("../' . $cssRelPath . $matches[1] . '")';
|
||||||
|
},
|
||||||
|
$assetContent
|
||||||
|
) . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self::dirReady("{$this->path}/cachedassets");
|
||||||
|
$ext = ($type === 'scripts' ? 'js' : 'css');
|
||||||
|
file_put_contents("{$this->path}/cachedassets/{$key}.{$ext}", $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the newly created cache
|
||||||
|
$files = self::formatCachedAssets($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will check if there are cache assets available for content.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* Hashed key for cached asset
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getCachedAssets($key) {
|
||||||
|
if (!file_exists("{$this->path}/cachedassets/{$key}.js") ||
|
||||||
|
!file_exists("{$this->path}/cachedassets/{$key}.css") {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return self::formatCachedAssets($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the aggregated cache files.
|
||||||
|
*
|
||||||
|
* @param array $keys
|
||||||
|
* The hash keys of removed files
|
||||||
|
*/
|
||||||
|
public function deleteCachedAssets($keys) {
|
||||||
|
$context = \context_system::instance();
|
||||||
|
$fs = get_file_storage();
|
||||||
|
|
||||||
|
foreach ($keys as $hash) {
|
||||||
|
foreach (array('js', 'css') as $ext) {
|
||||||
|
$path = "{$this->path}/cachedassets/{$key}.{$ext}";
|
||||||
|
if (file_exists($path)) {
|
||||||
|
unlink($path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format the cached assets data the way it's supposed to be.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* Hashed key for cached asset
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private static function formatCachedAssets($key) {
|
||||||
|
return array(
|
||||||
|
'scripts' => array((object) array(
|
||||||
|
'path' => "/cachedassets/{$key}.js",
|
||||||
|
'version' => ''
|
||||||
|
)),
|
||||||
|
'styles' => array((object) array(
|
||||||
|
'path' => "/cachedassets/{$key}.css",
|
||||||
|
'version' => ''
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursive function for copying directories.
|
* Recursive function for copying directories.
|
||||||
*
|
*
|
||||||
|
|
|
@ -91,4 +91,32 @@ interface FileStorage {
|
||||||
* @param string $filename
|
* @param string $filename
|
||||||
*/
|
*/
|
||||||
public function deleteExport($filename);
|
public function deleteExport($filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will concatenate all JavaScrips and Stylesheets into two files in order
|
||||||
|
* to improve page performance.
|
||||||
|
*
|
||||||
|
* @param array $files
|
||||||
|
* A set of all the assets required for content to display
|
||||||
|
* @param string $key
|
||||||
|
* Hashed key for cached asset
|
||||||
|
*/
|
||||||
|
public function cacheAssets(&$files, $key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will check if there are cache assets available for content.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* Hashed key for cached asset
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getCachedAssets($key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the aggregated cache files.
|
||||||
|
*
|
||||||
|
* @param array $keys
|
||||||
|
* The hash keys of removed files
|
||||||
|
*/
|
||||||
|
public function deleteCachedAssets($keys);
|
||||||
}
|
}
|
||||||
|
|
|
@ -536,6 +536,29 @@ interface H5PFrameworkInterface {
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function isContentSlugAvailable($slug);
|
public function isContentSlugAvailable($slug);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores hash keys for cached assets, aggregated JavaScripts and
|
||||||
|
* stylesheets, and connects it to libraries so that we know which cache file
|
||||||
|
* to delete when a library is updated.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* Hash key for the given libraries
|
||||||
|
* @param array $libraries
|
||||||
|
* List of dependencies(libraries) used to create the key
|
||||||
|
*/
|
||||||
|
public function saveCachedAssets($key, $libraries);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locate hash keys for given library and delete them.
|
||||||
|
* Used when cache file are deleted.
|
||||||
|
*
|
||||||
|
* @param int $library_id
|
||||||
|
* Library identifier
|
||||||
|
* @return array
|
||||||
|
* List of hash keys removed
|
||||||
|
*/
|
||||||
|
public function deleteCachedAssets($library_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1345,6 +1368,12 @@ class H5PStorage {
|
||||||
// Save library folder
|
// Save library folder
|
||||||
$this->h5pC->fs->saveLibrary($library);
|
$this->h5pC->fs->saveLibrary($library);
|
||||||
|
|
||||||
|
// Remove cachedassets that uses this library
|
||||||
|
if ($this->h5pC->aggregateAssets && isset($library['libraryId'])) {
|
||||||
|
$removedKeys = $this->h5pF->deleteCachedAssets($library['libraryId']);
|
||||||
|
$this->h5pC->fs->deleteCachedAssets($removedKeys);
|
||||||
|
}
|
||||||
|
|
||||||
// Remove tmp folder
|
// Remove tmp folder
|
||||||
H5PCore::deleteFileTree($library['uploadDirectory']);
|
H5PCore::deleteFileTree($library['uploadDirectory']);
|
||||||
|
|
||||||
|
@ -1680,6 +1709,8 @@ class H5PCore {
|
||||||
$this->exportEnabled = $export;
|
$this->exportEnabled = $export;
|
||||||
$this->development_mode = $development_mode;
|
$this->development_mode = $development_mode;
|
||||||
|
|
||||||
|
$this->aggregateAssets = FALSE; // Off by default.. for now
|
||||||
|
|
||||||
if ($development_mode & H5PDevelopment::MODE_LIBRARY) {
|
if ($development_mode & H5PDevelopment::MODE_LIBRARY) {
|
||||||
$this->h5pD = new H5PDevelopment($this->h5pF, $path . '/', $language);
|
$this->h5pD = new H5PDevelopment($this->h5pF, $path . '/', $language);
|
||||||
}
|
}
|
||||||
|
@ -1909,9 +1940,7 @@ class H5PCore {
|
||||||
* @return array files.
|
* @return array files.
|
||||||
*/
|
*/
|
||||||
public function getDependenciesFiles($dependencies, $prefix = '') {
|
public function getDependenciesFiles($dependencies, $prefix = '') {
|
||||||
$aggregateAssets = TRUE;
|
if ($this->aggregateAssets) {
|
||||||
|
|
||||||
if ($aggregateAssets) {
|
|
||||||
// Get aggregated files for assets
|
// Get aggregated files for assets
|
||||||
$key = self::getDependenciesHash($dependencies);
|
$key = self::getDependenciesHash($dependencies);
|
||||||
|
|
||||||
|
@ -1938,11 +1967,12 @@ class H5PCore {
|
||||||
$this->getDependencyAssets($dependency, 'preloadedCss', $files['styles'], $prefix);
|
$this->getDependencyAssets($dependency, 'preloadedCss', $files['styles'], $prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($aggregateAssets) {
|
if ($this->aggregateAssets) {
|
||||||
// Aggregate and store assets
|
// Aggregate and store assets
|
||||||
$this->fs->cacheAssets($files, $key);
|
$this->fs->cacheAssets($files, $key);
|
||||||
|
|
||||||
// TODO: Update cache table
|
// Keep track of which libraries have been cached in case they are updated
|
||||||
|
$this->h5pF->saveCachedAssets($key, $dependencies);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $files;
|
return $files;
|
||||||
|
|
Loading…
Reference in New Issue