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.
|
||||
*
|
||||
|
|
|
@ -91,4 +91,32 @@ interface FileStorage {
|
|||
* @param string $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
|
||||
*/
|
||||
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
|
||||
$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
|
||||
H5PCore::deleteFileTree($library['uploadDirectory']);
|
||||
|
||||
|
@ -1680,6 +1709,8 @@ class H5PCore {
|
|||
$this->exportEnabled = $export;
|
||||
$this->development_mode = $development_mode;
|
||||
|
||||
$this->aggregateAssets = FALSE; // Off by default.. for now
|
||||
|
||||
if ($development_mode & H5PDevelopment::MODE_LIBRARY) {
|
||||
$this->h5pD = new H5PDevelopment($this->h5pF, $path . '/', $language);
|
||||
}
|
||||
|
@ -1909,9 +1940,7 @@ class H5PCore {
|
|||
* @return array files.
|
||||
*/
|
||||
public function getDependenciesFiles($dependencies, $prefix = '') {
|
||||
$aggregateAssets = TRUE;
|
||||
|
||||
if ($aggregateAssets) {
|
||||
if ($this->aggregateAssets) {
|
||||
// Get aggregated files for assets
|
||||
$key = self::getDependenciesHash($dependencies);
|
||||
|
||||
|
@ -1938,11 +1967,12 @@ class H5PCore {
|
|||
$this->getDependencyAssets($dependency, 'preloadedCss', $files['styles'], $prefix);
|
||||
}
|
||||
|
||||
if ($aggregateAssets) {
|
||||
if ($this->aggregateAssets) {
|
||||
// Aggregate and store assets
|
||||
$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;
|
||||
|
|
Loading…
Reference in New Issue