From 5e56b46696b7cb04075f2f14573baf337c3b5f62 Mon Sep 17 00:00:00 2001 From: Frode Petterson Date: Tue, 17 Feb 2015 09:32:11 +0100 Subject: [PATCH] Support namespaces/constructor. --- h5p.classes.php | 84 ++++++++++++++++++++++++++++++++++++++----------- js/h5p.js | 22 +++++++------ 2 files changed, 79 insertions(+), 27 deletions(-) diff --git a/h5p.classes.php b/h5p.classes.php index c54a92c..27eecd4 100644 --- a/h5p.classes.php +++ b/h5p.classes.php @@ -14,7 +14,7 @@ interface H5PFrameworkInterface { * - h5pVersion: The version of the H5P plugin/module */ public function getPlatformInfo(); - + /** * Fetches a file from a remote server using HTTP GET @@ -223,7 +223,7 @@ interface H5PFrameworkInterface { * - language(optional): associative array containing: * - languageCode: Translation in json format */ - public function saveLibraryData(&$libraryData, $new = TRUE); + public function saveLibraryData(&$libraryData, $preloadedJs, $preloadedCss, $dropLibraryCss, $embedTypes); /** * Insert new content. @@ -610,6 +610,7 @@ class H5PValidator { 'majorVersion' => '/^[0-9]{1,5}$/', 'minorVersion' => '/^[0-9]{1,5}$/', ), + 'constructor' => '/^[A-Z][a-zA-Z0-9]{1,126}$/', ); /** @@ -1308,28 +1309,28 @@ class H5PStorage { // Find local library identifier $libraryId = $this->h5pC->getLibraryId($library, $libString); - // Assume new library - $new = TRUE; if ($libraryId) { // Found old library $library['libraryId'] = $libraryId; - if ($this->h5pF->isPatchedLibrary($library)) { - // This is a newer version than ours. Upgrade! - $new = FALSE; - } - else { + if (!$this->h5pF->isPatchedLibrary($library)) { $library['saveDependencies'] = FALSE; // This is an older version, no need to save. continue; } + + $oldOnes++; } + else { + $newOnes++; + } + // This is a new library or a newer version, save it! // Indicate that the dependencies of this library should be saved. $library['saveDependencies'] = TRUE; // Save library meta data - $this->h5pF->saveLibraryData($library, $new); + $this->saveLibrary($library); // Make sure destination dir is free $destination_path = $libraries_path . DIRECTORY_SEPARATOR . H5PCore::libraryToString($library, TRUE); @@ -1338,13 +1339,6 @@ class H5PStorage { // Move library folder $this->h5pC->copyFileTree($library['uploadDirectory'], $destination_path); H5PCore::deleteFileTree($library['uploadDirectory']); - - if ($new) { - $newOnes++; - } - else { - $oldOnes++; - } } // Go through the libraries again to save dependencies. @@ -1389,6 +1383,54 @@ class H5PStorage { } } + /** + * Write library record to database. + * + * @param array $library + */ + private function saveLibrary($library) { + // Get CSV values to store in rows. + $preloadedJs = $this->objectsToCsv($library, 'preloadedJs', 'path'); + $preloadedCss = $this->objectsToCsv($library, 'preloadedCss', 'path'); + $dropLibraryCss = $this->objectsToCsv($library, 'dropLibraryCss', 'machineName'); + $embedTypes = $this->objectsToCsv($library, 'dropLibraryCss'); + if (!isset($library['semantics'])) { + $library['semantics'] = ''; + } + if (!isset($library['fullscreen'])) { + $library['fullscreen'] = 0; + } + if (!isset($library['constructor'])) { + $library['constructor'] = ''; + } + + $this->h5pF->saveLibraryData($library, $preloadedJs, $preloadedCss, $dropLibraryCss, $embedTypes); + } + + /** + * Converts file list to comma separated values. + * + * @param array $library + * @param string $list identifier + * @param string $property (optional) Object property to use as value + * @return string + */ + private function objectsToCsv($library, $list, $property = NULL) { + $csv = ''; + + if (isset($library[$list])) { + foreach ($library[$list] as $object) { + if ($csv !== '') { + $csv .= ', '; + } + + $csv .= $property === NULL ? $object : $object[$property]; + } + } + + return $csv; + } + /** * Delete an H5P package * @@ -1659,6 +1701,7 @@ class H5PCore { $content['library'] = array( 'id' => $content['libraryId'], 'name' => $content['libraryName'], + 'constructor' => $content['libraryConstructor'], 'majorVersion' => $content['libraryMajorVersion'], 'minorVersion' => $content['libraryMinorVersion'], 'embedTypes' => $content['libraryEmbedTypes'], @@ -2709,11 +2752,16 @@ class H5PContentValidator { $library = $this->libraries[$value->library]; } + if ($library['constructor']) { + // Update constructor + $value->constructor = $library['constructor']; + } + $this->validateGroup($value->params, (object) array( 'type' => 'group', 'fields' => $library['semantics'], ), FALSE); - $validkeys = array('library', 'params'); + $validkeys = array('library', 'constructor', 'params'); if (isset($semantics->extraAttributes)) { $validkeys = array_merge($validkeys, $semantics->extraAttributes); } diff --git a/js/h5p.js b/js/h5p.js index 5df3f2b..a630dff 100644 --- a/js/h5p.js +++ b/js/h5p.js @@ -55,6 +55,7 @@ H5P.init = function () { } var library = { library: contentData.library, + constructor: contentData.constructor, params: JSON.parse(contentData.jsonContent) }; @@ -165,7 +166,7 @@ H5P.init = function () { * 3. Create a separate Drupal module that is able to listen for events from * both div and iframe embedded content and send them to analytics (custom for Zavango) * 4. Move the event system code to a separate file (public) - * 5. Make sure the helper functions provides all the relevant data, example values + * 5. Make sure the helper functions provides all the relevant data, example values * and time spent (public) * 6. Add documentation to the functions (public) * 7. Add xAPI events to all the basic questiontype: @@ -396,6 +397,9 @@ H5P.newRunnable = function (library, contentId, $attachTo, skipResize) { var constructor; try { nameSplit = nameSplit[0].split('.'); + if (typeof library.constructor === 'string') { + nameSplit.push(library.constructor); + } constructor = window; for (var i = 0; i < nameSplit.length; i++) { constructor = constructor[nameSplit[i]]; @@ -409,7 +413,7 @@ H5P.newRunnable = function (library, contentId, $attachTo, skipResize) { } var instance = new constructor(library.params, contentId); - + if (instance.$ === undefined) { instance.$ = H5P.jQuery(instance); } @@ -442,7 +446,7 @@ H5P.newRunnable = function (library, contentId, $attachTo, skipResize) { * @returns {undefined} */ H5P.error = function (err) { - if (window['console'] !== undefined && console.error !== undefined) { + if (window.console !== undefined && console.error !== undefined) { console.error(err); } }; @@ -1087,7 +1091,7 @@ H5P.setFinished = function (contentId, score, maxScore, time) { var toUnix = function (date) { return Math.round(date.getTime() / 1000); }; - + // Post the results // TODO: Should we use a variable with the complete path? H5P.jQuery.post(H5P.ajaxPath + 'setFinished', { @@ -1134,9 +1138,9 @@ if (H5P.jQuery) { /** * Trigger an event on an instance - * + * * Helper function that triggers an event if the instance supports event handling - * + * * @param {function} instance * An H5P instance * @param {string} eventType @@ -1155,10 +1159,10 @@ H5P.trigger = function(instance, eventType) { /** * Register an event handler - * + * * Helper function that registers an event handler for an event type if * the instance supports event handling - * + * * @param {function} instance * An h5p instance * @param {string} eventType @@ -1175,4 +1179,4 @@ H5P.on = function(instance, eventType, handler) { else if (instance.$ !== undefined && instance.$.on !== undefined) { instance.$.on(eventType, handler) } -}; \ No newline at end of file +};