Merge branch 'master' of ssh://stash.amendor.com:7999/h5p/h5p-core-php
commit
f60bc3939b
143
h5p.classes.php
143
h5p.classes.php
|
@ -219,6 +219,34 @@ interface H5PFrameworkInterface {
|
|||
* Library Id
|
||||
*/
|
||||
public function deleteLibraryDependencies($libraryId);
|
||||
|
||||
/**
|
||||
* Get all the data we need to export H5P
|
||||
*
|
||||
* @param int $contentId
|
||||
* ContentID of the node we are going to export
|
||||
* @param string $title
|
||||
* Title of the node to export
|
||||
* @param string $language
|
||||
* Language of the node to export
|
||||
* @return array
|
||||
* An array with all the data needed to export the h5p in the following format:
|
||||
* 'title' => string,
|
||||
* 'contentId' => string/int,
|
||||
* 'mainLibrary' => string (machine name for main library),
|
||||
* 'embedType' => string,
|
||||
* 'libraries' => array(
|
||||
* 'machineName' => string,
|
||||
* 'majorVersion' => int,
|
||||
* 'minorVersion' => int,
|
||||
* 'preloaded' => int(0|1),
|
||||
* 'language' => string,
|
||||
*/
|
||||
public function getExportData($contentId, $title, $language);
|
||||
/**
|
||||
* Check if export is enabled.
|
||||
*/
|
||||
public function isExportEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -244,7 +272,7 @@ class H5PValidator {
|
|||
private $h5pOptional = array(
|
||||
'contentType' => '/^.{1,255}$/',
|
||||
'author' => '/^.{1,255}$/',
|
||||
'license' => '/^(cc-by|cc-by-sa|cc-by-nd|cc-by-nc|cc-by-nc-sa|cc-by-nc-nd|pd|cr|MIT)$/',
|
||||
'license' => '/^(cc-by|cc-by-sa|cc-by-nd|cc-by-nc|cc-by-nc-sa|cc-by-nc-nd|pd|cr|MIT|GPL1|GPL2|GPL3|MPL|MPL2)$/',
|
||||
'dynamicDependencies' => array(
|
||||
'machineName' => '/^[\w0-9\-\.]{1,255}$/i',
|
||||
'majorVersion' => '/^[0-9]{1,5}$/',
|
||||
|
@ -268,7 +296,7 @@ class H5PValidator {
|
|||
|
||||
private $libraryOptional = array(
|
||||
'author' => '/^.{1,255}$/',
|
||||
'license' => '/^(cc-by|cc-by-sa|cc-by-nd|cc-by-nc|cc-by-nc-sa|cc-by-nc-nd|pd|cr|MIT|GPL1|GPL2|GPL3)$/',
|
||||
'license' => '/^(cc-by|cc-by-sa|cc-by-nd|cc-by-nc|cc-by-nc-sa|cc-by-nc-nd|pd|cr|MIT|GPL1|GPL2|GPL3|MPL|MPL2)$/',
|
||||
'description' => '/^.{1,}$/',
|
||||
'dynamicDependencies' => array(
|
||||
'machineName' => '/^[\w0-9\-\.]{1,255}$/i',
|
||||
|
@ -1003,6 +1031,110 @@ class H5PStorage {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is used for exporting zips
|
||||
*/
|
||||
Class H5PExport {
|
||||
public $h5pF;
|
||||
public $h5pC;
|
||||
|
||||
/**
|
||||
* Constructor for the H5PExport
|
||||
*
|
||||
* @param object $H5PFramework
|
||||
* The frameworks implementation of the H5PFrameworkInterface
|
||||
* @param H5PCore
|
||||
* Reference to an insance of H5PCore
|
||||
*/
|
||||
public function __construct($H5PFramework, $H5PCore) {
|
||||
$this->h5pF = $H5PFramework;
|
||||
$this->h5pC = $H5PCore;
|
||||
}
|
||||
/**
|
||||
* Create the H5P package
|
||||
*
|
||||
* @param object $exportData
|
||||
* The data to be exported.
|
||||
* @return H5P package.
|
||||
*/
|
||||
public function exportToZip($exportData) {
|
||||
$h5pDir = $this->h5pF->getH5pPath() . DIRECTORY_SEPARATOR;
|
||||
$tempPath = $h5pDir . 'temp' . DIRECTORY_SEPARATOR . $exportData['contentId'];
|
||||
$zipPath = $h5pDir . 'exports' . DIRECTORY_SEPARATOR . $exportData['contentId'] . '.h5p';
|
||||
// Check if h5p-package already exists.
|
||||
if (!file_exists($zipPath) == true) {
|
||||
// Temp dir to put the h5p files in
|
||||
@mkdir($tempPath);
|
||||
$this->h5pC->copyTree($h5pDir . 'content' . DIRECTORY_SEPARATOR . $exportData['contentId'], $tempPath . DIRECTORY_SEPARATOR . 'content');
|
||||
// Copies libraries to temp dir and create mention in h5p.json
|
||||
foreach($exportData['libraries'] as $library) {
|
||||
$source = $h5pDir . 'libraries' . DIRECTORY_SEPARATOR . $library['machineName'] . '-' . $library['majorVersion'] . '.' . $library['minorVersion'];
|
||||
$destination = $tempPath . DIRECTORY_SEPARATOR . $library['machineName'];
|
||||
$this->h5pC->copyTree($source, $destination);
|
||||
|
||||
// Set preloaded and dynamic dependencies
|
||||
if ($library['preloaded']) {
|
||||
$preloadedDependencies[] = array(
|
||||
'machineName' => $library['machineName'],
|
||||
'majorVersion' => $library['majorVersion'],
|
||||
'minorVersion' => $library['minorVersion'],
|
||||
);
|
||||
} else {
|
||||
$dynamicDependencies[] = array(
|
||||
'machineName' => $library['machineName'],
|
||||
'majorVersion' => $library['majorVersion'],
|
||||
'minorVersion' => $library['minorVersion'],
|
||||
);
|
||||
}
|
||||
}
|
||||
// Make embedTypes into an array
|
||||
$embedTypes = explode(', ', $exportData['embedType']);
|
||||
|
||||
// Build h5p.json
|
||||
$h5pJson = array (
|
||||
'title' => $exportData['title'],
|
||||
'language' => $exportData['language'],
|
||||
'mainLibrary' => $exportData['mainLibrary'],
|
||||
'embedTypes' => $embedTypes,
|
||||
);
|
||||
// Add preloaded and dynamic dependencies if they exist
|
||||
if ($preloadedDependencies) { $h5pJson['preloadedDependencies'] = $preloadedDependencies; }
|
||||
if ($dynamicDependencies) { $h5pJson['dynamicDependencies'] = $dynamicDependencies; }
|
||||
|
||||
// Save h5p.json
|
||||
$results = print_r(json_encode($h5pJson), true);
|
||||
file_put_contents($tempPath . DIRECTORY_SEPARATOR . 'h5p.json', $results);
|
||||
|
||||
// Create new zip instance.
|
||||
$zip = new ZipArchive();
|
||||
$zip->open($zipPath, ZIPARCHIVE::CREATE);
|
||||
|
||||
// Get all files and folders in $tempPath
|
||||
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($tempPath . DIRECTORY_SEPARATOR));
|
||||
// Add files to zip
|
||||
foreach ($iterator as $key=>$value) {
|
||||
$test = '.';
|
||||
// Do not add the folders '.' and '..' to the zip. This will make zip invalid.
|
||||
if (substr_compare($key, $test, -strlen($test), strlen($test)) !== 0) {
|
||||
// Get files path in $tempPath
|
||||
$filePath = explode($tempPath . DIRECTORY_SEPARATOR, $key);
|
||||
// Add files to the zip with the intended file-structure
|
||||
$zip->addFile($key, $filePath[1]);
|
||||
}
|
||||
}
|
||||
// Close zip and remove temp dir
|
||||
$zip->close();
|
||||
@rmdir($tempPath);
|
||||
}
|
||||
|
||||
// Set headers for automagic download!!
|
||||
header('Content-Description: File Transfer');
|
||||
header('Content-Type: application/zip');
|
||||
header('Content-Disposition: attachment; filename="' . $exportData['title'] . '.h5p"');
|
||||
readfile ($zipPath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions and storage shared by the other H5P classes
|
||||
*/
|
||||
|
@ -1225,6 +1357,9 @@ class H5PContentValidator {
|
|||
if (in_array('ul', $tags) || in_array('ol', $tags) && ! in_array('li', $tags)) {
|
||||
$tags[] = 'li';
|
||||
}
|
||||
if (in_array('del', $tags) || in_array('strike', $tags) && ! in_array('s', $tags)) {
|
||||
$tags[] = 's';
|
||||
}
|
||||
// Strip invalid HTML tags.
|
||||
$text = $this->filter_xss($text, $tags);
|
||||
}
|
||||
|
@ -1240,7 +1375,9 @@ class H5PContentValidator {
|
|||
|
||||
// Check if string is according to optional regexp in semantics
|
||||
if (isset($semantics->regexp)) {
|
||||
$pattern = '|' . $semantics->regexp->pattern . '|';
|
||||
// Note: '|' used as regexp fence, to allow / in actual patterns.
|
||||
// But also escaping '|' found in patterns, so that is valid too.
|
||||
$pattern = '|' . str_replace('|', '\\|', $semantics->regexp->pattern) . '|';
|
||||
$pattern .= isset($semantics->regexp->modifiers) ? $semantics->regexp->modifiers : '';
|
||||
if (preg_match($pattern, $text) === 0) {
|
||||
// Note: explicitly ignore return value FALSE, to avoid removing text
|
||||
|
|
37
js/h5p.js
37
js/h5p.js
|
@ -1,7 +1,7 @@
|
|||
var H5P = H5P || {};
|
||||
|
||||
// This needs to be determined before init is run.
|
||||
H5P.isFramed = (window.parent !== window);
|
||||
H5P.isFramed = (window.self !== window.top); // (window.parent !== window);
|
||||
|
||||
// Initialize H5P content
|
||||
// Scans for ".h5p-content"
|
||||
|
@ -62,36 +62,35 @@ H5P.init = function () {
|
|||
H5P.fullScreen($el, obj);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// H5Ps living in iframes. Note: Fullscreen button will be added
|
||||
// inside iFrame if relevant
|
||||
var $h5pIframes = H5P.jQuery(".h5p-iframe");
|
||||
$h5pIframes.each(function (idx, iframe) {
|
||||
var $iframe = H5P.jQuery(iframe),
|
||||
contentId = $iframe.data('content-id'),
|
||||
mainLibrary = $iframe.data('class');
|
||||
if ($h5pIframes.length !== 0) {
|
||||
$h5pIframes.each(function (idx, iframe) {
|
||||
var $iframe = H5P.jQuery(iframe),
|
||||
contentId = $iframe.data('content-id'),
|
||||
mainLibrary = $iframe.data('class');
|
||||
|
||||
// Get iFrame body, and reset it to contain only the normal H5P DIV.
|
||||
$iframe.contents().find('body')
|
||||
.html('<div class="h5p-content" data-class="' + mainLibrary + '" data-content-id="' + contentId + '"/>');
|
||||
iframe.contentDocument.open();
|
||||
iframe.contentDocument.write('<!doctype html><html><head>' + H5PIntegration.getHeadTags(contentId) + '</head><body><div class="h5p-content" data-class="' + mainLibrary + '" data-content-id="' + contentId + '"/></body></html>');
|
||||
iframe.contentDocument.close();
|
||||
});
|
||||
|
||||
// Add scripts required for this iFrame from settings
|
||||
H5PIntegration.addFilesToIframe($iframe, contentId);
|
||||
});
|
||||
if ($h5pIframes.length > 0) {
|
||||
// TODO: This seems very hacky... why can't we just use the resize event? What happens if we ain't done before the next interval starts?
|
||||
setInterval(function h5pIframeResizer() {
|
||||
setInterval(function () {
|
||||
$h5pIframes.each(function (idx, iframe) {
|
||||
var contentHeight = iframe.contentDocument.body.offsetHeight;
|
||||
var frameHeight = H5P.jQuery(iframe).innerHeight();
|
||||
var $iframe = H5P.jQuery(iframe);
|
||||
var contentHeight = $iframe.contents().height();
|
||||
var frameHeight = $iframe.innerHeight();
|
||||
|
||||
if (frameHeight !== contentHeight) {
|
||||
H5P.resizeIframe(H5P.jQuery(iframe).data('content-id'), contentHeight);
|
||||
H5P.resizeIframe($iframe.data('content-id'), contentHeight);
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
}, 250);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -429,7 +428,7 @@ if (String.prototype.trim === undefined) {
|
|||
|
||||
// Finally, we want to run init when document is ready. But not if we're
|
||||
// in an iFrame. Then we wait for parent to start init().
|
||||
if (H5P.jQuery && !H5P.isFramed) {
|
||||
if (H5P.jQuery) {
|
||||
H5P.jQuery(document).ready(function () {
|
||||
if (!H5P.initialized) {
|
||||
H5P.initialized = true;
|
||||
|
|
|
@ -60,7 +60,8 @@ div.h5p-semi-fullscreen {
|
|||
height: 100%;
|
||||
}
|
||||
.h5p-iframe-wrapper {
|
||||
width: auto; height: auto;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.h5p-fullscreen .h5p-iframe-wrapper,
|
||||
|
@ -91,6 +92,8 @@ div.h5p-semi-fullscreen {
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 10;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
}
|
||||
.h5p-iframe-wrapper.h5p-semi-fullscreen .buttons button:before {
|
||||
content: 'Exit ';
|
||||
|
|
Loading…
Reference in New Issue