Merge branch 'without-pal' of github.com:h5p/h5p-php-library into user-results

Conflicts:
	js/h5p-content-upgrade.js
	styles/h5p-admin.css
d6
Frode Petterson 2014-10-16 16:11:12 +02:00
commit e6125f5c61
4 changed files with 239 additions and 232 deletions

View File

@ -30,7 +30,7 @@ class H5PDevelopment {
$this->findLibraries($filesPath . '/development');
}
}
/**
* Get contents of file.
*
@ -41,15 +41,15 @@ class H5PDevelopment {
if (file_exists($file) === FALSE) {
return NULL;
}
$contents = file_get_contents($file);
if ($contents === FALSE) {
return NULL;
}
return $contents;
}
/**
* Scans development directory and find all libraries.
*
@ -57,39 +57,39 @@ class H5PDevelopment {
*/
private function findLibraries($path) {
$this->libraries = array();
if (is_dir($path) === FALSE) {
return;
return;
}
$contents = scandir($path);
for ($i = 0, $s = count($contents); $i < $s; $i++) {
if ($contents[$i]{0} === '.') {
continue; // Skip hidden stuff.
}
$libraryPath = $path . '/' . $contents[$i];
$libraryJSON = $this->getFileContents($libraryPath . '/library.json');
if ($libraryJSON === NULL) {
continue; // No JSON file, skip.
}
$library = json_decode($libraryJSON, TRUE);
if ($library === FALSE) {
continue; // Invalid JSON.
}
// TODO: Validate props? Not really needed, is it? this is a dev site.
// Save/update library.
$library['libraryId'] = $this->h5pF->getLibraryId($library['machineName'], $library['majorVersion'], $library['minorVersion']);
$this->h5pF->saveLibraryData($library, $library['libraryId'] === FALSE);
$library['path'] = $libraryPath;
$this->libraries[H5PDevelopment::libraryToString($library['machineName'], $library['majorVersion'], $library['minorVersion'])] = $library;
}
// TODO: Should we remove libraries without files? Not really needed, but must be cleaned up some time, right?
// Go trough libraries and insert dependencies. Missing deps. will just be ignored and not available. (I guess?!)
@ -106,17 +106,17 @@ class H5PDevelopment {
}
// TODO: Deps must be inserted into h5p_nodes_libraries as well... ? But only if they are used?!
}
/**
* @return array Libraris in development folder.
*/
public function getLibraries() {
return $this->libraries;
}
/**
* Get library
*
*
* @param string $name of the library.
* @param int $majorVersion of the library.
* @param int $minorVersion of the library.
@ -126,10 +126,10 @@ class H5PDevelopment {
$library = H5PDevelopment::libraryToString($name, $majorVersion, $minorVersion);
return isset($this->libraries[$library]) === TRUE ? $this->libraries[$library] : NULL;
}
/**
* Get semantics for the given library.
*
*
* @param string $name of the library.
* @param int $majorVersion of the library.
* @param int $minorVersion of the library.
@ -137,32 +137,32 @@ class H5PDevelopment {
*/
public function getSemantics($name, $majorVersion, $minorVersion) {
$library = H5PDevelopment::libraryToString($name, $majorVersion, $minorVersion);
if (isset($this->libraries[$library]) === FALSE) {
return NULL;
}
return $this->getFileContents($this->libraries[$library]['path'] . '/semantics.json');
}
/**
* Get translations for the given library.
*
*
* @param string $name of the library.
* @param int $majorVersion of the library.
* @param int $minorVersion of the library.
* @return string Translation
*/
public function getLanguage($name, $majorVersion, $minorVersion) {
public function getLanguage($name, $majorVersion, $minorVersion, $language) {
$library = H5PDevelopment::libraryToString($name, $majorVersion, $minorVersion);
if (isset($this->libraries[$library]) === FALSE) {
return NULL;
}
return $this->getFileContents($this->libraries[$library]['path'] . '/language/' . $this->language . '.json');
return $this->getFileContents($this->libraries[$library]['path'] . '/language/' . $language . '.json');
}
/**
* Writes library as string on the form "name majorVersion.minorVersion"
*
@ -175,4 +175,3 @@ class H5PDevelopment {
return $name . ' ' . $majorVersion . '.' . $minorVersion;
}
}

View File

@ -55,31 +55,31 @@ interface H5PFrameworkInterface {
* @return string Path to the last uploaded h5p
*/
public function getUploadedH5pPath();
/**
* Get the list of the current installed libraries
*
*
* @return array Associative array containg one item per machine name. This item contains an array of libraries.
*/
public function loadLibraries();
/**
* Saving the unsupported library list
*
*
* @param array A list of unsupported libraries
*/
public function setUnsupportedLibraries($libraries);
/**
* Returns unsupported libraries
*
*
* @return array A list of the unsupported libraries
*/
public function getUnsupportedLibraries();
/**
* Returns the URL to the library admin page
*
*
* @return string URL to admin page
*/
public function getAdminUrl();
@ -108,7 +108,7 @@ interface H5PFrameworkInterface {
* @param string $defaultLibraryWhitelist
*/
public function getWhitelist($isLibrary, $defaultContentWhitelist, $defaultLibraryWhitelist);
/**
* Is the library a patched version of an existing library?
*
@ -147,23 +147,23 @@ interface H5PFrameworkInterface {
* Object holding the information that is to be stored
*/
public function saveLibraryData(&$libraryData, $new = TRUE);
/**
* Insert new content.
*
*
* @param object $content
* @param int $contentMainId
*/
public function insertContent($content, $contentMainId = NULL);
/**
* Update old content.
*
*
* @param object $content
* @param int $contentMainId
*/
public function updateContent($content, $contentMainId = NULL);
/**
* Save what libraries a library is dependending on
*
@ -219,11 +219,11 @@ interface H5PFrameworkInterface {
public function saveLibraryUsage($contentId, $librariesInUse);
/**
* Get number of content/nodes using a library, and the number of
* Get number of content/nodes using a library, and the number of
* dependencies to other libraries
*
*
* @param int $library_id
* @return array The array contains two elements, keyed by 'content' and 'libraries'.
* @return array The array contains two elements, keyed by 'content' and 'libraries'.
* Each element contains a number
*/
public function getLibraryUsage($libraryId);
@ -249,7 +249,7 @@ interface H5PFrameworkInterface {
* @return string semantics.
*/
public function loadLibrarySemantics($name, $majorVersion, $minorVersion);
/**
* Makes it possible to alter the semantics, adding custom fields, etc.
*
@ -267,21 +267,21 @@ interface H5PFrameworkInterface {
* Library Id
*/
public function deleteLibraryDependencies($libraryId);
/**
* Delete a library from database and file system
*
*
* @param mixed $library Library
*/
public function deleteLibrary($library);
/**
* Load content.
*
* @return object Content, null if not found.
*/
public function loadContent($id);
/**
* Load dependencies for the given content of the given type.
*
@ -290,49 +290,55 @@ interface H5PFrameworkInterface {
* @return array
*/
public function loadContentDependencies($id, $type = NULL);
/**
* Get data from cache.
*
* @param string $group
* @param string $key
* Get stored setting.
*
* @param string $name Identifier
* @param string $default Optional
* @return mixed data
*/
public function cacheGet($group, $key);
public function getOption($name, $default = NULL);
/**
* Store data in cache.
*
* @param string $group
* @param string $key
* @param mixed $data
* Stores the given setting.
* For example when did we last check h5p.org for updates to our libraries.
*
* @param string $name Identifier
* @param mixed $value Data
*/
public function cacheSet($group, $key, $data);
public function setOption($name, $value);
/**
* Delete data from cache.
*
* @param string $group
* @param string $key
* This will set the filtered parameters for the given content.
*
* @param int $content_id
* @param string $parameters filtered
*/
public function cacheDel($group, $key = NULL);
public function setFilteredParameters($content_id, $parameters = '');
/**
* Will invalidate the cache for the content that uses the specified library.
* This means that the content dependencies has to be rebuilt, and the parameters refiltered.
*
* Will clear filtered params for all the content that uses the specified
* library. This means that the content dependencies will have to be rebuilt,
* and the parameters refiltered.
*
* @param int $library_id
*/
public function invalidateContentCache($library_id);
public function clearFilteredParameters($library_id);
/**
* Get content without cache.
* Get number of contents that has to get their content dependencies rebuilt
* and parameters refiltered.
*
* @return int
*/
public function getNotCached();
public function getNumNotFiltered();
/**
* Get number of contents using library as main library.
*
*
* @param int $library_id
* @return int
*/
public function getNumContent($library_id);
}
@ -447,14 +453,14 @@ class H5PValidator {
// Extract and then remove the package file.
$zip = new ZipArchive;
// Only allow files with the .h5p extension:
if (strtolower(substr($tmpPath, -3)) !== 'h5p') {
$this->h5pF->setErrorMessage($this->h5pF->t('The file you uploaded is not a valid HTML5 Package (It does not have the .h5p file extension)'));
H5PCore::deleteFileTree($tmpDir);
return;
}
if ($zip->open($tmpPath) === true) {
$zip->extractTo($tmpDir);
$zip->close();
@ -482,7 +488,7 @@ class H5PValidator {
if ($skipContent === TRUE) {
continue;
}
$mainH5pData = $this->getJsonData($filePath);
if ($mainH5pData === FALSE) {
$valid = FALSE;
@ -540,7 +546,7 @@ class H5PValidator {
}
$libraryH5PData = $this->getLibraryData($file, $filePath, $tmpDir);
if ($libraryH5PData !== FALSE) {
// Library's directory name must be:
// - <machineName>
@ -576,7 +582,7 @@ class H5PValidator {
}
if ($valid) {
if ($upgradeOnly) {
// When upgrading, we opnly add allready installed libraries,
// When upgrading, we opnly add allready installed libraries,
// and new dependent libraries
$upgrades = array();
foreach ($libraries as &$library) {
@ -594,25 +600,25 @@ class H5PValidator {
}
}
}
$libraries = $upgrades;
}
$this->h5pC->librariesJsonData = $libraries;
if ($skipContent === FALSE) {
$this->h5pC->mainJsonData = $mainH5pData;
$this->h5pC->contentJsonData = $contentJsonData;
$libraries['mainH5pData'] = $mainH5pData; // Check for the dependencies in h5p.json as well as in the libraries
}
$missingLibraries = $this->getMissingLibraries($libraries);
foreach ($missingLibraries as $missing) {
if ($this->h5pF->getLibraryId($missing['machineName'], $missing['majorVersion'], $missing['minorVersion'])) {
unset($missingLibraries[H5PCore::libraryToString($missing)]);
}
}
if (!empty($missingLibraries)) {
foreach ($missingLibraries as $library) {
$this->h5pF->setErrorMessage($this->h5pF->t('Missing required library @library', array('@library' => H5PCore::libraryToString($library))));
@ -1021,7 +1027,7 @@ class H5PStorage {
public $h5pF;
public $h5pC;
public $contentId = NULL; // Quick fix so WP can get ID of new content.
/**
@ -1052,11 +1058,11 @@ class H5PStorage {
$library_saved = FALSE;
$upgradedLibsCount = 0;
$mayUpdateLibraries = $this->h5pF->mayUpdateLibraries();
foreach ($this->h5pC->librariesJsonData as &$library) {
$libraryId = $this->h5pF->getLibraryId($library['machineName'], $library['majorVersion'], $library['minorVersion']);
$library['saveDependencies'] = TRUE;
if (!$libraryId) {
$new = TRUE;
}
@ -1101,21 +1107,21 @@ class H5PStorage {
if (isset($library['editorDependencies'])) {
$this->h5pF->saveLibraryDependencies($library['libraryId'], $library['editorDependencies'], 'editor');
}
// Make sure libraries dependencies, parameter filtering and export files gets regenerated for all content who uses this library.
$this->h5pF->invalidateContentCache($library['libraryId']);
$this->h5pF->clearFilteredParameters($library['libraryId']);
$upgradedLibsCount++;
}
}
if (!$skipContent) {
$current_path = $this->h5pF->getUploadedH5pFolderPath() . DIRECTORY_SEPARATOR . 'content';
// Find out which libraries are used by this package/content
$librariesInUse = array();
$this->h5pC->findLibraryDependencies($librariesInUse, $this->h5pC->mainJsonData);
// Save content
if ($content === NULL) {
$content = array();
@ -1132,19 +1138,19 @@ class H5PStorage {
if (!is_dir($contents_path)) {
mkdir($contents_path, 0777, true);
}
// Move the content folder
$destination_path = $contents_path . DIRECTORY_SEPARATOR . $contentId;
@rename($current_path, $destination_path);
// Save the content library dependencies
$this->h5pF->saveLibraryUsage($contentId, $librariesInUse);
H5PCore::deleteFileTree($this->h5pF->getUploadedH5pFolderPath());
}
// Update supported library list if neccessary:
$this->h5pC->validateLibrarySupport(TRUE);
if ($upgradeOnly) {
// TODO - support translation
$this->h5pF->setInfoMessage($this->h5pF->t('@num libraries were upgraded!', array('@num' => $upgradedLibsCount)));
@ -1152,7 +1158,7 @@ class H5PStorage {
return $library_saved;
}
/**
* Delete an H5P package
*
@ -1221,7 +1227,7 @@ Class H5PExport {
$this->h5pF = $H5PFramework;
$this->h5pC = $H5PCore;
}
/**
* Return path to h5p package.
*
@ -1234,7 +1240,7 @@ Class H5PExport {
$h5pDir = $this->h5pF->getH5pPath() . DIRECTORY_SEPARATOR;
$tempPath = $h5pDir . 'temp' . DIRECTORY_SEPARATOR . $content['id'];
$zipPath = $h5pDir . 'exports' . DIRECTORY_SEPARATOR . $content['id'] . '.h5p';
// Temp dir to put the h5p files in
@mkdir($tempPath, 0777, TRUE);
@mkdir($h5pDir . 'exports', 0777, TRUE);
@ -1251,8 +1257,8 @@ Class H5PExport {
// Build h5p.json
$h5pJson = array (
'title' => $content['title'],
// TODO - stop using 'und', this is not the preferred way.
// Either remove language from the json if not existing, or use "language": null
// TODO - stop using 'und', this is not the preferred way.
// Either remove language from the json if not existing, or use "language": null
'language' => isset($content['language']) ? $content['language'] : 'und',
'mainLibrary' => $content['library']['name'],
'embedTypes' => $embedTypes,
@ -1261,7 +1267,7 @@ Class H5PExport {
// Add dependencies to h5p
foreach ($content['dependencies'] as $dependency) {
$library = $dependency['library'];
// Copy library to h5p
$source = isset($library['path']) ? $library['path'] : $h5pDir . 'libraries' . DIRECTORY_SEPARATOR . H5PCore::libraryToString($library, TRUE);
$destination = $tempPath . DIRECTORY_SEPARATOR . $library['machineName'];
@ -1269,7 +1275,7 @@ Class H5PExport {
// Do not add editor dependencies to h5p json.
if ($dependency['type'] === 'editor') {
continue;
continue;
}
$h5pJson[$dependency['type'] . 'Dependencies'][] = array(
@ -1333,7 +1339,7 @@ Class H5PExport {
*/
private function addEditorLibraries($libraries, $editorLibraries) {
foreach ($editorLibraries as $editorLibrary) {
$libraries[$editorLibrary['machineName']] = $editorLibrary;
$libraries[$editorLibrary['machineName']] = $editorLibrary;
}
return $libraries;
}
@ -1378,12 +1384,12 @@ class H5PCore {
*/
public function __construct($H5PFramework, $path, $language = 'en', $export = FALSE, $development_mode = H5PDevelopment::MODE_NONE) {
$this->h5pF = $H5PFramework;
$this->h5pF = $H5PFramework;
$this->path = $path;
$this->exportEnabled = $export;
$this->development_mode = $development_mode;
if ($development_mode & H5PDevelopment::MODE_LIBRARY) {
$this->h5pD = new H5PDevelopment($this->h5pF, $path, $language);
}
@ -1391,7 +1397,7 @@ class H5PCore {
/**
* Save content and clear cache.
*
*
* @param array $content
* @return int Content ID
*/
@ -1400,17 +1406,12 @@ class H5PCore {
$this->h5pF->updateContent($content, $contentMainId);
}
else {
$content['id'] = $this->h5pF->insertContent($content, $contentMainId);
$content['id'] = $this->h5pF->insertContent($content, $contentMainId);
}
if (!isset($content['filtered'])) {
// TODO: Add filtered to all impl. and remove
$this->h5pF->cacheDel('parameters', $content['id']);
}
return $content['id'];
}
/**
* Load content.
*
@ -1419,7 +1420,7 @@ class H5PCore {
*/
public function loadContent($id) {
$content = $this->h5pF->loadContent($id);
if ($content !== NULL) {
$content['library'] = array(
'id' => $content['libraryId'],
@ -1430,7 +1431,7 @@ class H5PCore {
'fullscreen' => $content['libraryFullscreen'],
);
unset($content['libraryId'], $content['libraryName'], $content['libraryEmbedTypes'], $content['libraryFullscreen']);
// // TODO: Move to filterParameters?
// if ($this->development_mode & H5PDevelopment::MODE_CONTENT) {
// // TODO: Remove Drupal specific stuff
@ -1444,29 +1445,21 @@ class H5PCore {
// }
// }
}
return $content;
}
/**
* Filter content run parameters, rebuild content dependecy cache and export file.
*
*
* @param Object $content
* @return Object NULL on failure.
*/
public function filterParameters($content) {
if (isset($content['filtered'])) {
$params = ($content['filtered'] === '' ? NULL : $content['filtered']);
}
else {
// TODO: Add filtered to all impl. and remove
$params = $this->h5pF->cacheGet('parameters', $content['id']);
if (isset($content['filtered']) && $content['filtered'] !== '') {
return $content['filtered'];
}
if ($params !== NULL) {
return $params;
}
// Validate and filter against main library semantics.
$validator = new H5PContentValidator($this->h5pF, $this);
$params = (object) array(
@ -1476,25 +1469,25 @@ class H5PCore {
$validator->validateLibrary($params, (object) array('options' => array($params->library)));
$params = json_encode($params->params);
// Update content dependencies.
$content['dependencies'] = $validator->getDependencies();
$this->h5pF->deleteLibraryUsage($content['id']);
$this->h5pF->saveLibraryUsage($content['id'], $content['dependencies']);
if ($this->exportEnabled) {
// Recreate export file
$exporter = new H5PExport($this->h5pF, $this);
$exporter->createExportFile($content);
// TODO: Should we rather create the file once first accessed, like imagecache?
}
// Cache.
$this->h5pF->cacheSet('parameters', $content['id'], $params);
$this->h5pF->setFilteredParameters($content['id'], $params);
return $params;
}
/**
* Find the files required for this content to work.
*
@ -1503,10 +1496,10 @@ class H5PCore {
*/
public function loadContentDependencies($id, $type = NULL) {
$dependencies = $this->h5pF->loadContentDependencies($id, $type);
if ($this->development_mode & H5PDevelopment::MODE_LIBRARY) {
$developmentLibraries = $this->h5pD->getLibraries();
foreach ($dependencies as $key => $dependency) {
$libraryString = H5PCore::libraryToString($dependency);
if (isset($developmentLibraries[$libraryString])) {
@ -1515,13 +1508,13 @@ class H5PCore {
}
}
}
return $dependencies;
}
/**
* Get all dependency assets of the given type
*
*
* @param array $dependency
* @param string $type
* @param array $assets
@ -1531,12 +1524,12 @@ class H5PCore {
if (empty($dependency[$type]) || $dependency[$type][0] === '') {
return;
}
// Check if we should skip CSS.
if ($type === 'preloadedCss' && (isset($dependency['dropCss']) && $dependency['dropCss'] === '1')) {
return;
}
foreach ($dependency[$type] as $file) {
$assets[] = (object) array(
'path' => $dependency['path'] . '/' . trim(is_array($file) ? $file['path'] : $file),
@ -1544,23 +1537,23 @@ class H5PCore {
);
}
}
/**
* Combines path with cache buster / version.
*
*
* @param array $assets
* @return array
*/
public function getAssetsUrls($assets) {
$urls = array();
foreach ($assets as $asset) {
$urls[] = $asset->path . $asset->version;
}
return $urls;
}
/**
* Return file paths for all dependecies files.
*
@ -1578,14 +1571,14 @@ class H5PCore {
$dependency['preloadedJs'] = explode(',', $dependency['preloadedJs']);
$dependency['preloadedCss'] = explode(',', $dependency['preloadedCss']);
}
$dependency['version'] = "?ver={$dependency['majorVersion']}.{$dependency['minorVersion']}.{$dependency['patchVersion']}";
$this->getDependencyAssets($dependency, 'preloadedJs', $files['scripts']);
$this->getDependencyAssets($dependency, 'preloadedCss', $files['styles']);
}
return $files;
}
/**
* Load library semantics.
*
@ -1597,20 +1590,20 @@ class H5PCore {
// Try to load from dev lib
$semantics = $this->h5pD->getSemantics($name, $majorVersion, $minorVersion);
}
if ($semantics === NULL) {
// Try to load from DB.
$semantics = $this->h5pF->loadLibrarySemantics($name, $majorVersion, $minorVersion);
}
if ($semantics !== NULL) {
$semantics = json_decode($semantics);
$this->h5pF->alterLibrarySemantics($semantics, $name, $majorVersion, $minorVersion);
}
return $semantics;
}
/**
* Load library.
*
@ -1625,31 +1618,31 @@ class H5PCore {
$library['semantics'] = $this->h5pD->getSemantics($name, $majorVersion, $minorVersion);
}
}
if ($library === NULL) {
// Try to load from DB.
$library = $this->h5pF->loadLibrary($name, $majorVersion, $minorVersion);
}
return $library;
}
/**
* Deletes a library
*
*
* @param unknown $libraryId
*/
public function deleteLibrary($libraryId) {
$this->h5pF->deleteLibrary($libraryId);
// Force update of unsupported libraries list:
$this->validateLibrarySupport(TRUE);
}
/**
* Recursive. Goes through the dependency tree for the given library and
* Recursive. Goes through the dependency tree for the given library and
* adds all the dependencies to the given array in a flat format.
*
*
* @param array $librariesUsed Flat list of all dependencies.
* @param array $library To find all dependencies for.
* @param bool $editor Used interally to force all preloaded sub dependencies of an editor dependecy to be editor dependencies.
@ -1660,18 +1653,18 @@ class H5PCore {
if (!isset($library[$property])) {
continue; // Skip, no such dependencies.
}
if ($type === 'preloaded' && $editor === TRUE) {
// All preloaded dependencies of an editor library is set to editor.
$type = 'editor';
}
foreach ($library[$property] as $dependency) {
$dependencyKey = $type . '-' . $dependency['machineName'];
if (isset($dependencies[$dependencyKey]) === TRUE) {
continue; // Skip, already have this.
}
$dependencyLibrary = $this->loadLibrary($dependency['machineName'], $dependency['majorVersion'], $dependency['minorVersion']);
if ($dependencyLibrary) {
$dependencies[$dependencyKey] = array(
@ -1800,7 +1793,7 @@ class H5PCore {
}
return FALSE;
}
/**
* Determine the correct embed type to use.
*
@ -1809,32 +1802,32 @@ class H5PCore {
public static function determineEmbedType($contentEmbedType, $libraryEmbedTypes) {
// Detect content embed type
$embedType = strpos(strtolower($contentEmbedType), 'div') !== FALSE ? 'div' : 'iframe';
if ($libraryEmbedTypes !== NULL && $libraryEmbedTypes !== '') {
// Check that embed type is available for library
$embedTypes = strtolower($libraryEmbedTypes);
if (strpos($embedTypes, $embedType) === FALSE) {
// Not available, pick default.
$embedType = strpos($embedTypes, 'div') !== FALSE ? 'div' : 'iframe';
}
}
}
return $embedType;
}
/**
* Get the absolute version for the library as a human readable string.
*
*
* @param object $library
* @return string
*/
public static function libraryVersion($library) {
return $library->major_version . '.' . $library->minor_version . '.' . $library->patch_version;
}
/**
* Detemine which versions content with the given library can be upgraded to.
*
*
* @param object $library
* @param array $versions
* @return array
@ -1850,13 +1843,13 @@ class H5PCore {
return $upgrades;
}
/**
* Converts all the properties of the given object or array from
* snake_case to camelCase. Useful after fetching data from the database.
*
*
* Note that some databases does not support camelCase.
*
*
* @param mixed $arr input
* @param boolean $obj return object
* @return mixed object or array
@ -1875,36 +1868,36 @@ class H5PCore {
return $obj ? (object) $newArr : $newArr;
}
/**
* Check if currently installed H5P libraries are supported by
* the current versjon of core. Which versions of which libraries are supported is
* defined in the library-support.json file.
*
* @param boolean If TRUE, unsupported libraries list are rebuilt. If FALSE, list is
* @param boolean If TRUE, unsupported libraries list are rebuilt. If FALSE, list is
* rebuilt only if non-existing
*/
public function validateLibrarySupport($force = false) {
if (!($this->h5pF->getUnsupportedLibraries() === NULL || $force)) {
return;
}
$minVersions = $this->getMinimumVersionsSupported(realpath(dirname(__FILE__)) . '/library-support.json');
if ($minVersions === NULL) {
return;
}
// Get all libraries installed, check if any of them is not supported:
$libraries = $this->h5pF->loadLibraries();
$unsupportedLibraries = array();
// Iterate over all installed libraries
foreach ($libraries as $library_name => $versions) {
if (!isset($minVersions[$library_name])) {
continue;
}
$min = $minVersions[$library_name];
// For each version of this library, check if it is supported
foreach ($versions as $library) {
if (!$this->isLibraryVersionSupported($library, $min->versions)) {
@ -1920,23 +1913,23 @@ class H5PCore {
);
}
}
$this->h5pF->setUnsupportedLibraries(empty($unsupportedLibraries) ? NULL : $unsupportedLibraries);
}
}
/**
* Returns a list of the minimum version of libraries that are supported.
* This is needed because some old libraries are no longer supported by core.
*
*
* TODO: Make it possible for the systems to cache this list between requests.
*
*
* @param string $path to json file
* @return array indexed using library names
*/
public function getMinimumVersionsSupported($path) {
$minSupported = array();
// Get list of minimum version for libraries. Some old libraries are no longer supported.
$libraries = file_get_contents($path);
if ($libraries !== FALSE) {
@ -1950,13 +1943,13 @@ class H5PCore {
}
}
}
return empty($minSupported) ? NULL : $minSupported;
}
/**
* Check if a specific version of a library is supported
*
*
* @param object library
* @param array An array containing versions
* @return boolean TRUE if supported, otherwise FALSE
@ -1969,37 +1962,37 @@ class H5PCore {
// --- minor is higher than any minimumversion for a given major
// --- major and minor equals and patch is >= supported
$major_supported |= ($library->major_version > $minimumVersion->major);
if ($library->major_version == $minimumVersion->major) {
$minor_supported |= ($library->minor_version > $minimumVersion->minor);
}
if ($library->major_version == $minimumVersion->major &&
$library->minor_version == $minimumVersion->minor) {
$patch_supported |= ($library->patch_version >= $minimumVersion->patch);
}
}
return ($patch_supported || $minor_supported || $major_supported);
}
/**
* Helper function for creating markup for the unsupported libraries list
*
* Helper function for creating markup for the unsupported libraries list
*
* TODO: Make help text translatable
*
*
* @return string Html
* */
public function createMarkupForUnsupportedLibraryList($libraries) {
$html = '<div><span>The following versions of H5P libraries are not supported anymore:<span><ul>';
foreach ($libraries as $library) {
$downloadUrl = $library['downloadUrl'];
$libraryName = $library['name'];
$currentVersion = $library['currentVersion']['major'] . '.' . $library['currentVersion']['minor'] .'.' . $library['currentVersion']['patch'];
$html .= "<li><a href=\"$downloadUrl\">$libraryName</a> ($currentVersion)</li>";
}
$html .= '</ul><span><br>These libraries may cause problems on this site. See <a href="http://h5p.org/releases/h5p-core-1.3">here</a> for more info</div>';
return $html;
}
@ -2038,24 +2031,24 @@ class H5PContentValidator {
'select' => 'validateSelect',
'library' => 'validateLibrary',
);
// Keep track of the libraries we load to avoid loading it multiple times.
$this->libraries = array();
// TODO: Should this possible be done in core's loadLibrary? This might be done multiple places.
// Keep track of all dependencies for the given content.
$this->dependencies = array();
}
/**
* Get the flat dependecy tree.
*
*
* @return array
*/
public function getDependencies() {
return $this->dependencies;
}
/**
* Validate given text value against text semantics.
*/
@ -2280,19 +2273,19 @@ class H5PContentValidator {
$validkeys = array_merge($validkeys, $semantics->extraAttributes); // TODO: Validate extraAttributes
}
$this->filterParams($file, $validkeys);
if (isset($file->width)) {
$file->width = intval($file->width);
}
if (isset($file->height)) {
$file->height = intval($file->height);
}
if (isset($file->codecs)) {
$file->codecs = htmlspecialchars($file->codecs, ENT_QUOTES, 'UTF-8', FALSE);
}
if (isset($file->quality)) {
if (!is_object($file->quality) || !isset($file->quality->level) || !isset($file->quality->label)) {
unset($file->quality);
@ -2303,7 +2296,7 @@ class H5PContentValidator {
$file->quality->label = htmlspecialchars($file->quality->label, ENT_QUOTES, 'UTF-8', FALSE);
}
}
if (isset($file->copyright)) {
$this->validateGroup($file->copyright, H5PContentValidator::getCopyrightSemantics());
}
@ -2406,11 +2399,11 @@ class H5PContentValidator {
$value = new stdClass();
return;
}
if (!isset($this->libraries[$value->library])) {
$libspec = H5PCore::libraryFromString($value->library);
$library = $this->h5pC->loadLibrary($libspec['machineName'], $libspec['majorVersion'], $libspec['minorVersion']);
$library['semantics'] = json_decode($library['semantics']);
$library['semantics'] = $this->h5pC->loadLibrarySemantics($libspec['machineName'], $libspec['majorVersion'], $libspec['minorVersion']);
$this->libraries[$value->library] = $library;
// Find all dependencies for this library
@ -2700,7 +2693,7 @@ class H5PContentValidator {
/**
* Processes an HTML attribute value and strips dangerous protocols from URLs.
*
*
* @param $string
* The string with the attribute value.
* @param $decode
@ -2773,10 +2766,10 @@ class H5PContentValidator {
return $uri;
}
public static function getCopyrightSemantics() {
static $semantics;
if ($semantics === NULL) {
$semantics = (object) array(
'name' => 'copyright',
@ -2874,7 +2867,7 @@ class H5PContentValidator {
)
);
}
return $semantics;
}
}

View File

@ -213,18 +213,28 @@ var H5PUpgrades = H5PUpgrades || {};
var current = 0; // Track progress
asyncSerial(parameters, function (id, params, next) {
// Make params possible to work with
params = JSON.parse(params);
try {
// Make params possible to work with
params = JSON.parse(params);
if (!(params instanceof Object)) {
throw true;
}
}
catch (event) {
return next(info.errorContent.replace('%id', id) + ' ' + info.errorParamsBroken);
}
// Upgrade this content.
self.upgrade(info.library.name, new Version(info.library.version), self.version, params, function (err, params) {
if (!err) {
upgraded[id] = JSON.stringify(params);
current++;
self.throbber.setProgress(Math.round((info.total - self.left + current) / (info.total / 100)) + ' %');
if (err) {
return next(info.errorContent.replace('%id', id) + ' ' + err);
}
next(err);
upgraded[id] = JSON.stringify(params);
current++;
self.throbber.setProgress(Math.round((info.total - self.left + current) / (info.total / 100)) + ' %');
next();
});
}, function (err) {
@ -375,14 +385,16 @@ var H5PUpgrades = H5PUpgrades || {};
}
else {
// We found an upgrade hook, run it
if (upgrade.contentUpgrade !== undefined && typeof upgrade.contentUpgrade === 'function') {
upgrade.contentUpgrade(params, function (err, upgradedParams) {
var unnecessaryWrapper = (upgrade.contentUpgrade !== undefined ? upgrade.contentUpgrade : upgrade);
try {
unnecessaryWrapper(params, function (err, upgradedParams) {
params = upgradedParams;
nextMinor(err);
});
}
else {
nextMinor(info.errorScript.replace('%lib', library.name + ' ' + newVersion));
catch (err) {
next(err);
}
}
}, nextMajor);

View File

@ -246,6 +246,9 @@ button.h5p-admin.disabled:hover {
font-size: 1.5em;
font-weight: bold;
}
#h5p-admin-container .h5p-admin-center {
text-align: center;
}
.h5p-pagination {
text-align: center;
}