You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

210 lines
5.5 KiB

<?php
// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
//
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id$
class ScormLib
{
public function handle_file_creation($args)
{
if ($metadata = $this->getRequestMetadata($args)) {
$this->createItem(
$metadata,
[
'scormPackage' => $args['object'],
]
);
}
}
public function handle_file_update($args)
{
if (isset($args['initialFileId']) && $metadata = $this->getRequestMetadata($args)) {
$relationlib = TikiLib::lib('relation');
$items = $relationlib->get_relations_to('file', $args['initialFileId'], 'tiki.file.attach');
$transaction = TikiDb::get()->begin();
foreach ($items as $item) {
if ($item['type'] == 'trackeritem') {
$this->updateItem(
$item['itemId'],
$metadata,
[
'scormPackage' => $args['object'],
]
);
}
}
$transaction->commit();
}
}
private function getRequestMetadata($args)
{
$metadata = null;
$file = \Tiki\FileGallery\File::id($args['object']);
if (
$this->isZipFile($args)
&& $zip = $this->getZipFile($file)
) {
if ($manifest = $this->getScormManifest($zip)) {
$metadata = $this->getMetadata($manifest);
}
$zip->close();
}
return $metadata;
}
private function isZipFile($args)
{
if (! isset($args['filetype'])) {
return false;
}
return in_array($args['filetype'], ['application/zip', 'application/x-zip', 'application/x-zip-compressed']);
}
private function getZipFile($file)
{
global $prefs;
if (! class_exists('ZipArchive')) {
return null;
}
$zip = new ZipArchive();
$filepath = $file->getWrapper()->getReadableFile();
if ($zip->open($filepath) === true) {
return $zip;
}
}
private function getScormManifest($zip)
{
return $zip->getFromName('imsmanifest.xml');
}
private function getMetadata($manifest)
{
$dom = new DOMDocument();
$dom->loadXML($manifest);
$metadata = [];
foreach ($dom->getElementsByTagName('general')->item(0)->childNodes as $node) {
if ($node instanceof DOMElement) {
$metadata[$this->getKey($node)][] = $this->getData($node);
}
}
return $metadata;
}
private function getKey($node)
{
$raw = $node->tagName;
return substr($raw, strpos($raw, ':') + 1);
}
private function getData($node)
{
$data = [];
foreach ($node->getElementsByTagName('langstring') as $text) {
$data[$text->getAttribute('xml:lang')] = trim($text->textContent);
}
return $data;
}
private function createItem($metadata, $additional)
{
$definition = $this->getScormTracker();
$fields = $this->buildFields($definition, $metadata, $additional);
$utilities = new Services_Tracker_Utilities();
$utilities->insertItem(
$definition,
[
'status' => 'o',
'fields' => $fields,
]
);
}
private function updateItem($itemId, $metadata, $additional)
{
$definition = $this->getScormTracker();
$fields = $this->buildFields($definition, $metadata, $additional);
$utilities = new Services_Tracker_Utilities();
$utilities->updateItem(
$definition,
[
'itemId' => (int) $itemId,
'status' => 'o',
'fields' => $fields,
]
);
}
private function getScormTracker()
{
global $prefs;
return Tracker_Definition::get($prefs['scorm_tracker']);
}
private function buildFields($definition, $metadata, $additional)
{
$fields = [];
foreach ($metadata as $key => $values) {
if ($field = $definition->getFieldFromPermName($key)) {
if ($field['type'] === 'F') {
$fields[$key] = $this->getTagString($values);
} elseif ($field['isMultilingual'] == 'y') {
$fields[$key] = reset($values);
} else {
$fields[$key] = $this->getForDefaultLanguage($values);
}
}
}
return array_merge($fields, $additional);
}
private function getTagString($values)
{
$completeSet = [];
foreach ($values as $val) {
$completeSet = array_merge($completeSet, array_values($val));
}
return implode(' ', array_unique($completeSet));
}
private function getForDefaultLanguage($values)
{
global $prefs;
$defaultLanguage = $prefs['language'];
foreach ($values as $valueSet) {
if (isset($valueSet[$defaultLanguage])) {
return $valueSet[$defaultLanguage];
}
}
// If nothing matching the language found, return the first value
return reset(reset($values));
}
}